Skip to content

v0.51.0: SEP-2828 Check B outcome-to-decision pairing#186

Merged
vaaraio merged 1 commit into
mainfrom
feat/sep2828-check-b
Jun 2, 2026
Merged

v0.51.0: SEP-2828 Check B outcome-to-decision pairing#186
vaaraio merged 1 commit into
mainfrom
feat/sep2828-check-b

Conversation

@vaaraio
Copy link
Copy Markdown
Owner

@vaaraio vaaraio commented Jun 2, 2026

Adds Check B (outcome-to-decision content binding) to the SEP-2828 decision/outcome pairing, the field both independent implementers (XuebinMa/agent-guard emitter, Rul1an/Assay consumer) were waiting on.

What changes

  • outcomeDerived.decisionDigest: sha256:<hex> over the JCS-canonical full signed decision-record wire bytes (signature included). Optional on the type so pre-v0.51 records and the no-attestation fallback still parse, but a v0.51 emitter MUST set it.
  • records_paired now enforces both checks: Check A (instance anchor: same backLink attestation digest + nonce) and Check B (the receipt's decisionDigest equals this decision's digest). A receipt without decisionDigest does not pair: content binding is mandatory, not best-effort.
  • superseding_decision: among decision records sharing a back-link, the latest decidedAt is effective; ties break on the lexicographically lowest issuerAsserted.nonce, so every verifier picks the same winner without a clock. Sound because the SEP constrains timestamps to RFC3339 UTC second-precision with trailing Z.
  • 7th conformance vector substituted_decision_under_shared_attestation: Check A passes, Check B fails (the receipt commits to a different decision under the same attestation).
  • SEP markdown updated to match.

Envelope version stays 1; the field is additive.

Verification

  • 1162 passed, 13 skipped; ruff + mypy clean on changed files.
  • Independent stdlib-only walker (no Vaara imports): 7/7 vectors match expected.
  • Version surfaces consistent at 0.51.0.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added decision digest commitment to outcome records for outcome-to-decision binding verification.
    • Enhanced decision/receipt pairing validation with two-part checks: attestation back-link matching and decision digest matching.
    • Added deterministic tie-breaking for multiple decisions with identical timestamps using nonce ordering.
  • Documentation

    • Updated server-side execution record specification and pairing model.
  • Chores

    • Version bump to 0.51.0.

Pairing now enforces two checks: Check A (instance anchor on the shared
attestation back-link) and Check B (the outcome record commits to a
sha256 over the full signed decision wire bytes via
outcomeDerived.decisionDigest). Check A alone could not say which
decision a call ran under when several shared an attestation; Check B
closes that gap. The field is additive, envelope version stays 1.

Adds decision_digest and superseding_decision (latest decidedAt, tie
broken by lowest issuerAsserted.nonce) to the public surface, a seventh
conformance vector (substituted_decision_under_shared_attestation), and
resolves the supersession-tie winner. Independent stdlib walker: 7/7.
SEP draft updated (Check A/B, decisionDigest, supersession tie-break,
refer/AskUser to escalate enum note, fallback, verification step,
prior-art reconciliation). 1162 passed.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR implements decision digest binding as a normative pairing check (Check B) for execution-record verification: receipts must commit to a deterministic SHA256 JCS-canonicalized digest of the decision they reference, validated against computed decision digests during pairing, alongside deterministic supersession tie-breaking by lexicographic nonce.

Changes

Decision Digest Commitment for Receipt Pairing

Layer / File(s) Summary
Decision digest computation and supersession helpers
src/vaara/attestation/_decision_verifier.py, src/vaara/attestation/decision.py
Introduces decision_digest(record) computing sha256 JCS-canonical digest and superseding_decision(decisions) selecting by latest decided_at with lexicographic nonce tie-breaking; both exported publicly.
Receipt schema with decision_digest field
src/vaara/attestation/_receipt_types.py
OutcomeDerived gains optional decision_digest: Optional[str] field; serialization emits decisionDigest when present, deserialization validates sha256: prefix.
Pairing validation with Check B binding
src/vaara/attestation/_decision_verifier.py
records_paired() enhanced to require receipt outcome_derived.decision_digest present and constant-time matching computed digest; rejects missing or mismatched digests.
Unit tests for digest and pairing
tests/test_decision_record.py
Tests validate digest determinism/instance-binding, supersession winner selection, pairing success on digest match, and failures on digest omission or mismatch.
Specification and documentation updates
docs/sep/sep-server-execution-record.md, CHANGELOG.md
SEP refined to describe Check B digest binding, supersession tie-breaking by lexicographic nonce, backward-compatibility note; changelog documents v0.51.0 features.
Test vector generation script
scripts/generate_decision_pairing_vectors.py
_receipt() extended with optional dec_digest parameter; existing cases updated to commit digests; new Case 7 exercises Check B in isolation (shared back-link, different digest).
Conformance checker updates
tests/vectors/decision_pairing_v0/_check_independent.py
Adds decision_digest() and superseding_nonce() helpers; records_paired() validates digest matching; computed verdicts for shared_back_link and deterministic winner.
Test vectors with decision digest
tests/vectors/decision_pairing_v0/normative/*/...json
All receipt vectors updated with new decisionDigest values; new substituted_decision_under_shared_attestation case added; supersession tie winner resolved to d5a with nonce ordering note.
Version bumps
clients/ts/package.json, pyproject.toml, src/vaara/__init__.py
Package versions bumped from 0.50.0 to 0.51.0.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • vaaraio/vaara#181: Introduces foundational records_paired() based on attestation back-link digest/nonce; this PR extends it with decision digest Check B binding.
  • vaaraio/vaara#167: Establishes execution-receipt schema with backLink back-references and OutcomeDerived fields; this PR adds decision_digest field to that schema and ties it to pairing validation.
  • vaaraio/vaara#185: Creates decision/outcome pairing conformance vector framework and independent checker; this PR updates both to enforce decision digest matching as Check B.

Poem

🐰 A digest of decisions, now bound to each call,
Sha256 canonicalized, no slip-ups at all!
Check A anchors receipts, Check B locks the choice—
When nonces tie equally, lexicography's voice.
Pairing grows stricter; the vectors, they test,
Supersession resolved: deterministically best.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: the implementation of SEP-2828 Check B (outcome-to-decision pairing) for version 0.51.0.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 feat/sep2828-check-b

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 and usage tips.

@vaaraio vaaraio merged commit 277d8d4 into main Jun 2, 2026
12 of 13 checks passed
@vaaraio vaaraio deleted the feat/sep2828-check-b branch June 2, 2026 05:41
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