# OpenSpec Change: crypto-spec-conformance - **Change ID**: crypto-spec-conformance - **Package**: `@suaveplan/crypto` - **Status**: PROPOSED - **Date**: 2026-04-26 ## Summary Realign the folded `openspec/specs/crypto/spec.md` with the actual surface of `@suaveplan/crypto` (the multi-algorithm façade), add a cross-cutting `src/crypto.spec-conformance.test.ts`, and annotate every requirement with a `**Verified by:**` line so `bun scripts/openspec-conformance.ts @suaveplan/crypto` exits 0. Two prior archived change folders (`2026-04-19-crypto-primitive-replaceability`, `2026-04-19-enterprise-crypto`) carry `retroactively ticked` markers that the conformance script downgrades to `info` once a `*-spec-conformance` rectification exists. No public-API changes. ## Current state `@suaveplan/crypto` is the engine-pluggable façade composing the per-primitive subpackages (`crypto-utils`, `crypto-hash`, `crypto-curve`, `crypto-cipher`). Its surface is AEAD (3 algorithms), Ed25519 / ECDSA-P256 sign-verify, X25519 agreement, sealed-box, auth-box, `constantTimeEqual`, `zeroize`, `randomBytes` (single CSPRNG callsite), and a `CRYPTO_CODES` registry. Per-feature unit tests cover the happy paths, AAD authentication, tampered-ciphertext rejection, key/nonce length validation, fast-check round-trip properties, and engine substitution. The conformance gaps are: - **Spec drift.** The folded `openspec/specs/crypto/spec.md` was the original `enterprise-crypto` proposal — it specs `sha256`, `sha384`, `sha512`, `hmac`, `hkdf`, `pbkdf2`, `argon2id` as exports of this façade. After the per-primitive split those primitives moved to `@suaveplan/crypto-hash`. The `Purpose` section is the literal placeholder `TBD - created by archiving change enterprise-crypto. Update Purpose after archive.` All 13 requirements lack `**Verified by:**` lines. - **Implicit cross-cutting invariants are unpinned.** Engine pluggability across all five operation namespaces, the AEAD nonce-is-caller-supplied invariant (no internal randomness in `src/aead/`), `verify` returning a boolean (never throwing) on bad signatures, the single-`crypto.getRandomValues`-callsite property, and the structured-error-no-leak rule for AEAD failures are all stated by the spec but not directly asserted by any test. - **Retroactive ticking debt.** Archived change folders `2026-04-19-crypto-primitive-replaceability/tasks.md` and `2026-04-19-enterprise-crypto/tasks.md` contain `retroactively ticked`, which the conformance script flags as `error` until a `*-spec-conformance` rectification folder exists. ## What changes 1. **Rewrite `openspec/specs/crypto/spec.md`** to reflect the actual façade surface: - Fill the `## Purpose` section. - Replace the drifted hash / KDF / argon2id requirements (which now live in `@suaveplan/crypto-hash`'s spec) with thirteen requirements that match the façade: engine pluggability, AEAD round-trip across three algorithms, AEAD nonce-caller-supplied invariant, AEAD authentication-failure leak rule, Ed25519 / ECDSA-P256 sign-verify with `verify` boolean contract, X25519 stability, sealed-box authenticity, auth-box sender authentication, constant-time-equal, zeroize, single CSPRNG callsite, structured-errors-with-stable-registry, and 100% coverage gate. - Add a `**Verified by:**` line to every `### Requirement:` block pointing at concrete `*.test.ts::"name"` test cases. 2. **Add `src/crypto.spec-conformance.test.ts`** covering: - Default-engine wiring across all five namespaces. - Custom-engine substitution suppresses the default for sign and agree. - AEAD façade source contains zero byte-source consumption (`grep` over `src/aead/`). - AEAD decryption-failure error context is restricted to `{ algorithm, ciphertextLength }`. - Ed25519 / ECDSA-P256 `verify` returns `false` (never throws) on a wrong message. - X25519 agreement is byte-stable across repeated calls. - `constantTimeEqual` source contains no `return` / `break` inside its compare loop — only an XOR accumulator. - `zeroize` mutates in place (same `Uint8Array` reference). - Exactly one `crypto.getRandomValues(...)` callsite in `src/`, located in `src/primitives/random-bytes.ts`. - Every `CRYPTO_CODES` entry is referenced from at least one non-test source file. - `CRYPTO_CODES` is frozen. - Engine type exports compile. 3. **Rectify retroactive-ticking debt.** Creating this `crypto-spec-conformance` change folder downgrades the prior `retroactively ticked` markers in archived task lists from `error` to `info` per the conformance-script policy. ## Impact - Public API unchanged. - One new test file (~330 lines, under the 500-line budget). - `openspec/specs/crypto/spec.md` rewritten to reflect the actual façade surface; the prior text described primitives that have since moved to `@suaveplan/crypto-hash`. - Coverage stays at 100/100/100/100; the new tests exercise existing production code paths plus structural source-text invariants. - No new runtime dependencies.