| Internet-Draft | evidence.* family | July 2026 |
| Msebenzi | Expires 29 January 2027 | [Page] |
Autonomous agents act through tool invocations whose consequences outlive the sessions that produce them. Pre-action constraint families gate whether an agent may act: environment.* attests boolean world-state, and verification.* attests calibrated confidence over factual claims. No sibling family records, under equivalent verification discipline, what the agent then did. This document defines the evidence.* family: append-only, hash-chained, signature-bound evidence records of agent actions, designed so that a third party can recompute every verdict from signed primitives and a published key, without trusting the operator's runtime. It defines the family's membership criterion (independent recomputability with fail-closed verification), the family-wide record vocabulary and canonicalization discipline, a tri-state verification protocol (VALID, INVALID, UNVERIFIABLE), composition with the pre-action sibling families, and the conformance-vector discipline under which independent implementations demonstrate byte-level agreement. One reference record type, evidence.action, is specified together with its frozen conformance corpus. This document deliberately states what an evidence record does not prove.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 29 January 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
An autonomous agent that is permitted to act leaves consequences behind. The tool invocation completes, the file is written, the payment settles, the downstream system changes state — and the session that produced the invocation ends. What remains is whatever the operator chose to keep.¶
Two constraint families already address the moment before the action. The environment.* family [ENV-STATE] attests boolean world-state and gates execution unconditionally on the result. The verification.* family [VERIFICATION-STATE] attests calibrated confidence over a factual claim and derives a binary act/halt gate from it. Both are pre-action, both are fail-closed, and both are recomputable by a relying party that never trusts the issuer's runtime.¶
Neither records what the agent then did. The three-leg spine is: a pre-action gate decides, an action occurs, and a post-hoc evidence record commits to what occurred. The third leg is the one that is missing, and the gap is felt in the same register the sibling families named for their own domains. Post-action evidence today is fragmented across operator logs (unverifiable), platform audit chains (operator-controlled), and settlement receipts (payment-only). Each of the three is real infrastructure; none of the three lets a third party recompute, from published bytes alone, what a specific agent action committed to.¶
The gap is felt outside this document. In the x402-foundation public issue tracker, issue 2332 is titled "Post-settlement accountability layer: tamper-evident proof of agent action after payment" (https://github.com/x402-foundation/x402/issues/2332), with related discussion at issue 2291 on fulfillment obligations (https://github.com/x402-foundation/x402/issues/2291) and issue 2357 on independently verifiable receipts carried in the payment response (https://github.com/x402-foundation/x402/issues/2357). The shape of the problem raised there is general: an artifact can prove that value moved and still say nothing a third party can check about what was done for it. This document cites the discussion for the shape of the gap, not for any specific protocol, vendor, or field.¶
[ENV-STATE], Section 3.6 sanctions additional constraint families defined under the same family-definition discipline, with their own namespaces, membership criteria, and per-family vocabularies. [VERIFICATION-STATE] demonstrated that pattern by defining a sibling family rather than a member entry. This document completes the third leg by applying the same discipline to the post-action position.¶
The evidence.* family differs from both pre-action siblings in one structural respect that the rest of this document follows from: an evidence record does not gate anything. It is not a constraint. Its verification produces a verdict about the record, not a permission about an action. What it inherits from the siblings is the discipline — deterministic canonicalization, signed primitives, a published key, and a failure mode that never resolves in favour of acceptance.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP14] (RFC2119) (RFC8174) when, and only when, they appear in all capitals, as shown here.¶
In scope:¶
The membership criterion for the evidence.* family.¶
The family-wide record vocabulary and canonicalization discipline.¶
One reference record type, evidence.action, specified field by field.¶
The tri-state verification protocol a verifier executes.¶
Composition with the pre-action sibling families.¶
The conformance-vector discipline under which independent implementations demonstrate byte-level agreement.¶
Out of scope:¶
Signing-key management policy beyond the discipline of Section 9.¶
Retention, storage, indexing, and discovery of chain files.¶
Transport of records between parties.¶
Any claim about which model, prompt, or software produced an action (Section 8).¶
Normative specification of the payment-reference binding sketched informatively in Section 7.¶
Record — A single signed evidence record: a JSON object whose members are covered by an issuer signature, minus the signature member itself.¶
Record content — The record object with the signature member removed. All canonicalization, hashing, and signing in this family operate on record content, never on the signed record.¶
Session — The scope within which records are chained. Records carry a session identifier, and chaining is defined within a single session.¶
Chain — An ordered sequence of records for one session in which the record at position i+1 references the entry hash of the record at position i.¶
Entry hash — The hash of the canonical bytes of a record's content, used as the chain link. Its exact construction is specified in Section 4.4.¶
Genesis — The synthetic predecessor value used as the chain link for the first record of a session, derived from a domain-separated preimage rather than from a constant sentinel. Specified in Section 4.4.¶
Issuer — The party that signs records. In this family the issuer is the operator of the runtime that produced the action, not a third party (Section 8).¶
Verifier — The party that recomputes a chain from the records and a resolved public key, and emits a verdict. A verifier consumes only the record bytes and the key; it never queries the issuer's runtime.¶
Thumbprint — The JWK thumbprint [RFC7638] of the issuer's signing key, committed inside the signed bytes and recomputed by the verifier from the key it resolved.¶
Verdict — The terminal output of verification: one of VALID, INVALID, or UNVERIFIABLE (Section 5).¶
Strict ingest — The parse profile under which candidate record bytes are accepted or rejected before any hash is computed over them (Section 4.6).¶
[VERIFICATION-STATE], Section 3.1 presents a two-column comparison of the environment.* and verification.* families. The following table extends that comparison with the post-action column this document defines.¶
| Property | environment.* | verification.* | evidence.* |
|---|---|---|---|
| Temporal position | pre-action | pre-action | post-action |
| Predicate | boolean world-state | probabilistic claim-confidence in [0,1] | none: record of what occurred |
| Gate shape | binary halt | binary halt | none: verification verdict is tri-state |
| Failure discipline | fail-closed at execution | fail-closed at execution | fail-closed at verification |
| Attested object | state of the world | confidence over a claim | the action: tool, arguments, result, decision |
| Threshold ownership | oracle-defined, fixed-semantic | calibration-anchored, mapping-versioned | none |
| Chaining | none | none | per-session append-only hash chain |
The pre-action families are fail-closed about acting: uncertainty halts execution. The evidence.* family is fail-closed about believing: uncertainty halts acceptance of the record. The three families meet at the same design intent — ambiguity never resolves in favor of proceeding, whether the proceeding is an action or the acceptance of a claim about one.¶
The split is structural rather than editorial. A pre-action family owns a threshold and derives a permission from it; the evidence.* family owns neither. What carries across all three is the verification model: deterministic canonicalization, primitives inside the signed bytes, a key resolved from a published location, and local recomputation by a party that trusts no runtime.¶
The membership criterion of the evidence.* family is that a record type's verification MUST be independently recomputable and fail-closed. A record type satisfies this criterion if and only if: (1) every field that contributes to a verification verdict is covered by the issuer's signature; (2) the signed bytes are produced under a deterministic canonicalization that an independent implementation can reproduce byte-for-byte from the record's members — for this family, the JSON Canonicalization Scheme [RFC8785]; (3) records within a session are bound into an append-only hash chain such that removal, insertion, or reordering of any record is detectable from the records alone; and (4) a verifier that cannot complete recomputation — an unresolvable key, a failed canonicalization, a broken chain, a malformed member — MUST return UNVERIFIABLE and MUST NOT report the record as valid. A record type whose verification requires trusting the issuer's runtime, whose signed bytes cannot be independently reproduced, or whose verification degrades to acceptance on failure is outside this family regardless of how it is named.¶
As with the pre-action families, the criterion is not a per-type design choice made while a type is being drafted. A record type specification author MUST establish all four properties before proposing the type for the family, and a proposed type that does not demonstrably satisfy all four MUST be rejected from the family on that ground alone.¶
Family members are named under the evidence.* namespace using dot notation. The first component of the type identifier is the literal string evidence; the second component identifies the kind of occurrence the record type commits to; further components may be used by future revisions for sub-classification.¶
The record type specified by this document is evidence.action. Its version token is carried inside the record and is distinct from the type identifier; version-token discipline is specified in Section 4.2.¶
A record type specification author SHOULD choose a second component that names the kind of occurrence recorded (for example, action) rather than the implementation, the issuer, or the wire format. IANA MUST NOT register a type identifier within the evidence.* namespace whose specification does not satisfy the membership criterion of Section 3.2. The namespace and the criterion are coupled deliberately: a verifier encountering an evidence.* identifier relies on the family's discipline holding for that type, and a namespace that admitted non-conforming types would defeat that reliance.¶
A record type specification author MAY propose a new evidence.* record type by publishing a specification that:¶
(1) demonstrates that the proposed type satisfies all four properties of the membership criterion of Section 3.2;¶
(2) specifies the trust-root mechanism under which a verifier discovers the issuer's signing key, including how the key is bound to an issuer identity and how rotation is handled;¶
(3) specifies a verification algorithm whose terminal states are exactly VALID, INVALID, and UNVERIFIABLE, with no other terminal state and no path from a recomputation failure to VALID;¶
(4) declares every signed member the type adds to the family-wide vocabulary of Section 4.2, and states for each whether it contributes to a verdict;¶
(5) declares the type's MUST-implement signing algorithm and any SHOULD-implement or MAY-implement extension set, under the agility framework of Section 4.5;¶
(6) publishes, under the corpus discipline of Appendix A of this document, a frozen conformance corpus that includes at least one vector whose expected verdict is a rejection; and¶
(7) conforms to the register discipline of [ENV-STATE], Section 6 throughout.¶
These seven requirements correspond to the Expert Review criteria of Section 10.3. A specification missing any requirement is not conforming, and the proposed type MUST NOT be registered until the gap is closed.¶
This section specifies the vocabulary shared by every evidence.* record type and then specifies the reference record type, evidence.action, member by member. The member names, value spaces, and derivations given here are those of the reference implementation described in Appendix B; this document does not introduce members that no implementation carries.¶
Every hash and every signature preimage in this family is produced from the JSON Canonicalization Scheme [RFC8785]. Implementations of an evidence.* record type MUST apply JCS at every point where bytes are hashed or signed, and MUST NOT substitute any other serialization at any such point.¶
The requirement is load-bearing rather than stylistic. Recomputability is the family's membership criterion, and a non-canonical serializer — one whose object member order, whitespace, or number formatting varies by implementation — makes the same logical value hash differently in the issuer and in the verifier. That divergence appears exactly at the point where the commitment is supposed to be reproducible.¶
For the evidence.action record type, JCS is applied at four points:¶
record content, to derive the entry hash;¶
record content, to derive the signature preimage;¶
the request descriptor, to derive the request commitment;¶
an event's raw arguments value and raw result value, to derive the arguments hash and result hash.¶
The hash function at every one of those points is SHA-256, and every hash value in a record is carried as the string "sha256:" followed by the lowercase hexadecimal digest.¶
The following members appear, with identical semantics, on every evidence.* record.¶
v — string, required. The record's version token. The token identifies the record type and its wire revision together; it is not the IANA type identifier. For evidence.action the defined tokens are "evidence.action/0" and "evidence.action/1". A verifier MUST reject a record whose version token it does not support, and MUST NOT attempt verification under a different version's rules.¶
seq — number, required. The record's zero-based position within its session's chain.¶
session_id — string, required. The identifier of the session the record belongs to. Chaining is defined within one session_id.¶
ts — string, required. The record's issuance time. The reference implementation writes an ISO 8601 date-time in UTC. The only property a verifier checks over ts is non-regression within a bounded skew (Section 5.1); ts is not a trust anchor (Section 9.5).¶
prev_hash — string, required. The chain link: the entry hash of the preceding record in the session, or the genesis value for seq 0 (Section 4.4).¶
kid — string, required. The identifier of the key the record was signed under, as published in the issuer's key set.¶
key_thumbprint — string, required on "evidence.action/1", absent on "evidence.action/0". The JWK thumbprint [RFC7638] of the signing key. It is inside the signed bytes, and a verifier MUST compare it to the thumbprint of the key it actually resolved before checking the signature (Section 5.1). A record at version "evidence.action/1" that omits this member is malformed, and a verifier MUST NOT verify it.¶
iss — string, optional on "evidence.action/1", absent on "evidence.action/0". The issuer identifier. It is informational: the cryptographic binding is carried by key_thumbprint, and iss is inside the signed bytes so that it cannot be rewritten after signing.¶
jwks_uri — string, optional. An HTTPS URL naming where the signing key for this record is published as a JWK Set [RFC7517]. Because it is inside the signed bytes, it is the signer committing to a publication location rather than a rewritable hint. A verifier MUST reject a record whose jwks_uri is present and is not an HTTPS URL (Section 5.1), and MUST apply the fetch restrictions of Section 9.4 when resolving it.¶
sig — string, required. The signature over the canonical bytes of the record content, encoded base64url without padding. sig is the one member of a record that is not part of record content, and therefore not part of any preimage.¶
Absence and null are distinct under JCS: an absent member does not appear in the canonical bytes at all, while a member whose value is null does. A record type specification author who adds an optional member MUST specify that the member is omitted when it carries no value, and MUST NOT specify a null placeholder, because the two forms produce different canonical bytes and therefore different hashes.¶
An evidence.action record commits to one dispatched action. Beyond the family-wide members of Section 4.2, it carries the following.¶
Object, required. Two string members, vendor and version, naming the software that produced the record. This is a self-description by the issuer's runtime and carries no cryptographic weight; Section 8 states what it does not establish.¶
Object, required. The action itself, discriminated by a type member. Five event types are defined:¶
shell — members: type, outcome, argv (array of strings), cwd (string), and optionally exit_code (number), command (string) or command_hash (string), decision, decision_source. An implementation writes at most one of command and command_hash.¶
file_edit — members: type, outcome, path (string), content_hash (string), and optionally prev_content_hash (string), bytes (number). The record carries the hash of the new content, never the content.¶
file_read — members: type, outcome, path (string), and optionally content_hash (string).¶
tool_call — members: type, outcome, tool_name (string), args_hash (string), and optionally result_hash (string), decision, decision_source.¶
mcp_call — members: type, outcome, server (string), tool_name (string), args_hash (string), and optionally result_hash (string), decision, decision_source.¶
outcome is required on every event and takes one of five values: executed (the action ran to completion), blocked (a gate stopped it before dispatch), denied (a policy or human refused it before dispatch), errored (it ran and threw), timed_out (it exceeded its time budget). An implementation MUST record blocked, denied, errored, and timed_out outcomes as well as executed ones: a chain that carries only successes is survivorship-biased and cannot show that a gate ever fired.¶
decision takes one of allow, deny, ask, observed.¶
decision_source names the disposition that produced the decision. The values defined by the reference implementation are user, config, hook, and n/a. The format additionally defines fail-closed, which names the case where no actor reached a decision, the policy could not determine an answer, and the safe default fired. The distinction between config (an explicit rule matched and denied) and fail-closed (the safe default fired) is carried in the signed bytes, and a verifier that surfaces a halt cause MUST take decision_source as the primary signal for it. Appendix B states which of these values the reference implementation emits today.¶
args_hash and result_hash are SHA-256 over the JCS canonical bytes of the raw arguments value and the raw result value respectively. They are hashes of values, not of a serializer's output: the same logical arguments presented in a different member order produce byte-identical hashes.¶
String, required, present on every record. It is SHA-256 over the JCS canonical bytes of the record's request descriptor. The request descriptor is a closed object derived from the event by a pure function that reads only the members that constitute the action's identity, and never reads outcome, timing, environment, or any other post-dispatch value:¶
shell: class, argv, cwd¶
file_edit: class, path, content_hash¶
file_read: class, path¶
tool_call: class, tool, args_hash¶
mcp_call: class, server, tool, args_hash¶
A descriptor member name is not required to equal the name of the event member it derives from: the tool_call and mcp_call descriptors carry the action's tool identifier under the member name tool, derived from the event member tool_name of Section 4.3.2, and the two names denote the same identifier at their respective layers.¶
The descriptor's member set per class is closed. A record type specification author MUST NOT add members to a defined descriptor class, because the descriptor is the canonical identity a pre-action gate and a post-action recorder are compared on, and an open member set makes that comparison implementation-specific.¶
Object or null, required. When null, the record asserts no upstream authorization binding: the recorder observed the action without a gate having authorized it through this binding. When present, the object carries four members:¶
request_commitment (string) — MUST equal the record's top-level request_commitment. This equality is the continuity invariant: it is what makes "the request the gate authorized" and "the request the recorder observed" the same bytes.¶
gate_receipt (string) — a reference to the pre-action authorization the gate produced. Section 6.3 states the current limit of this member.¶
gate_family (string) — one of environment, verification, permit, naming the class of check the gate ran.¶
result (string) — one of act, halt.¶
gate_family names the class of check; decision_source names the disposition. The two compose orthogonally, and a verifier MUST NOT infer the cause of a halt from gate_family alone.¶
For the record at seq 0, prev_hash MUST equal:¶
"sha256:" + hex(SHA-256(JCS({
"v": <the record's version token>,
"session_id": <the record's session_id>,
"marker": "genesis"
})))
¶
The JCS object form is required so that member boundaries are unambiguous. A separator-less concatenation of the version token, the session identifier, and a literal marker is non-conforming: it permits cross-session splicing, because a version token of "x/0" with a session identifier of "123" concatenates to the same bytes as a version token of "x/01" with a session identifier of "23".¶
The version token is part of the genesis preimage. A verifier MUST recompute genesis using the version token carried by the record that opened the chain, not the version token the verifier itself writes, so that a chain opened under an earlier version still links.¶
For every record, the entry hash is:¶
"sha256:" + hex(SHA-256(JCS(record_content)))¶
where record_content is the record object with sig removed.¶
Stripping sig from the preimage is deliberate. It makes the entry hash insensitive to signature encoding: a re-encoded signature over identical content would otherwise produce a different entry hash and break the chain at precisely the moment when encoding variation makes verification hardest. The entry hash is a commitment to content; signature checking is a separate, independent step against a resolved key.¶
A chain file MAY carry a trailing checkpoint: a separately signed object whose members are the version token, a type member with the value "checkpoint", the session identifier, a count of records, the entry hash of the last record, a timestamp, and the key identifier. It is signed the same way a record is: Ed25519 over the JCS canonical bytes of its content.¶
When a checkpoint is present, a verifier MUST check that its count equals the number of records, that its last entry hash equals the entry hash the verifier computed for the final record, and that its signature verifies. A checkpoint failure is a chain failure.¶
An evidence.action signature is Ed25519 computed directly over the JCS canonical bytes of the record content. The signature value is encoded base64url without padding.¶
The algorithm identifier and the key representation are those of the JOSE algorithm registration for Edwards-curve signatures [RFC8037], and the signature is a detached signature over canonical bytes rather than a JWS [RFC7515] compact or JSON serialization. An implementation MUST NOT treat an evidence.action record as a JWS object; the signing input is the canonical bytes themselves, with no encoded header and no period-delimited signing input.¶
Ed25519 signatures are deterministic [RFC8032]: the same key over the same message produces the same signature bytes. An implementation MUST NOT introduce nonce or salt material into the signing path, because byte parity of signatures across independent implementations is one of the properties the conformance corpus of Appendix A exists to demonstrate.¶
Following the agility discipline of [ENV-STATE], Section 4.3, algorithm choice is a per-type concern. This document declares Ed25519 as the MUST-implement signing algorithm for evidence.action and declares no SHOULD-implement or MAY-implement extension set. A verifier MUST reject a record whose declared algorithm is not in the supported set for the record type; this rejection is fail-closed and is not a permitted silent downgrade.¶
A specification defining a successor record type MUST declare its own MUST-implement algorithm explicitly, and SHOULD specify the conditions under which the current MUST-implement is deprecated, the migration timeline for verifiers, and the backward-compatibility guarantee during the transition. The family-layer obligation is structural: the choice is made per type, declared explicitly, and honoured by verifiers without fallback.¶
A verifier MUST parse candidate record bytes under a strict profile before computing any hash over them. The strict profile rejects:¶
a duplicate member name within any object, at any nesting depth; and¶
any numeric member whose value does not round-trip losslessly as a finite IEEE 754 double-precision value.¶
A verifier MUST treat a strict-profile violation as a terminal parse failure and MUST NOT fall back to hashing the bytes it could not accept. The corresponding verdict is UNVERIFIABLE (Section 5.1).¶
The reason both rules are normative is recomputability rather than hygiene. A permissive parser resolves duplicate member names last-wins, so the bytes an issuer canonicalized and the bytes a verifier reconstructs from the same source text can differ while both parsers report success. A permissive parser also converts a numeric literal outside the exactly-representable range into a nearby representable value without signalling, so a value that entered the issuer's preimage is not the value that enters the verifier's. Both failures land precisely on the commitment that is supposed to be reproducible.¶
The round-trip formulation is deliberately broader than an integer range check. An integer literal whose magnitude exceeds the exactly-representable range fails the round-trip test, and so does a literal whose exponent overflows to a non-finite value. Pinning the rule to round-trip behaviour rather than to token shape is what makes independent implementations reject the identical set: two implementations that each apply their own notion of "too large" would agree on the common cases and diverge on the edges, and a corpus rejection vector would then be conformance-checkable in one implementation and not the other. Appendix B states which part of this rule the reference implementation currently enforces.¶
A verifier given a chain file and a key source MUST execute the following sequence and MUST stop at the first failure. Verdicts are named in Section 5.2.¶
Parse under strict ingest. Parse every line of the chain file under the strict profile of Section 4.6. A violation yields UNVERIFIABLE.¶
Resolve the key. Resolve the key named by the records' key identifier from the applicable key source. Where the source is a published key set, apply the fetch restrictions of Section 9.4. A key that cannot be resolved — an unreachable publication location, a malformed key set, no key under the named identifier, more than one key under the named identifier — yields UNVERIFIABLE. A verifier MUST NOT fall back to a different key source when the higher-precedence source is present but unresolvable, because such a fallback converts an unresolvable key into a verifiable one under a key the record did not name.¶
Check the committed publication location. If a record carries jwks_uri and it is not an HTTPS URL, the verdict is INVALID: the signer committed, inside the signed bytes, to a publication location a verifier must refuse to fetch.¶
Check the key binding. For a record at a version that carries key_thumbprint, recompute the thumbprint [RFC7638] of the key resolved in step 2 and compare it to the committed value. A mismatch, or an absent key_thumbprint at a version that requires it, yields INVALID. This check precedes signature verification: a verifier that checked the signature first would let a key substituted at the publication location pass by verifying under itself.¶
Check sequence. The record's seq MUST equal its zero-based position in the file. A mismatch yields UNVERIFIABLE.¶
Recompute canonical bytes. Strip sig, canonicalize the content under JCS, and derive the entry hash. A canonicalization that cannot be completed yields UNVERIFIABLE.¶
Recompute the chain link. For seq 0, the record's prev_hash MUST equal the genesis value of Section 4.4.1 computed from the record's own version token and session identifier. For every later record, prev_hash MUST equal the entry hash computed in step 6 for the preceding record. Any break yields UNVERIFIABLE.¶
Recompute the request commitment. Rebuild the request descriptor from the recorded event and hash it. A mismatch against the record's request_commitment yields UNVERIFIABLE: the recorded action does not match its own committed identity.¶
Verify the signature. Verify the signature over the canonical bytes from step 6 under the key resolved in step 2. A signature that does not verify against a resolved, published key yields INVALID.¶
Check timestamp non-regression. The record's ts MUST NOT precede the highest ts seen so far by more than the verifier's configured skew bound. A regression beyond the bound yields UNVERIFIABLE.¶
Verify the checkpoint, if present. Apply Section 4.4.3. A checkpoint failure yields UNVERIFIABLE.¶
Emit VALID. Only a chain that reaches this step without a failure is VALID.¶
An empty chain file is not VALID. A verifier MUST NOT report VALID for a file that carries no records.¶
A verifier that reports VALID MUST also report which key the chain verified under and where that key was resolved from. Without a caller-supplied pin, VALID means that the chain is internally consistent under the key that was presented, not that it was signed by any particular party; naming the key and its origin is what keeps that distinction visible to the consumer.¶
VALID — Every check of Section 5.1 completed and passed. The chain is intact, the signatures verify under the resolved key, and the key matches the identity the records committed to.¶
INVALID — The verifier resolved a key and a cryptographic binding failed against it: the committed thumbprint did not match the resolved key, the signature did not verify, the resolved key was not in a caller-supplied pinned set, or the record committed to a publication location that must not be fetched.¶
UNVERIFIABLE — The verifier could not complete recomputation: the key could not be resolved, the bytes could not be accepted under strict ingest, the canonicalization could not be reproduced, the chain did not link, the request commitment did not recompute, or a member was malformed.¶
INVALID and UNVERIFIABLE are distinct verdicts, and a verifier MUST NOT collapse them into one. They answer different questions for a consumer: INVALID says "a key was reached and the record failed against it," and UNVERIFIABLE says "no answer could be established." A consumer that cannot tell the two apart cannot tell a rewritten record from an unreachable key, and the remedies for those two states are not the same.¶
Only VALID exits success. A verifier MUST signal failure for both INVALID and UNVERIFIABLE through whatever mechanism its interface uses for failure, and MUST NOT provide a mode in which either verdict is reported as VALID.¶
The three verdicts of Section 5.2 are the family's interoperable vocabulary. An implementation MAY report a finer-grained result alongside the verdict — for example, distinguishing a linkage break from a request-commitment mismatch, or naming which trust check failed — provided every finer-grained result maps onto exactly one of the three verdicts and the mapping is published. Appendix B records the mapping for the reference implementation, whose result vocabulary is finer than three and whose classification of one case differs from the classification this section specifies.¶
An evidence.* record does not gate execution and does not satisfy the membership criterion of the environment.* family [ENV-STATE], Section 3.2: its failure mode is not gating, because it has no execution to gate. The families compose without overlapping. An implementation MUST NOT treat an evidence.* record as a constraint instance, and MUST NOT allow the presence, absence, or verdict of an evidence.* record to influence a pre-action gate decision.¶
The ordering the pre-action families specify among themselves is unaffected by this document. [VERIFICATION-STATE], Section 3.2 requires environment.* constraints to short-circuit before verification.* constraints, and [ENV-STATE], Section 5.5 makes an environment.* halt final. Recording happens after that ordering has run to its terminal state, so an evidence.* record cannot preempt, mask, or re-order any pre-action evaluation.¶
An implementation MUST surface a failure to record. Recording is evidence-producing rather than execution-gating, so a silently dropped record is indistinguishable, later, from an action that never happened — which is exactly the survivorship bias the outcome vocabulary of Section 4.3.2 exists to prevent.¶
Whether a recording failure also halts the deployment is a deployment policy decision, not a property of this family. Both postures are coherent and both are observed in practice: a purely observational deployment logs the failure and permits the action to proceed, while a deployment that treats un-recorded effects as unacceptable withholds the result from the agent so that the agent does not act on an un-recorded outcome. This document requires only that neither posture may swallow the failure.¶
The gate member of Section 4.3.4 carries gate_receipt, a reference to the pre-action authorization that permitted the action. The intent of the member is the end-to-end property: a verifier resolves gate_receipt to the pre-action receipt, and checks that the pre-action receipt's own request commitment equals the request commitment carried in the record's gate object, so that "what was authorized" and "what was recorded" are the same bytes across the two families.¶
That end-to-end resolution is not implemented. In the reference implementation, gate_receipt is self-anchored: it carries the record's own entry hash, which a verifier can recompute but which references nothing upstream. The member is therefore format-ahead-of-implementation, and this document states it as such rather than describing the intended property as an available one. An implementer MUST NOT infer from the presence of gate_receipt that any deployed recorder today resolves it to an upstream pre-action receipt. The status is recorded in Appendix B of this document.¶
A future revision of this document may specify the resolution rule normatively. It is deliberately not specified here, because the rule would bind two independently versioned families together and the binding has not been exercised end-to-end.¶
This section is informative.¶
A specification published alongside the reference implementation defines an optional payment-reference binding: a single optional top-level signed member, carrying a hash commitment to a selected, non-sensitive subset of a settlement artifact. The member would sit inside the signed bytes, so that the operator commits to it and cannot rewrite it after signing. Its intent is to make one question machine-checkable that a settlement artifact alone cannot answer: whether the operator committed to any output for a settled payment at all.¶
The binding is governed by a normative per-scheme mapping registry rather than by a field list alone. Two implementations can agree byte-for-byte on canonicalization and still produce non-comparable commitments if they read different source fields into the same subset member, so the mapping from a scheme's wire fields to the committed subset is part of the contract. The registry fails closed: an implementation emits no commitment for a scheme, network, and facilitator combination whose mapping row has not been confirmed against real observed output, and a row derived from documentation alone does not authorize emission.¶
Normative specification of the binding is deferred to a future revision of this document, pending observed-bytes verification of the target scheme. The motivating ecosystem is x402; no scheme mapping is confirmed at the time of writing, and this document therefore specifies no member name as normative, no value space, and no scheme identifier.¶
Section 8 applies to this binding without modification. A payment reference binds a record to a settlement artifact; it does not establish that anything was delivered or accepted.¶
This section enumerates, explicitly, what an evidence.* record is not and what it does not prove, to prevent conflation with adjacent primitives.¶
Not proof of model identity. An evidence record binds a tool identifier, an arguments hash, a result hash, a decision, and a signer. It carries no claim about which model, prompt, or software produced the action, and no such claim can be derived from it.¶
Not proof of output correctness, usefulness, or safety. A record proves that the operator committed, recomputably, to what occurred. An operator can honestly record an incorrect, useless, or harmful result; the record makes the commitment verifiable, not the content good.¶
Not a neutral third-party attestation. Records are operator-signed. The recomputability discipline narrows what a dishonest operator can do — any alteration of signed members is detectable by a verifier holding the records — but it does not make the signer independent of the action.¶
Not tamper-proof. The chain is tamper-evident. Alterations are detectable by verifiers in possession of the records; a signer who controls every copy of an unwitnessed chain can equivocate between inconsistent histories. External anchoring and witnessing are deployment measures discussed in Security Considerations; they are not properties of the family.¶
Not a delivery or settlement guarantee. Where a record references a payment artifact, the reference binds the record to that artifact; it does not establish that goods, services, or outputs were delivered or accepted.¶
Not a constraint type. evidence.* records do not gate execution and do not satisfy the membership criterion of the environment.* family. The families compose; they do not overlap.¶
Every property this family provides is a property of a record signed by the operator of the runtime that produced the action. A verifier that holds the records and the published key can establish that the operator committed to specific bytes and that those bytes have not changed since signing. Nothing in the family establishes that the committed bytes describe the action accurately, that the recorded output is the output a consumer received, or that the signer is independent of the action. Section 8 states these limits in full; they are repeated here because they bound the security analysis of every subsection below.¶
The practical consequence is that the family narrows a dishonest operator's options rather than eliminating them. Post-hoc alteration of a signed member is detectable. Dishonesty at signing time is not.¶
A holder of the signing key can produce any chain that verifies. Every integrity property of this family is conditional on key custody, and this document specifies no custody mechanism.¶
An operator publishing an evidence.* chain MUST publish the corresponding public key at a location under the operator's own control, and MUST NOT rely on a key set published by the specification author or by any implementation vendor. The issuer identity a record commits to is the operator's, not the implementation's.¶
An operator MUST publish a signing key before signing records under it. A verifier resolving a key identifier that is not present in the published key set returns UNVERIFIABLE, and a publish-after-sign order therefore produces a window in which honestly produced records are unverifiable.¶
Key rotation is a publication concern rather than a chain concern: a chain links by content hash, not by key, so a rotation does not break linkage. A verifier MUST NOT accept a chain whose records name a key identifier that is not resolvable in the published key set at verification time merely because an earlier verification succeeded. An operator SHOULD retain superseded public keys in the published key set for as long as records signed under them are expected to be verified.¶
A key set that publishes more than one key under a single key identifier is ambiguous. A verifier MUST return UNVERIFIABLE in that case, and MUST NOT select one of the candidates.¶
The chain is tamper-evident with respect to a verifier that holds the records. It is not equivocation-resistant. A signer who controls every copy of a chain can produce two internally consistent chains for the same session that disagree about what happened, and no verifier holding only one of them can detect the other.¶
External witnessing addresses this and is a deployment measure rather than a family property. An operator concerned with equivocation may record chain heads in a public-good transparency log, so that a later divergence between the operator's chain and the recorded head is detectable by a third party. The ceiling of the resulting claim is that a head was recorded in a public-good transparency log. An operator MUST NOT describe a record so anchored as third-party attested: the log records what it was given, and records nothing about the action.¶
Nothing in this document requires witnessing, and no verdict of Section 5 depends on it.¶
A record carries jwks_uri inside its signed bytes, and a verifier that fetches a URL taken from a record it has not yet verified is following an untrusted pointer. Absent restriction, that is a server-side request forgery primitive.¶
A verifier resolving a key set from a location named by a record MUST apply all of the following, and MUST treat any violation as an aborted fetch rather than as a weaker check:¶
the URL scheme is HTTPS and the port is the HTTPS default;¶
the host is a name rather than an IP literal;¶
the host does not resolve to a loopback, link-local, or otherwise non-public address, checked after name resolution so that a rebind between check and connect cannot slip through;¶
at most one redirect is followed, and only to the same origin;¶
the response body is bounded and the request is subject to a timeout;¶
the response carries a JSON content type.¶
An aborted fetch yields UNVERIFIABLE. A verifier MUST NOT respond to an aborted fetch by resolving the key from a different source (Section 5.1, step 2).¶
The ts member is issuer-asserted and unwitnessed. A verifier MUST NOT treat ts as evidence of when an action occurred, and MUST NOT use ts to order records: ordering is carried by seq and by the hash chain, both of which are covered by the signature.¶
The only property a verifier checks over ts is non-regression within a bounded skew (Section 5.1, step 10). The bound exists because clocks in a distributed deployment disagree, and a strict monotonicity requirement would reject honestly produced chains. An operator SHOULD synchronize the clock of any host that signs records, and a verifier SHOULD choose a skew bound no larger than its deployment requires, because the bound is also the window within which a reordering is not detectable from timestamps alone.¶
A record is bound to its position by seq, to its predecessor by prev_hash, and to its session by session_id, and all three are inside the signed bytes. Lifting a record out of one chain and inserting it into another therefore breaks the linkage check of Section 5.1, step 7, and re-presenting a record at a different position breaks the sequence check of step 5.¶
Replay of a whole chain is a different matter and is not addressed by the chain construction. A chain is a verifiable statement about what an operator committed to, not a statement about when a consumer received it. A consumer that needs freshness MUST establish it outside the record — for example by binding the chain into a protocol exchange that carries its own anti-replay mechanism — and MUST NOT infer freshness from ts (Section 9.5).¶
The strict-ingest profile of Section 4.6 is a security property and not only a parsing convention. Its absence produces a class of divergence in which an issuer and a verifier both report success over the same source text while having hashed different values — through a duplicate member resolved differently, or through a numeric literal silently converted to a nearby representable value. A divergence of that shape does not announce itself: it appears as a verification failure that neither party can reproduce, or worse, as a verification success over a value neither party intended.¶
Pinning the rule to lossless round-trip behaviour rather than to token shape is what makes the reject set identical across implementations. An implementation that applies a narrower rule accepts inputs a conforming implementation rejects, and the two disagree exactly at the edges an adversary chooses.¶
This document requests that IANA establish a registry for evidence.* record type identifiers and register this document as the family-definition document for the namespace. The registry mechanics below mirror those of [ENV-STATE], Section 8.¶
IANA is requested to register the evidence.* namespace as a record type prefix in the registry of Section 10.2. The namespace is the literal string evidence followed by a dot followed by one or more dot-separated components identifying the kind of occurrence a record type commits to and, optionally, sub-classifications.¶
This document is registered as the family-definition document for the evidence.* namespace. A specification proposing a new evidence.* type identifier MUST conform to this document. IANA MUST NOT register a specification that does not conform, regardless of the technical merit of the proposed type.¶
IANA is requested to establish a registry titled "evidence.* Record Types" (or a name the working group prefers) with the following structure.¶
Registry fields. Each registration entry has the following fields:¶
Type identifier — the dot-separated string under the evidence.* namespace (for example, evidence.action).¶
Defined In — a reference to the record type specification that defines the type. The reference SHOULD be a stable identifier (RFC number, Internet-Draft name and revision, or a permanent published-document URL).¶
Version — the version of the type specification at the time of registration.¶
Version Tokens — the version token or tokens the type's records carry in their v member, as specified in Section 4.2.¶
Status — one of: Provisional, Stable, Deprecated.¶
MUST-Implement Algorithm — the per-type signing algorithm declared per Section 4.5.¶
Conformance Corpus — a reference to the type's frozen conformance corpus per Appendix A, including the identifier under which the corpus manifest is published.¶
Notes — implementation-status references per [RFC7942], known-issues references, or coordination references with sibling specifications. May be empty.¶
Initial registry contents. This document registers one type identifier, with the following field values:¶
Type identifier: evidence.action¶
Defined In: this document¶
Version: 00¶
Version Tokens: evidence.action/0, evidence.action/1¶
Status: Provisional¶
MUST-Implement Algorithm: Ed25519¶
Conformance Corpus: the frozen corpus described in Appendix A¶
Notes: see Appendix B of this document for implementation status and known gaps¶
This document registers no other type identifier.¶
Registration policy. Registration follows the Specification Required policy of [RFC8126], Section 4.6 with Expert Review by designated experts the working group appoints. The criteria the experts apply are specified in Section 10.3.¶
A designated expert evaluating a proposed registration MUST verify that the proposed type satisfies all of the following:¶
(1) every field contributing to a verdict is covered by the issuer's signature (Section 3.2, property 1);¶
(2) the signed bytes are produced under a deterministic canonicalization an independent implementation can reproduce byte-for-byte (Section 3.2, property 2);¶
(3) records within a session are bound into an append-only hash chain in which removal, insertion, and reordering are detectable from the records alone (Section 3.2, property 3);¶
(4) a verifier that cannot complete recomputation returns UNVERIFIABLE and never reports the record as valid (Section 3.2, property 4);¶
(5) the type specification declares its MUST-implement signing algorithm and any extension sets per Section 4.5;¶
(6) the type specification publishes, per Appendix A of this document, a frozen conformance corpus that includes at least one vector whose expected verdict is a rejection; and¶
(7) the type specification conforms to the register discipline of [ENV-STATE], Section 6.¶
A proposed registration that fails any of these checks MUST be rejected by the designated experts. Rejection is not punitive; it indicates that the gap is to be closed in the proposed specification before the registration is reconsidered. A designated expert SHOULD identify which check the proposed registration failed and what closure of the gap would look like.¶
A designated expert SHOULD also evaluate a proposed registration for namespace coherence — an identifier that names the kind of occurrence recorded rather than the implementation, the issuer, or the wire format — and for implementation status per [RFC7942]. These additional criteria are guidance; they are not requirements a proposed registration MUST satisfy.¶
The Status field of Section 10.2 has three values.¶
Provisional. The type's specification has been adopted but has not been published as an RFC or equivalent stable document. Implementations of provisional types should expect specification changes.¶
Stable. The type's specification has been published as an RFC or equivalent stable document.¶
Deprecated. The type's specification has been superseded or withdrawn. Deprecation does not suspend the membership criterion of Section 3.2. The Notes field SHOULD reference the superseding specification or document the reason for withdrawal. A verifier MAY continue to support a deprecated type for backward compatibility, and SHOULD log its use distinctly.¶
A status transition MUST NOT change a registered type's version tokens, its MUST-implement algorithm, or its conformance corpus reference; a change to any of those is a revision of the type's specification rather than an administrative status update.¶
This appendix is informative in the sense of [RFC7942]: it describes a published artifact rather than adding requirements. The conformance sentence at the end of the appendix is the exception and is stated as the corpus states it.¶
A frozen conformance corpus for the evidence.action record format is published as a bundle containing a specification document, a machine-readable manifest, a key set, six vectors, a reference runner, a deterministic generator, and a second, independent verification path used during bundle authoring.¶
The corpus pins, for every vector, the SHA-256 of the vector's receipt file bytes and the file's byte length; and, for every entry of every vector expected to verify, the request commitment, the entry hash, the signature, the canonical byte length, and the canonical SHA-256. Every pinned value is re-derived from the receipt file bytes by the bundle's independent verification path before publication.¶
The corpus manifest, at the revision this document was written against, has the SHA-256 digest:¶
dad4e77cc5072446832b0b1771de11e2fc14094c6671061366477e60ce214ef3¶
The six vectors and the property each exercises:¶
| Vector | Property exercised | Expected |
|---|---|---|
| allow | A valid permitted call verifies byte-for-byte | VALID |
| deny | Rule-based denial-with-halt is a first-class verifiable outcome | VALID |
| fail-closed | A safe-default halt is a first-class verifiable outcome, distinguished in the signed bytes by decision_source | VALID |
| tampered | Post-signature mutation is rejected | reject |
| chain-multi | The verifier checks hash-chain linkage, not just per-record signatures | VALID |
| canonicalization-key-order | args_hash uses JCS, not a non-canonical serializer | VALID |
The tampered vector is the load-bearing one. It was produced by generating a valid record and then altering one element of the event in the file bytes, leaving the signature unchanged. Two independent checks catch the mutation: the request commitment recomputed from the altered event no longer matches the sealed value, and the canonical bytes of the content differ from what was signed. A verifier that reports the tampered vector as valid is non-conforming. The corpus does not require a specific rejection reason: a verifier that checks the request commitment before the signature reports a commitment mismatch, and a verifier that checks the signature first reports a signature failure. Both are conforming; the rejection is the requirement.¶
The chain-multi vector exists because a verifier that checks per-record signatures without checking linkage would pass every single-record vector. The corpus therefore asserts the linkage equalities explicitly: that the first record's prev_hash equals the genesis value for its session, and that the second record's prev_hash equals the first record's entry hash.¶
The canonicalization-key-order vector carries, in the manifest, both an unsorted arguments value and its JCS canonical form together with that form's byte length, so that an implementer can check their canonicalization path end-to-end rather than only its output hash.¶
Reject vectors for the strict-ingest profile of Section 4.6 are not part of this bundle. They belong to a second, separately frozen fixture described in Appendix A.3.¶
The corpus predates the tri-state vocabulary of Section 5.2 and names its outcomes VALID, TAMPERED, and UNRESOLVED. The mapping is direct: TAMPERED is a rejection reported by the corpus for chain-integrity and content-mismatch failures, and UNRESOLVED is the corpus name for a key that could not be resolved, which this document names UNVERIFIABLE. A future revision of the corpus is expected to adopt this document's vocabulary. Until it does, an implementer comparing the two documents should read the corpus's outcome names as corpus-local labels rather than as this document's verdicts.¶
Conformance in this family is a claim about agreement between implementations, so a corpus verified only by the implementation that produced it establishes little. Two separately frozen artifacts, verified by different means, are in use.¶
The receipt-vector bundle of Appendix A.1 carries a generator and a distinct verification path: the generator writes the vectors, the manifest, and the key set deterministically from a published test seed, and the second path re-derives every pinned hash, signature, and canonical byte length from the published receipt bytes before the bundle is released. Both paths live in the bundle; they are two implementations of the same computation, not two independent parties.¶
That bundle's signing key is derived from a published 32-byte seed. It is a test key and MUST NOT be used to sign production records. The seed is published so that an independent implementer can re-derive the private key, re-sign the canonical bytes, and confirm signature byte parity end to end rather than only verifying signatures produced by someone else.¶
The second artifact is a separately frozen fixture of canonicalization, thumbprint, chain-structure, and strict-ingest reject vectors, held with the reference implementation rather than in the receipt-vector bundle. It is the one exercised three ways: by the reference implementation's own canonicalization path, by an independent implementation of [RFC8785] written by a different author with no shared dependency, and against the values claimed by the fixture's external author, who authored them by reasoning from the relevant specifications rather than by executing the implementation. Its strict-ingest reject vectors are driven through the same harness and fail closed with the expected reasons. The harness exercises the same canonicalization and strict-ingest code path the shipped binary uses; it is not a second reference implementation.¶
Neither artifact establishes byte parity between two independent signing implementations. Appendix A.5 names that as the next tier.¶
An implementation claiming conformance MUST reproduce the corpus verdicts, including the REJECT set, identically.¶
The corpus is a v1 tier and names the orthogonal properties a later tier would cover:¶
Live key-set resolution. The corpus key set is offline; a later tier would exercise HTTPS resolution, rotation, caching, and the failure paths that produce UNVERIFIABLE.¶
Gate-receipt upstream binding. The gate_receipt member in the vectors carries a pinned literal; a later tier would exercise the end-to-end property of Section 6.3.¶
Transparency-log witnessing. Equivocation by a signer is not detectable from a single chain (Section 9.3); a later tier would exercise inclusion proofs.¶
Key rotation across vectors. All vectors are signed by one key.¶
Dual-implementation signing byte parity. The corpus demonstrates that one signing implementation produces bytes a conforming verifier accepts. It does not demonstrate that two independent signing implementations produce byte-identical records for the same logical event. That tier blocks on the existence of a second independent signing implementation and is the named next milestone.¶
This section records the implementation status of the evidence.action record type at the time of writing, per [RFC7942]. It is to be removed by the RFC Editor before publication, together with the reference to [RFC7942].¶
Name and version. @headlessoracle/chirindo, version 0.3.0.¶
Source. github.com/LembaGang/chirindo, Apache-2.0.¶
Coverage. The implementation writes and verifies evidence.action records at both defined version tokens, implements the canonicalization discipline of Section 4.1, the chain construction of Section 4.4, the signature scheme of Section 4.5, the strict-ingest gate of Section 4.6, and the verification protocol of Section 5.1 including key-binding-before-signature ordering. Key resolution follows a documented precedence, and a present-but-unresolvable publication location does not fall back to another key source.¶
Published key set. The implementation resolves keys from a published key set at https://headlessoracle.com/.well-known/jwks.json by default; an operator overrides that default per Section 9.2.¶
Live verification. The verify path has been exercised by hand against the live published key set over HTTPS, and the three verdict classes behaved as specified: a well-formed chain resolved its key and returned VALID; a chain whose committed thumbprint had been altered returned INVALID with a key-binding reason, rejected before the signature check; and a chain signed by a key the published set does not carry returned UNVERIFIABLE with an unresolvable-key reason and no silent fallback.¶
Third-party verification of the corpus fixture. The canonicalization fixture of Appendix A.3 was authored by an external party reasoning from the relevant specifications rather than by executing the implementation's code, and was then verified three ways — the implementation's own canonicalization path, an independent implementation of [RFC8785] by a different author, and the fixture author's claimed values — with byte and hash agreement on every canonicalization vector and on the key thumbprint. The receipt-chain entry hashes in the fixture are derived at fixture-build time from the implementation's own code path and additionally recompute through the independent canonicalizer applied to a harness-side content strip, so the agreement is not an artifact of feeding one object to one canonicalizer twice. Signature authenticity of the fixture's illustrative records was explicitly not established in that exercise; the fixture author held only a public key. The negative cases the fixture describes structurally are separately covered by the implementation's own test suite against a real key.¶
The following gaps are stated because the format leads the implementation in each case. An implementer MUST NOT infer the availability of these properties from this document.¶
Strict ingest covers part of the round-trip rule. Section 4.6 requires rejection of any numeric member that does not round-trip losslessly as a finite value. The implementation rejects integer-form literals outside the exactly-representable range and duplicate member names at any depth. An exponent-form literal that overflows to a non-finite value is not yet rejected. Section 4.6 states the rule the implementation is to converge on; the implementation does not satisfy it in full today.¶
The gate member is emitted in one of two shapes, neither complete. The recorder library emits a null gate on every record. The gate implementation emits a populated gate whose gate_family is permit and whose gate_receipt is self-anchored to the record's own entry hash. No deployed implementation resolves gate_receipt to an upstream pre-action receipt (Section 6.3).¶
The fail-closed disposition is not emitted. The decision_source value fail-closed is defined by the format and exercised by a corpus vector. The implementation's decision-source value space is user, config, hook, and n/a; it does not emit fail-closed today. A verifier of earlier vintage that has not learned the value would not be conforming for the corresponding corpus vector.¶
The verifier's result vocabulary is finer than three, and one case is classified differently. The implementation reports valid, tampered, invalid, empty, and unverifiable. Under Section 5.2, its invalid maps to INVALID, its unverifiable maps to UNVERIFIABLE, its empty maps to UNVERIFIABLE, and its tampered maps to UNVERIFIABLE except for the signature-failure case, which Section 5.1 step 9 classifies as INVALID and the implementation reports as tampered. Every one of the implementation's failure results exits non-zero, so the divergence is a labelling difference and not a fail-open path.¶
The payment-reference binding is specified but not built. Section 7 describes a design whose registry carries no confirmed mapping row. No implementation emits a payment reference.¶
The author thanks the authors of the sibling family specifications and the IETF community for ongoing discussion of attestation primitives.¶