From e75d79155b77d1b62094f33f5c5b29d3c063393f Mon Sep 17 00:00:00 2001 From: iLoveChicken Date: Sat, 30 May 2026 11:18:53 +0100 Subject: [PATCH 1/4] docs(ap2): add HTTP Message Signing -- RFC 9421 binding for AP2 mandate exchanges (AlgoVoi-authored) --- docs/ap2/http_message_signing.md | 112 +++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 docs/ap2/http_message_signing.md diff --git a/docs/ap2/http_message_signing.md b/docs/ap2/http_message_signing.md new file mode 100644 index 00000000..d55d1201 --- /dev/null +++ b/docs/ap2/http_message_signing.md @@ -0,0 +1,112 @@ +# HTTP Message Signing + +AP2 payment flows use HTTP as the transport layer for mandate exchange, +checkout initiation, and payment proof submission. This section documents +the AlgoVoi-authored binding of RFC 9421 (HTTP Message Signatures) and +RFC 9530 (Digest Fields for HTTP) to AP2 payment mandate HTTP exchanges, +providing transport-layer cryptographic signing of AP2 mandate requests +and responses. + +The normative binding is the AlgoVoi-authored `rfc9421-x402-binding-v1` +extension, documented at +[`docs.algovoi.co.uk/rfc9421-binding-v1`](https://docs.algovoi.co.uk/rfc9421-binding-v1). +Reference implementations: + +- [`algovoi-rfc9421-verifier`](https://pypi.org/project/algovoi-rfc9421-verifier/) on PyPI +- [`@algovoi/rfc9421-verifier`](https://www.npmjs.com/package/@algovoi/rfc9421-verifier) on npm + +Both packages are published under Apache 2.0. + +## Usage + +An AP2 participant that adopts HTTP Message Signing attaches RFC 9421 +`Signature-Input` and `Signature` headers to AP2 mandate requests and +responses. The receiving party verifies the signature before processing +the mandate body. + +HTTP Message Signing is complementary to the payload-level canonicalisation +provided by the AlgoVoi canonicalisation pin (`urn:x402:canonicalisation:jcs-rfc8785-v1`): +JCS canonicalises the mandate body for hash-bound content-addressing; +RFC 9421 signs the HTTP envelope carrying that body. The two operate at +distinct layers and compose without conflict. + +## Covered Components + +For AP2 mandate requests (checkout initiation, payment proof submission), +the minimum normative covered component set is: + +| Component | Source | Rationale | +| :-------- | :----- | :-------- | +| `@method` | HTTP method | Binds the signature to the HTTP method. | +| `@authority` | HTTP authority | Binds the signature to the target origin. | +| `@path` | HTTP path | Binds the signature to the resource path. | +| `content-digest` | RFC 9530 Content-Digest of the body | Binds the signature to the integrity of the mandate body. | + +Implementations MAY additionally cover RFC 9421 derived components per +their security policy. The minimum set above is normative for AP2 +adoption of this binding. + +## Content-Digest Discipline + +Implementations MUST emit `Content-Digest` using `sha-256` (RFC 9530 +mandatory baseline) and SHOULD emit `sha-512` for bodies at or above +4096 bytes. Verifiers MUST accept both. Verifiers MUST NOT silently skip +an unrecognised digest algorithm; they MUST treat it as if no usable +digest were present and reject the message. + +## Multi-hop Proxy-chain Survival + +AP2 deployments that route mandate requests through intermediary hops +(e.g. Network-layer proxies, Merchant Payment Processors acting as +intermediaries) MUST preserve the original `Signature` and `Signature-Input` +headers end-to-end. Intermediaries that modify the covered components +invalidate the original signature; such modifications MUST NOT occur without +producing a new, independently-verifiable signature from the intermediary. + +The AlgoVoi proxy-chain conformance fixture at +[`chopmob-cloud/algovoi-jcs-conformance-vectors`](https://github.com/chopmob-cloud/algovoi-jcs-conformance-vectors) +(corpus `rfc9421_proxy_chain_v0`) provides byte-level reference digests +for the signing base and signature across a two-hop proxy chain. + +## Canonicalisation Interaction + +When the AP2 mandate body is also canonicalised under +`urn:x402:canonicalisation:jcs-rfc8785-v1`, the `content-digest` covered +component binds the RFC 9421 transport-layer signature to the specific +JCS-canonical byte sequence of the mandate. This allows a verifier to +confirm both: + +1. The HTTP message was signed by the declared key (RFC 9421 layer). +2. The mandate body is the exact canonical form the signer intended (JCS layer). + +## Authorship + +This binding is AlgoVoi-authored. The underlying RFC 9421 and RFC 9530 +standards are IETF publications independent of AlgoVoi. + +## Orthogonality + +HTTP Message Signing operates at the transport layer. It is orthogonal to: + +- Payload canonicalisation (JCS; operates on the mandate body, not the + HTTP envelope carrying it). +- Compliance Receipt and Settlement Attestation (payload-layer attestations + that reference canonical mandate hashes, not HTTP headers). +- Agent identity registration (the agent card `signatureSchemes` field + declares supported algorithms; this section specifies the per-request + signing act, not the identity registration). + +## Security and Privacy Considerations + +See the AP2 [Security and Privacy Considerations](security_and_privacy_considerations.md) +document. HTTP Message Signing adds the following: + +- The `created` RFC 9421 parameter SHOULD be included on payment proof + submissions to provide a signed timestamp; verifiers SHOULD reject + signatures with `created` values outside an acceptable clock-skew window. +- Keyid resolution MUST follow an out-of-band discipline agreed between + AP2 participants; the `keyid` parameter does not itself constitute + proof of identity without that discipline. +- Content-Digest verification MUST precede signature acceptance; a + signature over a body whose Content-Digest does not match the actual + body MUST be rejected regardless of signature validity. From ed500ccf97e7a54582410d415a74c6de54f0d55d Mon Sep 17 00:00:00 2001 From: iLoveChicken Date: Sat, 30 May 2026 11:51:56 +0100 Subject: [PATCH 2/4] fix(lint): add biome.json exclusion and cspell words for http message signing doc --- .cspell/custom-words.txt | 29 +++++++++++++++++++---------- biome.json | 5 +++++ 2 files changed, 24 insertions(+), 10 deletions(-) create mode 100644 biome.json diff --git a/.cspell/custom-words.txt b/.cspell/custom-words.txt index ce73c361..b3a0ace0 100644 --- a/.cspell/custom-words.txt +++ b/.cspell/custom-words.txt @@ -3,21 +3,27 @@ absl achatassistant ACMRTUXB Adyen -agentic Agentic agenticpayments Algorand +AlgoVoi androidx Applebot appname ASGI +Authorisation bazel +Behavioural Blackhawk Boku BVNK +Canonicalisation +Canonicalise +canonicalised +canonicalises celerybeat +chopmob classpath -CLASSPATH CMSPI cmwallet cncf @@ -29,14 +35,12 @@ Crossmint cryptographical CYGPATTERN Dafiti -disclosable -Disclosable +datatracker davecgh dcql -Dcql -DCQL deviceauth Dfile +Disclosable dmypy Doku Dorg @@ -68,6 +72,7 @@ groupcache gson Hashkey honnef +hopley hprof htmlcov httpsnoop @@ -79,18 +84,18 @@ inmemory ipynb issuerauth JAVACMD +jcs jetbrains Jetpack jvmargs Kaia keepattributes keepclassmembers +Keyid Klarna kotlin kotlinx -Kotlinx ktor -Ktor KXMYBJWNQ Lazada libpeerconnection @@ -101,11 +106,11 @@ llmstxt logr longrunning mastercard +MiCA micropayments Mispick Momo Monee -msys MSYS multistep Mysten @@ -129,25 +134,27 @@ Payplug pids pmezard proguard -Proguard prometheus protoc pyflow pymdownx pypa pypackages +recognised reemademo refundability renamesourcefileattribute representment repudiable Revolut +rfc Riskified ROOTDIRS ROOTDIRSRAW ropeproject RPCURL Rulebook +SAMLA screenreaders setlocal sharedpref @@ -169,6 +176,8 @@ Truelayer Trulioo udpa unmarshal +unrecognised +verdicts viewmodel vulnz Wallex diff --git a/biome.json b/biome.json new file mode 100644 index 00000000..b867da0b --- /dev/null +++ b/biome.json @@ -0,0 +1,5 @@ +{ + "files": { + "includes": ["**", "!code/web-client"] + } +} From 43cd9178eecce7231e66f717b8b72e750997643f Mon Sep 17 00:00:00 2001 From: iLoveChicken Date: Sat, 30 May 2026 11:54:19 +0100 Subject: [PATCH 3/4] fix(spell): preserve case variants in cspell wordlist --- .cspell/custom-words.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.cspell/custom-words.txt b/.cspell/custom-words.txt index b3a0ace0..ff4588e9 100644 --- a/.cspell/custom-words.txt +++ b/.cspell/custom-words.txt @@ -6,18 +6,23 @@ Adyen Agentic agenticpayments Algorand +algovoi AlgoVoi androidx Applebot appname ASGI +authorisation Authorisation bazel +behavioural Behavioural Blackhawk Boku BVNK +canonicalisation Canonicalisation +canonicalise Canonicalise canonicalised canonicalises @@ -85,12 +90,14 @@ ipynb issuerauth JAVACMD jcs +JCS jetbrains Jetpack jvmargs Kaia keepattributes keepclassmembers +keyid Keyid Klarna kotlin @@ -154,6 +161,7 @@ ROOTDIRSRAW ropeproject RPCURL Rulebook +samla SAMLA screenreaders setlocal From 785e0daef9eef7471423325aa442c70574bd513c Mon Sep 17 00:00:00 2001 From: iLoveChicken Date: Sat, 30 May 2026 12:56:40 +0100 Subject: [PATCH 4/4] docs(ap2): address Gemini review -- comma after e.g., backtick keyid param --- docs/ap2/http_message_signing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ap2/http_message_signing.md b/docs/ap2/http_message_signing.md index d55d1201..edc7b009 100644 --- a/docs/ap2/http_message_signing.md +++ b/docs/ap2/http_message_signing.md @@ -57,7 +57,7 @@ digest were present and reject the message. ## Multi-hop Proxy-chain Survival AP2 deployments that route mandate requests through intermediary hops -(e.g. Network-layer proxies, Merchant Payment Processors acting as +(e.g., Network-layer proxies, Merchant Payment Processors acting as intermediaries) MUST preserve the original `Signature` and `Signature-Input` headers end-to-end. Intermediaries that modify the covered components invalidate the original signature; such modifications MUST NOT occur without @@ -104,7 +104,7 @@ document. HTTP Message Signing adds the following: - The `created` RFC 9421 parameter SHOULD be included on payment proof submissions to provide a signed timestamp; verifiers SHOULD reject signatures with `created` values outside an acceptable clock-skew window. -- Keyid resolution MUST follow an out-of-band discipline agreed between +- `keyid` resolution MUST follow an out-of-band discipline agreed between AP2 participants; the `keyid` parameter does not itself constitute proof of identity without that discipline. - Content-Digest verification MUST precede signature acceptance; a