run402 4.93.2 → 4.95.0

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 (316) hide show
  1. package/README.md +61 -59
  2. package/cli.mjs +40 -47
  3. package/core-dist/config.js +52 -18
  4. package/core-dist/control-plane-session.js +31 -6
  5. package/core-dist/keystore.js +7 -7
  6. package/core-dist/profiles.js +9 -7
  7. package/core-dist/{allowance-auth.js → wallet-auth.js} +15 -15
  8. package/{sdk/core-dist/allowance.js → core-dist/wallet.js} +20 -20
  9. package/{sdk/core-dist/write-auth-session.js → core-dist/write-approvals.js} +19 -19
  10. package/gitvault-surface.json +2 -2
  11. package/lib/admin.mjs +6 -6
  12. package/lib/agent.mjs +20 -18
  13. package/lib/ai.mjs +5 -5
  14. package/lib/approve.mjs +81 -0
  15. package/lib/apps.mjs +12 -12
  16. package/lib/archives.mjs +371 -8
  17. package/lib/argparse.mjs +5 -5
  18. package/lib/assets.mjs +14 -14
  19. package/lib/auth.mjs +34 -34
  20. package/lib/billing.mjs +6 -6
  21. package/lib/branches.mjs +7 -7
  22. package/lib/buzz-doctor.mjs +2 -2
  23. package/lib/buzz-notifications.mjs +5 -5
  24. package/lib/buzz.mjs +3 -3
  25. package/lib/buzz.test.mjs +1 -1
  26. package/lib/cache.mjs +1 -1
  27. package/lib/cdn.mjs +2 -2
  28. package/lib/ci.mjs +12 -12
  29. package/lib/claims.mjs +2 -2
  30. package/lib/cold-start.mjs +21 -21
  31. package/lib/command-manifest.mjs +55 -70
  32. package/lib/config.mjs +28 -28
  33. package/lib/contacts.mjs +16 -16
  34. package/lib/contracts.mjs +12 -12
  35. package/lib/credentials.mjs +33 -33
  36. package/lib/daemon-path.mjs +1 -1
  37. package/lib/delegates.mjs +14 -14
  38. package/lib/deliveries.mjs +6 -6
  39. package/lib/deploy-rehearse-discovery.test.mjs +7 -7
  40. package/lib/deploy-v2.mjs +241 -193
  41. package/lib/deploy.mjs +21 -53
  42. package/lib/dev.mjs +3 -3
  43. package/lib/doctor-source-scan.mjs +1 -1
  44. package/lib/doctor.mjs +63 -63
  45. package/lib/domains.mjs +27 -27
  46. package/lib/email.mjs +38 -38
  47. package/lib/errors.mjs +40 -24
  48. package/lib/escalations.mjs +5 -5
  49. package/lib/events.mjs +32 -25
  50. package/lib/feedback.mjs +12 -12
  51. package/lib/functions.mjs +34 -34
  52. package/lib/gitvault-daemon.mjs +1 -1
  53. package/lib/gitvault-scaffold.mjs +2 -2
  54. package/lib/gitvault.mjs +2 -2
  55. package/lib/grants.mjs +7 -7
  56. package/lib/image.mjs +10 -10
  57. package/lib/init.mjs +69 -69
  58. package/lib/jobs.mjs +15 -15
  59. package/lib/lightning-wallet.mjs +28 -28
  60. package/lib/live.mjs +1 -1
  61. package/lib/login.mjs +207 -0
  62. package/lib/logout.mjs +53 -0
  63. package/lib/logs.mjs +8 -8
  64. package/lib/messages.mjs +5 -5
  65. package/lib/next-actions.mjs +16 -16
  66. package/lib/org-context.mjs +13 -13
  67. package/lib/{org.mjs → orgs.mjs} +215 -167
  68. package/lib/pay.mjs +1 -1
  69. package/lib/projects.mjs +70 -84
  70. package/lib/redeem.mjs +7 -8
  71. package/lib/remote-helper-session.mjs +12 -12
  72. package/lib/repos.mjs +83 -83
  73. package/lib/rooms.mjs +105 -69
  74. package/lib/sdk-errors.mjs +10 -5
  75. package/lib/sdk.mjs +3 -3
  76. package/lib/secrets.mjs +13 -13
  77. package/lib/service.mjs +5 -5
  78. package/lib/session-proofs.mjs +21 -0
  79. package/lib/sign-in.mjs +296 -0
  80. package/lib/sites.mjs +22 -22
  81. package/lib/snapshots.mjs +10 -10
  82. package/lib/stats.mjs +2 -2
  83. package/lib/status.mjs +25 -25
  84. package/lib/subdomains.mjs +30 -30
  85. package/lib/subscriptions.mjs +10 -10
  86. package/lib/tier.mjs +29 -22
  87. package/lib/transfer.mjs +59 -86
  88. package/lib/up.mjs +14 -14
  89. package/lib/wallet-context.mjs +4 -4
  90. package/lib/wallet-context.test.mjs +3 -3
  91. package/lib/wallets.mjs +197 -32
  92. package/lib/webhook-secret.mjs +6 -6
  93. package/lib/webhooks.mjs +8 -8
  94. package/lib/whoami.mjs +102 -0
  95. package/package.json +1 -1
  96. package/sdk/core-dist/config.js +52 -18
  97. package/sdk/core-dist/control-plane-session.js +31 -6
  98. package/sdk/core-dist/keystore.js +7 -7
  99. package/sdk/core-dist/profiles.js +9 -7
  100. package/sdk/core-dist/{allowance-auth.js → wallet-auth.js} +15 -15
  101. package/{core-dist/allowance.js → sdk/core-dist/wallet.js} +20 -20
  102. package/{core-dist/write-auth-session.js → sdk/core-dist/write-approvals.js} +19 -19
  103. package/sdk/dist/actions.d.ts +4 -4
  104. package/sdk/dist/actions.d.ts.map +1 -1
  105. package/sdk/dist/app-up.d.ts +2 -2
  106. package/sdk/dist/app-up.d.ts.map +1 -1
  107. package/sdk/dist/config.d.ts +1 -2
  108. package/sdk/dist/config.d.ts.map +1 -1
  109. package/sdk/dist/config.js.map +1 -1
  110. package/sdk/dist/control-plane-credentials.d.ts +8 -8
  111. package/sdk/dist/control-plane-credentials.js +7 -7
  112. package/sdk/dist/credentials.d.ts +20 -20
  113. package/sdk/dist/credentials.d.ts.map +1 -1
  114. package/sdk/dist/credentials.js +1 -1
  115. package/sdk/dist/errors.d.ts +26 -28
  116. package/sdk/dist/errors.d.ts.map +1 -1
  117. package/sdk/dist/errors.js +35 -38
  118. package/sdk/dist/errors.js.map +1 -1
  119. package/sdk/dist/index.d.ts +29 -16
  120. package/sdk/dist/index.d.ts.map +1 -1
  121. package/sdk/dist/index.js +30 -17
  122. package/sdk/dist/index.js.map +1 -1
  123. package/sdk/dist/kernel.d.ts +1 -1
  124. package/sdk/dist/kernel.d.ts.map +1 -1
  125. package/sdk/dist/kernel.js +10 -9
  126. package/sdk/dist/kernel.js.map +1 -1
  127. package/sdk/dist/namespaces/admin.d.ts +52 -121
  128. package/sdk/dist/namespaces/admin.d.ts.map +1 -1
  129. package/sdk/dist/namespaces/admin.js +41 -45
  130. package/sdk/dist/namespaces/admin.js.map +1 -1
  131. package/sdk/dist/namespaces/agent.d.ts +2 -2
  132. package/sdk/dist/namespaces/agent.d.ts.map +1 -1
  133. package/sdk/dist/namespaces/agent.js +2 -2
  134. package/sdk/dist/namespaces/agent.js.map +1 -1
  135. package/sdk/dist/namespaces/ai.d.ts +2 -2
  136. package/sdk/dist/namespaces/ai.js +3 -3
  137. package/sdk/dist/namespaces/ai.js.map +1 -1
  138. package/sdk/dist/namespaces/assets.js +1 -1
  139. package/sdk/dist/namespaces/assets.js.map +1 -1
  140. package/sdk/dist/namespaces/billing.d.ts +6 -3
  141. package/sdk/dist/namespaces/billing.d.ts.map +1 -1
  142. package/sdk/dist/namespaces/billing.js.map +1 -1
  143. package/sdk/dist/namespaces/buzz-notifications.types.d.ts +1 -1
  144. package/sdk/dist/namespaces/buzz.d.ts +2 -2
  145. package/sdk/dist/namespaces/buzz.d.ts.map +1 -1
  146. package/sdk/dist/namespaces/buzz.js +2 -2
  147. package/sdk/dist/namespaces/buzz.js.map +1 -1
  148. package/sdk/dist/namespaces/buzz.types.d.ts +2 -2
  149. package/sdk/dist/namespaces/buzz.types.d.ts.map +1 -1
  150. package/sdk/dist/namespaces/ci.js +3 -3
  151. package/sdk/dist/namespaces/ci.js.map +1 -1
  152. package/sdk/dist/namespaces/credentials.types.d.ts +1 -1
  153. package/sdk/dist/namespaces/deploy.d.ts +1 -1
  154. package/sdk/dist/namespaces/deploy.d.ts.map +1 -1
  155. package/sdk/dist/namespaces/deploy.js +31 -32
  156. package/sdk/dist/namespaces/deploy.js.map +1 -1
  157. package/sdk/dist/namespaces/deploy.types.d.ts +6 -6
  158. package/sdk/dist/namespaces/deploy.types.d.ts.map +1 -1
  159. package/sdk/dist/namespaces/domains.d.ts +10 -2
  160. package/sdk/dist/namespaces/domains.d.ts.map +1 -1
  161. package/sdk/dist/namespaces/domains.js +10 -5
  162. package/sdk/dist/namespaces/domains.js.map +1 -1
  163. package/sdk/dist/namespaces/errors.js +1 -1
  164. package/sdk/dist/namespaces/escalations.d.ts +1 -1
  165. package/sdk/dist/namespaces/escalations.js +1 -1
  166. package/sdk/dist/namespaces/escalations.types.d.ts +2 -2
  167. package/sdk/dist/namespaces/escalations.types.d.ts.map +1 -1
  168. package/sdk/dist/namespaces/events.types.d.ts +1 -1
  169. package/sdk/dist/namespaces/functions.d.ts +1 -1
  170. package/sdk/dist/namespaces/functions.js +2 -2
  171. package/sdk/dist/namespaces/functions.js.map +1 -1
  172. package/sdk/dist/namespaces/gitvault.crypto.d.ts +1 -1
  173. package/sdk/dist/namespaces/gitvault.d.ts +26 -26
  174. package/sdk/dist/namespaces/gitvault.d.ts.map +1 -1
  175. package/sdk/dist/namespaces/gitvault.js +113 -113
  176. package/sdk/dist/namespaces/gitvault.js.map +1 -1
  177. package/sdk/dist/namespaces/me.d.ts +120 -0
  178. package/sdk/dist/namespaces/me.d.ts.map +1 -0
  179. package/sdk/dist/namespaces/me.js +34 -0
  180. package/sdk/dist/namespaces/me.js.map +1 -0
  181. package/sdk/dist/namespaces/org.d.ts +108 -6
  182. package/sdk/dist/namespaces/org.d.ts.map +1 -1
  183. package/sdk/dist/namespaces/org.js +63 -7
  184. package/sdk/dist/namespaces/org.js.map +1 -1
  185. package/sdk/dist/namespaces/org.types.d.ts +29 -9
  186. package/sdk/dist/namespaces/org.types.d.ts.map +1 -1
  187. package/sdk/dist/namespaces/pay.js +3 -3
  188. package/sdk/dist/namespaces/pay.js.map +1 -1
  189. package/sdk/dist/namespaces/projects.d.ts +9 -9
  190. package/sdk/dist/namespaces/projects.js +15 -15
  191. package/sdk/dist/namespaces/projects.js.map +1 -1
  192. package/sdk/dist/namespaces/projects.types.d.ts +28 -12
  193. package/sdk/dist/namespaces/projects.types.d.ts.map +1 -1
  194. package/sdk/dist/namespaces/rooms.d.ts +7 -7
  195. package/sdk/dist/namespaces/rooms.js +17 -17
  196. package/sdk/dist/namespaces/rooms.js.map +1 -1
  197. package/sdk/dist/namespaces/rooms.types.d.ts +9 -9
  198. package/sdk/dist/namespaces/rooms.types.d.ts.map +1 -1
  199. package/sdk/dist/namespaces/service.d.ts +1 -1
  200. package/sdk/dist/namespaces/service.js +1 -1
  201. package/sdk/dist/namespaces/{operator-session.d.ts → session.d.ts} +135 -51
  202. package/sdk/dist/namespaces/session.d.ts.map +1 -0
  203. package/sdk/dist/namespaces/{operator-session.js → session.js} +118 -30
  204. package/sdk/dist/namespaces/session.js.map +1 -0
  205. package/sdk/dist/namespaces/subdomains.d.ts +5 -5
  206. package/sdk/dist/namespaces/subdomains.d.ts.map +1 -1
  207. package/sdk/dist/namespaces/subdomains.js +6 -6
  208. package/sdk/dist/namespaces/subdomains.js.map +1 -1
  209. package/sdk/dist/namespaces/tier.d.ts +44 -21
  210. package/sdk/dist/namespaces/tier.d.ts.map +1 -1
  211. package/sdk/dist/namespaces/tier.js +7 -7
  212. package/sdk/dist/namespaces/tier.js.map +1 -1
  213. package/sdk/dist/namespaces/transfers.d.ts +119 -85
  214. package/sdk/dist/namespaces/transfers.d.ts.map +1 -1
  215. package/sdk/dist/namespaces/transfers.js +31 -38
  216. package/sdk/dist/namespaces/transfers.js.map +1 -1
  217. package/sdk/dist/namespaces/vouchers.d.ts +9 -10
  218. package/sdk/dist/namespaces/vouchers.d.ts.map +1 -1
  219. package/sdk/dist/namespaces/vouchers.js +4 -5
  220. package/sdk/dist/namespaces/vouchers.js.map +1 -1
  221. package/sdk/dist/namespaces/wallets.d.ts +72 -3
  222. package/sdk/dist/namespaces/wallets.d.ts.map +1 -1
  223. package/sdk/dist/namespaces/wallets.js +141 -3
  224. package/sdk/dist/namespaces/wallets.js.map +1 -1
  225. package/sdk/dist/namespaces/write-approval.d.ts +101 -0
  226. package/sdk/dist/namespaces/write-approval.d.ts.map +1 -0
  227. package/sdk/dist/namespaces/write-approval.js +62 -0
  228. package/sdk/dist/namespaces/write-approval.js.map +1 -0
  229. package/sdk/dist/node/actions-node.d.ts +3 -3
  230. package/sdk/dist/node/actions-node.d.ts.map +1 -1
  231. package/sdk/dist/node/actions-node.js +44 -44
  232. package/sdk/dist/node/actions-node.js.map +1 -1
  233. package/sdk/dist/node/assets-node.js +6 -6
  234. package/sdk/dist/node/assets-node.js.map +1 -1
  235. package/sdk/dist/node/{bearer-claim-key.d.ts → bearer-redeem-key.d.ts} +12 -12
  236. package/sdk/dist/node/bearer-redeem-key.d.ts.map +1 -0
  237. package/sdk/dist/node/{bearer-claim-key.js → bearer-redeem-key.js} +21 -21
  238. package/sdk/dist/node/bearer-redeem-key.js.map +1 -0
  239. package/sdk/dist/node/ci.d.ts +1 -1
  240. package/sdk/dist/node/ci.d.ts.map +1 -1
  241. package/sdk/dist/node/ci.js +6 -6
  242. package/sdk/dist/node/ci.js.map +1 -1
  243. package/sdk/dist/node/credentials.d.ts +18 -17
  244. package/sdk/dist/node/credentials.d.ts.map +1 -1
  245. package/sdk/dist/node/credentials.js +29 -28
  246. package/sdk/dist/node/credentials.js.map +1 -1
  247. package/sdk/dist/node/deploy-manifest.d.ts +3 -5
  248. package/sdk/dist/node/deploy-manifest.d.ts.map +1 -1
  249. package/sdk/dist/node/deploy-manifest.js +3 -12
  250. package/sdk/dist/node/deploy-manifest.js.map +1 -1
  251. package/sdk/dist/node/funding-recovery.d.ts +1 -1
  252. package/sdk/dist/node/funding-recovery.d.ts.map +1 -1
  253. package/sdk/dist/node/funding-recovery.js +1 -1
  254. package/sdk/dist/node/funding-recovery.js.map +1 -1
  255. package/sdk/dist/node/gitvault-apply.d.ts +1 -1
  256. package/sdk/dist/node/gitvault-apply.d.ts.map +1 -1
  257. package/sdk/dist/node/gitvault-apply.js +1 -1
  258. package/sdk/dist/node/gitvault-apply.js.map +1 -1
  259. package/sdk/dist/node/gitvault-handoff.d.ts +22 -22
  260. package/sdk/dist/node/gitvault-handoff.d.ts.map +1 -1
  261. package/sdk/dist/node/gitvault-handoff.js +45 -45
  262. package/sdk/dist/node/gitvault-handoff.js.map +1 -1
  263. package/sdk/dist/node/gitvault-prewarm.js +7 -7
  264. package/sdk/dist/node/gitvault-prewarm.js.map +1 -1
  265. package/sdk/dist/node/gitvault-restore.d.ts +1 -1
  266. package/sdk/dist/node/gitvault-restore.js +1 -1
  267. package/sdk/dist/node/index.d.ts +16 -16
  268. package/sdk/dist/node/index.d.ts.map +1 -1
  269. package/sdk/dist/node/index.js +15 -15
  270. package/sdk/dist/node/index.js.map +1 -1
  271. package/sdk/dist/node/manifest-export.js +2 -2
  272. package/sdk/dist/node/manifest-export.js.map +1 -1
  273. package/sdk/dist/node/org-adopt.d.ts +49 -0
  274. package/sdk/dist/node/org-adopt.d.ts.map +1 -0
  275. package/sdk/dist/node/org-adopt.js +77 -0
  276. package/sdk/dist/node/org-adopt.js.map +1 -0
  277. package/sdk/dist/node/paid-fetch.d.ts +7 -7
  278. package/sdk/dist/node/paid-fetch.d.ts.map +1 -1
  279. package/sdk/dist/node/paid-fetch.js +54 -54
  280. package/sdk/dist/node/paid-fetch.js.map +1 -1
  281. package/sdk/dist/node/preflight.d.ts +1 -1
  282. package/sdk/dist/node/preflight.d.ts.map +1 -1
  283. package/sdk/dist/node/preflight.js +1 -1
  284. package/sdk/dist/node/preflight.js.map +1 -1
  285. package/sdk/dist/node/sites-node.js +1 -1
  286. package/sdk/dist/node/sites-node.js.map +1 -1
  287. package/sdk/dist/node/source-scan.d.ts +1 -1
  288. package/sdk/dist/node/source-scan.js +2 -2
  289. package/sdk/dist/node/source-scan.js.map +1 -1
  290. package/sdk/dist/scoped.d.ts +11 -11
  291. package/sdk/dist/scoped.d.ts.map +1 -1
  292. package/sdk/dist/scoped.js +5 -5
  293. package/sdk/dist/scoped.js.map +1 -1
  294. package/core-dist/operator-session.js +0 -154
  295. package/lib/allowance.mjs +0 -355
  296. package/lib/cloud.mjs +0 -256
  297. package/lib/core.mjs +0 -123
  298. package/lib/operator-proofs.mjs +0 -22
  299. package/lib/operator.mjs +0 -771
  300. package/sdk/core-dist/operator-session.js +0 -154
  301. package/sdk/dist/namespaces/allowance.d.ts +0 -79
  302. package/sdk/dist/namespaces/allowance.d.ts.map +0 -1
  303. package/sdk/dist/namespaces/allowance.js +0 -149
  304. package/sdk/dist/namespaces/allowance.js.map +0 -1
  305. package/sdk/dist/namespaces/operator-session.d.ts.map +0 -1
  306. package/sdk/dist/namespaces/operator-session.js.map +0 -1
  307. package/sdk/dist/namespaces/operator.d.ts +0 -359
  308. package/sdk/dist/namespaces/operator.d.ts.map +0 -1
  309. package/sdk/dist/namespaces/operator.js +0 -272
  310. package/sdk/dist/namespaces/operator.js.map +0 -1
  311. package/sdk/dist/node/bearer-claim-key.d.ts.map +0 -1
  312. package/sdk/dist/node/bearer-claim-key.js.map +0 -1
  313. package/sdk/dist/node/operator-claim.d.ts +0 -49
  314. package/sdk/dist/node/operator-claim.d.ts.map +0 -1
  315. package/sdk/dist/node/operator-claim.js +0 -77
  316. package/sdk/dist/node/operator-claim.js.map +0 -1
package/lib/up.mjs CHANGED
@@ -7,27 +7,27 @@ import { getSdk } from "./sdk.mjs";
7
7
  import { reportSdkError, fail } from "./sdk-errors.mjs";
8
8
  import { assertKnownFlags, flagValue, normalizeArgv, positionalArgs } from "./argparse.mjs";
9
9
  import { createUpdateCheckScheduler, emitUpdateNotice } from "./update-check.mjs";
10
- import { allowanceAuthHeaders, isCoreApiTarget, updateProject } from "./config.mjs";
10
+ import { walletAuthHeaders, isCoreApiTarget, updateProject } from "./config.mjs";
11
11
  import { loadLiveControlPlaneSession } from "../core-dist/control-plane-session.js";
12
12
 
13
13
  const HELP = `run402 up — Provision/link/deploy the current app
14
14
 
15
15
  Usage:
16
- run402 up [repo-or-path] [--name <name>] [--project <id>] [--manifest <path>] [--dir <path>] [--tier <tier>] [-y|--yes] [--check|--print-spec|--print-manifest|--plan|--require-plan <id>|--repo-only] [--nested] [--verify] [--human|--json-stream] [--quiet]
17
- run402 up verify [repo-or-path] [--project <id>] [--manifest <path>] [--dir <path>] [--human|--json-stream]
16
+ run402 up [repo-or-path] [--name <name>] [--project <project_id>] [--manifest <path>] [--dir <path>] [--tier <tier>] [-y|--yes] [--check|--print-spec|--print-manifest|--plan|--require-plan <plan_id>|--repo-only] [--nested] [--verify] [--human|--json-stream] [--quiet]
17
+ run402 up verify [repo-or-path] [--project <project_id>] [--manifest <path>] [--dir <path>] [--human|--json-stream]
18
18
 
19
19
  Options:
20
20
  repo-or-path Local app directory or public Git repository URL. Defaults
21
21
  to the current directory.
22
22
  --name <name> Project display name when up needs to create a project.
23
23
  Not a deploy manifest field and never renames a project.
24
- --project <id> Explicit project id. All supplied selectors must agree.
24
+ --project <project_id> Explicit project id. All supplied selectors must agree.
25
25
  --manifest <path> Manifest path. Defaults to run402.json, then
26
26
  run402.deploy.json, then app.json in --dir/current directory.
27
27
  --dir <path> Workspace directory to inspect (default: current dir).
28
28
  --tier <tier> Bootstrap tier if no active Cloud tier exists
29
29
  (prototype, hobby, team; default prototype).
30
- -y, --yes Approve recursive prerequisites/local writes (allowance,
30
+ -y, --yes Approve recursive prerequisites/local writes (wallet,
31
31
  tier, project creation, workspace link) for non-interactive runs.
32
32
  --check Validate the manifest/config locally and print the
33
33
  preflight, including the site inventory by content type
@@ -39,7 +39,7 @@ Options:
39
39
  uploads, or local writes.
40
40
  --plan Ask the gateway for a reviewed deploy plan. No upload,
41
41
  commit, project provisioning, or workspace link write.
42
- --require-plan <id> Apply only if this reviewed plan still matches.
42
+ --require-plan <plan_id> Apply only if this reviewed plan still matches.
43
43
  --plan-fingerprint <fingerprint>
44
44
  Optional fingerprint returned by --plan. Only valid
45
45
  with --require-plan.
@@ -53,7 +53,7 @@ Options:
53
53
  --propagation-budget-s <n>
54
54
  Maximum wall-clock seconds to wait for fresh edge
55
55
  propagation during app HTTP verification (default 120).
56
- --verify After a deploy apply, wait for gateway/edge release
56
+ --verify After the deploy, wait for gateway/edge release
57
57
  coherence and attach the report to the final result.
58
58
  --no-propagation-wait
59
59
  Return propagation_pending immediately when the edge is
@@ -104,7 +104,7 @@ coordination only. RUN402_AGENT_NAME=<name> sets the name, overriding an
104
104
  existing one; RUN402_CLIENT=<name> declares the client when it is not
105
105
  auto-detected. A detected client that was not applied (the principal is
106
106
  already named) is still reported. Change the name any time with
107
- 'run402 org whoami --set-name <name>'. Reported under result.identity
107
+ 'run402 whoami --set-name <name>'. Reported under result.identity
108
108
  (source, detected, detection).
109
109
  --json Emit one final JSON object on stdout (default; compatibility no-op).
110
110
  --human Emit the legacy human success/blocking summary on stdout.
@@ -138,12 +138,12 @@ Works for both app manifests (run402.json) and deploy manifests
138
138
  (run402.deploy.json / app.json) that declare a top-level verify block.
139
139
 
140
140
  Usage:
141
- run402 up verify [repo-or-path] [--project <id>] [--manifest <path>] [--dir <path>] [--name <name>] [--human|--json-stream]
141
+ run402 up verify [repo-or-path] [--project <project_id>] [--manifest <path>] [--dir <path>] [--name <name>] [--human|--json-stream]
142
142
 
143
143
  Options:
144
144
  repo-or-path Local app directory or public Git repository URL. Defaults
145
145
  to the current directory.
146
- --project <id> Existing project id. Defaults to .run402/project.json,
146
+ --project <project_id> Existing project id. Defaults to .run402/project.json,
147
147
  manifest project id, then active project.
148
148
  --manifest <path> Manifest path. Defaults to run402.json, then
149
149
  run402.deploy.json, then app.json.
@@ -373,7 +373,7 @@ export async function run(args = []) {
373
373
  ? undefined
374
374
  : undefined,
375
375
  });
376
- // Cache the activated deployment id so `run402 subdomains claim` can
376
+ // Cache the activated deployment id so `run402 subdomains add` can
377
377
  // pass it as an optimization (the gateway binds the live release
378
378
  // without it). Best-effort: a keystore hiccup never fails `up`.
379
379
  {
@@ -773,12 +773,12 @@ async function readLocalGitState(workDir) {
773
773
  * inside `up`'s mental model" entry point to the same outcome.
774
774
  */
775
775
  async function runRepoOnly({ sdk, workDir, createdRepository, nested = false, opts, tier, idempotencyKey }) {
776
- // `sdk.up()`'s action graph auto-approves prerequisites (allowance, tier)
776
+ // `sdk.up()`'s action graph auto-approves prerequisites (wallet, tier)
777
777
  // for a cold start; calling projects.provision directly bypasses that, so
778
778
  // this mirrors the SAME gate `run402 projects provision` itself uses —
779
- // fail with the actionable NO_ALLOWANCE guidance rather than an opaque
779
+ // fail with the actionable NO_WALLET guidance rather than an opaque
780
780
  // auth error from the gateway.
781
- if (!isCoreApiTarget() && !loadLiveControlPlaneSession()) allowanceAuthHeaders("/projects/v1");
781
+ if (!isCoreApiTarget() && !loadLiveControlPlaneSession()) walletAuthHeaders("/projects/v1");
782
782
  const name = flagValue(opts, "--name") ?? undefined;
783
783
  const provisioned = await sdk.projects.provision({ tier, name, idempotencyKey });
784
784
  createdRepository = await gitInitIfNeeded(workDir);
@@ -25,7 +25,7 @@ import { join } from "node:path";
25
25
  import { fail } from "./sdk-errors.mjs";
26
26
  import { isValidProfileName } from "../core-dist/config.js";
27
27
  import { getDefaultWallet, profileExists, readMeta, profileDir } from "../core-dist/profiles.js";
28
- import { readAllowance } from "../core-dist/allowance.js";
28
+ import { readWallet } from "../core-dist/wallet.js";
29
29
  import { describeRejectedValue } from "../core-dist/redact.js";
30
30
  // The binding file is a CHECKOUT-LEVEL CONTRACT read by more than one surface,
31
31
  // so its reader lives in core — `run402-mcp` ships core/dist but not cli/, and
@@ -104,7 +104,7 @@ export function splitWalletFlag(rawArgv = []) {
104
104
  * a file left with no keys is deleted rather than committed empty.
105
105
  *
106
106
  * The file is shared by tiers (`wallet` from `wallets bind`, `org`/`room` from
107
- * `org bind`) and unknown keys are preserved, so one tier can never clobber
107
+ * `orgs bind`) and unknown keys are preserved, so one tier can never clobber
108
108
  * another's binding — which a whole-file write did until this existed.
109
109
  */
110
110
  export function updateBindingFile(dir, patch) {
@@ -301,12 +301,12 @@ function shortAddr(a) {
301
301
  return typeof a === "string" && a.length >= 12 ? `${a.slice(0, 6)}…${a.slice(-4)}` : a;
302
302
  }
303
303
 
304
- /** Best-effort address for display: meta.json (no key) first, allowance second. */
304
+ /** Best-effort address for display: meta.json (no key) first, wallet second. */
305
305
  function walletAddress(name) {
306
306
  const meta = readMeta(name);
307
307
  if (meta?.address) return meta.address;
308
308
  try {
309
- return readAllowance(join(profileDir(name), "allowance.json"))?.address ?? null;
309
+ return readWallet(join(profileDir(name), "wallet.json"))?.address ?? null;
310
310
  } catch {
311
311
  return null;
312
312
  }
@@ -67,8 +67,8 @@ describe("splitWalletFlag", () => {
67
67
  assert.deepEqual(r.walletFlag, { flag: "--wallet", value: "kychon" });
68
68
  });
69
69
  it("strips --wallet=<value> mid-args", () => {
70
- const r = splitWalletFlag(["deploy", "apply", "--wallet=foo", "--manifest", "x"]);
71
- assert.deepEqual(r.argv, ["deploy", "apply", "--manifest", "x"]);
70
+ const r = splitWalletFlag(["deploy", "--wallet=foo", "--manifest", "x"]);
71
+ assert.deepEqual(r.argv, ["deploy", "--manifest", "x"]);
72
72
  assert.equal(r.walletFlag.value, "foo");
73
73
  });
74
74
  it("leaves --profile to `repos`, which owns it as the AWS credential profile", () => {
@@ -238,7 +238,7 @@ describe("enforceWalletExists — fail closed", () => {
238
238
  });
239
239
  it("no-op for an existing wallet", () => {
240
240
  ensureProfileDir("client-a");
241
- writeFileSync(join(tmp, "profiles", "client-a", "allowance.json"), "{}");
241
+ writeFileSync(join(tmp, "profiles", "client-a", "wallet.json"), "{}");
242
242
  assert.doesNotThrow(() => enforceWalletExists({ name: "client-a", source: "binding" }, "deploy"));
243
243
  });
244
244
  it("fails closed for a missing wallet on a normal command", () => {
package/lib/wallets.mjs CHANGED
@@ -17,6 +17,7 @@ import { writeFileSync, readFileSync, existsSync, rmSync } from "node:fs";
17
17
  import { failUnknownSubcommand } from "./argparse.mjs";
18
18
  import { join } from "node:path";
19
19
  import { fail, reportSdkError } from "./sdk-errors.mjs";
20
+ import { walletFile, readWallet as readActiveWallet, saveWallet as saveActiveWallet } from "./config.mjs";
20
21
  import { isValidProfileName, getActiveProfile } from "../core-dist/config.js";
21
22
  import {
22
23
  listProfileNames,
@@ -30,10 +31,11 @@ import {
30
31
  getDefaultWallet,
31
32
  setDefaultWallet,
32
33
  } from "../core-dist/profiles.js";
33
- import { readAllowance, saveAllowance } from "../core-dist/allowance.js";
34
+ import { readWallet, saveWallet } from "../core-dist/wallet.js";
34
35
  import { describeRejectedValue } from "../core-dist/redact.js";
35
36
  import { getSdk } from "./sdk.mjs";
36
37
  import { readBindingFile, updateBindingFile } from "./wallet-context.mjs";
38
+ import { initializeWalletAction } from "./next-actions.mjs";
37
39
 
38
40
  const DEFAULT = "default";
39
41
  const PRIVATE_KEY_RE = /^0x[0-9a-fA-F]{64}$/;
@@ -42,16 +44,18 @@ const HELP = `run402 wallets — manage named wallets (profiles)
42
44
 
43
45
  Usage:
44
46
  run402 wallets list List all wallets (local_label, server_label, address, rail, active)
45
- run402 wallets current Show the resolved active wallet + how it was selected
46
- run402 wallets new <name> Create a new named wallet (key stays local)
47
+ run402 wallets current Show the active wallet: how it was selected, address, rail, file path, faucet use
48
+ run402 wallets fund Request testnet funds from the faucet into the active wallet (Base Sepolia or Tempo)
49
+ run402 wallets balance The active wallet's on-chain balances, plus its organization's allowance
50
+ run402 wallets new <name> Create a new wallet (key stays local); 'default' creates the root wallet
47
51
  run402 wallets use <name> Set the global default wallet
48
52
  run402 wallets rename <old> --to <new> Rename a wallet (legacy: rename <old> <new>)
49
53
  run402 wallets bind [<name>] Write ./.run402.json binding this directory to a wallet
50
54
  run402 wallets unbind Remove ./.run402.json
51
55
  run402 wallets import <name> --key <path|-> Adopt an existing private key as a named wallet
52
56
  run402 wallets rm <name> --yes Delete a wallet and its keys (requires --yes)
53
- run402 wallets lightning status The active wallet's Lightning allowance (balance, budget, custody)
54
- run402 wallets lightning mint Mint the Lightning allowance for the active wallet (same as init lightning)
57
+ run402 wallets lightning status The active wallet's Lightning wallet (balance, budget, custody)
58
+ run402 wallets lightning mint Mint the Lightning wallet for the active wallet (same as init lightning)
55
59
  run402 wallets lightning revoke Revoke it: the sub-wallet is deleted on Run402's Hub; the rail returns to x402
56
60
 
57
61
  Selection precedence for normal commands:
@@ -102,7 +106,7 @@ function walletInfo(name, active) {
102
106
  const label = meta?.label ?? null;
103
107
  if (!address) {
104
108
  try {
105
- const a = readAllowance(join(profileDir(name), "allowance.json"));
109
+ const a = readWallet(join(profileDir(name), "wallet.json"));
106
110
  address = a?.address ?? null;
107
111
  rail = rail ?? a?.rail ?? null;
108
112
  } catch {
@@ -127,7 +131,7 @@ function cmdList() {
127
131
  out(listProfileNames().map((n) => walletInfo(n, active)));
128
132
  }
129
133
 
130
- function cmdCurrent() {
134
+ async function cmdCurrent() {
131
135
  const ctx = activeContext();
132
136
  const name = ctx?.name ?? getActiveProfile();
133
137
  const info = walletInfo(name, name);
@@ -146,21 +150,33 @@ function cmdCurrent() {
146
150
  hint: "Run 'run402 wallets rename' to reconcile.",
147
151
  });
148
152
  }
153
+ // The active wallet's own file: when it was created, its persisted rail, and
154
+ // whether the faucet has been used on it. `faucet_used` tracks faucet
155
+ // invocation, not pay-readiness — `run402 wallets balance` reads real funds.
156
+ let local = null;
157
+ try {
158
+ local = await getSdk().wallets.status();
159
+ } catch (err) {
160
+ reportSdkError(err);
161
+ }
149
162
  out({
150
163
  local_label: name,
151
164
  source: ctx?.source ?? "unknown",
152
165
  source_detail: ctx?.sourceDetail ?? null,
153
- address: info.address,
166
+ address: local?.configured ? local.address : info.address,
154
167
  server_label: info.server_label,
168
+ configured: !!local?.configured,
169
+ created: local?.created ?? null,
170
+ rail: local?.configured ? local.rail ?? "x402" : info.rail,
171
+ faucet_used: !!local?.faucet_used,
172
+ path: local?.path ?? walletFile(),
173
+ ...(local?.configured ? {} : { next_actions: [initializeWalletAction()] }),
155
174
  warnings,
156
175
  });
157
176
  }
158
177
 
159
178
  async function cmdNew(args) {
160
179
  const name = requireName(args.find((a) => a && !a.startsWith("-")));
161
- if (name === DEFAULT) {
162
- fail({ code: "BAD_WALLET_NAME", message: "'default' is reserved. Use 'run402 init' for the default wallet.", details: { name } });
163
- }
164
180
  if (profileExists(name)) {
165
181
  fail({ code: "WALLET_EXISTS", message: `A wallet named '${name}' already exists.`, hint: "run402 wallets list", details: { name } });
166
182
  }
@@ -175,12 +191,23 @@ async function cmdNew(args) {
175
191
  const address = privateKeyToAccount(privateKey).address;
176
192
  const created = new Date().toISOString();
177
193
  ensureProfileDir(name);
178
- saveAllowance({ address, privateKey, created, funded: false, rail }, join(profileDir(name), "allowance.json"));
179
- writeMeta(name, { name, address, label: name, rail, created });
180
- await maybePushLabel(name, name, address);
194
+ saveWallet({ address, privateKey, created, funded: false, rail }, join(profileDir(name), "wallet.json"));
195
+ // The reserved `default` wallet lives at the config-dir root and carries no
196
+ // server label; a named wallet mirrors its name as the label.
197
+ if (name === DEFAULT) {
198
+ writeMeta(name, { name, address, rail, created });
199
+ } else {
200
+ writeMeta(name, { name, address, label: name, rail, created });
201
+ await maybePushLabel(name, name, address);
202
+ }
181
203
  // requireName constrains aliases to shell-safe lowercase identifiers.
182
- const command = rail === "lightning" ? `run402 --wallet ${name} init lightning` : `run402 wallets use ${name}`;
183
- out({ local_label: name, address, rail, created: true, next: command, next_actions: [{ type: "run_command", command, why: rail === "lightning" ? "Initialize this Lightning wallet." : "Select the wallet you just created." }] });
204
+ const command = rail === "lightning"
205
+ ? `run402 --wallet ${name} init lightning`
206
+ : name === DEFAULT ? "run402 wallets fund" : `run402 wallets use ${name}`;
207
+ const why = rail === "lightning"
208
+ ? "Initialize this Lightning wallet."
209
+ : name === DEFAULT ? "Fund the wallet you just created from the testnet faucet." : "Select the wallet you just created.";
210
+ out({ local_label: name, address, rail, created: true, next: command, next_actions: [{ type: "run_command", command, why }] });
184
211
  }
185
212
 
186
213
  function cmdUse(args) {
@@ -216,7 +243,7 @@ async function cmdRename(args) {
216
243
  let address = meta.address ?? null;
217
244
  if (!address) {
218
245
  try {
219
- address = readAllowance(join(profileDir(newName), "allowance.json"))?.address ?? null;
246
+ address = readWallet(join(profileDir(newName), "wallet.json"))?.address ?? null;
220
247
  } catch {
221
248
  /* best-effort */
222
249
  }
@@ -229,7 +256,7 @@ async function cmdRename(args) {
229
256
  function cmdBind(args) {
230
257
  let name = args.find((a) => a && !a.startsWith("-"));
231
258
  name = name ? requireName(name) : getActiveProfile();
232
- // MERGE, never clobber: the same file carries `org`/`room` from `org bind`.
259
+ // MERGE, never clobber: the same file carries `org`/`room` from `orgs bind`.
233
260
  const { contents } = updateBindingFile(process.cwd(), { wallet: name });
234
261
  const result = {
235
262
  wallet: name,
@@ -285,7 +312,7 @@ async function cmdImport(args) {
285
312
  }
286
313
  const created = new Date().toISOString();
287
314
  ensureProfileDir(name);
288
- saveAllowance({ address, privateKey, created, funded: false, rail: "x402" }, join(profileDir(name), "allowance.json"));
315
+ saveWallet({ address, privateKey, created, funded: false, rail: "x402" }, join(profileDir(name), "wallet.json"));
289
316
  writeMeta(name, { name, address, label: name, rail: "x402", created });
290
317
  await maybePushLabel(name, name, address);
291
318
  out({ local_label: name, address, imported: true });
@@ -323,11 +350,11 @@ function flagVal(args, flag) {
323
350
  }
324
351
 
325
352
  /**
326
- * Best-effort server-side label push. Signs with the TARGET wallet's allowance
353
+ * Best-effort server-side label push. Signs with the TARGET wallet's key
327
354
  * (not the active one) so a just-created/renamed wallet can set its own label.
328
355
  *
329
356
  * ON by default — the gateway label endpoint is live, and the display label is
330
- * what makes the wallet name show up cross-machine and in the operator console
357
+ * what makes the wallet name show up cross-machine and in the console
331
358
  * (WEB). Set `RUN402_WALLET_LABEL_SYNC=0` to disable (fully-offline wallet ops,
332
359
  * or hermetic tests). The local folder name is always the source of truth; this
333
360
  * only mirrors the display label to the server. Always best-effort — `setLabel`
@@ -339,7 +366,7 @@ async function maybePushLabel(name, label, address) {
339
366
  if (!address) return;
340
367
  try {
341
368
  const sdk = getSdk({
342
- allowancePath: join(profileDir(name), "allowance.json"),
369
+ walletPath: join(profileDir(name), "wallet.json"),
343
370
  keystorePath: join(profileDir(name), "projects.json"),
344
371
  });
345
372
  await sdk.wallet(address).setLabel(label);
@@ -364,6 +391,8 @@ export async function run(sub, args = []) {
364
391
  case "unbind": return cmdUnbind();
365
392
  case "import": return cmdImport(rest);
366
393
  case "rm": return cmdRm(rest);
394
+ case "fund": return cmdFund();
395
+ case "balance": return cmdBalance();
367
396
  case "lightning": return cmdLightning(rest);
368
397
  default:
369
398
  failUnknownSubcommand("wallets", sub);
@@ -371,30 +400,30 @@ export async function run(sub, args = []) {
371
400
  }
372
401
 
373
402
  // ── lightning ────────────────────────────────────────────────────────────────
374
- // The Lightning allowance of the ACTIVE wallet (mpp-lightning-over-nwc).
375
- // The pairing secret stays in allowance.json and is never printed.
403
+ // The Lightning wallet of the ACTIVE wallet (mpp-lightning-over-nwc).
404
+ // The pairing secret stays in wallet.json and is never printed.
376
405
  async function cmdLightning(args) {
377
406
  const action = args.find((a) => a && !a.startsWith("-")) ?? "status";
378
407
  const { ensureLightningWallet, revokeLightningWallet, describeLightning, readLightningBalance } = await import("./lightning-wallet.mjs");
379
- const { readAllowance } = await import("../core-dist/allowance.js");
408
+ const { readWallet } = await import("../core-dist/wallet.js");
380
409
  try {
381
410
  if (action === "status") {
382
- const allowance = readAllowance();
383
- if (!allowance) fail({ code: "NO_ALLOWANCE", message: "No allowance configured for this wallet.", hint: "run402 init lightning" });
411
+ const localWallet = readWallet();
412
+ if (!localWallet) fail({ code: "NO_WALLET", message: "No local wallet configured for this wallet.", hint: "run402 init lightning" });
384
413
  let wallet = null;
385
414
  try { wallet = await getSdk().agent.lightningWallet.get(); } catch (err) {
386
415
  const code = err?.body?.code ?? err?.code;
387
416
  if (code !== "LIGHTNING_WALLET_NOT_FOUND") throw err;
388
417
  }
389
- const balance = await readLightningBalance(allowance);
390
- const lightning = describeLightning(allowance, wallet, balance);
391
- out({ rail: allowance.rail ?? "x402", lightning, ...(lightning ? {} : { hint: "run402 init lightning" }) });
418
+ const balance = await readLightningBalance(localWallet);
419
+ const lightning = describeLightning(localWallet, wallet, balance);
420
+ out({ rail: localWallet.rail ?? "x402", lightning, ...(lightning ? {} : { hint: "run402 init lightning" }) });
392
421
  return;
393
422
  }
394
423
  if (action === "mint") {
395
424
  const result = await ensureLightningWallet();
396
- const balance = result.outcome === "stored" || result.outcome === "present" ? await readLightningBalance(result.allowance) : null;
397
- out({ outcome: result.outcome, rail: result.allowance.rail ?? "x402", lightning: describeLightning(result.allowance, result.wallet, balance) });
425
+ const balance = result.outcome === "stored" || result.outcome === "present" ? await readLightningBalance(result.localWallet) : null;
426
+ out({ outcome: result.outcome, rail: result.localWallet.rail ?? "x402", lightning: describeLightning(result.localWallet, result.wallet, balance) });
398
427
  return;
399
428
  }
400
429
  if (action === "revoke") {
@@ -407,3 +436,139 @@ async function cmdLightning(args) {
407
436
  reportSdkError(err);
408
437
  }
409
438
  }
439
+
440
+ // ── fund / balance (the ACTIVE wallet) ─────────────────────────────────────
441
+
442
+ const USDC_ABI = [{ name: "balanceOf", type: "function", stateMutability: "view", inputs: [{ name: "account", type: "address" }], outputs: [{ name: "", type: "uint256" }] }];
443
+ const USDC_MAINNET = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
444
+ const USDC_SEPOLIA = "0x036CbD53842c5426634e7929541eC2318f3dCF7e";
445
+ const PATH_USD = "0x20c0000000000000000000000000000000000000";
446
+ const TEMPO_RPC = "https://rpc.moderato.tempo.xyz/";
447
+
448
+ async function loadDeps() {
449
+ const { generatePrivateKey, privateKeyToAccount } = await import("viem/accounts");
450
+ const { createPublicClient, http, defineChain } = await import("viem");
451
+ const { base, baseSepolia } = await import("viem/chains");
452
+ const tempoModerato = defineChain({
453
+ id: 42431,
454
+ name: "Tempo Moderato",
455
+ nativeCurrency: { name: "pathUSD", symbol: "pathUSD", decimals: 6 },
456
+ rpcUrls: { default: { http: [TEMPO_RPC] } },
457
+ });
458
+ return { generatePrivateKey, privateKeyToAccount, createPublicClient, http, base, baseSepolia, tempoModerato };
459
+ }
460
+
461
+ async function cmdFund() {
462
+ const w = readActiveWallet();
463
+ if (!w) {
464
+ fail({
465
+ code: "NO_WALLET",
466
+ message: "No local wallet.",
467
+ hint: "Run: run402 init",
468
+ });
469
+ }
470
+
471
+ if (w.rail === "mpp") {
472
+ // Tempo Moderato faucet — instant, no polling needed
473
+ const { createPublicClient, http, tempoModerato } = await loadDeps();
474
+ const client = createPublicClient({ chain: tempoModerato, transport: http() });
475
+ const before = await readUsdcBalance(client, PATH_USD, w.address).catch(() => 0);
476
+
477
+ const res = await fetch(TEMPO_RPC, {
478
+ method: "POST",
479
+ headers: { "Content-Type": "application/json" },
480
+ body: JSON.stringify({ jsonrpc: "2.0", method: "tempo_fundAddress", params: [w.address], id: 1 }),
481
+ });
482
+ const data = await res.json();
483
+ if (data.error) {
484
+ fail({
485
+ code: "FAUCET_FAILED",
486
+ message: data.error.message || "Tempo faucet failed",
487
+ details: { rail: "mpp" },
488
+ });
489
+ }
490
+
491
+ // Re-read balance once (instant confirmation)
492
+ const now = await readUsdcBalance(client, PATH_USD, w.address).catch(() => before);
493
+ saveActiveWallet({ ...w, funded: true, lastFaucet: new Date().toISOString() });
494
+ console.log(JSON.stringify({
495
+ address: w.address,
496
+ rail: "mpp",
497
+ onchain: {
498
+ "tempo-moderato_pathusd_micros": now,
499
+ },
500
+ }, null, 2));
501
+ return;
502
+ }
503
+
504
+ // Default: Base Sepolia faucet (existing behavior)
505
+ const { createPublicClient, http, baseSepolia } = await loadDeps();
506
+ const client = createPublicClient({ chain: baseSepolia, transport: http() });
507
+ const before = await readUsdcBalance(client, USDC_SEPOLIA, w.address).catch(() => 0);
508
+
509
+ let data;
510
+ try {
511
+ data = await getSdk().wallets.faucet(w.address);
512
+ } catch (err) {
513
+ reportSdkError(err);
514
+ }
515
+
516
+ const MAX_WAIT = 30;
517
+ for (let i = 0; i < MAX_WAIT; i++) {
518
+ await new Promise(r => setTimeout(r, 1000));
519
+ const now = await readUsdcBalance(client, USDC_SEPOLIA, w.address).catch(() => before);
520
+ if (now > before) {
521
+ saveActiveWallet({ ...w, funded: true, lastFaucet: new Date().toISOString() });
522
+ console.log(JSON.stringify({
523
+ address: w.address,
524
+ rail: w.rail || "x402",
525
+ onchain: {
526
+ "base-sepolia_usd_micros": now,
527
+ },
528
+ }, null, 2));
529
+ return;
530
+ }
531
+ }
532
+
533
+ saveActiveWallet({ ...w, funded: true, lastFaucet: new Date().toISOString() });
534
+ console.log(JSON.stringify({ ...data, balance_confirmed: false, hint: "Faucet request sent but on-chain balance not yet confirmed" }));
535
+ }
536
+
537
+ async function readUsdcBalance(client, usdc, address) {
538
+ const raw = await client.readContract({ address: usdc, abi: USDC_ABI, functionName: "balanceOf", args: [address] });
539
+ return Number(raw);
540
+ }
541
+
542
+ async function cmdBalance() {
543
+ const w = readActiveWallet();
544
+ if (!w) {
545
+ fail({
546
+ code: "NO_WALLET",
547
+ message: "No local wallet.",
548
+ hint: "Run: run402 init",
549
+ });
550
+ }
551
+
552
+ const { createPublicClient, http, base, baseSepolia, tempoModerato } = await loadDeps();
553
+ const mainnetClient = createPublicClient({ chain: base, transport: http() });
554
+ const sepoliaClient = createPublicClient({ chain: baseSepolia, transport: http() });
555
+ const tempoClient = createPublicClient({ chain: tempoModerato, transport: http() });
556
+
557
+ const [mainnetUsdc, sepoliaUsdc, tempoPathUsd, billingRes] = await Promise.all([
558
+ readUsdcBalance(mainnetClient, USDC_MAINNET, w.address).catch(() => null),
559
+ readUsdcBalance(sepoliaClient, USDC_SEPOLIA, w.address).catch(() => null),
560
+ readUsdcBalance(tempoClient, PATH_USD, w.address).catch(() => null),
561
+ getSdk().billing.checkBalance(w.address).catch(() => null),
562
+ ]);
563
+
564
+ console.log(JSON.stringify({
565
+ address: w.address,
566
+ rail: w.rail || "x402",
567
+ onchain: {
568
+ "base-mainnet_usd_micros": mainnetUsdc,
569
+ "base-sepolia_usd_micros": sepoliaUsdc,
570
+ "tempo-moderato_pathusd_micros": tempoPathUsd,
571
+ },
572
+ allowance_usd_micros: billingRes ? billingRes.allowance_usd_micros : null,
573
+ }, null, 2));
574
+ }
@@ -1,18 +1,18 @@
1
1
  /**
2
- * run402 webhook-secret — Manage the operator webhook signing secret.
2
+ * run402 webhook-secret — Manage your webhook signing secret.
3
3
  *
4
4
  * Split out from notifications.mjs so the SURFACE inventory parser sees
5
5
  * `webhook-secret:rotate` as its own command, separate from the
6
6
  * `notifications:*` group.
7
7
  */
8
8
 
9
- import { allowanceAuthHeaders } from "./config.mjs";
10
- import { operatorProofs } from "./operator-proofs.mjs";
9
+ import { walletAuthHeaders } from "./config.mjs";
10
+ import { sessionProofs } from "./session-proofs.mjs";
11
11
  import { getSdk } from "./sdk.mjs";
12
12
  import { reportSdkError } from "./sdk-errors.mjs";
13
13
  import { assertKnownFlags, normalizeArgv, failUnknownSubcommand } from "./argparse.mjs";
14
14
 
15
- const HELP = `run402 webhook-secret — Manage the operator webhook signing secret
15
+ const HELP = `run402 webhook-secret — Manage your webhook signing secret
16
16
 
17
17
  Usage:
18
18
  run402 webhook-secret rotate
@@ -20,7 +20,7 @@ Usage:
20
20
  Notes:
21
21
  - Returns the new plaintext secret EXACTLY once. Store it immediately.
22
22
  - Previous secret remains valid for 24 hours after rotation.
23
- - Requires operator_passkey assurance level.
23
+ - Requires passkey assurance ('run402 login', or 'run402 agent passkey enroll').
24
24
  `;
25
25
 
26
26
  export async function run(sub, args = []) {
@@ -39,7 +39,7 @@ export async function run(sub, args = []) {
39
39
  }
40
40
  const parsedArgs = normalizeArgv(args);
41
41
  assertKnownFlags(parsedArgs, ["--help", "-h"]);
42
- const proofs = operatorProofs("/agent/v1/webhook-secret/rotate");
42
+ const proofs = sessionProofs("/agent/v1/webhook-secret/rotate");
43
43
  try {
44
44
  const data = await getSdk().admin.rotateWebhookSecret(proofs);
45
45
  console.log(JSON.stringify(data, null, 2));
package/lib/webhooks.mjs CHANGED
@@ -9,13 +9,13 @@ Usage:
9
9
  run402 email webhooks <action> [args...]
10
10
 
11
11
  Actions:
12
- list [--mailbox <slug|id>] [--project <id>] List webhooks
13
- get <webhook_id> [--mailbox <slug|id>] [--project <id>] Get a webhook
14
- delete <webhook_id> [--mailbox <slug|id>] [--project <id>] Delete a webhook
12
+ list [--mailbox <slug|id>] [--project <project_id>] List webhooks
13
+ get <webhook_id> [--mailbox <slug|id>] [--project <project_id>] Get a webhook
14
+ delete <webhook_id> [--mailbox <slug|id>] [--project <project_id>] Delete a webhook
15
15
  update <webhook_id> [--url <url>] [--events <e1,e2>] [--mailbox <slug|id>] Update a webhook
16
- register --url <url> --events <e1,e2> [--mailbox <slug|id>] [--project <id>] Register a new webhook
17
- deliveries [--status <s>] [--mailbox <slug|id>] [--project <id>] List durable delivery rows (DLQ visibility)
18
- redrive <delivery_id> [--mailbox <slug|id>] [--project <id>] Re-queue a dead-lettered delivery
16
+ register --url <url> --events <e1,e2> [--mailbox <slug|id>] [--project <project_id>] Register a new webhook
17
+ deliveries [--status <s>] [--mailbox <slug|id>] [--project <project_id>] List durable delivery rows (DLQ visibility)
18
+ redrive <delivery_id> [--mailbox <slug|id>] [--project <project_id>] Re-queue a dead-lettered delivery
19
19
 
20
20
  Valid events: delivery, bounced, complained, reply_received, mailbox_suspended
21
21
  Delivery statuses: pending, in_flight, delivered, failed_permanent (the DLQ)
@@ -41,12 +41,12 @@ const SUB_HELP = {
41
41
  update: `run402 email webhooks update — Update an existing webhook
42
42
 
43
43
  Usage:
44
- run402 email webhooks update <webhook_id> [--url <url>] [--events <e1,e2>] [--mailbox <slug|id>] [--project <id>]
44
+ run402 email webhooks update <webhook_id> [--url <url>] [--events <e1,e2>] [--mailbox <slug|id>] [--project <project_id>]
45
45
  `,
46
46
  register: `run402 email webhooks register — Register a new webhook
47
47
 
48
48
  Usage:
49
- run402 email webhooks register --url <url> --events <e1,e2> [--mailbox <slug|id>] [--project <id>]
49
+ run402 email webhooks register --url <url> --events <e1,e2> [--mailbox <slug|id>] [--project <project_id>]
50
50
  `,
51
51
  };
52
52