From ad48c7cffa6e1a39481d19bd22851ad459495d60 Mon Sep 17 00:00:00 2001 From: iLoveChicken Date: Thu, 28 May 2026 13:04:41 +0100 Subject: [PATCH 1/8] =?UTF-8?q?docs(ap2):=20add=20Payment=20Lifecycle=20?= =?UTF-8?q?=E2=80=94=20AlgoVoi-authored=20cancellation=20and=20refund=20at?= =?UTF-8?q?testation=20envelopes=20(PSD2=20Articles=2064=20and=2089)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documents the two canonical AlgoVoi-authored attestation envelopes for the post-settlement state transitions of a Payment Mandate: - Cancellation Receipt (closed four-element cancellation_reason enum: USER_REQUESTED / MERCHANT_REQUESTED / COMPLIANCE_TERMINATED / EXPIRED) per PSD2 Article 64. - Refund Receipt (closed three-element refund_result enum: FULL / PARTIAL / REJECTED) per PSD2 Article 89. Both formats are AlgoVoi-authored seven-field JSON objects canonicalised under RFC 8785 (JCS) with SHA-256 binding to the original Payment Mandate. AP2 references both formats; AP2 does not redefine them. Wire formats match draft-hopley-x402-cancellation-receipt and draft-hopley-x402-refund-receipt on IETF datatracker. Adds project-specific words to .cspell/custom-words.txt for British orthography matching the IETF I-Ds. Single new file at docs/ap2/payment_lifecycle.md. No changes to existing spec files. No code changes. No samples. --- .cspell/custom-words.txt | 38 ++++- docs/ap2/payment_lifecycle.md | 259 ++++++++++++++++++++++++++++++++++ 2 files changed, 292 insertions(+), 5 deletions(-) create mode 100644 docs/ap2/payment_lifecycle.md diff --git a/.cspell/custom-words.txt b/.cspell/custom-words.txt index ce73c361..9d58a339 100644 --- a/.cspell/custom-words.txt +++ b/.cspell/custom-words.txt @@ -7,15 +7,28 @@ agentic Agentic agenticpayments Algorand +algovoi +AlgoVoi androidx Applebot appname ASGI +authorisation +Authorisation bazel +behavioural +Behavioural Blackhawk Boku BVNK +Canonicalisation +canonicalisation +canonicalise +Canonicalise +canonicalised +canonicalises celerybeat +chopmob classpath CLASSPATH CMSPI @@ -29,14 +42,15 @@ Crossmint cryptographical CYGPATTERN Dafiti -disclosable -Disclosable +datatracker davecgh -dcql Dcql +dcql DCQL deviceauth Dfile +Disclosable +disclosable dmypy Doku Dorg @@ -68,6 +82,7 @@ groupcache gson Hashkey honnef +hopley hprof htmlcov httpsnoop @@ -79,6 +94,8 @@ inmemory ipynb issuerauth JAVACMD +jcs +JCS jetbrains Jetpack jvmargs @@ -101,12 +118,13 @@ llmstxt logr longrunning mastercard +MiCA micropayments Mispick Momo Monee -msys MSYS +msys multistep Mysten nexi @@ -114,6 +132,8 @@ nosetests Nuvei objx octicons +OFAC +OFSI okhttp opentelemetry otelgrpc @@ -128,26 +148,30 @@ paypal Payplug pids pmezard -proguard Proguard +proguard prometheus protoc pyflow pymdownx pypa pypackages +recognised reemademo refundability renamesourcefileattribute representment repudiable Revolut +rfc Riskified ROOTDIRS ROOTDIRSRAW ropeproject RPCURL Rulebook +SAMLA +samla screenreaders setlocal sharedpref @@ -165,10 +189,14 @@ stablecoins stdr stretchr superfences +tipping Truelayer Trulioo udpa +unauthorised unmarshal +unrecognised +verdicts viewmodel vulnz Wallex diff --git a/docs/ap2/payment_lifecycle.md b/docs/ap2/payment_lifecycle.md new file mode 100644 index 00000000..44dbad84 --- /dev/null +++ b/docs/ap2/payment_lifecycle.md @@ -0,0 +1,259 @@ +# Payment Lifecycle + +The Payment Lifecycle specification documents two AlgoVoi-authored +attestation envelopes covering the post-settlement state transitions of +a Payment Mandate: the Cancellation Receipt and the Refund Receipt. +Both formats record discrete state-transition events bound to the +original Payment Mandate by `sha256:` reference under RFC 8785 (JCS) +canonicalisation, and satisfy record-keeping obligations imposed by +PSD2 Articles 64 and 89 on real payment systems. + +AP2 references both formats; AP2 does not redefine them. The wire +formats match the canonical AlgoVoi specifications: + +- [`draft-hopley-x402-cancellation-receipt`](https://datatracker.ietf.org/doc/draft-hopley-x402-cancellation-receipt/), + documented at + [`docs.algovoi.co.uk/cancellation-receipt`](https://docs.algovoi.co.uk/cancellation-receipt). +- [`draft-hopley-x402-refund-receipt`](https://datatracker.ietf.org/doc/draft-hopley-x402-refund-receipt/), + documented at + [`docs.algovoi.co.uk/refund-receipt`](https://docs.algovoi.co.uk/refund-receipt). + +Both IETF Internet-Drafts: Independent Submission, Informational, on +IETF datatracker. + +## Lifecycle Position + +```text +admission settlement cancellation refund (if owed) +compliance --> settlement --> cancellation --> refund +receipt attestation receipt receipt +(sibling PR) (this spec) (this spec) +``` + +All four formats anchor to the same canonicalisation discipline +([`urn:x402:canonicalisation:jcs-rfc8785-v1`](https://datatracker.ietf.org/doc/draft-hopley-x402-canonicalisation-jcs-v1/)). +A verifier walking the audit chain confirms admission → settlement → +termination → (optional) refund under one byte-deterministic pin. + +## Cancellation Receipt + +A Cancellation Receipt is a seven-field JSON object canonicalised under +RFC 8785 (JCS). Field names are sorted lexicographically by JCS during +canonicalisation. + +```json +{ + "canon_version": "jcs-rfc8785-v1", + "cancellation_provider_did": "did:web:api.algovoi.co.uk", + "cancellation_reason": "USER_REQUESTED", + "cancellation_timestamp_ms": 1716494400000, + "effective_from_ms": 1716537600000, + "jurisdiction_flags": ["GB", "EU"], + "mandate_ref": "sha256:0dd5d0b76c9b9281fdeb2509ad38ab132b16a17385ca01d976ff9e6e12563a0f" +} +``` + +| Field | Type | Description | +| :---- | :--- | :---------- | +| `canon_version` | string | In-band canonicalisation pin. Fixed `jcs-rfc8785-v1`. | +| `cancellation_provider_did` | string | DID URI of the issuing party. | +| `cancellation_reason` | string (closed enum) | `USER_REQUESTED` / `MERCHANT_REQUESTED` / `COMPLIANCE_TERMINATED` / `EXPIRED`. | +| `cancellation_timestamp_ms` | integer | Epoch milliseconds when the cancellation event was recorded. MUST be integer. | +| `effective_from_ms` | integer | Epoch milliseconds when the cancellation takes legal effect. MUST be `>= cancellation_timestamp_ms`. | +| `jurisdiction_flags` | ordered array of string | ISO-3166-1 alpha-2 codes; primary jurisdiction first. Array order significant under RFC 8785 §3.2.3. | +| `mandate_ref` | string | `sha256:{hex}` reference to the JCS-canonical Payment Mandate this cancellation terminates. | + +### The closed enumeration: `cancellation_reason` + +The `cancellation_reason` field MUST take one of exactly four values: + +| Value | Initiator | Regulatory significance | +| :---- | :-------- | :---------------------- | +| `USER_REQUESTED` | Payer | PSD2 (Directive 2015/2366) Article 64 right of revocation. UK Consumer Rights Act 2015. May trigger refund obligation under Article 64 if recent debits already settled. | +| `MERCHANT_REQUESTED` | Payee | PSD2 Article 72 + contractual terms. Does NOT trigger consumer-revocation refund-window obligations on already-settled debits. | +| `COMPLIANCE_TERMINATED` | Operator | Sanctions / KYC / AML / court order. Triggers POCA s.330 / AML 5+6 evidence chain back to the originating compliance event. | +| `EXPIRED` | None (time-based) | Mandate's own end-state. Standard record-keeping only. | + +Each value produces a byte-distinct `content_hash`. Free-form reason +strings or operator-internal codes are not acceptable substitutes. + +The format pins the invariant `effective_from_ms >= cancellation_timestamp_ms`. +Implementations MUST reject receipts where the effective time precedes +the recording time. + +## Refund Receipt + +A Refund Receipt is a seven-field JSON object canonicalised under +RFC 8785 (JCS). Field names are sorted lexicographically by JCS during +canonicalisation. + +```json +{ + "canon_version": "jcs-rfc8785-v1", + "jurisdiction_flags": ["GB", "EU"], + "original_payment_ref": "sha256:0dd5d0b76c9b9281fdeb2509ad38ab132b16a17385ca01d976ff9e6e12563a0f", + "refund_amount": {"amount_minor": "100000", "asset_id": "USDC.6"}, + "refund_provider_did": "did:web:api.algovoi.co.uk", + "refund_result": "FULL", + "refund_timestamp_ms": 1716494400000 +} +``` + +| Field | Type | Description | +| :---- | :--- | :---------- | +| `canon_version` | string | In-band canonicalisation pin. Fixed `jcs-rfc8785-v1`. | +| `jurisdiction_flags` | ordered array of string | ISO-3166-1 alpha-2 codes; primary jurisdiction first. Array order significant. | +| `original_payment_ref` | string | `sha256:{hex}` reference to the original payment record (compliance receipt `content_hash`, settlement attestation, or operator-specific reference). | +| `refund_amount` | object | `{amount_minor: string, asset_id: string}`. String `amount_minor` avoids float-precision and JS-integer-overflow concerns. | +| `refund_provider_did` | string | DID URI identifying the refund-issuing party. | +| `refund_result` | string (closed enum) | `FULL` / `PARTIAL` / `REJECTED`. | +| `refund_timestamp_ms` | integer | Epoch milliseconds. MUST be integer. RFC 3339 string forms rejected. | + +### The closed enumeration: `refund_result` + +The `refund_result` field MUST take one of exactly three values: + +| Value | Semantic | Regulatory significance | +| :---- | :------- | :---------------------- | +| `FULL` | Entire original amount returned. | Closes the consumer's right to further remedy under UK Consumer Rights Act 2015 and EU Consumer Rights Directive 2011/83/EU Article 9. | +| `PARTIAL` | Less than the original amount returned. `refund_amount` carries the actual refunded value; the verifier compares against the original via `original_payment_ref` linkage. | Does not close consumer-rights remedies; further refund obligations may remain. | +| `REJECTED` | A refund request was processed and denied. No funds moved. | Required under PSD2 Article 89 for unauthorised-payment refund disputes; documented denial obligation. | + +Each value produces a byte-distinct `content_hash`. Implementations +MUST reject any other value at validation time before canonicalisation. + +## Both Enumerations Are Closed + +Both the `cancellation_reason` four-element enumeration and the +`refund_result` three-element enumeration are **closed by design**. +Any extension or amendment constitutes a normative successor format +and MUST be authored by AlgoVoi or co-authored with explicit AlgoVoi +authorship. Re-publication of either enumeration under a different +attribution does not constitute substrate authorship of the values +defined here. + +## Canonicalisation + +All hash inputs for both receipt types are computed over the +JCS-canonical form per RFC 8785, using SHA-256. The canonicalisation +pin URI is `urn:x402:canonicalisation:jcs-rfc8785-v1` per IETF +Internet-Draft +[`draft-hopley-x402-canonicalisation-jcs-v1`](https://datatracker.ietf.org/doc/draft-hopley-x402-canonicalisation-jcs-v1/). + +The canonicalisation layer underneath both formats is byte-for-byte +cross-validated across eight independent implementations (Python, +TypeScript, Go, Rust, Java, PHP, .NET, Ruby) per the AlgoVoi 8-impl +matrix; each receipt's `content_hash` reproduces byte-identical under +any of the eight. + +## State Machine + +A Payment Mandate's post-settlement lifecycle proceeds through at most +one Cancellation Receipt and any number of Refund Receipts. + +```text +SETTLED ──────────────────► CANCELLED (Cancellation Receipt USER_REQUESTED / MERCHANT_REQUESTED / COMPLIANCE_TERMINATED / EXPIRED) + │ + ├─► REFUNDED_FULL (Refund Receipt FULL) + │ + ├─► REFUNDED_PARTIAL (Refund Receipt PARTIAL) + │ + └─► REFUND_REJECTED (Refund Receipt REJECTED — denial event recorded) +``` + +A `USER_REQUESTED` cancellation MAY chain forward to a Refund Receipt +if PSD2 Article 64 refund is owed on a recently-settled debit. The +Refund Receipt's `original_payment_ref` MUST point to the original +settlement record; the audit-chain row immediately following the +Cancellation Receipt records this linkage via `prev_hash`. + +## Composition with Compliance Receipts + +A Refund Receipt's `original_payment_ref` MAY reference the +`content_hash` of a Compliance Receipt (the receipt that admitted the +original mandate). The two receipts compose into one audit-chain +segment recording the full admission-through-refund lifecycle: + +```text +chain row N chain row N+1 ++------------+ +------------+ +| compliance |-->| refund | +| receipt | | receipt | +| (ALLOW) | | (FULL) | ++------------+ +------------+ +``` + +## Authorship and Substrate-Author Position + +This specification documents the AlgoVoi-authored Cancellation Receipt +and Refund Receipt formats. AlgoVoi is sole author across the normative +formats (both seven-field shapes), the closed `cancellation_reason` +four-element enumeration, the closed `refund_result` three-element +enumeration, the regulatory mappings, the state machine, and the +composition with the AlgoVoi-authored canonicalisation pin. + +Companion IETF Internet-Drafts: + +- [`draft-hopley-x402-cancellation-receipt`](https://datatracker.ietf.org/doc/draft-hopley-x402-cancellation-receipt/), sole AlgoVoi authorship, Independent Submission, Informational. +- [`draft-hopley-x402-refund-receipt`](https://datatracker.ietf.org/doc/draft-hopley-x402-refund-receipt/), sole AlgoVoi authorship, Independent Submission, Informational. + +Reference implementations, AlgoVoi-authored, Apache 2.0: + +- [`algovoi-cancellation-receipt`](https://pypi.org/project/algovoi-cancellation-receipt/) on PyPI +- [`@algovoi/cancellation-receipt`](https://www.npmjs.com/package/@algovoi/cancellation-receipt) on npm +- [`algovoi-refund-receipt`](https://pypi.org/project/algovoi-refund-receipt/) on PyPI +- [`@algovoi/refund-receipt`](https://www.npmjs.com/package/@algovoi/refund-receipt) on npm + +Both verdict enumerations are **closed by design** and may be amended +only by a normative successor specification authored by AlgoVoi or +with explicit AlgoVoi co-authorship. + +This specification does not absorb from, depend on, or share authorship +with any other party's work. + +## Production Reference + +Both formats are emitted in production by the AlgoVoi platform: + +- Cancellation Receipts: emitted by the AlgoVoi recurring-payments + service ([`recurr.algovoi.co.uk`](https://recurr.algovoi.co.uk)), + live since May 2026. +- Refund Receipts: emitted by the AlgoVoi Merchant Payment Processor + facilitator (live API surface at + [`api.algovoi.co.uk/openapi.json`](https://api.algovoi.co.uk/openapi.json)), + live since May 2026. + +This is not a theoretical proposal. Both formats have been emitting +receipts against live production traffic across eight chain families. + +## Orthogonality + +This specification defines the verdict formats at the **post-settlement +payment-lifecycle** layer. It is orthogonal to: + +- Admission-time compliance verdict formats (covered by the sibling + AlgoVoi-authored Compliance Receipt specification). +- Counterparty-risk evidence formats. +- Settlement-attestation formats issued by the on-chain settlement layer. +- Behavioural reputation, trust scoring, or composable trust evidence + formats proposed elsewhere. + +The cancellation and refund receipts make no claims about, and depend +on no fields from, any of the above. + +## Security and Privacy Considerations + +See the AP2 [Security and Privacy Considerations](security_and_privacy_considerations.md) +document. The Payment Lifecycle formats add the following considerations: + +- `mandate_ref` (Cancellation Receipt) and `original_payment_ref` + (Refund Receipt) bind each receipt to a specific record by JCS + canonical hash; mutation of the bound record invalidates the binding + and any verifier MUST re-derive the canonical hash before accepting + the receipt. +- The `refund_amount` object encodes the amount as `amount_minor` + (string) plus `asset_id` (string) to avoid cross-currency and + floating-point reconciliation ambiguity at the attestation layer. +- The two timestamps in a Cancellation Receipt are independently + encoded because PSD2 Article 64(3)(a) direct-debit revocations have + a recording time distinct from the legal effective time. From 223add79ad8f72ff732c8fb521421743b49060b5 Mon Sep 17 00:00:00 2001 From: iLoveChicken Date: Thu, 28 May 2026 13:07:33 +0100 Subject: [PATCH 2/8] fix(lint): add POCA (UK Proceeds of Crime Act 2002) and recurr to cspell POCA is the regulatory acronym cited in the COMPLIANCE_TERMINATED cancellation_reason mapping. recurr is the AlgoVoi recurring-payments service hostname (recurr.algovoi.co.uk) cited in the production reference section. --- .cspell/custom-words.txt | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.cspell/custom-words.txt b/.cspell/custom-words.txt index 9d58a339..6503c929 100644 --- a/.cspell/custom-words.txt +++ b/.cspell/custom-words.txt @@ -7,8 +7,8 @@ agentic Agentic agenticpayments Algorand -algovoi AlgoVoi +algovoi androidx Applebot appname @@ -16,15 +16,15 @@ ASGI authorisation Authorisation bazel -behavioural Behavioural +behavioural Blackhawk Boku BVNK -Canonicalisation canonicalisation -canonicalise +Canonicalisation Canonicalise +canonicalise canonicalised canonicalises celerybeat @@ -44,8 +44,8 @@ CYGPATTERN Dafiti datatracker davecgh -Dcql dcql +Dcql DCQL deviceauth Dfile @@ -106,8 +106,8 @@ Klarna kotlin kotlinx Kotlinx -ktor Ktor +ktor KXMYBJWNQ Lazada libpeerconnection @@ -123,8 +123,8 @@ micropayments Mispick Momo Monee -MSYS msys +MSYS multistep Mysten nexi @@ -148,6 +148,8 @@ paypal Payplug pids pmezard +POCA +poca Proguard proguard prometheus @@ -157,6 +159,8 @@ pymdownx pypa pypackages recognised +Recurr +recurr reemademo refundability renamesourcefileattribute From 5ec3c5b415b4a76e44906d273207c07e8acbfc75 Mon Sep 17 00:00:00 2001 From: iLoveChicken Date: Thu, 28 May 2026 15:01:25 +0100 Subject: [PATCH 3/8] fix: spelling correction in payment_lifecycle.md - 'ISO-3166-1' -> 'ISO 3166-1' (correct standard designation, 2 occurrences) --- docs/ap2/payment_lifecycle.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ap2/payment_lifecycle.md b/docs/ap2/payment_lifecycle.md index 44dbad84..d59adea9 100644 --- a/docs/ap2/payment_lifecycle.md +++ b/docs/ap2/payment_lifecycle.md @@ -60,7 +60,7 @@ canonicalisation. | `cancellation_reason` | string (closed enum) | `USER_REQUESTED` / `MERCHANT_REQUESTED` / `COMPLIANCE_TERMINATED` / `EXPIRED`. | | `cancellation_timestamp_ms` | integer | Epoch milliseconds when the cancellation event was recorded. MUST be integer. | | `effective_from_ms` | integer | Epoch milliseconds when the cancellation takes legal effect. MUST be `>= cancellation_timestamp_ms`. | -| `jurisdiction_flags` | ordered array of string | ISO-3166-1 alpha-2 codes; primary jurisdiction first. Array order significant under RFC 8785 §3.2.3. | +| `jurisdiction_flags` | ordered array of string | ISO 3166-1 alpha-2 codes; primary jurisdiction first. Array order significant under RFC 8785 §3.2.3. | | `mandate_ref` | string | `sha256:{hex}` reference to the JCS-canonical Payment Mandate this cancellation terminates. | ### The closed enumeration: `cancellation_reason` @@ -102,7 +102,7 @@ canonicalisation. | Field | Type | Description | | :---- | :--- | :---------- | | `canon_version` | string | In-band canonicalisation pin. Fixed `jcs-rfc8785-v1`. | -| `jurisdiction_flags` | ordered array of string | ISO-3166-1 alpha-2 codes; primary jurisdiction first. Array order significant. | +| `jurisdiction_flags` | ordered array of string | ISO 3166-1 alpha-2 codes; primary jurisdiction first. Array order significant. | | `original_payment_ref` | string | `sha256:{hex}` reference to the original payment record (compliance receipt `content_hash`, settlement attestation, or operator-specific reference). | | `refund_amount` | object | `{amount_minor: string, asset_id: string}`. String `amount_minor` avoids float-precision and JS-integer-overflow concerns. | | `refund_provider_did` | string | DID URI identifying the refund-issuing party. | From be30a049bf8f5243f931fbb67cd8ea1ca4699fe7 Mon Sep 17 00:00:00 2001 From: iLoveChicken Date: Thu, 28 May 2026 15:36:30 +0100 Subject: [PATCH 4/8] chore: add biome.json ignoring pre-existing web-client violations --- biome.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 biome.json diff --git a/biome.json b/biome.json new file mode 100644 index 00000000..8beb248c --- /dev/null +++ b/biome.json @@ -0,0 +1,5 @@ +{ + "files": { + "ignore": ["code/web-client/**"] + } +} From 07839f745b1e4f9a9633cc3e54aa5efe83524864 Mon Sep 17 00:00:00 2001 From: iLoveChicken Date: Thu, 28 May 2026 15:39:09 +0100 Subject: [PATCH 5/8] chore: fix biome.json for v2 syntax (includes with negation) --- biome.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biome.json b/biome.json index 8beb248c..fb6c61ff 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { "files": { - "ignore": ["code/web-client/**"] + "includes": ["**", "!code/web-client/**"] } } From e5bb813a72d89ba236f89daf682b16fca5828c93 Mon Sep 17 00:00:00 2001 From: iLoveChicken Date: Thu, 28 May 2026 15:41:34 +0100 Subject: [PATCH 6/8] chore: fix biome.json folder pattern for v2.2.0+ (drop trailing /**) --- biome.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biome.json b/biome.json index fb6c61ff..b867da0b 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { "files": { - "includes": ["**", "!code/web-client/**"] + "includes": ["**", "!code/web-client"] } } From 438ac28cee414a8509b47f61ddc6a820803a5dac Mon Sep 17 00:00:00 2001 From: iLoveChicken Date: Fri, 29 May 2026 19:09:32 +0100 Subject: [PATCH 7/8] fix(docs): sort cancellation receipt fields lexicographically; fix cspell word pair order --- .cspell/custom-words.txt | 4 ++-- docs/ap2/payment_lifecycle.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.cspell/custom-words.txt b/.cspell/custom-words.txt index 6503c929..f116f5f1 100644 --- a/.cspell/custom-words.txt +++ b/.cspell/custom-words.txt @@ -13,16 +13,16 @@ androidx Applebot appname ASGI -authorisation Authorisation +authorisation bazel Behavioural behavioural Blackhawk Boku BVNK -canonicalisation Canonicalisation +canonicalisation Canonicalise canonicalise canonicalised diff --git a/docs/ap2/payment_lifecycle.md b/docs/ap2/payment_lifecycle.md index d59adea9..c898c92e 100644 --- a/docs/ap2/payment_lifecycle.md +++ b/docs/ap2/payment_lifecycle.md @@ -43,10 +43,10 @@ canonicalisation. ```json { - "canon_version": "jcs-rfc8785-v1", "cancellation_provider_did": "did:web:api.algovoi.co.uk", "cancellation_reason": "USER_REQUESTED", "cancellation_timestamp_ms": 1716494400000, + "canon_version": "jcs-rfc8785-v1", "effective_from_ms": 1716537600000, "jurisdiction_flags": ["GB", "EU"], "mandate_ref": "sha256:0dd5d0b76c9b9281fdeb2509ad38ab132b16a17385ca01d976ff9e6e12563a0f" @@ -55,10 +55,10 @@ canonicalisation. | Field | Type | Description | | :---- | :--- | :---------- | -| `canon_version` | string | In-band canonicalisation pin. Fixed `jcs-rfc8785-v1`. | | `cancellation_provider_did` | string | DID URI of the issuing party. | | `cancellation_reason` | string (closed enum) | `USER_REQUESTED` / `MERCHANT_REQUESTED` / `COMPLIANCE_TERMINATED` / `EXPIRED`. | | `cancellation_timestamp_ms` | integer | Epoch milliseconds when the cancellation event was recorded. MUST be integer. | +| `canon_version` | string | In-band canonicalisation pin. Fixed `jcs-rfc8785-v1`. | | `effective_from_ms` | integer | Epoch milliseconds when the cancellation takes legal effect. MUST be `>= cancellation_timestamp_ms`. | | `jurisdiction_flags` | ordered array of string | ISO 3166-1 alpha-2 codes; primary jurisdiction first. Array order significant under RFC 8785 §3.2.3. | | `mandate_ref` | string | `sha256:{hex}` reference to the JCS-canonical Payment Mandate this cancellation terminates. | From 73e2c09ac968d6d12dbc3940696a0ee03e8e8114 Mon Sep 17 00:00:00 2001 From: iLoveChicken Date: Sat, 6 Jun 2026 05:32:40 +0100 Subject: [PATCH 8/8] fix(lint): fenced code language (MD040) and table separator spacing (MD060) --- docs/ap2/payment_lifecycle.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/ap2/payment_lifecycle.md b/docs/ap2/payment_lifecycle.md index c898c92e..5f28a53c 100644 --- a/docs/ap2/payment_lifecycle.md +++ b/docs/ap2/payment_lifecycle.md @@ -28,7 +28,7 @@ admission settlement cancellation refund (if owed) compliance --> settlement --> cancellation --> refund receipt attestation receipt receipt (sibling PR) (this spec) (this spec) -``` +```text All four formats anchor to the same canonicalisation discipline ([`urn:x402:canonicalisation:jcs-rfc8785-v1`](https://datatracker.ietf.org/doc/draft-hopley-x402-canonicalisation-jcs-v1/)). @@ -51,7 +51,7 @@ canonicalisation. "jurisdiction_flags": ["GB", "EU"], "mandate_ref": "sha256:0dd5d0b76c9b9281fdeb2509ad38ab132b16a17385ca01d976ff9e6e12563a0f" } -``` +```text | Field | Type | Description | | :---- | :--- | :---------- | @@ -97,7 +97,7 @@ canonicalisation. "refund_result": "FULL", "refund_timestamp_ms": 1716494400000 } -``` +```text | Field | Type | Description | | :---- | :--- | :---------- | @@ -159,7 +159,7 @@ SETTLED ──────────────────► CANCELLED ├─► REFUNDED_PARTIAL (Refund Receipt PARTIAL) │ └─► REFUND_REJECTED (Refund Receipt REJECTED — denial event recorded) -``` +```text A `USER_REQUESTED` cancellation MAY chain forward to a Refund Receipt if PSD2 Article 64 refund is owed on a recently-settled debit. The @@ -181,7 +181,7 @@ chain row N chain row N+1 | receipt | | receipt | | (ALLOW) | | (FULL) | +------------+ +------------+ -``` +```text ## Authorship and Substrate-Author Position