x402-receipt-verifier について
x402 Receipt Verifierは、NEXUS独自の決済記録が成功したサービス呼び出しに対応するかを調べ、署名付きレシートを発行します。NEXUSのデプロイ済みアセットの決済監査向けで、レシート署名の検証にはオンライン確認が必要です。
主な機能
- 01決済記録と成功した呼び出しの照合
- 02サービス提供の検証結果の返却
- 03HMAC-SHA256署名付きレシートの発行
- 04オンラインでのレシート署名検証
- 05支払者の利用額状況の確認
活用シーン
- 01NEXUSの決済に対応するサービス提供の確認
- 02発行済みレシートの改ざん確認
- 03アセットごとの支払者の利用額状況の確認
MCP 対応
`/mcp`エンドポイントで`verify_payment_receipt`と`payer_spend_health`ツールを提供します。READMEによると、これらのMCP呼び出しは現在無料です。署名検証は別のHTTPエンドポイントで利用できます。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://x402-receipt-verifier-325572559480.us-central1.run.app/mcpclaude mcp add --transport http nexus-mcp-infra-x402-receipt-verifier https://x402-receipt-verifier-325572559480.us-central1.run.app/mcp{"mcpServers":{"nexus-mcp-infra-x402-receipt-verifier":{"type":"http","url":"https://x402-receipt-verifier-325572559480.us-central1.run.app/mcp"}}}Cursor で開く{"servers":{"nexus-mcp-infra-x402-receipt-verifier":{"type":"http","url":"https://x402-receipt-verifier-325572559480.us-central1.run.app/mcp"}}}VS Code で開く{"mcpServers":{"nexus-mcp-infra-x402-receipt-verifier":{"type":"http","url":"https://x402-receipt-verifier-325572559480.us-central1.run.app/mcp"}}}{"mcpServers":{"nexus-mcp-infra-x402-receipt-verifier":{"serverUrl":"https://x402-receipt-verifier-325572559480.us-central1.run.app/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
ツール
詳細
x402 レシート検証ツール
NEXUS 独自の x402 決済ログを配信ログと照合し、特定の決済が実際に成功したサービス呼び出しと対応していることを証明する署名付きレシートを発行します。NEXUS 候補 #13 -- 手動でビルド。FORGE による生成ではありません。
POST /verify-payment-receipt {"asset_name": "...", "payer_address": "0x...", "claimed_amount_usd": 0.01, "claimed_at": "2026-08-22T21:31:34Z"}-- x402 経由で $0.02 を請求(Base メインネット、実際の USDC)。POST /payer-spend-health {"asset_name": "...", "payer_address": "0x..."}-- x402 経由で $0.02 を請求。POST /verify-receipt-signature {"receipt": {...}, "signature": "..."}-- 無料。以前に発行されたレシートが真正で、改ざんされていないことを確認します。/mcpの MCP ツールverify_payment_receipt/payer_spend_health-- 現在は無料。「既知の制限事項」を参照してください。GET /health、GET /.well-known/agent-card.json、GET /openapi.json(x-payment-infoを含む)。
メインネットへの切り替え(2026-09-03)
当初は Base Sepolia テストネット上で構築し、計測していました。Base メインネットに切り替え、x402 の決済処理先を CDP ファシリテーターに変更しました(create_facilitator_config()。ws/live-entity-verification/erc8004-agent-liveness/onchain-activity-index にすでに適用済みのものと同じ切り替えです)。また、支払い先ウォレットを NEXUS_X402_PAYTO_ADDRESS に変更しました(デフォルト値を持たないフェイルファスト環境変数で、X402_WALLET_ADDRESS から名称を変更)。デプロイ前に、Cloud Run で CDP_API_KEY_ID/CDP_API_KEY_SECRET と NEXUS_X402_PAYTO_ADDRESS を設定する必要があります。
実際の処理内容(単なるログのダンプではない理由)
revenue_events(決済が完了した x402 支払い)と traffic_events(処理した HTTP リクエスト)は別々のテーブルで、相互に関連付けられていません。どちらのテーブルにも、特定の決済と、その決済対象の特定のリクエストを結び付ける共通 ID は保存されていません。このアセットは、NEXUS が他のどこでも行っていない照合を実行します。申告された (asset_name, payer_address, claimed_amount_usd, claimed_at) を受け取り、window_seconds 以内に一致する実際の revenue_events 行(存在する場合)を検索します。次に、その実際の決済時刻の直後に、同じアセットに対する成功した(2xx)traffic_events 行が記録されているかを確認します。判定結果(VERIFIED_DELIVERY/PAYMENT_NO_DELIVERY/PAYMENT_NOT_FOUND)と署名付きレシートがこのサービスの成果物であり、どちらかのテーブルへの生データアクセスを提供するものではありません。両テーブルの読み取りには、判定オブジェクトのみを返し、行データのダンプは決して返さない、Postgres の SECURITY DEFINER RPC 関数(nexus_verify_payment_receipt、nexus_payer_spend_health)を使用します。これは、両テーブルに対するこのコードベースの既存の INSERT のみを許可する RLS ポリシーと整合しています(CLAUDE.md SS5 を参照)。マイグレーション:add_x402_payment_receipt_verification_rpcs(Supabase プロジェクト ieduhdgfjdeffvzxvihf)。
意図的に限定した範囲: 対象は、すでにデプロイ済みの NEXUS 独自の x402 アセットのみです(自社の revenue_events/traffic_events に実際に記録されているもの)。第三者の決済申告を第三者のログと照合するのが当初のより広範な案でした(機会リストの項目 #3、「エージェント間決済の検証可能な実行レシート/証明」)。しかし、他の二者間の仲裁者として行動することによる法的責任や紛争責任のリスクがあると、明示的に指摘されていました。対象をすでに公開済みの自社アセットカタログに絞ることで、こうした問題をすべて回避できます。判定する第三者の申告はなく、すでに決済済みの自社データのみを扱います。
確認されている asset_name の表記(実データから判明)
既存カタログ全体で、revenue_events.asset_name の表記は 一貫して kebab-case になっているわけではありません。たとえば、類似性検索アセットの実際の保存値は "Similarity Search API"(表示用の大文字・小文字)であり、similarity-search-api ではありません。呼び出し元は保存されている文字列と完全に一致する値を渡す必要があります。そうしないと、RPC は正しく(バグではなく)PAYMENT_NOT_FOUND を返します。この文書の執筆時点で、revenue_events に確認されている実際の値は document-conversion-api、live-entity-verification、agent-verification-api、url-metadata-api、Similarity Search API、ws です。
署名付きレシート
signature は、NEXUS_RECEIPT_SIGNING_KEY を鍵として、receipt の正規化された JSON エンコーディングに対して計算した HMAC-SHA256(16 進数)です。これはオフラインで検証できる署名ではありません(そのためには非対称暗号と公開済みの公開鍵が必要ですが、意図的に対象外としています。「既知の制限」を参照してください)。レシートの所持者は、このアセットが提供する無料の POST /verify-receipt-signature を呼び出し、サーバー側で HMAC を再検証することで、レシートが本物であることを証明します。NEXUS_RECEIPT_SIGNING_KEY をローテーションすると、古い鍵で発行されたすべてのレシートが無効になります。
デプロイ先:Cloud Run
候補 #4/#3/#6 と同じパイプラインです。skills/infra-deploy-ops を参照してください。
# 1. First deploy -- PUBLIC_DOMAIN not known yet, every real request 421s until step 2.
./scripts/deploy_cloud_run.sh x402-receipt-verifier manual_assets/x402-receipt-verifier
# 2. Grab the printed *.run.app URL, then (only if it differs from env-vars.deploy.yaml's guess):
gcloud run services update x402-receipt-verifier --region us-central1 --project nexus-505016 \
--update-env-vars PUBLIC_DOMAIN=<the-real-domain>
既知の制限(意図的に未修正。CLAUDE.md SS3、必要性を示す証拠がない限りゲートを設けない)
- MCP ツールの呼び出しは課金されません。 このコードベースの他の手動アセット(
url-metadata-api、agent-verification-api、document-conversion-api)と同じインプロセス呼び出しパターンです。 - レシートの署名にはオンラインでの検証が必要であり、オフラインでの非対称検証はできません。上記を参照してください。
- 相関関係の判定は時間枠に基づくヒューリスティックであり、厳密な紐付けではありません。
revenue_eventsもtraffic_eventsも、挿入時に共通の相関 ID を保存しないため、VERIFIED_DELIVERYが示すのは「この支払いの後、時間枠内にこのアセットへのリクエストが成功した」ということであり、「この特定のリクエストが、この特定のトランザクションによって支払われた」ということではありません。トラフィックの少ないアセットでは実質的に正確ですが、多数の呼び出し元が同時にアクセスするような仮想的な高トラフィックのアセットでは判別が曖昧になります。その場合は、candidate_successful_calls(receiptに直接表示されます。main.pyのPaymentReceiptを参照)に 1 より大きい値が示されます。対象となった 6 つのアセットでは、2026-08-23 時点で、この問題が重要になるほど同時トラフィックが集中することはありませんでした。 Supabase RPC の実行前に支払いが確定します……2026-08-31 に訂正:誤検知でした。以下を参照してください。 2026-08-23 の品質ゲートでは、Supabase の障害時にも支払いが確定するとしていました。しかし、記述前にx402(固定バージョン2.15.0)のPaymentMiddlewareASGIのソースを実際に確認した人はいませんでした。ソースにはすでに、検証→実行→2xx の場合のみ確定、という処理が実装されています。ハンドラーの前にverify_payment(資金の移動なし)がcall_next(request)を介して実行されます。ハンドラーが ≥400 を返すか例外を発生させた場合(今回のケースでは Supabase 障害時に_verify_payment_receipt_coreが_NexusRpcErrorをHTTPException(502/503/504)として再送出します)、ミドルウェアはdispatcher.cancel()を呼び出し、process_settlement()は呼び出しません。つまり、課金されません。実際に確認済みです(実アプリと実際のPaymentMiddlewareASGIを使用し、ファシリテーターをモックしてHTTPException(504)を発生させました)。失敗時のsettle()/on_after_settleの呼び出しは 0 回、200 の場合は 1 回でした。コードの変更は不要です。アーキテクチャは当初から正しく実装されていました。- 匿名キーによる RPC の迂回。 2 つの Postgres RPC 関数は
anonに許可されています(PostgREST が関数を公開するために必要です)。SUPABASE_ANON_KEYが漏えいすると、このアセットの x402 課金を迂回して/rest/v1/rpc/nexus_verify_payment_receiptから直接呼び出せます。この RPC は NEXUS 自身の、すでに公開されているアセットカタログに関する相関関係の判定のみを返し、機密情報は公開されないため、許容しています。迂回されるのはペイウォールだけです。このコードベースで Supabase の匿名キーを使用する他のすべてのケースと同じリスクカテゴリです。 - 呼び出し元ごとのレート制限はありません。 7 日間の使い捨て計測期間には問題ありません。
品質ゲート(2026-08-22 デプロイ、支出上限による中断後の2026-08-23にゲート完了)
候補 #3/#4/#6 と同じ2エージェント方式(セキュリティの観点、機能性・品質・購入者体験の観点)で、今回はデプロイ後に実施しました。レビューは進行中でしたが、アカウントの月間支出上限に達したため、セッションが夜間に中断され、次のセッションで再開して完了しました。実際の指摘事項と対応内容は以下のとおりです。
- セキュリティ(指摘1件、低):
POST /verify-receipt-signatureに x402 ゲートとサイズ/深さの上限がなく、任意の呼び出し元が指定したreceipt辞書を無料でハッシュできる状態でした。深刻な脆弱性ではなく、低コストで発生させられるコスト/可用性上の懸念です。修正済み:ハッシュ処理の前に、4096バイト超または深さ10レベル超のリクエストボディを400/413で拒否します(main.pyの_validate_receipt_shape、_MAX_RECEIPT_BYTES/_MAX_RECEIPT_DEPTH)。 - 機能性/購入者体験(指摘1件、中): 2026-08-31に撤回。最初は「RPCが実行される前に決済が完了するため、Supabaseの障害が起きると購入者は請求される一方で救済手段がない」と報告しました。これは
PaymentMiddlewareASGIの読み違いであり、実際のバグではありませんでした。実証による確認については、上記の「既知の制限」を参照してください。 - ほかに確認した項目(候補 #3 のSSRFクラス、候補 #6 のzip爆弾/スレッドリーククラス、匿名キーによるRPCの過剰なデータ返却、HMACの正しさ、候補 #4 の自己決済
payToクラス、IPの切り詰め、インジェクションの攻撃対象領域)はすべて問題ありませんでした。関連するコードパスを再確認しており、単に問題なしと主張しただけではありません。 - 非常に軽微な見た目上の項目を2つ、意図的にそのままにしました。未使用の
ctx: Context = NoneMCPツールパラメーター(agent-verification-api/main.pyにすでにある同種の未使用パラメーターの慣例に沿っており、ここで修正するほどの逸脱ではありません)と、MCPパスでのみwindow_seconds/lookback_daysがエラーを出さずに上限・下限に丸められる点です(RESTではPydanticによって範囲外の値がすでに拒否されます。MCPパスでは置換後の値がレシートに返されるため確認できますが、明示的なエラーにはなりません。現時点ではゲートが必要だとする根拠はありません)。
計測(候補 #13、7日間)
最初の実デプロイから7日間(2026-08-23 → 判断日2026-08-30)。信頼できる情報源はCloud Runのログではなく、traffic_events/revenue_events/mcp_call_events(asset_name = 'x402-receipt-verifier')です。7日目に実際のトラフィックがゼロの場合(クローラーを除外)、Cloud Runサービスを一時停止/削除します(gcloud run services delete x402-receipt-verifier --region us-central1 --project nexus-505016)。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。