6.3 KiB
6.3 KiB
Tasks — restore-crypto-opinionated-layer
1. Authority concrete backend
- 1.1 Implement
InMemoryAuthorityagainst the existingAuthorityinterface (sign underDerivationCoordinateslot, validity-window check, revoked-slot rejection) - 1.2
dispose()zeroises every slot's secret material - 1.3 Tests: sign-success, sign-with-revoked-slot-fails, sign-with-out-of-window-key-fails, dispose-zeroises, AbortSignal cancellation
- 1.4 Co-located
.md
2. Identity hierarchy
- 2.1
RootIdentityandServerIdentitytyped wrappers - 2.2
createRoot(rng, clock, options)— generates root keychain + signs its own public bundle - 2.3
createServer(rootAuthority, options)— generates server keychain, signed under root - 2.4
rollServer(rootAuthority, serverIdentity, options)— version-bump rotation; emits CRL entry for prior version; appends audit-log entry - 2.5
revokeServer(rootAuthority, serverRef, reason)— appends CRL + audit entries; no re-issue - 2.6 Tests: createRoot self-verifies; createServer parent-signed; rollServer increments version + emits CRL; revokeServer appends without re-issue
- 2.7 Co-located
.mdper file
3. Three-regime Vault
- 3.1
Vaultclass with three regimes: public bundle (parent-signed plaintext), private-key blob (password-AEAD), vault payload (auth-box-sealed under keypair, parent-signed underDOMAIN_VAULT_V1) - 3.2
pack/unpackround-trip - 3.3
changePasswordre-encrypts the private-key blob without re-deriving the keychain - 3.4
rotateApplicationDatare-seals payload only (keys untouched) - 3.5
lock()zeroises secrets - 3.6 BIP39 restore re-derives identical keychain
- 3.7 Argon2id parameter floor enforced
- 3.8 Tests: round-trip, tamper-detect, wrong-password-distinct-from-tamper, BIP39-restore, lock-zeroises, Argon2id-floor, changePassword-without-re-derive, payload-data-round-trip, rotateApplicationData-keys-untouched
- 3.9 Delete
vault/legacy-vault/after the newVaultships and any internal callers migrate - 3.10 Co-located
.md(≥ 200 words) covering the three regimes
4. Packer / Unpacker
- 4.1
Packer.pack(value, schema, recipientAuthority, senderAuthority, domainTag)— encrypt-then-sign envelope - 4.2
Unpacker.unpack(envelope, recipientAuthority, senderPublicBundle, domainTag, options)— verify-then-decrypt - 4.3 Replay-window check via
issuedAt+nonce; rejects envelopes outside window or with seen nonce - 4.4 Tests: round-trip, recipient-verifies-sender, tamper-detect, replay-rejection, mismatched-domain-tag-fails
- 4.5 Co-located
.md
5. ChunkedPacker / ChunkedUnpacker
- 5.1
ChunkedPacker.packFileToChunks(stream, recipient, sender, options)— per-chunk-signed fragmentation - 5.2
ChunkedUnpacker.reassembleFile(chunks, options)— assemble; rejects on tampered chunk - 5.3 Tests: 1-chunk, N-chunk, tampered-chunk-rejected, missing-chunk-rejected, out-of-order-chunks-handled
- 5.4 Co-located
.md
6. RevocationList
- 6.1
RevocationListwithappend(entry, rootAuthority),verify(rootPublicBundle),check(serverRef) - 6.2 Append-only invariant (mutating past entries invalidates the list)
- 6.3 Tests: append-then-verify, mutate-past-entry-fails, check-revoked-server-true, check-non-revoked-server-false
- 6.4 Co-located
.md
7. AuditLog
- 7.1
AuditLogappend-only Merkle log; root signed byrootAuthority - 7.2
append(event),verify(rootPublicBundle),inclusion(eventId)proof - 7.3 Tampering with any past entry invalidates the root signature
- 7.4 Tests: append-roots-correctly, tamper-past-entry-fails, inclusion-proof-verifies
- 7.5 Co-located
.md
8. Wire-format schemas + KAT fixtures
- 8.1 Define
DERIVATION_COORDINATE_SCHEMA - 8.2 Define
KEY_SLOT_PRIVATE_SCHEMA,KEY_SLOT_PUBLIC_SCHEMA - 8.3 Define
VAULT_PAYLOAD_SCHEMA - 8.4 Define
PUBLIC_BUNDLE_SCHEMA(magic("SVPB") ‖ formatVersion ‖ issuerRef ‖ issuedAt ‖ nonce ‖ subjectRef ‖ slots[] ‖ parentSignature[64]) - 8.5 Define
CHAIN_BUNDLE_SCHEMA(magic("SVCB") ‖ formatVersion ‖ linkCount ‖ links[]) - 8.6 Define
CRL_ENTRY_SCHEMA,AUDIT_ENTRY_SCHEMA - 8.7 Commit eight golden-bytes fixtures under
test-fixtures/wire-format/ - 8.8
tests/wire-format-kat.test.tsbyte-for-byte assertion - 8.9 Co-located
.mdper schema
9. Property-based round-trip
- 9.1
tests/property-roundtrips.test.tsusingfast-check - 9.2 Cover every pack/unpack pair: keychain, vault, public bundle, chain bundle, packer envelope, chunk, CRL entry, audit entry
10. Error codes
- 10.1 Add
PACKER.ENCRYPT_FAILED,PACKER.SIGN_FAILED,PACKER.REPLAY_REJECTED,PACKER.DOMAIN_TAG_MISMATCH - 10.2 Add
CHUNK.TAMPERED,CHUNK.MISSING,CHUNK.OUT_OF_ORDER - 10.3 Add
CRL.NOT_VERIFIED,CRL.MUTATED - 10.4 Add
AUDIT.ROOT_MISMATCH,AUDIT.INCLUSION_PROOF_FAILED - 10.5 Add
VAULT.PAYLOAD_DECRYPT_FAILED,VAULT.PAYLOAD_VERIFY_FAILED - 10.6 Add
AUTHORITY.SLOT_REVOKED,AUTHORITY.SLOT_OUT_OF_WINDOW - 10.7 Each code thrown by ≥ 1 production code path (asserted by
tests/codes-thrown.test.ts)
11. Verification gates
- 11.1
bun run check— Biome 0/0/0 - 11.2
bunx turbo lint typecheck test --filter=@suaveplan/cryptogreen - 11.3
bunx turbo test:coverage --filter=@suaveplan/crypto100/100/100/100 - 11.4
bunx turbo test --filter=...@suaveplan/crypto(dependent sweep) green - 11.5 OpenSpec conformance script clean
12. Pre-archive 7-row checklist (AGENTS.md Section 13)
- 12.1 Generics threaded;
expectTypeOfassertions on every literal-type claim - 12.2 Zod schemas wired at every declared boundary
- 12.3 Every error code thrown by at least one production path
- 12.4 Strict-mode behaviours tested both on and off
- 12.5 OTel instruments emitted from production paths and asserted with a real
MeterProvider - 12.6 Lifecycle dedup tested where claimed (replay-window nonces, CRL append-only)
- 12.7 No retroactive tick
13. Archive
- 13.1 Fold spec deltas into
openspec/specs/crypto/spec.md - 13.2 Move
openspec/changes/restore-crypto-opinionated-layer/→openspec/archive/<yyyy-mm-dd>-restore-crypto-opinionated-layer/