# Capability Spec Delta: crypto (chain-bundle-adopt-envelope-schema) **Package**: `@suaveplan/crypto` **Status**: PROPOSED — gated on user sign-off > Pins the byte-identical wire-format invariant of `ChainBundle` so the > just-completed migration to `@suaveplan/bitpacker-crypto::EnvelopeSchema` > cannot drift the on-the-wire layout. No public-API change; this > Requirement formalises an invariant that was previously only enforced > by the implementation reading itself. ## ADDED Requirements ### Requirement: ChainBundle wire format is byte-identical to v0x0001 layout The `packChainBundle(linkBytes)` function SHALL produce bytes in the layout `[CHAIN_BUNDLE_MAGIC (4 bytes)][CHAIN_BUNDLE_FORMAT_VERSION (u8)][linkCount (u8)][...linkBytes concatenated]`. `CHAIN_BUNDLE_HEADER_BYTE_SIZE` SHALL be `6` (4 magic + 1 version + 1 linkCount). The implementation MAY consolidate the header construction through `@suaveplan/bitpacker-crypto::EnvelopeSchema`, but the resulting bytes MUST be byte-identical to the v0x0001 layout pinned by snapshot test. Any future drift in the underlying primitive that changes the byte layout is a wire-format break and MUST be caught by the snapshot test. #### Scenario: snapshot bytes match v0x0001 layout - **WHEN** `packChainBundle([fixedDeterministicLinkBytes])` runs with a fixed deterministic link payload - **THEN** the resulting bytes are byte-identical to the v0x0001 snapshot pinned in `chain-bundle.test.ts::"chain-bundle wire format is byte-identical to v0x0001 snapshot"` #### Scenario: header size constant is 6 - **WHEN** `CHAIN_BUNDLE_HEADER_BYTE_SIZE` is read - **THEN** the value is exactly `6` #### Scenario: bad magic surfaces as `CryptoError CHAIN.WRONG_FORMAT crypto.chain-bundle.bad-magic` - **WHEN** `parseChainBundle(bytes)` is called on bytes whose first 4 bytes do not match `CHAIN_BUNDLE_MAGIC` - **THEN** the call throws `CryptoError` with code `CHAIN.WRONG_FORMAT` and message `crypto.chain-bundle.bad-magic` #### Scenario: bad version surfaces as `CryptoError CHAIN.WRONG_FORMAT crypto.chain-bundle.unsupported-version` - **WHEN** `parseChainBundle(bytes)` is called on bytes whose 5th byte (formatVersion) is not `CHAIN_BUNDLE_FORMAT_VERSION` - **THEN** the call throws `CryptoError` with code `CHAIN.WRONG_FORMAT` and message `crypto.chain-bundle.unsupported-version` and `context.version` carrying the actual version byte #### Scenario: too-short bytes surface as `CryptoError CHAIN.WRONG_FORMAT crypto.chain-bundle.bytes-too-short` - **WHEN** `parseChainBundle(bytes)` is called on a buffer shorter than `CHAIN_BUNDLE_HEADER_BYTE_SIZE` - **THEN** the call throws `CryptoError` with code `CHAIN.WRONG_FORMAT` and message `crypto.chain-bundle.bytes-too-short` **Verified by:** `packages/crypto/crypto/src/bundles/chain-bundle/chain-bundle.test.ts::"chain-bundle wire format is byte-identical to v0x0001 snapshot"` AND `packages/crypto/crypto/src/bundles/chain-bundle/chain-bundle.test.ts::"parseChainBundle rejects bad magic"` AND `packages/crypto/crypto/src/bundles/chain-bundle/chain-bundle.test.ts::"parseChainBundle rejects bad version"` AND `packages/crypto/crypto/src/bundles/chain-bundle/chain-bundle.test.ts::"parseChainBundle rejects too-short payload"`