Skip to content

feat(x402-mcp): wallet_history — 手元の購入ログで「何を買ったか」を確認できる (0.16.0) - #547

Merged
cipherwebllc merged 2 commits into
mainfrom
feat/mcp-wallet-history
Sep 21, 2026
Merged

cipherwebllc merged 2 commits into
mainfrom
feat/mcp-wallet-history

Conversation

@cipherwebllc

Copy link
Copy Markdown
Owner

何を足すか

Agent が x402 で「何を買ったか」を、ウォレットの持ち主が後から確認できるようにする (/agent の follow-up ③)。x402_pay (search_shops を含む) の試行を手元の <OPENPAY_X402_HOME>/purchases.jsonl に記録し、新ツール wallet_history (x402 profile のみ・read-only) で直近を読む。

  • サーバは何も保持しないSDK は無変更 (公開済み 0.9.0 のまま)・Web 側コードも無変更
  • 金額と着金の真実は /agent の Agent activity (オンチェーン)。こちらは「何を」を補う。金額と tx は settlement: verified の領収書からだけ写す (SDK が署名内容との一致と署名者を検証済み)。tx で Activity の行と突き合わせられる
  • 設計: plans/agent-purchase-history.md v0.2 案 A (Sonnet 内部調査 → Fable 設計 → Codex 計画レビュー P0 1 / P1 12 反映 → user 裁定 9/22 = 案 A 先行)。案 B (サーバ索引+所有証明+Web 表示) は需要待ち

⚠️ 掟 15 対象 — merge 前に user の明示レビューをお願いします

買い手側の支払い経路を包む変更です。見てほしい箇所 (この順):

  1. packages/x402-mcp/src/tools.mjsx402PayImpl (約 25 行) — 既存の pay 本体は x402PayWithoutHistory名前を変えただけで中身は無変更。履歴は前後に足すだけ・例外は同じオブジェクトを再 throw・戻り値はオブジェクトのときだけ history: 'recorded' | 'failed' を足す
  2. packages/x402-mcp/src/history.mjsoutcomeFor (8 行) — 支払い結果の 4 分類は settlement と HTTP status だけで機械判定。body の文字列や LLM の解釈に委ねない。verified 以外を支払い済みと表示しない
  3. withDeadline — 履歴 I/O は 2 秒で打ち切り。固まったファイルシステムが、支払い済みの結果の返却を止めない (止まると再支払いを招く)
  4. 記録に入るもの: urlFieldsreceiptFields (どちらも許可フィールドのコピー)。署名・nonce・authorization・鍵・応答 body・query・第三者 host の path は入らない

公開文言 (要承認)

packages/x402-mcp/README.md の新節「Local purchase history」・ツール表 1 行・env 表 1 行・CHANGELOG.md の 0.16.0・ツールの description と固定 note (英語)。README の Local wallet threat model 節は無変更 (SHA-256 固定のテストが pass)。

順序 (0.15 のときと同じ)

この PR (MCP 0.16.0) → レビュー → merge → 実機一巡 (x402_paywallet_history) → user が npm publish → 別 PR で Web 切替 (lib/agentSetup.ts の版固定 0.16・public/agent/setup.mdpublic/llms.txt 12 ツール・agent-templates)。npm に 0.16.0 が出るまで Web の版固定は 0.15 のまま。

このため tests/lib/agentSetup.test.ts の版フェンスを「Web の版固定 = リポの MCP と同じ minor か、ちょうど 1 つ前 (major 跨ぎは次の major の .0)」に緩めた。Web の先行と 2 minor 以上の遅れは引き続き fail。

検証

  • tests/packages + 版フェンス 4 file: 32 files / 472 tests pass。入れ子の公開版 SDK (packages/x402-mcp/node_modules/openpay-x402-sdk) を退避した CI 相当でも同数 pass
  • 新規 tests/packages/x402-mcp-history.test.ts 67 件: 実 SDK + 実 fs で、verified / unverified / receipt_unavailable / 非 2xx / guard 拒否 / throw / 送信後の transport 失敗・履歴の失敗 (start / end / both) と I/O ハング (start / end) が pay の結果を変えない・秘密が入らない・symlink / hard link / 非絶対パス / 権限 / lstat-open 間のすり替え・ローテーション・壊れた行・全 signer mode・order profile に出ない
  • 既存 11 ツールの wire は byte 不変 (slice(0,11) の hash を固定) で末尾に 1 本追加・package-lock.json の差分は版の 2 行だけ (掟 16)・梱包フェンスに src/history.mjs 同梱と purchases*.jsonl 非同梱
  • history.mjs が import する SDK の 2 export (formatAtomicJpycSUPPORTED_JPYC_ASSETS) は公開済み 0.9.0 に実在 (registry の integrity と一致する入れ子の SDK で確認)
  • テスト実行後も実ホーム ~/.openpay-x402purchases.jsonl は作られない (x402_pay を呼ぶ既存テスト 5 file は一時ディレクトリへ隔離)
  • typecheck / eslint OK・smoke:list-tools 12 ツール
  • Opus 5 抜け漏れチェック: P0 なし・P1 1 (履歴 I/O に期限が無い) を反映。P2 のうち O_NOFOLLOW・応答の形の保護・note の追記・版フェンスの major 跨ぎも反映。安全でない前世代ファイルの自動修復は意図して見送り (keystore と同じ fail-closed)
  • full vitest はローカルで tests/lib/license/stock.test.ts (wasmoon) がハングするため CI に委ねる

🤖 Generated with Claude Code

https://claude.ai/code/session_01HeizmagJBgL5peL5mQpxkc

cipherwebllc and others added 2 commits September 22, 2026 06:05
x402_pay (search_shops を含む) の試行を <OPENPAY_X402_HOME>/purchases.jsonl に記録し、
新ツール wallet_history (x402 profile のみ・read-only) で直近を読む。サーバは何も保持しない。
SDK は無変更 (公開済み 0.9.0 のまま)。設計 = plans/agent-purchase-history.md v0.2 案 A。

- write-ahead の 2 行 (start → end)。end が無い・throw・2xx 以外は unknown として残す
- outcome は settlement と HTTP status から機械判定 (paid_verified / paid_unverified /
  not_paid / unknown)。body の文字列や LLM の解釈で決済状態を決めない (掟 15)
- 金額と tx は settlement=verified の領収書からだけ写す (SDK が署名内容との一致を検証済み)。
  それ以外は null で、金額と着金は /agent の Agent activity (オンチェーン) を案内。合計は出さない
- query / fragment は常に落とす。path を残すのは open-pay.jp だけ・他 host は pathTag (SHA-256 先頭 8 hex)
- 署名・nonce・authorization・鍵・応答 body は書かない。読み出しは許可フィールドから再構成
- 0600 の単一 write 追記・0700 ディレクトリ検査・symlink / hard link / 非絶対パスを拒否・
  512 KiB 超は 1 世代へ rename (in-place 切り詰めなし)。履歴のためにウォレットは作らない
- 隔離 (掟 12/13): 既存の pay 本体は無変更で包むだけ。履歴の失敗は結果も例外も変えず、
  x402_pay の結果に history: recorded | failed を足す

フェンス: 既存 11 ツールの wire は byte 不変 (slice(0,11) の hash を固定) で末尾に 1 本追加。
tests/lib/agentSetup.test.ts の版フェンスは「Web の版固定 = リポの MCP と同じ minor か
ちょうど 1 つ前」に緩める (版更新 → npm publish → Web 切替の間は必ず 1 minor 遅れる。
Web の先行と 2 minor 以上の遅れは引き続き fail)。x402_pay を呼ぶ既存テストは
OPENPAY_X402_HOME を一時ディレクトリへ隔離 (実ホームに書かない)。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HeizmagJBgL5peL5mQpxkc
… チェック反映)

P1 (掟 13 の隔離の穴): startPurchase / endPurchase を無条件に await していたため、応答しない
ファイルシステム (NFS / SMB / FUSE の I/O ハング) では、2xx で解錠済み (= 支払い済み) の結果が
呼び出し元へ返らず、Agent が失敗と解釈して再支払いしうる。start の連鎖 (historyStarts) により
以後の x402_pay もすべて止まっていた。期限 (既定 2 秒・timer.unref) と race し、時間切れは
history: failed として元の I/O を放流する。id は時間切れでも保持 (遅れて書かれた start 行を
end 行と結合できる)。

あわせて:
- 追記の open を O_WRONLY|O_APPEND|O_CREAT|O_NOFOLLOW に (keystore と同等・拒否前に link 先へ
  空ファイルを作るプリミティブを塞ぐ)
- 結果がオブジェクトのときだけ history を足す (掟 12: 応答の形を変えない)
- 固定 note と README に「ログはこの OS ユーザーの任意のプロセスが編集できるローカルファイル =
  便宜上の記録で証拠ではない」を追加。README: first party は open-pay.jp の完全一致・自前 origin は
  pathTag のみ・wallet_home_not_absolute は 3 つの wallet ツールが返す
- 版フェンス: major を跨ぐ版更新 (0.x → 1.0) でも同じ窓を許す

見送り (意図): 安全でない前世代ファイル (purchases.1.jsonl の link・緩い権限) は keystore と同じく
fail-closed のまま。自動で消したり直したりしない (記録は止まるが pay は無影響・wallet_history が
エラーコードを返す)。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HeizmagJBgL5peL5mQpxkc
@vercel

vercel Bot commented Sep 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
openpay Ignored Ignored Sep 21, 2026 9:17pm UTC

Request Review

@cipherwebllc
cipherwebllc merged commit 35df0f9 into main Sep 21, 2026
7 checks passed
@cipherwebllc
cipherwebllc deleted the feat/mcp-wallet-history branch September 21, 2026 21:39
cipherwebllc added a commit that referenced this pull request Sep 21, 2026
…ry = 何を買ったかの手元ログ) (#549)

openpay-x402-mcp 0.16.0 が npm に公開された (registry の integrity は #547 の dry-run と一致)。
Web 側の版固定を 0.15 → 0.16 に上げ、wallet_history の案内を足す。

- lib/agentSetup.ts AGENT_MCP_VERSION = 0.16 (/agent の生成設定・/guide/ai-pay が追従)
- public/agent/setup.md: 版固定 5 箇所・Step 5 の末尾に wallet_history の 1 段落
  (手元のログ・OpenPay のサーバーは買い手別の履歴を持たない・欠損しうる・paid_verified 以外を
  支払い済みとして示さない・金額と着金はオンチェーンで確認)
- public/llms.txt: 全 11 → 12 ツール・wallet_history の説明
- docs/agent-templates と AI ストアの MCP 設定例 (直書き) の版


Claude-Session: https://claude.ai/code/session_01HeizmagJBgL5peL5mQpxkc

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant