Finalize ConfigKit design and implementation plan

This commit is contained in:
2026-09-06 11:48:22 -05:00
parent 18524330fc
commit 9fc272f7a9
14 changed files with 2386 additions and 1116 deletions

View File

@@ -0,0 +1,37 @@
# ADR 0001: Separate Composition and Overlay
## Status
Accepted. This records a design decision, not implementation completion.
## Date
2026-09-06
## Context
Configuration fragments allow independent parts of an application to contribute
settings. Treating every file as a precedence layer makes accidental duplicates
silently depend on file order. Profiles, however, need intentional replacement.
## Decision
Use distinct strict-composition and intentional-overlay operations. Composition
rejects conflicting definitions; overlay provides explicit precedence. Keep the
operations opinionated rather than adding arbitrary per-field merge strategies.
The [architecture policy](../policy/architecture.md) owns the governing boundary;
the [target design](../roadmap/initial.md#composition-and-overlay) owns the planned
operation table until its current contract lands.
## Alternatives considered
- Last-wins loading for all files: convenient but conceals accidental conflicts.
- Strict loading for every layer: catches conflicts but cannot express profiles.
- User-defined merge policies: flexible but weakens consistency and expands the API.
## Consequences
Consumers must distinguish modular contributions from intentional overrides.
Diagnostics need both conflicting sources. File order remains useful for stable
traversal and reporting but cannot silently authorize replacement. Named mappings
are the natural representation for independently contributed entries.

View File

@@ -0,0 +1,38 @@
# ADR 0002: Own YAML Semantics Behind a Private Parser Boundary
## Status
Accepted. This records a design decision, not implementation completion.
## Date
2026-09-06
## Context
A shared library cannot provide consistent configuration semantics if each
consumer inherits parser conversions, node types, and extension behavior.
Exposing parser types also makes dependency changes part of the public API.
## Decision
ConfigKit defines its supported YAML policy and keeps parser integration private.
Application types and diagnostics must not require parser-specific public types.
Use a small internal boundary rather than a general parser/provider framework.
The [architecture policy](../policy/architecture.md) owns this constraint; the
[target design](../roadmap/initial.md#yaml-and-scalar-policy) owns planned syntax.
## Alternatives considered
- Expose parser nodes and hooks: easy integration but couples consumers to parser
behavior and permits bypassing library policy.
- Adopt the parser's entire YAML behavior: reduces initial code but leaves core
semantics outside ConfigKit's control.
- Abstract many configuration languages immediately: adds unsupported scope.
## Consequences
Parser changes require behavior-level compatibility verification. ConfigKit must
translate errors safely and enforce its own supported subset. Some existing
consumer custom decoders will need replacement with library-supported mechanisms
or application resolution. No particular parser dependency is selected here.

View File

@@ -0,0 +1,43 @@
# ADR 0003: Preserve Presence and Record Application Resolution
## Status
Accepted. This records a design decision, not implementation completion.
## Date
2026-09-06
## Context
Go zero values cannot distinguish omitted input from explicitly configured false,
zero, or empty text. Decoding immediately also loses information needed to explain
imports and overlays. Application normalization can subsequently make retained
input metadata disagree with runtime values.
## Decision
Preserve input presence and provenance separately from ordinary application Go
values. Keep application defaults and normalization application-owned, but record
resolution changes so final inspection and metadata describe the actual resolved
snapshot. Do not promise language-enforced immutability of exported Go values.
The [architecture policy](../policy/architecture.md) owns these invariants; the
[target design](../roadmap/initial.md#recorded-resolution-and-validation) owns the
planned recording mechanism and ownership semantics.
## Alternatives considered
- Infer presence from zero values: cannot preserve explicit zero-valued settings.
- Require pointers or optional wrappers everywhere: burdens application types and
confuses input presence with domain nullability.
- Retain only the composed input tree: cannot explain post-decode changes.
- Automatically diff mutations without reasons: detects changes but cannot explain
application intent or derivation dependencies.
## Consequences
Metadata and snapshot ownership are core concerns rather than optional debugging
features. Resolution hooks must participate in recording changes. Verification
must compare final values, origins, and rendering, including secret treatment.
This costs more than plain unmarshalling but removes repeated presence machinery
from consumers and supports trustworthy inspection.