integration(x402): buyer-funnel stack + v2 PAYMENT-SIGNATURE (supersedes #686–689) - #690
Merged
Conversation
…metadata
- new internal/buyprompts package is the one authoring point for how-to-buy
copy; the 402 page, /api/services.json ('buy' block with callShape +
prompts per buyer-software kind), the storefront, and 'obol sell info'
all render it, so instructions can no longer drift between surfaces
(the storefront was still advertising the removed --no-verify-identity flag)
- catalog entries gain openapiPath + docsPath (Scalar deep-link anchor);
storefront shows API-docs links for every offer type, skill.md service
details link the anchored docs
- x-payment-info always emits accepts[] with payTo, CAIP-2 network, atomic
amount, and the asset's EIP-712 signing domain, so an OpenAPI-only client
can construct a valid X-PAYMENT without a second fetch
- @scalar/api-reference bumped 1.34.0 -> 1.62.1; renovate custom manager +
postUpgradeTasks now keep it current, with scripts/update-scalar-sri.sh
refreshing the SRI hash inside the same renovate PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nnel metrics
- HandleProxy rewrites bare POST /services/<name> (and /chat/completions,
/v1) to /v1/chat/completions for agent/inference offers, so the most
common wrong-path mistake from external buyers succeeds instead of
paying into a 404; the 402 page's agent copy taught exactly that bare
form until this change
- terminal payment failures return structured JSON {error, reason, hint,
retriable}; the facilitator's invalidReason (previously discarded) now
rides the re-issued 402 challenge in error + extensions.paymentFailure,
and signature rejections state the expected EIP-712 domain
- legacy error phrases kept verbatim (flows/lib.sh greps for them)
- new funnel metrics: payment_failure_reasons_total{reason} (bounded
6-value set) and upstream_failed_after_verify_total, so first-try buyer
success is measurable per stage; docs/observability.md updated
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The ForwardAuth verifier advertises x402Version 2 in its 402 challenge but only read the payment from the legacy v1 X-PAYMENT header. Spec-compliant x402 v2 buyers (agentcash, poncho, coinbase SDK >= v2) attach the payment under PAYMENT-SIGNATURE, so their valid payment was silently ignored and the caller re-challenged — no verify, no settle, no log. This blocked every third-party v2 client from paying obol endpoints; only the in-tree buyer (which sends X-PAYMENT) worked. - Read the payment from X-PAYMENT (v1) OR PAYMENT-SIGNATURE (v2). - Decode via the canonical x402types.ToPaymentPayload helper instead of a local json.Unmarshal, keeping the envelope in lockstep with the SDK. - Mirror the settlement receipt onto both X-PAYMENT-RESPONSE and PAYMENT-RESPONSE. - Tests for the v2 header accept + settle + dual response header. Claude-Session: https://claude.ai/code/session_01VquWN9UMaSHH7MHGcG8bw1
Post-#689 a spec-compliant x402 v2 payment arrives under PAYMENT-SIGNATURE, but the funnel gate hadPayment only checked X-PAYMENT — so every successful v2 payment (exactly the cohort #689 unblocked) incremented none of the success/charge/upstream counters. Gate on both headers. Emergent defect of integrating #688 (X-PAYMENT-gated metrics) with #689 (v2 via PAYMENT-SIGNATURE).
This was referenced Jul 2, 2026
OisinKyne
approved these changes
Jul 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
One PR superseding #686, #687, #688, #689 — the buyer-funnel stack plus the x402 v2
PAYMENT-SIGNATUREfix, integrated with theforwardauth.goconflict resolved and two emergent defects fixed.Contents
26c058dcfaf3e9ServiceCardc5a2c57PAYMENT-SIGNATUREheader — already validated live on-chainforwardauth.goconflicts resolved keep-bothPAYMENT-SIGNATURE) payments in the funnel (emergent defect)forwardauth.goconflict resolution (keep-both)ToPaymentPayloaddecode (fix(x402): accept x402 v2 PAYMENT-SIGNATURE header in ForwardAuth verifier #689) wrapped in feat(x402): tolerant chat-path gateway, structured payment errors, funnel metrics #688's structuredwritePaymentError/reportFailure.X-PAYMENT-RESPONSEandPAYMENT-RESPONSEreceipt headers (fix(x402): accept x402 v2 PAYMENT-SIGNATURE header in ForwardAuth verifier #689) alongside feat(x402): tolerant chat-path gateway, structured payment errors, funnel metrics #688'ssettledOnChaindouble-pay guard.X-PAYMENT / PAYMENT-SIGNATURE(was v1-only).Emergent defect fixed
verifier.gogated the funnel metrics onhadPayment := Get("X-PAYMENT") != "". After #689, a spec-compliant v2 payment arrives underPAYMENT-SIGNATURE, so every successful v2 payment — exactly the cohort #689 unblocked — incremented none of the success/charge/upstream counters.hadPaymentnow checks both headers.Validation
go build ./...✓;internal/x402,internal/buyprompts,internal/serviceoffercontrollersuites green.Supersedes #686, #687, #688, #689.