docs(ap2): add Payment Lifecycle - AlgoVoi-authored cancellation and refund attestation envelopes (PSD2 Articles 64 and 89)#270
Conversation
…refund attestation envelopes (PSD2 Articles 64 and 89) 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.
There was a problem hiding this comment.
Code Review
This pull request introduces a new documentation file, docs/ap2/payment_lifecycle.md, which specifies the post-settlement state transitions of a Payment Mandate (Cancellation Receipt and Refund Receipt) under RFC 8785 (JCS) canonicalisation. It also updates .cspell/custom-words.txt with several new custom words. The review feedback points out that the JSON example and field table for the Cancellation Receipt are not sorted lexicographically, which contradicts the text and is inconsistent with other tables. Additionally, several newly added custom words in .cspell/custom-words.txt are out of order relative to the file's casing convention.
| { | ||
| "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" | ||
| } |
There was a problem hiding this comment.
The JSON example for the Cancellation Receipt is not sorted lexicographically by keys, which contradicts the statement on line 41: "Field names are sorted lexicographically by JCS during canonicalisation." Specifically, "cancellation_provider_did", "cancellation_reason", and "cancellation_timestamp_ms" should precede "canon_version" because 'c' comes before 'o'.
| { | |
| "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" | |
| } | |
| { | |
| "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" | |
| } |
| | `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. | |
There was a problem hiding this comment.
The fields in the Cancellation Receipt table are not sorted lexicographically, which is inconsistent with the Refund Receipt table (lines 104-110) and the lexicographical sorting requirement of JCS. Sorting the table lexicographically makes it easier to read and compare with the JSON example.
| | `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. | | |
| | `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. | |
| algovoi | ||
| AlgoVoi |
| authorisation | ||
| Authorisation |
| behavioural | ||
| Behavioural |
| canonicalise | ||
| Canonicalise |
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.
- 'ISO-3166-1' -> 'ISO 3166-1' (correct standard designation, 2 occurrences)
…pell word pair order
Summary
Adds the
Payment Lifecyclespecification to the AP2 documentationset, documenting the two canonical AlgoVoi-authored attestation
envelopes for the post-settlement state transitions of a Payment
Mandate:
cancellation_reasonenumeration:USER_REQUESTED / MERCHANT_REQUESTED / COMPLIANCE_TERMINATED / EXPIRED.refund_resultenumeration:FULL / PARTIAL / REJECTED.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. The wire
formats match the canonical AlgoVoi specifications on IETF datatracker
(
draft-hopley-x402-cancellation-receipt,draft-hopley-x402-refund-receipt) and the live documentation atdocs.algovoi.co.uk/cancellation-receiptand/refund-receipt.Single new file at
docs/ap2/payment_lifecycle.md. No changes toexisting spec files. No code changes. No samples.
Why AP2 needs this
AP2 today specifies the Cart Mandate, Payment Mandate, and Agent
Authorization primitives covering the pre-settlement and settlement
phases of a transaction. It does not document the post-settlement
lifecycle: cancellation and refund.
PSD2 Article 64 (right to revoke a payment authorisation) and PSD2
Article 89 (refund obligations) impose regulatory requirements on real
payment systems that AP2 does not currently address. Without a
canonical attestation format, every party records these state
transitions in a bespoke shape, breaking the property that a Shopping
Agent or downstream relying party can confirm that a post-settlement
state transition occurred by hashing a fixed-shape JSON object.
This PR closes the gap by referencing the AlgoVoi-authored formats
(already in production, on IETF datatracker, with reference
implementations on PyPI and npm) and documenting how they compose with
AP2's Payment Mandate primitive.
Production reference
Both formats are emitted in production by the AlgoVoi platform:
service (
recurr.algovoi.co.uk),live since May 2026.
facilitator (live API surface at
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.
Authorship and substrate-author position
This PR is sole AlgoVoi authorship across the documented formats (both
receipt types), normative seven-field shapes, closed enumerations
(four-element
cancellation_reason, three-elementrefund_result),regulatory mappings, state machine, and the composition with the
AlgoVoi-authored canonicalisation pin
(
urn:x402:canonicalisation:jcs-rfc8785-v1per IETF I-Ddraft-hopley-x402-canonicalisation-jcs-v1).Companion IETF Internet-Drafts:
draft-hopley-x402-cancellation-receipt, sole AlgoVoi authorship.draft-hopley-x402-refund-receipt, sole AlgoVoi authorship.Reference implementations, AlgoVoi-authored, Apache 2.0:
algovoi-cancellation-receipton PyPI,@algovoi/cancellation-receipton npm.algovoi-refund-receipton PyPI,@algovoi/refund-receipton npm.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. Conformance corpus:
chopmob-cloud/algovoi-jcs-conformance-vectors.Both enumerations are closed by design and may be amended only by
a normative successor specification authored by AlgoVoi or with
explicit AlgoVoi co-authorship. Re-publication of either format under
a different attribution does not constitute substrate authorship of
the elements defined here.
No coalition acknowledgements. This specification does not absorb
from, depend on, or share authorship with any other party's work.
Orthogonality
This specification defines the verdict formats at the post-settlement
payment-lifecycle layer. It is orthogonal to the admission-time
compliance verdict format (covered by the sibling AlgoVoi-authored
Compliance Receipt PR), counterparty-risk evidence formats,
settlement-attestation formats, and 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.
Scope
Single new file at
docs/ap2/payment_lifecycle.md. No changes toexisting spec files. No code changes. No samples. The
.cspell/custom-words.txtaddition is project-specific cspell vocabulary for British orthography
matching the IETF I-Ds.
-- AlgoVoi (chopmob-cloud)
https://docs.algovoi.co.uk/acquisition