Files
2026-05-27 23:29:53 +01:00

6.0 KiB

Why

@suaveplan/crypto ships with versioned-key vocabulary fully implemented in source — DerivationCoordinate carries masterVersion u16 ‖ userId u32 ‖ depth u8 ‖ slotVersion u8 (packages/crypto/crypto/src/derivation/{coordinate,layouts}/), the eight-slot Keychain is built on it (packages/crypto/crypto/src/keychain/), and RootIdentity / ServerIdentity / RevocationList reference a server version (packages/crypto/crypto/src/{identity,revocation}/). The umbrella restore-crypto-keychain-packer-umbrella was archived on 2026-05-03 with 20 requirements covering this surface, but its spec deltas never folded into openspec/specs/crypto/spec.md. The live spec lost DerivationCoordinate, DerivationLayout, masterVersion, slotVersion, BaseKeySchema, Authority, hierarchical identity, revocation, audit log, packer, replay protection, KAT vectors, trust-anchor bootstrap, and OTel redaction as named requirements. The only "version" terms that survived are the password-blob header byte and a stray rollServer increments version scenario with no defining requirement. To compound it, openspec/specs/crypto-keys/spec.md exists as a stub describing the deleted @suaveplan/crypto-keys package, contradicting the live crypto/spec.md:204-207 requirement that the package be deleted (zero matches in packages/). The corpus is internally inconsistent and the central crypto invariant — every key carries (masterVersion, slotVersion) — is undocumented at the requirement layer, so no Verified by: chain pins the existing tests to a spec.

What Changes

  • MODIFIED crypto capability: fold the 13 missing umbrella requirements into openspec/specs/crypto/spec.md with Verified by: pointers to existing tests in packages/crypto/crypto/src/{derivation,keychain,identity,revocation,audit-log,packer,chunked-packer,bundles,wire-format,domain-tags,authority}/. New requirements:
    • Eight-slot Keychain with full-width derivation coordinates (master / encrypt / sign / kx / salt / hash / stream / device)
    • DerivationLayout registry — pluggable u64 layout, default DERIVATION_LAYOUT_V1 (masterVersion u16 ‖ userId u32 ‖ depth u8 ‖ slotVersion u8)
    • Validity windows enforced at every verify call (notBefore / notAfter per slot, injectable Clock)
    • Domain-separation tag on every signed payload (DOMAIN_VAULT_V1, DOMAIN_PUBLIC_KEYCHAIN_V1, DOMAIN_PACKER_V1, DOMAIN_CHUNK_V1, DOMAIN_CRL_V1, DOMAIN_AUDIT_V1)
    • Public bundles are parent-signed and carry an issuer reference ((masterVersion, userId, depth, slotVersion))
    • Chain bundle traversal — concatenated parent-signed links
    • Wire-format schemas exposed and committed (PUBLIC_BUNDLE_MAGIC, CHAIN_BUNDLE_MAGIC, KEY_SLOT_PRIVATE_BYTE_SIZE, KEY_SLOT_PUBLIC_BYTE_SIZE, V1_COORDINATE_BYTE_SIZE, *_FORMAT_VERSION)
    • Authority — signing abstraction over hierarchical identity
    • Hierarchical identity — Root and Server (createRoot, createServer, rollServer with version + 1, revokeServer)
    • RevocationList — root-signed CRL keyed by (serverId, version)
    • AuditLog — append-only Merkle log
    • Packer — encrypt-and-sign envelope with replay protection (issuedAt + nonce)
    • ChunkedPacker — per-chunk-signed P2P fragmentation
  • NOT folded — deferred to a follow-up implementation change: the umbrella's Trust-anchor bootstrap requirement specified src/trust-anchors/ with loadTrustAnchor() / loadTrustAnchorFromEnv() / SUAVEPLAN_TRUST_ANCHOR_PATH. That directory and surface do not exist on genesis. Folding the requirement here would re-introduce the fail-mode this change is fixing (a requirement with no Verified by: pointer). It needs its own implementation change.
  • REMOVED crypto-keys capability: delete openspec/specs/crypto-keys/spec.md (the stub describing the deleted @suaveplan/crypto-keys package). The live crypto/spec.md requirement "Keypair, Keychain storage, BIP39, and legacy Vault live inside @suaveplan/crypto" already asserts the package is gone; the orphan stub contradicts it.
  • This change is spec-only — no source code changes, no test changes. Every new requirement has its Verified by: pointer resolve to an already-passing test file. If a requirement cannot be backed by an existing test, that requirement does not ship in this change (it gets a follow-up implementation change).

Capabilities

New Capabilities

(none)

Modified Capabilities

  • crypto: add 14 requirements covering versioned-key derivation, hierarchical identity, revocation, audit, packer envelopes, wire format, and trust-anchor bootstrap; no requirements modified or removed.
  • crypto-keys: remove the entire spec file. The capability does not exist on genesis (the package was deleted as part of restore-crypto-fold-keys-vault); the stub spec is an artifact of an incomplete archive.

Impact

  • Affected specs: openspec/specs/crypto/spec.md (additions only), openspec/specs/crypto-keys/spec.md (deleted).
  • Affected code: none. Source already implements every requirement being folded; this change documents what already ships.
  • Affected tests: none added, none removed. New Verified by: pointers reference existing test files at packages/crypto/crypto/src/{derivation,keychain,identity,revocation,audit-log,packer,chunked-packer,bundles,wire-format}/.
  • Conformance impact: bun openspec validate crypto-spec-restore-versioning --strict must pass. The post-archive live spec must also pass openspec validate --strict and the existing scripts/openspec-conformance.ts allowlist gate.
  • Downstream: future changes that touch Keychain, Authority, RevocationList, AuditLog, Packer, or ChunkedPacker will now have a stable requirement surface to delta against, instead of free-form code drift.
  • Risk: low — no behaviour changes. The risk is a Verified by: pointer resolving to a test that does not actually cover the requirement; mitigated by the validation step in tasks.md that greps each cited test file for the asserted scenario before the change is archived.