Skip to content

docs(ccb): establish the CCB framework and object registry; finding 7 stays open - #686

Merged
cryptskii merged 1 commit into
mainfrom
docs/rev15-ccb-object-registry
Aug 21, 2026
Merged

cryptskii merged 1 commit into
mainfrom
docs/rev15-ccb-object-registry

Conversation

@cryptskii

@cryptskii cryptskii commented Aug 21, 2026 •

Copy link
Copy Markdown
Collaborator

Finding 7 is NOT closed by this PR, and the document says so in its own header. What lands here is the framework, the namespace, and a complete gap inventory. Rev 15's commitments do not become independently derivable until the blocked classes are resolved — that is the work §7 schedules as three separate amendments.

Merging it as a framework is deliberate: holding it open until all ten designs are solved would turn a clean, reviewable framework into an unreviewable protocol omnibus.

Normative and encoder-free by design — no Rust, no reference encoder, no golden vectors. The single reviewable question is are these bytes uniquely specified? Whether an implementation emits them is the next question, answered separately, so a reference encoder cannot define the protocol by accident.

docs/papers/ccb-object-registry.md, one file.

Framework (§2) — complete, not blocked

Fixes what Req 3.1 requires and Rev 15 never supplies:

  • Envelope — u16_be(class) ‖ u16_be(schema_version) ‖ fields…, ascending declared field number, not self-describing.
  • Primitives — digest32 is deliberately distinct from bytes, because a 32-byte digest emitted as bytes carries a redundant length prefix a second implementation might reasonably omit. That is precisely the Req 3.2 divergence class.
  • Optionals — presence marker always emitted; skipping an absent field would let two logical objects share a byte string.
  • Sets — counted, ordered by element encoding, duplicates invalid rather than deduplicated. The count is in the preimage so variable-length elements can't be re-split ({"ab","c"} vs {"a","bc"}).
  • Nesting — inline by value, never by digest.

Sub-object-by-digest is rejected in the text, not merely avoided: a digest is only well-defined once its preimage is, so inserting policies by digest moves the same hole one layer down.

Namespace immutability (§2.7)

One table, not ad hoc per section. Once an (object_class, schema_version) ships, its discriminant and every field number are frozen — numbers never recycled, fields never renumbered, changed semantics take a new version or class, retired classes burned. Without this the registry becomes the next source of the ambiguity it closes.

Honest status (§4)

Nineteen live classes:

Count Classes
Fully specified (§5) 5 0x0002, 0x0004, 0x0005, 0x000B, 0x0013
Partial 4 0x0006, 0x000E, 0x000F, 0x0011
Blocked, class assignment only 10 see §6

The ten are blocked because Rev 15 names them without enumerating their contents — P_M is "the bounded market-fulfillment policy" and nothing more. §6 states the exact missing decision for each rather than inventing a field table. Writing one would settle protocol in this document exactly as writing an encoder first would settle it in Rust.

The framework and namespace are not blocked on §6 and can be implemented against for the five specified objects immediately.

storage_set_id absorbed as-shipped

Adopted exactly, with two deliberate deviations recorded rather than hidden: no envelope, because the preimage begins with the domain tag and 0x00 separator that dsm_domain_hasher emits (verified in source); and bare length-prefixed member ids with no element object class. Every deployed vault's signed anchor already commits an id under this construction, so the class is frozen and marked must not be "cleaned up". A future StorageSetV2 may adopt the envelope under a new number.

Class 0x0003 was briefly assigned to a StorageMemberId object before §5.2 established that member ids are bare bytes. It is burned, not reused — the immutability rule applied to the registry's own drafting.

What follows, recorded in §7

Three semantic amendments, not one omnibus, ordered by dependency:

  1. DLV state and policy — VaultStateV2, P_M, B_M, P_R, Φ, finishing M. First, because it is what unblocks Anchor V2. The beta family stays intentionally narrow: constant-product market execution and owner-local full close. The breadth of the existing Rust FulfillmentMechanism enum is not evidence its variants belong in a Rev 15 P_M.
  2. Routing and commitment — Route, RouteSet, X, TradeDigest. One dependency cluster; an accidental transport field must not become canonical merely because it exists in protobuf.
  3. Settlement and evidence — DlvProofMaterial, ConsumedDlvTransition, SettlementBundle, TraderAcceptance. A_B derives from Rev 15, not from the bespoke post_root receipt it replaces.

Then production encoder → independent conformance encoder/parser → golden vectors.

A prerequisite is recorded inside amendment 3. A_B carries ordinary DSM successor material (C_T^+, σ_T^+). The repo's CanonicalEncode module calls itself "Single source of truth for all canonical encodings" while the trait requires only "deterministic, unambiguous byte representation" — per-implementation determinism, not a cross-implementation schema (verified in common/canonical_encoding.rs). If ordinary DSM successor CCB is not normatively specified elsewhere, it opens as a Core canonical-successor encoding prerequisite and SoFi references it rather than restating it.

A three-tier rule governs every field: transcribe where Rev 15 fixes the logical fields, absorb as shipped only where compatibility is itself protocol-significant (the deployed storage_set_id), design normatively where the spec only names a concept — and in that tier Rust is evidence, not authority.

Anchor V2 stays blocked until 0x0001 is unblocked: h_n = c_{n-1} is not computable without CCB(VaultStateV2), which is blocked transitively on P_M, P_R and Φ.

Terminology

Canonical cross-implementation commitment encoding throughout. DSM has no global consensus layer; the only consensus string in the file is the sentence rejecting the term.

… stays open

Finding 7 of the Rev 15 conformance delta is NOT closed by this document, and
it now says so in its own header. What lands here is the framework, the
namespace, and a complete gap inventory. Rev 15's commitments do not become
independently derivable until the blocked classes are resolved, which is the
work §7 schedules.

The document is normative and encoder-free: no Rust, no reference encoder, no
golden vectors. Its single reviewable question is whether the bytes are uniquely
specified. Whether an implementation emits them is answered separately, so that
a reference encoder cannot define the protocol by accident.

The framework fixes what Req 3.1 requires but Rev 15 never supplies: a blob
envelope of u16_be class and u16_be schema version, primitive encodings with
digest32 distinct from bytes so a redundant length prefix cannot diverge,
explicit presence markers that are always emitted, counted sets ordered by
element encoding with duplicates invalid rather than collapsed, sorted maps, and
nested objects inline by value rather than by digest.

Sub-object-by-digest is rejected in the text, not just avoided. A digest is only
well defined once its preimage is, so inserting policies by digest would move
the same hole one layer down.

Discriminants and field numbers come from one namespace table and are immutable
once shipped: numbers are never recycled, fields never renumbered, changed
semantics take a new schema version or a new class, and retired classes are
burned. Without that rule the registry becomes the next source of the ambiguity
it exists to close.

Nineteen live classes. Five are fully specified, four are partial, ten carry
only a class assignment. The ten are stated as blocked with the exact missing
decision for each, rather than being given invented field tables.

storage_set_id is absorbed exactly as it ships, including two deliberate
deviations from the framework: no envelope, because the preimage begins with the
domain tag and 0x00 separator that dsm_domain_hasher emits, and bare
length-prefixed member ids with no element object class. Every deployed vault's
signed anchor already commits an id under that construction. The class is frozen
and marked must-not-be-cleaned-up. Class 0x0003 was briefly assigned to a
StorageMemberId object before that was resolved, and is burned rather than
reused — the immutability rule applied to the registry's own drafting.

§7 schedules the remainder as three semantic amendments rather than one omnibus:
DLV state and policy first because it unblocks Anchor V2, then routing and
commitment, then settlement and evidence. It records that the beta policy family
stays intentionally narrow — constant-product market execution and owner-local
full close — and that the breadth of the existing Rust FulfillmentMechanism enum
is not evidence that its variants belong in a Rev 15 P_M.

A prerequisite is recorded inside the third amendment: A_B carries ordinary DSM
successor material, and the repository's CanonicalEncode trait calls itself the
single source of truth for canonical encodings while requiring only deterministic
bytes per implementation. That is not a cross-implementation byte schema, so
ordinary DSM successor CCB must be opened as a Core prerequisite and referenced,
never restated ad hoc inside SoFi.

A three-tier rule governs every field in every amendment: transcribe where Rev 15
already fixes the logical fields, absorb as shipped only where compatibility is
itself protocol-significant, and design normatively where the spec only names a
concept. In that third tier Rust is evidence, not authority.

Called canonical cross-implementation commitment encoding throughout. DSM has no
global consensus layer and the other term would import a model the protocol does
not have.
@cryptskii
cryptskii force-pushed the docs/rev15-ccb-object-registry branch from 93ca5f9 to d2c56d0 Compare August 21, 2026 07:55
@cryptskii cryptskii changed the title docs(ccb): the canonical commit-bytes object registry, normative and encoder-free docs(ccb): establish the CCB framework and object registry; finding 7 stays open Aug 21, 2026
@cryptskii
cryptskii merged commit 831f03d into main Aug 21, 2026
18 checks passed
@cryptskii
cryptskii deleted the docs/rev15-ccb-object-registry branch August 21, 2026 12:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant