Skip to content

refactor(declarative): unify field contracts across diffing, payload mapping, and dump #2081

Description

@rspurgeon

Problem and desired outcome

A declarative field can be accepted by the load schema while still requiring
independent create extraction, comparison, update mapping, and dump conversion.
Define its behavior once, with action-specific projections shared across these
paths, to reduce drift when the Konnect SDK and resource surface evolve.

This is a design proposal following the resource capability and shared
reconciliation milestones. The migration must retain existing behavior before
support for additional SDK fields is considered.

Evidence from the current code

Assessment baseline: 0fe92b40.

Proposed responsibilities

Derive mechanical field structure from existing typed declarations and SDK
request/response types where trustworthy. Supply explicit reviewed policies
for behavior that type reflection cannot determine:

  • accepted declarative field paths and presence;
  • create eligibility, update eligibility, and immutable fields;
  • sparse update versus full replacement request requirements;
  • observable response fields and unknown/unreturned values;
  • comparison normalization and ordered versus unordered collections;
  • literal documented defaults, with narrowly scoped overrides;
  • write-only secrets and public vault references;
  • routing/relationship fields versus API body fields;
  • exportable fields and dump omission behavior.

The same resource-owned contract should provide separate create, update,
comparison, and export projections. These are different views of shared field
knowledge, not a single request struct reused everywhere.

Preserve the existing payload-loss checks as defense in depth. Keep custom
transformations explicit and reviewable; do not infer business semantics from
field names or permit arbitrary opaque maps to bypass validation.

Suggested migration

  1. Inventory the existing projection paths for one ordinary resource.
  2. Extract its current field policy without broadening field support.
  3. Route create, compare, update, and dump through those projections.
  4. Verify nil/empty and changed-field rendering behavior with existing tests.
  5. Exercise a resource with asymmetric create/update or response shapes.
  6. Expand through resource families after the exceptions are understood.

Any code generation should derive mechanical accessors or metadata. Assess it
against the existing reflection machinery before introducing a new generator
or a second manually maintained schema language.

Questions to resolve before broad implementation

  • Which schema facts should come from the SDK Go types versus the authoritative
    OpenAPI schema work in Task: embed schema data for runtime usage #1599?
  • How should absent, null, explicit empty, and defaulted fields be represented?
  • Where do response observability and comparison-only normalization belong?
  • Can ordinary sparse updates be derived while keeping full-body APIs explicit?
  • How do union discriminators select action-specific field contracts?
  • How is a future SDK field addition surfaced for review without silently
    changing the accepted declarative contract?

Acceptance criteria

  • A migrated ordinary field has one authoritative behavioral declaration.
  • Create, update, comparison, and export consume the shared contract.
  • Existing accepted fields, omission semantics, and request bodies remain.
  • Write-only values remain absent from plans, diffs, dumps, and diagnostics.
  • SDK-derived defaults do not introduce hidden cross-field defaults.
  • Unsupported mappings still fail explicitly before execution.
  • Duplicated migrated field lists are removed.
  • Applicable unchanged unit, integration, and dump tests pass.

Related work

Coordinate with #1599 and #1827 for schema authority and derivation. This issue
covers lifecycle projections beyond explain/load shape. #2051 covers
conformance tests and is not authorization to modify tests in this refactor.
#1039 addresses a specific API publication transport path.

Compatibility and validation

This is a behavior-preserving refactor. Preserve accepted YAML, omitted versus
explicit-empty scope, namespace and protection behavior, identity precedence,
external resources, error propagation, secret redaction, and saved-plan
serialization. Preserve execution ordering and request counts where existing
tests specify them. Do not silently broaden support while moving code.

Existing test packages, test files, fixtures, mocks, and golden artifacts must
remain unchanged without explicit maintainer permission.
Establish the
unchanged test baseline before implementation. Keep test-facing entry points
as delegating adapters when needed. New regression or conformance tests are a
separate follow-up requiring permission; their desirability does not authorize
test changes in this refactor.

Run production-only modernization/formatting, a CGO-disabled build, lint, the
unchanged unit suite, and applicable existing integration checks after each
migration. Avoid repository-wide rewrite commands that can modify tests.
Record baseline failures separately from regressions, and verify test-file
hashes and the final Git diff.

Refactoring program

Start with bounded #2079/#2080 migrations. #2081 and #2082 remain later design
tracks; the initial implementation does not close the whole program.

Implementation guide acceptance criteria

Treat docs/contributor/declarative-resource-implementation-guide.md as the authoritative implementation entry point for agents throughout this refactoring. Guide maintenance is part of the implementation, not a documentation follow-up.

  • Document how a field is carried through accepted YAML, comparison, action-specific SDK mapping, and dump, including omission/default and write-only-field contracts.
  • Update the guide in the same change as the code; replace obsolete instructions and checklists instead of appending competing patterns or historical baseline sections.
  • Keep the workflow concise, retain behavioral invariants, and link to current implementations instead of copying large implementation templates.
  • Verify code references, local links, and section anchors. An agent should be able to follow a resource or field through loading, planning, execution, and export without guessing missing wiring.
  • Preserve maintainer constraints, including the existing test freeze; documentation or golden-regeneration instructions do not authorize test changes.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions