Skip to content

LAB-783: StorageEnvelope compressed_data → msgpack bin encoding (protocol 1.1)#44

Merged
27Bslash6 merged 4 commits into
mainfrom
lab-783-envelope-bin-encoding-rfc
Jul 25, 2026
Merged

LAB-783: StorageEnvelope compressed_data → msgpack bin encoding (protocol 1.1)#44
27Bslash6 merged 4 commits into
mainfrom
lab-783-envelope-bin-encoding-rfc

Conversation

@27Bslash6

@27Bslash6 27Bslash6 commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

LAB-783 — Protocol RFC: StorageEnvelope compressed_data → msgpack bin encoding

Implements the RFC mandated by the LAB-764 GO decision (ray, 2026-07-25) for
cachekit-io/cachekit-core#54.
Spec change only — no implementation ships here; the writer flip is staged behind this PR on LAB-764.

What changes

  • spec/wire-format.md — protocol 1.1: writers MUST encode compressed_data (element [0]) as msgpack bin (0xc4/0xc5/0xc6); readers MUST accept the legacy array-of-ints encoding permanently. Dual-read compatibility statement (mutual in both directions under rmp-serde, toolchain-verified incl. bin wire through the shipped ByteStorage::retrieve()), no version field or discriminator, AAD-independence statement, ≤ +1 B tiny-envelope micro-regression, implementation-status note, and a new normative rule in Security Limits (validate declared length headers before allocating). Scope exclusions explicit: checksum stays array-of-8-ints, format untouched (feeds AAD v0x03).
  • decisions/envelope-bin-encoding.md — decision record: rationale, measured evidence (1.508× → 1.0039× wire, 6–11× codec throughput on 64 MiB incompressible), rejected options (a versioned envelope would itself be the breaking change), readers-first rollout order, deferred bin16/32 width-boundary vector (MUST land in the implementation PR).
  • test-vectors/wire-format.json — 6 *_bin twins appended (append-only; legacy vector objects byte-untouched, retained forever as legacy-read proof); fixture 1.0.0 → 1.1.0.
  • tools/wire-format-reference.py — stdlib-only generator/verifier: proves codec fidelity by re-encoding the legacy pins byte-identically to the rmp_serde-generated originals; msgpack-python third-encoder conformance when importable; fails closed on unclassifiable/duplicate/tampered vectors (all four corruption paths tested).
  • .github/workflows/verify.yml — adds wire-format-reference.py verify to both existing Python steps. Note for reviewers: this CI edit adds an enforcement gate (the wire-format fixture previously had no protocol-side verifier — LAB-423 finding); it does not touch existing checks.

Verification performed

  • All 6 *_bin vectors byte-verified against real rmp-serde 1.3.1 + serde_bytes 0.11.19 output (local cross-check crate; dual-read matrix re-confirmed on the pinned bytes in both reader directions).
  • All existing repo verifiers still green (interop, encryption, python-frame, JS cross-checks).
  • Mandatory crypto/protocol expert-panel gate passed (high stakes, 4-agent panel). All three LAB-764 checkpoints CONFIRMED: (a) AAD independence — AAD v0x03 is metadata-only, envelope bytes are AES-GCM plaintext; (b) scope strictly compressed_data; (c) format untouched. Panel findings applied in the second commit: corrected +4 B → +1 B micro-regression bound (header arithmetic), fail-closed verifier guards, Security-Limits allocation rule, implementation-status honesty note, prose dedupe.

Sequencing

Per LAB-783: authoring lands now; review/merge queues behind the LAB-244 merge wave. sdk-feature-matrix.md deliberately untouched (it never references element-level envelope encoding).

Closes LAB-783 (Multica). Parent tracking: LAB-764.

Summary by CodeRabbit

  • Documentation

    • Updated the wire-format specification for protocol 1.1.
    • Documented canonical binary encoding for compressed data, while retaining compatibility with legacy encoding.
    • Added guidance on rollout, security validation, and compatibility expectations.
  • Tests

    • Added expanded wire-format test vectors covering both legacy and binary encodings.
    • Extended verification across standard-library and optional-dependency environments.
    • Added checks for malformed length declarations and encoding consistency.
  • Changelog

    • Recorded the wire-format and compatibility updates under the upcoming release.

… + vectors)

Protocol 1.1: writers MUST emit compressed_data as msgpack bin
(0xc4/0xc5/0xc6); readers MUST accept the legacy array-of-ints encoding
permanently. Not a breaking change: dual-read is mutual in both
directions under rmp-serde (toolchain-verified on all pinned vectors,
including bin wire through the shipped ByteStorage::retrieve()); no
version field or discriminator. checksum stays array-of-ints (crypto-
adjacent, 1-7 B win); format untouched (feeds AAD v0x03, which contains
no envelope bytes). Tiny envelopes grow <= +4 B (empty 25->26 B);
incompressible payloads shrink ~35% with 6-11x codec throughput.

- spec/wire-format.md: canonical + legacy byte layouts, dual-read
  compatibility statement, AAD independence, micro-regression note
- decisions/envelope-bin-encoding.md: rationale, rejected options
  (versioned envelope would BE the breaking change), rollout order
  (readers-first as discipline), evidence
- test-vectors/wire-format.json: 6 *_bin twins appended (append-only,
  legacy vectors byte-untouched); fixture 1.0.0 -> 1.1.0
- tools/wire-format-reference.py: stdlib generate/verify; proves codec
  fidelity by re-encoding legacy pins byte-identically; msgpack
  third-encoder conformance when importable; twins byte-verified against
  rmp-serde 1.3.1 + serde_bytes 0.11.19 output
- verify.yml: wire-format verify added to both python steps (first
  protocol-side CI enforcement of this fixture)
Panel: bug-hunter-supreme, security-specialist, code-craftsman,
catchphrase-agent. All three LAB-764 checkpoints CONFIRMED (AAD
independence, checksum scope exclusion, format untouched). Applied:

- Corrected micro-regression bound: +4 B was bad header arithmetic
  (bin32 never pairs with fixarray); true bound is +1 B, only for
  compressed_data <= 15 B with no byte >= 0x80. Fixed in spec, decision
  record, CHANGELOG, and the tool assert.
- wire-format-reference.py fails closed on unclassifiable or
  duplicate-named vectors (was: silent skip in verify, silent drop in
  generate); ValueError now localized per-vector; impossible str8 codec
  branches deleted (format is always a fixstr registry token). All four
  corruption paths tested fail-closed.
- Security Limits: decoders MUST validate declared bin/array length
  headers against remaining input before allocating (bin32 = single-
  header 4 GiB OOM for pre-allocating readers).
- Implementation-status note: no shipped release emits bin yet.
- bin16/bin32 width-boundary vector explicitly deferred to the
  implementation PR (needs real LZ4 output > 255 B; documented in the
  decision record as a MUST for that PR).
- Prose dedupe: measured evidence consolidated into the decision record;
  dual-read table single-sourced in the spec; CHANGELOG trimmed to house
  style; fixture metadata de-normativized.
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 49 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 19756d26-4b7a-41ff-b152-80bca74fc79f

📥 Commits

Reviewing files that changed from the base of the PR and between d98e920 and c9dda7e.

📒 Files selected for processing (1)
  • tools/wire-format-reference.py

Walkthrough

The protocol specification and decision record define canonical MessagePack bin encoding for compressed_data while retaining legacy reads. A stdlib reference tool generates and verifies twin vectors, and CI runs verification in both dependency modes.

Changes

Envelope bin encoding

Layer / File(s) Summary
Protocol contract and rollout
decisions/envelope-bin-encoding.md, spec/wire-format.md, CHANGELOG.md
Protocol 1.1 now specifies bin for compressed_data, dual-read compatibility, length-header validation, unchanged checksum and format rules, and staged rollout details.
Reference codec and verification
tools/wire-format-reference.py
Adds bounded MessagePack envelope decoding and encoding, bin-twin generation, fixture validation, optional msgpack conformance checks, and CLI commands.
Fixtures and CI coverage
test-vectors/wire-format.json, .github/workflows/verify.yml, CHANGELOG.md
Adds six bin-encoded twin vectors, updates fixture metadata to version 1.1.0, and runs wire-format verification in standard-library and optional-dependency workflows.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

  • cachekit-io/cachekit-core#54 — Covers switching StorageEnvelope.compressed_data to canonical bin encoding while retaining backward-compatible reads.

Possibly related PRs

  • cachekit-io/protocol#18 — Earlier changes established the positional envelope and byte-field expectations extended by this wire-format update.

Sequence Diagram(s)

sequenceDiagram
  participant CI
  participant WireFormatReference
  participant WireFormatFixture
  CI->>WireFormatReference: run verify
  WireFormatReference->>WireFormatFixture: load legacy and bin vectors
  WireFormatReference->>WireFormatReference: decode and re-encode envelopes
  WireFormatReference-->>CI: return verification status
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely states the main change: StorageEnvelope compressed_data now uses MessagePack bin encoding for protocol 1.1.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch lab-783-envelope-bin-encoding-rfc

Comment @coderabbitai help to get the list of available commands.

@27Bslash6

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@27Bslash6

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.


Your included review limit is currently reached under our Fair Usage Limits Policy. Your recent PR review activity is in the 95th percentile or higher among CodeRabbit users, so adaptive limits apply. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 29 minutes.

…ifier

Expert-panel finding (LAB-783 crypto/protocol gate): _decode_bytes_field peeked
r.buf[r.pos] directly — the one decode path bypassing the bounds-checked _Reader.
A truncated/malformed vector raised a bare IndexError that verify()'s except did
not catch, aborting the whole run with a raw traceback and no per-vector context.
The decision record defers a bin16/bin32 boundary vector as a MUST for the
implementation PR, so this decode path will receive new/adversarial input.

- add bounds-checked _Reader.peek(); element[0] decode now raises the tool's own
  ValueError on truncation, consistent with every other field read.
- widen verify()'s per-vector isolation to catch IndexError/KeyError so a
  malformed fixture entry fails only itself with a named FAIL line.

Format-neutral by construction: no wire bytes change, all 12 vectors byte-identical,
verify stays 6/6 green (stdlib + msgpack-python conformance). Only the exception
type raised on already-malformed input changes.
@27Bslash6

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tools/wire-format-reference.py`:
- Around line 259-346: Refactor verify() by extracting the per-vector validation
into a focused helper, such as _verify_vector(base, bins, msgpack), while
preserving all existing checks, failure isolation, output, and return behavior.
Keep fixture-level validation, failure aggregation, orphan handling, and final
reporting in verify(); have the helper perform codec fidelity, twin equivalence,
size-bound, and optional msgpack conformance checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 895ec16e-c886-439a-af29-dbd26ed83ad6

📥 Commits

Reviewing files that changed from the base of the PR and between 05c89fb and d98e920.

📒 Files selected for processing (6)
  • .github/workflows/verify.yml
  • CHANGELOG.md
  • decisions/envelope-bin-encoding.md
  • spec/wire-format.md
  • test-vectors/wire-format.json
  • tools/wire-format-reference.py

Comment thread tools/wire-format-reference.py
CodeRabbit (Ruff PLR0915): verify() had 52 statements (>50). Extract the
per-vector validation — codec fidelity, twin equivalence, size bound, optional
msgpack-python conformance — into _verify_vector(base, bins, msgpack). The
per-vector try/except failure isolation stays in verify().

Behavior-identical: verify still 6/6 green (stdlib + msgpack conformance), same
output and same per-vector isolation; `ruff check --select PLR0915` now clean.

CodeRabbit-Resolved: wire-format-reference.py:346:split verify into per-phase helpers
@27Bslash6
27Bslash6 merged commit 6863495 into main Jul 25, 2026
2 checks passed
@27Bslash6
27Bslash6 deleted the lab-783-envelope-bin-encoding-rfc branch July 25, 2026 03:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant