Record source version decisions and remaining edge cases
This commit is contained in:
@@ -16,7 +16,10 @@ is one consumer-owned configuration specification and one acceptance policy.
|
|||||||
Different accepted declarations may coexist: ConfigKit does not require exact
|
Different accepted declarations may coexist: ConfigKit does not require exact
|
||||||
equality with the main declaration, impose SemVer, or invent an expected value.
|
equality with the main declaration, impose SemVer, or invent an expected value.
|
||||||
|
|
||||||
The consumer selects one of three modes through the supported loading API:
|
The consumer selects a load-wide enum on ordinary and layered options. Its zero
|
||||||
|
value retains current behavior; exact exported names remain implementation design
|
||||||
|
work. The same `Definition.Version` can be reused across loads with different
|
||||||
|
strictness. The three modes are:
|
||||||
|
|
||||||
| Mode | Missing non-main declaration | Present non-main declaration |
|
| Mode | Missing non-main declaration | Present non-main declaration |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
@@ -77,16 +80,18 @@ declarations need an explicit absence state and an appropriate source-location
|
|||||||
fallback for diagnostics, not an invented authored header coordinate.
|
fallback for diagnostics, not an invented authored header coordinate.
|
||||||
|
|
||||||
Preserve normal safe diagnostics, warning behavior, callback lifetime, and
|
Preserve normal safe diagnostics, warning behavior, callback lifetime, and
|
||||||
disclosure rules. The public evidence representation and treatment of classified
|
disclosure rules. Evidence will be attached to existing source inspection as a
|
||||||
declarations need the design decision below; retaining evidence does not authorize
|
detached declaration record, distinguishing unchecked sources, checked absence,
|
||||||
|
present null/text, and redaction, with local path and physical location. The
|
||||||
|
remaining sensitivity decision below governs disclosure; retaining evidence does not authorize
|
||||||
unredacted exposure of sensitive values or arbitrary malformed input.
|
unredacted exposure of sensitive values or arbitrary malformed input.
|
||||||
|
|
||||||
### Participation and unchanged boundaries
|
### Participation and unchanged boundaries
|
||||||
|
|
||||||
Document participation must be explicit, independent of filesystem naming or
|
Document participation must be explicit, independent of filesystem naming or
|
||||||
collection identity. The recommended scope is:
|
collection identity. The agreed scope is:
|
||||||
|
|
||||||
| Contribution | Recommended treatment |
|
| Contribution | Treatment |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Selected main document | Shared checker; declaration retained; no duplicate main callback |
|
| Selected main document | Shared checker; declaration retained; no duplicate main callback |
|
||||||
| Direct underlay documents | Check under the selected mode; accepted headers consumed |
|
| Direct underlay documents | Check under the selected mode; accepted headers consumed |
|
||||||
@@ -99,8 +104,7 @@ collection identity. The recommended scope is:
|
|||||||
|
|
||||||
A present empty document mapping is still a document. Reuse of a source in
|
A present empty document mapping is still a document. Reuse of a source in
|
||||||
allowed separate tiers retains existing acquisition semantics; do not introduce
|
allowed separate tiers retains existing acquisition semantics; do not introduce
|
||||||
a global once-only check or a new uniqueness policy. The participation boundary
|
a global once-only check or a new uniqueness policy.
|
||||||
and mode API remain recommendations to settle in stage 1.
|
|
||||||
|
|
||||||
Existing source acquisition, containment, import destinations, strict composition,
|
Existing source acquisition, containment, import destinations, strict composition,
|
||||||
precedence, inheritance, and complete-on-return loading continue to apply.
|
precedence, inheritance, and complete-on-return loading continue to apply.
|
||||||
@@ -113,6 +117,26 @@ per-input compatibility policies, automatic schema migration, YAML-selected
|
|||||||
callbacks, or general source-validation hooks. These are outside this delivery,
|
callbacks, or general source-validation hooks. These are outside this delivery,
|
||||||
not new permanent prohibitions on future work.
|
not new permanent prohibitions on future work.
|
||||||
|
|
||||||
|
### Agreed main-path and consumption behavior
|
||||||
|
|
||||||
|
In enabled modes, locate main's header source-locally, retain it, and derive its
|
||||||
|
effective protected path by prefixing main's destination. Use that effective
|
||||||
|
path consistently for protection, existing typed version conversion, and
|
||||||
|
inspection. Invoke the shared checker once for main. Preserve its existing
|
||||||
|
acceptance policy for absence; required mode additionally rejects a missing
|
||||||
|
header when an actual main document participates. `NoSource` retains the existing
|
||||||
|
absent-main checker behavior because it is not a document.
|
||||||
|
|
||||||
|
Default mode keeps the existing effective-path interpretation. Root-mounted main
|
||||||
|
inputs need no path adjustment; mounted-main callers opting in must account for
|
||||||
|
the enabled mode's source-local interpretation. No separate main-version path or
|
||||||
|
root-only main restriction is introduced.
|
||||||
|
|
||||||
|
For nested mapping headers, consume only the selected non-main declaration and
|
||||||
|
retain authored ancestor containers, including newly empty mappings. This avoids
|
||||||
|
removing additional input presence or changing unrelated default/composition
|
||||||
|
behavior. Sequence-element and structural-directive cases remain open below.
|
||||||
|
|
||||||
## Current baseline
|
## Current baseline
|
||||||
|
|
||||||
Reviewed worktree baseline: `b3fc6a5`. Input destinations and relative import
|
Reviewed worktree baseline: `b3fc6a5`. Input destinations and relative import
|
||||||
@@ -144,13 +168,13 @@ destinations are implemented; the
|
|||||||
|
|
||||||
### 1. Finalize the contract and integration design
|
### 1. Finalize the contract and integration design
|
||||||
|
|
||||||
Resolve the Open Decisions below. Select public mode names and placement, source
|
Resolve the Open Decisions below. Select exact public mode and evidence type
|
||||||
participation, main-path handling, and evidence types. Define header lookup for
|
names within the agreed load-wide API, participation, main-path, and inspection
|
||||||
|
design. Define header lookup for
|
||||||
nested paths and distinguish a missing member from an obstructing non-container
|
nested paths and distinguish a missing member from an obstructing non-container
|
||||||
ancestor. Specify consumption without broadening it into a generic transformation
|
ancestor. Specify consumption without broadening it into a generic transformation
|
||||||
API. Recommend removing only the selected header node and preserving its authored
|
API. Preserve authored ancestors when consuming nested mapping headers as agreed;
|
||||||
ancestor containers, including newly empty mappings; decide handling of overlaps
|
settle sequence-element consumption and structural-directive overlaps below.
|
||||||
with structural directives before implementation.
|
|
||||||
|
|
||||||
Record the change to main-only version ownership in an ADR and review public API
|
Record the change to main-only version ownership in an ADR and review public API
|
||||||
compatibility under repository policy. Do not rewrite accepted ADR decisions or
|
compatibility under repository policy. Do not rewrite accepted ADR decisions or
|
||||||
@@ -245,74 +269,87 @@ required to complete this feature.
|
|||||||
|
|
||||||
## Open Decisions
|
## Open Decisions
|
||||||
|
|
||||||
### Mode API and document participation
|
These are recommendations for further discussion, not accepted restrictions or
|
||||||
|
implemented behavior. The mode API location, source participation, main-path
|
||||||
|
handling, source-record evidence, and nested mapping ancestor preservation above
|
||||||
|
have been agreed.
|
||||||
|
|
||||||
Recommendation: expose a load-wide enum on ordinary and layered options, with
|
### Sensitivity of consumed declaration evidence
|
||||||
zero retaining current behavior, and use the participation table above. This
|
|
||||||
allows one reusable `Definition.Version` policy to be used with different adoption
|
|
||||||
strictness on different loads. Include mapping sources and selected overlays:
|
|
||||||
they contribute documents even though they are not necessarily imported files.
|
|
||||||
Exclude synthetic field operations and absent sources as described above.
|
|
||||||
|
|
||||||
Alternative: place the mode on `VersionRule` so policy and enforcement travel
|
Recommendation: classify declaration evidence using its original source shape
|
||||||
together. This reduces option plumbing but requires changing/copying the rule
|
at its mounted application path, including classified ancestors. Preserve the
|
||||||
to vary enforcement. A narrower first implementation checking imports and
|
header as private evidence long enough to apply applicable existing field-tag,
|
||||||
underlays but exempting overlays is also viable; it reduces integration work but
|
predicate, historical, and recorded-dependency sensitivity rules; consumption
|
||||||
offers weaker assurance about all contributing documents and needs an explicit
|
must not make a classified declaration public. Do not require the consumed path
|
||||||
documented exception. Neither choice should imply per-source independent policies.
|
to survive in final effective metadata. Use explicit redaction state and omit the
|
||||||
|
classified text from public evidence while retaining presence, source attribution,
|
||||||
|
and the fact that it was checked. The checker still receives the declaration as
|
||||||
|
trusted application code, as the existing version checker does.
|
||||||
|
|
||||||
### Mounted main documents and the protected application path
|
For example, a header `meta.version` mounted at `collections.weather` is masked
|
||||||
|
if either that header path or an ancestor such as `collections.weather.meta` is
|
||||||
|
classified. An unclassified header remains inspectable. A later override must
|
||||||
|
not erase applicable historical classification. Sequence evidence uses original
|
||||||
|
source coordinates and segment kinds, not indexes shifted by consumption.
|
||||||
|
|
||||||
Recommendation: in enabled modes, locate main's header source-locally as requested,
|
On failed loads, retain the existing safe diagnostic boundary: do not include raw
|
||||||
retain it, and derive its effective protected path by prefixing main's destination.
|
header text in generated failure messages. If checked evidence is exposed through
|
||||||
Use that derived path consistently for protection, existing typed version
|
load errors before full sensitivity is available, mask its text unless applicable
|
||||||
conversion, and inspection. Invoke the shared checker once for main, preserving
|
classification can already be established safely; this does not require a new
|
||||||
its existing acceptance policy for absence; required mode additionally rejects a
|
failed-load evidence API or continuing a failed load to finish classification.
|
||||||
missing declaration when an actual main document participates. `NoSource` retains
|
|
||||||
the existing absent-main checker behavior, since it is not a document.
|
|
||||||
Default mode keeps today's effective-path interpretation unchanged. This supports
|
|
||||||
mounted main input without contradicting source-local lookup or losing protection.
|
|
||||||
|
|
||||||
Alternative: separate the public source-header path from the existing effective
|
Alternative: always redact declaration text in public source evidence. This
|
||||||
main-version path while still using one checker. It makes both coordinate systems
|
simplifies classification and prevents disclosure, but hides ordinary version
|
||||||
explicit and can ease migration for mounted main callers, but adds configuration
|
identifiers that the consumer explicitly wants to inspect. Conversely, treating
|
||||||
and two paths that must be kept coherent. Root-only main input would simplify the
|
headers as inherently public would be simpler but would bypass existing
|
||||||
problem but would restrict an existing capability; do not impose that restriction
|
classification where the configured header path or its ancestor is sensitive.
|
||||||
as an implementation shortcut.
|
Prefer normal classification rather than either blanket rule.
|
||||||
|
|
||||||
### Evidence representation and sensitivity
|
### Headers that are sequence elements
|
||||||
|
|
||||||
Recommendation: attach a detached declaration record to existing source
|
Recommendation: support consumption of a selected sequence element by deleting
|
||||||
inspection, with local path, presence/null/text state, physical location, and
|
that element, retaining the sequence and its order among remaining elements.
|
||||||
explicit redaction state. Reuse existing sensitivity machinery where applicable
|
Later indexes shift in the remaining payload; an emptied sequence remains `[]`.
|
||||||
to the source's mounted header path, retaining classification evidence before
|
This is ordinary removal, not a merge strategy. Retain the header's original
|
||||||
consumption so removing a node does not erase its sensitivity. Main evidence and
|
index and physical location in source evidence; downstream payload paths reflect
|
||||||
source evidence should use consistent disclosure. Retain actual declaration text
|
the post-consumption sequence. Main's retained declaration is not deleted.
|
||||||
privately when needed; inspectable sensitive evidence can be redacted without
|
Removing a mapping member inside a sequence element instead retains that element,
|
||||||
denying that a declaration was checked. Specify handling for historical tags and
|
including an empty mapping, under the agreed ancestor-preservation rule.
|
||||||
dependency classification before choosing storage, rather than exposing raw
|
|
||||||
`Version.Text` unconditionally.
|
|
||||||
|
|
||||||
Alternative: expose declarations through a dedicated source query returning safe
|
This gives exact-node consumption a concrete meaning without restricting existing
|
||||||
snapshots instead of extending source records. This better accommodates on-demand
|
path forms. Verify protected-path and typed behavior where main retains an element
|
||||||
redaction and richer evidence, but adds an API and lookup semantics. Both choices
|
but non-main payloads have shifted indexes; do not invent alignment or bypass
|
||||||
must preserve physical attribution and the requested declaration evidence; neither
|
normal sequence replacement, decoding, or ownership rules to make such inputs fit.
|
||||||
should expose arbitrary malformed input or require reopening the source.
|
|
||||||
|
|
||||||
### Nested consumption and structural directives
|
Alternative: reject headers whose selected node is a sequence element in enabled
|
||||||
|
modes, while permitting mapping-member headers nested inside sequences. This
|
||||||
|
avoids index shifts and may be easier for consumers to reason about, but narrows
|
||||||
|
supported header locations and is not required for correctness if deletion is
|
||||||
|
specified. Replacing the element with null would preserve indexes but fabricate a
|
||||||
|
payload value and could change decoding; it is not the recommended interpretation
|
||||||
|
of consumption.
|
||||||
|
|
||||||
Recommendation: remove only the checked non-main declaration and retain authored
|
### Overlap with structural directives
|
||||||
ancestor containers, even when empty. Validate source structure and interpret
|
|
||||||
existing directives so header consumption cannot conceal an invalid directive or
|
|
||||||
silently cancel an import. Preserve the existing path vocabulary where its
|
|
||||||
semantics apply; explicitly work through sequence-index and structural-path
|
|
||||||
interactions before implementation instead of adding a blanket top-level-only
|
|
||||||
header restriction. Retaining ancestors best preserves input presence outside
|
|
||||||
the requested consumed value.
|
|
||||||
|
|
||||||
Alternative: prune ancestor containers emptied by consumption. This can make a
|
Recommendation: reject an actual overlap between a checked header and an existing
|
||||||
nested metadata-only header disappear completely from application payload, but
|
structural directive node with a structured error in enabled modes. A value must
|
||||||
also removes authored empty-container presence and can affect defaults and
|
not simultaneously serve as a consumed specification declaration and as import
|
||||||
composition. A dedicated top-level header location would simplify these cases,
|
or inheritance control. Include a header selected inside an import declaration
|
||||||
but narrows the existing configurable-path model and would need an explicit
|
or at an `extends` control; preserve ordinary structural validation so malformed
|
||||||
consumer requirement or design decision rather than an implementation shortcut.
|
controls cannot disappear through consumption. Use source-local paths and real
|
||||||
|
locations for these errors. This is a proposed semantic restriction to approve,
|
||||||
|
not an existing general prohibition on nested header paths.
|
||||||
|
|
||||||
|
Limit the rule to structural overlap, not substrings in ordinary keys. A header
|
||||||
|
at `metadata.version` is not blocked merely because its source also contains
|
||||||
|
`configkit.imports`, and a key such as `extends_version` is not an `extends`
|
||||||
|
control. Missing headers remain governed by the selected mode; existing invalid
|
||||||
|
directives still fail independently.
|
||||||
|
|
||||||
|
Alternative: interpret structural directives first, then allow the same node to
|
||||||
|
serve as a checked and consumed header. This can be defined and avoids a new
|
||||||
|
path restriction, but gives one value two unrelated roles: for example, an
|
||||||
|
accepted version string could also name an import file or inheritance parent.
|
||||||
|
It also needs extra ordering and retained-control rules to keep consumption from
|
||||||
|
canceling behavior. Prefer an explicit overlap error over that dual interpretation;
|
||||||
|
there is no identified consumer need for sharing these roles.
|
||||||
|
|||||||
Reference in New Issue
Block a user