Settle sequence identity definitions and policy lifetime
This commit is contained in:
@@ -45,6 +45,8 @@ later. Extending one does not automatically imply extending the other.
|
||||
|
||||
The proposed `configkit.sequences` block introduces a `key` declaration that
|
||||
accepts either one field or a list of fields for a compound identity.
|
||||
Fields are treated as a set; identity components may be strings, numbers,
|
||||
booleans, or explicitly supplied null values.
|
||||
Applications retain an optional interface for registering a collection
|
||||
and imposing its identity definition. Configuration declarations must conform
|
||||
to an application-owned constraint when one exists. The exact Go interface
|
||||
@@ -116,13 +118,13 @@ Identity and mode can be supplied independently. Omitted identity can use an
|
||||
application registration; an explicit matching declaration is accepted, and a
|
||||
conflicting declaration is invalid. Whole-sequence replacement does not itself
|
||||
require identity matching, but application-owned constraints still apply.
|
||||
Identity-policy lifetime across tiers remains under OD-3.
|
||||
Identity-policy lifetime across tiers is settled in OD-3 below.
|
||||
|
||||
Mode describes the current tier's combination instruction. A lower tier's
|
||||
`append` does not silently select append for a later overlay. Gather collection
|
||||
declarations before composing their relevant scope so their effect does not
|
||||
depend on which contribution is assembled first. Agreement and omission among
|
||||
peer declarations remain under OD-4.
|
||||
depend on which contribution is assembled first. Identity agreement is settled
|
||||
in OD-3; operation agreement and omission among peers remain under OD-4.
|
||||
|
||||
Permit sequence declarations in selected overlays and make their use independent
|
||||
of filesystem import enablement. This deliberately changes the current blanket
|
||||
@@ -185,6 +187,90 @@ inline/imported collections without duplicate authoring surfaces. Local wrappers
|
||||
around sequence values would require distinguishing application data from
|
||||
control mappings; the existing reserved namespace keeps that distinction clear.
|
||||
|
||||
### Identity Definitions And Lifetime
|
||||
|
||||
**OD-3: settled.**
|
||||
|
||||
#### Field Sets
|
||||
|
||||
`key` accepts a string or a nonempty list of strings naming direct, literal
|
||||
fields in each record. `key: id` and `key: [id]` are equivalent. A name such as
|
||||
`metadata.id` denotes that literal field, not a nested lookup.
|
||||
|
||||
Treat the selected fields as a set: remove repeated names and disregard authored
|
||||
field order when comparing definitions. For example, `[namespace, id]`,
|
||||
`[id, namespace]`, and `[namespace, id, id]` define the same identity. An empty
|
||||
list is invalid because it supplies no identity fields. These equivalence rules
|
||||
also apply when comparing configuration declarations with application
|
||||
registrations.
|
||||
|
||||
Use a consistent field order internally to construct compound identity tuples.
|
||||
Preserve component types and tuple boundaries; concatenating unstructured values
|
||||
must not cause otherwise distinct identities to collide.
|
||||
|
||||
#### Scalar Components And Equality
|
||||
|
||||
Each identified record must be a mapping, and every designated identity field
|
||||
must be present. Components may be strings, numbers, booleans, or explicit null.
|
||||
Missing fields and mapping or sequence components are invalid. A present null is
|
||||
a valid component and is distinct from an absent field. Two single-field null
|
||||
identities are equal; in a compound identity, all components must compare equal.
|
||||
|
||||
Strings compare exactly, with no trimming, case folding, or normalization.
|
||||
Empty strings remain valid. Scalar categories remain distinct: the string
|
||||
`"1"`, the number `1`, the boolean `true`, and null are different identities.
|
||||
|
||||
Numbers compare by mathematical value across integer, fractional, and exponent
|
||||
spellings: `1`, `1.0`, and `1e0` are equal, as are `0` and `-0`. Use exact numeric
|
||||
normalization for identity comparison without rounding through a floating-point
|
||||
conversion. This comparison does not rewrite authored values or alter existing
|
||||
typed decoding and projection semantics. The existing parser's rejection of
|
||||
non-finite numeric forms remains unchanged.
|
||||
|
||||
#### Agreement And Introduction
|
||||
|
||||
Within a strict tier, identity declarations for the same collection must agree.
|
||||
Equivalent field sets coalesce; different sets produce an error. Across tiers,
|
||||
append and replacement by identity use one agreed definition for the records
|
||||
being combined:
|
||||
|
||||
| Lower collection identity | Higher declaration | Result when combining records |
|
||||
| --- | --- | --- |
|
||||
| `id` | Omitted | Use `id` |
|
||||
| `id` | `id`, `[id]`, or `[id, id]` | Accept the equivalent definition |
|
||||
| `id` | `[namespace, id]` | Error: different identity definitions |
|
||||
| None | `id` | Establish `id` and validate all participating records under it |
|
||||
|
||||
An application registration supplies identity when configuration omits it and
|
||||
remains authoritative over explicit declarations. If neither the application nor
|
||||
either participating collection supplies an identity, append and replacement by
|
||||
identity fail; ConfigKit does not infer an `id` convention. Introducing identity
|
||||
for a previously unkeyed lower sequence requires checking both lower and incoming
|
||||
records, including uniqueness within each contribution.
|
||||
|
||||
#### Replacement And Policy Lifetime
|
||||
|
||||
YAML-owned identity follows the collection that survives an operation:
|
||||
|
||||
| Operation | Effective YAML-owned identity |
|
||||
| --- | --- |
|
||||
| Append | Retain or establish the agreed identity |
|
||||
| Replacement by identity | Retain or establish the agreed identity |
|
||||
| Whole-sequence replacement | Use the replacing tier's declaration and discard the lower collection's YAML-only identity |
|
||||
|
||||
Without an application constraint, whole-sequence replacement may introduce a
|
||||
different identity, such as replacing an `id`-keyed collection with a `name`-keyed
|
||||
collection. A whole-sequence replacement with no new identity declaration and no
|
||||
application registration produces an unkeyed sequence. No separate identity
|
||||
removal directive is needed.
|
||||
|
||||
Application registrations continue to constrain the replacement collection.
|
||||
If the application requires `id`, declaring `name` is invalid under every mode.
|
||||
The policy reset above applies when a sequence is actually replaced; effects of
|
||||
absent contributions, null collections, and kind mismatches remain under OD-6.
|
||||
These structural rules do not settle final-result enforcement for YAML-only
|
||||
identity declarations, which remains the OD-1 follow-up.
|
||||
|
||||
### Whole-Record Replacement By Identity
|
||||
|
||||
The third cross-tier operation replaces each matching lower record with the
|
||||
@@ -264,9 +350,9 @@ and does not extend to caller mutations after loading returns.
|
||||
|
||||
Keep the promise limited to the declared identity constraints. It does not by
|
||||
itself require registered paths to exist or settle null and non-sequence
|
||||
handling; those boundaries remain under OD-3 and OD-6. Final validation examines
|
||||
handling; those collection boundaries remain under OD-6. Final validation examines
|
||||
effective typed values, while assembly-time checks retain their role in
|
||||
validating authored contributions. A final string value alone does not prove
|
||||
validating authored contributions. A final scalar value alone does not prove
|
||||
that the field was explicitly supplied in a source.
|
||||
|
||||
The existing canonical final-value representation and shared publication path
|
||||
@@ -286,16 +372,17 @@ The initial recommendation is to compose each tier's contributions strictly,
|
||||
then apply one collection operation from the higher tier against the lower
|
||||
sequence. A collection declaration would therefore govern its tier's contribution
|
||||
at that destination, without sequentially erasing peer contributions. Multiple
|
||||
agreeing declarations could coalesce; conflicting explicit identity or operation
|
||||
declarations would produce errors.
|
||||
agreeing operation declarations could coalesce; conflicting explicit operations
|
||||
would produce errors. Identity declaration agreement is already settled in OD-3.
|
||||
|
||||
For append, the ordering recommendation is to retain lower-tier item order and
|
||||
then the higher tier's assembled item order. For replacement by identity, retain
|
||||
the position of each replaced record and append new identities in higher-tier
|
||||
order. Existing dependency-ready scheduling would continue to determine assembly
|
||||
order within a tier. Whole-sequence replacement would retain only the higher
|
||||
tier's assembled sequence. Ordering and the treatment of peer declarations remain
|
||||
recommendations awaiting agreement, not changes to the current ordering contract.
|
||||
tier's assembled sequence. Ordering and the treatment of peer operation
|
||||
declarations remain recommendations awaiting agreement, not changes to the
|
||||
current ordering contract.
|
||||
|
||||
This requires collection policy to survive import expansion through precedence
|
||||
assembly. Correctness includes final values, projected item paths, source
|
||||
@@ -333,37 +420,17 @@ Application-registered collections have the settled final-result guarantee
|
||||
above. Should a configuration-only identity declaration carry the same
|
||||
guarantee, or govern structural assembly alone?
|
||||
|
||||
**Initial recommendation:** With declaration scope settled in OD-2, resolve
|
||||
identity-policy lifetime across replacement in OD-3 before this choice. Final
|
||||
enforcement needs an unambiguous effective policy for each retained collection. The
|
||||
application-owned guarantee can proceed independently of this choice.
|
||||
**Discussion basis:** Declaration scope and identity-policy lifetime are settled
|
||||
in OD-2 and OD-3. Revisit final enforcement using the effective identity of each
|
||||
retained collection. The application-owned guarantee remains independent of
|
||||
this choice.
|
||||
|
||||
**Alternatives:** Applying the same final check to YAML-declared identities
|
||||
would give both declaration forms consistent enforcement, but requires resolving
|
||||
which policy survives replacement or follows nested records. Limiting YAML-only
|
||||
identity to assembly keeps policy lifetime narrower, but later operations could
|
||||
produce a final collection that no longer satisfies that identity declaration.
|
||||
|
||||
### OD-3. What Constitutes Identity, And When Can It Change?
|
||||
|
||||
Settle compound-key field selection, value types, missing/null components,
|
||||
empty and repeated field lists, empty identity strings, and agreement between
|
||||
declarations. Decide whether whole-sequence replacement can introduce a different identity
|
||||
definition after discarding the lower collection when the application has imposed
|
||||
no identity constraint. An application-owned constraint remains authoritative.
|
||||
|
||||
**Initial recommendation:** Interpret `key: id` as `[id]` and a compound key as
|
||||
an ordered tuple of direct, literal string fields. Retain exact string comparison
|
||||
and require every component to be present. Preserve tuple boundaries rather than
|
||||
concatenating values. Identity declarations participating in append or replacement
|
||||
by identity must agree; equal definitions within a scope coalesce and conflicting
|
||||
definitions fail. Detailed list validation and identity changes at whole-sequence
|
||||
replacement boundaries remain to be settled.
|
||||
|
||||
**Alternative:** Permit additional scalar types or nested field paths. These
|
||||
support more schemas but add type-equality and addressing rules. A load-wide fixed
|
||||
identity definition simplifies agreement across tiers; allowing a replacement to
|
||||
establish a new definition gives independently authored layers more flexibility.
|
||||
would give both declaration forms consistent enforcement, but requires carrying
|
||||
the effective policy through later lifecycle stages, including nested records.
|
||||
Limiting YAML-only identity to assembly keeps policy lifetime narrower, but later
|
||||
operations could produce a final collection that no longer satisfies that
|
||||
identity declaration.
|
||||
|
||||
### OD-4. What Does A Combination Choice Control?
|
||||
|
||||
|
||||
Reference in New Issue
Block a user