release(v0.39.2): SEP-2787 v2 envelope with full wire round-trip, audit-event schema 1.0, Qi survey mapping#151
Conversation
…it-event schema 1.0, Qi survey mapping The four mechanical alignments Vaara committed to in modelcontextprotocol/modelcontextprotocol#2787 after the trust-surface grouping was incorporated into the SEP draft on soup-oss commit dd030d5b ship as the v2 envelope shape: 1. toolCalls lives under payloadDerived, not plannerDeclared. Tool bindings (name, server fingerprint, args commitment) are facts derived from the request payload, not planner declarations. 2. argsProjection serialises with a JSON-stringified projection field carrying the JCS-canonical encoding of the projection object. The digest is taken over those bytes. 3. The v1 kind-discriminated union is dropped. ArgsRef and ArgsProjection self-discriminate by which fields are present. 4. Commitment-only audit composes on ArgsProjection as a hash-only-identity projection of the form {"digest": "sha256:..."}. No separate ArgsDigest type ships in the spec. parse_attestation(d) is the new wire-decode entrypoint: inverse of Attestation.to_dict(). 13 new tests cover emit -> JCS bytes -> parse -> verify across HS256, ES256, RS256 for both ArgsRef and ArgsProjection, plus parse rejection on missing-field and unsupported-alg inputs and a byte-identical re-emit check. Two doc artefacts ship in the same release: - docs/audit_event_schema.md: AUDIT-EVENT-SCHEMA-1.0, versioned wire/storage contract for the audit events Vaara emits. Independent of code version so third-party consumers can pin without coupling to a Python runtime version. - docs/qi_survey_mapping.md: Vaara surface coverage against the taxonomy in Qi et al., Towards Trustworthy Agentic AI (arXiv:2605.23989, 2026-05-17). Direct, partial, and out-of-scope rows by Perceive / Plan / Act / Reflect / Learn / Multi-agent / Long-horizon stage under both top-level dimensions. SEP-2787 reference implementation tag sep2787-ref-v2 lands on this release commit alongside v0.39.2 for cross-repo provenance. The v0.40 slot stays reserved for the deployment-shape scope (HTTP transport, multi-tenancy schema, hot-reload extended, fan-out) per project_v040_roadmap_opa_frame_20260527.md.
📝 WalkthroughWalkthroughVersion 0.39.2 introduces SEP-2787 v2 attestation envelope specification. The core change refactors the args commitment model from a single ChangesSEP-2787 v2 Attestation Envelope Release
🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly Related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/vaara/attestation/_sep2787_types.py (1)
203-221: 💤 Low valueConsider validating
canonicalizationvalue inargs_from_dict.The
ArgsReftype restrictscanonicalizationtoLiteral["jcs"], butargs_from_dictaccepts any value from the wire without validation. A malformed envelope with"canonicalization": "cbor"would create anArgsRefinstance that violates the type constraint.🛡️ Proposed validation
def args_from_dict(d: dict[str, Any]) -> ArgsCommitment: if "ref" in d: if "digest" not in d: raise AttestationError("ArgsRef missing 'digest'") + canon = d.get("canonicalization", "jcs") + if canon != "jcs": + raise AttestationError(f"unsupported canonicalization {canon!r}") return ArgsRef( ref=d["ref"], digest=d["digest"], - canonicalization=d.get("canonicalization", "jcs"), + canonicalization=canon, )🤖 Prompt for 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. In `@src/vaara/attestation/_sep2787_types.py` around lines 203 - 221, The args_from_dict function currently accepts any canonicalization value from the input and then constructs an ArgsRef (which expects Literal["jcs"]); update args_from_dict to validate the canonicalization field when creating an ArgsRef: read canonicalization = d.get("canonicalization", "jcs") and if canonicalization != "jcs" raise AttestationError (e.g. "unsupported canonicalization: {value}") before returning ArgsRef(ref=..., digest=..., canonicalization=canonicalization) so only the allowed "jcs" value is accepted.
🤖 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.
Nitpick comments:
In `@src/vaara/attestation/_sep2787_types.py`:
- Around line 203-221: The args_from_dict function currently accepts any
canonicalization value from the input and then constructs an ArgsRef (which
expects Literal["jcs"]); update args_from_dict to validate the canonicalization
field when creating an ArgsRef: read canonicalization =
d.get("canonicalization", "jcs") and if canonicalization != "jcs" raise
AttestationError (e.g. "unsupported canonicalization: {value}") before returning
ArgsRef(ref=..., digest=..., canonicalization=canonicalization) so only the
allowed "jcs" value is accepted.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: c907bff3-3e3f-40f7-9041-16f019549e46
📒 Files selected for processing (18)
CHANGELOG.mdCOMPLIANCE.mdclients/ts/package.jsondocs/audit_event_schema.mddocs/qi_survey_mapping.mddocs/sep2787-overt-mapping.mdpyproject.tomlsrc/vaara/__init__.pysrc/vaara/attestation/__init__.pysrc/vaara/attestation/_sep2787_canonical.pysrc/vaara/attestation/_sep2787_emit.pysrc/vaara/attestation/_sep2787_types.pysrc/vaara/attestation/_sep2787_verifier.pysrc/vaara/attestation/sep2787.pytests/test_attestation_sep2787.pytests/test_attestation_sep2787_shape.pytests/test_attestation_sep2787_step5.pytests/test_attestation_sep2787_wire.py
Walker: - drop the kind-discriminated args handler; ArgsRef and ArgsProjection self-discriminate by present fields - tampered-case logic checks that the recanonicalised present body fails signature verification (canonical_signing_input.bin remains the pre-tamper canonical that the signature was computed over) - case 10 uses wall clock for TTL evaluation; expected.json no longer carries verify_at_epoch - case 12 renamed to args-commitment-missing-discriminator; flag toolCalls whose args carries neither ref nor projection README: - drop the proposed-shape framing; SEP text adopted trust-surface enveloping - describe the v2 args union without the kind discriminator - spell out the canonical_signing_input.bin convention for tampered cases so independent implementers do not re-trip the same surprise MANIFEST: - refresh bucket list to match the v2 case directories - provenance points at vaaraio/vaara@5ea7cd3, tag sep2787-ref-v2, merged via vaaraio/vaara#151 Walker smoke test: 6/6 normative positive + 3/3 normative negative + 4/4 verifier-policy negative.
Summary
SEP-2787 reference implementation lands the v2 envelope shape with
full wire round-trip. Two doc artefacts and one new public API
(
parse_attestation) ship in the same release.The four mechanical alignments Vaara committed to in
modelcontextprotocol/modelcontextprotocol#2787after thetrust-surface grouping was incorporated into the SEP draft on
soup-oss commit
dd030d5b:toolCallslives underpayloadDerived, notplannerDeclared.Tool bindings (name, server fingerprint, args commitment) are
facts derived from the request payload, not planner declarations.
argsProjectionserialises with a JSON-stringifiedprojectionfield carrying the JCS-canonical encoding of the projection
object. The digest is taken over those bytes.
kind-discriminated union is dropped.ArgsRefandArgsProjectionself-discriminate by which fields are present.ArgsProjectionas ahash-only-identity projection of the form
{"digest": "sha256:..."}. No separateArgsDigestships.Wire round-trip
parse_attestation(d)is the inverse ofAttestation.to_dict(). Itreconstructs the Python dataclass tree from a wire JSON dict so a
third-party consumer of the published v0 test vectors can parse,
verify, and re-emit envelopes byte-identically. Field-presence
validation and alg allowlisting happen on the boundary. 13 new tests
in
tests/test_attestation_sep2787_wire.pycoveremit -> JCS bytes -> parse -> verifyacross HS256, ES256, RS256 for bothArgsRefandArgsProjection, plus parse rejection on missing-field andunsupported-alg inputs and a byte-identical re-emit check.
Docs
docs/audit_event_schema.md: AUDIT-EVENT-SCHEMA-1.0, the versionedwire/storage contract for Vaara audit events. Versioned
independently of the Python package so third-party consumers can
pin to a schema version without coupling to a runtime version.
docs/qi_survey_mapping.md: Vaara surface coverage against thetaxonomy in Qi et al., Towards Trustworthy Agentic AI
(arXiv:2605.23989, 2026-05-17).
docs/sep2787-overt-mapping.mdfield table updated to v2.SEP-2787 reference implementation tags
sep2787-ref-v2(this release): v2 envelope shape with full wireround-trip.
sep2787-ref-v1(preserved ata61e87c): camelCase envelope.sep2787-ref-v0(preserved at3d7af54): snake_case envelope.The v0 test vectors at
vaaraio/modelcontextprotocol#2789will beregenerated against the v2 shape in a follow-up push to the
sep2787-v0-test-vectorsbranch, with a confirming comment underthe SEP draft at
modelcontextprotocol/modelcontextprotocol#2787.Test plan
ruff checkon changed Python pathspytest tests/test_attestation_sep2787*.py(47 tests pass:34 prior + 13 new wire tests)
pytestsuite in CIv0.39.2triggers Release workflow; PyPI + npm publishgh release view v0.39.2shows artefacts + Sigstore signaturespip install vaara==0.39.2andnpm view @vaara/client@0.39.2sep2787-ref-v2lands on the same release commitSummary by CodeRabbit
Release Notes – v0.39.2
New Features
parse_attestation()function for round-trip attestation parsing and verification.Documentation