Normative
Status of this specification
Publishing a specification before an implementation is deliberate — the design benefits from review while it is still cheap to change — but it makes an honest status page mandatory. This is that page, and it is the only place on this site where maturity is stated.
Where each part stands
Section titled “Where each part stands”| Part | Status | What that means |
|---|---|---|
| The shared substrate | Stable | One hash, one signature suite, one chained-record schema, one padding function. Nothing here may become optional |
| SSP/1 — synchronization | Complete enough to implement | Its open gaps are enumerated, and promotion carries its own eight gates, all open. Not wire-compatible with any prior mesh synchronization protocol, and no interoperability with one is claimed |
| SOP/1 — object plane | Complete, gated | The full architecture: ES256 root identity, recorded key protection, receipt durability. Promotion to a normative production protocol is gated on G1–G10 below |
| SOP/1 blob annex | Draft | Changes nothing in SOP/1 and carries its own three gates; GB1 is closed, GB2 and GB3 are open |
| SOVM-SYNC-RT | Draft | Carries its own three gates; GR1 is closed, GR2 and GR3 are open |
| SOVM-IROH | Draft | Carries its own three gates, all closed. Draft is the document’s maturity, not the gates’: closing them retires the reservation on the binding, it does not promote the page |
Conformance means agreement with the text plus agreement with the published vectors. Both layers now carry vectors, so independent implementations can be checked against each other on the bytes they exchange, on every refusal the fail-closed inventory requires, and on the state they materialize from the event sets the corpus enumerates — but not yet on convergence as a property over the sets it does not, and SSP/1 §39 names that remainder as the gap that blocks production use.
Decision gates
Section titled “Decision gates”The following gates MUST pass before SOP/1 becomes a normative production protocol. All ten are open. A gate that fails is information rather than a setback: the size-padding capability in particular is specified to fail closed rather than degrade, so “this cannot be done with current tooling” is a legitimate and useful outcome.
| Gate | State | Verdict |
|---|---|---|
| G1 OpenMLS mobile viability | open | target |
| G2 Secure hardware identity | open | target |
| G3 OpenMLS persistence security | open | target |
| G4 Membership/fork behavior | open | target |
| G5 PME interoperability | open | target |
| G6 PME performance | open | target |
| G7 Revocation semantics | open | target |
| G8 Metadata leakage review | open | target |
| G9 COSE interoperability and misuse resistance | open | target |
| G10 Disaster recovery | open | target |
A gate is marked closed here only together with a published verdict naming the evidence it closed on; an open gate’s verdict is a target.
G1. OpenMLS mobile viability
Section titled “G1. OpenMLS mobile viability”Demonstrate correct operation on:
- iOS node hardware;
- Android node hardware;
- suspend/resume;
- process death;
- long offline periods;
- app upgrade;
- node restart.
Building for a target is insufficient; integration must be exercised.
G2. Secure hardware identity
Section titled “G2. Secure hardware identity”The intent of this gate — demonstrate the selected MLS credential/signature integration without silently exporting the SSP root identity private key — cannot be tested as phrased: a gate stated as the absence of a behaviour has no achievable evidence standard, because no finite test run demonstrates that an export never happens. The gate is therefore stated as observable outcomes.
On each target platform, demonstrate that:
- a node root key is generated inside the platform keystore, marked non-extractable at generation, and that an extraction attempt fails;
- the node identity record carries the
key_protectionandattestation_kindvalues that platform actually supports, and the MLS credential binding transcript of Section 5.3 binds them; - a verifier presented with
hardware_attestedand no evidence, expired evidence, or evidence over a different key treats the node assoftware(Section 5.2.4); - a policy requiring a minimum level refuses a node below it rather than admitting it;
- on an element exposing the atomic sign-verify-or-abort primitive that Section 5.4 requires, the hardware signer’s verify-after-sign check is present and rejects a corrupted signature; on an element exposing none, the implementation’s declaration under that section records that, and the per-platform verdict names the unmitigated fault-injection residual rather than reporting a pass.
Each of these is an observable outcome with a pass and a fail. The verdict MUST
be reported per platform and MUST NOT be averaged: an Android StrongBox node
reaching hardware_attested and an iOS node reaching hardware_unattested are
two different results and G2 records both.
G3. OpenMLS persistence security
Section titled “G3. OpenMLS persistence security”Demonstrate:
- encrypted durable state;
- safe deletion behavior;
- no plaintext key backup;
- crash consistency;
- upgrade/migration behavior;
- iOS Keychain accessibility classes use an appropriate
ThisNodeOnlypolicy for non-migratable key material; - iOS key-store/support files are excluded from backup where appropriate.
Exclusion is retained at directory granularity as defence in depth and MUST
NOT be relied on as the confidentiality control:
isExcludedFromBackupis documented as guidance to the system rather than a guarantee, and it is file metadata that the write-temp-then-rename path of any durable store discards. The control is that durable state is ciphertext under a KEK held with a…ThisDeviceOnlyKeychain accessibility class, and that Keystore key material never leaves the TEE or StrongBox to be backed up at all; - Android backup behavior is explicitly configured, including
android:allowBackup, cloud-backup rules, node-transfer rules, and use of no-backup storage for sensitive files; - restore/migration tests prove that copied application files alone do not recreate usable SOP/MLS key authority.
G4. Membership/fork behavior
Section titled “G4. Membership/fork behavior”Exercise:
- simultaneous proposals;
- concurrent commits;
- stale commits;
- delayed Welcome;
- offline member catch-up;
- removed offline member;
- blind relay CAS sequencing;
- simultaneous Commit race with exactly one accepted winner;
- second-Commit rejection for the same MLS epoch;
- relay outage with queued membership changes;
- semantically invalid accepted Commit followed by client rejection and recovery;
- fork detection/recovery for states created outside the normal sequenced path;
- sequencer bootstrap for a newly created group;
- rejection of concurrent dual-sequencer operation and correct epoch transfer on sequencer migration;
- receipt-based sequencer state-loss recovery: recovery from concordant receipt-chain evidence, fail-closed on divergent valid chains, and genesis-reset fallback when no usable receipt evidence survives;
- committer death: MLS epoch advanced but the KEK-distribution message never arrives, followed by recovery through a fresh security rotation and voiding of the undistributed generation;
- sequencer equivocation detection from two valid receipts for the same (group_id, epoch) with different commit hashes, followed by sequencer migration and state audit;
- receipt-chain continuity verification across sequencer migration.
G5. PME interoperability
Section titled “G5. PME interoperability”Demonstrate that SOP-PME-1 files can be:
- written;
- transferred unchanged;
- read by target DuckDB versions;
- selectively scanned;
- compacted;
- verified after corruption tests;
- shown to reject a module transplanted within an object, or between objects
sharing a DEK, by
storage_idverification — the empty module AAD (Section 11.3) does not detect either; - Padmé-padded to the exact target on every object while remaining
byte-for-byte valid PME/Parquet — including an object already at its target,
which still carries the reserved
sovm:sop-pad-v1entry with an empty value, and the sizes immediately above each Thrift varint step, which are reachable only by lengthening the key (Section 11.8); - written with stable Parquet field IDs on every column;
- written with an always-present random 16-byte key_ref, in the writer step order of Section 11.12;
- imported into iroh-blobs with
storage_idexactly equal to the returned iroh-blobs hash.
G6. PME performance
Section titled “G6. PME performance”Benchmark representative datasets on:
- desktop x86-64;
- Apple Silicon;
- Android ARM;
- iPhone/iPad ARM.
Measure:
- ingestion throughput;
- encrypted write overhead;
- selective scan overhead using manifest/catalog-first pruning before PME open;
- false-positive/open rate from manifest/catalog pruning;
- APPEND_DELETE delete-filter pruning effectiveness, including optional data-object row-identity filters, their false-positive rates, and manifest/companion-object size impact;
- full scan overhead;
- compaction;
- memory use;
- battery impact;
- effect of 16, 32, and 64 MiB object targets;
- effect of representative Parquet row-group sizes;
- CPU/platform AES-GCM acceleration availability and impact, including ARMv8 AES/PMULL or equivalent acceleration on minimum supported Android hardware.
G7. Revocation semantics
Section titled “G7. Revocation semantics”Verify through adversarial tests that a removed node cannot:
- receive current post-removal domain KEK generations;
- receive unauthorized historical key packages;
- publish new accepted manifests/access records;
- decrypt future objects.
Additionally verify through adversarial tests that a FORWARD_ONLY member cannot unwrap or decrypt any object predating its admission boundary, including after arbitrary rewrap and KEK-generation-retirement activity in the domain (Section 7.6).
Also verify documentation clearly states that previously authorized historical data cannot be forcibly forgotten.
G8. Metadata leakage review
Section titled “G8. Metadata leakage review”Confirm that untrusted infrastructure does not receive semantic:
- table names;
- schema names;
- domain names;
- plaintext statistics;
- row keys;
- key names.
G9. COSE interoperability and misuse resistance
Section titled “G9. COSE interoperability and misuse resistance”Demonstrate:
- AccessRecord/wrapped-DEK
COSE_Encrypt0conformance; - producer-manifest
COSE_Sign1conformance; - access-record issuer-signature and outer
COSE_Encrypt0conformance; - historical key-history
COSE_Sign1conformance; - deterministic CBOR test vectors;
- protected-header and algorithm validation;
- external-AAD context binding;
- nonce uniqueness under A256GCM;
- rejection of unknown critical headers;
- rejection of algorithm downgrade or cross-context replay.
G10. Disaster recovery
Section titled “G10. Disaster recovery”Demonstrate, on representative hardware:
- periodic catalog checkpoint objects and encrypted+signed
RecoveryRootrecords are produced and placed on blind replicas under ordinary placement policy; - the protected node recovery/key store retains the latest known
RecoveryRootor its content hash without depending on an iroh-local tag; - full recovery of a domain dataset from a blind archive plus a bare node
recovery/key store only:
RecoveryRootresolved, checkpoint fetched bycheckpoint_storage_id, checkpoint access record opened with retained KEK history, catalog restored, objects resolved and queried; - recovery from a stale but valid
RecoveryRootproduces a consistent older catalog and validates any later root chain supplied by the archive adapter; - domain genesis reset end-to-end, including receipt-chain restart and old group retirement;
- sequencer state-loss recovery succeeds from concordant signed receipt evidence and fails closed on divergent valid receipt chains; and
- recovery fails closed, with a clear user-facing state, when any of the three required components (ciphertext, manifest/access metadata, KEK history) is absent.
Known risks to the design
Section titled “Known risks to the design”Recorded because a reader evaluating SOVM/1 should know where it is least settled, not only where it is strongest.
| Area | Risk |
|---|---|
| Parquet encryption | Writer/reader interoperability is unproven |
| Query path | One key per object may conflict with how query engines register decryption keys |
| MLS on constrained nodes | Group state must survive process death, long offline periods and software upgrade, including on mobile platforms |
| Hardware identity | Secure-element integration is platform-specific and may not be available everywhere |
| Sequencer | Correctness under equivocation, migration and state loss is intricate and untested |
| Performance | Encrypted Parquet has non-trivial overhead that has not been benchmarked on target hardware |
Reading the specification with this in mind
Section titled “Reading the specification with this in mind”The specification uses RFC 2119 keywords throughout, which can read as more settled than the situation warrants. A useful convention while the gates are open:
- MUST / MUST NOT — a design commitment an implementation is expected to honour, and which conformance vectors will eventually test.
- SHOULD — a considered default, more likely than the rest to move in response to implementation experience.
- Anything named by a gate above — treat as intent until the gate closes.