Skip to content

Commit b0c64e0

Browse files
committed
spec(errata): §2.2.1 USD=USDC clarification + fixture address realism (audit-A H2/M9)
Closes audit-A residual findings on the spec side. A-H2 (HIGH) — spec/06-x402-integration.md new §2.2.1 Documents that for v1.1.0, amount_usd is the same value as the x402 USDC amount divided by 10^6 — no Stripe processing fee uplift. Wallet path is pre-funded by Stripe with fees already absorbed. Removes ambiguity around sub-cent precision (amount_usd: 0.005 is canonical for a 5,000-micro USDC invoice). A-M9 (MEDIUM) — fixtures/x402-happy-path-pure.json Replaced placeholder addresses that failed the strict 40-hex regex: 0xAAAA…AAA1 (41 chars) -> 0xAaaAaAAaaAaAAaaAaAaAAaaAaAaAAaaAaAaAAaAa 0xSPLITTER…01234 (non-hex) -> 0x000000000000000000000000000000000000C0DE Regenerated base64 X-Payment + X-Payment-Response headers to match. Other 2 fixtures (error-payment-invalid, error-not-accepted) had 0xabc... strings inside narrative messages, not address fields — left intact. Companion commit: JobDoneBot cf17aed Hub + SDK side of audit-A residual sweep
1 parent 19e687b commit b0c64e0

2 files changed

Lines changed: 11 additions & 7 deletions

File tree

fixtures/x402-happy-path-pure.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"Content-Type": "application/json",
1313
"X-Agent-ID": "jdb_ag_x402test_happy_001",
1414
"X-API-Key": "jdb_ak_xxxxxxxxxxxxxxxxxxxxx",
15-
"X-Payment": "eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiYmFzZSIsInBheWxvYWQiOnsic2lnbmF0dXJlIjoiMHgxMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMjM0NTY3OCIsImF1dGhvcml6YXRpb24iOnsiZnJvbSI6IjB4QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUExIiwidG8iOiIweFNQTElUVEVSMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTIzNCIsInZhbHVlIjoiMjAwMDAwIiwidmFsaWRBZnRlciI6IjE3NjI2ODk2MDAiLCJ2YWxpZEJlZm9yZSI6IjE3NjI2ODk2NjAiLCJub25jZSI6IjB4ZGVhZGJlZWYwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1NjcifX19"
15+
"X-Payment": "eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiYmFzZSIsInBheWxvYWQiOnsic2lnbmF0dXJlIjoiMHgxMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMjM0NTY3OCIsImF1dGhvcml6YXRpb24iOnsiZnJvbSI6IjB4QWFhQWFBQWFhQWFBQWFhQWFBYUFBYWFBYUFhQUFhYUFhQWFBQWFBYSIsInRvIjoiMHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBDMERFIiwidmFsdWUiOiIyMDAwMDAiLCJ2YWxpZEFmdGVyIjoiMTc2MjY4OTYwMCIsInZhbGlkQmVmb3JlIjoiMTc2MjY4OTY2MCIsIm5vbmNlIjoiMHhkZWFkYmVlZjAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3In19fQ=="
1616
},
1717
"body": {
1818
"jecp": "1.0",
@@ -30,8 +30,8 @@
3030
"payload": {
3131
"signature": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef12345678",
3232
"authorization": {
33-
"from": "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1",
34-
"to": "0xSPLITTER000000000000000000000000000001234",
33+
"from": "0xAaaAaAAaaAaAAaaAaAaAAaaAaAaAAaaAaAaAAaAa",
34+
"to": "0x000000000000000000000000000000000000C0DE",
3535
"value": "200000",
3636
"validAfter": "1762689600",
3737
"validBefore": "1762689660",
@@ -44,7 +44,7 @@
4444
{
4545
"endpoint": "/verify",
4646
"request_body": { "x402Version": 1, "paymentPayload": "<echoes decoded>", "paymentRequirements": "<from challenge>" },
47-
"response_body": { "isValid": true, "invalidReason": null, "payer": "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1" }
47+
"response_body": { "isValid": true, "invalidReason": null, "payer": "0xAaaAaAAaaAaAAaaAaAaAAaaAaAaAAaaAaAaAAaAa" }
4848
},
4949
{
5050
"endpoint": "/settle",
@@ -54,7 +54,7 @@
5454
"errorReason": null,
5555
"transaction": "0xc0ffee0000000000000000000000000000000000000000000000000000000001",
5656
"network": "base",
57-
"payer": "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1"
57+
"payer": "0xAaaAaAAaaAaAAaaAaAaAAaaAaAaAAaaAaAaAAaAa"
5858
}
5959
}
6060
],
@@ -64,7 +64,7 @@
6464
"headers": {
6565
"Content-Type": "application/json",
6666
"Cache-Control": "no-store",
67-
"X-Payment-Response": "eyJzdWNjZXNzIjp0cnVlLCJ0cmFuc2FjdGlvbiI6IjB4YzBmZmVlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxIiwibmV0d29yayI6ImJhc2UiLCJwYXllciI6IjB4QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUExIn0=",
67+
"X-Payment-Response": "eyJzdWNjZXNzIjp0cnVlLCJ0cmFuc2FjdGlvbiI6IjB4YzBmZmVlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMSIsIm5ldHdvcmsiOiJiYXNlIiwicGF5ZXIiOiIweEFhYUFhQUFhYUFhQUFhYUFhQWFBQWFhQWFBYUFBYWFBYUFhQUFhQWEifQ==",
6868
"Access-Control-Expose-Headers": "X-Payment-Response, X-Request-Id"
6969
},
7070
"body": {
@@ -83,7 +83,7 @@
8383
"x402": {
8484
"settlement_tx": "0xc0ffee0000000000000000000000000000000000000000000000000000000001",
8585
"network": "base",
86-
"payer": "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1",
86+
"payer": "0xAaaAaAAaaAaAAaaAaAaAAaaAaAaAAaaAaAaAAaAa",
8787
"facilitator": "https://x402.org/facilitator"
8888
}
8989
},

spec/06-x402-integration.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ WWW-Authenticate: x402 realm="jecp.dev", network="base", asset="USDC"
113113
| `WWW-Authenticate` header | SHOULD | Standard HTTP challenge per RFC 7235. Allows non-JSON-aware clients to surface the requirement. |
114114
| `Cache-Control: no-store` | MUST | Prevents CDN caching of paid challenge responses. |
115115

116+
#### 2.2.1 `amount_usd` semantics on `stripe-wallet` entries
117+
118+
When both `stripe-wallet` and `exact` (x402) entries are emitted for the same action, the `stripe-wallet` entry's `amount_usd` and the `exact` entry's `max_amount_required` (atomic USDC) reference the **same underlying price**. For v1.1.0, USD ≡ USDC at 1:1 — the `amount_usd` value is `max_amount_required ÷ 10^6` exactly, with no Stripe processing-fee uplift. Rationale: the wallet path is pre-funded via Stripe (top-up flows absorb the fee at top-up time), so per-call billing does not re-charge for fees. Hubs MUST serialize `amount_usd` with up to 6 decimal places so sub-cent prices (e.g., `$0.005` = `5000` micro-USDC) round-trip cleanly through JSON; clients MUST NOT cast to integer cents. A future v1.2 MAY introduce per-call fee uplift; if so, the relationship between the two amounts will be redefined under a new field — the v1.1.0 invariant is "same value, different unit."
119+
116120
### 2.3 `accepts[]` order
117121

118122
When both `stripe-wallet` and `exact` (x402) entries are present, the Hub MUST list `stripe-wallet` first. Rationale: Stripe is more recoverable (chargeback / dispute paths exist). This is a normative requirement to mitigate mode-confusion attacks (Panel 2 TM-MC: agents that misinterpret order may consume the wrong signed authorization). x402-native positioning lives in marketing surfaces, not in protocol field order.

0 commit comments

Comments
 (0)