Files
suaveplan/openspec/archive/2026-05-03-restore-crypto-opinionated-layer/proposal.md
2026-05-27 23:29:53 +01:00

6.7 KiB

restore-crypto-opinionated-layer — build the missing modules in @suaveplan/crypto

Packages: @suaveplan/crypto Status: PROPOSED Type: feature (additive; no breaking changes to existing modules) Carved from: restore-crypto-keychain-packer umbrella (2026-05-03) Depends on: restore-crypto-cleanup-duplicates and restore-crypto-fold-keys-vault must land first

Why

After slices 1 and 2, @suaveplan/crypto holds the keychain, derivation, bundles, domain-tags, authority shell, errors, and folded keypair / BIP39 / legacy-Vault surface. The big gap is the behavioural opinionated layer — the actual signing hierarchy, signed envelopes, and append-only structures that turn primitives into a coherent product. Without these modules, the package is a label without a substance.

This slice ships the seven missing modules:

  1. Authority — concrete in-memory backend behind the existing interface; signs under a DerivationCoordinate slot, rejects revoked slots, enforces validity windows, zeroises on dispose()
  2. RootIdentity / ServerIdentity and createRoot / createServer / rollServer / revokeServer — typed wrappers around the keychain pair and the hierarchy operations that were modelled by upstream nx/libs/keys/src/lib/keys-common.ts
  3. Vault (three-regime) — replaces the transitional legacy-vault from slice 2 with the spec-defined three-regime serialisation: public bundle (parent-signed, plaintext), private-key blob (password-AEAD, rotatable via changePassword without re-derivation), vault payload (auth-box-sealed under keypair, parent-signed under DOMAIN_VAULT_V1)
  4. Packer / Unpacker — schema-driven encrypt-and-sign envelope over @suaveplan/bitpacker; issuedAt + nonce for replay-window protection
  5. ChunkedPacker / ChunkedUnpacker — per-chunk-signed P2P fragmentation; tampered chunks fail at reassembly
  6. RevocationList — root-signed CRL; append-only; verify-against-anchor
  7. AuditLog — append-only Merkle log; root-signed root; tamper-detection on past entries
  8. wire-format/ — eight schemas committed with golden-bytes KAT fixtures: DERIVATION_COORDINATE_SCHEMA, KEY_SLOT_PRIVATE_SCHEMA, KEY_SLOT_PUBLIC_SCHEMA, VAULT_PAYLOAD_SCHEMA, PUBLIC_BUNDLE_SCHEMA, CHAIN_BUNDLE_SCHEMA, CRL_ENTRY_SCHEMA, AUDIT_ENTRY_SCHEMA

Property-based round-trip tests using fast-check accompany every schema.

What changes

Added — @suaveplan/crypto/src/

  • authority/in-memory-authority/ — concrete InMemoryAuthority implementing the existing Authority interface
  • identity/root-identity/, identity/server-identity/, identity/operations/ — createRoot, createServer, rollServer, revokeServer
  • vault/vault.ts (three-regime), vault/vault.types.ts, vault/changePassword.ts, vault/rotateApplicationData.ts — replaces legacy-vault/
  • packer/packer.ts (encrypt-and-sign envelope), packer/replay-window.ts
  • chunked-packer/chunked-packer.ts, chunked-packer/reassembly.ts
  • revocation/revocation-list.ts
  • audit-log/audit-log.ts, audit-log/merkle.ts
  • wire-format/{derivation-coordinate,key-slot-private,key-slot-public,vault-payload,public-bundle,chain-bundle,crl-entry,audit-entry}-schema.ts (eight schemas)
  • test-fixtures/wire-format/*.bin — eight golden-bytes KAT fixtures
  • Co-located .md for every implementation file (≥ 200 words, basic + advanced examples, full API reference)

Modified

  • vault/legacy-vault/ — deleted in this slice once the three-regime Vault ships and any internal callers migrate
  • crypto/src/index.ts — re-exports the new modules
  • crypto/src/errors/codes/codes.ts — add codes for PACKER.*, CHUNK.*, CRL.*, AUDIT.*, VAULT.PAYLOAD_*, AUTHORITY.SLOT_REVOKED, etc.

Tests added

  • Per-feature *.test.ts for happy-path + every documented failure mode
  • Per-feature *.spec-conformance.test.ts for type-level + observability + lifecycle scenarios
  • tests/wire-format-kat.test.ts golden-bytes assertion against every committed fixture
  • tests/property-roundtrips.test.ts — fast-check property tests for every pack/unpack pair
  • Tampered-vault, tampered-chunk, expired-key, revoked-key, replay-rejection scenarios each pinned by a named it(...)

Out of scope

  • @suaveplan/crypto-cli package — slice 4
  • @suaveplan/slsa migration to Authority — slice 4
  • Import-allowlist conformance gate — slice 4
  • HSM / threshold / YubiKey backends for Authority (the interface allows them; concrete drivers are dedicated future changes)

Source mapping

The modules in this slice fold the contents of restore-crypto-keychain-packer/specs/crypto/spec.md requirements 7 (Vault), 8 (Packer), 9 (ChunkedPacker), 11 (RevocationList), 12 (AuditLog), 13 (Authority concrete backend), 14 (Hierarchical identity), 18 (Wire-format KAT vectors), and 19 (Property-based round-trip).

Requirement Umbrella spec source Notes
InMemoryAuthority umbrella ### Requirement: Authority — signing abstraction over hierarchical identity Concrete backend behind existing interface
RootIdentity / ServerIdentity / hierarchy ops umbrella ### Requirement: Hierarchical identity — Root and Server Verbatim
Three-regime Vault umbrella ### Requirement: Vault — three-regime serialisation with BIP39 restore and arbitrary application data Replaces transitional legacy-vault
Packer / Unpacker umbrella ### Requirement: Packer — encrypt-and-sign envelope Verbatim
ChunkedPacker / ChunkedUnpacker umbrella ### Requirement: ChunkedPacker — per-chunk-signed P2P fragmentation Verbatim
RevocationList umbrella ### Requirement: RevocationList — root-signed CRL Verbatim
AuditLog umbrella ### Requirement: AuditLog — append-only Merkle log Verbatim
Wire-format KAT vectors umbrella ### Requirement: Wire-format KAT vectors Eight golden-bytes fixtures
Property-based round-trip umbrella ### Requirement: Property-based round-trip coverage fast-check

Verification approach

  • 100/100/100/100 coverage on every new module
  • Per-feature it(...) names match the **Verified by:** lines in the spec deltas
  • KAT fixtures committed and asserted byte-for-byte on every CI run
  • Property tests run 100+ iterations per pack/unpack pair
  • bun run check clean across monorepo
  • bunx turbo lint typecheck test:coverage build --filter=@suaveplan/crypto green

Migration impact

  • The transitional vault/legacy-vault/ is deleted in this slice. Any internal code (no out-of-package consumer today) that imported from @suaveplan/crypto/vault/legacy-vault migrates to the three-regime Vault at @suaveplan/crypto/vault.
  • No public API breaks for anything else.