§15 Schema delta summary
Additions, widenings and encodings relative to ver-record-1.0.1.json.
15.1 The delta
| Location | Change | Section |
|---|---|---|
/ver_version | const → "1.1" | §1 |
/lineage | new — parents[], recipe_sha256, recipe_uri; recipe_uri ⇒ recipe_sha256 | §3 |
/extensions | new — reverse-DNS namespaced object | §13 |
/allOf[0] | new — a compose chain event requires lineage with ≥ 2 composed parents | §3.3 |
/provenance/registry | new — registry snapshot binding; required when a bare action token is not one of the sixteen | §2.2 |
/provenance/chain/items/action | enum → constrained string + registry | §2.3 |
/provenance/chain/items/target, /uri | new; a sign event's target must be record | §2.3.1, §2.3.2 |
/provenance | new — a sign event requires signature | §2.3.3 |
/provenance/c2pa/status | + unverifiable; reason required for it and forbidden otherwise; error_detail optional everywhere | §6 |
/metadata/raw/items | + index, + bytes_ref, + consumed_by_cpnp; bytes XOR bytes_ref; index required per family with > 1 entry | §10.1, §10.2 |
/metadata/availability | + other key, + upstream_withheld state | §10.3, §5.2 |
/metadata/availability_basis | string → oneOf[string, per-family object]; entries non-empty; required per stripped_suspected family in the object form | §10.3 |
/metadata/normalized | top-level values carrying redacted must match the redacted-value object | §5.2 |
/metadata/redactions/items | salted_sha256 → commitment_sha256 + commitment_alg; + state; + normalized_pointer; commitment required/forbidden by state | §5.2 |
/metadata/trust/items, /metadata/conflicts/items/values/items | closed | §15.2 |
$defs/sha256Hash, $defs/pixelHash | closed; pixelHash split out so both can be | §15.2 |
$defs/spaceDescriptor/kind | + joint_visual_text | §11.1 |
$defs/spaceDescriptor/metric | + hamming; binary ⇔ hamming; binary ⇒ normalization: none | §11.2 |
$defs/spaceDescriptor/space_id | widened pattern (first-label hyphens, prerelease, build) | §11.6 |
$defs/spaceDescriptor | model conditionally required by kind; + derived_from; + descriptor_uri/descriptor_sha256 with the coupling. The descriptor object itself was already closed in 1.0.1; its provenance sub-object is closed here | §11.5, §11.3, §15.2 |
$defs/modelDescriptor | new, closed — + revision, + checkpoint_uri (⇒ revision), + bundle, + artifacts[]; weights_sha256 unchanged in meaning | §4 |
$defs/bundleManifest | new — bundle_digest_alg, manifest_sha256, files[]; no canonicalization member | §4.2 |
$defs/portablePath | new — hardened path grammar, used by bundle.files[].path and artifacts[].path | §4.2 |
$defs/referenceClaim | new, closed — set_manifest_sha256 required; tolerance_hamming_max; dtype-conditional tolerance rules and the 0.99 float floor | §8.2, §11.2 |
$defs/redactedValue | new, closed | §5.2 |
$defs/lineageParent | new, closed — resolvable-identifier rule; pixel_hash as {value, cpnp_version} | §3.3 |
$defs/compute | new | §9 |
$defs/embedding | + compute; dim/dtype required; no inline vector for binary; recipe closed | §9, §12, §11.2 |
15.2 The seven objects, closed
sha256Hash, spaceDescriptor.model, .reference, .provenance, metadata.trust[], conflicts[].values[] and embedding.recipe were left open in 1.0.x by oversight rather than by design (SCH-04): the prose enumerates their members and the schema forgot to say so. 1.0.1 deferred closing them to keep its corrective delta surgical (ADR-0002), and an earlier revision of this draft deferred them again to preserve the superset property. They are closed here.
sha256Hash needed a structural change to be closable at all: 1.0.x composed it into identity.pixel_hash through allOf, so closing the shared definition would have rejected width and height. 1.1 gives pixel_hash its own definition ($defs/pixelHash), after which both are closed independently. The record shape is unchanged — the same four members, the same requirements.
Closure is taken under VERSIONING.md §2.3's evident-intent carve-out and is recorded in COMPATIBILITY.md. A Producer that needs a member the standard does not define has extensions (§13), which is the mechanism that makes closure affordable.
15.3 URI ⇒ digest, everywhere it applies
A URI that a Consumer is told to fetch and use is only as trustworthy as the digest beside it. 1.1 requires the digest wherever the URI names an artifact whose content this Record depends on:
| URI | Requires | Section |
|---|---|---|
spaceDescriptor.descriptor_uri | descriptor_sha256 | §11.3 |
lineage.recipe_uri | recipe_sha256 | §3.3 |
reference.set_uri | set_manifest_sha256 (always, not conditionally — a reference block is a tolerance claim) | §8.2 |
model.checkpoint_uri | model.revision (an immutable pin rather than a digest, because the artifact is a repository) | §4.3 |
raw[].bytes_ref, vector_ref, source_bytes_ref, artifacts[].uri | sha256 — already required by the object's own shape | §10.1, §4.3 |
Two URIs are deliberately not coupled, and the boundary is stated so that the omission is a decision: provenance.acquisition.source_uri (the bytes it names are already covered by content_hash and source_bytes_ref, E25) and provenance.chain[].uri (a location where something was published, not an artifact whose integrity the Record binds).
15.4 Normative here, not in the schema
Everything the schema can express, it now expresses. What remains is the set of rules JSON Schema cannot carry at any price, plus one deliberate exception.
(a) Not expressible in JSON Schema — profile-enforced for the life of VER 1.x. No ratification vote can encode these; the only question is whether that is acknowledged.
| Rule | Section | Why no schema can carry it |
|---|---|---|
space_id unique within spaces[] | §11.4 | No key-uniqueness keyword over an array of objects; uniqueItems compares whole items. Profile: VER401 |
raw[].index unique and contiguous within a family | §10.1 | Comparing two array members. Profile |
dim/dtype equal the referenced descriptor's | §12 | A cross-object comparison. Profile: VER601, VER602 |
Vector byte length = dim × sizeof(dtype), or ceil(dim/8) | §11.2 | Arithmetic over three members. Profile: VER603–VER605 |
tolerance_hamming_max ≤ dim | §11.2 | Comparing two members. Profile |
commitment_sha256 equal in ledger and normalized view | §5.2 | Comparing two members. Profile |
Authority control over space_id | §11.6 | A domain-ownership fact about the world, not a property of the document |
| Raw-segment byte ranges | E11 | A statement about which octets a digest covers, not about the JSON that carries it |
Every digest-recomputation rule — manifest_sha256, descriptor_sha256, recipe_sha256, set_manifest_sha256, commitment_sha256, raw[].sha256 | §4.2, §11.3, §3.4, §8.2, §5.3, E11 | Requires hashing |
| Bundle path uniqueness, pre-sorted order, and symlink-free resolution | §4.2 | Two of the three compare members; the third is a filesystem property |
lineage contains no cycle | §3.3 | A property of a graph spanning Records |
| Fusion recipe is part of a fused space's identity | §11.5 | A cross-Record question |
| Registry membership of a bare action token | §2.3 | The registry changes between releases; a schema cannot hold it |
| Derived artifacts of a redacted value are withdrawn | §5.4 | Joining redactions[] to embeddings[].source is a cross-object comparison, and "derived from" is not a property of the document at all. Profile: VER1011 for the exact-field map; everything beyond it is a Producer duty no validator can discharge |
| The raw-carriage carve-out is value-scoped | §5.2, E15 | Whether a preserved segment contains a redacted value requires parsing arbitrary container bytes. The profile checks the two projections it can decide — the family's own segment (VER1005/VER1010) and the ledger field's prefix-mapped family — and a value duplicated into an unrelated family is the Producer's duty under the value-scoped MUST |
(b) Encodable in principle, deliberately not encoded, for a stated reason.
| Rule | Section | Reason |
|---|---|---|
| The size limits | §7 | Three distinct quantities, none portably encodable: no keyword bounds the document's byte length; maxLength bounds base64 text, not decoded octets — conflating the two is the incoherence §7 exists to fix; and no keyword sums across array members. Profile: VER104, whose defaults now match §7 exactly |
Per-kind preprocessing member lists, including a joint_visual_text descriptor's two halves | §11.1, E13 | Descriptor completeness is graded, not gated: E13's full-descriptor definition backs a warning (VER405) so that an incomplete descriptor produces a diagnosis rather than an unparseable Record. Promoting it to a schema requirement is a ratification question, listed on RELEASE.md |
The redacted-value shape below the top level of metadata.normalized | §5.2 | The top level is encoded. Below it, the vocabulary belongs to IPTC and a partial structural check on a privacy construct reads as a guarantee it is not — and no profile code reads nested members either, a limit this row previously misstated by naming codes that check the ledger, not the nested shape. Below the top level the shape is prose-normative only |
