Files
suaveplan/openspec/archive/2026-05-03-extract-shared-crypto-interfaces/tasks.md
2026-05-27 23:29:53 +01:00

8.1 KiB

Tasks — Extract shared crypto interfaces

Every checkbox MUST reflect work actually done in this change. No retroactive ticking. Implementation is gated on user sign-off of the API shape (§1.5).

1. Spec authoring & sign-off

  • 1.1 Author proposal.md with audit-revised consumer list and parity checklist
  • 1.2 Author this tasks.md
  • 1.3 Author specs/types/spec.md with one Requirement per added type
  • 1.4 Author specs/bitpacker-crypto/spec.md with the MODIFIED requirements (DI options)
  • 1.5 GATE — user sign-off on the API shape before any further implementation work
  • 1.6 openspec change validate extract-shared-crypto-interfaces --strict exits clean

2. @suaveplan/types — add Authority/DomainTag/AeadOps interfaces

  • 2.1 Author packages/core/types/src/domain-tag.ts — branded DomainTag type + sibling domain-tag.md (≥200 words, basic + advanced examples)
  • 2.2 Author packages/core/types/src/authority.ts — Authority, KeySlotPublic<T>, KeySlotPrivate<T>, SlotId, AuthorityVerifier + sibling authority.md
  • 2.3 Author packages/core/types/src/aead-ops.ts — AeadAlgorithm, AeadOpsOptions, AeadOps + sibling aead-ops.md
  • 2.4 Wire all three into packages/core/types/src/index.ts (alphabetical insertion)
  • 2.5 Run bunx turbo lint typecheck test --filter=@suaveplan/types — verify green and zero-runtime byte-budget guard still passes (no .js file > 200 bytes)

3. @suaveplan/crypto — re-export types from @suaveplan/types

  • 3.1 Edit packages/crypto/crypto/src/domain-tags/domain-tags.ts: drop the local DomainTag declaration; re-export from @suaveplan/types. Keep all DOMAIN_* runtime constants and the encodeDomainTag / buildSigningInput / isDomainTag helpers.
  • 3.2 Edit packages/crypto/crypto/src/authority/authority.ts: drop the local Authority, KeySlotPublic, SlotId declarations; re-export from @suaveplan/types. Keep InMemoryAuthority, inMemoryAuthority, and verifyAuthoritySignature runtime helpers. Cast slotId to PurposeTag at the indexing site (one-line cast — type contract unchanged at the public surface).
  • 3.3 packages/crypto/crypto/src/authority/index.ts re-exports the canonical types from @suaveplan/types so @suaveplan/crypto/authority subpath continues to expose Authority / KeySlotPublic / SlotId.
  • 3.4 Run bunx turbo lint typecheck test --filter=@suaveplan/crypto — 265/265 tests stay green
  • 3.5 Verify no API regression: grep -rE "import.*Authority.*from.*@suaveplan/crypto" /home/ubuntu/web/genesis/packages/ finds the same call-sites compiling unchanged

4. @suaveplan/bitpacker-crypto — drop crypto runtime dep, accept verifier+aead via DI

  • 4.1 Edit packages/bitpacker/bitpacker-crypto/package.json: move @suaveplan/crypto from dependencies to devDependencies. Update package description.
  • 4.2 Edit vite.config.ts externals: drop "@suaveplan/crypto" and /^@suaveplan\/crypto\// entries
  • 4.3 Refactor src/signed/signed-bitschema.ts:
    • Import Authority, AuthorityVerifier, DomainTag, KeySlotPublic, SlotId from @suaveplan/types
    • Add required verifier: AuthorityVerifier to SignedBitSchemaOptions
    • Add verifier to Zod options schema
    • Replace verifyAuthoritySignature(...) calls with verifier(...)
  • 4.4 Refactor src/multisigned/multisigned-bitschema.ts — same shape
  • 4.5 Refactor src/hashchain/hashchain-schema.ts — same shape
  • 4.6 Refactor src/encrypted/encrypted-bitschema.ts:
    • Import AeadAlgorithm, AeadOps, Rng from @suaveplan/types
    • Move AEAD_KEY_LENGTH, AEAD_NONCE_LENGTH, AEAD_XCHACHA_NONCE_LENGTH constant declarations into this file (drop the @suaveplan/crypto import)
    • Add required aead: AeadOps to EncryptedBitSchemaOptions
    • Add aead to Zod options schema
    • Replace aeadEncrypt(...) / aeadDecrypt(...) with aead.encrypt(...) / aead.decrypt(...)
  • 4.7 Author tests/helpers/crypto-deps.ts: exports cryptoVerifier: AuthorityVerifier (= verifyAuthoritySignature) and cryptoAead: AeadOps (= { encrypt: aeadEncrypt, decrypt: aeadDecrypt }). Single test-side import point for @suaveplan/crypto runtime functions.
  • 4.8 Update tests/helpers/fake-authority.ts: types from @suaveplan/types; runtime helpers (buildSigningInput, ed25519) continue from @suaveplan/crypto
  • 4.9 Update every *.test.ts and *.spec-conformance.test.ts that constructs a primitive: import cryptoVerifier / cryptoAead from tests/helpers/crypto-deps.ts and pass into the options bundle
    • src/signed/signed-bitschema.test.ts (16 sites)
    • src/signed/signed-bitschema.spec-conformance.test.ts (4 sites)
    • src/multisigned/multisigned-bitschema.test.ts (11 sites)
    • src/hashchain/hashchain-schema.test.ts (13 sites)
    • src/encrypted/encrypted-bitschema.test.ts (17 sites)
    • src/encrypted/encrypted-bitschema.spec-conformance.test.ts (5 sites)
    • src/composition.test.ts (6 sites)
    • src/coverage.test.ts (17 sites)
  • 4.10 Update sibling .md docs to reflect new DI options:
    • src/signed/signed-bitschema.md — verifier shown in basic + advanced examples
    • src/multisigned/multisigned-bitschema.md — verifier shown
    • src/hashchain/hashchain-schema.md — verifier shown
    • src/encrypted/encrypted-bitschema.md — aead shown; AEAD constants documented as locally-declared
    • Root README.md quick-start examples updated

5. Verification — 5-gate

  • 5.1 bun run check — Biome 0/0/0 across the monorepo
  • 5.2 bunx turbo lint typecheck test --filter=@suaveplan/types — green; zero-runtime byte-budget guard satisfied
  • 5.3 bunx turbo lint typecheck test --filter=@suaveplan/crypto — 265/265 stays green
  • 5.4 bunx turbo lint typecheck test --filter=@suaveplan/bitpacker-crypto — green
  • 5.5 bunx turbo test:coverage --filter=@suaveplan/bitpacker-crypto — 100/100/100/100
  • 5.6 bunx turbo build --filter=...@suaveplan/bitpacker-crypto — every dependent compiles green
  • 5.7 bun scripts/folder-reorg/generate-manifest.ts — dep graph stays acyclic; manifest regenerates clean
  • 5.8 Grep guard: ! grep -rE 'from "@suaveplan/crypto"|from "@suaveplan/crypto/' packages/bitpacker/bitpacker-crypto/src/ --include="*.ts" | grep -v "\.test\.ts" — zero matches in production source

6. Pre-archive 7-row checklist (AGENTS.md §13)

  • 6.1 Generics threaded — Authority, KeySlotPublic<T>, AuthorityVerifier, AeadOps all stay generic-friendly through the refactor
  • 6.2 Zod schemas wired at every declared boundary — 4 primitive options bundles updated to validate the new verifier/aead field
  • 6.3 Every error code touched in this change is still thrown by ≥1 production code path
  • 6.4 Strict-mode behaviors tested both on and off where applicable (DI rejection on missing verifier covered by Zod boundary)
  • 6.5 OTel spans emitted from production paths; asserted with the existing in-process recording tracer
  • 6.6 Lifecycle dedup tested where claimed
  • 6.7 No retroactive tick — every box reflects work done in this change

7. Archive

  • 7.1 Fold specs/types/spec.md into openspec/specs/types/spec.md
  • 7.2 Fold specs/bitpacker-crypto/spec.md into openspec/specs/bitpacker-crypto/spec.md
  • 7.3 Move openspec/changes/extract-shared-crypto-interfaces/ → openspec/archive/<yyyy-mm-dd>-extract-shared-crypto-interfaces/
  • 7.4 STATUS.md update: refactor landed; cycle eliminated; chain-bundle-adopt-envelope-schema and public-bundle-adopt-envelope-schema follow-ups unblocked
  • 7.5 Update CLAUDE.md package listing for @suaveplan/types (note new shared crypto interfaces) and @suaveplan/bitpacker-crypto (note required DI options)

8. Follow-up changes (queue, not done in this change)

  • 8.1 chain-bundle-adopt-envelope-schema — migrate crypto::ChainBundle to use EnvelopeSchema (now unblocked); wire format byte-identical pinned by snapshot test
  • 8.2 public-bundle-adopt-envelope-schema — migrate crypto::PublicBundle to use EnvelopeSchema + SignedBitSchema (now unblocked)