Files
suaveplan/openspec/archive/2026-05-02-bitpacker-canonical-spec/specs/bitpacker/spec.md
2026-05-27 23:29:53 +01:00

79 lines
4.2 KiB
Markdown

<!-- markdownlint-disable MD024 -->
# Capability Spec Delta: bitpacker (bitpacker-canonical-spec)
**Package**: `@suaveplan/bitpacker`
**Status**: PROPOSED
> Every requirement below carries a `**Verified by:**` line at authoring time. The requirements are ported from upstream `/mnt/s/web/suaveplan/openspec/specs/bitpacker/spec.md` (cited in the proposal source mapping); SHALL phrasing has been added to satisfy the genesis OpenSpec validator. Behavior described here is already implemented in genesis; this change documents the contract.
## Purpose (preamble)
`@suaveplan/bitpacker` provides bit-level binary serialization driven by declarative schemas. It supports fixed-width primitives (`u8`, `i16`, etc.), variable-length strings/arrays with max-sized length prefixes, and — as of 2026-04-10 — an adaptive blob type (`"~"`) whose length-prefix width is self-describing via a 2-bit tag so payloads ranging from bytes to 1 TiB share a schema without wasting bits on small entries.
## ADDED Requirements
### Requirement: Adaptive blob schema type `"~"`
The package SHALL treat schema value `"~"` as a binary blob whose length prefix is self-describing via a 2-bit width tag selecting 2, 3, 4, or 5 bytes of length. Pack input and unpack output SHALL be `Uint8Array` with no encoding.
#### Scenario: tag selected for a small payload
- **WHEN** packing 200 bytes with schema field `data: "~"`
- **THEN** the written bits are `[tag=0][2-byte length=200][200 raw bytes]`
#### Scenario: tag selected for a large payload
- **WHEN** packing 500 MiB
- **THEN** the tag is `2` and the length prefix is 4 bytes
#### Scenario: payload over 1 TiB rejected
- **WHEN** packing a buffer whose length exceeds `0xFFFFFFFFFF`
- **THEN** the packer throws
#### Scenario: round-trip preserves bytes
- **WHEN** a `Uint8Array` is packed then unpacked
- **THEN** the output is byte-identical to the input
**Verified by:** `packages/bitpacker/bitpacker-strategies/src/strategies/blob/blob.test.ts::"selects 2-byte length tag for payloads under 64 KiB"` AND `packages/bitpacker/bitpacker-strategies/src/strategies/blob/blob.test.ts::"selects 4-byte length tag for payloads over 16 MiB"` AND `packages/bitpacker/bitpacker-strategies/src/strategies/blob/blob.test.ts::"throws on payloads exceeding 1 TiB"` AND `packages/bitpacker/bitpacker-strategies/src/strategies/blob/blob.test.ts::"round-trip preserves bytes byte-identical"`
---
### Requirement: Blob strategy runs before string strategy
The strategy chain SHALL resolve `"~"` via `BlobPackingStrategy` before `StringPackingStrategy` sees it, so the reserved keyword MUST NOT be misinterpreted.
#### Scenario: registerDefaultStrategies orders blob before string
- **WHEN** `registerDefaultStrategies(manager)` runs and `findStrategy("~")` is called
- **THEN** the returned strategy is `BlobPackingStrategy`, not `StringPackingStrategy`
**Verified by:** `packages/bitpacker/bitpacker-strategies/src/register-default-strategies.test.ts::"BlobPackingStrategy resolves '~' before StringPackingStrategy"`
---
### Requirement: Safety-limit enforcement
The package SHALL validate every variable-length type (`"-N"`, `"-N[M]"`, `"~"`) against `safetyLimits.maxBufferSize` before writing.
#### Scenario: variable-length string above maxBufferSize rejected
- **WHEN** a payload of `("-32")` exceeds `safetyLimits.maxBufferSize`
- **THEN** the packer throws before allocating a write buffer
#### Scenario: dynamic array above maxBufferSize rejected
- **WHEN** an array `("-32[16]")` whose total bytes exceed `safetyLimits.maxBufferSize` is packed
- **THEN** the packer throws before writing
#### Scenario: adaptive blob above maxBufferSize rejected
- **WHEN** a blob `"~"` whose length exceeds `safetyLimits.maxBufferSize` is packed
- **THEN** the packer throws before writing
**Verified by:** `packages/bitpacker/bitpacker-validation/src/safety/safety-checks.test.ts::"rejects variable-length string above maxBufferSize"` AND `packages/bitpacker/bitpacker-validation/src/safety/safety-checks.test.ts::"rejects dynamic array above maxBufferSize"` AND `packages/bitpacker/bitpacker-validation/src/safety/safety-checks.test.ts::"rejects adaptive blob above maxBufferSize"`
<!-- markdownlint-enable MD024 -->