7.1 KiB
Capability Spec Delta: bitpacker-crypto (extract-shared-crypto-interfaces)
Package: @suaveplan/bitpacker-crypto
Status: PROPOSED — gated on user sign-off of the API shape
Modifies the four DI-using primitives shipped by the archived
bitpacker-crypto-rewrite(2026-05-02) to acceptverifierandaeadvia dependency injection. No wire-format change.
MODIFIED Requirements
Requirement: SignedBitSchema integrates with Authority + DomainTag (verifier injected)
The defineSignedBitSchema<T>(bodyCodec, options) function SHALL
accept a required verifier: AuthorityVerifier field on its options
bundle. The primitive SHALL call verifier(domain, parentPublicSlot, body, signature) instead of importing verifyAuthoritySignature
directly. All other behavior (verify-then-decode order, unpackSelf
trust-anchor flow, cross-domain replay rejection, CRYPTO_VERIFY_FAILED
on tamper) remains identical to the archived bitpacker-crypto-rewrite
spec.
The primitive SHALL import Authority, AuthorityVerifier, DomainTag,
KeySlotPublic, and SlotId types from @suaveplan/types instead of
from @suaveplan/crypto/authority and @suaveplan/crypto/domain-tags.
Scenario: missing verifier rejects at construction time
- WHEN
defineSignedBitSchema(codec, { domain: D })is called WITHOUT averifierfield - THEN the Zod options-validation throws AND no schema instance is returned
Scenario: DI'd verifier produces same boolean answer as direct import
- WHEN
defineSignedBitSchema(codec, { domain, verifier: verifyAuthoritySignature })packs a payload and the result isunpack-ed - THEN the round-trip matches the original AND the verify path emits the same OTel span as the archived rewrite
Scenario: bitpacker-crypto's compiled dist/ contains zero references to @suaveplan/crypto
- WHEN
bunx turbo build --filter=@suaveplan/bitpacker-cryptoruns - THEN
grep -r "@suaveplan/crypto" packages/bitpacker/bitpacker-crypto/dist/returns zero matches in*.jsand*.d.tsfiles
Verified by: packages/bitpacker/bitpacker-crypto/src/signed/signed-bitschema.test.ts::"missing verifier rejects at construction time" AND packages/bitpacker/bitpacker-crypto/src/signed/signed-bitschema.test.ts::"pack signs via Authority under the configured domain" AND packages/bitpacker/bitpacker-crypto/src/signed/signed-bitschema.spec-conformance.test.ts::"signed-pack emits OTel span with domain attribute"
Requirement: MultiSignedBitSchema accepts injected verifier
The defineMultiSignedBitSchema<T>(bodyCodec, options) function SHALL
accept a required verifier: AuthorityVerifier field on its options
bundle. The primitive SHALL call verifier(...) for each signature
verification instead of importing verifyAuthoritySignature. Wire
format, count enforcement, firstBadSignerIndex reporting,
CRYPTO_MULTISIGN_COUNT_MISMATCH semantics — all unchanged.
Scenario: missing verifier rejects at construction time
- WHEN
defineMultiSignedBitSchema(codec, { domain: D, signerCount: 2 })is called WITHOUT averifierfield - THEN the Zod options-validation throws
Scenario: DI'd verifier preserves firstBadSignerIndex semantics
- WHEN a 3-signer payload's second signature is flipped and
verify(bytes, [pubA, pubB, pubC])is called with the DI'dverifyAuthoritySignature - THEN the result is
{ valid: false, firstBadSignerIndex: 1 }identical to the archived rewrite
Verified by: packages/bitpacker/bitpacker-crypto/src/multisigned/multisigned-bitschema.test.ts::"missing verifier rejects at construction time" AND packages/bitpacker/bitpacker-crypto/src/multisigned/multisigned-bitschema.test.ts::"verify pinpoints which signer failed"
Requirement: HashChainSchema accepts injected verifier
The defineHashChainSchema<TPayload>(options) function SHALL accept
a required verifier: AuthorityVerifier field on its options bundle.
verifyEntry and verifyChain SHALL use the DI'd verifier. All
chain-walk, prev-hash linkage, tamper detection (firstBadIndex),
pluggable hash registry behavior — all unchanged.
Scenario: missing verifier rejects at construction time
- WHEN
defineHashChainSchema({ domain: D, payloadCodec: c })is called WITHOUT averifierfield - THEN the Zod options-validation throws
Scenario: chain verification detects tamper at exact index with DI'd verifier
- WHEN a 5-entry chain is built using the DI'd verifier, then
entry-2's payload is mutated and
verifyChainis called - THEN the result is
{ valid: false, firstBadIndex: 2 }identical to the archived rewrite
Verified by: packages/bitpacker/bitpacker-crypto/src/hashchain/hashchain-schema.test.ts::"missing verifier rejects at construction time" AND packages/bitpacker/bitpacker-crypto/src/hashchain/hashchain-schema.test.ts::"chain verification detects tamper at exact index"
Requirement: EncryptedBitSchema accepts injected AEAD operations
The defineEncryptedBitSchema<T>(bodyCodec, options) function SHALL
accept a required aead: AeadOps field on its options bundle. The
primitive SHALL call aead.encrypt(...) and aead.decrypt(...)
instead of importing aeadEncrypt / aeadDecrypt directly.
The constants AEAD_KEY_LENGTH = 32, AEAD_NONCE_LENGTH = 12, and
AEAD_XCHACHA_NONCE_LENGTH = 24 SHALL be declared locally in
encrypted-bitschema.ts (not imported from @suaveplan/crypto).
Duplication is acceptable because these values are part of the
bit-packer-crypto wire format.
The primitive SHALL import AeadAlgorithm, AeadOps, Rng from
@suaveplan/types. Wire format [version u8][algTag u8][nonceLen u8] [nonce][ciphertext + tag] and the closed ENCRYPTED_ALG_TAGS enum
remain unchanged.
Scenario: missing aead rejects at construction time
- WHEN
defineEncryptedBitSchema(codec, { key })is called WITHOUT anaeadfield - THEN the Zod options-validation throws
Scenario: DI'd AEAD bundle preserves round-trip semantics
- WHEN
defineEncryptedBitSchema(codec, { key, aead: { encrypt: aeadEncrypt, decrypt: aeadDecrypt } })packs and unpacks a payload - THEN the round-trip matches the original AND tampered ciphertext
rejects with
CRYPTO_DECRYPT_FAILEDidentical to the archived rewrite
Scenario: bitpacker-crypto's package.json lists @suaveplan/crypto only as devDependency
- WHEN
cat packages/bitpacker/bitpacker-crypto/package.json | jq -r '.dependencies | keys[]'runs - THEN the output does NOT include
@suaveplan/crypto - AND
cat packages/bitpacker/bitpacker-crypto/package.json | jq -r '.devDependencies | keys[]'DOES include@suaveplan/crypto
Verified by: packages/bitpacker/bitpacker-crypto/src/encrypted/encrypted-bitschema.test.ts::"missing aead rejects at construction time" AND packages/bitpacker/bitpacker-crypto/src/encrypted/encrypted-bitschema.test.ts::"round-trips through XChaCha20-Poly1305" AND packages/bitpacker/bitpacker-crypto/src/encrypted/encrypted-bitschema.test.ts::"tampered ciphertext rejects with CRYPTO_DECRYPT_FAILED"