Add audited application resolution
This commit is contained in:
@@ -47,8 +47,8 @@ version checker, contributes no source, and continues through defaults, decode,
|
||||
projection. A missing file remains an error; it is never interpreted as no input.
|
||||
|
||||
The current `Options` boundary accepts a defaults factory and `VersionRule`.
|
||||
Imports, active profiles, filesystem context, overrides, resolver and semantic
|
||||
validator callbacks, and dynamic secret classification return an explicit
|
||||
Imports, active profiles, filesystem context, overrides, semantic validator
|
||||
callbacks, and dynamic secret classification return an explicit
|
||||
`options.unavailable` error because their lifecycle stages are not implemented.
|
||||
The reserved profile spelling `default` selects no active profile. `NoSource`
|
||||
additionally rejects imports, active profiles, and filesystem context as invalid
|
||||
@@ -84,6 +84,44 @@ source coordinates are retained. `History` records the Go-zero or application
|
||||
default baseline followed by exact base definitions, including equal-valued input.
|
||||
All metadata queries and returned nested records are detached.
|
||||
|
||||
### Recorded application resolution
|
||||
|
||||
An optional `Definition.Resolve` callback runs after successful typed decoding. It
|
||||
receives the working configuration and a per-load `Resolution` context. The context's
|
||||
`IsExplicit` query uses surviving input presence, so explicit false, zero, empty, and
|
||||
null are never confused with absence or static defaults.
|
||||
|
||||
`Default` assigns and records a derived value only when its path is not explicit.
|
||||
`Normalize` always assigns and records. For transformations performed directly by
|
||||
application code, `Resolution.Record` declares a derived-default or normalization
|
||||
operation; a recorded container covers changes to its descendants. Records require
|
||||
a schema-valid path, valid kind, safe nonempty reason, and schema-valid dependency
|
||||
paths. Repeated records at one path are coalesced: reasons and dependencies retain
|
||||
their first occurrence, the last helper value is authoritative, and any normalization
|
||||
makes the combined operation a normalization.
|
||||
|
||||
ConfigKit projects the configuration before and after the callback. Every net change
|
||||
must have an exact or ancestor record. Helper-assigned values must agree with the
|
||||
final value at their declared path, which supports ordinary map-entry copy/writeback
|
||||
while detecting forgotten writeback or unrelated targets. Invalid paths, kinds,
|
||||
values, records, helper targets, and unrecorded mutations fail the load. Equal-valued
|
||||
derived assignments may still record application intent even when there is no
|
||||
structural change.
|
||||
|
||||
`Resolution.Error` and `Resolution.Warning` attach exact or nearest available input
|
||||
locations. Reported errors fail the load; warnings survive on a successful result. A
|
||||
returned resolver error adds one generic `resolve.hook_failed` error only when the
|
||||
callback did not report an error, and its text is never exposed. Callback panics are
|
||||
programming failures. Resolution and validation contexts are callback-scoped; using
|
||||
a nil, zero, or retained context outside its active callback panics with fixed,
|
||||
value-free text.
|
||||
|
||||
Successful records update effective origins and append detached metadata history
|
||||
without changing input explicitness. Removed paths leave effective metadata but
|
||||
retain history. ConfigKit privately snapshots each recorded before/after subtree for
|
||||
later safe explanation; caller mutations of `Result.Config` cannot alter those
|
||||
snapshots.
|
||||
|
||||
## YAML documents
|
||||
|
||||
The private YAML boundary currently accepts exactly one nonempty document whose root
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
This is the contributor entry point for ConfigKit. Read the task-specific owners
|
||||
below before making changes. The repository is in early implementation: its public
|
||||
loader currently covers one strict source, typed defaults, schema-version checks,
|
||||
and base/default metadata. The [component overview](internal/overview.md) owns the
|
||||
implementation inventory.
|
||||
recorded application resolution, and metadata. The
|
||||
[component overview](internal/overview.md) owns the implementation inventory.
|
||||
|
||||
## Initial orientation
|
||||
|
||||
|
||||
@@ -192,6 +192,17 @@ later lifecycle option. No application loader or production line was copied.
|
||||
Narratio's resolution, validation, import/profile, campaign/session, and command
|
||||
behavior remains assigned to its later owning work.
|
||||
|
||||
Resolution implementation record (2026-09-06): ConfigKit adapted the intent of
|
||||
Narratio's `Resolve`, `applyPipelineDefaults`, component default helpers,
|
||||
`mergeCampaignSession`, and `selectStableInput` into a generic recorded resolver in
|
||||
`resolution.go`. The synthetic timeout/artifact cases preserve explicit-input
|
||||
decisions, derived dependencies, normalization, and map copy/writeback without
|
||||
copying campaign/session algorithms or concrete defaults. ConfigKit adds structural
|
||||
mutation auditing, container coverage, helper/path consistency checks, equal-value
|
||||
intent, coalesced repeated writes, private before/after snapshots, deterministic
|
||||
record ordering, and safe hook diagnostics. Semantic validation remains assigned to
|
||||
the next lifecycle work.
|
||||
|
||||
### Secrets bootstrap
|
||||
|
||||
Assigned to the explicit bootstrap operation:
|
||||
|
||||
@@ -19,10 +19,14 @@ module and package documentation boundary. Its implemented public primitives are
|
||||
baseline/final trees, and initial default/input origins; and
|
||||
- public single-source lifecycle coordination in `load.go`, version-report contexts
|
||||
in `validation.go`, and detached base/default metadata assembly in
|
||||
`load_metadata.go`.
|
||||
`load_metadata.go`; and
|
||||
- recorded application defaulting and normalization in `resolution.go`, including
|
||||
explicitness queries, helper verification, structural mutation audit, coalesced
|
||||
intent, private before/after snapshots, and resolution metadata integration.
|
||||
|
||||
The [configuration contract](../config.md) owns implemented input, schema, decoding,
|
||||
single-source lifecycle, version checking, metadata, and ownership behavior.
|
||||
single-source lifecycle, version checking, recorded resolution, metadata, and
|
||||
ownership behavior.
|
||||
|
||||
The source-extraction inventory records the application foundations assigned to
|
||||
future implementation work:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Status and ownership
|
||||
|
||||
Status: implementation in progress; Stages 1–7 are complete and later stages are
|
||||
Status: implementation in progress; Stages 1–8 are complete and later stages are
|
||||
pending.
|
||||
|
||||
Audience: a `gpt-5.6-terra` coding agent implementing one stage per prompt, in
|
||||
@@ -684,7 +684,36 @@ Acceptance:
|
||||
|
||||
## Stage 8 — Implement recorded application resolution
|
||||
|
||||
Status: pending.
|
||||
Status: complete.
|
||||
|
||||
Completion evidence (2026-09-06):
|
||||
|
||||
- Implemented per-load `Resolution`, `IsExplicit`, `Record`, `Default`, `Normalize`,
|
||||
`Error`, and `Warning` in [`resolution.go`](../../resolution.go), and enabled the
|
||||
resolver in `Load` after successful decode while leaving semantic validation gated.
|
||||
- Added schema-aware path/kind/dependency checks, safe reason requirements, dynamic
|
||||
and typed helper projection, final helper/path consistency checks, before/after
|
||||
structural comparison, exact/ancestor record coverage, and distinct safe failures
|
||||
for invalid values, targets, records, and unrecorded changes.
|
||||
- Coalesced repeated path intent deterministically, retaining unique reasons and
|
||||
dependencies, using the last helper value, and promoting mixed operations to
|
||||
normalization. Equal-valued derived intent remains recorded; map copy/writeback,
|
||||
container coverage, deletions, and new dynamic/map descendants are supported.
|
||||
- Integrated resolution origins and history without changing surviving input
|
||||
explicitness, retained private detached before/after snapshots, sorted records by
|
||||
semantic path, and made retained callback-context use panic with fixed value-free
|
||||
text. Resolver errors are suppressed unless explicitly reported through the
|
||||
context; warnings remain on successful results. The
|
||||
[current resolution contract](../config.md#recorded-application-resolution) owns
|
||||
this behavior.
|
||||
- Focused tests execute the timeout/artifact consumer shape, explicit null/zero and
|
||||
absent-baseline behavior, normalization, map writeback, equal and repeated helper
|
||||
intent, stable map-derived record order, subtree removal, snapshot detachment,
|
||||
unrelated targets, invalid paths/kinds/values, unrecorded mutation, safe hook
|
||||
failures, and closed resolution/version contexts. Verified `go test ./...`,
|
||||
`go test -race ./...`, `go vet ./...`, `go build ./...`, `go mod tidy -diff`, and
|
||||
`git diff --check` with Go 1.26.7 on linux/amd64. No deviations were required;
|
||||
semantic validation remains later work.
|
||||
|
||||
Read: feature [resolution callbacks](initial.md#resolution-and-validation-callbacks).
|
||||
|
||||
|
||||
@@ -571,37 +571,16 @@ rendering remain target work below.
|
||||
|
||||
## Recorded resolution and validation
|
||||
|
||||
Application-owned resolution runs after decoding and may derive absent values
|
||||
or normalize explicitly configured ones. Provide a narrow resolution context
|
||||
that exposes metadata and records each changed semantic path, operation kind
|
||||
(derived default or normalization), and a safe reason. Dependency paths may be
|
||||
recorded when a value is derived from other fields.
|
||||
Application-owned recorded resolution is implemented. The
|
||||
[current resolution contract](../config.md#recorded-application-resolution) owns
|
||||
explicitness queries, helpers and manual records, structural mutation auditing,
|
||||
coalescing, diagnostics, origins, history, and snapshot ownership. Layered input
|
||||
history, redacted explanation, and secret dependency propagation remain target work.
|
||||
|
||||
A resolver may mutate the typed configuration, but ConfigKit compares its
|
||||
before/after configuration projection and requires records for changed paths.
|
||||
Unrecorded changes are resolution errors. Container replacement records cover
|
||||
changed descendants. Capture previous/final values internally from the actual
|
||||
configuration rather than trusting separately supplied values. Application
|
||||
resolvers own meaningful reasons; a diff alone cannot explain intent. Reasons
|
||||
must not embed secrets. The proposed [resolution API](#resolution-and-validation-callbacks)
|
||||
provides helpers to combine assignments and records. Snapshot comparison verifies
|
||||
net changes during the hook; it does not reconstruct intermediate assignments.
|
||||
A record describes the hook's before/final transition and declared intent, not an
|
||||
automatically recovered event log. Equal-valued derived-default assignments may
|
||||
still have a record identifying their intent. Multiple records at the same path
|
||||
are coalesced for that hook, retaining declared reasons and dependencies.
|
||||
|
||||
The final configuration, effective output, presence queries, and explanation
|
||||
records must agree. Do not render the pre-resolution YAML tree as the final
|
||||
configuration. ConfigKit promises an independently owned snapshot it does not
|
||||
subsequently mutate, not language-enforced immutability of exported Go values.
|
||||
Callers should treat returned configuration as read-only; later caller mutations
|
||||
are outside the captured metadata snapshot.
|
||||
|
||||
Canonical typed projection, detached cloning, and structural comparison are now
|
||||
implemented as private foundations. The [current ownership contract](../config.md#typed-projection-and-ownership)
|
||||
owns those mechanics; publishing independently captured results remains lifecycle
|
||||
work.
|
||||
Canonical typed projection, detached cloning, structural comparison, and publishing
|
||||
independently captured resolved results are implemented. The
|
||||
[current ownership contract](../config.md#typed-projection-and-ownership) owns those
|
||||
mechanics.
|
||||
|
||||
Application semantic validation runs after successful resolution and collects
|
||||
independent errors in a standard diagnostic form. Validators are read-only and
|
||||
@@ -613,7 +592,9 @@ is outside this lifecycle. Do not run later hooks on an invalid typed value.
|
||||
Safe diagnostic/provenance value records, canonical diagnostic rendering, and
|
||||
`LoadError` access are implemented. Their current contracts are owned by
|
||||
[`records.go`](../../records.go) and [`diagnostic.go`](../../diagnostic.go).
|
||||
Attaching those records to the loading lifecycle remains target work below.
|
||||
Base/default and resolution records are attached to the current loading lifecycle.
|
||||
Additional layers, safe historical values, redaction, and rendering remain target
|
||||
work below.
|
||||
|
||||
Retain input sources, layer, line/column where available, import sites, effective
|
||||
origins, overridden definition records, and resolution operations. Container
|
||||
@@ -814,6 +795,10 @@ behavior. Layered callback history and safe historical values remain target beha
|
||||
|
||||
### Resolution and validation callbacks
|
||||
|
||||
The resolution declarations and behavior below are implemented; the
|
||||
[current recorded-resolution contract](../config.md#recorded-application-resolution)
|
||||
is authoritative. Semantic validation behavior in this section remains target work.
|
||||
|
||||
```go
|
||||
func (r *Resolution) IsExplicit(path Path) bool
|
||||
func (r *Resolution) Record(path Path, kind ChangeKind, reason string, dependencies ...Path)
|
||||
|
||||
Reference in New Issue
Block a user