# Tasks — restore-crypto-cli-and-allowlist ## 1. `@suaveplan/crypto-cli` scaffold - [ ] 1.1 Create `packages/crypto/crypto-cli/` from package template (`package.json`, `tsconfig.lib.json`, `vite.config.ts`, `vitest.config.ts`, `README.md`, `src/index.ts`) - [ ] 1.2 `package.json` `bin` entry → `dist/keychain.js` - [ ] 1.3 Deps: `@suaveplan/cli`, `@suaveplan/readline`, `@suaveplan/crypto`, `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/i18n`, `@suaveplan/opentelemetry` ## 2. Subcommands - [ ] 2.1 `keychain root init` — generate root identity, write encrypted vault, emit public bundle - [ ] 2.2 `keychain server init` — generate server identity under a root, emit signed public bundle, append audit log - [ ] 2.3 `keychain server roll` — version-bump rotation; appends CRL + audit; `--idempotency-key` - [ ] 2.4 `keychain server revoke` — appends CRL + audit; no re-issue; `--idempotency-key` - [ ] 2.5 `keychain inspect` — view a packed public keychain (verifies self-signature) - [ ] 2.6 `keychain verify` — verify any signed envelope against a trust anchor + CRL - [ ] 2.7 `keychain export-public` — strip secrets, output portable public bundle - [ ] 2.8 `keychain restore` — re-derive a vault from BIP39 mnemonic + version ## 3. Cross-cutting CLI behaviour - [ ] 3.1 TTY-only password input via `cli`'s `password` prompt; `--password` flag rejected - [ ] 3.2 Stdin/stdout streamable; `--output json|binary|text` - [ ] 3.3 Distinct exit codes: 0/2/10/11/12/13/14/15 - [ ] 3.4 `--idempotency-key` on `server roll` and `server revoke`; local-file ledger - [ ] 3.5 OTel spans + structured logger output for every command - [ ] 3.6 Co-located `.md` per command (≥ 200 words) ## 4. CLI tests - [ ] 4.1 Per-command happy-path test - [ ] 4.2 Per-command failure-mode tests (bad password, tampered vault, expired key, revoked key, missing trust anchor) - [ ] 4.3 `tests/exit-codes.test.ts` — every documented exit code reachable - [ ] 4.4 `tests/no-password-flag.test.ts` — `--password` rejected with security pointer - [ ] 4.5 `tests/tty-mock.test.ts` — TTY prompt UX without a real TTY (driven via `cli`'s `InputReader`) - [ ] 4.6 `tests/round-trip-end-to-end.test.ts` — `root init` → `inspect` → `verify` → `export-public` byte-equal ## 5. `@suaveplan/slsa` migration - [ ] 5.1 Snapshot pre-migration DSSE fixtures (round-trip equality target) - [ ] 5.2 Replace direct `crypto.ed25519.sign(secretKey, …)` with `Authority.sign(DOMAIN_SLSA_BUILDER_V1, …)` - [ ] 5.3 Builder identity constructed from a `ServerIdentity` issued under a SLSA-builder root - [ ] 5.4 `package.json`: add `@suaveplan/crypto`; remove `@suaveplan/crypto` (now `crypto-core`) for signing; retain `crypto-hash` + `crypto-utils` - [ ] 5.5 New test `tests/no-direct-crypto-core.test.ts` — pins import discipline (no signing-related imports of `@suaveplan/crypto-core` etc.) - [ ] 5.6 Round-trip equality test against pre-migration DSSE fixtures ## 6. Import-allowlist conformance gate - [ ] 6.1 Create `scripts/conformance/crypto-core-allowlist.yml` with two entries: `@suaveplan/crypto`, `@suaveplan/crypto-cli` - [ ] 6.2 Extend `scripts/openspec-conformance.ts` to scan every workspace package's `src/` for forbidden primitive imports; fail with `error` severity for non-allowlisted packages - [ ] 6.3 Test `scripts/conformance/crypto-core-allowlist.test.ts` — positive (allowed) + negative (forbidden) fixture packages - [ ] 6.4 Audit the 5 current consumers (`crypto-sodium`, `crypto-browser`, `slsa`, `bitpacker-crypto`, `drive-plugin-chunks`, `packer`): for each, decide migrate or allowlist with rationale; document the decision in `scripts/conformance/crypto-core-allowlist.yml` comments ## 7. Verification gates (per package touched) For each of `@suaveplan/crypto-cli`, `@suaveplan/slsa`: - [ ] 7.1 `bun run check` — Biome 0/0/0 - [ ] 7.2 `bunx turbo lint typecheck test --filter=@suaveplan/` green - [ ] 7.3 `bunx turbo test:coverage --filter=@suaveplan/` 100/100/100/100 - [ ] 7.4 `bun scripts/openspec-conformance.ts @suaveplan/` exit 0, no `error` findings - [ ] 7.5 `bunx turbo build --filter=@suaveplan/` green ## 8. Pre-archive 7-row checklist (AGENTS.md Section 13) - [ ] 8.1 Generics threaded; `expectTypeOf` assertions on every literal-type claim - [ ] 8.2 Zod schemas wired at every CLI command boundary - [ ] 8.3 Every error code thrown by ≥ 1 production path - [ ] 8.4 Strict-mode behaviours tested both on and off (allowlist gate strict mode) - [ ] 8.5 OTel instruments emitted from production paths and asserted with a real `MeterProvider` - [ ] 8.6 Lifecycle dedup tested (`--idempotency-key` ledger) - [ ] 8.7 No retroactive tick ## 9. Manifest + docs - [ ] 9.1 `CLAUDE.md`: add `crypto-cli` package entry - [ ] 9.2 `bun scripts/folder-reorg/generate-manifest.ts` to refresh `MANIFEST.md` - [ ] 9.3 Root `README.md`: brief mention of the `keychain` CLI ## 10. Archive - [ ] 10.1 Fold spec deltas into `openspec/specs/crypto-cli/spec.md`, `openspec/specs/slsa/spec.md`, `openspec/specs/crypto-core/spec.md` (allowlist requirement) - [ ] 10.2 Move the umbrella `openspec/changes/restore-crypto-keychain-packer/` → `openspec/archive/-restore-crypto-keychain-packer/` (umbrella is now fully resolved by the four child slices) - [ ] 10.3 Move `openspec/changes/restore-crypto-cli-and-allowlist/` → `openspec/archive/-restore-crypto-cli-and-allowlist/`