# Capability Spec Delta: bitpacker-crypto (bitpacker-crypto-port, Option A) **Package**: `@suaveplan/bitpacker-crypto` **Status**: PROPOSED — gated on Option A acceptance in `proposal.md` > Every requirement below carries a `**Verified by:**` line at authoring time. Option A is a deliberate scope-down: the only behavior contract this change adds is "the upstream provider abstraction is intentionally not part of `@suaveplan/bitpacker-crypto`." The tests that pin this contract live next to the package source. ## ADDED Requirements ### Requirement: Decision record exists in-tree The package SHALL ship a `SUPERSEDED.md` file at the package root documenting (i) every upstream symbol intentionally not ported, (ii) the upstream file and line range it came from, (iii) the genesis replacement (a concrete `@suaveplan/*` package and export), and (iv) the rationale. The file SHALL be at least 200 words and SHALL include one runnable example showing how a caller wanting "encrypt then pack" achieves it via `@suaveplan/packer` + `@suaveplan/crypto`. #### Scenario: SUPERSEDED.md is present and well-formed - **WHEN** the file `packages/bitpacker/bitpacker-crypto/SUPERSEDED.md` is read - **THEN** it exists, is at least 200 words excluding code blocks, contains a section per upstream symbol listed in `proposal.md` source mapping, and contains at least one fenced code block whose first line begins with `import` from `@suaveplan/` #### Scenario: every parity-table row has a SUPERSEDED.md section - **WHEN** the parity-table rows in `bitpacker-modular-restructure/proposal.md` flagged "⛔ intentionally superseded; see `bitpacker-crypto-port`" are enumerated (5 rows) - **THEN** each row has a corresponding section header in `SUPERSEDED.md` and the section names the same upstream file the parity-table row referenced **Verified by:** `packages/bitpacker/bitpacker-crypto/SUPERSEDED.test.ts::"SUPERSEDED.md exists and is well-formed"` AND `packages/bitpacker/bitpacker-crypto/SUPERSEDED.test.ts::"every parity-table row maps to a SUPERSEDED.md section"` --- ### Requirement: Upstream provider symbols are NOT exported The package SHALL NOT export any of the following symbols by these exact names: `BaseCryptoProvider`, `CryptoRegistry`, `LibsodiumCryptoProvider`, `EllipticCryptoProvider`, `NoOpCryptoProvider`, `generateNonce`, `concatBytes`, `validateKeyLength`, `constantTimeEqual`, `secureWipe`, `createCryptoRegistry`, `getGlobalRegistry`, `createXChaCha20Provider`, `createAesGcmProvider`, `createSecp256k1Provider`, `createEd25519Provider`, `createP256Provider`, `createTestProvider`, `createSlowProvider`, `createUnreliableProvider`. Any future re-introduction of these names SHALL constitute a deliberate spec change reverting this decision. #### Scenario: rejected symbol cannot be imported - **WHEN** a TypeScript consumer writes `import { BaseCryptoProvider } from "@suaveplan/bitpacker-crypto";` - **THEN** the import fails to resolve at typecheck time #### Scenario: every rejected symbol pinned by an `it` - **WHEN** `SUPERSEDED.test.ts` runs - **THEN** there is exactly one `it(...)` per name in the list above and each asserts the runtime export is `undefined` #### Scenario: parity-table rows show ⛔ status - **WHEN** the parity table in `bitpacker-modular-restructure/proposal.md` is read after this change archives - **THEN** the five rows for `Crypto provider`, `Crypto registry`, `Crypto adapter — noop`, `Crypto adapter — libsodium`, `Crypto adapter — elliptic` show "⛔ intentionally superseded; see `bitpacker-crypto-port`" with no remaining 🚫 marker **Verified by:** `packages/bitpacker/bitpacker-crypto/SUPERSEDED.test.ts::"BaseCryptoProvider is not a runtime export"` AND `packages/bitpacker/bitpacker-crypto/SUPERSEDED.test.ts::"CryptoRegistry is not a runtime export"` AND `packages/bitpacker/bitpacker-crypto/SUPERSEDED.test.ts::"LibsodiumCryptoProvider is not a runtime export"` AND `packages/bitpacker/bitpacker-crypto/SUPERSEDED.test.ts::"EllipticCryptoProvider is not a runtime export"` AND `packages/bitpacker/bitpacker-crypto/SUPERSEDED.test.ts::"NoOpCryptoProvider is not a runtime export"` AND `packages/bitpacker/bitpacker-crypto/SUPERSEDED.test.ts::"generateNonce is not a runtime export"` AND `packages/bitpacker/bitpacker-crypto/SUPERSEDED.test.ts::"concatBytes is not a runtime export"` AND `packages/bitpacker/bitpacker-crypto/SUPERSEDED.test.ts::"validateKeyLength is not a runtime export"` AND `packages/bitpacker/bitpacker-crypto/SUPERSEDED.test.ts::"constantTimeEqual is not a runtime export"` AND `packages/bitpacker/bitpacker-crypto/SUPERSEDED.test.ts::"secureWipe is not a runtime export"` --- ### Requirement: README routes future callers to the genesis crypto family The package's `README.md` SHALL contain a "Crypto provider needs?" section that names the genesis replacement packages (`@suaveplan/crypto`, `@suaveplan/crypto-sodium`, `@suaveplan/crypto-browser`, `@suaveplan/crypto-vault`, `@suaveplan/packer`) and links to each. The section SHALL be ≤120 words and SHALL NOT document the rejected upstream API. #### Scenario: README routing section is present - **WHEN** `packages/bitpacker/bitpacker-crypto/README.md` is read - **THEN** it contains a level-2 heading `## Crypto provider needs?` and the body names every package listed above with a markdown link #### Scenario: README does not document the rejected API - **WHEN** the README is grepped for `BaseCryptoProvider`, `CryptoRegistry`, or `LibsodiumCryptoProvider` - **THEN** there are zero matches outside of the link to `SUPERSEDED.md` **Verified by:** `packages/bitpacker/bitpacker-crypto/SUPERSEDED.test.ts::"README has Crypto provider needs section linking the replacement packages"` AND `packages/bitpacker/bitpacker-crypto/SUPERSEDED.test.ts::"README does not document the rejected upstream API"` ## REMOVED Requirements ### Requirement: Provider abstraction port from upstream `bitpacker/src/crypto/` **Reason:** Upstream's `BaseCryptoProvider` / `CryptoRegistry` / three adapters (`libsodium`, `elliptic`, `noop`) are a self-referential abstraction layer over `@suaveplan/crypto`. No upstream consumer outside the bitpacker package itself imports any of them (verified 2026-05-02 by grep across `/mnt/s/web/suaveplan/packages`). Genesis already ships every underlying primitive in five focused packages (`@suaveplan/crypto`, `crypto-sodium`, `crypto-browser`, `crypto-vault`, `crypto-keys`) plus a higher-level chunked AEAD in `@suaveplan/packer`. Re-adding the abstraction would duplicate that work, conflict with the genesis structured-error / OTel conventions, and contradict the "no duplicate libraries" directive in CLAUDE.md. **Migration:** Future bitpacker callers should reach for the genesis crypto family directly. See `SUPERSEDED.md` for the per-symbol replacement table and an "encrypt-then-pack" example using `@suaveplan/packer` + `@suaveplan/crypto`.