@wardby/cli 0.2.1 → 0.3.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 (407) hide show
  1. package/.env.example +34 -4
  2. package/README.md +41 -4
  3. package/dist/claude-coding-worker/driver.d.ts +6 -1
  4. package/dist/claude-coding-worker/driver.js +27 -1
  5. package/dist/claude-coding-worker/main.js +2 -0
  6. package/dist/claude-coding-worker/tool-socket.d.ts +9 -0
  7. package/dist/claude-coding-worker/tool-socket.js +26 -0
  8. package/dist/cli-help.d.ts +1 -1
  9. package/dist/cli-help.js +13 -4
  10. package/dist/cli.d.ts +1 -1
  11. package/dist/cli.js +219 -29
  12. package/dist/coding/collect-exclude.d.ts +25 -0
  13. package/dist/coding/collect-exclude.js +76 -0
  14. package/dist/coding/profile.d.ts +67 -22
  15. package/dist/coding/profile.js +58 -25
  16. package/dist/coding/protected-path-wording.d.ts +24 -0
  17. package/dist/coding/protected-path-wording.js +55 -0
  18. package/dist/coding/protected-paths.d.ts +31 -0
  19. package/dist/coding/protected-paths.js +48 -0
  20. package/dist/coding/protocol.d.ts +75 -4
  21. package/dist/coding/protocol.js +107 -7
  22. package/dist/coding/registry/adapters.d.ts +2 -0
  23. package/dist/coding/registry/adapters.js +9 -0
  24. package/dist/coding/registry/allowlist.d.ts +9 -0
  25. package/dist/coding/registry/allowlist.js +28 -0
  26. package/dist/coding/registry/json-scan.d.ts +55 -0
  27. package/dist/coding/registry/json-scan.js +191 -0
  28. package/dist/coding/registry/lockfiles.d.ts +6 -0
  29. package/dist/coding/registry/lockfiles.js +89 -0
  30. package/dist/coding/registry/npm-lockfile.d.ts +9 -0
  31. package/dist/coding/registry/npm-lockfile.js +73 -0
  32. package/dist/coding/registry/npm-plan.d.ts +29 -0
  33. package/dist/coding/registry/npm-plan.js +289 -0
  34. package/dist/coding/registry/npm.d.ts +7 -0
  35. package/dist/coding/registry/npm.js +252 -0
  36. package/dist/coding/registry/pypi.d.ts +4 -0
  37. package/dist/coding/registry/pypi.js +210 -0
  38. package/dist/coding/registry/report.d.ts +37 -0
  39. package/dist/coding/registry/report.js +31 -0
  40. package/dist/coding/registry/token.d.ts +4 -0
  41. package/dist/coding/registry/token.js +7 -0
  42. package/dist/coding/registry/types.d.ts +286 -0
  43. package/dist/coding/registry/types.js +19 -0
  44. package/dist/coding/registry/worker-config.d.ts +14 -0
  45. package/dist/coding/registry/worker-config.js +31 -0
  46. package/dist/coding/services/builtins.d.ts +22 -0
  47. package/dist/coding/services/builtins.js +85 -0
  48. package/dist/coding/services/catalog.d.ts +443 -0
  49. package/dist/coding/services/catalog.js +159 -0
  50. package/dist/coding/services/declaration.d.ts +11 -0
  51. package/dist/coding/services/declaration.js +114 -0
  52. package/dist/coding/services/note.d.ts +8 -0
  53. package/dist/coding/services/note.js +15 -0
  54. package/dist/coding/services/resolve.d.ts +25 -0
  55. package/dist/coding/services/resolve.js +50 -0
  56. package/dist/coding/services/wording.d.ts +25 -0
  57. package/dist/coding/services/wording.js +70 -0
  58. package/dist/coding-proxy/main.js +24 -4
  59. package/dist/coding-worker/artifact.d.ts +6 -0
  60. package/dist/coding-worker/debug-trace.d.ts +37 -0
  61. package/dist/coding-worker/debug-trace.js +117 -0
  62. package/dist/coding-worker/driver.d.ts +13 -1
  63. package/dist/coding-worker/driver.js +102 -13
  64. package/dist/coding-worker/errors.js +8 -0
  65. package/dist/coding-worker/main.js +10 -2
  66. package/dist/coding-worker/sdk.d.ts +2 -2
  67. package/dist/coding-worker/sdk.js +7 -2
  68. package/dist/coding-worker/types.d.ts +3 -0
  69. package/dist/config/providers.d.ts +41 -0
  70. package/dist/config/providers.js +66 -0
  71. package/dist/core/budget-groups.d.ts +108 -5
  72. package/dist/core/budget-groups.js +125 -19
  73. package/dist/core/budget-wording.d.ts +22 -0
  74. package/dist/core/budget-wording.js +55 -0
  75. package/dist/core/datastores.js +18 -2
  76. package/dist/core/db.d.ts +5 -1
  77. package/dist/core/db.js +8 -2
  78. package/dist/core/dispatch.d.ts +33 -6
  79. package/dist/core/dispatch.js +260 -43
  80. package/dist/core/engine-native.js +27 -10
  81. package/dist/core/grants.d.ts +86 -0
  82. package/dist/core/grants.js +126 -0
  83. package/dist/core/host-events.d.ts +49 -0
  84. package/dist/core/host-events.js +257 -0
  85. package/dist/core/host-identity-links.d.ts +54 -0
  86. package/dist/core/host-identity-links.js +189 -0
  87. package/dist/core/host-status.d.ts +61 -0
  88. package/dist/core/host-status.js +211 -0
  89. package/dist/core/in-flight-runs.d.ts +8 -0
  90. package/dist/core/in-flight-runs.js +56 -0
  91. package/dist/core/provider-wording.d.ts +12 -0
  92. package/dist/core/provider-wording.js +44 -0
  93. package/dist/core/reconciler.d.ts +38 -2
  94. package/dist/core/reconciler.js +86 -2
  95. package/dist/core/repo-access.d.ts +99 -0
  96. package/dist/core/repo-access.js +136 -0
  97. package/dist/core/review-host-checks.d.ts +11 -0
  98. package/dist/core/review-host-checks.js +41 -0
  99. package/dist/core/review-host-tools.d.ts +47 -0
  100. package/dist/core/review-host-tools.js +347 -0
  101. package/dist/core/run-heartbeat.d.ts +27 -0
  102. package/dist/core/run-heartbeat.js +54 -0
  103. package/dist/core/runner.d.ts +30 -8
  104. package/dist/core/runner.js +237 -40
  105. package/dist/core/secrets.d.ts +11 -2
  106. package/dist/core/secrets.js +25 -6
  107. package/dist/core/subagent-memory-tools.d.ts +1 -1
  108. package/dist/core/subagent-memory-tools.js +16 -3
  109. package/dist/core/tool-admin.d.ts +81 -0
  110. package/dist/core/tool-admin.js +129 -0
  111. package/dist/core/tool-names.d.ts +42 -0
  112. package/dist/core/tool-names.js +64 -0
  113. package/dist/core/untrusted-content.d.ts +32 -0
  114. package/dist/core/untrusted-content.js +72 -0
  115. package/dist/core/webhooks.d.ts +8 -1
  116. package/dist/core/webhooks.js +23 -2
  117. package/dist/generated/prisma/browser.d.ts +100 -0
  118. package/dist/generated/prisma/client.d.ts +100 -0
  119. package/dist/generated/prisma/commonInputTypes.d.ts +30 -0
  120. package/dist/generated/prisma/enums.d.ts +6 -0
  121. package/dist/generated/prisma/enums.js +6 -1
  122. package/dist/generated/prisma/internal/class.d.ts +143 -0
  123. package/dist/generated/prisma/internal/class.js +4 -4
  124. package/dist/generated/prisma/internal/prismaNamespace.d.ts +1746 -577
  125. package/dist/generated/prisma/internal/prismaNamespace.js +179 -6
  126. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +186 -0
  127. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +179 -6
  128. package/dist/generated/prisma/models/Agent.d.ts +294 -1
  129. package/dist/generated/prisma/models/AgentRepository.d.ts +1425 -0
  130. package/dist/generated/prisma/models/AgentRepository.js +1 -0
  131. package/dist/generated/prisma/models/AgentTool.d.ts +95 -1
  132. package/dist/generated/prisma/models/AuthUser.d.ts +56 -1
  133. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +258 -7
  134. package/dist/generated/prisma/models/CodingProxySession.d.ts +123 -2
  135. package/dist/generated/prisma/models/CodingRun.d.ts +1276 -95
  136. package/dist/generated/prisma/models/CodingService.d.ts +1348 -0
  137. package/dist/generated/prisma/models/CodingService.js +1 -0
  138. package/dist/generated/prisma/models/HostEventDelivery.d.ts +946 -0
  139. package/dist/generated/prisma/models/HostEventDelivery.js +1 -0
  140. package/dist/generated/prisma/models/HostIdentity.d.ts +1232 -0
  141. package/dist/generated/prisma/models/HostIdentity.js +1 -0
  142. package/dist/generated/prisma/models/HostIdentityLinkRequest.d.ts +1473 -0
  143. package/dist/generated/prisma/models/HostIdentityLinkRequest.js +1 -0
  144. package/dist/generated/prisma/models/Principal.d.ts +455 -0
  145. package/dist/generated/prisma/models/RegistryAllowance.d.ts +1148 -0
  146. package/dist/generated/prisma/models/RegistryAllowance.js +1 -0
  147. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +1219 -0
  148. package/dist/generated/prisma/models/RegistryApprovedVersion.js +1 -0
  149. package/dist/generated/prisma/models/RegistryFetch.d.ts +1428 -0
  150. package/dist/generated/prisma/models/RegistryFetch.js +1 -0
  151. package/dist/generated/prisma/models/RegistryPlanRefusal.d.ts +1294 -0
  152. package/dist/generated/prisma/models/RegistryPlanRefusal.js +1 -0
  153. package/dist/generated/prisma/models/RegistryVersionFact.d.ts +1085 -0
  154. package/dist/generated/prisma/models/RegistryVersionFact.js +1 -0
  155. package/dist/generated/prisma/models/ResourceGrant.d.ts +1437 -0
  156. package/dist/generated/prisma/models/ResourceGrant.js +1 -0
  157. package/dist/generated/prisma/models/Run.d.ts +389 -1
  158. package/dist/generated/prisma/models/RunHostCheck.d.ts +1239 -0
  159. package/dist/generated/prisma/models/RunHostCheck.js +1 -0
  160. package/dist/generated/prisma/models/RunHostStatus.d.ts +1315 -0
  161. package/dist/generated/prisma/models/RunHostStatus.js +1 -0
  162. package/dist/generated/prisma/models/Tool.d.ts +15 -3
  163. package/dist/generated/prisma/models.d.ts +13 -0
  164. package/dist/help/build.d.ts +1 -0
  165. package/dist/help/build.js +9 -0
  166. package/dist/help/catalog.d.ts +24 -0
  167. package/dist/help/catalog.js +160 -0
  168. package/dist/help/cli.d.ts +2 -0
  169. package/dist/help/cli.js +65 -0
  170. package/dist/help/runtime.d.ts +3 -0
  171. package/dist/help/runtime.js +44 -0
  172. package/dist/help/search.d.ts +9 -0
  173. package/dist/help/search.js +104 -0
  174. package/dist/help-index.json +660 -0
  175. package/dist/import/cli-args.js +3 -2
  176. package/dist/import/create.d.ts +5 -0
  177. package/dist/import/create.js +67 -13
  178. package/dist/import/index.js +19 -9
  179. package/dist/import/neutral-schema.d.ts +11 -11
  180. package/dist/mcp/auth/access.d.ts +70 -0
  181. package/dist/mcp/auth/access.js +58 -0
  182. package/dist/mcp/auth/grants-cli.d.ts +149 -0
  183. package/dist/mcp/auth/grants-cli.js +518 -0
  184. package/dist/mcp/auth/host-account-cli.d.ts +2 -0
  185. package/dist/mcp/auth/host-account-cli.js +47 -0
  186. package/dist/mcp/auth/ownership.d.ts +26 -52
  187. package/dist/mcp/auth/ownership.js +19 -14
  188. package/dist/mcp/auth/repo-authorization.d.ts +22 -0
  189. package/dist/mcp/auth/repo-authorization.js +51 -0
  190. package/dist/mcp/auth/resource-server.d.ts +31 -2
  191. package/dist/mcp/auth/resource-server.js +84 -3
  192. package/dist/mcp/auth/self-hosted/browser.js +2 -2
  193. package/dist/mcp/auth/self-hosted/cli.js +47 -13
  194. package/dist/mcp/auth/self-hosted/credentials.d.ts +20 -2
  195. package/dist/mcp/auth/self-hosted/credentials.js +62 -4
  196. package/dist/mcp/auth/self-hosted/session.d.ts +2 -1
  197. package/dist/mcp/context.d.ts +27 -1
  198. package/dist/mcp/errors.d.ts +25 -6
  199. package/dist/mcp/errors.js +98 -0
  200. package/dist/mcp/host-events/github-ingress.d.ts +36 -0
  201. package/dist/mcp/host-events/github-ingress.js +92 -0
  202. package/dist/mcp/host-events/github-user-callback.d.ts +18 -0
  203. package/dist/mcp/host-events/github-user-callback.js +50 -0
  204. package/dist/mcp/index.d.ts +8 -1
  205. package/dist/mcp/index.js +106 -16
  206. package/dist/mcp/server.js +27 -9
  207. package/dist/mcp/tools/agents.js +446 -48
  208. package/dist/mcp/tools/budget-groups.js +3 -3
  209. package/dist/mcp/tools/datastore.js +22 -15
  210. package/dist/mcp/tools/grants.d.ts +2 -0
  211. package/dist/mcp/tools/grants.js +239 -0
  212. package/dist/mcp/tools/help.d.ts +5 -0
  213. package/dist/mcp/tools/help.js +67 -0
  214. package/dist/mcp/tools/host-accounts.d.ts +2 -0
  215. package/dist/mcp/tools/host-accounts.js +114 -0
  216. package/dist/mcp/tools/memory.d.ts +7 -1
  217. package/dist/mcp/tools/memory.js +5 -5
  218. package/dist/mcp/tools/repositories.d.ts +2 -0
  219. package/dist/mcp/tools/repositories.js +181 -0
  220. package/dist/mcp/tools/runs.d.ts +6 -0
  221. package/dist/mcp/tools/runs.js +60 -6
  222. package/dist/mcp/tools/scheduling.js +3 -6
  223. package/dist/mcp/tools/secrets.js +18 -6
  224. package/dist/mcp/tools/services.d.ts +2 -0
  225. package/dist/mcp/tools/services.js +222 -0
  226. package/dist/mcp/tools/subagents.js +52 -16
  227. package/dist/mcp/tools/tools.d.ts +41 -0
  228. package/dist/mcp/tools/tools.js +201 -40
  229. package/dist/mcp/tools/trigger.js +36 -6
  230. package/dist/mcp/tools/webhooks.js +15 -4
  231. package/dist/mcp/transport/streamable-http.d.ts +10 -0
  232. package/dist/mcp/transport/streamable-http.js +32 -2
  233. package/dist/providers/auth/delegating.d.ts +19 -0
  234. package/dist/providers/auth/delegating.js +71 -0
  235. package/dist/providers/auth/index.d.ts +2 -0
  236. package/dist/providers/auth/index.js +11 -0
  237. package/dist/providers/auth/self-hosted.d.ts +2 -1
  238. package/dist/providers/auth/self-hosted.js +16 -4
  239. package/dist/providers/auth/types.d.ts +6 -0
  240. package/dist/providers/coding-proxy/memory-ledger.d.ts +3 -0
  241. package/dist/providers/coding-proxy/memory-ledger.js +21 -2
  242. package/dist/providers/coding-proxy/metering.d.ts +4 -0
  243. package/dist/providers/coding-proxy/metering.js +28 -2
  244. package/dist/providers/coding-proxy/prisma-ledger.d.ts +17 -0
  245. package/dist/providers/coding-proxy/prisma-ledger.js +50 -5
  246. package/dist/providers/coding-proxy/proxy.d.ts +13 -0
  247. package/dist/providers/coding-proxy/proxy.js +479 -18
  248. package/dist/providers/coding-proxy/registry/audit.d.ts +131 -0
  249. package/dist/providers/coding-proxy/registry/audit.js +380 -0
  250. package/dist/providers/coding-proxy/registry/bounded-fetch.d.ts +16 -0
  251. package/dist/providers/coding-proxy/registry/bounded-fetch.js +77 -0
  252. package/dist/providers/coding-proxy/registry/plan.d.ts +58 -0
  253. package/dist/providers/coding-proxy/registry/plan.js +304 -0
  254. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +34 -0
  255. package/dist/providers/coding-proxy/registry/prisma-store.js +151 -0
  256. package/dist/providers/coding-proxy/registry/service.d.ts +213 -0
  257. package/dist/providers/coding-proxy/registry/service.js +1137 -0
  258. package/dist/providers/coding-proxy/registry/store.d.ts +127 -0
  259. package/dist/providers/coding-proxy/registry/store.js +70 -0
  260. package/dist/providers/coding-proxy/runtime.d.ts +17 -0
  261. package/dist/providers/coding-proxy/runtime.js +63 -0
  262. package/dist/providers/coding-proxy/secure-fetch.js +0 -1
  263. package/dist/providers/coding-proxy/server.d.ts +11 -0
  264. package/dist/providers/coding-proxy/server.js +163 -0
  265. package/dist/providers/coding-proxy/types.d.ts +15 -0
  266. package/dist/providers/engine/types.d.ts +10 -0
  267. package/dist/providers/executor/build.d.ts +2 -2
  268. package/dist/providers/executor/composition.d.ts +3 -0
  269. package/dist/providers/executor/composition.js +19 -0
  270. package/dist/providers/executor/container.d.ts +105 -3
  271. package/dist/providers/executor/container.js +296 -20
  272. package/dist/providers/executor/dbos.d.ts +2 -3
  273. package/dist/providers/executor/in-process.d.ts +2 -3
  274. package/dist/providers/executor/routing.d.ts +7 -0
  275. package/dist/providers/executor/routing.js +13 -0
  276. package/dist/providers/executor/types.d.ts +22 -0
  277. package/dist/providers/jobs/claude-tool-setup.d.ts +23 -0
  278. package/dist/providers/jobs/claude-tool-setup.js +50 -0
  279. package/dist/providers/jobs/collect-prune.d.ts +7 -0
  280. package/dist/providers/jobs/collect-prune.js +27 -0
  281. package/dist/providers/jobs/docker-isolation.d.ts +48 -3
  282. package/dist/providers/jobs/docker-isolation.js +213 -22
  283. package/dist/providers/jobs/docker-services.d.ts +35 -0
  284. package/dist/providers/jobs/docker-services.js +191 -0
  285. package/dist/providers/jobs/docker.d.ts +49 -2
  286. package/dist/providers/jobs/docker.js +279 -32
  287. package/dist/providers/jobs/fake-kubernetes-api.d.ts +1 -0
  288. package/dist/providers/jobs/fake-kubernetes-api.js +12 -3
  289. package/dist/providers/jobs/kubernetes-isolation.d.ts +17 -2
  290. package/dist/providers/jobs/kubernetes-isolation.js +238 -57
  291. package/dist/providers/jobs/kubernetes-platform.d.ts +10 -4
  292. package/dist/providers/jobs/kubernetes-platform.js +11 -5
  293. package/dist/providers/jobs/kubernetes-preflight.js +3 -0
  294. package/dist/providers/jobs/kubernetes.d.ts +21 -2
  295. package/dist/providers/jobs/kubernetes.js +112 -21
  296. package/dist/providers/jobs/types.d.ts +18 -0
  297. package/dist/providers/llm/anthropic.js +6 -2
  298. package/dist/providers/llm/bedrock.js +2 -1
  299. package/dist/providers/llm/claude-messages.d.ts +5 -1
  300. package/dist/providers/llm/claude-messages.js +1 -0
  301. package/dist/providers/llm/claude-provider.d.ts +3 -1
  302. package/dist/providers/llm/claude-provider.js +5 -1
  303. package/dist/providers/llm/index.d.ts +1 -1
  304. package/dist/providers/llm/index.js +1 -1
  305. package/dist/providers/llm/pricing-anthropic.d.ts +10 -0
  306. package/dist/providers/llm/pricing-anthropic.js +32 -14
  307. package/dist/providers/llm/pricing-bedrock-claude.d.ts +8 -0
  308. package/dist/providers/llm/pricing-bedrock-claude.js +9 -0
  309. package/dist/providers/llm/routing.d.ts +10 -1
  310. package/dist/providers/llm/routing.js +18 -0
  311. package/dist/providers/llm/types.d.ts +12 -0
  312. package/dist/providers/llm/types.js +8 -1
  313. package/dist/providers/review-host/diff-lines.d.ts +16 -0
  314. package/dist/providers/review-host/diff-lines.js +59 -0
  315. package/dist/providers/review-host/github-events.d.ts +6 -0
  316. package/dist/providers/review-host/github-events.js +180 -0
  317. package/dist/providers/review-host/github-user-auth.d.ts +38 -0
  318. package/dist/providers/review-host/github-user-auth.js +128 -0
  319. package/dist/providers/review-host/github.d.ts +57 -0
  320. package/dist/providers/review-host/github.js +567 -0
  321. package/dist/providers/review-host/index.d.ts +12 -0
  322. package/dist/providers/review-host/index.js +30 -0
  323. package/dist/providers/review-host/review-format.d.ts +19 -0
  324. package/dist/providers/review-host/review-format.js +59 -0
  325. package/dist/providers/review-host/types.d.ts +284 -0
  326. package/dist/providers/review-host/types.js +24 -0
  327. package/dist/providers/vcs/git.d.ts +16 -6
  328. package/dist/providers/vcs/git.js +77 -13
  329. package/dist/providers/vcs/github.d.ts +74 -3
  330. package/dist/providers/vcs/github.js +195 -15
  331. package/dist/providers/vcs/types.d.ts +42 -4
  332. package/dist/quickstart/index.js +13 -2
  333. package/dist/sandbox/fetch-policy.d.ts +20 -2
  334. package/dist/sandbox/fetch-policy.js +64 -3
  335. package/dist/sandbox/host-functions.d.ts +9 -1
  336. package/dist/sandbox/host-functions.js +12 -5
  337. package/dist/serve.js +1 -1
  338. package/dist/wardby-bin.js +6 -0
  339. package/docs/README.md +30 -0
  340. package/docs/architecture-runtime.md +90 -0
  341. package/docs/assets/brand/wardby-icon-512.png +0 -0
  342. package/docs/assets/brand/wardby-icon.svg +16 -0
  343. package/docs/assets/brand/wardby-mascot-profile-512.png +0 -0
  344. package/docs/assets/brand/wardby-mascot.png +0 -0
  345. package/docs/assets/brand/wardby-mascot.svg +5 -0
  346. package/docs/assets/wardby-workflow.svg +106 -0
  347. package/docs/code-review-agents.md +481 -0
  348. package/docs/coding-agent-setup.md +172 -0
  349. package/docs/coding-packages.md +455 -0
  350. package/docs/coding-services.md +300 -0
  351. package/docs/coding-worker-byo-images.md +98 -0
  352. package/docs/coding-worker-isolation.md +1061 -0
  353. package/docs/getting-started-gke.md +615 -0
  354. package/docs/getting-started-identity-provider.md +308 -0
  355. package/docs/getting-started.md +133 -0
  356. package/docs/observability.md +53 -0
  357. package/docs/release-verification.md +66 -0
  358. package/docs/security-deployment.md +657 -0
  359. package/help/code-review-agents.md +31 -0
  360. package/help/coding-packages.md +31 -0
  361. package/help/coding-services.md +71 -0
  362. package/help/creating-agents.md +68 -0
  363. package/help/deploy-gke.md +39 -0
  364. package/help/deployment-targets.md +39 -0
  365. package/help/errors/budget-group-exhausted.md +25 -0
  366. package/help/errors/docker-isolation-unsupported.md +26 -0
  367. package/help/errors/protected-path.md +45 -0
  368. package/help/errors/repo-access.md +27 -0
  369. package/help/errors/service-declaration-invalid.md +27 -0
  370. package/help/errors/service-declaration-unavailable.md +25 -0
  371. package/help/errors/service-launcher-unsupported.md +30 -0
  372. package/help/errors/service-not-allowed.md +27 -0
  373. package/help/errors/service-unknown.md +23 -0
  374. package/help/errors/service-unready.md +49 -0
  375. package/help/getting-started.md +31 -0
  376. package/help/github.md +30 -0
  377. package/help/identity-and-access.md +39 -0
  378. package/help/mcp.md +30 -0
  379. package/help/native-capabilities.md +30 -0
  380. package/help/observability.md +41 -0
  381. package/help/operating-agents.md +30 -0
  382. package/help/security.md +27 -0
  383. package/help/troubleshooting/budgets.md +26 -0
  384. package/help/troubleshooting/coding-workers.md +47 -0
  385. package/help/troubleshooting/repository-access.md +27 -0
  386. package/package.json +12 -3
  387. package/prisma/migrations/20260925010000_coding_collect_exclude/migration.sql +8 -0
  388. package/prisma/migrations/20260925015000_allowed_egress_default/migration.sql +8 -0
  389. package/prisma/migrations/20260925020000_coding_package_registry/migration.sql +55 -0
  390. package/prisma/migrations/20260925030000_tool_name_per_owner/migration.sql +11 -0
  391. package/prisma/migrations/20260926010000_run_trigger_host_event/migration.sql +7 -0
  392. package/prisma/migrations/20260926020000_code_review_hosts/migration.sql +53 -0
  393. package/prisma/migrations/20260926030000_auth_user_roles/migration.sql +9 -0
  394. package/prisma/migrations/20260926040000_agent_effort/migration.sql +6 -0
  395. package/prisma/migrations/20260926050000_registry_lockfile_plan/migration.sql +32 -0
  396. package/prisma/migrations/20260926050000_repo_access_authorization/migration.sql +82 -0
  397. package/prisma/migrations/20260926060000_registry_plan_refusal/migration.sql +19 -0
  398. package/prisma/migrations/20260926100000_registry_plan_refusal_published_at/migration.sql +5 -0
  399. package/prisma/migrations/20260926190000_run_host_status/migration.sql +18 -0
  400. package/prisma/migrations/20260926210000_run_host_status_at_dispatch/migration.sql +5 -0
  401. package/prisma/migrations/20260927010000_resource_grants/migration.sql +72 -0
  402. package/prisma/migrations/20260927020000_proxy_session_budget_exhausted/migration.sql +3 -0
  403. package/prisma/migrations/20260927030000_coding_debug_trace/migration.sql +4 -0
  404. package/prisma/migrations/20260927040000_proxy_session_upstream_failure/migration.sql +3 -0
  405. package/prisma/migrations/20260927050000_coding_run_services/migration.sql +74 -0
  406. package/prisma/migrations/20260928000000_coding_run_tool_image/migration.sql +5 -0
  407. package/prisma/schema.prisma +407 -21
@@ -21,9 +21,10 @@ export function parseImportArgs(args) {
21
21
  throw new Error("Missing bundle directory positional argument");
22
22
  }
23
23
  const dir = positionals[0];
24
- // Parse owner/public
24
+ // Parse owner/public: --public may be combined with --owner (the owner of
25
+ // the imported agents, which --public then shares with everyone).
25
26
  const isPublic = values.public ?? false;
26
- const owner = isPublic ? null : (values.owner ?? null);
27
+ const owner = values.owner ?? null;
27
28
  // Validate on-conflict
28
29
  const onConflict = (values["on-conflict"] ?? "fail");
29
30
  if (!VALID_CONFLICT_POLICIES.includes(onConflict)) {
@@ -11,7 +11,12 @@ import type { SecretCipher } from "../providers/secrets/types.js";
11
11
  export interface CreateOptions {
12
12
  db: PrismaClient;
13
13
  cipher: SecretCipher;
14
+ /** Owner of the imported tools, secrets, datastores, webhooks and budget groups; null in --public mode. */
14
15
  ownerId: string | null;
16
+ /** Owner of the imported agents (defaults to ownerId): never null for a real import. */
17
+ agentOwnerId?: string | null;
18
+ /** --public: share each imported agent with everyone at execute. */
19
+ publicAgents?: boolean;
15
20
  defaultBudget: string;
16
21
  secretMode: "references" | "envelope";
17
22
  transferPrivateKey?: KeyObject;
@@ -8,12 +8,15 @@ import { createSecret, attachSecret } from "../core/secrets.js";
8
8
  import { createDatastore, attachDatastore } from "../core/datastores.js";
9
9
  import { createWebhook } from "../core/webhooks.js";
10
10
  import { deriveJsonSchema } from "../sandbox/zod-params.js";
11
+ import { findSameNamedAttachedTool, reservedToolNameReason } from "../core/tool-names.js";
11
12
  import { ToolCapabilitiesPatchSchema, FETCH_WILDCARD } from "../sandbox/tool-capabilities.js";
12
13
  import { PostgresDatastore } from "../providers/datastore/postgres.js";
13
14
  import { decryptTransferEnvelope } from "../providers/secrets/transfer-envelope.js";
14
15
  import { mapBudget } from "./budgets.js";
16
+ import { EVERYONE_KEY, everyoneGrantData } from "../core/grants.js";
15
17
  export async function createFromBundle(bundle, recon, opts) {
16
18
  const { db, cipher, ownerId, secretMode, transferPrivateKey, allowOpenFetch } = opts;
19
+ const agentOwnerId = opts.agentOwnerId === undefined ? ownerId : opts.agentOwnerId;
17
20
  const warnings = [];
18
21
  const webhookSecrets = [];
19
22
  const pendingSecretReentry = [];
@@ -37,28 +40,41 @@ export async function createFromBundle(bundle, recon, opts) {
37
40
  for (const t of bundle.readTools()) {
38
41
  if (toolRejected(t.name) || toolSkipped(t.name))
39
42
  continue;
43
+ // A built-in dispatched before user tools would shadow it, so the tool
44
+ // could be created but never called (see core/tool-names.ts).
45
+ const reserved = reservedToolNameReason(eff(t.name));
46
+ if (reserved) {
47
+ warnings.push(`tool ${t.name}: skipped — ${reserved}`);
48
+ continue;
49
+ }
40
50
  const schema = await deriveJsonSchema(t.paramsZod);
41
51
  if (!schema.ok) {
42
52
  warnings.push(`tool ${t.name}: failed to derive JSON schema, skipping`);
43
53
  continue;
44
54
  }
45
- const tool = await db.tool.upsert({
46
- where: { name: eff(t.name) },
47
- create: {
48
- name: eff(t.name),
49
- description: t.description,
50
- paramsZod: t.paramsZod,
51
- code: t.code,
52
- jsonSchema: schema.value,
53
- ownerId,
54
- },
55
- update: {},
56
- });
55
+ // Names are unique per owner: reuse the target owner's own same-named
56
+ // tool (what upsert-by-name used to do), never another owner's. A
57
+ // compound unique with a nullable column can't key an upsert, hence
58
+ // findFirst + create.
59
+ const tool = (await db.tool.findFirst({ where: { ownerId, name: eff(t.name) } })) ??
60
+ (await db.tool.create({
61
+ data: {
62
+ name: eff(t.name),
63
+ description: t.description,
64
+ paramsZod: t.paramsZod,
65
+ code: t.code,
66
+ jsonSchema: schema.value,
67
+ ownerId,
68
+ },
69
+ }));
57
70
  toolIdMap.set(t.name, tool.id);
58
71
  toolsCreated++;
59
72
  }
60
73
  // Step 2: Agents
61
74
  const agentIdMap = new Map();
75
+ // Agents this import owns (created now, or already the import owner's):
76
+ // only their attachments are stamped with the owner's consent below.
77
+ const ownedAgentIds = new Set();
62
78
  for (const a of bundle.readAgents()) {
63
79
  if (agentSkipped(a.name))
64
80
  continue;
@@ -74,11 +90,27 @@ export async function createFromBundle(bundle, recon, opts) {
74
90
  timezone: a.timezone,
75
91
  maxTurns: a.maxTurns,
76
92
  scheduleEnabled,
77
- ownerId,
93
+ ownerId: agentOwnerId,
78
94
  },
79
95
  update: {},
80
96
  });
81
97
  agentIdMap.set(a.name, agent.id);
98
+ if (agentOwnerId !== null && agent.ownerId === agentOwnerId) {
99
+ ownedAgentIds.add(agent.id);
100
+ if (opts.publicAgents) {
101
+ await db.resourceGrant.upsert({
102
+ where: {
103
+ resourceType_resourceId_granteeKey: {
104
+ resourceType: "agent",
105
+ resourceId: agent.id,
106
+ granteeKey: EVERYONE_KEY,
107
+ },
108
+ },
109
+ create: everyoneGrantData("agent", agent.id, "execute", "import"),
110
+ update: {},
111
+ });
112
+ }
113
+ }
82
114
  agentsCreated++;
83
115
  }
84
116
  // Step 3: Attach tools
@@ -105,7 +137,26 @@ export async function createFromBundle(bundle, recon, opts) {
105
137
  warnings.push(`agent-tool ${at.agentName}/${at.toolName}: invalid capabilities, skipping attachment`);
106
138
  continue;
107
139
  }
140
+ // Same guard as MCP attach_tool: an existing agent reused by name may
141
+ // already hold a different tool under this name (say a public one), and
142
+ // the runtime dispatches by name. Unlike attach_tool this check-then-
143
+ // upsert is not one Serializable transaction: the importer is an
144
+ // operator-only path, so a concurrent attach racing it is not defended
145
+ // against here (the runner's load-time duplicate check still is).
146
+ const clash = await findSameNamedAttachedTool(db, agentId, { id: toolId, name: eff(at.toolName) });
147
+ if (clash) {
148
+ warnings.push(`agent-tool ${at.agentName}/${at.toolName}: skipped — the agent already has a different tool with the same name (${clash.id})`);
149
+ continue;
150
+ }
108
151
  const caps = capsPatch.data;
152
+ // The importing operator is trusted with the database, so on an agent
153
+ // this import owns it grants the bundle's capabilities in the owner's
154
+ // name (the runner honours them only with that stamp). An existing
155
+ // agent owned by someone else keeps an unstamped, inert attachment.
156
+ const consent = ownedAgentIds.has(agentId) ? agentOwnerId : null;
157
+ if (consent === null) {
158
+ warnings.push(`agent-tool ${at.agentName}/${at.toolName}: attached without capabilities in force — the agent belongs to another owner, who must re-grant them with attach_tool`);
159
+ }
109
160
  await db.agentTool.upsert({
110
161
  where: { agentId_toolId: { agentId, toolId } },
111
162
  create: {
@@ -115,12 +166,15 @@ export async function createFromBundle(bundle, recon, opts) {
115
166
  allowedDatastorePrefixes: caps.allowedDatastorePrefixes ?? [],
116
167
  allowedHosts: caps.allowedHosts ?? [],
117
168
  allowedSharedDatastorePrefixes: caps.allowedSharedDatastorePrefixes ?? {},
169
+ attachedById: agentOwnerId,
170
+ capabilitiesGrantedById: consent,
118
171
  },
119
172
  update: {
120
173
  allowedSecrets: caps.allowedSecrets ?? [],
121
174
  allowedDatastorePrefixes: caps.allowedDatastorePrefixes ?? [],
122
175
  allowedHosts: caps.allowedHosts ?? [],
123
176
  allowedSharedDatastorePrefixes: caps.allowedSharedDatastorePrefixes ?? {},
177
+ capabilitiesGrantedById: consent,
124
178
  },
125
179
  });
126
180
  }
@@ -10,19 +10,19 @@ import { supportedGlobalsFromPrelude } from "./tool-scan.js";
10
10
  import { SANDBOX_PRELUDE } from "../sandbox/prelude.js";
11
11
  import { resolveLlmRegistrations } from "../providers/llm/registration.js";
12
12
  import { RoutingLlmProvider } from "../providers/llm/routing.js";
13
- import { loadProviderConfig } from "../config/providers.js";
13
+ import { loadMcpConfig, loadProviderConfig } from "../config/providers.js";
14
14
  import { buildSecretCipher } from "../providers/secrets/index.js";
15
15
  import { resolvePrincipal } from "../mcp/auth/principal.js";
16
16
  import { loadTransferPrivateKey, transferKeyIdOf } from "../providers/secrets/transfer-envelope.js";
17
17
  import { readFileSync } from "node:fs";
18
18
  export async function runImport(opts) {
19
19
  const env = opts.env ?? process.env;
20
- // Guard: owner XOR public
20
+ // Guard: --owner or --public (or both). --public no longer means
21
+ // owner-less: the imported agents are owned by --owner, or by the
22
+ // importing operator (LOCAL_PRINCIPAL), and shared with everyone at
23
+ // execute (resource-sharing grants spec §3.8).
21
24
  if (opts.owner === null && !opts.isPublic) {
22
- throw new Error("Must specify either --owner or --public (not neither)");
23
- }
24
- if (opts.owner !== null && opts.isPublic) {
25
- throw new Error("Cannot specify both --owner and --public");
25
+ throw new Error("Must specify --owner, --public, or both");
26
26
  }
27
27
  // Open bundle
28
28
  const bundle = openBundle(opts.dir);
@@ -36,10 +36,13 @@ export async function runImport(opts) {
36
36
  // Load existing names from db
37
37
  const existingAgents = await opts.db.agent.findMany({ select: { name: true } });
38
38
  const existingAgentNames = new Set(existingAgents.map((a) => a.name));
39
- const existingTools = await opts.db.tool.findMany({ select: { name: true } });
40
- const existingToolNames = new Set(existingTools.map((t) => t.name));
41
- // For owner-scoped entities (secrets, budgets), load only if we have an owner
39
+ // For owner-scoped entities (tools, secrets, budgets), load only if we have an owner
42
40
  const ownerId = opts.owner !== null && !opts.isPublic ? (await resolvePrincipal(opts.owner, opts.db)).id : null;
41
+ // Tool names are unique per owner (null = the public namespace), so only
42
+ // the target owner's tools can collide; another owner's same-named tool
43
+ // is no conflict.
44
+ const existingTools = await opts.db.tool.findMany({ where: { ownerId }, select: { name: true } });
45
+ const existingToolNames = new Set(existingTools.map((t) => t.name));
43
46
  // Tier-1 capabilities: "budgets" and "shared-datastores" are implemented
44
47
  const capabilitiesSupported = new Set(["budgets", "shared-datastores"]);
45
48
  // Run preflight reconciliation
@@ -84,11 +87,18 @@ export async function runImport(opts) {
84
87
  // Build secret cipher
85
88
  const providerConfig = loadProviderConfig(env);
86
89
  const cipher = buildSecretCipher(providerConfig, env);
90
+ // The imported agents' owner: --owner, or in --public mode the importing
91
+ // operator. Resolved only for a real import (never on --dry-run).
92
+ const agentOwnerId = opts.isPublic
93
+ ? (await resolvePrincipal(opts.owner ?? loadMcpConfig(env).localPrincipal, opts.db)).id
94
+ : ownerId;
87
95
  // Run create
88
96
  const result = await createFromBundle(bundle, recon, {
89
97
  db: opts.db,
90
98
  cipher,
91
99
  ownerId,
100
+ agentOwnerId,
101
+ publicAgents: opts.isPublic,
92
102
  defaultBudget: opts.defaultBudget ?? "10.00",
93
103
  secretMode: effectiveSecretMode,
94
104
  transferPrivateKey,
@@ -46,13 +46,13 @@ export declare const ManifestSchema: z.ZodObject<{
46
46
  capabilities: z.ZodArray<z.ZodString, "many">;
47
47
  counts: z.ZodRecord<z.ZodString, z.ZodNumber>;
48
48
  }, "strip", z.ZodTypeAny, {
49
- capabilities: string[];
50
- bundleVersion: number;
51
49
  source: {
52
50
  product: string;
53
51
  exporterVersion: string;
54
52
  exportedAt: string;
55
53
  };
54
+ capabilities: string[];
55
+ bundleVersion: number;
56
56
  secretMode: "references" | "envelope";
57
57
  transferKeyId: string | null;
58
58
  contentWindowDays: number | null;
@@ -62,13 +62,13 @@ export declare const ManifestSchema: z.ZodObject<{
62
62
  runAuditSince: string | null;
63
63
  counts: Record<string, number>;
64
64
  }, {
65
- capabilities: string[];
66
- bundleVersion: number;
67
65
  source: {
68
66
  product: string;
69
67
  exporterVersion: string;
70
68
  exportedAt: string;
71
69
  };
70
+ capabilities: string[];
71
+ bundleVersion: number;
72
72
  secretMode: "references" | "envelope";
73
73
  counts: Record<string, number>;
74
74
  transferKeyId?: string | null | undefined;
@@ -98,41 +98,41 @@ export declare const NeutralAgentSchema: z.ZodObject<{
98
98
  slug: z.ZodOptional<z.ZodDefault<z.ZodNullable<z.ZodString>>>;
99
99
  emailAllowlist: z.ZodOptional<z.ZodDefault<z.ZodNullable<z.ZodUnknown>>>;
100
100
  }, "strip", z.ZodTypeAny, {
101
- description?: string | null | undefined;
102
101
  slug?: string | null | undefined;
102
+ description?: string | null | undefined;
103
103
  emailAllowlist?: unknown;
104
104
  }, {
105
- description?: string | null | undefined;
106
105
  slug?: string | null | undefined;
106
+ description?: string | null | undefined;
107
107
  emailAllowlist?: unknown;
108
108
  }>>;
109
109
  }, "strip", z.ZodTypeAny, {
110
110
  name: string;
111
111
  model: string;
112
112
  budgetUsd: string;
113
- systemPrompt: string;
114
113
  kind: "native";
114
+ provider: "openai" | "bedrock";
115
+ systemPrompt: string;
115
116
  schedule: string | null;
116
117
  timezone: string;
117
118
  scheduleEnabled: boolean;
118
119
  maxTurns: number;
119
120
  memoryEnabled: boolean;
120
- provider: "openai" | "bedrock";
121
121
  region: string | null;
122
122
  ownerEmail: string | null;
123
123
  unmodeled: {
124
- description?: string | null | undefined;
125
124
  slug?: string | null | undefined;
125
+ description?: string | null | undefined;
126
126
  emailAllowlist?: unknown;
127
127
  };
128
128
  }, {
129
129
  name: string;
130
130
  model: string;
131
131
  budgetUsd: string;
132
+ provider: "openai" | "bedrock";
132
133
  systemPrompt: string;
133
134
  scheduleEnabled: boolean;
134
135
  maxTurns: number;
135
- provider: "openai" | "bedrock";
136
136
  kind?: "native" | undefined;
137
137
  schedule?: string | null | undefined;
138
138
  timezone?: string | undefined;
@@ -140,8 +140,8 @@ export declare const NeutralAgentSchema: z.ZodObject<{
140
140
  region?: string | null | undefined;
141
141
  ownerEmail?: string | null | undefined;
142
142
  unmodeled?: {
143
- description?: string | null | undefined;
144
143
  slug?: string | null | undefined;
144
+ description?: string | null | undefined;
145
145
  emailAllowlist?: unknown;
146
146
  } | undefined;
147
147
  }>;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * The MCP seam for agent access (resource-sharing grants spec §3.3). Every
3
+ * agent tool routes through here instead of ownership.ts's owner-or-public
4
+ * rule, which no longer applies to agents: an owner-less agent is reachable
5
+ * only through its grants (the migration gives everyone execute).
6
+ *
7
+ * - Below read: 404 with the same text as a missing row, so existence never
8
+ * leaks. At read or above but below the level required: 403 naming both.
9
+ * - The helpers take a `db` argument so a Serializable transaction reads the
10
+ * grant rows through `tx`; a concurrent revoke then conflicts instead of
11
+ * racing.
12
+ * - `ctx.operator` (stdio's local operator, never an HTTP principal) is
13
+ * owner of every agent for access checks and sees every agent in
14
+ * listings, but does NOT bypass requireBindingOwner: one owner's secrets,
15
+ * datastores and repositories never reach another owner's agent.
16
+ */
17
+ import type { Prisma, PrismaClient } from "#prisma";
18
+ import { type Access, type Level } from "../../core/grants.js";
19
+ import type { McpRequestContext } from "../context.js";
20
+ import { McpError } from "../errors.js";
21
+ export type AgentLevel = Level<"agent">;
22
+ export type AgentAccess = Access<"agent">;
23
+ type AgentRef = {
24
+ id: string;
25
+ ownerId: string | null;
26
+ };
27
+ type GrantDb = Pick<PrismaClient, "resourceGrant">;
28
+ export declare function agentNotFound(id: string): McpError;
29
+ export declare function insufficientAgentAccess(id: string, required: AgentLevel | "owner", held: AgentAccess): McpError;
30
+ /** The caller's access to an agent row already read. */
31
+ export declare function agentAccess(ctx: McpRequestContext, agent: AgentRef, db?: GrantDb): Promise<AgentAccess>;
32
+ /** For a row already read (inside a transaction, or with includes): 404 below read, 403 below `required`. */
33
+ export declare function assertAgentAccess<A extends AgentRef>(ctx: McpRequestContext, agent: A | null, id: string, required: AgentLevel | "owner", db?: GrantDb): Promise<{
34
+ agent: A;
35
+ access: AgentAccess;
36
+ }>;
37
+ /** 404 if missing or access < read; 403 if read <= access < required. Returns row + access. */
38
+ export declare function requireAgentAccess(ctx: McpRequestContext, id: string, required: AgentLevel | "owner", db?: Pick<PrismaClient, "agent" | "resourceGrant">): Promise<{
39
+ agent: {
40
+ name: string;
41
+ model: string;
42
+ budgetUsd: import("@prisma/client-runtime-utils").Decimal;
43
+ kind: import("#prisma").AgentKind;
44
+ id: string;
45
+ ownerId: string | null;
46
+ createdAt: Date;
47
+ updatedAt: Date;
48
+ systemPrompt: string;
49
+ schedule: string | null;
50
+ timezone: string;
51
+ scheduleEnabled: boolean;
52
+ lastScheduledAt: Date | null;
53
+ maxTurns: number;
54
+ budgetGroupId: string | null;
55
+ memoryEnabled: boolean;
56
+ effort: string | null;
57
+ };
58
+ access: AgentAccess;
59
+ }>;
60
+ /**
61
+ * Bindings (secrets, datastores, repositories, capability grants): strict
62
+ * ownership, whatever the grants. The stdio operator does NOT bypass this:
63
+ * it can adopt the agent first (make_owner / grants adopt-public).
64
+ */
65
+ export declare function requireBindingOwner(ctx: McpRequestContext, agent: AgentRef): void;
66
+ /** Prisma where for agent listings: own rows plus rows granted >= read; the operator sees all. */
67
+ export declare function readableAgentsWhere(ctx: McpRequestContext, db?: GrantDb): Promise<Prisma.AgentWhereInput>;
68
+ /** One grant lookup for a whole listing: returns agent -> the caller's access. */
69
+ export declare function agentAccessResolver(ctx: McpRequestContext, db?: GrantDb): Promise<(agent: AgentRef) => AgentAccess>;
70
+ export {};
@@ -0,0 +1,58 @@
1
+ import { atLeast, effectiveAccess, grantedAccessMap, grantedIds } from "../../core/grants.js";
2
+ import { McpError } from "../errors.js";
3
+ export function agentNotFound(id) {
4
+ return new McpError(404, `Agent "${id}" not found.`);
5
+ }
6
+ function describeLevel(level) {
7
+ return level === "owner" ? "the agent's owner" : `${level} access`;
8
+ }
9
+ export function insufficientAgentAccess(id, required, held) {
10
+ return new McpError(403, `Agent "${id}": this needs ${describeLevel(required)}; you have ${held === "owner" ? "owner" : held} access.`);
11
+ }
12
+ /** The caller's access to an agent row already read. */
13
+ export function agentAccess(ctx, agent, db = ctx.db) {
14
+ return effectiveAccess(db, "agent", agent, ctx.principal.id, { operator: ctx.operator === true });
15
+ }
16
+ /** For a row already read (inside a transaction, or with includes): 404 below read, 403 below `required`. */
17
+ export async function assertAgentAccess(ctx, agent, id, required, db = ctx.db) {
18
+ if (!agent)
19
+ throw agentNotFound(id);
20
+ const access = await agentAccess(ctx, agent, db);
21
+ if (!atLeast("agent", access, "read"))
22
+ throw agentNotFound(id);
23
+ if (!atLeast("agent", access, required))
24
+ throw insufficientAgentAccess(id, required, access);
25
+ return { agent, access };
26
+ }
27
+ /** 404 if missing or access < read; 403 if read <= access < required. Returns row + access. */
28
+ export async function requireAgentAccess(ctx, id, required, db = ctx.db) {
29
+ const agent = await db.agent.findUnique({ where: { id } });
30
+ return assertAgentAccess(ctx, agent, id, required, db);
31
+ }
32
+ /**
33
+ * Bindings (secrets, datastores, repositories, capability grants): strict
34
+ * ownership, whatever the grants. The stdio operator does NOT bypass this:
35
+ * it can adopt the agent first (make_owner / grants adopt-public).
36
+ */
37
+ export function requireBindingOwner(ctx, agent) {
38
+ if (agent.ownerId === null) {
39
+ throw new McpError(403, `Agent "${agent.id}" has no owner, so nothing can be bound to it; an admin can assign one with make_owner.`);
40
+ }
41
+ if (agent.ownerId !== ctx.principal.id) {
42
+ throw new McpError(403, `Only the owner of agent "${agent.id}" can change its bindings.`);
43
+ }
44
+ }
45
+ /** Prisma where for agent listings: own rows plus rows granted >= read; the operator sees all. */
46
+ export async function readableAgentsWhere(ctx, db = ctx.db) {
47
+ if (ctx.operator)
48
+ return {};
49
+ const ids = await grantedIds(db, "agent", ctx.principal.id, "read");
50
+ return { OR: [{ ownerId: ctx.principal.id }, { id: { in: ids } }] };
51
+ }
52
+ /** One grant lookup for a whole listing: returns agent -> the caller's access. */
53
+ export async function agentAccessResolver(ctx, db = ctx.db) {
54
+ if (ctx.operator)
55
+ return () => "owner";
56
+ const granted = await grantedAccessMap(db, "agent", ctx.principal.id);
57
+ return (agent) => agent.ownerId !== null && agent.ownerId === ctx.principal.id ? "owner" : (granted.get(agent.id) ?? "none");
58
+ }
@@ -0,0 +1,149 @@
1
+ import { type PrismaClient } from "#prisma";
2
+ /** The report needs only raw queries, so it can run on a schema the generated client doesn't match. */
3
+ export interface ReportDb {
4
+ $queryRaw<T = unknown>(query: TemplateStringsArray, ...values: unknown[]): PromiseLike<T>;
5
+ }
6
+ export declare const BEHAVIOUR_CHANGES: string[];
7
+ export interface MigrationReport {
8
+ grantsTable: boolean;
9
+ ownerlessAgents: {
10
+ agentId: string;
11
+ name: string;
12
+ everyoneGrant: string | null;
13
+ /** What adopting the agent as each principal would bring back into force (review I3). */
14
+ revivedByAdopter: {
15
+ principalId: string;
16
+ subject: string;
17
+ secrets: string[];
18
+ datastores: string[];
19
+ toolCapabilities: string[];
20
+ }[];
21
+ }[];
22
+ inertBindings: {
23
+ kind: "secret" | "datastore";
24
+ agentId: string;
25
+ agentName: string;
26
+ agentOwnerId: string | null;
27
+ boundName: string;
28
+ resourceId: string;
29
+ resourceOwnerId: string | null;
30
+ /** Removed by prune-bindings (owned agent); on an owner-less agent adopt-public decides. */
31
+ prunable: boolean;
32
+ }[];
33
+ suspendedCapabilities: {
34
+ agentId: string;
35
+ agentName: string;
36
+ toolId: string;
37
+ toolName: string;
38
+ regrant: string;
39
+ }[];
40
+ /**
41
+ * Capabilities the migration stamps with the current owner on owner-less
42
+ * tools: a previous owner may have set them before a make_owner (review
43
+ * M2). They stay in force; the owner should review them.
44
+ */
45
+ reviewCapabilities: {
46
+ agentId: string;
47
+ agentName: string;
48
+ toolId: string;
49
+ toolName: string;
50
+ regrant: string;
51
+ }[];
52
+ failingEdges: {
53
+ parentAgentId: string;
54
+ parentOwnerId: string | null;
55
+ childAgentId: string;
56
+ childOwnerId: string | null;
57
+ boundName: string;
58
+ }[];
59
+ webhooks: {
60
+ onOwnerlessAgents: {
61
+ id: string;
62
+ agentId: string;
63
+ createdBy: string | null;
64
+ }[];
65
+ creatorLacksExecute: {
66
+ id: string;
67
+ agentId: string;
68
+ createdBy: string | null;
69
+ }[];
70
+ };
71
+ behaviourChanges: string[];
72
+ orphanGrants: {
73
+ id: string;
74
+ resourceType: string;
75
+ resourceId: string;
76
+ }[] | null;
77
+ }
78
+ export declare function migrationReport(db: ReportDb): Promise<MigrationReport>;
79
+ export declare function formatMigrationReport(report: MigrationReport): string;
80
+ export interface AdoptedAgent {
81
+ agentId: string;
82
+ name: string;
83
+ bindingsRemoved: {
84
+ kind: "secret" | "datastore";
85
+ boundName: string;
86
+ resourceId: string;
87
+ }[];
88
+ bindingsKept: {
89
+ kind: "secret" | "datastore";
90
+ boundName: string;
91
+ }[];
92
+ capabilitiesStamped: string[];
93
+ /** Every attached tool the new owner doesn't own (review M7); `regrant` only when it had capabilities. */
94
+ foreignTools: {
95
+ toolId: string;
96
+ toolName: string;
97
+ toolOwnerId: string | null;
98
+ regrant: string | null;
99
+ }[];
100
+ failingEdges: {
101
+ parentAgentId: string;
102
+ childAgentId: string;
103
+ boundName: string;
104
+ }[];
105
+ /** The everyone grant before and after adoption (null = none). */
106
+ everyoneGrant: {
107
+ before: string | null;
108
+ after: string | null;
109
+ };
110
+ }
111
+ export interface AdoptResult {
112
+ owner: {
113
+ id: string;
114
+ subject: string;
115
+ };
116
+ dryRun: boolean;
117
+ agents: AdoptedAgent[];
118
+ }
119
+ /** Gives every owner-less agent `ownerSubject` as its owner. See the module header. */
120
+ export declare function adoptPublic(db: PrismaClient, opts: {
121
+ ownerSubject: string;
122
+ dryRun: boolean;
123
+ keepEveryoneExecute?: boolean;
124
+ }): Promise<AdoptResult>;
125
+ export declare function formatAdoptResult(result: AdoptResult): string;
126
+ export interface PruneResult {
127
+ dryRun: boolean;
128
+ removed: {
129
+ kind: "secret" | "datastore";
130
+ agentId: string;
131
+ agentName: string;
132
+ boundName: string;
133
+ resourceId: string;
134
+ resourceOwnerId: string | null;
135
+ }[];
136
+ }
137
+ /** Deletes cross-owner secret/datastore bindings on owned agents, in one transaction. */
138
+ export declare function pruneBindings(db: PrismaClient, opts: {
139
+ dryRun: boolean;
140
+ }): Promise<PruneResult>;
141
+ export declare function formatPruneResult(result: PruneResult): string;
142
+ /**
143
+ * The owner of an agent made with `wardby agent create` (resource-sharing
144
+ * grants spec §3.8): `--owner <subject>` must already exist (a typo never
145
+ * mints a principal), otherwise the local operator (LOCAL_PRINCIPAL),
146
+ * found or created exactly as stdio does.
147
+ */
148
+ export declare function resolveCliAgentOwner(db: PrismaClient, ownerSubject: string | undefined, localPrincipal: string): Promise<string>;
149
+ export declare function grantsCommand(args: string[], db: PrismaClient, output?: (value: string) => void): Promise<void>;