x402 的已扣款未交付故障:x402-conformance 的 CI 檢查如何捕捉問題
Paid, charged, empty: the x402 failure that CI should catch
x402-conformance 1.5.0 本週發布,檢查數由 1.0.0 的 23 項增至 58 項,涵蓋 facilitator、資源伺服器及用戶端。檢查涵蓋已結算但未交付、逾時重試導致重複付款等情況;另有兩項針對資產和網絡替換的 facilitator 檢查已合併至 main,將隨 1.6.0 發佈。
The x402 bug I worry about most isn't someone getting content for free. It's the opposite. The client pays, settlement goes through, the money moves, and what comes back is a 500, a redirect, or nothing at all because the connection dropped. Paid, charged, empty.
On the seller's side the logs look fine: a settle succeeded. On the buyer's side, especially when the buyer is an agent with a wallet and a budget, money is gone and no data arrived. It rarely shows up in normal tests, because the happy path works.
In my earlier post I went through five ways a paid endpoint can serve content it wasn't paid for. This one is mostly about the reverse, plus a few related checks I've added since.
What changed
x402-conformance is an open set of checks for x402 facilitators, resource servers and, now, clients. The 1.0.0 release had 23 checks. 1.5.0, published this week, has 58.
- It runs on Solana devnet and Base Sepolia.- It's Apache-2.0.- It never signs, pays or touches mainnet. The devnet runs use throwaway keys, and most checks run against a facilitator double on loopback with no wallet at all.## The money checks The rule behind most of them: if you charged, you delivered. If you didn't deliver, you didn't charge.
- A paid handler that fails (a 5xx, a throw or a redirect) must not be settled, and the server must not send a PAYMENT-RESPONSE for it.- A paid HEAD request is never settled. There's no body to deliver.- If the client disconnects while /settle is in flight, the server either settles nothing, or settles once and returns the settled result when the same signed payment is resent. No second charge.- The paid response keeps the handler's own 2xx status and headers, so a 201 with a Location header stays a 201.- A crash between a successful settle and the response doesn't lead to a second settle after restart.- A client retry after a timeout doesn't pay twice.- One payment identifier settles once, even across eight parallel requests or two replicas.Then there's binding: a payment has to be for the request it's presented on. A payment for a cheap route is refused on a dearer one, a payment with an altered payTo, asset or network is refused before the server calls /settle, and a payment for a cheaper method or query doesn't unlock a dearer one. Some of these (the parallel, replica, delivery and abort checks) are functions you call from your own tests rather than CLI flags. The README shows how. ## Client-side checks Clients can lose money too, so there are three checks for them, run through a recording proxy:
- A client never hands a 402 back to its caller as if it were a success.- Given several offers, a client pays one on its configured networks and within its own maximum amount, not just whichever is listed first.- A client offered x402 V2 doesn't fall back to V1.## Asset and network substitution Someone reviewing the suite pointed out a gap on the facilitator side. A verifier that only compares amount and payTo will accept a payment for the right amount to the right address in a different token. Or one authorized on a different network, like a payment made on devnet presented against a route priced on mainnet. Same number, same recipient, worth nothing to the seller. Two new facilitator checks cover this. One asks /verify to accept a payment in a different mint than the requirement asked for. The other sends a payment whose authorized network differs from the requirement's network while amount, recipient and asset all match. Both must be rejected, and each comes with a deliberately broken facilitator double that the check has to catch. They're on main now and go out in the next release (1.6.0). One limit: the network check covers the facilitator comparing networks. The deeper EVM case, a signature that is valid on more than one chain, needs a live signature to test and is out of reach of the offline checks. ## Try it npx -y x402-conformance-svm demoThat runs the basic resource server checks against a bundled mock server behind a facilitator double. No wallet, no chain, a few seconds. To see what a failure looks like: npx -y x402-conformance-svm demo --fault serve_on_any_settleThen point it at your own server, which needs to read X402_FACILITATOR_URL: npx -y x402-conformance-svm probe --resource http://127.0.0.1:4020/paid --start "node server.js"There's also a GitHub Action if you want it in CI. It's still experimental. Passing a check is evidence about one property, not a certificate of conformance. Issues and check proposals are welcome: github.com/atsp-protocol/x402-conformance
來源:DEV Community · dev.to