Normative
Registry
One specification, one namespace. This page indexes every registered identifier across both layers, so a proposed new value can be checked for collisions in one place and the shared conventions can be read once instead of inferred twice.
It is an index, not a definition: the linked section is the normative home of each value, and the site’s drift check asserts that every wire-visible literal below still appears in its home specification — a row here cannot quietly outlive the thing it names.
The module identifiers are checked differently, because their home is the profiles index rather than a specification section: the check asserts that each one is declared in that index and each module the index declares is registered here, so neither page can name a module the other has dropped.
COSE content types
Section titled “COSE content types”Durable signed records are versioned by their protected content type, named
sovm/<layer>-<record>-v<N>. The content type sits inside the signed structure,
so it cannot be swapped in flight, and a verifier that does not know it fails
closed.
| Content type | Record | Normative home |
|---|---|---|
sovm/ssp-event-v1 |
Change event | SSP/7 data model |
sovm/ssp-vouch-v1 |
Vouch certificate | SSP/1 identity |
sovm/ssp-role-v1 |
Role assignment | SSP/1 scope |
sovm/ssp-custodian-v1 |
Custodian designation | SSP/1 scope |
sovm/ssp-capability-v1 |
Capability requirement | SSP/1 scope |
sovm/ssp-modules-v1 |
Per-node module set | SSP/1 scope |
sovm/ssp-binding-v1 |
Transport binding | SSP/1 transport |
sovm/ssp-eventkey-v1 |
Event-signing subkey | SSP/10 data model |
sovm/ssp-succession-v1 |
Identity succession | SSP/1 identity |
sovm/sop-access-v1 |
Access record (wrapped DEK) | SOP/1 domains |
sovm/sop-recovery-root-v1 |
Recovery root | SOP/1 objects |
sovm/sop-authorization-v1 |
Membership authorization record | SOP/1 identity |
Raw domain-separation labels
Section titled “Raw domain-separation labels”Transient transcript signatures and derivations use raw ASCII labels, named
sovm-<scope>-<purpose>-v<N>. The dividing rule: durable records get content
types; a signature that never outlives its ceremony gets a label.
| Label | Purpose | Normative home |
|---|---|---|
sovm-mesh-id-v1 |
mesh_id derivation |
SSP/1 terminology |
sovm-mesh-pair-v1 |
Pairing transcript | SSP/1 identity |
sovm-mls-credential-binding-v1 |
MLS credential binding transcript | SOP/1 identity |
HKDF info strings
Section titled “HKDF info strings”Scoped by their input key rather than globally.
info |
Purpose | Normative home |
|---|---|---|
pair-session |
Pairing session key | SSP/1 identity |
pair-sas |
SAS derivation | SSP/1 identity |
Object kinds and encrypted-object formats
Section titled “Object kinds and encrypted-object formats”Manifest-carried enumerations of the object plane. An implementation MUST fail closed on an unregistered value in either column — the base plane’s own rule, stated at SOP/1 §12.3, which the blob extension relies on for its omission behaviour.
| Identifier | Kind | Normative home |
|---|---|---|
SOP-PME-1 |
Encrypted-object format (Parquet) | SOP/1 Parquet profile |
SOP-BLOB-1 |
Encrypted-object format (chunked AEAD blob) | Blob extension format |
blob |
object_kind manifest value |
Blob extension manifest profile |
Container metadata keys
Section titled “Container metadata keys”Keys an encrypted-object container carries in its own metadata rather than in a
SOVM record, named sovm:<layer>-<use>-v<N>. The colon separates them from the
COSE content types above, which share the sovm namespace but not the shape: a
value in this family is never a signed record, and never reaches a verifier.
A row here reserves a key prefix. A writer MAY extend the key as the row’s normative home permits, and a reader MUST recognise it by prefix.
| Key | Use | Normative home |
|---|---|---|
sovm:sop-pad-v1 |
Reserved size-padding entry in the encrypted Parquet footer | SOP/1 Parquet profile |
Conformance module identifiers
Section titled “Conformance module identifiers”Names for whole capabilities rather than for wire values: the unit in which an implementation states what it built, and a domain states what it requires. The namespace is fixed here rather than in a second registry, which is what makes an unregistered module identifier an unregistered value — so the fail-closed rule this page already carries covers it, and a node that meets a module it does not know refuses instead of guessing.
Each identifier’s home is its row in the profiles index, which names the tier, the whole sections the module comprises, and what an implementation that omits it must do. The normative text does not move: the index points at sections, and the sections keep their sentences.
| Identifier | Capability | Normative home |
|---|---|---|
SOVM-BASE |
The floor: substrate, identity, host interface — in every module set by construction | Profiles index |
SOVM-SYNC |
The SSP/1 synchronization layer, claimed whole | Profiles index |
SOVM-OBJ |
The SOP/1 object plane, claimed whole | Profiles index |
SOVM-SYNC-RT |
Realtime push mode | Profiles index |
SOVM-DEL |
APPEND_DELETE domains, including placement and blind replicas |
Profiles index |
SOVM-SEQ |
Blind Commit sequencer | Profiles index |
SOVM-HIST |
Historical access beyond FORWARD_ONLY |
Profiles index |
SOVM-BLOB |
The blob extension, as a claimable capability | Profiles index |
SOVM-IROH |
The iroh transport binding | Profiles index |
Each module identifier also carries an MLS extension type value, from the
RFC 9420 private-use range, for
the capability declaration: a mesh
requires a module by listing this value in a group’s
required_capabilities. The mapping is registry data — declared here, never
negotiated in a message.
| Module | MLS extension type |
|---|---|
SOVM-BASE |
0xF401 |
SOVM-SYNC |
0xF402 |
SOVM-OBJ |
0xF403 |
SOVM-SYNC-RT |
0xF404 — registered for completeness; tier 2 MUST NOT appear in required_capabilities |
SOVM-DEL |
0xF405 |
SOVM-SEQ |
0xF406 |
SOVM-HIST |
0xF407 |
SOVM-BLOB |
0xF408 |
SOVM-IROH |
0xF409 — registered for completeness; which binding a session runs is a transport fact, not group state |
The SOVM-* prefix is the one module namespace: a claim naming an identifier outside this table is an unregistered identifier
and is rejected, never mapped. Placement carries no module row of its own — the
capability travels inside SOVM-DEL, because garbage collection’s correctness
assumes deletes exist and a dependency like that must be declared together with
what it depends on (the coupling rule).
Module identifiers are named SOVM-<CAPABILITY> in upper case, unversioned
at their first definition. A change to what a module comprises that an existing
implementation could not satisfy takes -v2 and upward, following the -v<N>
convention the content types and labels above already use.
That suffix shape is deliberately not the bare numeral the
encrypted-object formats carry, so the two cannot be read for one another in one
namespace: SOVM-BLOB is the module a node claims, SOP-BLOB-1 is the
encrypted-object format that module defines, and a future incompatible
redefinition of the module would be SOVM-BLOB-v2 rather than SOVM-BLOB-2.
Transport binding identifiers
Section titled “Transport binding identifiers”A transport binding is SOVM/1’s third document
class: how SOVM/1’s messages cross a named transport, plus a registered
identifier, adding no semantics. The binding’s conformance identifier is a
module identifier and lives in the table above —
SOVM-IROH is the first. What is registered
here are the wire-visible values a binding defines, with the binding page as
each value’s normative home.
| Value | Purpose | Normative home |
|---|---|---|
sovm/0 |
ALPN string of the iroh binding — versions the binding’s wire format, never the protocol | SOVM-IROH §2 |
PROTOCOL_VIOLATION (0x01) |
QUIC application close code — stream or frame discipline violated | SOVM-IROH §9 |
TRUST_FAILED (0x02) |
QUIC application close code — the trust-resumption hard fail | SOVM-IROH §9 |
FRAME_TOO_LARGE (0x03) |
QUIC application close code — frame exceeded the receiver’s declared bound | SOVM-IROH §9 |
UNSUPPORTED_BINDING_VERSION (0x04) |
QUIC application close code — no mutually supported binding wire format | SOVM-IROH §9 |
The ALPN carries the binding-format version and nothing else; the protocol is
versioned in-band by ssp_version
(messages §30). That division is the
lesson transport §23
records, kept visible where the values are registered.
Shared conventions
Section titled “Shared conventions”Four rules hold across the whole specification. Their normative home is the substrate part, and this section is an index over it — the same index-not-definition split every other section of this page keeps.
- One signature container. Every durable record in either layer is a
COSE_Sign1under the substrate signature profile:ES256only, so that the node root key can be held in secure hardware; deterministic CBOR payload, the signer’s 16-bytesite_idin the protectedkid, empty unprotected bucket, fail-closed on unknown critical headers. SOP/1 additionally uses one encryption suite (A256GCMCOSE_Encrypt0) for its wrapped-key records; SSP/1 seals nothing. - One context principle.
external_aadcarries what the verifier must supply rather than trust. SSP/1 records bind the 16-bytemesh_id; SOP/1 records bind richer per-record context — storage identity, domain, key generation — on the same principle. A record replayed outside its context does not fail a policy check; it fails signature verification. - One hash. An identifier is BLAKE3 over the exact bytes of a signed or
stored structure —
event_id,access_record_hash,object_manifest_hash,storage_id, every chain link. Neither layer maintains a second hash namespace. - One chaining shape. Policy-shaped state is a chained record: monotonic generation plus predecessor hash, per authority. SOP/1 instantiates it for authorization records and sequencing receipts; SSP/1 for role assignments and (generation-only) transport bindings. A fork in any chain is detectable evidence, never a silent divergence.
Adding a value
Section titled “Adding a value”A new identifier MUST be registered here in the same change that introduces it, and MUST follow the naming patterns above. The registry exists precisely so that the check is one page rather than two specifications.
A module identifier is registered the same way and in the same change, and the gate a candidate must pass before it becomes a module at all is on the profiles index.