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
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  Command-line interface for [Run402](https://run402.com) — provision Postgres databases, deploy static sites, run Node 22 serverless functions, host content-addressed CDN assets, send email, sign on-chain. Paid autonomously with x402 (USDC on Base) or MPP (pathUSD on Tempo, or sats over Bitcoin Lightning). **Prototype tier is free on testnet.**
6
6
 
7
- The CLI lets an agent act as its own first-class Run402 principal rather than borrowing a human account. Identity records who invoked an action; organization roles, grants, delegates, freshness, and spend policy determine what that principal may do. People remain first-class owners and members without having to run the CLI themselves.
7
+ The CLI lets an agent act as its own first-class Run402 principal rather than borrowing a human account. Identity records who invoked an action; organization roles, grants, grant keys, freshness, and spend policy determine what that principal may do. People remain first-class owners and members without having to run the CLI themselves.
8
8
 
9
9
  For the full CLI reference (every flag, every subcommand) start at **<https://docs.run402.com/llms-cli.txt>** — the index holds the first-deploy contract and links one fetchable `/llms-cli-<slice>.txt` per topic (deploy, commands, repos, orgs, functions, assets, ops, errors, frontend, platform); <https://docs.run402.com/llms-cli-full.txt> is the whole reference as one document.
10
10
 
@@ -76,7 +76,7 @@ run402 repos list --org org_1a2b3c
76
76
  run402 repos delete --project prj_xyz --force # refuses without --force while the vault holds generations
77
77
  ```
78
78
 
79
- A hosted git remote, encrypted before it leaves the machine — no deploy, no manifest, no app. `origin` is claimed additively — an existing `origin` is never touched, the run402 remote falls back to `run402` instead. A directory inside another repository is never scaffolded into that repository: the skip carries a `create_nested_repo` next action, `--nested` makes it its own nested repository (one line appended to the enclosing repository's local `.git/info/exclude`, nothing else touched), and `create` prints a `git push` next action only for a remote it actually added. Every mutating `repos` verb (`create`, `rename`, `delete`, `capture`, `policy`, `mirror`, `gc`, `handoff`, `resume`, `invite`, `join`) is CLI/OpenClaw-only by design — no MCP tool exists or will exist for them (one-shot recovery receipts, immutable generations, irreversible delete, single-use bearer keys). Three READ-ONLY tools do exist — `repos_view`, `repos_list_heads`, `repos_fsck` — teaching only `repos` spellings. See `run402 repos --help` for the full tiered surface (common: `create`/`view`/`list`; occasional: `capture`/`mirror`/`recover`/`handoff`/`resume`/`invite`/`join`; lifecycle: `rename`/`delete`; maintenance: `fsck`/`gc`/`access`/`policy`), and the CLI reference's `repos` section for the terminal-loss statement and the progressive backup warning.
79
+ A hosted git remote, encrypted before it leaves the machine — no deploy, no manifest, no app. `origin` is claimed additively — an existing `origin` is never touched, the run402 remote falls back to `run402` instead. A directory inside another repository is never scaffolded into that repository: the skip carries a `create_nested_repo` next action, `--nested` makes it its own nested repository (one line appended to the enclosing repository's local `.git/info/exclude`, nothing else touched), and `create` prints a `git push` next action only for a remote it actually added. From MCP, the vault is reached through a `run` snippet against `r.repos`; the verbs that mint or redeem a one-time secret (`handoff`/`invite` keys, `resume`/`join`) refuse there with `SECRET_REQUIRES_CLI`, naming the `run402 repos` command to hand the person. See `run402 repos --help` for the full tiered surface (common: `create`/`view`/`list`; occasional: `capture`/`mirror`/`recover`/`handoff`/`resume`/`invite`/`join`; lifecycle: `rename`/`delete`; maintenance: `fsck`/`gc`/`access`/`policy`), and the CLI reference's `repos` section for the terminal-loss statement and the progressive backup warning.
80
80
 
81
81
  **Handoff / resume.** `run402 repos handoff [--note-file <path>]` captures the actual working tree (staged/unstaged/untracked, like `git stash push -u`) into the vault and mints a single-use bearer key (`kgh1_…`, printed to stdout exactly once); `run402 repos resume <kgh1_…>` claims it on another machine, clones fresh, and reapplies the exact dirty state with `git stash apply --index`. No shared keystore, no shared wallet — the key is the whole handoff. On a wallet with no active tier, `resume` first folds the same cold-start chain `create` does (wallet → faucet → one x402 prototype payment); `--no-init` opts out, and the claim itself never waits on it. Sensitive untracked files (`.env`, `*.pem`, SSH/AWS/GPG dirs, …) are excluded from capture by default (`--include-sensitive <glob>` re-admits one). See the reference `run402.com/llms-cli.txt` for the full note-schema and flag reference.
82
82
 
@@ -121,7 +121,7 @@ This links two separately held public identities through fresh signatures; it ne
121
121
 
122
122
  ### Buzz community control plane
123
123
 
124
- `run402 buzz status` reports skill installation, human-adoption offers/adoptions, community installation, and this agent's enrollment independently, and safely reports `supported: false` against an older gateway. The canonical ownership workflow is `buzz adopt offer --org … --identity-link …`: it capability-checks before mutation and returns a normal durable HTTPS handoff. Poll with `buzz adopt offer show <buzzhao_id>` and cancel with `buzz adopt offer cancel <buzzhao_id>`. The raw challenge command is explicitly advanced as `buzz adopt direct …`; direct completion/cancellation remain `buzz adopt complete|cancel`. Other goal workflows are `buzz install` and `buzz enroll`; decisions are `buzz install activate|update|revoke` and `buzz approve|deny|revoke`. `buzz install discover --community <buzz:community:host>` lists Run402-owned active descriptors without authentication. MCP intentionally has no signing/passkey mutation and only renders exact HTTPS/CLI handoffs. All commands print JSON to stdout, advice to stderr, have zero spend impact, and never accept Nostr/wallet secrets, session material, service keys, delegates, or payment credentials. Failure JSON preserves the gateway's code-specific `next_actions`, exact repair `field`, and retry safety; never replace it with a generic edit-and-retry. See the [Fizz/Honey examples](../buzz/references/community-control-plane.md).
124
+ `run402 buzz status` reports skill installation, human-adoption offers/adoptions, community installation, and this agent's enrollment independently, and safely reports `supported: false` against an older gateway. The canonical ownership workflow is `buzz adopt offer --org … --identity-link …`: it capability-checks before mutation and returns a normal durable HTTPS handoff. Poll with `buzz adopt offer show <buzzhao_id>` and cancel with `buzz adopt offer cancel <buzzhao_id>`. The raw challenge command is explicitly advanced as `buzz adopt direct …`; direct completion/cancellation remain `buzz adopt complete|cancel`. Other goal workflows are `buzz install` and `buzz enroll`; decisions are `buzz install activate|update|revoke` and `buzz approve|deny|revoke`. `buzz install discover --community <buzz:community:host>` lists Run402-owned active descriptors without authentication. MCP intentionally has no signing/passkey mutation and only renders exact HTTPS/CLI handoffs. All commands print JSON to stdout, advice to stderr, have zero spend impact, and never accept Nostr/wallet secrets, session material, service keys, grant keys, or payment credentials. Failure JSON preserves the gateway's code-specific `next_actions`, exact repair `field`, and retry safety; never replace it with a generic edit-and-retry. See the [Fizz/Honey examples](../buzz/references/community-control-plane.md).
125
125
 
126
126
  ### Buy from an x402 URL
127
127
 
package/cli.mjs CHANGED
@@ -70,8 +70,7 @@ COORDINATE — work alongside other agents and humans
70
70
 
71
71
  AUTHORITY — who may act, and with what credential
72
72
  credentials Manage local credential material (project-keys)
73
- delegates Scoped deploy credentials for agents (create, list, revoke, rotate)
74
- grants Per-project capability grants for agent/CI principals (create, revoke)
73
+ grants Project grants and grant keys for agents (create, list, revoke, revoke-key, rotate-key)
75
74
  orgs Organizations, members, invites & audit (list, get, members, invite, audit)
76
75
  identity Public proof-backed external agent identity links
77
76
  auth Manage project user authentication (magic link, passwords, settings)
@@ -285,11 +284,6 @@ switch (cmd) {
285
284
  await run(sub, rest);
286
285
  break;
287
286
  }
288
- case "delegates": {
289
- const { run } = await import("./lib/delegates.mjs");
290
- await run(sub, rest);
291
- break;
292
- }
293
287
  case "events": {
294
288
  const { run } = await import("./lib/events.mjs");
295
289
  await run(sub, rest);
@@ -22,7 +22,7 @@
22
22
  * Unknown keys are ignored on purpose: that is what makes an older client
23
23
  * forward-compatible with a binding file written by a newer one.
24
24
  */
25
- import { readFileSync } from "node:fs";
25
+ import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
26
26
  import { dirname, join, resolve } from "node:path";
27
27
  /** The committed binding file. Safe to check in — it names, never authorizes. */
28
28
  export const BINDING_FILE = ".run402.json";
@@ -80,4 +80,31 @@ export function readBindingFile(dir = process.cwd()) {
80
80
  return {};
81
81
  }
82
82
  }
83
+ /**
84
+ * MERGE keys into a directory's committed binding file. A `null` (or
85
+ * `undefined`) value removes its key; a file left with no keys is deleted
86
+ * rather than committed empty.
87
+ *
88
+ * The file is shared by tiers (`wallet` from `wallets bind`, `org`/`room` from
89
+ * `orgs bind`) and unknown keys are preserved, so one tier can never clobber
90
+ * another's binding.
91
+ */
92
+ export function updateBindingFile(dir, patch) {
93
+ const file = bindingFilePath(dir);
94
+ const next = { ...readBindingFile(dir) };
95
+ for (const [k, v] of Object.entries(patch)) {
96
+ if (v === null || v === undefined)
97
+ delete next[k];
98
+ else
99
+ next[k] = v;
100
+ }
101
+ if (Object.keys(next).length === 0) {
102
+ const existed = existsSync(file);
103
+ if (existed)
104
+ rmSync(file, { force: true });
105
+ return { file, contents: null, removed: existed };
106
+ }
107
+ writeFileSync(file, JSON.stringify(next, null, 2) + "\n");
108
+ return { file, contents: next, removed: false };
109
+ }
83
110
  //# sourceMappingURL=binding-file.js.map
@@ -22,9 +22,9 @@ const PRIVATE_KEY_RE = /^0x[a-fA-F0-9]{64}$/;
22
22
  * - `core/src/wallet-auth.ts` passes a malformed `privateKey` to
23
23
  * `@noble/curves` which throws "expected 32 bytes, got N".
24
24
  *
25
- * The CLI's `cli/lib/config.mjs:readWallet()` wrapper and the MCP
26
- * `src/tools/{status,init}.ts` callers translate the throw into their own
27
- * structured envelopes (`code: BAD_WALLET_FILE`).
25
+ * The CLI's `cli/lib/config.mjs:readWallet()` wrapper and the Node SDK's
26
+ * `readLocalWallet()` (`sdk/src/node/wallets.ts`) translate the throw into
27
+ * their own structured envelopes (`code: BAD_WALLET_FILE`).
28
28
  */
29
29
  /**
30
30
  * If a wallet file is readable by group or other (any of the low 0o077
package/lib/auth.mjs CHANGED
@@ -710,8 +710,7 @@ function scaffoldIdent(args, flag, def) {
710
710
 
711
711
  // Pure, offline generator — no SDK / network / project. Emits the conventional
712
712
  // role-table migration, the matching requireRole gate snippet, and a
713
- // first-operator bootstrap. (Keep in sync with the MCP `scaffold_roles` tool in
714
- // src/tools/scaffold-roles.ts — same artifacts, different presentation.)
713
+ // first-operator bootstrap.
715
714
  function scaffoldRoles(args) {
716
715
  const table = scaffoldIdent(args, "--table", "app_roles");
717
716
  const userCol = scaffoldIdent(args, "--user-col", "user_id");