Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 29 additions & 10 deletions .cspell/custom-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,34 @@ absl
achatassistant
ACMRTUXB
Adyen
agentic
Agentic
agenticpayments
Algorand
algovoi
AlgoVoi
AMLR
androidx
Applebot
appname
ASGI
authorisation
Authorisation
bazel
behavioural
Behavioural
Blackhawk
Boku
BVNK
CAIP
canonicalisation
Canonicalisation
canonicalise
Canonicalise
canonicalised
canonicalises
celerybeat
chopmob
classpath
CLASSPATH
CMSPI
cmwallet
cncf
Expand All @@ -29,14 +42,12 @@ Crossmint
cryptographical
CYGPATTERN
Dafiti
disclosable
Disclosable
datatracker
davecgh
dcql
Dcql
DCQL
deviceauth
Dfile
Disclosable
dmypy
Doku
Dorg
Expand Down Expand Up @@ -68,6 +79,7 @@ groupcache
gson
Hashkey
honnef
hopley
hprof
htmlcov
httpsnoop
Expand All @@ -79,6 +91,8 @@ inmemory
ipynb
issuerauth
JAVACMD
jcs
JCS
jetbrains
Jetpack
jvmargs
Expand All @@ -88,8 +102,6 @@ keepclassmembers
Klarna
kotlin
kotlinx
Kotlinx
ktor
Ktor
KXMYBJWNQ
Lazada
Expand All @@ -101,12 +113,13 @@ llmstxt
logr
longrunning
mastercard
MiCA
micropayments
microunits
Mispick
Momo
Monee
msys
MSYS
multistep
Mysten
nexi
Expand All @@ -129,25 +142,29 @@ Payplug
pids
pmezard
proguard
Proguard
prometheus
protoc
pyflow
pymdownx
pypa
pypackages
recognised
reemademo
refundability
renamesourcefileattribute
reorganised
representment
repudiable
Revolut
rfc
Riskified
ROOTDIRS
ROOTDIRSRAW
ropeproject
RPCURL
Rulebook
samla
SAMLA
screenreaders
setlocal
sharedpref
Expand All @@ -169,6 +186,8 @@ Truelayer
Trulioo
udpa
unmarshal
unrecognised
verdicts
viewmodel
vulnz
Wallex
Expand Down
5 changes: 5 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"files": {
"includes": ["**", "!code/web-client"]
}
}
161 changes: 161 additions & 0 deletions docs/ap2/settlement_attestation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# Settlement Attestation

The Settlement Attestation is a categorical, content-addressed attestation
envelope emitted by a facilitator after settlement is confirmed on-chain.
It is the post-settlement categorical record: did the on-chain transaction
settle as expected, is it still awaiting finality, or was it reversed?

The format is AlgoVoi-authored. AP2 references it; AP2 does not redefine
it. The normative wire format is the canonical AlgoVoi Settlement Attestation
specified in IETF Internet-Draft
[`draft-hopley-x402-settlement-attestation`](https://datatracker.ietf.org/doc/draft-hopley-x402-settlement-attestation/)
and documented at
[`docs.algovoi.co.uk/settlement-attestation-v1`](https://docs.algovoi.co.uk/settlement-attestation-v1).

## Usage

The Settlement Attestation is generated by the facilitator after on-chain
confirmation of a payment transaction. It SHOULD be emitted before any
post-settlement notification is issued to the merchant or shopping agent.

The attestation enables a Shopping Agent or downstream relying party to
confirm the categorical settlement outcome without querying the chain
directly, and provides a categorical decision record that satisfies
record-keeping obligations under MiCA Article 80, AMLR Article 56,
DORA Article 14, and UK MLRs 2017 Regulation 40.

## Attestation Shape

A Settlement Attestation is a JSON object canonicalised under RFC 8785
(JCS). Field names are sorted lexicographically by JCS during
canonicalisation.

```json
{
"amount_microunits": 1000000,
"asset_id": "eip155:84532/erc20:0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"canon_version": "jcs-rfc8785-v1",
"chain": "eip155:84532",
"settled_at": "2026-05-30T06:38:46Z",
"settled_payment_ref": "sha256:0dd5d0b76c9b9281fdeb2509ad38ab132b16a17385ca01d976ff9e6e12563a0f",
"settlement_status": "SETTLED",
"signature": "<detached signature over JCS canonical bytes>",
"tx_id": "0x3a3777f4e2b6e3e0e0e3f3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3"
}
```text

| Field | Type | Description |
| :---- | :--- | :---------- |
| `amount_microunits` | integer | Settled amount in chain-native microunits. MUST be a JSON integer; string-encoded representations are rejected at canonicalisation time. |
| `asset_id` | string | CAIP-19 asset identifier of the settled asset. |
| `canon_version` | string | In-band canonicalisation pin. Fixed `jcs-rfc8785-v1` for this version. |
| `chain` | string | CAIP-2 chain identifier. |
| `settled_at` | string | ISO 8601 UTC timestamp of facilitator-side settlement confirmation. |
| `settled_payment_ref` | string | `sha256:{hex}` content-addressed reference to the settled Payment Mandate. |
| `settlement_status` | string (closed enum) | `SETTLED` / `PENDING_FINALITY` / `REVERSED`. |
| `signature` | string | Detached signature over the JCS canonical bytes. |
| `tx_id` | string | Chain-native transaction identifier as confirmed on-chain. |

## The closed enumeration: `settlement_status`

The `settlement_status` field MUST take one of exactly three values:

| Value | Meaning | Regulatory significance |
| :---- | :------ | :---------------------- |
| `SETTLED` | Transaction confirmed on-chain at or beyond the chain-specific finality threshold | Discharges MiCA Article 80 / AMLR Article 56 / UK MLRs 2017 Reg 40 transaction record obligations for the settled payment. |
| `PENDING_FINALITY` | Transaction observed on-chain but has not yet reached the required confirmation depth | Enables downstream parties to defer post-settlement actions until finality is confirmed. |
| `REVERSED` | Transaction was previously SETTLED or PENDING_FINALITY but has subsequently been reorganised out, refunded, or otherwise reversed | Triggers DORA Article 14 operational-resilience incident handling at the facilitator. |

A `PENDING_FINALITY` attestation MAY be superseded by a later `SETTLED`
or `REVERSED` attestation referencing the same `tx_id`. Implementations
MUST treat the latest attestation as authoritative for a given `tx_id`.

The enumeration is **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.

## Canonicalisation

The attestation is canonicalised under RFC 8785 (JCS) per the
canonicalisation pin URI `urn:x402:canonicalisation:jcs-rfc8785-v1`,
defined in IETF Internet-Draft
[`draft-hopley-x402-canonicalisation-jcs-v1`](https://datatracker.ietf.org/doc/draft-hopley-x402-canonicalisation-jcs-v1/).

The discipline is byte-for-byte cross-validated across eight independent
implementations (Python, TypeScript, Go, Rust, Java, PHP, .NET, Ruby)
per the AlgoVoi 8-impl matrix. Reference implementations:

- [`algovoi-settlement-attestation`](https://pypi.org/project/algovoi-settlement-attestation/) on PyPI
- [`@algovoi/settlement-attestation`](https://www.npmjs.com/package/@algovoi/settlement-attestation) on npm

Both packages are published under Apache 2.0.

## Composition

The Settlement Attestation chains from the Compliance Receipt via the
`settled_payment_ref` field:

```text
compliance receipt (ALLOW)
|
v
settlement attestation (SETTLED / PENDING_FINALITY / REVERSED)
|
v (if mandate subsequently cancelled)
cancellation receipt (see Payment Lifecycle)
|
v (if refund owed)
refund receipt (see Payment Lifecycle)
```text

A verifier walking this chain confirms the full mandate lifecycle under
one canonicalisation pin, starting from the admission decision.

## Authorship and Substrate-Author Position

This specification documents the AlgoVoi-authored Settlement Attestation
format. AlgoVoi is sole author across the normative format, the canonical
field shape, the closed three-element status enumeration, the regulatory
mapping, and the composition with the AlgoVoi-authored canonicalisation pin.

This specification does not absorb from, depend on, or share authorship
with any other party's work.

## Production Reference

The format is generated in production by the AlgoVoi facilitator. Live
settlement attestations have been emitting against Base Sepolia
(chain `eip155:84532`) since 2026-05-26. Public verifier:
[`verify.algovoi.co.uk/action-ref`](https://verify.algovoi.co.uk/action-ref).

## Orthogonality

The Settlement Attestation records the **categorical post-settlement
status** observed on-chain. It is orthogonal to:

- Admission-time compliance verdicts (Compliance Receipt; separate format).
- Cryptographic proof-of-payment-conditions receipts (e.g. STARK receipt
extensions; those prove cryptographic conditions held; this records
categorical on-chain status).
- Post-settlement mandate lifecycle (cancellation, refund) covered by the
Payment Lifecycle specification.
- Composite trust verdicts (Trust Query; separate format).

The Settlement Attestation makes no claims about, and depends 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 Settlement Attestation adds the following considerations:

- The `settled_payment_ref` binds the attestation to a specific Payment
Mandate by JCS canonical hash; mutation of the bound mandate invalidates
the binding and any verifier MUST re-derive the canonical hash before
accepting the attestation.
- A `REVERSED` status attestation MUST be retained alongside any prior
`SETTLED` or `PENDING_FINALITY` attestation for the same `tx_id` to
provide a complete audit trail under DORA Article 14.
- The `tx_id` field is chain-native and opaque; relying parties MUST NOT
interpret its internal structure beyond treating it as a unique
transaction identifier for the declared `chain`.
Loading