run402 4.96.0 → 4.98.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 (225) hide show
  1. package/README.md +3 -3
  2. package/cli.mjs +1 -7
  3. package/core-dist/binding-file.js +28 -1
  4. package/core-dist/wallet.js +3 -3
  5. package/lib/auth.mjs +1 -2
  6. package/lib/buzz-doctor.mjs +21 -806
  7. package/lib/buzz-doctor.test.mjs +7 -6
  8. package/lib/buzz.mjs +1 -1
  9. package/lib/buzz.test.mjs +13 -2
  10. package/lib/command-manifest.mjs +3 -6
  11. package/lib/credentials.mjs +4 -4
  12. package/lib/deploy-v2.mjs +27 -27
  13. package/lib/doctor.mjs +72 -811
  14. package/lib/errors.mjs +1 -1
  15. package/lib/events.mjs +1 -1
  16. package/lib/grants.mjs +148 -46
  17. package/lib/init.mjs +35 -576
  18. package/lib/logs.mjs +1 -1
  19. package/lib/org-context.mjs +39 -376
  20. package/lib/orgs.mjs +22 -106
  21. package/lib/projects.mjs +2 -3
  22. package/lib/repos.mjs +6 -6
  23. package/lib/rooms.mjs +1 -2
  24. package/lib/sdk-errors.mjs +26 -0
  25. package/lib/sites.mjs +5 -5
  26. package/lib/status.mjs +14 -154
  27. package/lib/up.mjs +1 -2
  28. package/lib/vault-scaffold.mjs +2 -3
  29. package/lib/vault-target.mjs +14 -141
  30. package/lib/wallet-context.mjs +61 -227
  31. package/lib/wallets.mjs +47 -310
  32. package/package.json +1 -2
  33. package/sdk/core-dist/binding-file.js +28 -1
  34. package/sdk/core-dist/wallet.js +3 -3
  35. package/sdk/dist/errors.d.ts +25 -3
  36. package/sdk/dist/errors.d.ts.map +1 -1
  37. package/sdk/dist/errors.js +46 -4
  38. package/sdk/dist/errors.js.map +1 -1
  39. package/sdk/dist/grant-key-credentials.d.ts +38 -0
  40. package/sdk/dist/grant-key-credentials.d.ts.map +1 -0
  41. package/sdk/dist/grant-key-credentials.js +42 -0
  42. package/sdk/dist/grant-key-credentials.js.map +1 -0
  43. package/sdk/dist/index.d.ts +25 -17
  44. package/sdk/dist/index.d.ts.map +1 -1
  45. package/sdk/dist/index.js +18 -14
  46. package/sdk/dist/index.js.map +1 -1
  47. package/sdk/dist/kernel.d.ts +34 -0
  48. package/sdk/dist/kernel.d.ts.map +1 -1
  49. package/sdk/dist/kernel.js +15 -1
  50. package/sdk/dist/kernel.js.map +1 -1
  51. package/sdk/dist/namespaces/admin.d.ts.map +1 -1
  52. package/sdk/dist/namespaces/admin.js +8 -0
  53. package/sdk/dist/namespaces/admin.js.map +1 -1
  54. package/sdk/dist/namespaces/agent.d.ts +2 -2
  55. package/sdk/dist/namespaces/agent.d.ts.map +1 -1
  56. package/sdk/dist/namespaces/agent.js +4 -0
  57. package/sdk/dist/namespaces/agent.js.map +1 -1
  58. package/sdk/dist/namespaces/agent.types.d.ts +5 -0
  59. package/sdk/dist/namespaces/agent.types.d.ts.map +1 -1
  60. package/sdk/dist/namespaces/apps.d.ts.map +1 -1
  61. package/sdk/dist/namespaces/apps.js +2 -0
  62. package/sdk/dist/namespaces/apps.js.map +1 -1
  63. package/sdk/dist/namespaces/auth.d.ts.map +1 -1
  64. package/sdk/dist/namespaces/auth.js +9 -0
  65. package/sdk/dist/namespaces/auth.js.map +1 -1
  66. package/sdk/dist/namespaces/billing.d.ts +1 -1
  67. package/sdk/dist/namespaces/billing.js +1 -1
  68. package/sdk/dist/namespaces/branches.d.ts.map +1 -1
  69. package/sdk/dist/namespaces/branches.js +2 -0
  70. package/sdk/dist/namespaces/branches.js.map +1 -1
  71. package/sdk/dist/namespaces/buzz.js +1 -1
  72. package/sdk/dist/namespaces/buzz.js.map +1 -1
  73. package/sdk/dist/namespaces/ci.d.ts.map +1 -1
  74. package/sdk/dist/namespaces/ci.js +2 -0
  75. package/sdk/dist/namespaces/ci.js.map +1 -1
  76. package/sdk/dist/namespaces/credentials.d.ts +4 -27
  77. package/sdk/dist/namespaces/credentials.d.ts.map +1 -1
  78. package/sdk/dist/namespaces/credentials.js +33 -4
  79. package/sdk/dist/namespaces/credentials.js.map +1 -1
  80. package/sdk/dist/namespaces/deploy.js +5 -5
  81. package/sdk/dist/namespaces/deploy.js.map +1 -1
  82. package/sdk/dist/namespaces/domains.d.ts +1 -1
  83. package/sdk/dist/namespaces/domains.js +1 -1
  84. package/sdk/dist/namespaces/errors.d.ts +1 -1
  85. package/sdk/dist/namespaces/errors.js +2 -2
  86. package/sdk/dist/namespaces/escalations.d.ts +2 -2
  87. package/sdk/dist/namespaces/escalations.d.ts.map +1 -1
  88. package/sdk/dist/namespaces/escalations.js +4 -2
  89. package/sdk/dist/namespaces/escalations.js.map +1 -1
  90. package/sdk/dist/namespaces/escalations.types.d.ts +3 -3
  91. package/sdk/dist/namespaces/escalations.types.d.ts.map +1 -1
  92. package/sdk/dist/namespaces/events.d.ts +1 -1
  93. package/sdk/dist/namespaces/events.js +1 -1
  94. package/sdk/dist/namespaces/functions.js +1 -1
  95. package/sdk/dist/namespaces/functions.js.map +1 -1
  96. package/sdk/dist/namespaces/grants.d.ts +43 -9
  97. package/sdk/dist/namespaces/grants.d.ts.map +1 -1
  98. package/sdk/dist/namespaces/grants.js +103 -10
  99. package/sdk/dist/namespaces/grants.js.map +1 -1
  100. package/sdk/dist/namespaces/grants.types.d.ts +120 -15
  101. package/sdk/dist/namespaces/grants.types.d.ts.map +1 -1
  102. package/sdk/dist/namespaces/grants.types.js +12 -3
  103. package/sdk/dist/namespaces/grants.types.js.map +1 -1
  104. package/sdk/dist/namespaces/identity-links.types.d.ts +2 -2
  105. package/sdk/dist/namespaces/identity-links.types.d.ts.map +1 -1
  106. package/sdk/dist/namespaces/live.d.ts +0 -16
  107. package/sdk/dist/namespaces/live.d.ts.map +1 -1
  108. package/sdk/dist/namespaces/live.js +19 -0
  109. package/sdk/dist/namespaces/live.js.map +1 -1
  110. package/sdk/dist/namespaces/me.d.ts.map +1 -1
  111. package/sdk/dist/namespaces/me.js +3 -0
  112. package/sdk/dist/namespaces/me.js.map +1 -1
  113. package/sdk/dist/namespaces/org.d.ts +1 -1
  114. package/sdk/dist/namespaces/org.d.ts.map +1 -1
  115. package/sdk/dist/namespaces/org.js +4 -1
  116. package/sdk/dist/namespaces/org.js.map +1 -1
  117. package/sdk/dist/namespaces/projects.d.ts +1 -1
  118. package/sdk/dist/namespaces/projects.d.ts.map +1 -1
  119. package/sdk/dist/namespaces/projects.js +6 -1
  120. package/sdk/dist/namespaces/projects.js.map +1 -1
  121. package/sdk/dist/namespaces/repos.d.ts.map +1 -1
  122. package/sdk/dist/namespaces/repos.js +7 -2
  123. package/sdk/dist/namespaces/repos.js.map +1 -1
  124. package/sdk/dist/namespaces/rooms.d.ts +3 -3
  125. package/sdk/dist/namespaces/rooms.d.ts.map +1 -1
  126. package/sdk/dist/namespaces/rooms.js +6 -3
  127. package/sdk/dist/namespaces/rooms.js.map +1 -1
  128. package/sdk/dist/namespaces/session.d.ts.map +1 -1
  129. package/sdk/dist/namespaces/session.js +18 -0
  130. package/sdk/dist/namespaces/session.js.map +1 -1
  131. package/sdk/dist/namespaces/transfers.d.ts.map +1 -1
  132. package/sdk/dist/namespaces/transfers.js +3 -0
  133. package/sdk/dist/namespaces/transfers.js.map +1 -1
  134. package/sdk/dist/namespaces/wallets.d.ts.map +1 -1
  135. package/sdk/dist/namespaces/wallets.js +2 -0
  136. package/sdk/dist/namespaces/wallets.js.map +1 -1
  137. package/sdk/dist/namespaces/write-approval.d.ts.map +1 -1
  138. package/sdk/dist/namespaces/write-approval.js +3 -0
  139. package/sdk/dist/namespaces/write-approval.js.map +1 -1
  140. package/sdk/dist/node/actions-node.d.ts.map +1 -1
  141. package/sdk/dist/node/actions-node.js +3 -0
  142. package/sdk/dist/node/actions-node.js.map +1 -1
  143. package/sdk/dist/node/buzz-doctor-contract.d.ts +155 -0
  144. package/sdk/dist/node/buzz-doctor-contract.d.ts.map +1 -0
  145. package/sdk/dist/node/buzz-doctor-contract.js +385 -0
  146. package/sdk/dist/node/buzz-doctor-contract.js.map +1 -0
  147. package/sdk/dist/node/buzz-doctor.d.ts +155 -0
  148. package/sdk/dist/node/buzz-doctor.d.ts.map +1 -0
  149. package/sdk/dist/node/buzz-doctor.js +810 -0
  150. package/sdk/dist/node/buzz-doctor.js.map +1 -0
  151. package/sdk/dist/node/credentials.d.ts +18 -13
  152. package/sdk/dist/node/credentials.d.ts.map +1 -1
  153. package/sdk/dist/node/credentials.js +13 -13
  154. package/sdk/dist/node/credentials.js.map +1 -1
  155. package/sdk/dist/node/diagnostics.d.ts +45 -0
  156. package/sdk/dist/node/diagnostics.d.ts.map +1 -0
  157. package/sdk/dist/node/diagnostics.js +67 -0
  158. package/sdk/dist/node/diagnostics.js.map +1 -0
  159. package/sdk/dist/node/doctor.d.ts +101 -0
  160. package/sdk/dist/node/doctor.d.ts.map +1 -0
  161. package/sdk/dist/node/doctor.js +618 -0
  162. package/sdk/dist/node/doctor.js.map +1 -0
  163. package/sdk/dist/node/index.d.ts +61 -9
  164. package/sdk/dist/node/index.d.ts.map +1 -1
  165. package/sdk/dist/node/index.js +37 -2
  166. package/sdk/dist/node/index.js.map +1 -1
  167. package/sdk/dist/node/init.d.ts +137 -0
  168. package/sdk/dist/node/init.d.ts.map +1 -0
  169. package/sdk/dist/node/init.js +507 -0
  170. package/sdk/dist/node/init.js.map +1 -0
  171. package/sdk/dist/node/lightning-wallet.d.ts +61 -0
  172. package/sdk/dist/node/lightning-wallet.d.ts.map +1 -0
  173. package/sdk/dist/node/lightning-wallet.js +126 -0
  174. package/sdk/dist/node/lightning-wallet.js.map +1 -0
  175. package/sdk/dist/node/local-actions.d.ts +23 -0
  176. package/sdk/dist/node/local-actions.d.ts.map +1 -0
  177. package/sdk/dist/node/local-actions.js +38 -0
  178. package/sdk/dist/node/local-actions.js.map +1 -0
  179. package/sdk/dist/node/org-context.d.ts +169 -0
  180. package/sdk/dist/node/org-context.d.ts.map +1 -0
  181. package/sdk/dist/node/org-context.js +403 -0
  182. package/sdk/dist/node/org-context.js.map +1 -0
  183. package/sdk/dist/node/status.d.ts +62 -0
  184. package/sdk/dist/node/status.d.ts.map +1 -0
  185. package/sdk/dist/node/status.js +132 -0
  186. package/sdk/dist/node/status.js.map +1 -0
  187. package/sdk/dist/node/vault-target.d.ts +49 -0
  188. package/sdk/dist/node/vault-target.d.ts.map +1 -0
  189. package/sdk/dist/node/vault-target.js +109 -0
  190. package/sdk/dist/node/vault-target.js.map +1 -0
  191. package/sdk/dist/node/wallets.d.ts +242 -0
  192. package/sdk/dist/node/wallets.d.ts.map +1 -0
  193. package/sdk/dist/node/wallets.js +484 -0
  194. package/sdk/dist/node/wallets.js.map +1 -0
  195. package/sdk/dist/project-auth-classification.d.ts +8 -8
  196. package/sdk/dist/project-auth-classification.d.ts.map +1 -1
  197. package/sdk/dist/project-auth-classification.js +7 -7
  198. package/sdk/dist/project-auth-classification.js.map +1 -1
  199. package/sdk/dist/scoped.d.ts +6 -14
  200. package/sdk/dist/scoped.d.ts.map +1 -1
  201. package/sdk/dist/scoped.js +10 -21
  202. package/sdk/dist/scoped.js.map +1 -1
  203. package/sdk/dist/secret-gate.d.ts +377 -0
  204. package/sdk/dist/secret-gate.d.ts.map +1 -0
  205. package/sdk/dist/secret-gate.js +273 -0
  206. package/sdk/dist/secret-gate.js.map +1 -0
  207. package/vault-surface.json +1 -1
  208. package/fixtures/buzz-v0.5.2-cli-capabilities.json +0 -92
  209. package/fixtures/run402-buzz-doctor-v1-contract.json +0 -140
  210. package/lib/buzz-doctor-contract.mjs +0 -97
  211. package/lib/buzz-doctor-contract.test.mjs +0 -134
  212. package/lib/delegates.mjs +0 -189
  213. package/lib/lightning-wallet.mjs +0 -115
  214. package/sdk/dist/delegate-credentials.d.ts +0 -37
  215. package/sdk/dist/delegate-credentials.d.ts.map +0 -1
  216. package/sdk/dist/delegate-credentials.js +0 -41
  217. package/sdk/dist/delegate-credentials.js.map +0 -1
  218. package/sdk/dist/namespaces/delegates.d.ts +0 -50
  219. package/sdk/dist/namespaces/delegates.d.ts.map +0 -1
  220. package/sdk/dist/namespaces/delegates.js +0 -99
  221. package/sdk/dist/namespaces/delegates.js.map +0 -1
  222. package/sdk/dist/namespaces/delegates.types.d.ts +0 -88
  223. package/sdk/dist/namespaces/delegates.types.d.ts.map +0 -1
  224. package/sdk/dist/namespaces/delegates.types.js +0 -10
  225. package/sdk/dist/namespaces/delegates.types.js.map +0 -1
@@ -5,15 +5,16 @@ import { join } from "node:path";
5
5
  import { describe, it } from "node:test";
6
6
  import { bech32 } from "@scure/base";
7
7
  import {
8
- buildBuzzDoctorReport,
8
+ BUZZ_DOCTOR_CHECK_ORDER,
9
+ BUZZ_DOCTOR_CONTRACT,
9
10
  BUZZ_DOCTOR_MIN_RUN402_VERSION,
10
11
  BUZZ_DOCTOR_REPAIR_MATRIX,
11
12
  isPublicAddress,
12
13
  normalizeNostrSubject,
13
- parseBuzzDoctorArgs,
14
14
  pinnedLookup,
15
- } from "./buzz-doctor.mjs";
16
- import { BUZZ_DOCTOR_CHECK_ORDER, BUZZ_DOCTOR_CONTRACT, validateBuzzDoctorReport } from "./buzz-doctor-contract.mjs";
15
+ validateBuzzDoctorReport,
16
+ } from "#sdk/node";
17
+ import { buildBuzzDoctorReport, parseBuzzDoctorArgs } from "./buzz-doctor.mjs";
17
18
 
18
19
  const SUBJECT = "6b6951a5738dfe576d0c44bf7a5f8afe655005a156f9d3e648d81437c3f5ebbf";
19
20
  const OTHER_SUBJECT = "a".repeat(64);
@@ -72,7 +73,7 @@ function healthyDependencies(overrides = {}) {
72
73
  runCommand,
73
74
  lookup: async () => [{ address: "93.184.216.34", family: 4 }],
74
75
  pinnedRelayRead: async () => ({ ok: true, status: 200, elapsed_ms: 4 }),
75
- originProbe: async () => ({ ok: true, status: 200, elapsed_ms: 3 }),
76
+ originProbe: async () => ({ reachable: true, classification: "ok", status: 200, elapsed_ms: 3 }),
76
77
  updateCheck: async () => ({ name: "cli_update", status: "ok" }),
77
78
  getActiveProfile: () => "buzz-fizz",
78
79
  profileExistsImpl: () => true,
@@ -154,7 +155,7 @@ describe("Buzz doctor bounded zero-mutation runner", () => {
154
155
  }
155
156
  return commandError();
156
157
  };
157
- dependencies.originProbe = async () => ({ ok: false, status: 503, failure: "http_503" });
158
+ dependencies.originProbe = async () => ({ reachable: false, classification: "http", status: 503, error: "http_503", elapsed_ms: 3 });
158
159
  dependencies.lookup = async () => [
159
160
  { address: "93.184.216.34", family: 4 },
160
161
  { address: "127.0.0.1", family: 4 },
package/lib/buzz.mjs CHANGED
@@ -67,7 +67,7 @@ Advanced recovery reads:
67
67
  Security:
68
68
  - JSON stdout only; progress and pending-state advice go to stderr.
69
69
  - This command never accepts an nsec, private key, mnemonic, seed, service key,
70
- delegate token, recovery code, or payment material.
70
+ grant key, recovery code, or payment material.
71
71
  - Buzz signatures are public evidence. Run402 authority still comes only from
72
72
  human/agent principals, org membership, and project grants.
73
73
  - Every command in this group has zero spend impact.
package/lib/buzz.test.mjs CHANGED
@@ -7,11 +7,22 @@ import { afterEach, beforeEach, describe, it, mock } from "node:test";
7
7
  let sdk;
8
8
  const authModes = [];
9
9
 
10
+ // Organization resolution is real (the `--org` flag resolves locally); every
11
+ // other namespace is the test's fake, and `authModes` records the auth mode of
12
+ // each client that reaches one.
13
+ const { run402: realSdk } = await import("../sdk/dist/node/index.js");
10
14
  mock.module("./sdk.mjs", {
11
15
  namedExports: {
12
16
  getSdk: (options = {}) => {
13
- authModes.push(options.authMode ?? "default");
14
- return sdk;
17
+ let recorded = false;
18
+ return new Proxy({}, {
19
+ get(_target, prop) {
20
+ if (prop === "orgs") return realSdk({ surface: "cli", disablePaidFetch: true }).orgs;
21
+ if (!recorded) authModes.push(options.authMode ?? "default");
22
+ recorded = true;
23
+ return sdk?.[prop];
24
+ },
25
+ });
15
26
  },
16
27
  },
17
28
  });
@@ -235,13 +235,10 @@ export const COMMAND_MANIFEST = [
235
235
 
236
236
  // ── grants ───────────────────────────────────────────────────────────────
237
237
  { path: ["grants", "create"], positionals: [p("wallet")], projectScoped: true, legacyPositionalProject: true, minimalArgs: ["0x1111111111111111111111111111111111111111", "--capability", "deploy"] },
238
+ { path: ["grants", "list"], positionals: [], projectScoped: true, legacyPositionalProject: true, minimalArgs: [] },
238
239
  { path: ["grants", "revoke"], positionals: [p("grant_id")], projectScoped: true, legacyPositionalProject: true, minimalArgs: ["grt_gate1"] },
239
-
240
- // ── delegates ────────────────────────────────────────────────────────────
241
- { path: ["delegates", "create"], legacyPositionalProject: false, positionals: [], projectScoped: true, minimalArgs: ["--grant", "11111111-1111-1111-1111-111111111111"] },
242
- { path: ["delegates", "list"], legacyPositionalProject: false, positionals: [], projectScoped: true, minimalArgs: [] },
243
- { path: ["delegates", "revoke"], legacyPositionalProject: false, positionals: [p("delegate_id")], projectScoped: true, minimalArgs: ["dlg_gate1"] },
244
- { path: ["delegates", "rotate"], legacyPositionalProject: false, positionals: [p("delegate_id")], projectScoped: true, minimalArgs: ["dlg_gate1"] },
240
+ { path: ["grants", "revoke-key"], positionals: [p("key_id")], projectScoped: true, legacyPositionalProject: true, minimalArgs: ["key_gate1"] },
241
+ { path: ["grants", "rotate-key"], positionals: [p("key_id")], projectScoped: true, legacyPositionalProject: true, minimalArgs: ["key_gate1"] },
245
242
 
246
243
  // ── events / live ────────────────────────────────────────────────────────
247
244
  { path: ["events", "list"], positionals: [], projectScoped: true, legacyPositionalProject: false, minimalArgs: [], runStyle: "sub" },
@@ -39,7 +39,7 @@ Project credentials (on the gateway — named, revocable, rotatable):
39
39
  Revoke immediately, freeing the name
40
40
  token [--project <project_id>] [--kind <anon|service>]
41
41
  Mint a SHORT-LIVED token. Works with only a
42
- delegate — the unattended recovery path.
42
+ grant key — the unattended recovery path.
43
43
 
44
44
  Local cache (on this machine):
45
45
  project-keys Manage the local project-key cache
@@ -49,7 +49,7 @@ Notes:
49
49
  plus a fresh step-up, so a scoped agent credential can never escalate
50
50
  itself into a permanent root. Authenticate with a wallet (SIWX) or a
51
51
  sign-in session ('run402 login').
52
- - 'token' is the exception: a delegate can mint one with no human present.
52
+ - 'token' is the exception: a grant key can mint one with no human present.
53
53
  - Secrets are returned EXACTLY ONCE and are never recoverable. Full JSON goes
54
54
  to stdout so you can pipe it; the warnings go to stderr.
55
55
 
@@ -106,7 +106,7 @@ Usage:
106
106
  The secret is printed ONCE, on stdout, inside the JSON. Pipe it:
107
107
  run402 credentials issue --kind service --name ci | jq -r .secret
108
108
 
109
- Requires owner membership on the project's org plus a fresh step-up. A delegate
109
+ Requires owner membership on the project's org plus a fresh step-up. A grant key
110
110
  can NEVER do this; use 'run402 credentials token' instead.
111
111
  `,
112
112
  list: `run402 credentials list — list a project's credentials
@@ -157,7 +157,7 @@ Usage:
157
157
  run402 credentials token [--project <project_id>] [--kind <anon|service>]
158
158
 
159
159
  The cold-restart recovery path, and the ONE credential call an agent can make
160
- with no human present: a delegate is accepted here. There is no step-up because
160
+ with no human present: a grant key is accepted here. There is no step-up because
161
161
  there is nobody to prompt, and what you get back expires, so it cannot become a
162
162
  durable root. Defaults to --kind service.
163
163
  `,
package/lib/deploy-v2.mjs CHANGED
@@ -44,7 +44,7 @@ import {
44
44
  import { getSdk } from "./sdk.mjs";
45
45
  import { reportSdkError, fail } from "./sdk-errors.mjs";
46
46
  import { API, walletAuthHeaders, getActiveProjectId, resolveProjectId, isCoreApiTarget, updateProject } from "./config.mjs";
47
- import { delegateTokenFromEnv } from "#sdk/node";
47
+ import { grantKeyFromEnv } from "#sdk/node";
48
48
  import { flagValue, normalizeArgv } from "./argparse.mjs";
49
49
  import { loadLiveControlPlaneSession } from "../core-dist/control-plane-session.js";
50
50
  import { withAutoApprove } from "./sign-in.mjs";
@@ -486,10 +486,10 @@ async function rehearseCmd(rawArgs) {
486
486
  fail({ code: "BAD_USAGE", message: "--teardown must be one of: on_pass, keep, always", details: { flag: "--teardown", value: teardown } });
487
487
  }
488
488
  const project = flagValue(args, "--project") ?? undefined;
489
- // A delegate is a complete deploy credential and the gateway explicitly
489
+ // A grant key is a complete deploy credential and the gateway explicitly
490
490
  // supports rehearsing with one (the route rejects only CI sessions).
491
491
  // Rehearsal is the SAFE path; never make it the harder one.
492
- if (!isCoreApiTarget() && !loadLiveControlPlaneSession() && !delegateTokenFromEnv()) {
492
+ if (!isCoreApiTarget() && !loadLiveControlPlaneSession() && !grantKeyFromEnv()) {
493
493
  walletAuthHeaders(`/apply/v1/plans/${givenPlanId ?? "_"}/rehearse`);
494
494
  }
495
495
  const sdk = getSdk();
@@ -723,9 +723,9 @@ async function promoteCmd(args) {
723
723
 
724
724
  // Preserve the aggressive early-exit when no local wallet is configured
725
725
  // — same as apply.
726
- // A delegate holds `deploy` and the gateway accepts it on this route; refusing
726
+ // A grant key holds `deploy` and the gateway accepts it on this route; refusing
727
727
  // locally would tell a wallet-less holder to run `run402 init` (see 4.11.2).
728
- if (!delegateTokenFromEnv()) walletAuthHeaders("/apply/v1/releases");
728
+ if (!grantKeyFromEnv()) walletAuthHeaders("/apply/v1/releases");
729
729
 
730
730
  try {
731
731
  // Call the engine directly (matches the pattern used by apply / resume
@@ -1295,20 +1295,20 @@ async function deployCmd(args) {
1295
1295
 
1296
1296
 
1297
1297
  let sdkOpts;
1298
- const delegateToken = delegateTokenFromEnv();
1298
+ const grantKey = grantKeyFromEnv();
1299
1299
  if (useGithubActionsOidc) {
1300
1300
  sdkOpts = {
1301
1301
  credentials: githubActionsCredentials({ projectId: releaseSpec.project_id, apiBase: API }),
1302
1302
  disablePaidFetch: true,
1303
1303
  };
1304
- } else if (delegateToken) {
1305
- // A delegate is a complete, self-contained deploy credential: the owner
1304
+ } else if (grantKey) {
1305
+ // A grant key is a complete, self-contained deploy credential: the owner
1306
1306
  // minted it with their wallet and handed it over, so this process needs no
1307
1307
  // wallet of its own. Skipping the guard is the point — an agent that
1308
1308
  // lost its local state (or never had a wallet) can still deploy. Paid fetch
1309
- // is disabled for the same reason it is under CI: a delegate authorizes
1309
+ // is disabled for the same reason it is under CI: a grant key authorizes
1310
1310
  // deploys, not spending.
1311
- sdkOpts = { delegateToken, disablePaidFetch: true };
1311
+ sdkOpts = { grantKey, disablePaidFetch: true };
1312
1312
  } else if (!isCoreApiTarget() && !loadLiveControlPlaneSession()) {
1313
1313
  // Aggressive early exit when no local wallet is configured — unless a
1314
1314
  // wallet-less person is deploying via their sign-in session
@@ -1766,9 +1766,9 @@ async function resumeCmd(args) {
1766
1766
  emitDeployUpdateNotice("resume", args, { quiet: opts.quiet });
1767
1767
  const project = resolveProjectId(opts.project);
1768
1768
 
1769
- // A delegate holds `deploy` and the gateway accepts it on this route; refusing
1769
+ // A grant key holds `deploy` and the gateway accepts it on this route; refusing
1770
1770
  // locally would tell a wallet-less holder to run `run402 init` (see 4.11.2).
1771
- if (!delegateTokenFromEnv()) walletAuthHeaders("/apply/v1/operations");
1771
+ if (!grantKeyFromEnv()) walletAuthHeaders("/apply/v1/operations");
1772
1772
 
1773
1773
  try {
1774
1774
  const result = await getSdk({ disablePaidFetch: true })._applyEngine.resume(opts.operationId, {
@@ -1794,9 +1794,9 @@ async function statusCmd(args) {
1794
1794
  missing: "Missing <operation_id>.",
1795
1795
  });
1796
1796
  const project = resolveProjectId(parsed.flags["--project"] ?? null);
1797
- // A delegate holds `deploy` and the gateway accepts it on this route; refusing
1797
+ // A grant key holds `deploy` and the gateway accepts it on this route; refusing
1798
1798
  // locally would tell a wallet-less holder to run `run402 init` (see 4.11.2).
1799
- if (!delegateTokenFromEnv()) walletAuthHeaders("/apply/v1/operations");
1799
+ if (!grantKeyFromEnv()) walletAuthHeaders("/apply/v1/operations");
1800
1800
 
1801
1801
  try {
1802
1802
  const result = await getSdk()._applyEngine.status(operationId, { project });
@@ -1822,24 +1822,24 @@ async function listCmd(args) {
1822
1822
  };
1823
1823
 
1824
1824
  const project = resolveProjectId(opts.project);
1825
- // NOT ungated for delegates, deliberately: /apply/v1/operations (list) is
1825
+ // NOT ungated for grant keys, deliberately: /apply/v1/operations (list) is
1826
1826
  // `apikeyAuth` only — unlike get/events/resume/promote, which accept a
1827
- // delegate bearer. Listing every operation on a project is broader than
1827
+ // grant-key bearer. Listing every operation on a project is broader than
1828
1828
  // the per-operation reads a deploy credential is scoped to. If this is
1829
1829
  // ever widened, widen the ROUTE first, then this guard.
1830
1830
  //
1831
1831
  // The refusal is correct; the REMEDY must still be honest. Falling through
1832
- // to NO_WALLET would tell a delegate holder to run `run402 init`, which
1832
+ // to NO_WALLET would tell a grant-key holder to run `run402 init`, which
1833
1833
  // is wrong for a credential that is wallet-less by design — the same
1834
1834
  // misleading-remedy shape removed from the payment path in 4.11.2.
1835
- if (delegateTokenFromEnv()) {
1835
+ if (grantKeyFromEnv()) {
1836
1836
  fail({
1837
- code: "DELEGATE_SCOPE_INSUFFICIENT",
1838
- message: "Listing deploy operations is not available to a delegate.",
1839
- hint: "Use `run402 deploy status <operation_id>`, `deploy events <operation_id>` or `deploy verify <operation_id>` for a specific operation, which a delegate CAN read. A full listing needs the project apikey or the owner wallet.",
1840
- details: { command: "deploy list", credential: "delegate", route: "GET /apply/v1/operations" },
1837
+ code: "GRANT_KEY_SCOPE_INSUFFICIENT",
1838
+ message: "Listing deploy operations is not available to a grant key.",
1839
+ hint: "Use `run402 deploy status <operation_id>`, `deploy events <operation_id>` or `deploy verify <operation_id>` for a specific operation, which a grant key CAN read. A full listing needs the project apikey or the owner wallet.",
1840
+ details: { command: "deploy list", credential: "grant_key", route: "GET /apply/v1/operations" },
1841
1841
  next_actions: [
1842
- { type: "run_command", command: "run402 deploy status <operation_id>", why: "Per-operation reads are within a delegate's deploy scope." },
1842
+ { type: "run_command", command: "run402 deploy status <operation_id>", why: "Per-operation reads are within a grant key's deploy scope." },
1843
1843
  ],
1844
1844
  });
1845
1845
  }
@@ -1870,9 +1870,9 @@ async function eventsCmd(args) {
1870
1870
  const opts = { operationId, project: parsed.flags["--project"] ?? null };
1871
1871
 
1872
1872
  const project = resolveProjectId(opts.project);
1873
- // A delegate holds `deploy` and the gateway accepts it on this route; refusing
1873
+ // A grant key holds `deploy` and the gateway accepts it on this route; refusing
1874
1874
  // locally would tell a wallet-less holder to run `run402 init` (see 4.11.2).
1875
- if (!delegateTokenFromEnv()) walletAuthHeaders("/apply/v1/operations");
1875
+ if (!grantKeyFromEnv()) walletAuthHeaders("/apply/v1/operations");
1876
1876
 
1877
1877
  try {
1878
1878
  const result = await getSdk()._applyEngine.events(opts.operationId, { project });
@@ -1916,9 +1916,9 @@ async function verifyCmd(args) {
1916
1916
  ? 60
1917
1917
  : parsePositiveInt(parsed.flags["--timeout"], "--timeout");
1918
1918
 
1919
- // A delegate holds `deploy` and the gateway accepts it on this route; refusing
1919
+ // A grant key holds `deploy` and the gateway accepts it on this route; refusing
1920
1920
  // locally would tell a wallet-less holder to run `run402 init` (see 4.11.2).
1921
- if (!delegateTokenFromEnv()) walletAuthHeaders("/apply/v1/operations");
1921
+ if (!grantKeyFromEnv()) walletAuthHeaders("/apply/v1/operations");
1922
1922
 
1923
1923
  try {
1924
1924
  let result;