@wardby/cli 0.2.1 → 0.4.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 (555) hide show
  1. package/.env.example +53 -4
  2. package/README.md +52 -13
  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 +14 -4
  10. package/dist/cli.d.ts +1 -1
  11. package/dist/cli.js +284 -36
  12. package/dist/coding/base-commit.d.ts +6 -0
  13. package/dist/coding/base-commit.js +12 -0
  14. package/dist/coding/collect-exclude.d.ts +25 -0
  15. package/dist/coding/collect-exclude.js +76 -0
  16. package/dist/coding/profile.d.ts +67 -22
  17. package/dist/coding/profile.js +58 -25
  18. package/dist/coding/protected-path-wording.d.ts +24 -0
  19. package/dist/coding/protected-path-wording.js +55 -0
  20. package/dist/coding/protected-paths.d.ts +31 -0
  21. package/dist/coding/protected-paths.js +48 -0
  22. package/dist/coding/protocol.d.ts +91 -4
  23. package/dist/coding/protocol.js +123 -12
  24. package/dist/coding/provider.d.ts +6 -1
  25. package/dist/coding/provider.js +16 -9
  26. package/dist/coding/registry/adapters.d.ts +2 -0
  27. package/dist/coding/registry/adapters.js +9 -0
  28. package/dist/coding/registry/allowlist.d.ts +9 -0
  29. package/dist/coding/registry/allowlist.js +28 -0
  30. package/dist/coding/registry/json-scan.d.ts +55 -0
  31. package/dist/coding/registry/json-scan.js +191 -0
  32. package/dist/coding/registry/lockfiles.d.ts +6 -0
  33. package/dist/coding/registry/lockfiles.js +89 -0
  34. package/dist/coding/registry/npm-lockfile.d.ts +9 -0
  35. package/dist/coding/registry/npm-lockfile.js +73 -0
  36. package/dist/coding/registry/npm-plan.d.ts +29 -0
  37. package/dist/coding/registry/npm-plan.js +289 -0
  38. package/dist/coding/registry/npm.d.ts +7 -0
  39. package/dist/coding/registry/npm.js +252 -0
  40. package/dist/coding/registry/pypi.d.ts +4 -0
  41. package/dist/coding/registry/pypi.js +210 -0
  42. package/dist/coding/registry/report.d.ts +37 -0
  43. package/dist/coding/registry/report.js +31 -0
  44. package/dist/coding/registry/token.d.ts +4 -0
  45. package/dist/coding/registry/token.js +7 -0
  46. package/dist/coding/registry/types.d.ts +286 -0
  47. package/dist/coding/registry/types.js +19 -0
  48. package/dist/coding/registry/worker-config.d.ts +14 -0
  49. package/dist/coding/registry/worker-config.js +31 -0
  50. package/dist/coding/services/builtins.d.ts +22 -0
  51. package/dist/coding/services/builtins.js +85 -0
  52. package/dist/coding/services/catalog.d.ts +443 -0
  53. package/dist/coding/services/catalog.js +159 -0
  54. package/dist/coding/services/declaration.d.ts +11 -0
  55. package/dist/coding/services/declaration.js +114 -0
  56. package/dist/coding/services/note.d.ts +8 -0
  57. package/dist/coding/services/note.js +15 -0
  58. package/dist/coding/services/resolve.d.ts +25 -0
  59. package/dist/coding/services/resolve.js +50 -0
  60. package/dist/coding/services/wording.d.ts +25 -0
  61. package/dist/coding/services/wording.js +70 -0
  62. package/dist/coding-proxy/main.js +24 -4
  63. package/dist/coding-worker/artifact.d.ts +6 -0
  64. package/dist/coding-worker/debug-trace.d.ts +37 -0
  65. package/dist/coding-worker/debug-trace.js +117 -0
  66. package/dist/coding-worker/driver.d.ts +13 -1
  67. package/dist/coding-worker/driver.js +102 -13
  68. package/dist/coding-worker/errors.js +8 -0
  69. package/dist/coding-worker/main.js +10 -2
  70. package/dist/coding-worker/sdk.d.ts +2 -2
  71. package/dist/coding-worker/sdk.js +7 -2
  72. package/dist/coding-worker/types.d.ts +3 -0
  73. package/dist/config/providers.d.ts +66 -0
  74. package/dist/config/providers.js +137 -0
  75. package/dist/core/attribution.d.ts +101 -0
  76. package/dist/core/attribution.js +208 -0
  77. package/dist/core/budget-groups.d.ts +120 -10
  78. package/dist/core/budget-groups.js +133 -24
  79. package/dist/core/budget-wording.d.ts +22 -0
  80. package/dist/core/budget-wording.js +55 -0
  81. package/dist/core/coding-queue.d.ts +3 -0
  82. package/dist/core/coding-queue.js +6 -2
  83. package/dist/core/coding-service-status.d.ts +11 -0
  84. package/dist/core/coding-service-status.js +17 -0
  85. package/dist/core/cost-report.d.ts +88 -0
  86. package/dist/core/cost-report.js +248 -0
  87. package/dist/core/datastores.js +18 -2
  88. package/dist/core/db.d.ts +5 -1
  89. package/dist/core/db.js +8 -2
  90. package/dist/core/dispatch.d.ts +74 -7
  91. package/dist/core/dispatch.js +382 -47
  92. package/dist/core/engine-native.js +44 -14
  93. package/dist/core/glob.d.ts +10 -0
  94. package/dist/core/glob.js +33 -0
  95. package/dist/core/grants.d.ts +86 -0
  96. package/dist/core/grants.js +126 -0
  97. package/dist/core/host-events.d.ts +72 -0
  98. package/dist/core/host-events.js +597 -0
  99. package/dist/core/host-identity-links.d.ts +54 -0
  100. package/dist/core/host-identity-links.js +189 -0
  101. package/dist/core/host-status.d.ts +78 -0
  102. package/dist/core/host-status.js +228 -0
  103. package/dist/core/in-flight-runs.d.ts +8 -0
  104. package/dist/core/in-flight-runs.js +56 -0
  105. package/dist/core/issue-bridge.d.ts +60 -0
  106. package/dist/core/issue-bridge.js +189 -0
  107. package/dist/core/issue-dedupe.d.ts +70 -0
  108. package/dist/core/issue-dedupe.js +255 -0
  109. package/dist/core/issue-events.d.ts +42 -0
  110. package/dist/core/issue-events.js +155 -0
  111. package/dist/core/issue-status.d.ts +29 -0
  112. package/dist/core/issue-status.js +241 -0
  113. package/dist/core/issue-tracker-tools.d.ts +64 -0
  114. package/dist/core/issue-tracker-tools.js +850 -0
  115. package/dist/core/model-usage.d.ts +10 -0
  116. package/dist/core/model-usage.js +24 -0
  117. package/dist/core/provider-wording.d.ts +12 -0
  118. package/dist/core/provider-wording.js +44 -0
  119. package/dist/core/reconciler.d.ts +42 -2
  120. package/dist/core/reconciler.js +97 -2
  121. package/dist/core/repo-access.d.ts +99 -0
  122. package/dist/core/repo-access.js +136 -0
  123. package/dist/core/review-host-checks.d.ts +11 -0
  124. package/dist/core/review-host-checks.js +41 -0
  125. package/dist/core/review-host-tools.d.ts +47 -0
  126. package/dist/core/review-host-tools.js +354 -0
  127. package/dist/core/run-heartbeat.d.ts +27 -0
  128. package/dist/core/run-heartbeat.js +54 -0
  129. package/dist/core/run-pricing.d.ts +61 -0
  130. package/dist/core/run-pricing.js +56 -0
  131. package/dist/core/runner.d.ts +33 -8
  132. package/dist/core/runner.js +410 -62
  133. package/dist/core/scheduler.d.ts +4 -1
  134. package/dist/core/scheduler.js +3 -2
  135. package/dist/core/secrets.d.ts +11 -2
  136. package/dist/core/secrets.js +25 -6
  137. package/dist/core/self-defects.d.ts +80 -0
  138. package/dist/core/self-defects.js +180 -0
  139. package/dist/core/subagent-memory-tools.d.ts +1 -1
  140. package/dist/core/subagent-memory-tools.js +16 -3
  141. package/dist/core/tool-admin.d.ts +81 -0
  142. package/dist/core/tool-admin.js +129 -0
  143. package/dist/core/tool-names.d.ts +42 -0
  144. package/dist/core/tool-names.js +67 -0
  145. package/dist/core/untrusted-content.d.ts +32 -0
  146. package/dist/core/untrusted-content.js +72 -0
  147. package/dist/core/webhooks.d.ts +17 -2
  148. package/dist/core/webhooks.js +42 -3
  149. package/dist/generated/prisma/browser.d.ts +166 -0
  150. package/dist/generated/prisma/client.d.ts +166 -0
  151. package/dist/generated/prisma/commonInputTypes.d.ts +152 -52
  152. package/dist/generated/prisma/enums.d.ts +13 -0
  153. package/dist/generated/prisma/enums.js +12 -1
  154. package/dist/generated/prisma/internal/class.d.ts +242 -0
  155. package/dist/generated/prisma/internal/class.js +4 -4
  156. package/dist/generated/prisma/internal/prismaNamespace.d.ts +2571 -577
  157. package/dist/generated/prisma/internal/prismaNamespace.js +312 -6
  158. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +328 -0
  159. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +312 -6
  160. package/dist/generated/prisma/models/Agent.d.ts +682 -1
  161. package/dist/generated/prisma/models/AgentIssueProject.d.ts +1838 -0
  162. package/dist/generated/prisma/models/AgentIssueProject.js +1 -0
  163. package/dist/generated/prisma/models/AgentRepository.d.ts +1425 -0
  164. package/dist/generated/prisma/models/AgentRepository.js +1 -0
  165. package/dist/generated/prisma/models/AgentTool.d.ts +95 -1
  166. package/dist/generated/prisma/models/AuthUser.d.ts +56 -1
  167. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +258 -7
  168. package/dist/generated/prisma/models/CodingProxySession.d.ts +195 -2
  169. package/dist/generated/prisma/models/CodingRun.d.ts +1405 -95
  170. package/dist/generated/prisma/models/CodingRunServiceStatus.d.ts +1404 -0
  171. package/dist/generated/prisma/models/CodingRunServiceStatus.js +1 -0
  172. package/dist/generated/prisma/models/CodingService.d.ts +1348 -0
  173. package/dist/generated/prisma/models/CodingService.js +1 -0
  174. package/dist/generated/prisma/models/HostEventDelivery.d.ts +946 -0
  175. package/dist/generated/prisma/models/HostEventDelivery.js +1 -0
  176. package/dist/generated/prisma/models/HostIdentity.d.ts +1232 -0
  177. package/dist/generated/prisma/models/HostIdentity.js +1 -0
  178. package/dist/generated/prisma/models/HostIdentityLinkRequest.d.ts +1473 -0
  179. package/dist/generated/prisma/models/HostIdentityLinkRequest.js +1 -0
  180. package/dist/generated/prisma/models/IssueFingerprint.d.ts +1183 -0
  181. package/dist/generated/prisma/models/IssueFingerprint.js +1 -0
  182. package/dist/generated/prisma/models/IssuePullRequest.d.ts +1255 -0
  183. package/dist/generated/prisma/models/IssuePullRequest.js +1 -0
  184. package/dist/generated/prisma/models/ModelCatalogEntry.d.ts +1322 -0
  185. package/dist/generated/prisma/models/ModelCatalogEntry.js +1 -0
  186. package/dist/generated/prisma/models/Principal.d.ts +455 -0
  187. package/dist/generated/prisma/models/RegistryAllowance.d.ts +1148 -0
  188. package/dist/generated/prisma/models/RegistryAllowance.js +1 -0
  189. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +1219 -0
  190. package/dist/generated/prisma/models/RegistryApprovedVersion.js +1 -0
  191. package/dist/generated/prisma/models/RegistryFetch.d.ts +1428 -0
  192. package/dist/generated/prisma/models/RegistryFetch.js +1 -0
  193. package/dist/generated/prisma/models/RegistryPlanRefusal.d.ts +1294 -0
  194. package/dist/generated/prisma/models/RegistryPlanRefusal.js +1 -0
  195. package/dist/generated/prisma/models/RegistryVersionFact.d.ts +1085 -0
  196. package/dist/generated/prisma/models/RegistryVersionFact.js +1 -0
  197. package/dist/generated/prisma/models/ResourceGrant.d.ts +1437 -0
  198. package/dist/generated/prisma/models/ResourceGrant.js +1 -0
  199. package/dist/generated/prisma/models/Run.d.ts +1402 -82
  200. package/dist/generated/prisma/models/RunAttribution.d.ts +1259 -0
  201. package/dist/generated/prisma/models/RunAttribution.js +1 -0
  202. package/dist/generated/prisma/models/RunHostCheck.d.ts +1239 -0
  203. package/dist/generated/prisma/models/RunHostCheck.js +1 -0
  204. package/dist/generated/prisma/models/RunHostStatus.d.ts +1315 -0
  205. package/dist/generated/prisma/models/RunHostStatus.js +1 -0
  206. package/dist/generated/prisma/models/RunIssueStatus.d.ts +1199 -0
  207. package/dist/generated/prisma/models/RunIssueStatus.js +1 -0
  208. package/dist/generated/prisma/models/RunModelUsage.d.ts +1316 -0
  209. package/dist/generated/prisma/models/RunModelUsage.js +1 -0
  210. package/dist/generated/prisma/models/Tool.d.ts +15 -3
  211. package/dist/generated/prisma/models/WorkItem.d.ts +1408 -0
  212. package/dist/generated/prisma/models/WorkItem.js +1 -0
  213. package/dist/generated/prisma/models.d.ts +22 -0
  214. package/dist/help/build.d.ts +1 -0
  215. package/dist/help/build.js +9 -0
  216. package/dist/help/catalog.d.ts +24 -0
  217. package/dist/help/catalog.js +160 -0
  218. package/dist/help/cli.d.ts +2 -0
  219. package/dist/help/cli.js +65 -0
  220. package/dist/help/runtime.d.ts +3 -0
  221. package/dist/help/runtime.js +44 -0
  222. package/dist/help/search.d.ts +9 -0
  223. package/dist/help/search.js +104 -0
  224. package/dist/help-index.json +999 -0
  225. package/dist/import/cli-args.js +3 -2
  226. package/dist/import/create.d.ts +5 -0
  227. package/dist/import/create.js +67 -13
  228. package/dist/import/index.js +19 -9
  229. package/dist/import/neutral-schema.d.ts +18 -18
  230. package/dist/knowledge/check.d.ts +13 -0
  231. package/dist/knowledge/check.js +69 -0
  232. package/dist/knowledge/cli.d.ts +14 -0
  233. package/dist/knowledge/cli.js +67 -0
  234. package/dist/knowledge/concept.d.ts +54 -0
  235. package/dist/knowledge/concept.js +78 -0
  236. package/dist/knowledge/note.d.ts +11 -0
  237. package/dist/knowledge/note.js +39 -0
  238. package/dist/knowledge/relevance.d.ts +11 -0
  239. package/dist/knowledge/relevance.js +14 -0
  240. package/dist/knowledge/span-hash.d.ts +3 -0
  241. package/dist/knowledge/span-hash.js +16 -0
  242. package/dist/mcp/auth/access.d.ts +72 -0
  243. package/dist/mcp/auth/access.js +58 -0
  244. package/dist/mcp/auth/grants-cli.d.ts +149 -0
  245. package/dist/mcp/auth/grants-cli.js +518 -0
  246. package/dist/mcp/auth/host-account-cli.d.ts +2 -0
  247. package/dist/mcp/auth/host-account-cli.js +47 -0
  248. package/dist/mcp/auth/ownership.d.ts +25 -51
  249. package/dist/mcp/auth/ownership.js +19 -14
  250. package/dist/mcp/auth/repo-authorization.d.ts +22 -0
  251. package/dist/mcp/auth/repo-authorization.js +51 -0
  252. package/dist/mcp/auth/resource-server.d.ts +33 -2
  253. package/dist/mcp/auth/resource-server.js +99 -3
  254. package/dist/mcp/auth/self-hosted/browser.js +2 -2
  255. package/dist/mcp/auth/self-hosted/cli.js +47 -13
  256. package/dist/mcp/auth/self-hosted/credentials.d.ts +23 -5
  257. package/dist/mcp/auth/self-hosted/credentials.js +62 -4
  258. package/dist/mcp/auth/self-hosted/session.d.ts +7 -6
  259. package/dist/mcp/context.d.ts +30 -1
  260. package/dist/mcp/errors.d.ts +25 -6
  261. package/dist/mcp/errors.js +98 -0
  262. package/dist/mcp/host-events/deliveries.d.ts +9 -0
  263. package/dist/mcp/host-events/deliveries.js +17 -0
  264. package/dist/mcp/host-events/github-ingress.d.ts +38 -0
  265. package/dist/mcp/host-events/github-ingress.js +83 -0
  266. package/dist/mcp/host-events/github-user-callback.d.ts +18 -0
  267. package/dist/mcp/host-events/github-user-callback.js +50 -0
  268. package/dist/mcp/host-events/jira-ingress.d.ts +29 -0
  269. package/dist/mcp/host-events/jira-ingress.js +92 -0
  270. package/dist/mcp/index.d.ts +10 -1
  271. package/dist/mcp/index.js +187 -19
  272. package/dist/mcp/server.js +32 -11
  273. package/dist/mcp/tools/agents.js +519 -50
  274. package/dist/mcp/tools/budget-groups.js +3 -3
  275. package/dist/mcp/tools/cost-report.d.ts +8 -0
  276. package/dist/mcp/tools/cost-report.js +60 -0
  277. package/dist/mcp/tools/datastore.js +22 -15
  278. package/dist/mcp/tools/grants.d.ts +2 -0
  279. package/dist/mcp/tools/grants.js +239 -0
  280. package/dist/mcp/tools/help.d.ts +5 -0
  281. package/dist/mcp/tools/help.js +67 -0
  282. package/dist/mcp/tools/host-accounts.d.ts +2 -0
  283. package/dist/mcp/tools/host-accounts.js +114 -0
  284. package/dist/mcp/tools/issue-projects.d.ts +2 -0
  285. package/dist/mcp/tools/issue-projects.js +238 -0
  286. package/dist/mcp/tools/memory.d.ts +7 -1
  287. package/dist/mcp/tools/memory.js +5 -5
  288. package/dist/mcp/tools/model-catalog.d.ts +22 -0
  289. package/dist/mcp/tools/model-catalog.js +423 -0
  290. package/dist/mcp/tools/repositories.d.ts +2 -0
  291. package/dist/mcp/tools/repositories.js +182 -0
  292. package/dist/mcp/tools/runs.d.ts +6 -0
  293. package/dist/mcp/tools/runs.js +60 -6
  294. package/dist/mcp/tools/scheduling.js +3 -6
  295. package/dist/mcp/tools/secrets.js +18 -6
  296. package/dist/mcp/tools/services.d.ts +2 -0
  297. package/dist/mcp/tools/services.js +222 -0
  298. package/dist/mcp/tools/subagents.js +52 -16
  299. package/dist/mcp/tools/tools.d.ts +41 -0
  300. package/dist/mcp/tools/tools.js +201 -40
  301. package/dist/mcp/tools/trigger.js +65 -7
  302. package/dist/mcp/tools/webhooks.js +15 -4
  303. package/dist/mcp/transport/streamable-http.d.ts +15 -0
  304. package/dist/mcp/transport/streamable-http.js +55 -3
  305. package/dist/mcp/webhooks/ingress.d.ts +2 -1
  306. package/dist/mcp/webhooks/ingress.js +9 -2
  307. package/dist/providers/auth/delegating.d.ts +19 -0
  308. package/dist/providers/auth/delegating.js +71 -0
  309. package/dist/providers/auth/index.d.ts +2 -0
  310. package/dist/providers/auth/index.js +11 -0
  311. package/dist/providers/auth/self-hosted.d.ts +10 -2
  312. package/dist/providers/auth/self-hosted.js +55 -6
  313. package/dist/providers/auth/types.d.ts +6 -0
  314. package/dist/providers/coding-proxy/memory-ledger.d.ts +4 -1
  315. package/dist/providers/coding-proxy/memory-ledger.js +31 -3
  316. package/dist/providers/coding-proxy/metering.d.ts +6 -1
  317. package/dist/providers/coding-proxy/metering.js +41 -4
  318. package/dist/providers/coding-proxy/prisma-ledger.d.ts +17 -0
  319. package/dist/providers/coding-proxy/prisma-ledger.js +106 -8
  320. package/dist/providers/coding-proxy/proxy.d.ts +25 -2
  321. package/dist/providers/coding-proxy/proxy.js +561 -38
  322. package/dist/providers/coding-proxy/registry/audit.d.ts +131 -0
  323. package/dist/providers/coding-proxy/registry/audit.js +380 -0
  324. package/dist/providers/coding-proxy/registry/bounded-fetch.d.ts +16 -0
  325. package/dist/providers/coding-proxy/registry/bounded-fetch.js +77 -0
  326. package/dist/providers/coding-proxy/registry/plan.d.ts +58 -0
  327. package/dist/providers/coding-proxy/registry/plan.js +304 -0
  328. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +34 -0
  329. package/dist/providers/coding-proxy/registry/prisma-store.js +151 -0
  330. package/dist/providers/coding-proxy/registry/service.d.ts +213 -0
  331. package/dist/providers/coding-proxy/registry/service.js +1137 -0
  332. package/dist/providers/coding-proxy/registry/store.d.ts +127 -0
  333. package/dist/providers/coding-proxy/registry/store.js +70 -0
  334. package/dist/providers/coding-proxy/runtime.d.ts +17 -0
  335. package/dist/providers/coding-proxy/runtime.js +63 -0
  336. package/dist/providers/coding-proxy/secure-fetch.js +0 -1
  337. package/dist/providers/coding-proxy/server.d.ts +11 -0
  338. package/dist/providers/coding-proxy/server.js +163 -0
  339. package/dist/providers/coding-proxy/types.d.ts +33 -1
  340. package/dist/providers/coding-proxy/types.js +12 -1
  341. package/dist/providers/engine/types.d.ts +29 -0
  342. package/dist/providers/executor/build.d.ts +2 -2
  343. package/dist/providers/executor/composition.d.ts +3 -0
  344. package/dist/providers/executor/composition.js +28 -1
  345. package/dist/providers/executor/container.d.ts +134 -4
  346. package/dist/providers/executor/container.js +394 -37
  347. package/dist/providers/executor/dbos.d.ts +4 -3
  348. package/dist/providers/executor/dbos.js +7 -5
  349. package/dist/providers/executor/in-process.d.ts +2 -3
  350. package/dist/providers/executor/routing.d.ts +13 -0
  351. package/dist/providers/executor/routing.js +18 -0
  352. package/dist/providers/executor/types.d.ts +34 -0
  353. package/dist/providers/issue-tracker/adf.d.ts +31 -0
  354. package/dist/providers/issue-tracker/adf.js +181 -0
  355. package/dist/providers/issue-tracker/index.d.ts +5 -0
  356. package/dist/providers/issue-tracker/index.js +12 -0
  357. package/dist/providers/issue-tracker/jira-client.d.ts +41 -0
  358. package/dist/providers/issue-tracker/jira-client.js +151 -0
  359. package/dist/providers/issue-tracker/jira-events.d.ts +3 -0
  360. package/dist/providers/issue-tracker/jira-events.js +98 -0
  361. package/dist/providers/issue-tracker/jira.d.ts +116 -0
  362. package/dist/providers/issue-tracker/jira.js +502 -0
  363. package/dist/providers/issue-tracker/types.d.ts +269 -0
  364. package/dist/providers/issue-tracker/types.js +16 -0
  365. package/dist/providers/jobs/claude-tool-setup.d.ts +23 -0
  366. package/dist/providers/jobs/claude-tool-setup.js +50 -0
  367. package/dist/providers/jobs/collect-prune.d.ts +7 -0
  368. package/dist/providers/jobs/collect-prune.js +27 -0
  369. package/dist/providers/jobs/docker-isolation.d.ts +48 -3
  370. package/dist/providers/jobs/docker-isolation.js +213 -22
  371. package/dist/providers/jobs/docker-services.d.ts +35 -0
  372. package/dist/providers/jobs/docker-services.js +191 -0
  373. package/dist/providers/jobs/docker.d.ts +53 -2
  374. package/dist/providers/jobs/docker.js +307 -32
  375. package/dist/providers/jobs/fake-kubernetes-api.d.ts +1 -0
  376. package/dist/providers/jobs/fake-kubernetes-api.js +12 -3
  377. package/dist/providers/jobs/kubernetes-isolation.d.ts +17 -2
  378. package/dist/providers/jobs/kubernetes-isolation.js +238 -57
  379. package/dist/providers/jobs/kubernetes-platform.d.ts +10 -4
  380. package/dist/providers/jobs/kubernetes-platform.js +11 -5
  381. package/dist/providers/jobs/kubernetes-preflight.js +3 -0
  382. package/dist/providers/jobs/kubernetes.d.ts +24 -2
  383. package/dist/providers/jobs/kubernetes.js +153 -22
  384. package/dist/providers/jobs/service-state.d.ts +22 -0
  385. package/dist/providers/jobs/service-state.js +17 -0
  386. package/dist/providers/jobs/types.d.ts +18 -0
  387. package/dist/providers/llm/anthropic.d.ts +3 -3
  388. package/dist/providers/llm/anthropic.js +3 -5
  389. package/dist/providers/llm/bedrock.d.ts +3 -3
  390. package/dist/providers/llm/bedrock.js +3 -8
  391. package/dist/providers/llm/catalog-lookup.d.ts +10 -0
  392. package/dist/providers/llm/catalog-lookup.js +15 -0
  393. package/dist/providers/llm/catalog-shipped.d.ts +18 -0
  394. package/dist/providers/llm/catalog-shipped.js +197 -0
  395. package/dist/providers/llm/catalog-store.d.ts +58 -0
  396. package/dist/providers/llm/catalog-store.js +138 -0
  397. package/dist/providers/llm/catalog-types.d.ts +66 -0
  398. package/dist/providers/llm/catalog-types.js +64 -0
  399. package/dist/providers/llm/catalog.d.ts +61 -0
  400. package/dist/providers/llm/catalog.js +147 -0
  401. package/dist/providers/llm/claude-messages.d.ts +5 -1
  402. package/dist/providers/llm/claude-messages.js +1 -0
  403. package/dist/providers/llm/claude-provider.d.ts +10 -12
  404. package/dist/providers/llm/claude-provider.js +15 -6
  405. package/dist/providers/llm/index.d.ts +9 -6
  406. package/dist/providers/llm/index.js +8 -5
  407. package/dist/providers/llm/openai.d.ts +14 -5
  408. package/dist/providers/llm/openai.js +24 -14
  409. package/dist/providers/llm/pricing-core.d.ts +5 -3
  410. package/dist/providers/llm/registration.js +8 -12
  411. package/dist/providers/llm/routing.d.ts +21 -11
  412. package/dist/providers/llm/routing.js +47 -13
  413. package/dist/providers/llm/types.d.ts +12 -0
  414. package/dist/providers/llm/types.js +8 -1
  415. package/dist/providers/review-host/diff-lines.d.ts +16 -0
  416. package/dist/providers/review-host/diff-lines.js +59 -0
  417. package/dist/providers/review-host/github-events.d.ts +6 -0
  418. package/dist/providers/review-host/github-events.js +226 -0
  419. package/dist/providers/review-host/github-user-auth.d.ts +38 -0
  420. package/dist/providers/review-host/github-user-auth.js +128 -0
  421. package/dist/providers/review-host/github.d.ts +57 -0
  422. package/dist/providers/review-host/github.js +568 -0
  423. package/dist/providers/review-host/index.d.ts +12 -0
  424. package/dist/providers/review-host/index.js +30 -0
  425. package/dist/providers/review-host/review-format.d.ts +19 -0
  426. package/dist/providers/review-host/review-format.js +59 -0
  427. package/dist/providers/review-host/types.d.ts +309 -0
  428. package/dist/providers/review-host/types.js +24 -0
  429. package/dist/providers/vcs/git.d.ts +16 -6
  430. package/dist/providers/vcs/git.js +78 -34
  431. package/dist/providers/vcs/github.d.ts +94 -3
  432. package/dist/providers/vcs/github.js +223 -17
  433. package/dist/providers/vcs/types.d.ts +48 -4
  434. package/dist/quickstart/index.d.ts +2 -0
  435. package/dist/quickstart/index.js +36 -8
  436. package/dist/sandbox/fetch-policy.d.ts +20 -2
  437. package/dist/sandbox/fetch-policy.js +64 -3
  438. package/dist/sandbox/host-functions.d.ts +9 -1
  439. package/dist/sandbox/host-functions.js +12 -5
  440. package/dist/serve.js +8 -2
  441. package/dist/viewer/api-schema.d.ts +2757 -0
  442. package/dist/viewer/api-schema.js +165 -0
  443. package/dist/viewer/build-schemas.d.ts +2 -0
  444. package/dist/viewer/build-schemas.js +18 -0
  445. package/dist/viewer/event-bus.d.ts +38 -0
  446. package/dist/viewer/event-bus.js +232 -0
  447. package/dist/viewer/graph.d.ts +40 -0
  448. package/dist/viewer/graph.js +243 -0
  449. package/dist/viewer/http.d.ts +30 -0
  450. package/dist/viewer/http.js +133 -0
  451. package/dist/viewer/run-detail.d.ts +4 -0
  452. package/dist/viewer/run-detail.js +61 -0
  453. package/dist/wardby-bin.js +11 -0
  454. package/docs/README.md +40 -0
  455. package/docs/agent-recipes.md +383 -0
  456. package/docs/architecture-runtime.md +90 -0
  457. package/docs/assets/brand/wardby-icon-512.png +0 -0
  458. package/docs/assets/brand/wardby-icon.svg +16 -0
  459. package/docs/assets/brand/wardby-mascot-profile-512.png +0 -0
  460. package/docs/assets/brand/wardby-mascot.png +0 -0
  461. package/docs/assets/brand/wardby-mascot.svg +5 -0
  462. package/docs/assets/wardby-workflow.svg +106 -0
  463. package/docs/code-review-agents.md +508 -0
  464. package/docs/coding-agent-setup.md +175 -0
  465. package/docs/coding-packages.md +455 -0
  466. package/docs/coding-services.md +300 -0
  467. package/docs/coding-worker-byo-images.md +98 -0
  468. package/docs/coding-worker-isolation.md +1068 -0
  469. package/docs/getting-started-gke.md +632 -0
  470. package/docs/getting-started-identity-provider.md +319 -0
  471. package/docs/getting-started.md +147 -0
  472. package/docs/jira-agents.md +649 -0
  473. package/docs/knowledge.md +387 -0
  474. package/docs/models.md +221 -0
  475. package/docs/observability.md +53 -0
  476. package/docs/release-verification.md +66 -0
  477. package/docs/security-deployment.md +667 -0
  478. package/docs/viewer-api.md +142 -0
  479. package/help/admin-viewer.md +39 -0
  480. package/help/agent-recipes.md +173 -0
  481. package/help/architecture-agent.md +189 -0
  482. package/help/builder-agent.md +80 -0
  483. package/help/code-review-agents.md +37 -0
  484. package/help/coding-packages.md +31 -0
  485. package/help/coding-services.md +71 -0
  486. package/help/cost-attribution.md +67 -0
  487. package/help/creating-agents.md +90 -0
  488. package/help/deploy-gke.md +45 -0
  489. package/help/deployment-targets.md +39 -0
  490. package/help/errors/budget-group-exhausted.md +25 -0
  491. package/help/errors/docker-isolation-unsupported.md +26 -0
  492. package/help/errors/model-unavailable.md +63 -0
  493. package/help/errors/protected-path.md +45 -0
  494. package/help/errors/repo-access.md +27 -0
  495. package/help/errors/service-declaration-invalid.md +27 -0
  496. package/help/errors/service-declaration-unavailable.md +25 -0
  497. package/help/errors/service-launcher-unsupported.md +30 -0
  498. package/help/errors/service-not-allowed.md +27 -0
  499. package/help/errors/service-unknown.md +23 -0
  500. package/help/errors/service-unready.md +49 -0
  501. package/help/getting-started.md +32 -0
  502. package/help/github.md +48 -0
  503. package/help/identity-and-access.md +44 -0
  504. package/help/jira.md +135 -0
  505. package/help/knowledge.md +47 -0
  506. package/help/mcp.md +30 -0
  507. package/help/models.md +90 -0
  508. package/help/native-capabilities.md +30 -0
  509. package/help/observability.md +41 -0
  510. package/help/operating-agents.md +36 -0
  511. package/help/security.md +27 -0
  512. package/help/troubleshooting/budgets.md +32 -0
  513. package/help/troubleshooting/coding-workers.md +47 -0
  514. package/help/troubleshooting/repository-access.md +27 -0
  515. package/package.json +14 -3
  516. package/prisma/migrations/20260925010000_coding_collect_exclude/migration.sql +8 -0
  517. package/prisma/migrations/20260925015000_allowed_egress_default/migration.sql +8 -0
  518. package/prisma/migrations/20260925020000_coding_package_registry/migration.sql +55 -0
  519. package/prisma/migrations/20260925030000_tool_name_per_owner/migration.sql +11 -0
  520. package/prisma/migrations/20260926010000_run_trigger_host_event/migration.sql +7 -0
  521. package/prisma/migrations/20260926020000_code_review_hosts/migration.sql +53 -0
  522. package/prisma/migrations/20260926030000_auth_user_roles/migration.sql +9 -0
  523. package/prisma/migrations/20260926040000_agent_effort/migration.sql +6 -0
  524. package/prisma/migrations/20260926050000_registry_lockfile_plan/migration.sql +32 -0
  525. package/prisma/migrations/20260926050000_repo_access_authorization/migration.sql +82 -0
  526. package/prisma/migrations/20260926060000_registry_plan_refusal/migration.sql +19 -0
  527. package/prisma/migrations/20260926100000_registry_plan_refusal_published_at/migration.sql +5 -0
  528. package/prisma/migrations/20260926190000_run_host_status/migration.sql +18 -0
  529. package/prisma/migrations/20260926210000_run_host_status_at_dispatch/migration.sql +5 -0
  530. package/prisma/migrations/20260927010000_resource_grants/migration.sql +72 -0
  531. package/prisma/migrations/20260927020000_proxy_session_budget_exhausted/migration.sql +3 -0
  532. package/prisma/migrations/20260927030000_coding_debug_trace/migration.sql +4 -0
  533. package/prisma/migrations/20260927040000_proxy_session_upstream_failure/migration.sql +3 -0
  534. package/prisma/migrations/20260927050000_coding_run_services/migration.sql +74 -0
  535. package/prisma/migrations/20260928000000_coding_run_tool_image/migration.sql +5 -0
  536. package/prisma/migrations/20260930000000_jira_issue_projects/migration.sql +34 -0
  537. package/prisma/migrations/20261001000000_jira_phase2_allowlists/migration.sql +3 -0
  538. package/prisma/migrations/20261001010000_jira_link_types_allowlist/migration.sql +2 -0
  539. package/prisma/migrations/20261002000000_jira_coding_bridge/migration.sql +28 -0
  540. package/prisma/migrations/20261002010000_jira_issue_creation/migration.sql +25 -0
  541. package/prisma/migrations/20261003000000_issue_cost_attribution/migration.sql +56 -0
  542. package/prisma/migrations/20261003010000_coding_run_service_status/migration.sql +23 -0
  543. package/prisma/migrations/20261003020000_viewer_notify/migration.sql +54 -0
  544. package/prisma/migrations/20261003030000_viewer_notify_fixes/migration.sql +47 -0
  545. package/prisma/migrations/20261003040000_viewer_indexes/migration.sql +12 -0
  546. package/prisma/migrations/20261004000000_model_catalog/migration.sql +26 -0
  547. package/prisma/schema.prisma +663 -21
  548. package/dist/mcp/tools/models.d.ts +0 -8
  549. package/dist/mcp/tools/models.js +0 -15
  550. package/dist/providers/llm/pricing-anthropic.d.ts +0 -4
  551. package/dist/providers/llm/pricing-anthropic.js +0 -30
  552. package/dist/providers/llm/pricing-bedrock-claude.d.ts +0 -12
  553. package/dist/providers/llm/pricing-bedrock-claude.js +0 -37
  554. package/dist/providers/llm/pricing.d.ts +0 -30
  555. package/dist/providers/llm/pricing.js +0 -74
@@ -1,7 +1,15 @@
1
1
  import { McpError } from "../errors.js";
2
- import { requireReadableAgent } from "../auth/ownership.js";
2
+ import { agentAccess, requireAgentAccess } from "../auth/access.js";
3
3
  import { publicCodingRunResult } from "../../coding/protocol.js";
4
+ import { countPlanRefusals, summarizeRegistryFetches } from "../../coding/registry/report.js";
5
+ import { storedServiceLabels } from "../../coding/services/catalog.js";
4
6
  import { textResult } from "./text-result.js";
7
+ /**
8
+ * Run visibility (resource-sharing grants spec §3.5, A6): a run's output is
9
+ * the triggerer's and the agent owner's, never every reader's. The owner
10
+ * (and the stdio operator) sees every run; anyone else only runs with
11
+ * Run.triggeredById equal to themselves.
12
+ */
5
13
  export function registerRunTools(mcp) {
6
14
  mcp.registerTool({
7
15
  name: "list_runs",
@@ -12,9 +20,13 @@ export function registerRunTools(mcp) {
12
20
  required: ["agentId"],
13
21
  },
14
22
  handler: async (args, ctx) => {
15
- await requireReadableAgent(ctx.db, args.agentId, ctx.principal.id);
23
+ const { access } = await requireAgentAccess(ctx, args.agentId, "read");
16
24
  const runs = await ctx.db.run.findMany({
17
- where: { agentId: args.agentId, ...(args.status ? { status: args.status } : {}) },
25
+ where: {
26
+ agentId: args.agentId,
27
+ ...(args.status ? { status: args.status } : {}),
28
+ ...(access === "owner" ? {} : { triggeredById: ctx.principal.id }),
29
+ },
18
30
  take: args.limit,
19
31
  orderBy: { startedAt: "desc" },
20
32
  });
@@ -40,21 +52,63 @@ export function registerRunTools(mcp) {
40
52
  inputSchema: { type: "object", properties: { runId: { type: "string" } }, required: ["runId"] },
41
53
  handler: async (args, ctx) => {
42
54
  const run = await ctx.db.run.findUnique({ where: { id: args.runId } });
55
+ const notFound = new McpError(404, `Run "${args.runId}" not found.`);
43
56
  if (!run)
44
- throw new McpError(404, `Run "${args.runId}" not found.`);
45
- await requireReadableAgent(ctx.db, run.agentId, ctx.principal.id);
57
+ throw notFound;
58
+ // Its triggerer keeps seeing it even after losing access to the agent;
59
+ // otherwise only the agent's owner. read on the agent is not enough.
60
+ if (run.triggeredById !== ctx.principal.id) {
61
+ const agent = await ctx.db.agent.findUnique({ where: { id: run.agentId } });
62
+ if (!agent || (await agentAccess(ctx, agent)) !== "owner")
63
+ throw notFound;
64
+ }
46
65
  const codingRun = await ctx.db.codingRun.findUnique({
47
66
  where: { runId: run.id },
48
- select: { result: true, queuedAt: true },
67
+ select: {
68
+ result: true,
69
+ queuedAt: true,
70
+ failureCategory: true,
71
+ diagnosticId: true,
72
+ debugTrace: true,
73
+ services: true,
74
+ },
49
75
  });
50
76
  const codingResult = publicCodingRunResult(codingRun?.result);
51
77
  // A pending coding run with queuedAt is waiting for a concurrency slot
52
78
  // (CODING_MAX_CONCURRENT), not stuck.
53
79
  const codingQueuedAt = run.status === "pending" && codingRun?.queuedAt ? codingRun.queuedAt.toISOString() : undefined;
80
+ // Packages served/refused only exist for coding runs; a non-coding run
81
+ // has no RegistryFetch rows at all, so skip the query entirely.
82
+ const registryFetches = codingRun
83
+ ? await ctx.db.registryFetch.findMany({ where: { runId: run.id }, orderBy: { createdAt: "asc" } })
84
+ : [];
85
+ const { packages, packageRefusals } = summarizeRegistryFetches(registryFetches);
86
+ // Lockfile verification (POST /registry/<ecosystem>/-/plan): exact
87
+ // versions approved for the run, and distinct entries it refused.
88
+ const packagePlan = codingRun
89
+ ? {
90
+ approved: await ctx.db.registryApprovedVersion.count({ where: { runId: run.id } }),
91
+ refused: countPlanRefusals(registryFetches),
92
+ }
93
+ : undefined;
94
+ // A failed coding run's error is only an opaque id; these two say which
95
+ // stage failed and are the key an operator searches the control-plane
96
+ // log for (the real reason is logged there, never persisted). Both are
97
+ // designed to be safe to show the agent's owner (schema.prisma).
98
+ const failureCategory = codingRun?.failureCategory ?? undefined;
99
+ const diagnosticId = codingRun?.diagnosticId ?? undefined;
100
+ // Which services the run started with ("postgres 16"); never their images or environments.
101
+ const services = codingRun ? storedServiceLabels(codingRun.services) : [];
54
102
  return textResult({
55
103
  ...run,
56
104
  ...(codingResult ? { codingResult } : {}),
105
+ ...(failureCategory ? { failureCategory } : {}),
106
+ ...(diagnosticId ? { diagnosticId } : {}),
57
107
  ...(codingQueuedAt ? { codingQueuedAt } : {}),
108
+ // An admin turned on the debug trace: the worker's full trace is in its pod log.
109
+ ...(codingRun?.debugTrace ? { debugTrace: true } : {}),
110
+ ...(services.length > 0 ? { services } : {}),
111
+ ...(codingRun ? { packages, packageRefusals, packagePlan } : {}),
58
112
  });
59
113
  },
60
114
  });
@@ -1,7 +1,7 @@
1
1
  import { Prisma } from "#prisma";
2
2
  import { validateCronExpression } from "../../core/cron.js";
3
3
  import { McpError } from "../errors.js";
4
- import { assertCanMutate, requireOwnedAgent } from "../auth/ownership.js";
4
+ import { assertAgentAccess, requireAgentAccess } from "../auth/access.js";
5
5
  import { textResult } from "./text-result.js";
6
6
  export function registerSchedulingTools(mcp) {
7
7
  mcp.registerTool({
@@ -20,10 +20,7 @@ export function registerSchedulingTools(mcp) {
20
20
  throw new McpError(400, `Invalid schedule/timezone: ${err instanceof Error ? err.message : String(err)}`);
21
21
  }
22
22
  const agent = await ctx.db.$transaction(async (tx) => {
23
- const existing = await tx.agent.findUnique({ where: { id: args.agentId }, include: { codingProfile: true } });
24
- if (!existing)
25
- throw new McpError(404, `Agent "${args.agentId}" not found.`);
26
- assertCanMutate(existing.ownerId, ctx.principal.id, `Agent "${args.agentId}" is not owned by the caller.`);
23
+ const { agent: existing } = await assertAgentAccess(ctx, await tx.agent.findUnique({ where: { id: args.agentId }, include: { codingProfile: true } }), args.agentId, "write", tx);
27
24
  if (existing.kind === "coding" && !existing.codingProfile?.defaultTask) {
28
25
  throw new McpError(400, "A default task is required before enabling a coding-agent schedule.");
29
26
  }
@@ -40,7 +37,7 @@ export function registerSchedulingTools(mcp) {
40
37
  scope: "agents:write",
41
38
  inputSchema: { type: "object", properties: { agentId: { type: "string" } }, required: ["agentId"] },
42
39
  handler: async (args, ctx) => {
43
- await requireOwnedAgent(ctx.db, args.agentId, ctx.principal.id);
40
+ await requireAgentAccess(ctx, args.agentId, "write");
44
41
  const agent = await ctx.db.agent.update({ where: { id: args.agentId }, data: { scheduleEnabled: false } });
45
42
  return textResult(agent);
46
43
  },
@@ -6,7 +6,8 @@
6
6
  import { inputRequired, inputResponse } from "@modelcontextprotocol/server";
7
7
  import { createSecret, listSecrets, attachSecret, detachSecret, deleteSecret } from "../../core/secrets.js";
8
8
  import { McpError } from "../errors.js";
9
- import { requireOwnedAgent, requireOwnedSecret } from "../auth/ownership.js";
9
+ import { requireOwnedSecret } from "../auth/ownership.js";
10
+ import { requireAgentAccess, requireBindingOwner } from "../auth/access.js";
10
11
  import { getSecretElicitationOutcome } from "./secret-elicitation.js";
11
12
  import { textResult } from "./text-result.js";
12
13
  export function registerSecretsTools(mcp, opts) {
@@ -87,9 +88,15 @@ export function registerSecretsTools(mcp, opts) {
87
88
  required: ["agentId", "name"],
88
89
  },
89
90
  handler: async (args, ctx) => {
90
- await requireOwnedAgent(ctx.db, args.agentId, ctx.principal.id);
91
+ // Strictly the agent owner's own secret on the owner's own agent
92
+ // (A2/S2-2): a binding hands the value to every tool the owner lets
93
+ // read it. Not even the stdio operator crosses owners.
94
+ const { agent } = await requireAgentAccess(ctx, args.agentId, "read");
95
+ requireBindingOwner(ctx, agent);
96
+ const ownerId = agent.ownerId;
91
97
  try {
92
- await attachSecret(args.agentId, args.name, ctx.principal.id, ctx.db, args.alias ?? args.name);
98
+ // Resolved among the agent owner's secrets (== the caller here).
99
+ await attachSecret(args.agentId, args.name, ownerId, ctx.db, args.alias ?? args.name);
93
100
  }
94
101
  catch (err) {
95
102
  throw new McpError(404, err instanceof Error ? err.message : String(err));
@@ -100,15 +107,20 @@ export function registerSecretsTools(mcp, opts) {
100
107
  mcp.registerTool({
101
108
  name: "detach_secret",
102
109
  scope: "secrets:write",
110
+ description: "Detaches a secret from an agent. `name` is the alias it was attached under; the secret's own name also works when no attachment has that alias.",
103
111
  inputSchema: {
104
112
  type: "object",
105
113
  properties: { agentId: { type: "string" }, name: { type: "string" } },
106
114
  required: ["agentId", "name"],
107
115
  },
108
116
  handler: async (args, ctx) => {
109
- await requireOwnedAgent(ctx.db, args.agentId, ctx.principal.id);
110
- await detachSecret(args.agentId, args.name, ctx.db);
111
- return textResult({ detached: true });
117
+ const { agent } = await requireAgentAccess(ctx, args.agentId, "read");
118
+ requireBindingOwner(ctx, agent);
119
+ const count = await detachSecret(args.agentId, args.name, ctx.db);
120
+ if (count === 0) {
121
+ throw new McpError(404, `No secret is attached to agent "${args.agentId}" as "${args.name}".`);
122
+ }
123
+ return textResult({ detached: true, count });
112
124
  },
113
125
  });
114
126
  mcp.registerTool({
@@ -0,0 +1,2 @@
1
+ import type { WardbyMcpServer } from "../server.js";
2
+ export declare function registerServiceTools(mcp: WardbyMcpServer): void;
@@ -0,0 +1,222 @@
1
+ /**
2
+ * The coding-run service catalog over MCP (docs/coding-services.md). Reading
3
+ * it needs only agents:read: agent owners need to see which services exist and
4
+ * the variables (testEnv) their tests will get before allowing one, and entries
5
+ * hold no secrets (serviceEnv values are throwaway per-run test credentials).
6
+ * Changing it needs services:manage, a privileged scope honoured only with a
7
+ * role granting it (service-manager or admin; resource-server.ts): an entry
8
+ * decides which image runs next to every coding run that names it, and with
9
+ * what. Each change is audit-logged (event coding.service_catalog.<action>).
10
+ * Built-in entries ship with wardby and change only with a release.
11
+ */
12
+ import { z } from "zod";
13
+ import { CodingServiceDefinitionSchema, catalogEntryFromRow, codingServiceNameSchema, codingServiceVersionSchema, } from "../../coding/services/catalog.js";
14
+ import { logger } from "../../core/logger.js";
15
+ import { McpError } from "../errors.js";
16
+ import { textResult } from "./text-result.js";
17
+ const servicesLog = logger.child({ module: "mcp-services" });
18
+ const KeySchema = z.object({ name: codingServiceNameSchema, version: codingServiceVersionSchema }).strict();
19
+ /** Everything but the key is optional here; the merged entry is validated in full. */
20
+ const UpdateSchema = z
21
+ .object({
22
+ name: codingServiceNameSchema,
23
+ version: codingServiceVersionSchema,
24
+ image: z.unknown().optional(),
25
+ port: z.unknown().optional(),
26
+ serviceEnv: z.unknown().optional(),
27
+ testEnv: z.unknown().optional(),
28
+ readiness: z.unknown().optional(),
29
+ resources: z.unknown().optional(),
30
+ dataPath: z.unknown().optional(),
31
+ writablePaths: z.unknown().optional(),
32
+ })
33
+ .strict();
34
+ function parse(schema, label, value) {
35
+ const result = schema.safeParse(value);
36
+ if (!result.success) {
37
+ const details = result.error.issues
38
+ .map((issue) => `${issue.path.join(".") || "input"}: ${issue.message}`)
39
+ .join("; ");
40
+ throw new McpError(400, `Invalid ${label}: ${details}`);
41
+ }
42
+ return result.data;
43
+ }
44
+ function audit(ctx, action, entry) {
45
+ servicesLog.info({
46
+ event: `coding.service_catalog.${action}`,
47
+ name: entry.name,
48
+ version: entry.version,
49
+ ...(entry.image ? { image: entry.image } : {}),
50
+ by: ctx.principal.id,
51
+ }, "coding service catalog changed");
52
+ }
53
+ async function findEntry(ctx, key) {
54
+ const row = await ctx.db.codingService.findUnique({ where: { name_version: key } });
55
+ if (!row)
56
+ throw new McpError(404, `No coding service "${key.name} ${key.version}" in the catalog.`);
57
+ return row;
58
+ }
59
+ function refuseBuiltin(key) {
60
+ return new McpError(403, `"${key.name} ${key.version}" is built in: built-in services change only with a wardby release. Create an entry under another name or version instead.`);
61
+ }
62
+ function view(row) {
63
+ return { ...catalogEntryFromRow(row), builtin: row.builtin, createdAt: row.createdAt, updatedAt: row.updatedAt };
64
+ }
65
+ const keyJsonSchema = {
66
+ name: { type: "string", description: 'Catalog name a repository declares, e.g. "postgres".' },
67
+ version: { type: "string", description: 'Version a repository declares, e.g. "16".' },
68
+ };
69
+ const definitionProperties = {
70
+ ...keyJsonSchema,
71
+ image: { type: "string", description: "Registry digest to run: repo@sha256:<64 hex>. Tags are refused." },
72
+ port: {
73
+ type: "integer",
74
+ minimum: 1,
75
+ maximum: 65535,
76
+ description: "The port the service listens on (informational).",
77
+ },
78
+ serviceEnv: {
79
+ type: "object",
80
+ additionalProperties: { type: "string" },
81
+ description: "Environment for the service container. Throwaway per-run values only, never secrets.",
82
+ },
83
+ testEnv: {
84
+ type: "object",
85
+ additionalProperties: { type: "string" },
86
+ description: "Variables the agent's shells receive (e.g. DATABASE_URL). Upper-case names; wardby's own names (PATH, HOME, PIP_*, WARDBY_*, ...) are refused.",
87
+ },
88
+ readiness: {
89
+ type: "object",
90
+ additionalProperties: false,
91
+ required: ["command", "periodSeconds", "timeoutSeconds", "failureThreshold"],
92
+ properties: {
93
+ command: { type: "array", minItems: 1, maxItems: 16, items: { type: "string" } },
94
+ periodSeconds: { type: "integer", minimum: 1, maximum: 60 },
95
+ timeoutSeconds: { type: "integer", minimum: 1, maximum: 60 },
96
+ failureThreshold: { type: "integer", minimum: 1, maximum: 120 },
97
+ },
98
+ description: "Startup probe: a command in the service's image that succeeds once it accepts connections on 127.0.0.1.",
99
+ },
100
+ resources: {
101
+ type: "object",
102
+ additionalProperties: false,
103
+ required: ["cpuMillicores", "memoryMib", "diskMib"],
104
+ properties: {
105
+ cpuMillicores: { type: "integer", minimum: 100, maximum: 4000 },
106
+ memoryMib: { type: "integer", minimum: 64, maximum: 16384 },
107
+ diskMib: { type: "integer", minimum: 64, maximum: 8192 },
108
+ },
109
+ description: "Requests equal limits. diskMib sizes the data volume.",
110
+ },
111
+ dataPath: {
112
+ type: "string",
113
+ description: "Absolute directory the service writes its data to: an empty volume in each run.",
114
+ },
115
+ writablePaths: {
116
+ type: "array",
117
+ maxItems: 4,
118
+ items: { type: "string" },
119
+ description: "Further directories the image writes to (a socket directory, /tmp); its root filesystem is read-only.",
120
+ },
121
+ };
122
+ export function registerServiceTools(mcp) {
123
+ mcp.registerTool({
124
+ name: "list_services",
125
+ scope: "agents:read",
126
+ description: "The coding-run service catalog (name, version, image, built in or not): the names a coding agent's codingProfile.services can allow.",
127
+ inputSchema: { type: "object", additionalProperties: false, properties: {} },
128
+ handler: async (_args, ctx) => {
129
+ const rows = await ctx.db.codingService.findMany({ orderBy: [{ name: "asc" }, { version: "asc" }] });
130
+ return textResult(rows.map((row) => ({
131
+ name: row.name,
132
+ version: row.version,
133
+ kind: row.kind,
134
+ image: row.image,
135
+ port: row.port,
136
+ builtin: row.builtin,
137
+ })));
138
+ },
139
+ });
140
+ mcp.registerTool({
141
+ name: "get_service",
142
+ scope: "agents:read",
143
+ description: "One catalog entry in full, including the variables (testEnv) a run's shells receive — the contract a repository's tests rely on.",
144
+ inputSchema: {
145
+ type: "object",
146
+ additionalProperties: false,
147
+ required: ["name", "version"],
148
+ properties: keyJsonSchema,
149
+ },
150
+ handler: async (rawArgs, ctx) => {
151
+ const key = parse(KeySchema, "get_service arguments", rawArgs);
152
+ return textResult(view(await findEntry(ctx, key)));
153
+ },
154
+ });
155
+ mcp.registerTool({
156
+ name: "create_service",
157
+ scope: "services:manage",
158
+ description: "Service managers (services:manage): add a catalog entry repositories can then declare in .wardby/services.yaml. The image must be pinned by digest; kind is sidecar (a fresh instance in each run's pod).",
159
+ inputSchema: {
160
+ type: "object",
161
+ additionalProperties: false,
162
+ required: ["name", "version", "image", "port", "readiness", "resources", "dataPath"],
163
+ // kind is checked by the zod schema (only "sidecar" today), so a refusal names the field.
164
+ properties: { ...definitionProperties, kind: { type: "string", description: 'Only "sidecar" today.' } },
165
+ },
166
+ handler: async (rawArgs, ctx) => {
167
+ const definition = parse(CodingServiceDefinitionSchema, "create_service arguments", rawArgs);
168
+ const key = { name: definition.name, version: definition.version };
169
+ if (await ctx.db.codingService.findUnique({ where: { name_version: key } })) {
170
+ throw new McpError(409, `The catalog already has "${key.name} ${key.version}"; use update_service to change it.`);
171
+ }
172
+ const row = await ctx.db.codingService.create({
173
+ data: { ...definition, builtin: false, createdById: ctx.principal.id },
174
+ });
175
+ audit(ctx, "create", definition);
176
+ return textResult(view(row));
177
+ },
178
+ });
179
+ mcp.registerTool({
180
+ name: "update_service",
181
+ scope: "services:manage",
182
+ description: "Service managers (services:manage): change a non-built-in catalog entry (name and version identify it and never change). Runs already dispatched keep the entry they started with.",
183
+ inputSchema: {
184
+ type: "object",
185
+ additionalProperties: false,
186
+ required: ["name", "version"],
187
+ properties: definitionProperties,
188
+ },
189
+ handler: async (rawArgs, ctx) => {
190
+ const { name, version, ...patch } = parse(UpdateSchema, "update_service arguments", rawArgs);
191
+ const row = await findEntry(ctx, { name, version });
192
+ if (row.builtin)
193
+ throw refuseBuiltin({ name, version });
194
+ const changes = Object.fromEntries(Object.entries(patch).filter(([, value]) => value !== undefined));
195
+ const next = parse(CodingServiceDefinitionSchema, "coding service", { ...catalogEntryFromRow(row), ...changes });
196
+ const { name: _name, version: _version, kind: _kind, ...fields } = next;
197
+ const updated = await ctx.db.codingService.update({ where: { name_version: { name, version } }, data: fields });
198
+ audit(ctx, "update", next);
199
+ return textResult(view(updated));
200
+ },
201
+ });
202
+ mcp.registerTool({
203
+ name: "delete_service",
204
+ scope: "services:manage",
205
+ description: "Service managers (services:manage): remove a non-built-in catalog entry. Repositories still declaring it are refused at their next run (service_unknown).",
206
+ inputSchema: {
207
+ type: "object",
208
+ additionalProperties: false,
209
+ required: ["name", "version"],
210
+ properties: keyJsonSchema,
211
+ },
212
+ handler: async (rawArgs, ctx) => {
213
+ const key = parse(KeySchema, "delete_service arguments", rawArgs);
214
+ const row = await findEntry(ctx, key);
215
+ if (row.builtin)
216
+ throw refuseBuiltin(key);
217
+ await ctx.db.codingService.delete({ where: { name_version: key } });
218
+ audit(ctx, "delete", key);
219
+ return textResult({ deleted: key });
220
+ },
221
+ });
222
+ }
@@ -1,13 +1,20 @@
1
1
  /**
2
- * AgentSubAgent CRUD — agent-composition edges. Attach/detach require
3
- * ownership of both the parent and child agent (same convention as
4
- * attach_tool requiring ownership of both the agent and the tool), and
5
- * attach rejects any edge that would create a cycle in the parent/child
6
- * graph (§7 of the design doc) — cycles are not something Postgres can
7
- * enforce natively.
2
+ * AgentSubAgent CRUD — agent-composition edges. An edge runs the child
3
+ * (with its owner's bindings) whenever the parent delegates, and hands the
4
+ * child whatever the parent's runs pass it, so it is a binding of the
5
+ * parent: only the parent's owner attaches or detaches one (review I2; a
6
+ * write-grantee could otherwise route every run's data to their own agent).
7
+ * Across owners it also needs an explicit grant (resource-sharing grants
8
+ * spec §3.4.4, N1): the caller needs execute on the child, and the parent's
9
+ * owner must be the child's owner or hold execute on it (canDelegate,
10
+ * re-checked on every delegation at run time). The child's owner can
11
+ * always cut an edge. Attach also rejects any edge that would
12
+ * create a cycle in the parent/child graph (§7 of the design doc) — cycles
13
+ * are not something Postgres can enforce natively.
8
14
  */
9
15
  import { Prisma } from "#prisma";
10
- import { requireOwnedAgent } from "../auth/ownership.js";
16
+ import { atLeast, canDelegate } from "../../core/grants.js";
17
+ import { agentAccess, agentAccessResolver, agentNotFound, requireAgentAccess, requireBindingOwner, } from "../auth/access.js";
11
18
  import { McpError } from "../errors.js";
12
19
  import { textResult } from "./text-result.js";
13
20
  /**
@@ -60,8 +67,16 @@ export function registerSubAgentTools(mcp) {
60
67
  if (args.parentAgentId === args.childAgentId) {
61
68
  throw new McpError(400, "An agent cannot be its own sub-agent.");
62
69
  }
63
- const parent = await requireOwnedAgent(ctx.db, args.parentAgentId, ctx.principal.id);
64
- const child = await requireOwnedAgent(ctx.db, args.childAgentId, ctx.principal.id);
70
+ const { agent: parent } = await requireAgentAccess(ctx, args.parentAgentId, "read");
71
+ requireBindingOwner(ctx, parent);
72
+ // The caller could trigger the child anyway; the edge must not widen that.
73
+ const { agent: child } = await requireAgentAccess(ctx, args.childAgentId, "execute");
74
+ if (parent.ownerId === null) {
75
+ throw new McpError(403, `Agent "${parent.id}" has no owner, so it can't take sub-agents; an admin can assign one with make_owner.`);
76
+ }
77
+ if (!(await canDelegate(ctx.db, parent, child))) {
78
+ throw new McpError(403, `"${child.name}" belongs to another owner, who has not given the owner of "${parent.name}" execute access to it.`);
79
+ }
65
80
  if (await canReach(ctx.db, args.childAgentId, args.parentAgentId)) {
66
81
  throw new McpError(400, `Attaching "${child.name}" as a sub-agent of "${parent.name}" would create a cycle.`);
67
82
  }
@@ -95,8 +110,20 @@ export function registerSubAgentTools(mcp) {
95
110
  required: ["parentAgentId", "childAgentId"],
96
111
  },
97
112
  handler: async (args, ctx) => {
98
- await requireOwnedAgent(ctx.db, args.parentAgentId, ctx.principal.id);
99
- await requireOwnedAgent(ctx.db, args.childAgentId, ctx.principal.id);
113
+ // The parent's owner (or the stdio operator), or the child's owner: a
114
+ // child's owner can always take its agent back out of someone else's
115
+ // composition.
116
+ const [parent, child] = await Promise.all([
117
+ ctx.db.agent.findUnique({ where: { id: args.parentAgentId } }),
118
+ ctx.db.agent.findUnique({ where: { id: args.childAgentId } }),
119
+ ]);
120
+ const parentAccess = parent ? await agentAccess(ctx, parent) : "none";
121
+ const childAccess = child ? await agentAccess(ctx, child) : "none";
122
+ if (parentAccess !== "owner" && childAccess !== "owner") {
123
+ if (!atLeast("agent", parentAccess, "read"))
124
+ throw agentNotFound(args.parentAgentId);
125
+ throw new McpError(403, `Detaching needs ownership of "${args.parentAgentId}" or of "${args.childAgentId}".`);
126
+ }
100
127
  await ctx.db.agentSubAgent.deleteMany({
101
128
  where: { parentAgentId: args.parentAgentId, childAgentId: args.childAgentId },
102
129
  });
@@ -113,20 +140,29 @@ export function registerSubAgentTools(mcp) {
113
140
  required: ["agentId"],
114
141
  },
115
142
  handler: async (args, ctx) => {
116
- await requireOwnedAgent(ctx.db, args.agentId, ctx.principal.id);
143
+ await requireAgentAccess(ctx, args.agentId, "read");
144
+ const accessOf = await agentAccessResolver(ctx);
117
145
  const [asParent, asChild] = await Promise.all([
118
146
  ctx.db.agentSubAgent.findMany({
119
147
  where: { parentAgentId: args.agentId },
120
- include: { child: { select: { id: true, name: true } } },
148
+ include: { child: { select: { id: true, name: true, ownerId: true } } },
121
149
  }),
122
150
  ctx.db.agentSubAgent.findMany({
123
151
  where: { childAgentId: args.agentId },
124
- include: { parent: { select: { id: true, name: true } } },
152
+ include: { parent: { select: { id: true, name: true, ownerId: true } } },
125
153
  }),
126
154
  ]);
155
+ // Only agents the caller can read are named; the rest are counted.
156
+ const readable = (agent) => atLeast("agent", accessOf(agent), "read");
157
+ const children = asParent.filter((e) => readable(e.child));
158
+ const parents = asChild.filter((e) => readable(e.parent));
159
+ const hiddenChildren = asParent.length - children.length;
160
+ const hiddenParents = asChild.length - parents.length;
127
161
  return textResult({
128
- children: asParent.map((e) => ({ boundName: e.boundName, agentId: e.child.id, agentName: e.child.name })),
129
- parents: asChild.map((e) => ({ boundName: e.boundName, agentId: e.parent.id, agentName: e.parent.name })),
162
+ children: children.map((e) => ({ boundName: e.boundName, agentId: e.child.id, agentName: e.child.name })),
163
+ parents: parents.map((e) => ({ boundName: e.boundName, agentId: e.parent.id, agentName: e.parent.name })),
164
+ ...(hiddenChildren > 0 ? { hiddenChildren } : {}),
165
+ ...(hiddenParents > 0 ? { hiddenParents } : {}),
130
166
  });
131
167
  },
132
168
  });
@@ -1,2 +1,43 @@
1
+ /**
2
+ * Tool authoring — raw path only (Amendment A: the guided Elicitation/Tasks
3
+ * flow is deferred; this ships create_tool + dry_run_tool as the
4
+ * test-before-commit loop instead). A compile/validation failure is a
5
+ * NORMAL tool result carrying `{ok:false, errorKind, errorMessage}` — not
6
+ * an isError — since the call itself succeeded (compilation was attempted
7
+ * and correctly reported a problem the caller can fix and retry), matching
8
+ * runInSandbox's own SandboxResult convention. Ownership/scope failures
9
+ * (attach/detach on an agent or tool you don't own) DO throw, same
10
+ * convention as every other tool in this codebase.
11
+ */
12
+ import { type Tool } from "#prisma";
1
13
  import type { WardbyMcpServer } from "../server.js";
14
+ /**
15
+ * A tool row as a caller who doesn't own it may see it: name and
16
+ * description, never code or paramsZod (A7). `public` tells an owner-less
17
+ * tool apart from the caller's own same-named one (names are unique per
18
+ * owner, not globally). Shared by list_tools and get_agent.
19
+ */
20
+ export declare function projectTool(tool: Tool, principalId: string): {
21
+ name: string;
22
+ code: string;
23
+ createdAt: Date;
24
+ updatedAt: Date;
25
+ id: string;
26
+ ownerId: string | null;
27
+ description: string;
28
+ paramsZod: string;
29
+ jsonSchema: import("@prisma/client/runtime/client").JsonValue;
30
+ } | {
31
+ id: string;
32
+ name: string;
33
+ description: string;
34
+ public: boolean;
35
+ ownerIsCaller?: undefined;
36
+ } | {
37
+ id: string;
38
+ name: string;
39
+ description: string;
40
+ public: boolean;
41
+ ownerIsCaller: boolean;
42
+ };
2
43
  export declare function registerToolAuthoringTools(mcp: WardbyMcpServer): void;