4.7 KiB
ADR 0013: Check Source Versions with One Shared Policy
Status
Accepted and implemented. The
configuration contract owns current
behavior. The completed roadmap, implementation plan, consumer request, and
resolved review findings are preserved at e4270c9 under docs/roadmap/ in
Git history; the development guide
provides retrieval examples.
Date
2026-10-15
Context
Applications that assemble one configuration from independently authored
documents need a way to require that each contributing document declares a
version accepted by the application's existing Definition.Version checker.
Checking only the eventual composed value lets another source hide a rejected
declaration, while separate consumer-side parsing duplicates ConfigKit's source
handling and diagnostics.
The extension must preserve one application-owned acceptance policy and the existing loading lifecycle. Source declarations are compatibility evidence, not independent fragment schemas or values to compare for equality. Existing composition, placement, precedence, source identity, diagnostics, and sensitivity rules remain authoritative.
Decision
Provide a load-wide source-version mode for ordinary and layered loading. The
zero-value mode preserves current behavior. The enabled modes check declarations
when present or require them, using the existing Definition.Version path and
checker. Interpret the configured path relative to each participating source
before placement or composition. Different declarations may be accepted by the
same checker; ConfigKit adds no equality, SemVer, or expected-version rule.
Apply the selected policy to the actual main document, direct underlays,
imports, and selected overlays. Missing non-main declarations are skipped in
if-present mode and rejected in required mode. Existing main absence behavior
remains, with required mode additionally rejecting an absent declaration on an
actual main document. NoSource, unmatched optional inputs, synthetic field
operations, and empty groups do not become documents that need declarations.
Reuse the existing version vocabulary and validation boundary: absence, null, exact strings, and strict decimal integers retain their established meanings; unsupported present values fail version-type validation. Warnings remain nonfatal, and source declarations do not replace final application decoding or domain validation.
After an accepted non-main declaration is checked, consume exactly that node before its remaining application content is composed or overlaid. Preserve the main declaration and its value semantics. Keep the declaration, source-local path, physical location, and checked absence as detached source evidence, separate from effective application values and history. Apply established sensitivity rules to that evidence, including original mounted paths and ancestors; retain existing safe failure disclosure.
In enabled modes, the main declaration remains source-local while its protected application path is derived from the main input's destination. This distinction does not change default-mode path interpretation or weaken protection of remaining payload and synthetic operations.
Public option-field additions and the enabled-mode interpretation for mounted main inputs are compatibility considerations for separately authorized minor- release preparation. This decision does not select a release version or authorize release notes or publication.
Alternatives Considered
- Check only the final composed value. Later sources can hide an earlier rejected declaration, so this does not validate every contributing document.
- Let consumers parse and check each source. This duplicates acquisition, source attribution, safe diagnostics, and lifecycle coordination in every application.
- Require declarations to be equal or impose a universal version grammar. Consumers already own the acceptance policy; ConfigKit need not invent an expected value or a domain-specific compatibility rule.
- Keep accepted non-main declarations in application payload. A selected source-local declaration is metadata for this policy and cannot also remain an ordinary field at the same path without ambiguity.
Consequences
Consumers can apply one existing version policy across contributing documents and select gradual or required adoption per load. Accepted non-main headers no longer participate in application composition; their inspectable evidence is kept separate and subject to sensitivity classification. Default callers retain current behavior. The implementation plan records the concrete API names, integration order, and validation evidence.