spec: external execution evidence verification guidance (#34)#38
spec: external execution evidence verification guidance (#34)#38aryanputta wants to merge 2 commits into
Conversation
|
🟡 Contributor Check: MEDIUM
Automated check by AGT Contributor Check. |
imran-siddique
left a comment
There was a problem hiding this comment.
The scoping here is correct -- treating the receipt as evidence the Trust Record binds rather than a field the Trust Record carries is the right design. A few things need to be resolved before this can merge.
1. Broken internal reference: "steps 1-7 above" does not exist in this section
The closing paragraph says:
"the verification of steps 1-7 above is unchanged"
§3.3.1 defines exactly 2 steps. There are no steps 1-7 in this section. The §3.3 base verification protocol has 7 steps, but "above" in the context of §3.3.1 refers to this subsection. This will confuse any reader who tries to follow the reference. Either change "steps 1-7 above" to "the standard verification protocol in §3.3" (naming the actual section), or restructure the sentence to say explicitly that the gateway-produced record validation is unaffected.
2. "Canonical receipt" uses the word canonical without defining canonicalization
"Verifies the issuer signature over the canonical receipt (every field except
signature)"
TRACE uses JCS (RFC 8785, canonical JSON serialization) for the main record signing. Is JCS also the canonicalization for the receipt? If yes, state it explicitly. If the receipt uses a different byte representation for signing (e.g. sorted-key JSON without whitespace, or CBOR), define it here. A verifier implementing step 1 needs to know exactly what byte sequence to verify the signature over. "Every field except signature" is not sufficient without specifying the serialization.
3. No normative reference to the receipt schema
The receipt fields (issuer, issuer_key_id, signature, evidence_hash, evidence_type, linked_call_id) are named here but their types, formats, and constraints are defined in cMCP #301, not in this spec. A TRACE verifier implementing §3.3.1 cannot parse or verify a receipt without knowing the schema. Add a normative reference: something like "The receipt structure is defined in [cMCP audit spec, §X]" with a link or citation. Without it, §3.3.1 is non-implementable standalone.
4. Step 2 does not define how linked_call_id resolution works
"Checks
linked_call_idresolves to the audit entry it claims to bind"
This is underspecified. The Trust Record commits the audit chain via tool_transcript.hash. A verifier needs to: (a) obtain the audit chain, (b) locate the entry whose call_id equals linked_call_id. Step 2 should say something like: "Confirms that the audit chain committed by tool_transcript.hash contains an entry with call_id equal to linked_call_id." Without this, "resolves" is ambiguous about where the verifier looks and how.
5. No failure behavior defined
The base §3.3 protocol specifies what happens when verification fails. §3.3.1 defines when to verify and what to check, but says nothing about what a verifier MUST or SHOULD do when step 1 or step 2 fails. Should it mark the external evidence invalid while keeping the Trust Record valid? Should it fail the entire record? Return a structured error status alongside the main verification result? Specify at minimum whether a step 1 or step 2 failure affects the validity of the enclosing Trust Record.
6. CHANGELOG conflict with #37
Both PRs add a new ## [Unreleased] block at the same position in CHANGELOG.md. This will conflict on merge. This PR should rebase on #37 and merge its changelog entry into the single [Unreleased] block.
7. __pycache__ files committed
Same issue as #37 -- binary .pyc files in the diff. Add __pycache__/ to .gitignore and amend.
Issues 1, 2, 3, and 5 are correctness or implementability issues -- a verifier author cannot implement §3.3.1 correctly from this text alone. 4 is a precision gap. 6 and 7 are mechanical. Address 1-5 before requesting re-review.
imran-siddique
left a comment
There was a problem hiding this comment.
The scoping here is right - framing external execution evidence as "TRACE binds evidence; it does not assert that a physical action occurred" keeps the spec honest about what the TEE can and cannot prove. A few things to address:
Compiled bytecode files
Same issue as PR #37: src/agentrust_trace/__pycache__/*.pyc and tests/__pycache__/*.pyc are included. Strip these before merge. (If you fix .gitignore in #37 first, make sure the fix is rebased into this branch too so it does not reappear here.)
Broken cross-reference
§3.3.1 ends with: "verification of steps 1-7 above is unchanged." §3.3 does not have numbered steps. This reference is broken. Either add explicit numbered steps to §3.3 or replace "steps 1-7" with a concrete reference to what is unchanged.
"Canonical receipt" is undefined
The spec says verifiers should "verify the issuer signature over the canonical receipt (every field except signature)". What is the canonicalization algorithm? Is this RFC 8785 (JCS)? Alphabetically sorted JSON? Something custom? Without a defined canonicalization, two compliant implementations will produce different byte strings and one will reject signatures the other accepts. This needs a normative definition (even a one-liner pointing to RFC 8785 would be sufficient if that is the intended algorithm).
evidence_hash pre-image is still undefined
The guidance describes verifying the issuer signature over "the canonical receipt" but does not specify what bytes produce evidence_hash. The cMCP audit entry schema defines evidence_hash as a "hash of the evidence" without further specification. For a TRACE-level spec to be useful, it needs to say what is hashed, in what encoding, with what canonicalization. Otherwise evidence_hash is an opaque blob that implementers cannot independently reproduce.
Interaction with TRACE's audit chain commitment
The spec notes the receipt "lives on the cMCP audit entry, inside the audit chain the Trust Record already commits to." That is correct. But §3.3.1 does not say how a verifier locates the relevant audit entry given a linked_call_id. The Trust Record carries audit_chain_tip and audit_chain_root but not the full chain. Does the verifier need the exported audit bundle? If so, say so. If the receipt is meaningful without the bundle, say that instead.
Add an OPTIONAL agent block (agent_id, manifest_id, binding) distinct from subject so the manifest-to-session binding (cMCP #302) is verifiable offline. subject still identifies the gateway session; records without the block stay valid. Adds the offline agent-identity cross-check to the verification protocol. Review feedback (imran-siddique): - agent block now requires agent_id + manifest_id when present (no empty/partial blocks); binding is optional and informational only, with a registered value set (svid-matched, manifest-presented, operator-asserted) verifiers MUST NOT base trust on. - manifest_id documented format-agnostic (byte-equal comparison). - catalog-hash half of the cross-check marked a future extension (no v0.1 field); tracked as §7 open questions plus the binding registry. - documented canonical block vs profile addenda: cMCP carries richer evidence (issuer, hashes, authenticated_subject) in gateway.agent_identity; the canonical block is the portable subset every TRACE verifier relies on. - subject == agent.agent_id explicitly permitted. - synced the packaged schema (src/agentrust_trace/schema/trace-v0.1.json) that validate() actually uses, in addition to schema/trace-claim.json. - added examples/agent-bound-tdx.json and a positive DID acceptance test. - added .gitignore; no bytecode committed. 47 tests pass; ruff clean. Signed-off-by: Aryan Putta <aryansputta@gmail.com>
Describe how a verifier treats a controller-signed receipt attached to a cMCP audit entry (cMCP #301). No Trust Record wire-format change; the receipt lives on the audit entry the Trust Record already commits via tool_transcript.hash. Review feedback (imran-siddique): - replaced the broken 'steps 1-7 above' reference with an explicit pointer to the §3.3 protocol (steps 1-7), which is what stays unchanged. - defined the receipt canonicalization as RFC 8785 (JCS), matching §3.2.2. - added a normative pointer: the receipt fields/formats are defined by the cMCP audit-entry schema (#301), not by TRACE. - specified evidence_hash is an opaque issuer-defined digest committed by the signature; TRACE does not recompute its pre-image (stays within §2.4 scope). - specified linked_call_id resolution against the exported audit bundle (/audit/export) for the chain committed by tool_transcript.hash. - defined failure behavior: receipt verification result is separate from the Trust Record verdict; a failed receipt is invalid but does not by itself reject the gateway-produced record. Rebased on #33 so .gitignore carries over and the CHANGELOG shares one [Unreleased] block. 47 tests pass; ruff clean. Signed-off-by: Aryan Putta <aryansputta@gmail.com>
eda1ceb to
895ae98
Compare
|
Thanks — addressed all points; force-pushed clean (rebased on #37).
|
Closes #34.
Problem
cMCP #301 (Option A, confirmed) adds an optional external execution evidence receipt to a cMCP audit entry: an independent authority (e.g. a safety controller) signs an assertion about a specific call (
issuer,issuer_key_id,signature,evidence_hash,evidence_type,linked_call_id), bound bylinked_call_idto the entrycall_id.cmcp-verifychecks the receipt when configured with the issuer trusted key. TRACE should describe how a verifier treats such evidence so the spec and cmcp-verify stay aligned.Change
Adds §3.3.1 External execution evidence (OPTIONAL) under Verification:
signature) and checkslinked_call_idagainst the bound entry.Compatibility
Backward compatible: guidance plus optional verification, no Trust Record format change. The receipt lives on the cMCP audit entry, within the audit chain the Trust Record already commits, so no schema or model change is needed. Affects Level 1+ optionally; existing conformance tests unaffected.
DCO signed-off. 37/37 tests pass locally.