<?xml version="1.0" encoding="utf-8"?>
<!-- name="GENERATOR" content="github.com/mmarkdown/mmark Mmark Markdown Processor - mmark.miek.nl" -->
<rfc version="3" ipr="trust200902" docName="draft-hopley-x402-payment-evidence-frame-00" submissionType="independent" category="info" xml:lang="en" xmlns:xi="http://www.w3.org/2001/XInclude" indexInclude="true">

<front>
<title abbrev="x402-payment-evidence-frame">Payment Evidence Frame for Agentic-Payment Lifecycle Receipts</title><seriesInfo value="draft-hopley-x402-payment-evidence-frame-00" stream="independent" status="informational" name="Internet-Draft"></seriesInfo>
<author initials="C." surname="Hopley" fullname="Christopher Hopley"><organization>AlgoVoi</organization><address><postal><street></street>
<country>GB</country>
</postal><email>chopmob@gmail.com</email>
</address></author><date year="2026" month="May" day="30"></date>
<area>Independent Submission</area>
<workgroup>Independent Submission</workgroup>
<keyword>x402</keyword>
<keyword>agentic payments</keyword>
<keyword>payment evidence</keyword>
<keyword>receipt</keyword>
<keyword>audit chain</keyword>
<keyword>JCS</keyword>
<keyword>RFC 8785</keyword>
<keyword>categorical receipt</keyword>
<keyword>payment frame</keyword>
<keyword>MiCA</keyword>
<keyword>PSD2</keyword>
<keyword>A2A</keyword>
<keyword>MPP</keyword>

<abstract><t>This document specifies a Payment Evidence Frame (PEF): a
transport-agnostic envelope that wraps any payment lifecycle receipt
from the x402 agentic-payment receipt stack under a named claim type,
a deterministic frame identifier, and an optional transport-layer
signature.</t>
<t>The frame introduces three properties that the inner receipt types
do not individually provide: (1) a stable cross-system identifier
(<tt>frame_id</tt>) derived deterministically from the receipt content by
SHA-256 over the JCS-canonical preimage, so the same payment evidence
can be referenced by identifier across HTTP headers, agent-to-agent
task artifacts, audit logs, and on-chain memo fields without
re-serialising the full receipt; (2) a taxonomy label (<tt>claim_type</tt>)
that tells a consumer what class of evidence a frame carries before
the inner receipt format is parsed; and (3) a receipt integrity hash
(<tt>receipt_hash</tt>) that allows any downstream party to confirm the inner
receipt is unaltered without deserialising its full structure.</t>
<t>The format uses the same JCS canonicalisation discipline
(draft-hopley-x402-canonicalisation-jcs) as the five inner receipt
formats it envelopes, so implementations require only one
canonicalisation primitive for the full receipt stack.</t>
</abstract>

</front>

<middle>

<section anchor="introduction"><name>1. Introduction</name>

<section anchor="motivation"><name>1.1. Motivation</name>
<t>The x402 agentic-payment receipt stack defines five categorical
receipt formats for the distinct events in a payment lifecycle:</t>

<ul spacing="compact">
<li>draft-hopley-x402-compliance-receipt -- pre-payment admission
screening (ALLOW / REFER / DENY).</li>
<li>draft-hopley-x402-settlement-attestation -- per-execution
settlement confirmation (SETTLED / PENDING_FINALITY / REVERSED).</li>
<li>draft-hopley-x402-cancellation-receipt -- mandate termination
(USER_REQUESTED / MERCHANT_REQUESTED / COMPLIANCE_TERMINATED /
EXPIRED).</li>
<li>draft-hopley-x402-refund-receipt -- post-settlement refund
(FULL / PARTIAL / REJECTED).</li>
<li>draft-hopley-x402-composite-trust-query -- verifier-of-verifier
conclusion over an audit chain composed of the above
(TRUSTED / PROVISIONAL / INSUFFICIENT_EVIDENCE / UNTRUSTED).</li>
</ul>
<t>Each receipt is a self-contained JCS-canonical JSON object with a
content hash. Each is independently verifiable. Each is designed
to be retained in an audit chain via hash-chain linkage.</t>
<t>A gap exists at the transport and interoperability layer. A
compliance receipt emitted by system A and consumed by system B
must be carried in some envelope that system B can inspect without
knowing in advance which of the five receipt formats it will find.
An agent-to-agent task artifact, an HTTP response extension field,
a memo field on a blockchain transaction, and a webhook payload all
face the same need: carry a receipt with enough metadata that the
consumer can route it, verify its integrity, and correlate it with
other events in the lifecycle -- without parsing the inner format
first.</t>
<t>Three specific gaps motivate this document:</t>

<ol>
<li><t><strong>Stable cross-system identifier.</strong> A compliance receipt's
content hash changes if any field changes. There is no stable
identifier for &quot;the payment evidence bundle associated with
transaction T&quot; that persists across the HTTP layer, the agent
layer, and the audit-chain layer without carrying the full receipt
bytes at every hop.</t>
</li>
<li><t><strong>Taxonomy label.</strong> A consumer receiving a JSON blob over a
generic channel (e.g. an A2A task artifact, an HTTP header) has
no standard signal for which of the five receipt types it holds
before deserialising the full struct. Dispatch logic cannot switch
on receipt type without parsing.</t>
</li>
<li><t><strong>Integrity without deserialisation.</strong> A consumer that only needs
to confirm &quot;this receipt has not been altered since the issuer
signed the frame&quot; must today fully parse the inner receipt and
recompute its content hash. A receipt hash in the frame envelope
allows integrity checks to be performed at the frame layer.</t>
</li>
</ol>
<t>The Payment Evidence Frame specified in this document addresses all
three gaps with a ten-field envelope that adds no new
canonicalisation rules and no new cryptographic primitives.</t>
</section>

<section anchor="scope"><name>1.2. Scope</name>
<t>This document specifies:</t>

<ul spacing="compact">
<li>The canonical JSON shape of the Payment Evidence Frame (Section 3).</li>
<li>The frame identifier derivation algorithm (<tt>frame_id</tt>, Section 4).</li>
<li>The receipt hash derivation algorithm (<tt>receipt_hash</tt>, Section 5).</li>
<li>The reference to the canonicalisation discipline applicable to
the frame (Section 6 -- normative reference to
draft-hopley-x402-canonicalisation-jcs, not redefined inline).</li>
<li>The claim type taxonomy (Section 3.2).</li>
<li>Composition of PEF with the five inner receipt formats and with
transport protocols (Section 7).</li>
<li>Year-N auditability properties (Section 8).</li>
<li>Worked examples covering all five claim types (Appendix A).</li>
</ul>
<t>This document does NOT specify:</t>

<ul spacing="compact">
<li>The inner receipt formats. They are specified in their respective
I-Ds (draft-hopley-x402-compliance-receipt, etc.). The PEF
envelope is additive; it does not redefine any inner receipt field.</li>
<li>The transport protocol. PEF is a JSON shape; where it appears
(HTTP response body, HTTP header, A2A task artifact, MPP method
response, on-chain memo) is out of scope.</li>
<li>The optional signature value. The <tt>signature</tt> field carries a
pre-computed RFC 9421 signature string when supplied; the signing
procedure is defined in draft-hopley-x402-rfc9421-x402-binding,
not redefined here.</li>
</ul>
</section>

<section anchor="relationship-to-other-internet-drafts"><name>1.3. Relationship to Other Internet-Drafts</name>
<t>This document normatively references:</t>

<ul spacing="compact">
<li>draft-hopley-x402-canonicalisation-jcs -- the JCS canonicalisation
discipline pinned in Section 6.</li>
</ul>
<t>This document is complementary to:</t>

<ul spacing="compact">
<li>draft-hopley-x402-compliance-receipt -- provides the
<tt>compliance-receipt-v1</tt> inner receipt format for frames with
<tt>claim_type: payment_admission</tt>.</li>
<li>draft-hopley-x402-settlement-attestation -- provides the
<tt>settlement-attestation-v1</tt> inner receipt format for frames with
<tt>claim_type: payment_settlement</tt>.</li>
<li>draft-hopley-x402-cancellation-receipt -- provides the
<tt>cancellation-receipt-v1</tt> inner receipt format for frames with
<tt>claim_type: payment_cancellation</tt>.</li>
<li>draft-hopley-x402-refund-receipt -- provides the
<tt>refund-receipt-v1</tt> inner receipt format for frames with
<tt>claim_type: payment_refund</tt>.</li>
<li>draft-hopley-x402-composite-trust-query -- provides the
<tt>composite-trust-query-v1</tt> inner receipt format for frames with
<tt>claim_type: composite_verdict</tt>.</li>
<li>draft-hopley-x402-rfc9421-x402-binding -- defines the signing
procedure for the optional <tt>signature</tt> field.</li>
</ul>
<t>PEF sits above all five receipt formats. It does not replace them;
it envelopes them for transport and cross-system reference.</t>
</section>
</section>

<section anchor="conventions-and-definitions"><name>2. Conventions and Definitions</name>

<section anchor="notation"><name>2.1. Notation</name>
<t>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;,
&quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and
&quot;OPTIONAL&quot; in this document are to be interpreted as described in
BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here.</t>
</section>

<section anchor="definitions"><name>2.2. Definitions</name>
<t><strong>Payment Evidence Frame (PEF)</strong>: a JSON object of the shape
specified in Section 3, wrapping one inner receipt from the x402
agentic-payment receipt stack under a named claim type and a
deterministic frame identifier.</t>
<t><strong>frame_id</strong>: a string of the form <tt>sha256:&lt;lowercase-hex-64&gt;</tt>
derived from the JCS-canonical bytes of the PEF preimage (the frame
object with <tt>frame_id</tt> and <tt>signature</tt> fields excluded). See
Section 4 for the derivation algorithm. The <tt>frame_id</tt> is stable:
it does not change if the <tt>signature</tt> field is subsequently added,
and it does not change across independent re-derivations from
identical content.</t>
<t><strong>receipt_hash</strong>: a string of the form <tt>sha256:&lt;lowercase-hex-64&gt;</tt>
equal to the SHA-256 of the JCS-canonical bytes of the <tt>receipt</tt>
field value. See Section 5.</t>
<t><strong>claim_type</strong>: a string-valued taxonomy label drawn from the closed
five-element enumeration in Section 3.2. Identifies the lifecycle
event the frame represents and the expected inner receipt format.</t>
<t><strong>receipt_format</strong>: a string-valued identifier for the inner receipt
format, drawn from the closed mapping in Section 3.3.</t>
<t><strong>frame_provider_did</strong>: a DID URI identifying the party that
constructed and issued the PEF frame.</t>
<t><strong>frame_timestamp_ms</strong>: an integer Unix epoch millisecond timestamp
at which the frame was constructed.</t>
<t><strong>preimage</strong>: the PEF frame object with the <tt>frame_id</tt> and
<tt>signature</tt> fields removed, used as input to the <tt>frame_id</tt>
derivation algorithm. The preimage is itself a valid JSON object and
is canonicalised under draft-hopley-x402-canonicalisation-jcs before
hashing.</t>
<t><strong>canon_version</strong>: an in-band string identifying the canonicalisation
discipline. For this version of the format, the full URN is
<tt>urn:x402:canonicalisation:jcs-rfc8785-v1</tt>.</t>
</section>
</section>

<section anchor="frame-format-specification"><name>3. Frame Format Specification</name>
<t>A Payment Evidence Frame is a JSON object with ten fields, of which
nine are REQUIRED and one (<tt>signature</tt>) is OPTIONAL. The frame is
canonicalised under draft-hopley-x402-canonicalisation-jcs per
Section 6. Field names sort lexicographically by JCS during
canonicalisation; the object uses arbitrary authoring order.</t>
<t>The ten fields are:</t>
<table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>

<tbody>
<tr>
<td><tt>canon_version</tt></td>
<td>string</td>
<td>REQUIRED</td>
<td>Canonicalisation URN. Fixed value for this version.</td>
</tr>

<tr>
<td><tt>claim_type</tt></td>
<td>string</td>
<td>REQUIRED</td>
<td>Lifecycle event taxonomy. Closed five-element enum.</td>
</tr>

<tr>
<td><tt>frame_id</tt></td>
<td>string</td>
<td>REQUIRED</td>
<td>SHA-256 of JCS(preimage). Stable cross-system identifier.</td>
</tr>

<tr>
<td><tt>frame_provider_did</tt></td>
<td>string</td>
<td>REQUIRED</td>
<td>DID URI of the party that constructed the frame.</td>
</tr>

<tr>
<td><tt>frame_timestamp_ms</tt></td>
<td>integer</td>
<td>REQUIRED</td>
<td>Unix epoch milliseconds at which the frame was constructed.</td>
</tr>

<tr>
<td><tt>pef_version</tt></td>
<td>string</td>
<td>REQUIRED</td>
<td>Format version. Fixed value <tt>1</tt> for this version.</td>
</tr>

<tr>
<td><tt>receipt</tt></td>
<td>object</td>
<td>REQUIRED</td>
<td>The inner receipt, embedded verbatim.</td>
</tr>

<tr>
<td><tt>receipt_format</tt></td>
<td>string</td>
<td>REQUIRED</td>
<td>Inner receipt format identifier. Closed mapping per Section 3.3.</td>
</tr>

<tr>
<td><tt>receipt_hash</tt></td>
<td>string</td>
<td>REQUIRED</td>
<td>SHA-256 of JCS(receipt). Integrity check without deserialisation.</td>
</tr>

<tr>
<td><tt>signature</tt></td>
<td>string</td>
<td>OPTIONAL</td>
<td>Pre-computed RFC 9421 transport-layer signature, when present.</td>
</tr>
</tbody>
</table>
<section anchor="pef-version"><name>3.1. pef_version</name>
<t>A string-valued field. The value MUST be <tt>1</tt> for this version of the
format. Implementations MUST reject any other value at validation
time.</t>
</section>

<section anchor="claim-type"><name>3.2. claim_type</name>
<t>A string-valued field drawn from the following closed five-element
enumeration:</t>
<table>
<thead>
<tr>
<th>claim_type</th>
<th>Lifecycle event</th>
<th>Expected receipt_format</th>
</tr>
</thead>

<tbody>
<tr>
<td><tt>payment_admission</tt></td>
<td>Pre-payment compliance screen</td>
<td><tt>compliance-receipt-v1</tt></td>
</tr>

<tr>
<td><tt>payment_settlement</tt></td>
<td>Per-execution settlement confirmation</td>
<td><tt>settlement-attestation-v1</tt></td>
</tr>

<tr>
<td><tt>payment_cancellation</tt></td>
<td>Mandate or order termination</td>
<td><tt>cancellation-receipt-v1</tt></td>
</tr>

<tr>
<td><tt>payment_refund</tt></td>
<td>Post-settlement refund</td>
<td><tt>refund-receipt-v1</tt></td>
</tr>

<tr>
<td><tt>composite_verdict</tt></td>
<td>Verifier-of-verifier audit chain conclusion</td>
<td><tt>composite-trust-query-v1</tt></td>
</tr>
</tbody>
</table><t>The enumeration is closed. Implementations MUST reject any value not
in this set at validation time before canonicalisation. The
<tt>claim_type</tt> field is the primary dispatch signal: a consumer routing
incoming frames by lifecycle event MUST switch on <tt>claim_type</tt>
before inspecting the inner <tt>receipt</tt>.</t>
</section>

<section anchor="receipt-format"><name>3.3. receipt_format</name>
<t>A string-valued field drawn from the following closed mapping, keyed
by <tt>claim_type</tt>:</t>
<table>
<thead>
<tr>
<th>claim_type</th>
<th>receipt_format</th>
</tr>
</thead>

<tbody>
<tr>
<td><tt>payment_admission</tt></td>
<td><tt>compliance-receipt-v1</tt></td>
</tr>

<tr>
<td><tt>payment_settlement</tt></td>
<td><tt>settlement-attestation-v1</tt></td>
</tr>

<tr>
<td><tt>payment_cancellation</tt></td>
<td><tt>cancellation-receipt-v1</tt></td>
</tr>

<tr>
<td><tt>payment_refund</tt></td>
<td><tt>refund-receipt-v1</tt></td>
</tr>

<tr>
<td><tt>composite_verdict</tt></td>
<td><tt>composite-trust-query-v1</tt></td>
</tr>
</tbody>
</table><t>The <tt>receipt_format</tt> value MUST match the inner receipt's self-
declared format identifier. Implementations MUST verify this mapping
at validation time. The mapping is closed and version-pinned; future
versions of either the frame or the inner receipt formats would
advance the version indicator.</t>
</section>

<section anchor="receipt"><name>3.4. receipt</name>
<t>An object-valued field containing the inner receipt, embedded
verbatim. The object MUST conform to the shape specified by the
format identified in <tt>receipt_format</tt>. The object MUST NOT be
modified, re-ordered, or re-encoded relative to its canonical form
before embedding; consumers SHOULD re-canonicalise and re-hash the
embedded receipt to verify <tt>receipt_hash</tt>.</t>
</section>

<section anchor="receipt-hash"><name>3.5. receipt_hash</name>
<t>A string-valued field of the form <tt>sha256:&lt;lowercase-hex-64&gt;</tt>. The
hex digest is the SHA-256 of the JCS-canonical bytes of the <tt>receipt</tt>
field value. See Section 5 for the derivation algorithm.</t>
<t><tt>receipt_hash</tt> allows a consumer to confirm the inner receipt is
unaltered without fully deserialising it. A consumer that only needs
integrity confirmation computes SHA-256(JCS(<tt>receipt</tt>)) and compares
against <tt>receipt_hash</tt>. A mismatch indicates tampering.</t>
<t>Implementations MUST NOT strip the <tt>sha256:</tt> prefix during
canonicalisation or verification.</t>
</section>

<section anchor="frame-id"><name>3.6. frame_id</name>
<t>A string-valued field of the form <tt>sha256:&lt;lowercase-hex-64&gt;</tt>. The
hex digest is SHA-256 of the JCS-canonical bytes of the PEF preimage.
See Section 4 for the derivation algorithm.</t>
<t><tt>frame_id</tt> is the stable cross-system identifier for this payment
evidence bundle. It is deterministic: independent parties holding the
same inner receipt and the same frame metadata MUST derive the same
<tt>frame_id</tt>. It is stable across signature addition: adding the
<tt>signature</tt> field does not change the <tt>frame_id</tt> because <tt>signature</tt>
is excluded from the preimage.</t>
<t>Implementations MUST NOT strip the <tt>sha256:</tt> prefix during
canonicalisation or verification.</t>
</section>

<section anchor="frame-provider-did"><name>3.7. frame_provider_did</name>
<t>A string-valued DID URI identifying the party that constructed and
issued the PEF frame. The DID method is not constrained; the field
is treated as opaque identifier-bytes under JCS canonicalisation.</t>
<t>The frame provider is typically the platform or agent that built the
inner receipt and is issuing it to a downstream consumer. The DID
MAY be the same as the <tt>compliance_provider_did</tt>, <tt>settlement_provider_did</tt>,
or <tt>verifier_did</tt> in the inner receipt if the same party is acting
in both capacities.</t>
</section>

<section anchor="frame-timestamp-ms"><name>3.8. frame_timestamp_ms</name>
<t>An integer-valued field carrying the Unix epoch millisecond timestamp
at which the frame was constructed, in UTC.</t>
<t>This field MUST be an integer. RFC 3339 string forms (e.g.
<tt>&quot;2026-05-30T12:00:00Z&quot;</tt>) MUST be rejected at the validation layer
before canonicalisation. This is Substrate Rule 2, normatively
specified in draft-hopley-x402-canonicalisation-jcs Section 4.1.</t>
</section>

<section anchor="canon-version"><name>3.9. canon_version</name>
<t>A string-valued in-band canonicalisation rule pin. For this version
of the frame format the value MUST be
<tt>urn:x402:canonicalisation:jcs-rfc8785-v1</tt>.</t>
<t>The full URN form is used here (rather than the short form
<tt>jcs-rfc8785-v1</tt> used in the inner receipt formats) to distinguish
the frame-level canonicalisation pin from the inner receipt's own
<tt>canon_version</tt> field. The underlying discipline is identical.</t>
</section>

<section anchor="signature-optional"><name>3.10. signature (OPTIONAL)</name>
<t>A string-valued field carrying a pre-computed RFC 9421 HTTP Message
Signature string (draft-hopley-x402-rfc9421-x402-binding) when
present.</t>
<t>The <tt>signature</tt> field is OPTIONAL. Its absence does not affect frame
validity or <tt>frame_id</tt> derivation. When present, it binds the frame
to a transport-layer identity claim. The signing procedure,
verification algorithm, and key material requirements are defined in
draft-hopley-x402-rfc9421-x402-binding.</t>
<t>The <tt>signature</tt> field is excluded from the preimage used to derive
<tt>frame_id</tt> (Section 4). This exclusion means <tt>frame_id</tt> is stable
before and after signature addition, enabling a two-phase workflow:
(1) build frame and derive <tt>frame_id</tt>; (2) sign and attach
<tt>signature</tt> without invalidating any prior references to the
<tt>frame_id</tt>.</t>
</section>
</section>

<section anchor="frame-id-derivation"><name>4. Frame ID Derivation</name>
<t>The <tt>frame_id</tt> is derived as follows:</t>

<ol>
<li><t><strong>Construct the preimage.</strong> Start with the full PEF frame object.
Remove the <tt>frame_id</tt> field. Remove the <tt>signature</tt> field if
present. The resulting object is the preimage. The preimage is a
valid JSON object containing all fields except <tt>frame_id</tt> and
<tt>signature</tt>.</t>
</li>
<li><t><strong>Canonicalise the preimage.</strong> Apply the JCS canonicalisation
discipline per draft-hopley-x402-canonicalisation-jcs. This
produces a deterministic byte sequence. Field names are sorted
lexicographically; whitespace is removed; numeric values are
normalised per RFC 8785 Section 3.2.2.3; the <tt>receipt</tt> object is
recursively canonicalised.</t>
</li>
<li><t><strong>Hash.</strong> Compute SHA-256 of the canonical byte sequence.</t>
</li>
<li><t><strong>Encode.</strong> Encode as the lowercase hex string of the 32-byte
digest, prefixed with <tt>sha256:</tt>. The result is a 71-character
string.</t>
</li>
</ol>
<t>Implementations MUST follow these steps in order. In particular:</t>

<ul spacing="compact">
<li>The <tt>frame_id</tt> field itself MUST be absent from the preimage. If
a frame is received with a <tt>frame_id</tt> field present, the verifier
MUST remove it before computing the expected value and comparing.</li>
<li>The <tt>signature</tt> field MUST be absent from the preimage regardless
of whether it is present in the received frame.</li>
<li>The <tt>receipt</tt> object inside the preimage is canonicalised as part
of the preimage, not separately. The <tt>receipt</tt> is NOT
independently re-canonicalised and substituted; it is included in
the preimage object as-is and the whole preimage is canonicalised
in one pass.</li>
</ul>

<section anchor="verification"><name>4.1. Verification</name>
<t>To verify a received frame's <tt>frame_id</tt>:</t>

<ol spacing="compact">
<li>Remove <tt>frame_id</tt> and <tt>signature</tt> from the frame object.</li>
<li>Canonicalise the result per draft-hopley-x402-canonicalisation-jcs.</li>
<li>Compute SHA-256 of the canonical bytes.</li>
<li>Compare <tt>sha256:&lt;hex&gt;</tt> against the received <tt>frame_id</tt>.</li>
<li>If they match, the <tt>frame_id</tt> is valid. If they differ, the frame
has been tampered with or the <tt>frame_id</tt> was incorrectly derived.</li>
</ol>
</section>

<section anchor="stability-property"><name>4.2. Stability Property</name>
<t>The <tt>frame_id</tt> is stable across the <tt>signature</tt> field lifecycle.
A frame built without a <tt>signature</tt> and a frame with an identical
content but an added <tt>signature</tt> field produce the same <tt>frame_id</tt>.
This enables the following pattern:</t>

<ol spacing="compact">
<li>Build frame, derive <tt>frame_id</tt>.</li>
<li>Reference <tt>frame_id</tt> in downstream systems (audit chain, A2A
task artifact, HTTP header, memo field).</li>
<li>Later, sign the frame and attach <tt>signature</tt>.</li>
<li>Downstream references to <tt>frame_id</tt> remain valid.</li>
</ol>
</section>
</section>

<section anchor="receipt-hash-derivation"><name>5. Receipt Hash Derivation</name>
<t>The <tt>receipt_hash</tt> is derived as follows:</t>

<ol spacing="compact">
<li>Extract the <tt>receipt</tt> object from the frame.</li>
<li>Canonicalise the <tt>receipt</tt> object per
draft-hopley-x402-canonicalisation-jcs.</li>
<li>Compute SHA-256 of the canonical byte sequence.</li>
<li>Encode as <tt>sha256:&lt;lowercase-hex-64&gt;</tt>.</li>
</ol>
<t>The <tt>receipt_hash</tt> is a commitment to the inner receipt content at
the time the frame was built. If the inner receipt is subsequently
modified (e.g. a field is altered in transit), the recomputed hash
will differ from <tt>receipt_hash</tt>, and the consumer will detect
tampering without needing to re-derive <tt>frame_id</tt>.</t>
<t>Implementations MUST verify <tt>receipt_hash</tt> as part of frame
validation. The two-step verification is:</t>

<ol spacing="compact">
<li>Verify <tt>receipt_hash</tt>: recompute SHA-256(JCS(<tt>receipt</tt>)) and
compare.</li>
<li>Verify <tt>frame_id</tt>: per Section 4.1.</li>
</ol>
<t>Both checks MUST pass for a frame to be considered valid.</t>
</section>

<section anchor="canonicalisation"><name>6. Canonicalisation</name>
<t>The PEF frame (excluding the <tt>signature</tt> field when present) MUST be
canonicalised under the discipline pinned by
draft-hopley-x402-canonicalisation-jcs and identified by the URN:</t>

<artwork><![CDATA[urn:x402:canonicalisation:jcs-rfc8785-v1
]]></artwork>
<t>The full normative specification of the discipline (JCS RFC 8785
plus the schema-normalisation requirements including Substrate
Rule 2 for integer timestamps) is in that document. This document
does not redefine the discipline inline.</t>
<t>The <tt>signature</tt> field, when present, MUST be excluded from
canonicalisation for the purposes of <tt>frame_id</tt> derivation (Section
4). A frame with a <tt>signature</tt> field is canonical in its full form
for transport; the <tt>frame_id</tt> preimage is canonical without it.</t>
</section>

<section anchor="composition-with-x402-receipt-stack-and-transport-protocols"><name>7. Composition with x402 Receipt Stack and Transport Protocols</name>

<section anchor="receipt-stack-composition"><name>7.1. Receipt Stack Composition</name>
<t>A PEF frame envelopes exactly one inner receipt. The five inner
receipt formats and their expected claim types are:</t>
<table>
<thead>
<tr>
<th>receipt_format</th>
<th>claim_type</th>
<th>Inner I-D</th>
</tr>
</thead>

<tbody>
<tr>
<td><tt>compliance-receipt-v1</tt></td>
<td><tt>payment_admission</tt></td>
<td>draft-hopley-x402-compliance-receipt</td>
</tr>

<tr>
<td><tt>settlement-attestation-v1</tt></td>
<td><tt>payment_settlement</tt></td>
<td>draft-hopley-x402-settlement-attestation</td>
</tr>

<tr>
<td><tt>cancellation-receipt-v1</tt></td>
<td><tt>payment_cancellation</tt></td>
<td>draft-hopley-x402-cancellation-receipt</td>
</tr>

<tr>
<td><tt>refund-receipt-v1</tt></td>
<td><tt>payment_refund</tt></td>
<td>draft-hopley-x402-refund-receipt</td>
</tr>

<tr>
<td><tt>composite-trust-query-v1</tt></td>
<td><tt>composite_verdict</tt></td>
<td>draft-hopley-x402-composite-trust-query</td>
</tr>
</tbody>
</table><t>A payment lifecycle generates a sequence of PEF frames: one
<tt>payment_admission</tt> frame when the compliance receipt is emitted,
one <tt>payment_settlement</tt> frame when the settlement attestation is
emitted, zero or one <tt>payment_cancellation</tt> frame, zero or one
<tt>payment_refund</tt> frame, and zero or more <tt>composite_verdict</tt> frames
when a verifier queries the resulting audit chain.</t>
<t>Each frame's <tt>frame_id</tt> is an independent stable identifier for that
lifecycle event. Downstream systems correlating events across a
lifecycle do so by collecting <tt>frame_id</tt> values from each frame as
it is emitted, rather than by walking the underlying audit chain.</t>
</section>

<section anchor="x402-transport"><name>7.2. x402 Transport</name>
<t>In the x402 HTTP protocol, a PEF frame MAY be included in the verify
response body as an extension field alongside the existing payment
confirmation fields:</t>

<artwork><![CDATA[POST /verify HTTP/1.1
...

HTTP/1.1 200 OK
Content-Type: application/json

{
  "x402Version": 1,
  "settlement_evidence": {
    "pef_version": "1",
    "claim_type": "payment_settlement",
    "receipt_format": "settlement-attestation-v1",
    "frame_id": "sha256:<hex64>",
    ...
  }
}
]]></artwork>
<t>A PEF frame MAY also be carried in an <tt>X-Payment-Evidence</tt> response
header, with the <tt>frame_id</tt> value as the header value and the full
frame retrievable at a content-addressed endpoint. The full frame
transport via header is implementation-defined.</t>
</section>

<section anchor="agent-to-agent-a2a-task-artifacts"><name>7.3. Agent-to-Agent (A2A) Task Artifacts</name>
<t>In A2A payment agent flows, a PEF frame MAY be attached as a task
artifact after a payment task completes. The standard artifact shape
is:</t>

<sourcecode type="json"><![CDATA[{
  "type": "payment_evidence",
  "mimeType": "application/json",
  "data": {
    "pef_version": "1",
    "claim_type": "payment_settlement",
    "frame_id": "sha256:<hex64>",
    "receipt_format": "settlement-attestation-v1",
    "receipt_hash": "sha256:<hex64>",
    "receipt": { ... }
  }
}
]]></sourcecode>
<t>The <tt>frame_id</tt> is the stable correlation handle for the orchestrator
managing a multi-step payment workflow. Agents reference the
<tt>frame_id</tt> in subsequent task messages without carrying the full
receipt bytes.</t>
</section>

<section anchor="mpp-payment-method-response"><name>7.4. MPP Payment Method Response</name>
<t>In Multi-Party Payment (MPP) flows, a PEF frame MAY be included in
the payment method authorisation response body, providing the payer
agent with a portable receipt envelope that references the
compliance-screen and settlement events in a single
content-addressed form.</t>
</section>

<section anchor="audit-chain-integration"><name>7.5. Audit Chain Integration</name>
<t>A PEF frame MAY be anchored into an audit chain as a chain row. The
chain row shape per draft-hopley-x402-compliance-receipt Section 5.1
uses the frame's <tt>receipt_hash</tt> (the SHA-256 of the inner receipt)
as the <tt>row_content_hash</tt>. This enables an audit chain that
interleaves PEF frames with raw receipt records: a chain walker can
verify both the inner receipt and the frame envelope from a single
retained chain.</t>
<t>Alternatively, the <tt>frame_id</tt> itself (the SHA-256 of the JCS
preimage) MAY be used as the <tt>row_content_hash</tt> when the audit chain
is a chain of frames rather than a chain of raw receipts. In this
case the chain references frame envelopes, and each frame is
independently verifiable.</t>
</section>
</section>

<section anchor="year-n-auditability-properties"><name>8. Year-N Auditability Properties</name>
<t>The six properties pinned by
draft-hopley-x402-canonicalisation-jcs Section 5 apply to the PEF
frame:</t>

<ol spacing="compact">
<li>Self-describing canonicalisation pin via <tt>canon_version</tt>.</li>
<li>No external rule registry required.</li>
<li>Cross-implementation verifiability (8-implementation matrix per
the discipline I-D).</li>
<li>Tamper detection via <tt>receipt_hash</tt> (inner receipt) and
<tt>frame_id</tt> (frame envelope).</li>
<li>Regulatory lifecycle coverage via closed <tt>claim_type</tt> enumeration
spanning all five payment lifecycle events.</li>
</ol>
<t>Plus three PEF-specific properties:</t>

<ol start="6">
<li><t><strong>Stable cross-system identifier.</strong> <tt>frame_id</tt> is derivable by
any party holding the frame bytes using only SHA-256 and the JCS
discipline. A consumer reading a retained <tt>frame_id</tt> reference
years after emission can re-derive the identifier from the stored
frame bytes without access to any AlgoVoi infrastructure.</t>
</li>
<li><t><strong>Inner receipt integrity without deserialisation.</strong> <tt>receipt_hash</tt>
is SHA-256(JCS(<tt>receipt</tt>)). A consumer verifying a stored frame
confirms inner receipt integrity with one hash comparison. The
inner receipt remains independently verifiable at its own content
address.</t>
</li>
<li><t><strong>Signature stability.</strong> The optional <tt>signature</tt> field, if
subsequently added to a stored frame, does not alter <tt>frame_id</tt>.
Audit chain entries referencing a <tt>frame_id</tt> remain valid after
the frame is signed. This allows post-hoc signature enrichment of
stored frames without invalidating existing references.</t>
</li>
</ol>
</section>

<section anchor="iana-considerations"><name>9. IANA Considerations</name>

<section anchor="urn-namespace-registration"><name>9.1. URN Namespace Registration</name>
<t>This document references the URN
<tt>urn:x402:canonicalisation:jcs-rfc8785-v1</tt> registered by
draft-hopley-x402-canonicalisation-jcs Section 10.1. No additional
URN namespace registration is required by this document.</t>
</section>

<section anchor="frame-format-identifier"><name>9.2. Frame Format Identifier</name>
<t>This document defines the frame format identifier:</t>

<artwork><![CDATA[urn:x402:frame:payment-evidence-v1
]]></artwork>
<t>This identifier MAY be used by PEF implementations to refer to
Payment Evidence Frames as a class. Registration with IANA is
requested under the <tt>x402</tt> URN namespace.</t>
</section>

<section anchor="claim-type-registry"><name>9.3. Claim Type Registry</name>
<t>This document defines the <tt>claim_type</tt> closed enumeration:</t>

<artwork><![CDATA[payment_admission
payment_settlement
payment_cancellation
payment_refund
composite_verdict
]]></artwork>
<t>These values are defined for the <tt>urn:x402:frame:payment-evidence-v1</tt>
frame format. Future additions to the enumeration would require a
new I-D revising this document.</t>
</section>
</section>

<section anchor="security-considerations"><name>10. Security Considerations</name>

<section anchor="frame-tampering"><name>10.1. Frame Tampering</name>
<t>A PEF frame's <tt>frame_id</tt> is the SHA-256 of its JCS-canonical
preimage. Tampering with any field in the preimage (any field other
than <tt>signature</tt>) produces a different hash; the tampered frame
fails verification against any stored <tt>frame_id</tt> reference.
Tampering with the inner <tt>receipt</tt> is detected by <tt>receipt_hash</tt>
mismatch before <tt>frame_id</tt> is even computed. Implementations MUST
verify both <tt>receipt_hash</tt> and <tt>frame_id</tt> before accepting a frame.</t>
</section>

<section anchor="preimage-exclusion"><name>10.2. Preimage Exclusion</name>
<t>The <tt>frame_id</tt> excludes <tt>signature</tt> from its preimage (Section 4).
This is an intentional design choice that enables signature addition
after <tt>frame_id</tt> derivation. A consumer MUST NOT include <tt>signature</tt>
in the preimage when verifying <tt>frame_id</tt>; doing so would make
unsigned and signed frames verify differently, breaking stable
cross-system references.</t>
</section>

<section anchor="frame-provider-identity"><name>10.3. Frame Provider Identity</name>
<t>The <tt>frame_provider_did</tt> field is a self-asserted DID. It identifies
the party that constructed the frame but does not by itself prove
that party's identity to a consumer. Consumers MUST establish trust
in the frame provider through out-of-band means (DID method
resolution, certificate authority, mutual-trust agreement, or the
optional <tt>signature</tt> field per draft-hopley-x402-rfc9421-x402-binding).</t>
</section>

<section anchor="claim-type-mismatch"><name>10.4. Claim Type Mismatch</name>
<t>A malicious party could embed a <tt>compliance-receipt-v1</tt> inner receipt
in a frame with <tt>claim_type: payment_settlement</tt>. Implementations
MUST verify that <tt>claim_type</tt> and <tt>receipt_format</tt> are consistent
per the mapping in Section 3.3, and MUST verify that the inner
receipt's self-declared format (its own version field or equivalent)
matches <tt>receipt_format</tt>. A mismatch MUST cause the frame to be
rejected.</t>
</section>

<section anchor="receipt-hash-collision"><name>10.5. Receipt Hash Collision</name>
<t><tt>receipt_hash</tt> is SHA-256, which is collision-resistant to currently
known attacks. A consumer SHOULD NOT accept a frame whose
<tt>receipt_hash</tt> is all-zeros or any other degenerate value. The
concern is not SHA-256 weakness but implementation errors that emit
a zero hash when the inner receipt is empty or malformed; the
<tt>receipt</tt> field MUST be a non-empty object.</t>
</section>

<section anchor="signature-absence"><name>10.6. Signature Absence</name>
<t>The <tt>signature</tt> field is OPTIONAL. Its absence does not indicate a
frame is invalid or untrustworthy; many legitimate frames are
unsigned. Consumers that require a transport-layer identity
guarantee (e.g. for regulatory-grade evidence submission) SHOULD
require the <tt>signature</tt> field to be present and verify it per
draft-hopley-x402-rfc9421-x402-binding before accepting the frame
as authoritative evidence.</t>
</section>

<section anchor="timestamp-integrity"><name>10.7. Timestamp Integrity</name>
<t><tt>frame_timestamp_ms</tt> is self-asserted by the frame provider. It
records the claimed time at which the frame was constructed, not a
verified time. Consumers relying on frame timestamps for
time-sensitive decisions (e.g. refund window eligibility) SHOULD
verify the timestamp against independently-derived evidence
(settlement chain timestamps, HTTP Date header, blockchain block
timestamp).</t>
</section>
</section>

<section anchor="references"><name>11. References</name>

<section anchor="normative-references"><name>11.1. Normative References</name>

<ul spacing="compact">
<li>[RFC2119] Bradner, S., &quot;Key words for use in RFCs to Indicate
Requirement Levels&quot;, BCP 14, RFC 2119, DOI 10.17487/RFC2119,
March 1997.</li>
<li>[RFC8174] Leiba, B., &quot;Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words&quot;, BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017.</li>
<li>[RFC8259] Bray, T., Ed., &quot;The JavaScript Object Notation (JSON)
Data Interchange Format&quot;, STD 90, RFC 8259, DOI 10.17487/RFC8259,
December 2017.</li>
<li>[RFC8785] Rundgren, A., Jordan, B., and S. Erdtman, &quot;JSON
Canonicalization Scheme (JCS)&quot;, RFC 8785, DOI 10.17487/RFC8785,
June 2020.</li>
</ul>
</section>

<section anchor="informative-references"><name>11.2. Informative References</name>

<ul spacing="compact">
<li>draft-hopley-x402-canonicalisation-jcs, Hopley, C., &quot;JCS
Canonicalisation Discipline for Agentic-Payment Receipts&quot;,
May 2026.</li>
<li>draft-hopley-x402-compliance-receipt, Hopley, C., &quot;Categorical
Compliance Screening Receipt Format for Agentic-Payment Flows&quot;,
May 2026.</li>
<li>draft-hopley-x402-settlement-attestation, Hopley, C.,
&quot;Categorical Settlement Attestation Format for Agentic-Payment
Flows&quot;, May 2026.</li>
<li>draft-hopley-x402-cancellation-receipt, Hopley, C.,
&quot;Categorical Mandate Cancellation Receipt Format for
Agentic-Payment Flows&quot;, May 2026.</li>
<li>draft-hopley-x402-refund-receipt, Hopley, C., &quot;Categorical
Refund Receipt Format for Agentic-Payment Flows&quot;, May 2026.</li>
<li>draft-hopley-x402-composite-trust-query, Hopley, C., &quot;Composite
Trust Query Response Format for Agentic-Payment Audit Chains&quot;,
May 2026.</li>
<li>draft-hopley-x402-rfc9421-x402-binding, Hopley, C., &quot;RFC 9421
HTTP Message Signatures Binding for x402 Payment Frames&quot;,
May 2026.</li>
<li>AlgoVoi, &quot;Substrate Authorship and Provenance&quot;,
<eref target="https://docs.algovoi.co.uk/substrate-authorship-provenance">https://docs.algovoi.co.uk/substrate-authorship-provenance</eref></li>
<li>AlgoVoi, &quot;Payment Evidence Frame reference implementation&quot;,
<eref target="https://pypi.org/project/algovoi-pef/">https://pypi.org/project/algovoi-pef/</eref></li>
<li>EU Markets in Crypto-Assets Regulation (MiCA, Regulation (EU)
2023/1114), Article 80.</li>
<li>EU Anti-Money Laundering Regulation (AMLR, Regulation (EU)
2024/1624), Article 56.</li>
<li>EU Payment Services Directive 2 (PSD2, Directive 2015/2366),
Articles 64, 72, 89.</li>
</ul>
</section>
</section>

</middle>

<back>

<section anchor="appendix-a-examples-informative"><name>Appendix A. Examples (Informative)</name>

<section anchor="a-1-payment-admission-compliance-screen-allow"><name>A.1. payment_admission -- compliance screen ALLOW</name>

<sourcecode type="json"><![CDATA[{
  "canon_version": "urn:x402:canonicalisation:jcs-rfc8785-v1",
  "claim_type": "payment_admission",
  "frame_id": "sha256:9badca886409ed26d09adfe6ce133a53100909dd4544d4ad160e130b6a755f29",
  "frame_provider_did": "did:key:z6MkgExzvcpvxrghf4Q3285xqSdenhRZHcP6wc5UvY6VVaz5",
  "frame_timestamp_ms": 1780143974835,
  "pef_version": "1",
  "receipt": {
    "canon_version": "jcs-rfc8785-v1",
    "jurisdiction_flags": ["UK", "EU"],
    "payer_ref": "sha256:e0f023d54479255752bac099d0565984b5884afec0f1a1ebe27e0eaf70a205ba",
    "screen_provider_did": "did:key:z6MkgExzvcpvxrghf4Q3285xqSdenhRZHcP6wc5UvY6VVaz5",
    "screen_result": "ALLOW",
    "screen_timestamp_ms": 1780143974835
  },
  "receipt_format": "compliance-receipt-v1",
  "receipt_hash": "sha256:bc7a68b64925b8a76109d35e89cca4c7ae04073fa686844975a5b5f4410afa27"
}
]]></sourcecode>
<t>A compliance screen result of ALLOW. The <tt>frame_id</tt> is stable: any
downstream consumer, agent, or audit system holding the same inner
receipt and frame metadata MUST derive the identical <tt>frame_id</tt>.</t>
</section>

<section anchor="a-2-payment-settlement-settled-on-chain"><name>A.2. payment_settlement -- settled on-chain</name>

<sourcecode type="json"><![CDATA[{
  "canon_version": "urn:x402:canonicalisation:jcs-rfc8785-v1",
  "claim_type": "payment_settlement",
  "frame_id": "sha256:3c4f1e2a8b7d6e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f",
  "frame_provider_did": "did:web:api.algovoi.co.uk",
  "frame_timestamp_ms": 1780144012000,
  "pef_version": "1",
  "receipt": {
    "amount_microunits": 1000000,
    "canon_version": "jcs-rfc8785-v1",
    "jurisdiction_flags": ["UK"],
    "settled_payment_ref": "sha256:0dd5d0b76c9b9281fdeb2509ad38ab132b16a17385ca01d976ff9e6e12563a0f",
    "settlement_chain": "base_mainnet",
    "settlement_provider_did": "did:web:api.algovoi.co.uk",
    "settlement_result": "SETTLED",
    "settlement_timestamp_ms": 1780144010000
  },
  "receipt_format": "settlement-attestation-v1",
  "receipt_hash": "sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
}
]]></sourcecode>
<t>A confirmed on-chain settlement on <tt>base_mainnet</tt>. The <tt>frame_id</tt>
can be passed in the x402 <tt>/verify</tt> response body as
<tt>settlement_evidence.frame_id</tt>, allowing the merchant backend to
reference the payment evidence without embedding the full receipt.</t>
</section>

<section anchor="a-3-payment-cancellation-mandate-terminated-by-compliance"><name>A.3. payment_cancellation -- mandate terminated by compliance</name>

<sourcecode type="json"><![CDATA[{
  "canon_version": "urn:x402:canonicalisation:jcs-rfc8785-v1",
  "claim_type": "payment_cancellation",
  "frame_id": "sha256:b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3",
  "frame_provider_did": "did:web:api.algovoi.co.uk",
  "frame_timestamp_ms": 1780145000000,
  "pef_version": "1",
  "receipt": {
    "cancellation_reason": "COMPLIANCE_TERMINATED",
    "cancellation_timestamp_ms": 1780144990000,
    "canon_version": "jcs-rfc8785-v1",
    "issuer_did": "did:web:api.algovoi.co.uk",
    "jurisdiction_flags": ["UK", "EU"],
    "mandate_ref": "sha256:c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4"
  },
  "receipt_format": "cancellation-receipt-v1",
  "receipt_hash": "sha256:d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5"
}
]]></sourcecode>
<t>A mandate terminated by compliance action. The <tt>claim_type</tt> signals
<tt>payment_cancellation</tt> without the consumer needing to inspect the
inner receipt's <tt>cancellation_reason</tt> field to classify the event.</t>
</section>

<section anchor="a-4-payment-refund-partial-refund-issued"><name>A.4. payment_refund -- partial refund issued</name>

<sourcecode type="json"><![CDATA[{
  "canon_version": "urn:x402:canonicalisation:jcs-rfc8785-v1",
  "claim_type": "payment_refund",
  "frame_id": "sha256:e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6",
  "frame_provider_did": "did:web:api.algovoi.co.uk",
  "frame_timestamp_ms": 1780146000000,
  "pef_version": "1",
  "receipt": {
    "canon_version": "jcs-rfc8785-v1",
    "issuer_did": "did:web:api.algovoi.co.uk",
    "jurisdiction_flags": ["UK"],
    "refund_amount_microunits": 500000,
    "refund_result": "PARTIAL",
    "refund_timestamp_ms": 1780145990000,
    "settlement_ref": "sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
  },
  "receipt_format": "refund-receipt-v1",
  "receipt_hash": "sha256:f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7"
}
]]></sourcecode>
<t>A partial refund. Note the <tt>settlement_ref</tt> in the inner receipt
linking back to the settlement attestation frame -- the full
lifecycle is traceable by <tt>frame_id</tt> at each stage.</t>
</section>

<section anchor="a-5-composite-verdict-verifier-of-verifier-trusted"><name>A.5. composite_verdict -- verifier-of-verifier TRUSTED</name>

<sourcecode type="json"><![CDATA[{
  "canon_version": "urn:x402:canonicalisation:jcs-rfc8785-v1",
  "claim_type": "composite_verdict",
  "frame_id": "sha256:a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8",
  "frame_provider_did": "did:web:api.algovoi.co.uk",
  "frame_timestamp_ms": 1780147000000,
  "pef_version": "1",
  "receipt": {
    "canon_version": "jcs-rfc8785-v1",
    "chain_ref": "sha256:0dd5d0b76c9b9281fdeb2509ad38ab132b16a17385ca01d976ff9e6e12563a0f",
    "ctq_timestamp_ms": 1780146990000,
    "jurisdiction_flags": ["UK", "EU"],
    "query_ref": "sha256:8b7df143d91c716ecfa5fc1730022f6b421b05cedee8fd52b1fc65a96030ad52",
    "trust_outcome": "TRUSTED",
    "verifier_did": "did:web:api.algovoi.co.uk"
  },
  "receipt_format": "composite-trust-query-v1",
  "receipt_hash": "sha256:b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9"
}
]]></sourcecode>
<t>A composite trust query verdict of TRUSTED, wrapped in a PEF frame
for transport. The <tt>frame_id</tt> can be passed to an orchestrating
agent as the correlation handle for the full audit conclusion,
without embedding the full CTQ response in every downstream message.</t>
</section>

<section anchor="a-6-signed-frame-optional-signature-field"><name>A.6. Signed Frame (OPTIONAL signature field)</name>

<sourcecode type="json"><![CDATA[{
  "canon_version": "urn:x402:canonicalisation:jcs-rfc8785-v1",
  "claim_type": "payment_settlement",
  "frame_id": "sha256:3c4f1e2a8b7d6e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f",
  "frame_provider_did": "did:web:api.algovoi.co.uk",
  "frame_timestamp_ms": 1780144012000,
  "pef_version": "1",
  "receipt": { "..." : "..." },
  "receipt_format": "settlement-attestation-v1",
  "receipt_hash": "sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
  "signature": "sig=:base64url-encoded-signature:; keyid=\"...\"; created=1780144012"
}
]]></sourcecode>
<t>The <tt>frame_id</tt> is identical to the unsigned example in A.2. Adding
<tt>signature</tt> does not change the <tt>frame_id</tt> because <tt>signature</tt> is
excluded from the preimage. Downstream references to the <tt>frame_id</tt>
derived before signing remain valid.</t>
</section>
</section>

<section anchor="appendix-b-reference-implementations-informative"><name>Appendix B. Reference Implementations (Informative)</name>
<t>The following open-source implementations conform to this format.
Both implement <tt>build_pef()</tt>, <tt>verify_pef()</tt>, and <tt>pef_frame_id()</tt>
with byte-for-byte cross-language parity.</t>

<ul>
<li><t>algovoi-pef (Python) on PyPI:
<eref target="https://pypi.org/project/algovoi-pef/">https://pypi.org/project/algovoi-pef/</eref>
Depends on algovoi-substrate for the JCS canonicalisation
primitive. Apache 2.0 licensed.</t>
</li>
<li><t>@algovoi/pef (TypeScript) on npm:
<eref target="https://www.npmjs.com/package/@algovoi/pef">https://www.npmjs.com/package/@algovoi/pef</eref>
Byte-for-byte parity with the Python sibling. Depends on
@algovoi/substrate for the JCS canonicalisation primitive.
Apache 2.0 licensed.</t>
</li>
</ul>
<t>A live production instance of PEF emission is accessible at:</t>

<artwork><![CDATA[POST https://api.algovoi.co.uk/compliance/screen
]]></artwork>
<t>The <tt>compliance_receipt_pef</tt> field in the response carries a
<tt>payment_admission</tt> PEF frame when the screen result is ALLOW or
DENY. The <tt>frame_id</tt> is derivable by any party holding the
returned frame using only SHA-256 and the JCS discipline.</t>
</section>

<section anchor="known-adopters-informative"><name>Known Adopters (Informative)</name>
<table>
<thead>
<tr>
<th>Adopter</th>
<th>Surface</th>
<th>Claim types emitted</th>
</tr>
</thead>

<tbody>
<tr>
<td>AlgoVoi (<tt>api.algovoi.co.uk</tt>)</td>
<td><tt>/compliance/screen</tt> response</td>
<td><tt>payment_admission</tt></td>
</tr>

<tr>
<td>AlgoVoi (<tt>api.algovoi.co.uk</tt>)</td>
<td><tt>/checkout/*/verify</tt> response</td>
<td><tt>payment_settlement</tt></td>
</tr>
</tbody>
</table></section>

<section anchor="acknowledgments"><name>Acknowledgments</name>
<t>This document, the frame format it specifies, and the reference
implementations derived from it are AlgoVoi work under AlgoVoi
authorship. Substrate authorship history is catalogued at
<eref target="https://docs.algovoi.co.uk/substrate-authorship-provenance">https://docs.algovoi.co.uk/substrate-authorship-provenance</eref>.</t>
<t>The canonicalisation discipline pinned by Section 6 is normatively
specified in draft-hopley-x402-canonicalisation-jcs under the same
authorship.</t>
<t>This document closes the transport layer gap in the agentic-payment
receipt stack. Below it sit five AlgoVoi-authored receipt formats:
compliance, settlement, cancellation, refund, and composite trust
query. PEF sits above all five and provides the stable cross-system
identifier and taxonomy label that enables receipt bytes to travel
across HTTP, agent-to-agent, and audit-chain boundaries without
losing their identity or requiring the consumer to parse the inner
format before routing.</t>
<t>The author acknowledges Anders Rundgren as the editor of RFC 8785,
the JSON Canonicalization Scheme on which the canonicalisation
discipline builds.</t>
</section>

</back>

</rfc>
