@visa/cli 4.1.0-rc.32 → 4.1.0-rc.321

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +293 -57
  2. package/dist/cli.js +635 -355
  3. package/dist/managed-runtime/resolve-and-update.mjs +268 -0
  4. package/dist/managed-runtime/runtime-readiness.mjs +126 -0
  5. package/dist/managed-runtime/update-and-restart.mjs +1079 -0
  6. package/dist/mcp-apps/ucp-checkout.html +280 -0
  7. package/dist/mcp-server/index.js +523 -271
  8. package/dist/merchant-ucp-mcp/index.js +7 -0
  9. package/dist/skills/pair-visa-agent/RUNTIMES.md +122 -79
  10. package/dist/skills/pair-visa-agent/SKILL.md +390 -333
  11. package/dist/skills/pair-visa-agent/scripts/__tests__/setup.test.mjs +407 -0
  12. package/dist/skills/pair-visa-agent/scripts/setup.mjs +310 -30
  13. package/dist/skills/visa-shopify-checkout/SKILL.md +122 -0
  14. package/dist/skills/visa-shopify-checkout/references/evidence-and-states.md +37 -0
  15. package/dist/skills/visa-ucp-shopping/SKILL.md +86 -0
  16. package/dist/subway-direct.mjs +1 -0
  17. package/install.ps1 +10 -6
  18. package/install.sh +8 -3
  19. package/native/bin/darwin-arm64/visa-runtime-signer +0 -0
  20. package/native/bin/darwin-x64/visa-runtime-signer +0 -0
  21. package/native/bin/linux-arm64/visa-runtime-signer +0 -0
  22. package/native/bin/linux-x64/visa-runtime-signer +0 -0
  23. package/native/bin/win32-arm64/visa-runtime-signer.exe +0 -0
  24. package/native/bin/win32-x64/visa-keychain-win.exe +0 -0
  25. package/native/bin/win32-x64/visa-runtime-signer.exe +0 -0
  26. package/package.json +33 -30
  27. package/server.json +4 -4
  28. package/dist/checkout-engine/adapters/generic.d.ts +0 -19
  29. package/dist/checkout-engine/adapters/generic.js +0 -201
  30. package/dist/checkout-engine/adapters/index.d.ts +0 -7
  31. package/dist/checkout-engine/adapters/index.js +0 -17
  32. package/dist/checkout-engine/adapters/stripe-like.d.ts +0 -10
  33. package/dist/checkout-engine/adapters/stripe-like.js +0 -21
  34. package/dist/checkout-engine/browser-launch.d.ts +0 -46
  35. package/dist/checkout-engine/browser-launch.js +0 -81
  36. package/dist/checkout-engine/ceremony.d.ts +0 -64
  37. package/dist/checkout-engine/ceremony.js +0 -261
  38. package/dist/checkout-engine/cli-engine.d.ts +0 -208
  39. package/dist/checkout-engine/cli-engine.js +0 -584
  40. package/dist/checkout-engine/detect.d.ts +0 -61
  41. package/dist/checkout-engine/detect.js +0 -392
  42. package/dist/checkout-engine/evidence.d.ts +0 -25
  43. package/dist/checkout-engine/evidence.js +0 -104
  44. package/dist/checkout-engine/executor.d.ts +0 -174
  45. package/dist/checkout-engine/executor.js +0 -1306
  46. package/dist/checkout-engine/hosted-approval.d.ts +0 -135
  47. package/dist/checkout-engine/hosted-approval.js +0 -311
  48. package/dist/checkout-engine/index.d.ts +0 -6
  49. package/dist/checkout-engine/index.js +0 -8
  50. package/dist/checkout-engine/inline-target.d.ts +0 -13
  51. package/dist/checkout-engine/inline-target.js +0 -37
  52. package/dist/checkout-engine/instrument.d.ts +0 -55
  53. package/dist/checkout-engine/instrument.js +0 -87
  54. package/dist/checkout-engine/live-fill-approval.d.ts +0 -43
  55. package/dist/checkout-engine/live-fill-approval.js +0 -90
  56. package/dist/checkout-engine/mandate/card-mandate.d.ts +0 -117
  57. package/dist/checkout-engine/mandate/card-mandate.js +0 -221
  58. package/dist/checkout-engine/mandate/mandate-ledger.d.ts +0 -135
  59. package/dist/checkout-engine/mandate/mandate-ledger.js +0 -318
  60. package/dist/checkout-engine/mandate.d.ts +0 -25
  61. package/dist/checkout-engine/mandate.js +0 -100
  62. package/dist/checkout-engine/outcome.d.ts +0 -30
  63. package/dist/checkout-engine/outcome.js +0 -225
  64. package/dist/checkout-engine/owner-only-file.d.ts +0 -19
  65. package/dist/checkout-engine/owner-only-file.js +0 -41
  66. package/dist/checkout-engine/package.json +0 -3
  67. package/dist/checkout-engine/pay-args.d.ts +0 -14
  68. package/dist/checkout-engine/pay-args.js +0 -44
  69. package/dist/checkout-engine/pay.d.ts +0 -1
  70. package/dist/checkout-engine/pay.js +0 -13
  71. package/dist/checkout-engine/receipt.d.ts +0 -81
  72. package/dist/checkout-engine/receipt.js +0 -109
  73. package/dist/checkout-engine/repo-env.d.ts +0 -11
  74. package/dist/checkout-engine/repo-env.js +0 -23
  75. package/dist/checkout-engine/run-live-fill.d.ts +0 -1
  76. package/dist/checkout-engine/run-live-fill.js +0 -493
  77. package/dist/checkout-engine/types.d.ts +0 -39
  78. package/dist/checkout-engine/types.js +0 -2
  79. package/dist/checkout-engine/vgs-gateway/fetch-credential.d.mts +0 -74
  80. package/dist/checkout-engine/vgs-gateway/fetch-credential.mjs +0 -248
  81. package/dist/checkout-engine/vgs-gateway/server-mint-client.d.ts +0 -82
  82. package/dist/checkout-engine/vgs-gateway/server-mint-client.js +0 -178
  83. package/dist/checkout-engine/vgs-live-instrument.d.ts +0 -168
  84. package/dist/checkout-engine/vgs-live-instrument.js +0 -289
  85. package/dist/checkout-engine/vic-confirmation.d.ts +0 -34
  86. package/dist/checkout-engine/vic-confirmation.js +0 -39
package/README.md CHANGED
@@ -1,21 +1,22 @@
1
1
  # @visa/cli
2
2
 
3
- Visa CLI v4 gives an AI agent a **Visa Verified Agent** identity and a scoped,
4
- human-capped signer for a Turnkey-managed wallet. Agents discover paid
5
- x402/MPP services and pay with USDC over MCP (Model Context Protocol); the
6
- human approves the limits and every payment is checked against on-device policy
7
- before anything is signed. Larger browser purchases use a separately approved
8
- VIC credential and card mandate.
9
-
10
- The v4 flow has three parts, always in this order:
11
-
12
- 1. **Identity** — the human enrolls in the browser (email or Google sign-in, card on file, bank verification) and mints a `.visa` name bound to the agent.
13
- 2. **Delegation** — a pairing ceremony gives the runtime a scoped, revocable
14
- Turnkey signer with human-approved per-transaction and daily caps. The
15
- runtime never receives the human wallet's root key.
16
- 3. **Payment** — `find → inspect → pay` handles x402/MPP purchases with gasless
17
- USDC and explicit maxima; `checkout` / `mandate` handles larger VIC browser
18
- purchases.
3
+ Visa CLI v4 pairs an AI runtime to a human-approved **Visa agent identity**.
4
+ The pairing ceremony creates one stable agent ID and activates one
5
+ runtime-custodied Ed25519 identity key. It does not create payment authority,
6
+ a mailbox, or a `.visa` name. New paired agents request publication of their
7
+ public key to the TAP directory by default; owners can durably remove it with
8
+ `visa agent tap-opt-out <agent-id>`.
9
+
10
+ The protected product flow has three explicit parts:
11
+
12
+ 1. **Enrollment** — call `agent_enroll` or have the owner run `visa agent enroll`
13
+ and approves the exact device and its limits in the browser. The private key
14
+ stays on the runtime device. Retired setup, pairing, handoff, and per-rail
15
+ grant names return `legacy_door_removed`; they never resume or proxy work.
16
+ 2. **Capabilities** — payment methods, spend grants, email and directory
17
+ bindings are configured separately, each with its own human-visible terms.
18
+ 3. **Use** — when a separately provisioned capability exists, the wallet and
19
+ VIC commands enforce that capability's own policy and approval boundary.
19
20
 
20
21
  ## Install
21
22
 
@@ -31,7 +32,17 @@ Windows PowerShell:
31
32
  iwr -useb https://app.visacli.sh/install.ps1 | iex
32
33
  ```
33
34
 
34
- Node.js 18+ is required. macOS, Windows, and Linux are supported for the v4 wallet flow.
35
+ Node.js 20+ is required. macOS, Windows, and Linux are supported for the v4 wallet flow.
36
+
37
+ ### Managed runtime convergence
38
+
39
+ The RC package also installs `visa-runtime-converge` for supervisor-owned
40
+ OpenClaw/Hermes/Telegram deployments. A scheduled invocation resolves the
41
+ preview server's recommended exact RC, stages and integrity-checks it, restarts
42
+ through the configured supervisor, verifies the loaded version/environment, and
43
+ rolls back a failed activation. It never updates an interactive owner-managed
44
+ installation. Configuration and readiness contracts are documented in
45
+ [`packages/visa-cli-openclaw/RUNTIMES.md`](https://github.com/Visa-Crypto-Labs/Visa-mono/blob/staging/packages/visa-cli-openclaw/RUNTIMES.md).
35
46
 
36
47
  ## MCP setup
37
48
 
@@ -65,44 +76,150 @@ args = ["<npm root -g>/@visa/cli/dist/mcp-server/index.js"]
65
76
 
66
77
  There is no CLI subcommand for starting the MCP server directly — the MCP server is the bundled `dist/mcp-server/index.js` entrypoint, which `visa-cli connect <client>` registers for you.
67
78
 
68
- ## Enroll a Verified Agent
79
+ ### UCP commerce bundle
69
80
 
70
- Enrollment starts from the agent, not the terminal: the agent calls the **`enroll_agent`** MCP tool, which opens the enrollment page in the browser and prints a 6-character confirmation code in the terminal. The human signs in with **email or Google**, chooses the agent's `.visa` name, adds a card, completes the bank's verification step, and types the confirmation code. When the browser reports the credential was sent to the CLI, the agent calls `enroll_agent` with `{"action":"claim"}` to park the credential on the device.
81
+ Install the Visa pairing skill, discovery-first UCP shopping skill, bounded
82
+ Shopify checkout skill, and both Visa and Shopify UCP MCP entries in one step:
71
83
 
72
- Only enter a confirmation code you watched your own terminal print. Enrollment
73
- must begin with `enroll_agent` and present Turnkey email or Google sign-in.
84
+ ```bash
85
+ visa agent skill --commerce --runtime codex
86
+ # runtimes with writable MCP config: codex, openclaw, hermes
74
87
 
75
- ## Connect an agent runtime (pairing)
88
+ # Inspect the installed local bundle without changing skills or MCP config:
89
+ visa agent skill --commerce --runtime codex --check
90
+ ```
76
91
 
77
- Enrollment mints identity; **pairing is what lets a runtime sign payments.**
92
+ The shopping skill turns broad requests into a short seller/variant list and
93
+ requires an exact selection plus an all-in ceiling before checkout. The pinned
94
+ Shopify UCP server requires Node.js 22 or newer. A successful run
95
+ reports both MCP entries as mounted or already mounted; restart or reload the
96
+ agent before using the new tools. The installer never performs discovery or a
97
+ checkout itself. The install-only command exits successfully after writing the
98
+ bundle, but reports `commerceReady: false` / `ucp_check_required` until the
99
+ explicit `--check` gate passes. `commerceReady` is a compatibility alias for
100
+ local bundle readiness only; it never proves that a merchant purchase can be
101
+ completed. The JSON result keeps `purchase.ready: false` until a separate live
102
+ checkout preflight is performed.
103
+
104
+ Checked readiness is read-only: missing or modified skills and missing,
105
+ conflicting, or malformed MCP entries are reported without installing or
106
+ rewriting anything. It parses the active local profile and its pinned Shopify
107
+ profile contract directly from disk, without starting `npx`, and reports the
108
+ exact profile initialization command if local state is missing or invalid. It
109
+ also refuses to claim local natural-language shopping readiness when a
110
+ top-level `ucp` or `shop` skill with a `SKILL.md` is present in the same runtime
111
+ directory. The installer reports those paths but never deletes or disables
112
+ user-owned skills.
113
+
114
+ If the selected runtime already has a non-equivalent `shopify-ucp` entry, the
115
+ command fails without changing that entry or its environment, authentication,
116
+ timeout, or filtering fields. Rename or remove the existing entry explicitly
117
+ before rerunning; the installer does not silently replace or downgrade it.
118
+
119
+ ### MCP 2026-07-28 compatibility
120
+
121
+ This release speaks the modern, stateless MCP `2026-07-28` protocol over stdio and deliberately rejects the legacy `initialize` handshake. Your client must support per-request protocol envelopes and `server/discover`; update the client before upgrading Visa CLI if it still sends MCP `2025-*` traffic. `visa-cli connect` can write configuration for every listed client, but configuration support does not imply that an older installed client understands the new wire revision.
122
+
123
+ The server now exposes:
124
+
125
+ - JSON Schema 2020-12 tool inputs and outputs, `structuredContent`, namespaced result metadata, cache hints, and receipt `resource_link` blocks.
126
+ - Resources for agent status, capabilities, recent activity, and canonical `visa://receipt/{transactionId}` receipts.
127
+ - Prompts for pairing/funding, spend inspection, safe purchasing, and receipt reconciliation, with completion support.
128
+ - The `io.modelcontextprotocol/tasks` extension for durable, pollable `pay_merchant` approval work. Task lifecycle is owner-scoped in the auth service; an MCP-process restart fails an in-flight checkout closed instead of replaying it.
129
+ - Multi-round-trip `input_required` URL elicitation with HMAC-protected, client-bound request state when the client supports URL elicitation but not Tasks.
130
+ - The `io.modelcontextprotocol/ui` Visa Control Center MCP App at `ui://visa/control-center`.
131
+
132
+ Visa sidebands no longer pollute business JSON. Clients receive keys such as `io.visa/visa-receipt` and `io.visa/update-available` in result `_meta`.
133
+
134
+ ## Setup doors
135
+
136
+ There is one protected enrollment workflow. The CLI is its only entrance in
137
+ this build; a future canonical MCP entrance may call the same workflow. Legacy
138
+ names are hidden refusals, not compatibility paths.
139
+
140
+ | Transition | Blessed door | Status |
141
+ |---|---|---|
142
+ | New agent, from any runtime | `visa agent enroll` / `agent_enroll` | One protected enrollment implementation; owner approves in the browser |
143
+ | Existing owner account on this device | `agent_login` / `visa agent login` | Canonical sign-in; adds no agent |
144
+ | Resume a paused agent | `visa agent resume <agent-id>` | Live lifecycle control, not enrollment |
145
+
146
+ ## Pair an agent identity
147
+
148
+ For a new agent, the owner starts the protected command with the three trusted
149
+ origins supplied by the operator, opens the printed URL, enters its short code,
150
+ and approves the device and limits. Repeat the same command with `--wait` to
151
+ finish an interrupted local wait. The old setup and pairing names do not resume
152
+ an earlier ceremony; they return one deterministic refusal and the current
153
+ command.
78
154
 
79
155
  ```bash
80
- visa agent create # in the human's terminal — prints the pairing id
81
- visa agent claim <pairing-id> --runtime <name> --context "<one-line purpose>"
82
- visa agent verify <pairing-id> <code> # verifies the channel, opens the authorization page
83
- visa agent list # shows the activated runtime
156
+ visa agent enroll --wait
157
+ visa agent list
158
+ visa agent show <agent-id>
84
159
  ```
85
160
 
86
- The browser authorization is the human gate: it shows the runtime and context and sets the **per-transaction and daily spend caps**. If the runtime lost its network response, `visa agent resume <pairing-id>` reprints the code and resumes delivery; `visa agent cancel [pairing-id]` abandons an unapproved request. Pairing credentials are stored on the agent machine with mode `0600`; the pairing link contains no credential.
161
+ On macOS and Linux, the private identity key is stored under
162
+ `~/.visa-cli/agents` in an owner-only directory with file mode `0600`. It is
163
+ currently an exportable local file: copying it transfers identity proof, and
164
+ losing it blocks new proofs because same-agent key recovery is not yet
165
+ available. Protocol-v2 identity pairing fails closed on Windows until the CLI
166
+ can apply and verify an owner-only Windows ACL. The pairing link contains no
167
+ credential or private key.
87
168
 
88
- ## Caps, then funding — strict order
169
+ ## Recover an existing account session
170
+
171
+ `visa agent login` opens the Turnkey-first web sign-in for an existing v4
172
+ account, then `visa agent login-claim` stores the returned account session in
173
+ the OS keychain. `--wait` keeps the first command polling for the full
174
+ 15-minute browser window.
89
175
 
90
176
  ```bash
91
- visa wallet limits --per-transaction 0.25 --daily 2.00 # BEFORE any funds arrive
92
- visa wallet show # address, network, policy
93
- visa wallet fund # funding instructions
177
+ visa agent login # sign in and display the terminal confirmation code
178
+ visa agent login-claim # resume pickup after returning from the browser
179
+ ```
180
+
181
+ This is account-session recovery, not agent pairing. It does not create or
182
+ replace an identity key, delegate a wallet, select a card, set a budget, or
183
+ grant spend authority. The pending PKCE verifier is kept under
184
+ `~/.visa-cli/session-recovery/` in owner-only local state and is pinned to the
185
+ exact web origin that started the flow.
186
+ Session recovery currently fails closed on Windows until the CLI can apply and
187
+ verify an owner-only ACL for this pending verifier.
188
+
189
+ ## Wallet capability: grant, caps, then funding
190
+
191
+ Pairing never creates or repairs payment authority — the owner delegates it in
192
+ a separate grant ceremony, and re-pairing is not a substitute:
193
+
194
+ ```bash
195
+ visa agent login # owner account session, once
196
+ visa agent grant-wallet <agent-id> --ceiling 25 --per-transaction 1 --wait
197
+ ```
198
+
199
+ The owner approves once in the browser; the runtime polls to activation and
200
+ receives a delegated, capped, revocable signer (it can never mint one itself).
201
+ `visa agent pause <agent-id>` temporarily blocks new Visa CLI card and wallet payments at the canonical authority service (mandates remain intact; resume with `visa agent resume <agent-id>`). `visa agent revoke <agent-id>` withdraws the current server grant without touching identity; provider-credential removal is a separate lifecycle.
202
+
203
+ With a wallet delegated, set caps before funding:
204
+
205
+ ```bash
206
+ visa wallet limits --agent <agent-id> --per-transaction 0.25 --daily 2.00
207
+ visa wallet show --agent <agent-id> # address, network, policy
208
+ visa wallet fund --agent <agent-id> # funding instructions
94
209
  ```
95
210
 
96
211
  Fund the wallet with USDC only after limits are set. Payments are gasless — no ETH is ever needed. Mainnet (Base) is the production default; set `VISA_V4_NETWORK=base-sepolia` for testnet, where `visa wallet fund` points at the faucet.
97
212
 
213
+ Updating wallet limits preserves the active session budget window and its spent exposure. Reapplying the same limits is a no-op; `wallet limits` does not provide an implicit session-spend reset.
214
+
98
215
  ## Discover and pay
99
216
 
100
217
  ```bash
101
218
  visa find "current weather by city" --max 0.10 # discovery; spends nothing
102
219
  visa inspect <listing-id> # fetches the live 402 challenge; spends nothing
103
- visa pay <listing-id> --max 0.05 # policy check → sign → settle
104
- visa activity # recent payments
105
- visa receipt <receipt-id> # journaled proof with on-chain tx
220
+ visa pay <listing-id> --agent <agent-id> --max 0.05 # policy check → sign → settle
221
+ visa activity --agent <agent-id> # recent payments
222
+ visa receipt <receipt-id> --agent <agent-id> # journaled proof with on-chain tx
106
223
 
107
224
  # Advanced direct-URL mode uses the same probe, policy, and receipt path.
108
225
  visa inspect --url https://provider.example/paid
@@ -116,12 +233,33 @@ owned by `apps/mpp`, and VIC uses the checkout/mandate surface. Unsupported
116
233
  rails are refused before signing. The wallet exposes no agent key-export
117
234
  command.
118
235
 
236
+ Each wallet-enabled agent has an isolated Turnkey credential, policy, journal,
237
+ receipts, and paid-response directory. `--agent` / the MCP `agent` field may be
238
+ omitted while exactly one wallet authority exists; with multiple authorities it
239
+ is required so the CLI never guesses which agent can spend.
240
+
119
241
  ## MCP tools (v4 surface)
120
242
 
243
+ Rows marked **Removed** are kept so old transcripts still resolve: the tool is
244
+ no longer in `tools/list`, and a direct call by name answers
245
+ `legacy_door_removed` naming the one door for a new agent,
246
+ `visa agent enroll-protected`.
247
+
248
+ A leftover direct-mode `turnkey.json` is not usable wallet authority.
249
+ `agent_capabilities` reports wallet status `legacy_direct_mode` and unavailable;
250
+ `get_status` directs even an already paired agent to `agent_enroll`. Have the
251
+ owner complete `visa agent enroll` before attempting payment.
252
+
253
+ Auth HTTP 410 responses with `code: route_retired` or `error: route_retired`
254
+ are classified as `legacy_door_removed`. Follow `agent_enroll` /
255
+ `visa agent enroll`; retrying the retired route does not restore it.
256
+
257
+
121
258
  | Tool | Description |
122
259
  |------|-------------|
123
- | `enroll_agent` | Two-step Verified Agent enrollment: default opens the browser flow with a hand-off challenge; `{"action":"claim"}` stores the enrollment credential on this device |
124
- | `wallet_status` | Wallet address, network, policy, and pairing state |
260
+ | `agent_capabilities` | Derived live capability map (identity, wallet, card, mail, tap, subway) with upgrade paths |
261
+ | `agent_login` | Start/claim the owner's device account session (required before a grant) |
262
+ | `wallet_status` | Delegated wallet address, network, and policy state |
125
263
  | `wallet_policy_set` | Set per-transaction / daily caps (with human approval) |
126
264
  | `wallet_discover` | Sweep x402 directories for services, with live re-probing |
127
265
  | `wallet_probe` | Fetch a service's live 402 challenge without paying |
@@ -129,6 +267,14 @@ command.
129
267
  | `wallet_directory_pay` | Directory find + pay in one call, same policy path |
130
268
  | `wallet_history` | Journaled payment receipts |
131
269
  | `wallet_fund` | Funding instructions for the wallet address |
270
+ | `checkout_merchants` | Read-only: merchants where your card has completed real checkouts, from this device's receipts |
271
+ | `setup_agent` | **Removed.** Use `visa agent enroll-protected` |
272
+ | `setup_start` | **Removed.** Use `visa agent enroll-protected` |
273
+ | `setup_status` | **Removed.** Use `visa agent enroll-protected` |
274
+ | `setup_resume` | **Removed.** Use `visa agent enroll-protected` |
275
+ | `setup_cancel` | **Removed.** Use `visa agent enroll-protected` |
276
+ | `agent_connect` | **Removed.** Authority is approved during `visa agent enroll-protected` |
277
+ | `agent_connect_poll` | **Removed.** Authority is approved during `visa agent enroll-protected` |
132
278
  | `get_status` | Account and wallet state summary |
133
279
  | `feedback` | Submit feedback on a tool result |
134
280
  | `reset` | Clear local auth state and credentials |
@@ -163,23 +309,19 @@ visa pay <listing-id> --max <usd>
163
309
  visa activity
164
310
  visa receipt <receipt-id>
165
311
 
166
- # Human-approved agent runtime pairing
167
- visa agent create
168
- visa agent claim <pairing-id> --runtime <name> --context "<purpose>"
169
- visa agent verify <pairing-id> <code>
170
- visa agent resume <pairing-id>
171
- visa agent cancel [pairing-id]
312
+ # Primary same-machine setup
313
+ visa agent enroll --wait
314
+
315
+ # Existing-account session
316
+ visa agent login
172
317
  visa agent list
173
318
 
174
- # Human-approved VIC browser purchase
175
- visa checkout review <checkout-url> <amount>
176
- visa checkout pay <review-id>
177
- visa mandate start <checkout-url> <ceiling>
178
- visa mandate budget <ceiling>
179
- visa mandate list
319
+ # Retired doors (they refuse — do not retry)
320
+ # visa setup start / visa checkout pay / visa mandate start
180
321
 
181
322
  # MCP client connections
182
- visa connections
323
+ visa connections # detected / configured / loaded
324
+ visa connections --probe # also start the Visa MCP server once and confirm it serves tools
183
325
  visa connect codex
184
326
  visa disconnect codex
185
327
 
@@ -200,14 +342,19 @@ visa-cli feedback # submit feedback
200
342
 
201
343
  | Path | Contents |
202
344
  |------|----------|
203
- | `~/.visa-mcp/agent-credential.json` | Verified Agent enrollment credential (mode 0600) |
204
- | `~/.visa-cli/` | Pairing / delegated signer credentials (mode 0600) |
205
- | `~/.visa-v4/policy.json` | Wallet spend policy — never edit by hand; use `visa wallet limits` |
345
+ | `~/.visa-cli/pairings/` | Pending ceremony verifier or runtime identity key (owner-only mode 0600 on macOS/Linux; v2 pairing currently disabled on Windows) |
346
+ | `~/.visa-cli/agents/` | Activated agent identity, runtime private key, and signed activation credentials (owner-only mode 0600 on macOS/Linux; v2 pairing currently disabled on Windows) |
347
+ | `~/.visa-cli/session-recovery/` | Pending login-only PKCE verifier and pinned web origin (owner-only mode 0600 on macOS/Linux) |
348
+ | `~/.visa-cli/removed-agents/` | Records of agents deleted on the server, kept 30 days then dropped. Written automatically; nothing reads it |
349
+ | `~/.visa-mcp/agent-credential.json` | Legacy checkout-credential compatibility record (mode 0600) |
350
+ | `~/.visa-v4/agents/<agentId>/` | Per-agent Turnkey credential, spend policy, reservation journal, receipts, and paid responses — never edit by hand |
206
351
 
207
352
  ## Troubleshooting
208
353
 
209
- **Wallet commands report pairing is required**
210
- Payments on a production network require the paired delegated credential — complete enrollment and pairing first. There is no local fallback wallet on mainnet, by design.
354
+ **Wallet commands report that payment setup is required**
355
+ Identity pairing deliberately grants no payment authority. Complete the
356
+ separate wallet/instrument and spend-policy setup when available; pairing again
357
+ will not upgrade an identity into a signer.
211
358
 
212
359
  **`policy refused` from `pay`**
213
360
  A cap or allowlist said no; nothing was signed. Raise caps only via `visa wallet limits` with the human's approval.
@@ -215,12 +362,101 @@ A cap or allowlist said no; nothing was signed. Raise caps only via `visa wallet
215
362
  **`expected 402 from <url>`**
216
363
  That URL isn't payment-gated — probe the service's actual paid route (`wallet_probe` / `visa find`).
217
364
 
218
- **Pairing ended `expired` or `cancelled`**
219
- The ceremony timed out — re-run `visa agent create` and claim the new pairing id.
365
+ **Setup ended `expired` or `cancelled`**
366
+ The ceremony timed out — restart with `visa agent enroll --wait`. Do not retry
367
+ `visa setup start`; that door is removed.
220
368
 
221
369
  **Tools don't appear in the AI client**
222
370
  Restart the client or reconnect the MCP server (`/mcp` → `visa-cli` → reconnect in Claude Code). Re-run `visa-cli connect <client>` to rewrite the config.
223
371
 
372
+ **Branching on failures from `--format json`**
373
+ Every failure envelope carries `code`, `kind`, `fix`, and `nextAction`. Branch on
374
+ `code` (stable, append-only) and `kind` (`caller` = fix it yourself and retry;
375
+ `platform` = stop and escalate to a human), never on the English `error` text.
376
+ Deterministic preconditions always resolve to a specific code:
377
+
378
+ | Condition | `code` | `kind` |
379
+ |-----------|--------|--------|
380
+ | Not logged in (`find`, `activity`, `receipt`) | `session_required` | `caller` |
381
+ | No wallet grant on this runtime (`wallet show\|fund\|limits`, `pay`, `--local` reads) | `wallet_credential_required` | `platform` |
382
+ | Wallet grant approved but not fully delivered (`pay`) | `wallet_delivery_required` | `platform` |
383
+ | Local identity record missing for the selected agent (`pay`) | `identity_required` | `caller` |
384
+ | Identity root migrated; direct signing retired (`pay`) | `universal_required_managed_only` | `platform` |
385
+ | Managed wallet limits are owner-set (`wallet limits` with caps) | `managed_limits_owner_controlled` | `platform` |
386
+ | Listing is not x402 (`pay <listing-id>`) | `invalid_argument` | `caller` |
387
+ | Activity id not found or not attributable (`receipt`) | `activity_entry_not_found` | `caller` |
388
+
389
+ `unspecified_error` (`platform`) is reserved for failures the CLI cannot
390
+ classify and is intentionally kept on two guards: a wallet binding that does not
391
+ match the signed-in owner profile (an integrity refusal, not a caller state),
392
+ and a `wallet limits` change that would broaden policy without the operator's
393
+ `VISA_V4_WALLET_ALLOW_POLICY_RAISE=1`. Both need a human; escalate rather than retry.
394
+
224
395
  ## Monorepo context
225
396
 
226
397
  Request routing (MCP vs MPP vs web): [docs/agents/ARCHITECTURE.md](../../docs/agents/ARCHITECTURE.md). Branches and deploy: [docs/agents/PIPELINE.md](../../docs/agents/PIPELINE.md). Contributor workflow: [AGENTS.md](../../AGENTS.md), doc index: [docs/agents/README.md](../../docs/agents/README.md).
398
+
399
+ ### Native device TAP lifecycle
400
+
401
+ `visa agent keychain connect-device --agent <name-or-id>` selects this device for
402
+ identity-only TAP signing after the existing browser owner ceremony verifies its
403
+ certificate, delegation, Gate authorization and native key binding. The selected
404
+ native profile serves actual TAP consumers; unavailable custody or invalid selected
405
+ metadata fails closed. Wallet/card keys and payment authority remain separate.
406
+
407
+ `--agent` accepts either a locally paired agent or the stable UUID of a protected
408
+ agent created by `visa agent enroll`; the latter has no Auth-paired record
409
+ and resolves its owner root from the independently claimed selection. The device
410
+ ceremonies (`connect-device`, `renew`, `resume`, `revoke --purpose tap`) travel the
411
+ public identity-device relay with native possession proofs, so a missing or expired
412
+ `visa agent login` never blocks them; the owner approval and owner revocation pages
413
+ remain required. Hosted purposes (`card:vic`, `wallet:x402`, hosted `tap`, `subway`)
414
+ still need a locally paired agent and its Auth session.
415
+
416
+ `visa agent keychain renew --agent <name-or-id> --purpose tap` creates an independently
417
+ addressed successor for the same runtime and opens the owner review page. Both keys
418
+ survive interruption. `visa agent keychain resume --agent <name-or-id>` resumes the
419
+ exact pending operation, including a locked-keychain cleanup retry. `--no-open`
420
+ prints the owner URL. Expired locators require another owner ceremony using the
421
+ preserved successor key. `keychain status` reports the selected profile and local
422
+ renewal phase; it is a local projection, not a live authority check.
423
+
424
+ Only public certificates/proposals and opaque native handles enter the durable
425
+ renewal journal. Selection changes after verified owner activation. The previous
426
+ handle is deleted only after possession-authenticated protected readback proves
427
+ that exact prior generation retired; uncertain readback preserves it. Native
428
+ custody uses the configured OS store or explicit headless KEK descriptor.
429
+
430
+ `visa agent keychain revoke --agent <name-or-id> --purpose tap` opens an independent
431
+ owner review for the selected native runtime. The protected owner action stops current
432
+ and pending TAP authority, including an interrupted renewal. Local locks or unreadable
433
+ recovery journals do not prevent opening the owner review. The CLI preserves every known
434
+ handle until exact terminal readback, then deletes keys idempotently; `keychain resume`
435
+ retries locked cleanup. A public revoked selection tombstone prevents legacy TAP fallback.
436
+ After cleanup completes, `connect-device` explicitly enrolls a new runtime.
437
+
438
+ ### Native Subway owner certificates
439
+
440
+ Subway certificate issuance and renewal retired with the runtime certificate plane
441
+ (UNIFY D2); `agent keychain renew` and `revoke` accept only `--purpose tap`. A Subway
442
+ certificate an earlier build already selected keeps signing through the native
443
+ financial-presence key while its owner signature stays valid: WebSocket messages and
444
+ direct libp2p Noise authentication use structured native signing operations, and an
445
+ invalid, expired, revoked, or unavailable selection fails closed. Existing unpaired
446
+ mesh usage retains its current behavior.
447
+
448
+ ### Protected managed-wallet rollout
449
+
450
+ Protected authority onboarding is opt-in with `visa config set wallet.protectedAuthority true` until its deployment is ready. The default retains the existing fresh-enrollment and locally verified legacy managed-wallet path. This setting never downgrades saved protected devices: native pending/active/history records and protected wallet bindings always require protected recovery, including when the authority is unavailable. Existing direct configurations retain their scoped local-credential checks.
451
+
452
+ A managed reconnect without verifiable local enrollment history requires recovery; restore the saved device records or complete independent owner classification through the protected authority deployment. Auth's execution-mode response alone cannot classify that missing history. No automatic retry through legacy setup occurs after an authority error.
453
+
454
+ ### Fresh protected native agent
455
+
456
+ Start from an empty CLI home with:
457
+
458
+ ```sh
459
+ visa agent enroll --wait
460
+ ```
461
+
462
+ Enter the terminal code in the existing browser owner ceremony, then approve the native device and its spending limits. Repeat the same command to resume after interruption; use `--no-open` to print links. The CLI uses its build-channel Auth and web origins; there is no caller-selected Authority origin. Auth forwards the exact protected request bytes to the private Authority, while the owner stamps and device proofs remain end-to-end. No Auth login is needed. An unclaimed expired request can be replaced with `--restart`. This path creates a new protected namespace and preserves any existing Auth login profile.