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

4.2 KiB

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"