Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,153 @@
# Tasks — Restore the keychain + packer top-layer; rename `crypto` → `crypto-core`
> Every checkbox MUST reflect work actually done in this change. Do not retroactively tick boxes for work that was already in main when this change opened. Do not tick a box for a test that doesn't exist or doesn't pin the requirement it claims to verify. Retroactive ticking is the failure mode this template guards against.
## 1. Spec authoring
- [ ] 1.1 Read `../suaveplan/enterprise/keys.md`, `server-keys.md`, `crypto.md`, `packer.md`, `packer-browser.md` end-to-end
- [ ] 1.2 Read existing `openspec/specs/crypto/spec.md` (current primitive-layer spec; will be moved under `crypto-core`)
- [ ] 1.3 Read `openspec/AGENTS.md` Sections 13 and 14
- [ ] 1.4 Draft `proposal.md` from `openspec/templates/proposal.md` — DONE in this change folder
- [ ] 1.5 Fill in `## Source mapping` table — every requirement cites a line range OR appears in the "no source line" table with justification — DONE
- [ ] 1.6 Draft spec deltas:
- [ ] 1.6.a `specs/crypto-core/spec.md` — RENAMED + import-allowlist requirement
- [ ] 1.6.b `specs/crypto/spec.md` — full new spec (Keychain, Vault, Packer, ChunkedPacker, Authority, RevocationList, AuditLog, Identity hierarchy, domain tags, KAT vectors)
- [ ] 1.6.c `specs/crypto-cli/spec.md` — eight commands + UX rules + exit codes
- [ ] 1.6.d `specs/crypto-keys/spec.md` — REMOVED with migration pointer
- [ ] 1.6.e `specs/crypto-vault/spec.md` — REMOVED with migration pointer
- [ ] 1.6.f `specs/slsa/spec.md` — MODIFIED: builder identity via `Authority`
- [ ] 1.7 Every requirement in every spec delta carries a `**Verified by:**` line naming concrete `it(...)` titles
## 2. Implementation — `@suaveplan/bitpacker` (`bytes` field)
- [ ] 2.0.1 Extend `FieldType` with `"bytes"` and add `byteLength` to `FieldDef` Zod schema (`packages/primitives/bitpacker/src/types/common.ts`)
- [ ] 2.0.2 Implement bytes encoding in `BitWriter`: pad to byte boundary, write `byteLength` bytes, pad after; matching path in `BitReader`
- [ ] 2.0.3 Expose `BitWriter.byteAlign()` and `BitReader.byteAlign()` as public methods
- [ ] 2.0.4 Update `BitSchema` size computation for variable-length payloads; document fixed-vs-runtime size semantics
- [ ] 2.0.5 Add error codes: `SCHEMA.INVALID_BYTE_LENGTH`, `PACK.BYTES_LENGTH_MISMATCH`, `UNPACK.INSUFFICIENT_BYTES`
- [ ] 2.0.6 KAT-assert that pre-change schemas (uint/int/bool/fixed only) produce byte-identical output (`tests/legacy-schema-kat.test.ts`)
- [ ] 2.0.7 Sibling `.md` for the new field type plus updated `bit-schema.md`
- [ ] 2.0.8 Pre-publish gate green for `@suaveplan/bitpacker`
## 2. Implementation — `@suaveplan/crypto-core` (rename)
- [ ] 2.1 Create `packages/crypto/crypto-core/` and move every file from `packages/crypto/crypto/` (preserve git history via `git mv`)
- [ ] 2.2 Update `package.json` `name` → `@suaveplan/crypto-core`
- [ ] 2.3 Update every `workspace:^` reference in the monorepo from `@suaveplan/crypto` to `@suaveplan/crypto-core` *except* for consumers that should now use the new opinionated `@suaveplan/crypto`
- [ ] 2.4 Update every `import` statement accordingly (codemod: `bun scripts/codemods/rename-crypto-to-core.ts`)
- [ ] 2.5 Update `CLAUDE.md` package list entry for crypto → crypto-core
- [ ] 2.6 Verify primitive surface is byte-identical: `bunx turbo build --filter=@suaveplan/crypto-core` and diff `dist/index.d.ts` against pre-rename snapshot
## 3. Implementation — `@suaveplan/crypto` (new opinionated layer)
- [ ] 3.1 Scaffold `packages/crypto/crypto/` from the package template (`package.json`, `tsconfig.lib.json`, `vite.config.ts`, `vitest.config.ts`, `README.md`, `src/index.ts`)
- [ ] 3.2 Set `package.json` deps: `crypto-core`, `crypto-utils`, `crypto-hash`, `crypto-curve`, `crypto-cipher`, `bitpacker`, `error`, `events`, `types`, `i18n`, `opentelemetry`, `@scure/bip39`, `zod`
- [ ] 3.3 Move `crypto-keys/src/keypair/*` → `crypto/src/keychain/keypair/*`
- [ ] 3.4 Move `crypto-keys/src/keychain/*` → `crypto/src/keychain/*` (memory + serialized adapters)
- [ ] 3.5 Move `crypto-vault/src/mnemonic/*` → `crypto/src/vault/mnemonic/*`
- [ ] 3.6 Move `crypto-vault/src/vault/*` → `crypto/src/vault/*`
- [ ] 3.7 Implement `DerivationCoordinate` (`purpose ASCII[4] ‖ application ASCII[4] ‖ layoutId u8 ‖ <layout fields>`) and `DerivationLayout` registry; ship `DERIVATION_LAYOUT_V1` (u16 + u32 + u8 + u8 = 64 bits exactly)
- [ ] 3.8 Implement open `purpose` registry seeded with the eight defaults (`mast`/`encr`/`sign`/`kx`/`salt`/`hash`/`strm`/`dev`); `registerPurpose(tag)` adds without wire-format break
- [ ] 3.9 Implement 8-slot `Keychain` type using `DerivationCoordinate` per slot, plus `{algorithm, notBefore, notAfter, secretKey?, publicKey?}`
- [ ] 3.10 Implement and commit wire-format schemas (`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`); export each from `src/wire-format/`; commit golden-bytes fixtures under `test-fixtures/wire-format/`
- [ ] 3.11 Implement `packPublicBundle` / `unpackPublicBundle` (parent-signed under `DOMAIN_PUBLIC_KEYCHAIN_V1`; embedded `issuerRef` part of signed bytes)
- [ ] 3.12 Implement `packChainBundle` / `parseChainBundle` / `verifyChain(bundle, trustAnchor, clock, crl)` walker (leaf-first concatenation; per-link validity-window, CRL, issuer-match, signature checks; max 16 links)
- [ ] 3.13 Implement `Authority` interface and in-memory backend (`InMemoryAuthority`)
- [ ] 3.14 Implement `Packer` / `Unpacker` (encrypt-then-sign envelope; domain-tag prefix; replay-window check)
- [ ] 3.15 Implement `ChunkedPacker` / `ChunkedUnpacker` (per-chunk signature; reassembly with tamper detection)
- [ ] 3.16 Implement `Vault` with **three encryption regimes**: (a) public bundle (plaintext, parent-signed); (b) private-key blob (password-AEAD, rotatable via `changePassword` without re-derivation); (c) vault payload (auth-box-sealed under keypair, parent-signed under `DOMAIN_VAULT_V1`, carries `master`/`seedCount`/`keychain`/`data: Uint8Array`); BIP39 + Argon2id; `lock()` zeroises; `rotateApplicationData()` re-seals payload only
- [ ] 3.17 Implement `RevocationList` (root-signed CRL; append-only; verify-against-anchor)
- [ ] 3.18 Implement `AuditLog` (append-only Merkle log; root-signed root; tamper-detection on past entries)
- [ ] 3.19 Implement `RootIdentity`, `ServerIdentity`, `createRoot`, `createServer`, `rollServer`, `revokeServer` (replacing `ChainSigner`)
- [ ] 3.20 Implement domain-separation tag constants as branded `string` types; signature paths require a tag
- [ ] 3.21 Wire `@suaveplan/error` codes (one per failure class — see spec for full list)
- [ ] 3.22 Wire OTel spans + counters + histograms via `@suaveplan/opentelemetry`; redaction-test asserts no key bytes in attributes
- [ ] 3.23 Wire `@suaveplan/events` for pack/unpack/chunk/reassemble/issue/roll/revoke events
- [ ] 3.24 Inject `Clock` and `Rng` (from `@suaveplan/types`) at every entry point; no `Date.now()` / `Math.random()` anywhere in `src/`
- [ ] 3.25 Wire `@suaveplan/i18n` for all user-visible error messages
- [ ] 3.26 Co-located `.md` per implementation file (≥ 200 words, basic + advanced examples)
## 4. Implementation — `@suaveplan/crypto-cli` (new)
- [ ] 4.1 Scaffold `packages/crypto/crypto-cli/` with `package.json` `bin` entry → `dist/keychain.js`
- [ ] 4.2 Deps: `@suaveplan/cli`, `@suaveplan/readline`, `@suaveplan/crypto`, `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/i18n`, `@suaveplan/opentelemetry`
- [ ] 4.3 Implement `keychain root init` — generate root identity, write encrypted vault, emit public bundle
- [ ] 4.4 Implement `keychain server init` — generate server identity under a root, emit signed public bundle, append to audit log
- [ ] 4.5 Implement `keychain server roll` — version-bump rotation, signed by root, append CRL entry for prior version, append audit-log entry
- [ ] 4.6 Implement `keychain server revoke` — append CRL entry, append audit-log entry, do not re-issue
- [ ] 4.7 Implement `keychain inspect` — view a packed public keychain (verifies self-signature)
- [ ] 4.8 Implement `keychain verify` — verify any signed envelope against a trust anchor + CRL
- [ ] 4.9 Implement `keychain export-public` — strip secrets, output portable public bundle
- [ ] 4.10 Implement `keychain restore` — re-derive a vault from BIP39 mnemonic + version
- [ ] 4.11 TTY-only password input via `cli`'s `password` prompt; `--password` flag rejected with a security-pointer error
- [ ] 4.12 Stdin/stdout streamable for every command; `--output json|binary|text`
- [ ] 4.13 Distinct exit codes: 0 success, 2 usage error, 10 bad password, 11 tampered vault, 12 expired key, 13 revoked key, 14 missing trust anchor, 15 audit-log mismatch
- [ ] 4.14 `--idempotency-key` on `server roll` and `server revoke`; local-file ledger
- [ ] 4.15 OTel spans + structured logger output for every command
## 5. Implementation — `@suaveplan/slsa` (modified)
- [ ] 5.1 Replace direct `crypto.ed25519.sign(secretKey, …)` calls with `Authority.sign(DOMAIN_SLSA_BUILDER_V1, …)`
- [ ] 5.2 Builder identity now constructed from a `ServerIdentity` issued under a SLSA-builder root
- [ ] 5.3 Provenance test fixtures regenerated with new construction path; DSSE envelope output unchanged (asserted by round-trip equality test)
- [ ] 5.4 `@suaveplan/crypto` added as workspace dep; `@suaveplan/crypto` (now `crypto-core`) for signing removed
- [ ] 5.5 `@suaveplan/crypto-hash` and `@suaveplan/crypto-utils` retained — hashing + encoding helpers stay open
- [ ] 5.6 New test `tests/no-direct-crypto-core.test.ts` pins import discipline
## 6. Anti-sediment enforcement
- [ ] 6.1 Add `scripts/conformance/crypto-core-allowlist.yml` with two entries: `@suaveplan/crypto`, `@suaveplan/crypto-cli`
- [ ] 6.2 Extend `scripts/openspec-conformance.ts` to fail with `error` severity when any package outside the allowlist imports cryptographic primitives from `crypto-core` / `crypto-hash`-as-MAC / `crypto-curve` / `crypto-cipher` (encoding helpers from `crypto-utils` and pure-hash uses from `crypto-hash` remain open)
- [ ] 6.3 Test `scripts/conformance/crypto-core-allowlist.test.ts` exercises positive (allowed) and negative (forbidden) cases against fixture packages
- [ ] 6.4 Wire-format KAT test at `packages/crypto/crypto/tests/wire-format-kat.test.ts` asserts golden bytes for: vault-v1, public-keychain-v1, packer-envelope-v1, chunk-v1, crl-v1, audit-entry-v1
- [ ] 6.5 Property-based round-trip test at `packages/crypto/crypto/tests/property-roundtrips.test.ts` (fast-check)
## 7. Tests
- [ ] 7.1 Unit tests at `src/<feature>/<feature>.test.ts` covering every scenario in the spec deltas
- [ ] 7.2 Spec-conformance tests at `src/<feature>/<feature>.spec-conformance.test.ts` pinning type-level / observability / strict-mode / lifecycle scenarios
- [ ] 7.3 Integration / contract / property tests where the spec demands them
- [ ] 7.4 Every `it(...)` carries `{ timeout: 5000 }` (or 30000 for genuinely async)
- [ ] 7.5 Tampered-vault, tampered-chunk, expired-key, revoked-key scenarios each pinned by a named `it(...)`
- [ ] 7.6 Replay-rejection test (old envelope, fresh verify) pinned
## 8. Documentation
- [ ] 8.1 Sibling `.md` for every implementation `.ts` (≥200 words, basic + advanced examples, full API reference)
- [ ] 8.2 README at `packages/crypto/crypto/README.md` links every co-located `.md`
- [ ] 8.3 README at `packages/crypto/crypto-cli/README.md` lists every command with examples
- [ ] 8.4 Update `CLAUDE.md` package listing: remove `crypto-keys` + `crypto-vault`, rename `crypto` → `crypto-core`, add `crypto` + `crypto-cli`
- [ ] 8.5 Refresh `MANIFEST.md` via `bun scripts/folder-reorg/generate-manifest.ts`
## 9. Pre-archive verification (the 5-gate triple, per package touched)
For each of `@suaveplan/crypto-core`, `@suaveplan/crypto`, `@suaveplan/crypto-cli`, `@suaveplan/slsa`:
- [ ] 9.1 `bun run check` — Biome 0 errors / 0 warnings / 0 info across the whole monorepo
- [ ] 9.2 `bunx turbo lint typecheck test --filter=@suaveplan/<pkg>` — green
- [ ] 9.3 `bunx turbo test:coverage --filter=@suaveplan/<pkg>` — 100/100/100/100
- [ ] 9.4 `bun scripts/openspec-conformance.ts @suaveplan/<pkg>` — exit 0, no `error` findings
- [ ] 9.5 `bunx turbo build --filter=@suaveplan/<pkg>` — green
## 10. Pre-archive 7-row checklist (AGENTS.md Section 13)
- [ ] 10.1 Generics threaded; `expectTypeOf` assertions on every literal-type claim (slot map, algorithm tag, domain-separation tag)
- [ ] 10.2 Zod schemas wired at every declared boundary (Keychain, Vault, packed envelopes, CRL entries, audit entries, CLI command args)
- [ ] 10.3 Every error code in `error-codes.ts` thrown by at least one production path
- [ ] 10.4 Strict-mode behaviours tested both on and off (algorithm allowlist, validity-window enforcement, replay-window enforcement)
- [ ] 10.5 OTel instruments emitted from production paths and asserted with a real in-memory `MeterProvider`
- [ ] 10.6 Lifecycle dedup tested where claimed (replay-window dedup of nonces; idempotency-key dedup in CLI)
- [ ] 10.7 No retroactive tick — every box above reflects work done in this change
## 11. Archive
- [ ] 11.1 Fold spec deltas into `openspec/specs/crypto-core/spec.md`, `openspec/specs/crypto/spec.md`, `openspec/specs/crypto-cli/spec.md`, `openspec/specs/slsa/spec.md`
- [ ] 11.2 Delete `openspec/specs/crypto-keys/` and `openspec/specs/crypto-vault/` (folded packages)
- [ ] 11.3 Move `openspec/changes/restore-crypto-keychain-packer/` → `openspec/archive/<yyyy-mm-dd>-restore-crypto-keychain-packer/`
- [ ] 11.4 `MANIFEST.md` refreshed and committed
- [ ] 11.5 Root `README.md` updated to reflect new crypto package layout
## Audit Note (2026-05-02)
DEFERRED in the genesis spec-cleanup pass on 2026-05-02. Rationale:
- 101 tasks across multiple packages: rename @suaveplan/crypto → @suaveplan/crypto-core, introduce new @suaveplan/crypto top-layer (Packer/Unpacker/Authority/AuditLog/RevocationList/Keychain/Vault), modify @suaveplan/slsa, modify @suaveplan/bitpacker, and add new @suaveplan/crypto-cli package. Genuinely large architectural change requiring sustained focused work — not safe to bulk-approve under an audit pass. 0/101 done.