<?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-canonicalisation-jcs-v1-03" submissionType="IETF" category="info" xml:lang="en" xmlns:xi="http://www.w3.org/2001/XInclude" indexInclude="true">

<front>
<title abbrev="x402-canonicalisation-jcs">JCS Canonicalisation Discipline for Agentic-Payment Receipts</title><seriesInfo value="draft-hopley-x402-canonicalisation-jcs-v1-03" stream="IETF" status="informational" name="Internet-Draft"></seriesInfo>
<author initials="C." surname="Hopley" fullname="Christopher Hopley"><organization>AlgoVoi</organization><address><postal><street></street>
</postal><email>chopmob@gmail.com</email>
</address></author><date year="2026" month="June" day="15"></date>
<area>Independent Submission</area>
<workgroup>Independent Submission</workgroup>
<keyword>x402</keyword>
<keyword>agentic payments</keyword>
<keyword>JCS</keyword>
<keyword>RFC 8785</keyword>
<keyword>canonicalisation</keyword>
<keyword>receipt format</keyword>
<keyword>audit retention</keyword>

<abstract>
<t>This document specifies a canonicalisation discipline for
agentic-payment receipt formats. The discipline pins JSON Canonicalization
Scheme (JCS, RFC 8785) as the canonical preimage form, plus a small
set of schema-normalisation rules that must be applied before
canonicalisation to preserve byte-determinism across independent
implementations and across statutory retention periods.</t>
<t>The discipline is identified by the URN
<tt>urn:x402:canonicalisation:jcs-rfc8785-v1</tt>. Receipt formats that
reference this discipline carry an in-band <tt>canon_version</tt> field
recording the version under which they were emitted, enabling
year-N re-verification of retained bytes without dependence on an
out-of-band rule registry.</t>
<t>The discipline is byte-for-byte cross-validated across eight
independent JCS implementations in eight programming languages:
Python (<tt>rfc8785</tt>), TypeScript (<tt>canonicalize</tt>), Go
(<tt>gowebpki/jcs</tt>), Rust (<tt>serde_jcs</tt>), Java
(<tt>cyberphone/json-canonicalization</tt>, by the RFC 8785 editor), PHP
(<tt>root23/php-json-canonicalization</tt>), C#/.NET
(<tt>Baqhub.Packages.JsonCanonicalization</tt>), and Ruby
(<tt>json-canonicalization</tt>). The attestation record covering 192
byte-for-byte agreements is published at the AlgoVoi conformance
vectors repository.</t>
<t>This document is normatively referenced by
[draft-hopley-x402-compliance-receipt],
[draft-hopley-x402-refund-receipt], and successor AlgoVoi-authored
receipt-format Internet-Drafts. It is complementary to
[draft-vauban-x402-stark-receipts], which uses a compatible
canonicalisation discipline for its cryptographic settlement proofs.</t>
<t>This document is an Independent Submission filed per RFC 4846 and
is intended for publication as Informational. It is not an IETF
Standards Track document, does not represent IETF community
consensus, and has not been subject to review by an IETF Working
Group. Change control resides with the document author. The
canonicalisation discipline specified is one approach among
possible alternatives; implementers may choose this approach,
alternative approaches, or hybrid approaches as appropriate to
their requirements.</t>
</abstract>

</front>
<middle>
<section anchor="sect-1-introduction"><name>Introduction</name>

<section anchor="sect-1-1-motivation"><name>Motivation</name>
<t>Agentic-payment receipt formats (including the AlgoVoi compliance
receipt, refund receipt, and successor formats in this series)
take a content hash over a canonicalised JSON object:</t>

<artwork><![CDATA[content_hash = SHA-256( canonicalize( object ) )
]]></artwork>
<t>If two implementations of a receipt format canonicalise the same
logical object differently, they produce different content hashes.
Downstream verifiers see hash mismatch and reject the receipt; audit
chains break; year-N supervisor re-verification of retained bytes
fails.</t>
<t>This problem is well-understood in the JSON canonicalisation
literature. RFC 8785 (JCS) provides the standard solution at the
canonicalisation layer: a single deterministic JSON encoding rule
that every conforming implementation produces identically.</t>
<t>What RFC 8785 does NOT specify is the <strong>schema-normalisation
discipline that must be applied BEFORE canonicalisation</strong>. Receipt
formats that emit <tt>timestamp</tt> as RFC 3339 strings, that allow
duplicate keys in source JSON, or that fail to pin field-name
normalisation produce divergent canonical bytes despite both
implementations being RFC 8785 conformant. The receipt format
itself must impose pre-canonicalisation discipline.</t>
<t>This document specifies the discipline.</t>
</section>

<section anchor="sect-1-2-scope"><name>Scope</name>
<t>This document specifies:</t>

<ul spacing="compact">
<li>The canonicalisation rule used for content hashes
(Section 3).</li>
<li>The schema-normalisation requirements applied BEFORE
canonicalisation (Section 4).</li>
<li>The retention property (Section 5) that motivates the discipline
for statutory record-keeping under MiCA, AMLR, and DORA.</li>
<li>The version pin (<tt>canon_version</tt> field) and its compatibility
semantics (Section 6).</li>
<li>Cross-implementation reproducibility evidence (Section 7).</li>
<li>Non-normative recommendations for the <tt>action_ref</tt> primitive
(Sections 8 and 9).</li>
</ul>
<t>This document does NOT specify:</t>

<ul spacing="compact">
<li>A specific receipt format. Receipt formats are specified by
dedicated I-Ds (e.g. <tt>draft-hopley-x402-compliance-receipt</tt>,
<tt>draft-hopley-x402-refund-receipt</tt>) that normatively reference
this canonicalisation discipline.</li>
<li>A wire protocol. The discipline applies at the
canonicalisation-of-an-object layer; the wire protocol that
transports the canonical bytes is out of scope.</li>
<li>Cryptographic settlement proofs. Cryptographically-strong
settlement proofs are an orthogonal mechanism specified
elsewhere (out of scope for this canonicalisation discipline).</li>
</ul>
</section>

<section anchor="sect-1-3-relationship-to-other-internet-drafts"><name>Relationship to other Internet-Drafts</name>
<t>This document is normatively referenced by:</t>

<ul spacing="compact">
<li><eref target="admission-time compliance
screening receipts"> target="admission-time compliance
screening receipts"</eref></li>
<li><eref target="post-settlement refund
receipts"> target="post-settlement refund
receipts"</eref></li>
<li>Future AlgoVoi-authored receipt-format I-Ds (settlement
attestation, cancellation receipt, mandate revocation receipt,
etc.)</li>
</ul>
</section>

<section anchor="sect-1-4-authorship-and-provenance"><name>Authorship and provenance</name>
<t>This document, the canonicalisation discipline it specifies, and the
conformance vectors derived from it are AlgoVoi work under sole
AlgoVoi authorship. Substrate authorship history is catalogued at
<eref target="https://docs.algovoi.co.uk/substrate-authorship-provenance"> target="https://docs.algovoi.co.uk/substrate-authorship-provenance"</eref>.</t>
</section>
</section>

<section anchor="sect-2-conventions-and-definitions"><name>Conventions and Definitions</name>

<section anchor="sect-2-1-notation"><name>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="sect-2-2-definitions"><name>Definitions</name>
<t><strong>canonicalisation discipline</strong>: the combination of (a) the
canonicalisation rule (Section 3) and (b) the schema-normalisation
requirements (Section 4). A receipt format that references this
discipline must conform to both.</t>
<t><strong>canon_version</strong>: an in-band string identifying which version of
this canonicalisation discipline applies. Fixed value
<tt>jcs-rfc8785-v1</tt> for the discipline specified in this document.
Future versions of this discipline MUST increment <tt>canon_version</tt>.</t>
<t><strong>content hash</strong>: SHA-256, lowercase hex, of the canonical bytes
produced by applying this discipline to a JSON object.</t>
<t><strong>JCS</strong>: JSON Canonicalization Scheme as specified in [RFC8785].</t>
<t><strong>load-bearing under canonicalisation</strong>: a field whose value, type,
or ordering produces byte-distinct canonical bytes from any
variation. Implementations MUST preserve load-bearing properties
exactly during emission and verification.</t>
<t><strong>Substrate Rule 2</strong>: the schema-normalisation requirement that
timestamp fields MUST be JSON integers (milliseconds since Unix
epoch) and MUST NOT be RFC 3339 strings. So-named because it was
the second normative rule formalised in the canonicalisation
discipline; the first was the JCS pin itself.</t>
</section>
</section>

<section anchor="sect-3-the-canonicalisation-discipline"><name>The Canonicalisation Discipline</name>
<t>The canonicalisation discipline specified by this document is
identified by the URN:</t>

<artwork><![CDATA[urn:x402:canonicalisation:jcs-rfc8785-v1
]]></artwork>
<t>A content hash produced under this discipline is computed as:</t>

<artwork><![CDATA[content_hash = SHA-256( JCS( object ) ), lowercase hex
]]></artwork>
<t>Where:</t>

<ul spacing="compact">
<li><tt>object</tt> is a JSON object that has been through the
schema-normalisation requirements of Section 4.</li>
<li><tt>JCS</tt> is the JSON Canonicalization Scheme of [RFC8785].</li>
<li><tt>SHA-256</tt> is the cryptographic hash function of [RFC6234].</li>
</ul>
<t>The lowercase-hex encoding of the SHA-256 output is canonical.
Uppercase-hex or base64-encoded forms are NOT acceptable for
<tt>content_hash</tt> values that participate in cross-implementation
hash equality checks.</t>
</section>

<section anchor="sect-4-schema-normalisation-requirements"><name>Schema Normalisation Requirements</name>
<t>Schema normalisation MUST be applied BEFORE canonicalisation. The
following requirements are normative.</t>

<section anchor="sect-4-1-substrate-rule-2-integer-millisecond-timestamps"><name>Substrate Rule 2 -- integer-millisecond timestamps</name>
<t>Timestamp fields whose semantic is &quot;an instant in time&quot; MUST be
encoded as JSON integers representing milliseconds since the Unix
epoch (1970-01-01T00:00:00Z).</t>
<t>RFC 3339 string forms (e.g. <tt>&quot;2026-05-28T12:00:00Z&quot;</tt>) are NOT
acceptable as canonical preimage form.</t>
<t>Rationale: RFC 3339 admits multiple lexically distinct encodings of
the same semantic instant (e.g. <tt>&quot;2026-05-28T12:00:00Z&quot;</tt> vs
<tt>&quot;2026-05-28T12:00:00+00:00&quot;</tt> vs <tt>&quot;2026-05-28T13:00:00+01:00&quot;</tt>).
These produce different JCS canonical bytes and therefore different
SHA-256 hashes despite representing the same instant. The integer
form is unambiguous: a given instant has exactly one millisecond
representation, and JCS encodes integers deterministically per
[RFC8785] Section 3.2.2.3.</t>
<t>Implementations MUST reject non-integer timestamp inputs (RFC 3339
strings, floating-point milliseconds, ISO duration strings, etc.)
at the validation step BEFORE canonicalisation. Coercion of
non-conforming inputs is non-conforming behaviour (Section 4.5).</t>
</section>

<section anchor="sect-4-2-field-names-are-load-bearing-opaque-bytes"><name>Field names are load-bearing opaque bytes</name>
<t>Field names are load-bearing under RFC 8785. Renaming a field while
preserving its value produces a different canonical content hash.</t>
<t>Schemas using this discipline MUST pin field names exactly. Aliases
at the wire layer (e.g. accepting <tt>tx_id</tt> as an alias for
<tt>transaction_id</tt>) MUST be normalised to the canonical name before
canonicalisation.</t>
<t>This rule is consistent with [RFC8785] Section 3.2.3, which sorts
object keys lexicographically by code point but does not normalise
or alias keys.</t>
</section>

<section anchor="sect-4-3-array-element-order-is-preserved"><name>Array element order is preserved</name>
<t>Array element order is preserved under RFC 8785 ([RFC8785]
Section 3.2.3). Arrays are NOT sorted during canonicalisation.</t>
<t><tt>[&quot;EU&quot;, &quot;UK&quot;]</tt> and <tt>[&quot;UK&quot;, &quot;EU&quot;]</tt> produce different canonical bytes
and different content hashes.</t>
<t>Schemas requiring a canonical array order MUST specify it at the
schema level (e.g. &quot;the <tt>jurisdiction_flags</tt> array MUST be ordered
primary-jurisdiction-first&quot;), NOT rely on JCS to impose ordering.</t>
</section>

<section anchor="sect-4-4-numeric-values-follow-rfc-8785-section-3-2-2-3"><name>Numeric values follow RFC 8785 Section 3.2.2.3</name>
<t>Numeric values in JSON objects are canonicalised per [RFC8785]
Section 3.2.2.3. Implementations MUST emit numbers in the canonical
form specified there.</t>
<t>For amount-typed fields (e.g. payment amounts, refund amounts),
schemas SHOULD encode amounts as decimal-digit strings in the
asset's minor unit rather than as JSON numbers. Rationale: large
amounts may exceed JavaScript's <tt>Number.MAX_SAFE_INTEGER</tt>
(2^53 - 1), and floating-point JSON numbers admit
representation-precision loss across implementations. String
encoding avoids both classes of failure.</t>
</section>

<section anchor="sect-4-5-type-validation-precedes-canonicalisation"><name>Type validation precedes canonicalisation</name>
<t>Type validation occurs BEFORE canonicalisation. Verifiers MUST
reject non-conforming inputs at the parse or schema-validation step,
NOT by coercing to canonical form before computing content hashes.</t>
<t>Specifically, verifiers MUST reject (not coerce) inputs with:</t>

<ul spacing="compact">
<li>Wrong scalar type for a field (e.g. RFC 3339 string for a
timestamp; floating-point number for a minor-unit amount).</li>
<li>Missing required fields.</li>
<li>Duplicate keys in source JSON.</li>
<li>Non-normalised Unicode where the schema pins a normalisation
form (e.g. NFC for DID URIs).</li>
</ul>
<t>Producer-side rule violations should fail loudly at conformance
test. Verifier-side coercion fails silently as cross-observer
disagreement months later, AND breaks re-verifiability at audit
time: the coercion step is verifier-local and will not be replayed
identically by a supervisor running the canonical rule against the
raw retained object.</t>
</section>

<section anchor="sect-4-6-in-band-rule-pin-canon-version"><name>4.6. In-band rule pin (<tt>canon_version</tt>)</name>
<t>Objects produced under this discipline SHOULD include a
<tt>canon_version</tt> field carrying the discipline version under which
they were emitted. The current value is <tt>jcs-rfc8785-v1</tt>.</t>
<t>Producers emitting objects under a statutory retention obligation
(see Section 5) MUST include <tt>canon_version</tt>. The rule version
must be determinable at re-verification time without reference to
the emitting system's current configuration.</t>
<t><tt>canon_version</tt> is itself canonicalised and contributes to the
content hash. A receipt emitted under one discipline version cannot
be silently re-hashed under a successor version.</t>
</section>
</section>

<section anchor="sect-5-retention-property"><name>Retention Property</name>
<t>Canonicalisation determinism is a retention obligation as well as a
cross-observer property. Objects produced for frameworks with
retention obligations under European Union law MUST be re-verifiable
against the canonicalisation rule version under which they were
emitted. Applicable frameworks include:</t>

<ul spacing="compact">
<li>Markets in Crypto-Assets Regulation, Article 80 (Regulation (EU)
2023/1114): operator records of crypto-asset transactions must
be retained and re-verifiable for the statutory period.</li>
<li>Anti-Money Laundering Regulation, Article 56 (Regulation (EU)
2024/1624): obliged entity records must be retained for five
years and made available to competent authorities.</li>
<li>Digital Operational Resilience Act, Article 14 (Regulation (EU)
2022/2554): ICT-related incident and operational records must be
retained and audit-traceable.</li>
</ul>
<t>A supervisor re-verifying retained bytes at year five against a
contemporaneous canonicalisation rule needs identical canonical
bytes across that five-year gap. The rule version must be
determinable from the retained bytes alone, without reference to
the emitting system's current state.</t>
<t>This document's <tt>canon_version</tt> discipline (Section 4.6) makes the
rule version self-describing on the retained bytes. A verifier
reading a receipt years after emission can determine which version
of this canonicalisation discipline to apply and reproduce the
content hash byte-identical.</t>
<t>Equivalent record-keeping obligations apply in jurisdictions outside
the European Union; the discipline is jurisdiction-neutral but the
retention property is named-target for the EU regulations because
their re-verifiability requirement is explicit.</t>
</section>

<section anchor="sect-6-versioning"><name>Versioning</name>
<t>This document specifies version <tt>jcs-rfc8785-v1</tt> of the
canonicalisation discipline.</t>
<t>Future revisions that change any normative requirement in Section 4
or Section 3 MUST increment the <tt>canon_version</tt> (e.g.
<tt>jcs-rfc8785-v2</tt>). Successor versions will be published as
follow-on Internet-Drafts in the same document series
(<tt>draft-hopley-x402-canonicalisation-jcs-v&lt;n&gt;</tt>).</t>
<t>Downstream receipt-format specifications that reference this
discipline MUST cite a specific <tt>canon_version</tt> value. A receipt
format MAY support multiple discipline versions concurrently
(e.g. accept both v1 and v2 on input) but each individual emitted
object carries exactly one <tt>canon_version</tt> value identifying which
rule was applied at emission.</t>
</section>

<section anchor="sect-7-cross-implementation-reproducibility"><name>Cross-Implementation Reproducibility</name>
<t>The canonicalisation discipline has been byte-for-byte cross-validated
across <strong>eight independent JCS implementations in eight programming
languages</strong>, executed on 2026-05-24:</t>
<table>
<thead>
<tr>
<th>Language</th>
<th>Library</th>
<th>Author / authoring entity</th>
</tr>
</thead>

<tbody>
<tr>
<td>Python</td>
<td><tt>rfc8785</tt> 0.1.4</td>
<td>Trail of Bits</td>
</tr>

<tr>
<td>TypeScript</td>
<td><tt>canonicalize</tt> 3.0.0</td>
<td>Samuel Erdtman</td>
</tr>

<tr>
<td>Go</td>
<td><tt>gowebpki/jcs</tt> v1.0.1</td>
<td>Web PKI Working Group</td>
</tr>

<tr>
<td>Rust</td>
<td><tt>serde_jcs</tt> 0.2.0</td>
<td>independent author</td>
</tr>

<tr>
<td>Java</td>
<td><tt>io.github.erdtman:java-json-canonicalization</tt> 1.1</td>
<td>Anders Rundgren (RFC 8785 editor) and Samuel Erdtman</td>
</tr>

<tr>
<td>PHP</td>
<td><tt>root23/php-json-canonicalization</tt> 1.0.1</td>
<td>root23</td>
</tr>

<tr>
<td>C# / .NET</td>
<td><tt>Baqhub.Packages.JsonCanonicalization</tt> 1.0.1</td>
<td>Baqhub</td>
</tr>

<tr>
<td>Ruby</td>
<td><tt>json-canonicalization</tt> 1.0.0</td>
<td>RubyGems community</td>
</tr>
</tbody>
</table><t>All eight implementations were independently authored by
non-overlapping author sets, including the editor of RFC 8785
itself (Anders Rundgren via the Java implementation).</t>
<t>The matrix validates 24 conformance vectors across three anchor sets
(<tt>action_ref_namespace_v0</tt>, <tt>action_ref_transactional_v0</tt>,
<tt>compliance_receipt_v1</tt>), producing 192 byte-for-byte agreements
(24 vectors x 8 implementations). The attestation record is at:</t>

<artwork><![CDATA[https://github.com/chopmob-cloud/algovoi-jcs-conformance-vectors/
    blob/main/_attestations/2026-05-24-8-impl-cross-validation.md
]]></artwork>
<t>A receipt-format implementation conforming to this canonicalisation
discipline, written in any of the eight listed languages, produces
identical canonical bytes for any receipt under the discipline.</t>
</section>

<section anchor="sect-8-scope-conventions-for-action-ref-non-normative"><name>8. Scope Conventions for <tt>action_ref</tt> (Non-Normative)</name>
<t>The <tt>action_ref</tt> atomic primitive is defined elsewhere in the
substrate as:</t>

<artwork><![CDATA[action_ref = SHA-256( JCS( { agent_id, action_type, scope, timestamp_ms } ) )
]]></artwork>
<t>At the canonicalisation layer, the <tt>scope</tt> field is typed as a
non-empty string with no closed enumeration. This document records
a non-normative convention for scope namespacing observed across
production emitters.</t>
<t><strong>Recommended portable form</strong>: <tt>&lt;emitter&gt;:&lt;scope&gt;</tt> namespace prefix.</t>
<t>Current production usage observed across the substrate's emitter
set as of 2026-05-24:</t>
<table>
<thead>
<tr>
<th><tt>scope</tt> value</th>
<th>Emitter surface</th>
</tr>
</thead>

<tbody>
<tr>
<td><tt>algovoi:compliance_screen</tt></td>
<td>AlgoVoi <tt>/compliance/screen</tt></td>
</tr>

<tr>
<td><tt>algovoi:refund</tt></td>
<td>AlgoVoi refund receipt issuer</td>
</tr>

<tr>
<td><tt>algovoi:settlement</tt></td>
<td>AlgoVoi settlement attestation issuer</td>
</tr>
</tbody>
</table><t>Additional emitters using this discipline are expected to
namespace their own <tt>scope</tt> values under a <tt>&lt;emitter&gt;:&lt;scope&gt;</tt>
convention. The substrate does not enumerate third-party
emitters in this specification.</t>
<t>The namespaced value is hashed into <tt>action_ref</tt> like any other
string, so the dedup / idempotency property of the primitive is
preserved. The recommendation gives reputation consumers and
downstream verifiers an unambiguous mapping target where multiple
emitters would otherwise collide on unprefixed short-form scopes
(e.g. two emitters both using <tt>payment</tt> for genuinely different
semantic concepts).</t>
<t>Byte-level reference digests for the four named anchors above plus
four unprefixed equivalents and four pair invariants are pinned in
the <tt>action_ref_namespace_v0</tt> conformance vector set:</t>

<artwork><![CDATA[https://github.com/chopmob-cloud/algovoi-jcs-conformance-vectors/
    tree/main/vectors/action_ref_namespace_v0/
]]></artwork>
<t>Spec-level closure of the scope value-space would lock out future
emitters arriving with valid new scopes and is intentionally
avoided.</t>
</section>

<section anchor="sect-9-transactional-action-ref-lifecycle-non-normative"><name>9. Transactional <tt>action_ref</tt> Lifecycle (Non-Normative)</name>
<t>For transactional flows that traverse multiple state transitions
(authorisation -&gt; settlement -&gt; refund; issuance -&gt; execution -&gt;
revocation; admission -&gt; review -&gt; close), the <tt>action_ref</tt>
primitive serves as a stable identity anchor across the full
lifecycle.</t>
<t>The four-field preimage <tt>{ agent_id, action_type, scope,
timestamp_ms }</tt> is fixed at the moment the action is first
declared and does not change as the action progresses through
state transitions.</t>
<t>Per-transition lifecycle metadata (for example settlement-proof
timestamps, refund-window expiry, authority-verification timestamps,
revocation-check timestamps) lives OUTSIDE the <tt>action_ref</tt>
preimage. These are separate claims that may evolve as the action
moves through its states. Keeping them outside the preimage
preserves the invariant: the <tt>action_ref</tt> digest is stable across
every state transition; the identity of the action does not change
when the authority state, settlement state, or refund state does.</t>
<t>This is the load-bearing property that makes <tt>action_ref</tt> composable
across the substrate's emitter set. A downstream verifier auditing
a single transition (e.g. the settlement step of a payment) does
not need to replay the full chain to bind the action; the
<tt>action_ref</tt> digest alone is sufficient. Per-transition timestamp
claims at each step provide the temporal proof that the transition
was valid at that moment, independently verifiable.</t>
<t>The integer <tt>timestamp_ms</tt> requirement (Substrate Rule 2,
Section 4.1) applies to the preimage timestamp as well as to any
per-transition timestamps emitted alongside it. RFC 3339 string
forms are NOT acceptable for either the preimage or the lifecycle
metadata. The integer-timestamp invariant is independently anchored
in [I-D.vauban-x402-stark-receipts] Section 7.1, which explicitly
rejects <tt>timestamp</tt> (RFC 3339 string) as a wire form.</t>
</section>

<section anchor="sect-10-iana-considerations"><name>IANA Considerations</name>

<section anchor="sect-10-1-urn-namespace-registration"><name>URN Namespace Registration</name>
<t>This document requests registration of the URN namespace:</t>

<artwork><![CDATA[urn:x402:canonicalisation:jcs-rfc8785-v1
]]></artwork>

<ul spacing="compact">
<li>Namespace ID: <tt>x402</tt></li>
<li>Sub-namespace: <tt>canonicalisation</tt></li>
<li>Version identifier: <tt>jcs-rfc8785-v1</tt></li>
<li>Purpose: identifies the JSON canonicalisation discipline specified
by this document, including JCS RFC 8785 plus the schema-
normalisation requirements in Section 4.</li>
<li>Registry: IETF URN sub-namespace (if accepted by ART area)
or AlgoVoi-published registry for the <tt>x402</tt> namespace.</li>
<li>Registration authority: this Internet-Draft is the normative
source for the discipline identified by this URN. Other Internet-
Drafts, standards documents, or implementations that reference
the URN inherit the discipline as specified here. The URN
identifier is stable across revisions of this Internet-Draft so
long as the canonicalisation rules it identifies remain
byte-compatible; a non-compatible revision SHALL register a new
URN (<tt>jcs-rfc8785-v2</tt>, etc.) as described in Section 10.2.</li>
</ul>

<section anchor="sect-10-1-1-citation-convention-for-documents-using-this-discipline"><name>Citation Convention for Documents Using This Discipline</name>
<t>Documents (Internet-Drafts, RFCs, published specifications, or
implementations) that use the canonicalisation discipline specified
by this document SHOULD cite the URN
<tt>urn:x402:canonicalisation:jcs-rfc8785-v1</tt> as a Normative Reference,
either directly or via reference to this Internet-Draft. The
schema-normalisation rules in Section 4 of this document (including
the integer-millisecond timestamp encoding of Substrate Rule 2, the
ordered-array significance rule, and the in-band <tt>canon_version</tt>
pinning rule) extend RFC 8785 [RFC8785] in ways that are load-bearing
for byte-identical interoperability; citing RFC 8785 alone is
insufficient to identify the discipline as registered.</t>
<t>The recommended citation form in a referencing document is:</t>

<ul spacing="compact">
<li>In Normative References: an entry citing this Internet-Draft (or
its successor RFC, once published), including the document
identifier.</li>
<li>In document body where the discipline is invoked: a reference of
the form &quot;the canonicalisation discipline registered as
<tt>urn:x402:canonicalisation:jcs-rfc8785-v1</tt>&quot; or equivalent.</li>
</ul>
<t>A document citing this URN inherits the discipline at the revision
of this Internet-Draft current at the time of the document's
publication; the URN registration authority preserves identifier
stability across byte-compatible revisions, per the registration
authority paragraph above.</t>
<t>This Section is informational with respect to documents that do not
use the discipline. It is recommendatory (SHOULD) with respect to
documents that do.</t>
</section>
</section>

<section anchor="sect-10-2-canon-version-value-registration"><name>canon_version Value Registration</name>
<t>The string value <tt>jcs-rfc8785-v1</tt> is registered as the discipline
version identifier carried in <tt>canon_version</tt> fields produced under
this document.</t>
<t>Successor versions will register <tt>jcs-rfc8785-v2</tt>, <tt>jcs-rfc8785-v3</tt>,
etc. as follow-on revisions of this Internet-Draft are published.</t>
</section>
</section>

<section anchor="sect-11-security-considerations"><name>Security Considerations</name>

<section anchor="sect-11-1-cross-implementation-hash-equivalence"><name>Cross-implementation hash equivalence</name>
<t>The discipline guarantees that two conforming implementations,
applied to byte-identical normalised JSON objects, produce
byte-identical content hashes. This property is fundamental to
audit-chain integrity and supervisor re-verification.</t>
<t>A non-conforming implementation that coerces input rather than
rejecting it (Section 4.5) breaks this guarantee silently. Such an
implementation appears to function correctly at point of emission
but produces hashes that diverge from supervisor re-verification.
The non-conformance can go undetected until audit, at which point
retained records are unverifiable.</t>
<t>Operators MUST validate their implementations against the
conformance vector corpus (Section 7) BEFORE relying on the
discipline for retention-obligated records.</t>
</section>

<section anchor="sect-11-2-timestamp-ambiguity"><name>Timestamp ambiguity</name>
<t>The integer-millisecond timestamp requirement (Section 4.1) is a
security property as well as a determinism property. RFC 3339
string timestamps admit ambiguity in timezone representation
(e.g. <tt>Z</tt> vs <tt>+00:00</tt> vs <tt>-00:00</tt>), leap-second handling, and
sub-second precision. An attacker emitting receipts with
ambiguous timestamps could produce two byte-distinct receipts
representing the same logical instant; a verifier checking
content hashes would treat them as distinct events.</t>
<t>The integer-millisecond form eliminates this attack class:
each instant has exactly one valid millisecond representation.</t>
</section>

<section anchor="sect-11-3-field-name-aliasing"><name>Field-name aliasing</name>
<t>The field-name discipline (Section 4.2) prevents an aliasing
attack: a producer emitting <tt>tx_id</tt> while a downstream verifier
expects <tt>transaction_id</tt> produces a hash mismatch that the
verifier sees as tampering, even though no semantic tampering
occurred. The discipline requires the wire-layer alias to be
normalised to the canonical name before canonicalisation;
post-normalisation, the hash check is unambiguous.</t>
</section>

<section anchor="sect-11-4-version-rollback-attack"><name>Version-rollback attack</name>
<t>The <tt>canon_version</tt> field is itself canonicalised. A producer
cannot silently downgrade a receipt from <tt>jcs-rfc8785-v2</tt> to
<tt>jcs-rfc8785-v1</tt> post-emission without changing the content hash.
A verifier seeing a v1-claimed hash that does not validate
against v1 canonicalisation rejects the receipt; a verifier
seeing a v2-claimed hash treats it as v2.</t>
</section>

<section anchor="sect-11-5-numeric-precision"><name>Numeric precision</name>
<t>The amount-as-string recommendation (Section 4.4) prevents a
precision-loss attack: large amounts emitted as JSON numbers may
lose precision when round-tripped through a verifier whose JSON
parser uses 64-bit floats, producing a different hash than the
producer expected. String encoding in minor units preserves
precision exactly.</t>
</section>
</section>

</middle>
<back>
<section anchor="sect-12-references"><name>References</name>

<section anchor="sect-12-1-normative-references"><name>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>[RFC6234] Eastlake 3rd, D. and T. Hansen, &quot;US Secure Hash
Algorithms (SHA and SHA-based HMAC and HKDF)&quot;, RFC 6234,
DOI 10.17487/RFC6234, May 2011.</li>
<li>[RFC8141] Saint-Andre, P. and J. Klensin, &quot;Uniform Resource
Names (URNs)&quot;, RFC 8141, DOI 10.17487/RFC8141, April 2017.</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="sect-12-2-informative-references"><name>Informative References</name>

<ul spacing="compact">
<li>[I-D.hopley-x402-compliance-receipt]
Hopley, C., &quot;Categorical Compliance Screening Receipt Format
for Agentic-Payment Flows&quot;,
draft-hopley-x402-compliance-receipt-00, May 2026.</li>
<li>[I-D.hopley-x402-refund-receipt]
Hopley, C., &quot;Categorical Refund Receipt Format for
Agentic-Payment Flows&quot;,
draft-hopley-x402-refund-receipt-00, May 2026.</li>
<li>[AlgoVoi-JCS-8-impl]
AlgoVoi, &quot;Eight-implementation cross-validation attestation
for JCS RFC 8785&quot;, 2026-05-24,
<eref target="https://github.com/chopmob-cloud/algovoi-jcs-conformance-vectors/blob/main/_attestations/2026-05-24-8-impl-cross-validation.md"> target="https://github.com/chopmob-cloud/algovoi-jcs-conformance-vectors/blob/main/_attestations/2026-05-24-8-impl-cross-validation.md"</eref></li>
<li>[AlgoVoi-Substrate-Authorship]
AlgoVoi, &quot;Substrate Authorship and Provenance&quot;,
<eref target="https://docs.algovoi.co.uk/substrate-authorship-provenance"> target="https://docs.algovoi.co.uk/substrate-authorship-provenance"</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 Digital Operational Resilience Act (DORA, Regulation (EU)
2022/2554), Article 14.</li>
</ul>
</section>
</section>

<section anchor="appendix-a-example-canonical-forms-informative"><name>Appendix A. Example Canonical Forms (Informative)</name>

<section anchor="a-1-integer-timestamp-normalisation-substrate-rule-2"><name>A.1. Integer-timestamp normalisation (Substrate Rule 2)</name>
<t>Input object (non-conforming, RFC 3339 string):</t>

<sourcecode type="json"><![CDATA[{
  "agent_id": "did:web:api.algovoi.co.uk",
  "action_type": "compliance_screen",
  "scope": "algovoi:compliance_screen",
  "timestamp": "2024-05-28T12:00:00Z"
}
]]></sourcecode>
<t>Validator MUST reject (Section 4.5). Conforming object:</t>

<sourcecode type="json"><![CDATA[{
  "agent_id": "did:web:api.algovoi.co.uk",
  "action_type": "compliance_screen",
  "scope": "algovoi:compliance_screen",
  "timestamp_ms": 1716897600000
}
]]></sourcecode>
<t>JCS canonical bytes (sorted keys, no whitespace):</t>

<artwork><![CDATA[{"action_type":"compliance_screen","agent_id":"did:web:api.algovoi.co.uk","scope":"algovoi:compliance_screen","timestamp_ms":1716897600000}
]]></artwork>
<t>SHA-256 content_hash (lowercase hex):</t>

<artwork><![CDATA[7528529a8be2044488e603b7913efaa4f83620dbcc63010d4a1478cf7e9a473c
]]></artwork>
<t>This digest is the <tt>action_ref</tt> value for the example.</t>
</section>

<section anchor="a-2-array-order-is-load-bearing"><name>A.2. Array order is load-bearing</name>
<t>Two otherwise-identical receipt fragments varying only
<tt>jurisdiction_flags</tt> array order:</t>

<sourcecode type="json"><![CDATA[{ "jurisdiction_flags": ["UK", "EU"], ... }
{ "jurisdiction_flags": ["EU", "UK"], ... }
]]></sourcecode>
<t>These produce different JCS canonical bytes (RFC 8785 Section 3.2.3
preserves array order) and therefore different content hashes. The
receipt format using this discipline MUST specify a canonical array
order at the schema layer (e.g. &quot;primary jurisdiction first&quot;).</t>
</section>

<section anchor="a-3-canon-version-pin"><name>A.3. canon_version pin</name>
<t>Two otherwise-identical receipts varying only <tt>canon_version</tt>:</t>

<sourcecode type="json"><![CDATA[{ "canon_version": "jcs-rfc8785-v1", ... }
{ "canon_version": "jcs-rfc8785-v2", ... }
]]></sourcecode>
<t>These produce different canonical bytes. A receipt emitted under
v1 cannot be silently re-hashed under v2.</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
canonicalisation discipline:</t>
<table>
<thead>
<tr>
<th>Language</th>
<th>Package</th>
<th>Function</th>
</tr>
</thead>

<tbody>
<tr>
<td>Python</td>
<td><eref target="https://pypi.org/project/algovoi-substrate/"> target="https://pypi.org/project/algovoi-substrate/"</eref></td>
<td><tt>algovoi_substrate.canonicalize</tt></td>
</tr>

<tr>
<td>TypeScript</td>
<td><eref target="https://www.npmjs.com/package/@algovoi/substrate"> target="https://www.npmjs.com/package/@algovoi/substrate"</eref></td>
<td><tt>canonicalize</tt>, <tt>sha256Jcs</tt></td>
</tr>
</tbody>
</table><t>Both packages depend transitively on <tt>rfc8785</tt> (Python) /
<tt>canonicalize</tt> (TypeScript) for the JCS layer and add the
schema-normalisation discipline of Section 4 on top.</t>
<t>The conformance vector corpus that anchors this discipline:</t>

<artwork><![CDATA[https://github.com/chopmob-cloud/algovoi-jcs-conformance-vectors
]]></artwork>
<t>The eight-implementation cross-validation attestation referenced
in Section 7 is at:</t>

<artwork><![CDATA[_attestations/2026-05-24-8-impl-cross-validation.md
]]></artwork>
</section>

<section anchor="appendix-c-known-adopters-informative"><name>Appendix C. Known Adopters (Informative)</name>
<t>The following downstream parties have published artefacts that
anchor to the canonicalisation discipline specified by this
document. Inclusion in this list is informational and reflects
public adoption only; it does not imply endorsement or normative
authority from the listed party.</t>
<table>
<thead>
<tr>
<th>Adopter</th>
<th>Surface</th>
<th>Anchor</th>
</tr>
</thead>

<tbody>
<tr>
<td>AlgoVoi (<tt>api.algovoi.co.uk</tt>)</td>
<td>Production compliance and refund-receipt issuer</td>
<td>All AlgoVoi-emitted receipts under <tt>canon_version: jcs-rfc8785-v1</tt></td>
</tr>

<tr>
<td>Supership (<tt>andysalvo</tt>)</td>
<td><tt>service_trust_v0</tt> conformance vectors</td>
<td>Downstream-adopter vector set anchored to the canonicalisation discipline; submitted to the AlgoVoi corpus on 2026-05-23 and recorded as an independent adoption signal</td>
</tr>
</tbody>
</table><t>Adopters publishing vector sets or receipt-format extensions that
anchor to this discipline are encouraged to publish them in
adopter-controlled repositories with <tt>canon_version</tt> recorded
in-band, so each adopter's authorship is unambiguous and their
artefact is independently citable.</t>
<t>This appendix is maintained as a record of observed adoption at the
time of revision; absence from this list is not normative.</t>
</section>

<section anchor="appendix-d-acknowledgments"><name>Appendix D. Acknowledgments</name>
<t>This document, and the canonicalisation discipline it specifies,
are AlgoVoi work under sole AlgoVoi authorship. The URN
<tt>urn:x402:canonicalisation:jcs-rfc8785-v1</tt> registered by Section
10.1 of this document identifies the discipline as specified
herein; other documents that reference the URN inherit the
discipline as defined in this Internet-Draft. The registration
authority is preserved across revisions of this document so long
as the canonicalisation rules remain byte-compatible.</t>
<t>The canonicalisation discipline persists under AlgoVoi-controlled
surfaces, each independently citable:</t>

<ul spacing="compact">
<li>This Internet-Draft on the IETF datatracker (Independent
Submission, Informational).</li>
<li>The substrate authorship provenance record at
<eref target="https://docs.algovoi.co.uk/substrate-authorship-provenance"> target="https://docs.algovoi.co.uk/substrate-authorship-provenance"</eref>.</li>
<li>The Substrate Adopters Registry at
<eref target="https://docs.algovoi.co.uk/adopters"> target="https://docs.algovoi.co.uk/adopters"</eref> (records parties publishing
artefacts under <tt>canon_version: jcs-rfc8785-v1</tt>, with
machine-readable JSON-LD mirror).</li>
<li>The <tt>algovoi-substrate</tt> reference implementation on PyPI and
npm, plus five companion AlgoVoi-authored receipt-format
reference implementations under the same canonicalisation pin.</li>
<li>The eight-implementation cross-validation attestation record in
the AlgoVoi conformance vectors corpus
(<eref target="https://github.com/chopmob-cloud/algovoi-jcs-conformance-vectors"> target="https://github.com/chopmob-cloud/algovoi-jcs-conformance-vectors"</eref>);
cumulative 512/512 byte-for-byte agreements across two
attestation runs covering seven distinct vector sets under eight
independent JCS implementations.</li>
</ul>
<t>The integer-millisecond canonical timestamp convention specified
in Section 4 (Substrate Rule 2) was first posted publicly on
x402-foundation/x402 issue #2357 on 2026-05-20 by Andy Salvo
(Crest Deployment Systems LLC) as the canonical preimage field
for <tt>action_ref</tt> work-receipt derivation. The convention was
adopted into the canonicalisation discipline specified in this
document. The conformance vector <tt>0009 (field-name-load-bearing)</tt>
on x402-foundation/x402 pull request #2398, also contributed by
Andy Salvo, demonstrates the same invariant from the work-receipt
layer.</t>
<t>The framework-bound-retention scoping clause referenced by
downstream receipt-format I-Ds that anchor to this discipline was
contributed by feedoracle (FeedOracle).</t>
<t>The author acknowledges Anders Rundgren as the editor of RFC 8785,
the JSON Canonicalization Scheme on which this discipline builds.</t>
</section>
</back>

</rfc>
