Apply CLI overrides after typed decoding
This commit is contained in:
@@ -55,8 +55,8 @@ The current lifecycle is:
|
||||
validate options → parse the selected source → extract source controls and
|
||||
traverse/strictly compose enabled imports
|
||||
→ build schema → check the optional application version → apply a selected overlay
|
||||
→ apply explicit CLI overrides → expand sibling inheritance
|
||||
→ create and clone defaults → strictly decode
|
||||
→ expand sibling inheritance
|
||||
→ create and clone defaults → strictly decode → apply explicit CLI overrides
|
||||
→ recorded application resolution
|
||||
→ resolve typed secret references → semantic validation → classify secrets
|
||||
→ snapshot configuration and metadata
|
||||
@@ -137,13 +137,13 @@ Each group is applied once as a precedence tier. The main tier is then composed
|
||||
with the accumulated underlay policy, and the optional application version is
|
||||
checked against that composed main tier only. Underlay roots cannot claim that
|
||||
version path (`underlay.version`); imported fragments retain `import.version`
|
||||
protection. ConfigKit then applies the selected overlay and explicit CLI
|
||||
overrides. Scalar, sequence, and null definitions replace lower values between
|
||||
tiers unless a collection policy defines the sequence operation; mappings
|
||||
combine recursively. Syntax and strict-composition errors inside a tier cannot
|
||||
be masked by a higher-priority tier. Defaults, typed decoding, resolution,
|
||||
secret lookup, validation, and publication run once on the final assembled
|
||||
input.
|
||||
protection. ConfigKit then applies the selected overlay and resolves inheritance.
|
||||
Scalar, sequence, and null definitions replace lower values between tiers unless
|
||||
a collection policy defines the sequence operation; mappings combine recursively.
|
||||
After successful defaults and typed decoding, CLI overrides are applied to that
|
||||
typed configuration before application resolution. Syntax, strict-composition,
|
||||
inheritance, and decoding errors cannot be masked by a CLI override. Resolution,
|
||||
secret lookup, validation, and publication run once on the resulting values.
|
||||
|
||||
An active layered overlay requires `LayeredOptions.OverlayFilesystem` explicitly,
|
||||
independent of the main source's namespace. Its name and root-relative lookup
|
||||
@@ -530,20 +530,20 @@ historical path. Its effective value and each chronological before/after value a
|
||||
parser values. `Present=false` with empty YAML means absence or deletion; explicit
|
||||
null is present and renders as `null`. The history starts with the canonical typed
|
||||
application-default or Go-zero baseline, followed by relevant underlay and main-tier
|
||||
contributions in precedence order, the selected overlay, supplied CLI records,
|
||||
and audited net resolution operations. Within each strict tier, replay follows
|
||||
contributions in precedence order, the selected overlay, and structural inheritance
|
||||
events. Typed defaulting and decoding reconcile that source history before supplied
|
||||
CLI records and audited net resolution operations. Within each strict tier, replay follows
|
||||
[scoped assembly order](#explicit-imports), not source-record acquisition order.
|
||||
Structural inheritance events appear after source replay
|
||||
and before typed reconciliation, including consumed or canceled `extends` input
|
||||
and equal-valued child replacements. Overlapping parent/child resolution records
|
||||
Inheritance events include consumed or canceled `extends` input and equal-valued
|
||||
child replacements. Overlapping parent/child resolution records
|
||||
are rendered
|
||||
as one net subtree event with combined reasons and dependencies, rather than
|
||||
pretending that the recorded assignments ran in lexical order. Explicit equal
|
||||
writes remain visible. When input replay
|
||||
differs from the final typed input, a `ChangeDecoding` event records the transition
|
||||
before domain resolution. Its origin retains the decoded path's source/default
|
||||
attribution; its reason identifies static-default retention and canonical decoding.
|
||||
This built-in inspection operation is not accepted by `Resolution.Record`.
|
||||
writes remain visible. When structural replay differs from the pre-CLI typed input,
|
||||
a `ChangeDecoding` event records retained defaults and canonical decoding. CLI
|
||||
contributions then retain their raw input representation while effective and
|
||||
resolution values use the typed projection. This built-in inspection operation is
|
||||
not accepted by `Resolution.Record`.
|
||||
|
||||
Base, overlay, and CLI history preserves the policy-validated input representation,
|
||||
including a superseded value that could not have decoded into the final Go field.
|
||||
@@ -640,13 +640,15 @@ must resolve to a nonempty value. Secret references work in typed structs, maps,
|
||||
pointers, slices, and arrays. A dynamic `any` value does not establish secret
|
||||
semantics and cannot contain `Secret`; applications must use a typed slot.
|
||||
|
||||
ConfigKit resolves only the effective names after recorded application resolution
|
||||
and before semantic validation. Each unique name is read with `os.LookupEnv` once
|
||||
per load. Validation can inspect the credential through the deliberately named
|
||||
`Value()` accessor and distinguish success with `IsResolved()`. Later loads read
|
||||
the environment again, and cloned defaults are rebuilt from names so a previously
|
||||
resolved result cannot retain a stale credential. `Load` never writes to the
|
||||
environment.
|
||||
ConfigKit resolves only the effective names after CLI assignment and recorded
|
||||
application resolution, and before semantic validation. CLI overrides may supply
|
||||
or replace a typed secret reference; lookup uses that effective name and retains
|
||||
its effective source location for diagnostics. Each unique name is read with
|
||||
`os.LookupEnv` once per load. Validation can inspect the credential through the
|
||||
deliberately named `Value()` accessor and distinguish success with `IsResolved()`.
|
||||
Later loads read the environment again, and cloned defaults are rebuilt from names
|
||||
so a previously resolved result cannot retain a stale credential. `Load` never
|
||||
writes to the environment.
|
||||
|
||||
Credential bytes are held only in the per-load lookup state and the trusted returned
|
||||
configuration, and are returned only by `Value`. Secret formatting uses a safe
|
||||
@@ -710,18 +712,19 @@ files when appropriate; ConfigKit stores no implicit global report.
|
||||
|
||||
### 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
|
||||
An optional `Definition.Resolve` callback runs after successful defaults, typed
|
||||
decoding, and explicit CLI assignment. 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.
|
||||
|
||||
`Resolution.InputInfo(path)` returns detached effective metadata from the fixed
|
||||
decoded entry state, before application resolution runs. It includes retained static
|
||||
defaults, preserves explicit null, and uses the same exact semantic path matching as
|
||||
`Metadata.Lookup`; missing, malformed, and key/index-shape-mismatched paths return
|
||||
false without diagnostics. Its `Explicit` value agrees with `IsExplicit` for every
|
||||
found entry path. Resolution changes, additions, removals, and moves do not alter
|
||||
this entry view.
|
||||
post-decode entry state, including explicit CLI overrides, before application
|
||||
resolution runs. It includes retained static defaults, preserves explicit null, and
|
||||
uses the same exact semantic path matching as `Metadata.Lookup`; missing,
|
||||
malformed, and key/index-shape-mismatched paths return false without diagnostics.
|
||||
Its `Explicit` value agrees with `IsExplicit` for every found entry path. Resolution
|
||||
changes, additions, removals, and moves do not alter this entry view.
|
||||
|
||||
`Resolution.Source(id)` returns a detached record for an already acquired source in
|
||||
the same load: the main source, imports, selected overlay, and supplied CLI records
|
||||
@@ -950,10 +953,16 @@ must never contain the raw argument or configured value. General environment
|
||||
variable overlays are an explicit non-goal: environment access is reserved for
|
||||
typed secret references.
|
||||
|
||||
Overrides apply after the selected overlay and before typed defaults/decoding, so
|
||||
the input precedence is application defaults < composed base < selected overlay <
|
||||
CLI. Recorded resolution, typed secret lookup, and semantic validation follow the
|
||||
effective override tree. Overrides also work with `NoSource`.
|
||||
Overrides are prepared after source assembly and inheritance, then assigned after
|
||||
typed defaults and decoding and before application resolution. The order is:
|
||||
defaults and decoded sources < CLI < application resolution. A CLI mapping
|
||||
recursively overlays the decoded mapping; a CLI sequence replaces the complete
|
||||
decoded sequence regardless of source collection operations. Inheritance and
|
||||
typed defaulting do not run again after CLI assignment. Earlier parsing,
|
||||
composition, inheritance, and decoding failures remain errors even if an override
|
||||
would replace the failing value. Recorded resolution, typed secret lookup, and
|
||||
semantic validation use the effective post-override values. Overrides also work
|
||||
with `NoSource`.
|
||||
|
||||
Values are converted directly into ConfigKit's owned tree without YAML parsing or
|
||||
string coercion. Supported values are `nil`, built-in strings and booleans, all
|
||||
@@ -964,7 +973,8 @@ false, and zero remain intentional; empty sequences replace whole lists; and map
|
||||
values recursively overlay existing mappings. Map keys are sorted canonically and
|
||||
sequence order is preserved.
|
||||
|
||||
All records are detached and validated before any is applied. Root and explicit
|
||||
All records are detached and validated before any is applied. They cannot create
|
||||
`configkit` or `extends` controls. Root and explicit
|
||||
sequence-index paths are invalid; parsed numeric tokens remain mapping keys. A path
|
||||
may create missing mapping ancestors but cannot traverse an existing scalar, null,
|
||||
or sequence. Duplicate and ancestor/descendant-overlapping records are rejected.
|
||||
@@ -981,8 +991,12 @@ unsupported types, nonfinite floats, and limit excesses fail with safe `override
|
||||
diagnostics. Diagnostics and provenance identify the safe `Flag` source, never raw
|
||||
arguments or values.
|
||||
|
||||
Override origins are explicit CLI origins. History retains replaced base/overlay
|
||||
definitions and records equal-value replacements as well as structural changes.
|
||||
Override origins are explicit CLI origins. Resolution receives CLI values with
|
||||
their explicit-presence and source information. Absence-based defaults preserve
|
||||
those values, while recorded normalization and derivation may change them. History
|
||||
retains replaced source definitions and records equal-value replacements as well
|
||||
as structural changes. Secret lookup and validation use post-resolution values
|
||||
with their effective source locations.
|
||||
Caller-owned maps and slices are snapshotted during loading and must not be mutated
|
||||
concurrently with the call. The executable `ExampleOverride` shows translating a
|
||||
parser's explicit-set state into records while preserving an explicitly supplied
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Sequence Identity And Combination Implementation Plan
|
||||
|
||||
Status: implementation in progress; Stages 1–25 complete.
|
||||
Status: implementation in progress; Stages 1–26 complete.
|
||||
|
||||
Audience: a Luna coding agent implementing one numbered stage per prompt, in
|
||||
order. This plan starts at commit
|
||||
@@ -878,6 +878,13 @@ assignment, inspection, and effective-value handoffs.
|
||||
Validation: override/lifecycle/resolution/inheritance/history/secret tests,
|
||||
`go test -race ./...`, and the everyday check.
|
||||
|
||||
**Completion:** Activated typed CLI assignment after structural expansion and
|
||||
decoding in the shared load lifecycle, including resolution, history, and
|
||||
effective secret-reference context. Removed early application and replay fallback
|
||||
paths, updated contracts and examples, and revised obsolete relationship-change
|
||||
expectations. Verified focused lifecycle and secret tests, `go test -race ./...`,
|
||||
and `./scripts/check.sh`.
|
||||
|
||||
## Stage 27 — Enforce Final Application Identity Constraints
|
||||
|
||||
Scope: the final-result guarantee, not another combination or inheritance phase.
|
||||
|
||||
Reference in New Issue
Block a user