Skip to content

refactor: make the recipient-binding encode infallible and state the scope-transplant rule - #1843

Merged
FSM1 merged 2 commits into
mainfrom
refactor/1551-1711-recipient-binding-and-transplant-rule
Sep 14, 2026
Merged

FSM1 merged 2 commits into
mainfrom
refactor/1551-1711-recipient-binding-and-transplant-rule

Conversation

@FSM1

@FSM1 FSM1 commented Sep 14, 2026 •

Copy link
Copy Markdown
Owner

Wave 19, lane C2. Two comp:core issues that share the recipient-binding and carried-unknown surface.

What changes

#1551 — the recipient-binding encode becomes infallible.
The preimage is a map of four byte strings the function builds itself. It nests two levels against MAX_DEPTH 128 and the map is local, so neither check_depth nor Map::reject_if_wiped can fire. The encode now goes through encode_fixed_depth, which is the codec's own name for a tree whose nesting the construction site fixes.

  • encode_recipient_binding returns Vec<u8>.
  • sign_recipient_binding returns EcdsaSignature.
  • verify_recipient_binding stays fallible for the signature check and loses only the ? on its encode leg.
  • mint_grant_row loses the .ok()? that the false fallibility fed.

mint_grant_row keeps its Option. The diffie_hellman leg is a real contributory backstop, so remint_grants keeps its Rejected mapping for that leg. This is the open call in step 4 of the issue; the decision is recorded on the issue.

Six caller sites drop an .expect or an .unwrap. The wire format does not change and the KAT vectors do not change: crates/core/kat/manifest.json is untouched and the recipient-binding accept vectors re-encode byte-for-byte.

#1711 — the scope-transplant rule is stated.
blueprint/core.md now states, inside the carried unknown fields law that it qualifies, that every new envelope-level or epochTag-level structure is either scope-transplant-safe or refused by name at the authoring path that moves it, the way author_child_envelope already refuses the grant section. One sentence covers both levels.

reseal_interior_node carries a one-line cross-reference immediately before its publish_interior_head call. That is the single call site where the scope changes while carried unknown fields travel; the sweep keeps the node inside its own scope and carries no cross-reference.

Verification

cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings, cargo test -p cipherbox-core, cargo test -p cipherbox-engine, cargo check -p cipherbox-wasm --target wasm32-unknown-unknown, pnpm lint:md, pnpm lint:tracker-refs. All green. No TypeScript is touched.

Review gates

Simplify, security and crypto and privacy passes ran inline over git diff main...HEAD. The crypto and privacy pass confirms the preimage bytes, the RFC 6979 ECDSA signing path and the zeroize ownership are all unchanged, and that the one removed refusal was unreachable rather than fail-closed.

Body checks / follow-ups filed

Closes #1551.
Closes #1711.

Summary by CodeRabbit

  • Documentation

    • Documented requirements for preserving carried fields when scopes change, including safe handling or explicit refusal of scope-bound structures.
    • Added implementation guidance for authors of carried structures.
  • Reliability

    • Simplified recipient-binding encoding and signing so valid in-memory inputs no longer expose unnecessary failure paths.
    • Updated verification, grant creation, rotation, and regression coverage to use the streamlined behavior.
  • Tests

    • Preserved existing verification, replay-scope, and recipient-binding assertions while updating test expectations.

Note

Make encode_recipient_binding and sign_recipient_binding infallible and add scope-transplant rule

  • Changes encode_recipient_binding in write_body.rs from a fallible codec return to raw bytes using a fixed-depth encoder; sign_recipient_binding now returns the signature directly.
  • Updates all production call sites (ledger.rs, rotation.rs) and test fixtures to remove error unwrapping and result expectations around the recipient-binding API.
  • Adds a blueprint rule in core.md: carried unknown fields must survive scope changes when re-sealed under another scope's AAD; structure authors must classify new envelope/epochTag structures as either transplant-safe or explicitly refused.
  • Adds an implementation comment in reseal_interior_node identifying it as the authoring path where carried unknown fields cross a scope boundary.
  • Behavioral Change: encode_recipient_binding and sign_recipient_binding no longer return Result; all callers that previously handled encoding errors must be updated.

Macroscope summarized 91511de.

… dead mint refusal

The recipient-binding preimage is four byte strings the encoder builds
itself, so neither check_depth nor Map::reject_if_wiped can fire. Route it
through encode_fixed_depth, drop the Result from encode_recipient_binding
and sign_recipient_binding, and delete the .ok()? in mint_grant_row that
the false fallibility fed.

mint_grant_row keeps its Option for the diffie_hellman contributory
backstop, so remint_grants keeps its Rejected mapping for that leg.

The wire format and the KAT vectors do not change.
publish_interior_head carries envelope-level and epochTag-level unknown
fields from a record authored under one scope's AAD into a record authored
under another scope's AAD. blueprint/core.md now states, inside the carried
unknown fields law, that every new structure at either level is either
scope-transplant-safe or refused by name at that authoring path, the way
author_child_envelope already refuses the grant section.

The scope-changing call site in reseal_interior_node carries a one-line
cross-reference to the rule.
@coderabbitai

coderabbitai Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: e1674eae-bf95-452d-8120-fcdc0f76900d

📥 Commits

Reviewing files that changed from the base of the PR and between 0384ee1 and 91511de.

📒 Files selected for processing (11)
  • blueprint/core.md
  • crates/core/examples/kat_gen.rs
  • crates/core/src/seal/write_body.rs
  • crates/core/tests/kat_manifest.rs
  • crates/engine/src/grants/create.rs
  • crates/engine/src/grants/ledger.rs
  • crates/engine/src/net/rotation.rs
  • crates/engine/src/rotation/cascade.rs
  • crates/engine/src/rotation/reseal.rs
  • crates/engine/src/rotation/rotate.rs
  • crates/engine/src/rotation/trigger.rs
💤 Files with no reviewable changes (1)
  • crates/engine/src/grants/ledger.rs

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


Walkthrough

The change makes recipient-binding encoding and signing infallible by using fixed-depth encoding. Callers remove obsolete error handling. The blueprint documents scope-transplant requirements for preserved fields, and the affected authoring path references the rule.

Changes

Recipient-binding API

Layer / File(s) Summary
Infallible binding encoding and signing
crates/core/src/seal/write_body.rs
encode_recipient_binding uses encode_fixed_depth and returns Vec<u8>. sign_recipient_binding returns EcdsaSignature. Verification and tests remove obsolete propagation.
Binding caller updates
crates/core/examples/kat_gen.rs, crates/core/tests/kat_manifest.rs, crates/engine/src/grants/*, crates/engine/src/rotation/*
Callers use direct binding values and remove obsolete expect, unwrap, and optional-failure handling.

Scope-transplant rule

Layer / File(s) Summary
Scope-transplant rule and authoring reference
blueprint/core.md, crates/engine/src/net/rotation.rs
The blueprint requires new envelope-level and epochTag-level structures to be scope-transplant-safe or refused by name. The scope-changing authoring path references this rule.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Refactor

Merge Risk: ⚪ Minimal · up to 91511

The change preserves recipient-binding behavior and caller contracts, with no established production-impacting regression.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR meets the coding requirements in [#1551] and [#1711]. In write_body.rs, encode_recipient_binding uses encode_fixed_depth and returns Vec<u8>. sign_recipient_binding returns `EcdsaSign…
Out of Scope Changes check ✅ Passed The changed files support the two linked objectives. Source edits implement the infallible recipient-binding API and update its callers and test fixtures. Documentation edits state the scope-transplan…
Docstring Coverage ✅ Passed Docstring coverage is 92.86% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 8 files. (2 skipped: 1 …
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies both primary changes: making recipient-binding encoding infallible and documenting the scope-transplant rule.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/1551-1711-recipient-binding-and-transplant-rule

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@FSM1

FSM1 commented Sep 14, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 14, 2026 •

Copy link
Copy Markdown
✅ 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.

@FSM1
FSM1 marked this pull request as ready for review September 14, 2026 23:50
@FSM1
FSM1 merged commit 398087d into main Sep 14, 2026
32 checks passed
@FSM1
FSM1 deleted the refactor/1551-1711-recipient-binding-and-transplant-rule branch September 14, 2026 23:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant