Files
2026-05-27 23:29:53 +01:00

49 lines
3.2 KiB
Markdown

<!-- markdownlint-disable MD024 -->
# 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"`
<!-- markdownlint-enable MD024 -->