@wardby/cli 0.2.0 → 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 (491) hide show
  1. package/.env.example +34 -4
  2. package/README.md +183 -71
  3. package/dist/claude-coding-worker/driver.d.ts +7 -1
  4. package/dist/claude-coding-worker/driver.js +31 -2
  5. package/dist/claude-coding-worker/main.js +5 -2
  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 +99 -3
  21. package/dist/coding/protocol.js +155 -4
  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 +18 -0
  60. package/dist/coding-worker/artifact.js +48 -6
  61. package/dist/coding-worker/debug-trace.d.ts +37 -0
  62. package/dist/coding-worker/debug-trace.js +117 -0
  63. package/dist/coding-worker/driver.d.ts +14 -1
  64. package/dist/coding-worker/driver.js +106 -14
  65. package/dist/coding-worker/errors.d.ts +7 -0
  66. package/dist/coding-worker/errors.js +26 -0
  67. package/dist/coding-worker/main.js +13 -4
  68. package/dist/coding-worker/sdk.d.ts +2 -2
  69. package/dist/coding-worker/sdk.js +7 -2
  70. package/dist/coding-worker/types.d.ts +3 -0
  71. package/dist/config/providers.d.ts +41 -0
  72. package/dist/config/providers.js +66 -0
  73. package/dist/core/budget-groups.d.ts +109 -6
  74. package/dist/core/budget-groups.js +125 -19
  75. package/dist/core/budget-wording.d.ts +22 -0
  76. package/dist/core/budget-wording.js +55 -0
  77. package/dist/core/coding-queue.d.ts +1 -1
  78. package/dist/core/datastores.d.ts +1 -1
  79. package/dist/core/datastores.js +18 -2
  80. package/dist/core/db.d.ts +40 -2
  81. package/dist/core/db.js +75 -2
  82. package/dist/core/dispatch.d.ts +49 -7
  83. package/dist/core/dispatch.js +290 -45
  84. package/dist/core/engine-native.js +27 -10
  85. package/dist/core/grants.d.ts +86 -0
  86. package/dist/core/grants.js +126 -0
  87. package/dist/core/host-events.d.ts +49 -0
  88. package/dist/core/host-events.js +257 -0
  89. package/dist/core/host-identity-links.d.ts +54 -0
  90. package/dist/core/host-identity-links.js +189 -0
  91. package/dist/core/host-status.d.ts +61 -0
  92. package/dist/core/host-status.js +211 -0
  93. package/dist/core/http-runtime.js +3 -4
  94. package/dist/core/in-flight-runs.d.ts +8 -0
  95. package/dist/core/in-flight-runs.js +56 -0
  96. package/dist/core/lease.d.ts +1 -1
  97. package/dist/core/private-directory.d.ts +20 -0
  98. package/dist/core/private-directory.js +36 -0
  99. package/dist/core/provider-wording.d.ts +12 -0
  100. package/dist/core/provider-wording.js +44 -0
  101. package/dist/core/reconciler.d.ts +39 -3
  102. package/dist/core/reconciler.js +86 -2
  103. package/dist/core/repo-access.d.ts +99 -0
  104. package/dist/core/repo-access.js +136 -0
  105. package/dist/core/review-host-checks.d.ts +11 -0
  106. package/dist/core/review-host-checks.js +41 -0
  107. package/dist/core/review-host-tools.d.ts +47 -0
  108. package/dist/core/review-host-tools.js +347 -0
  109. package/dist/core/run-heartbeat.d.ts +27 -0
  110. package/dist/core/run-heartbeat.js +54 -0
  111. package/dist/core/runner.d.ts +31 -9
  112. package/dist/core/runner.js +237 -40
  113. package/dist/core/scheduler.d.ts +1 -1
  114. package/dist/core/secrets.d.ts +12 -3
  115. package/dist/core/secrets.js +25 -6
  116. package/dist/core/subagent-memory-tools.d.ts +2 -2
  117. package/dist/core/subagent-memory-tools.js +16 -3
  118. package/dist/core/tool-admin.d.ts +81 -0
  119. package/dist/core/tool-admin.js +129 -0
  120. package/dist/core/tool-names.d.ts +42 -0
  121. package/dist/core/tool-names.js +64 -0
  122. package/dist/core/untrusted-content.d.ts +32 -0
  123. package/dist/core/untrusted-content.js +72 -0
  124. package/dist/core/webhooks.d.ts +9 -2
  125. package/dist/core/webhooks.js +23 -2
  126. package/dist/generated/prisma/browser.d.ts +328 -0
  127. package/dist/generated/prisma/browser.js +17 -0
  128. package/dist/generated/prisma/client.d.ts +347 -0
  129. package/dist/generated/prisma/client.js +34 -0
  130. package/dist/generated/prisma/commonInputTypes.d.ts +839 -0
  131. package/dist/generated/prisma/commonInputTypes.js +10 -0
  132. package/dist/generated/prisma/enums.d.ts +59 -0
  133. package/dist/generated/prisma/enums.js +59 -0
  134. package/dist/generated/prisma/internal/class.d.ts +605 -0
  135. package/dist/generated/prisma/internal/class.js +49 -0
  136. package/dist/generated/prisma/internal/prismaNamespace.d.ts +4494 -0
  137. package/dist/generated/prisma/internal/prismaNamespace.js +628 -0
  138. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +635 -0
  139. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +599 -0
  140. package/dist/generated/prisma/models/Agent.d.ts +3560 -0
  141. package/dist/generated/prisma/models/Agent.js +1 -0
  142. package/dist/generated/prisma/models/AgentDatastore.d.ts +1210 -0
  143. package/dist/generated/prisma/models/AgentDatastore.js +1 -0
  144. package/dist/generated/prisma/models/AgentMemory.d.ts +986 -0
  145. package/dist/generated/prisma/models/AgentMemory.js +1 -0
  146. package/dist/generated/prisma/models/AgentRepository.d.ts +1425 -0
  147. package/dist/generated/prisma/models/AgentRepository.js +1 -0
  148. package/dist/generated/prisma/models/AgentSecret.d.ts +1212 -0
  149. package/dist/generated/prisma/models/AgentSecret.js +1 -0
  150. package/dist/generated/prisma/models/AgentSubAgent.d.ts +1217 -0
  151. package/dist/generated/prisma/models/AgentSubAgent.js +1 -0
  152. package/dist/generated/prisma/models/AgentTool.d.ts +1403 -0
  153. package/dist/generated/prisma/models/AgentTool.js +1 -0
  154. package/dist/generated/prisma/models/AuthFormChallenge.d.ts +1298 -0
  155. package/dist/generated/prisma/models/AuthFormChallenge.js +1 -0
  156. package/dist/generated/prisma/models/AuthLoginKey.d.ts +1245 -0
  157. package/dist/generated/prisma/models/AuthLoginKey.js +1 -0
  158. package/dist/generated/prisma/models/AuthRateLimit.d.ts +979 -0
  159. package/dist/generated/prisma/models/AuthRateLimit.js +1 -0
  160. package/dist/generated/prisma/models/AuthSession.d.ts +1376 -0
  161. package/dist/generated/prisma/models/AuthSession.js +1 -0
  162. package/dist/generated/prisma/models/AuthUser.d.ts +1700 -0
  163. package/dist/generated/prisma/models/AuthUser.js +1 -0
  164. package/dist/generated/prisma/models/BudgetGroup.d.ts +1548 -0
  165. package/dist/generated/prisma/models/BudgetGroup.js +1 -0
  166. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +1681 -0
  167. package/dist/generated/prisma/models/CodingAgentProfile.js +1 -0
  168. package/dist/generated/prisma/models/CodingProxyRequest.d.ts +1749 -0
  169. package/dist/generated/prisma/models/CodingProxyRequest.js +1 -0
  170. package/dist/generated/prisma/models/CodingProxySession.d.ts +1626 -0
  171. package/dist/generated/prisma/models/CodingProxySession.js +1 -0
  172. package/dist/generated/prisma/models/CodingRun.d.ts +3583 -0
  173. package/dist/generated/prisma/models/CodingRun.js +1 -0
  174. package/dist/generated/prisma/models/CodingService.d.ts +1348 -0
  175. package/dist/generated/prisma/models/CodingService.js +1 -0
  176. package/dist/generated/prisma/models/Datastore.d.ts +1434 -0
  177. package/dist/generated/prisma/models/Datastore.js +1 -0
  178. package/dist/generated/prisma/models/DatastoreEntry.d.ts +1314 -0
  179. package/dist/generated/prisma/models/DatastoreEntry.js +1 -0
  180. package/dist/generated/prisma/models/HostEventDelivery.d.ts +946 -0
  181. package/dist/generated/prisma/models/HostEventDelivery.js +1 -0
  182. package/dist/generated/prisma/models/HostIdentity.d.ts +1232 -0
  183. package/dist/generated/prisma/models/HostIdentity.js +1 -0
  184. package/dist/generated/prisma/models/HostIdentityLinkRequest.d.ts +1473 -0
  185. package/dist/generated/prisma/models/HostIdentityLinkRequest.js +1 -0
  186. package/dist/generated/prisma/models/OAuthAuthorizationCode.d.ts +1526 -0
  187. package/dist/generated/prisma/models/OAuthAuthorizationCode.js +1 -0
  188. package/dist/generated/prisma/models/OAuthAuthorizationRequest.d.ts +1350 -0
  189. package/dist/generated/prisma/models/OAuthAuthorizationRequest.js +1 -0
  190. package/dist/generated/prisma/models/OAuthClient.d.ts +1289 -0
  191. package/dist/generated/prisma/models/OAuthClient.js +1 -0
  192. package/dist/generated/prisma/models/OAuthFamily.d.ts +1540 -0
  193. package/dist/generated/prisma/models/OAuthFamily.js +1 -0
  194. package/dist/generated/prisma/models/OAuthGrant.d.ts +1280 -0
  195. package/dist/generated/prisma/models/OAuthGrant.js +1 -0
  196. package/dist/generated/prisma/models/Principal.d.ts +2245 -0
  197. package/dist/generated/prisma/models/Principal.js +1 -0
  198. package/dist/generated/prisma/models/RegistryAllowance.d.ts +1148 -0
  199. package/dist/generated/prisma/models/RegistryAllowance.js +1 -0
  200. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +1219 -0
  201. package/dist/generated/prisma/models/RegistryApprovedVersion.js +1 -0
  202. package/dist/generated/prisma/models/RegistryFetch.d.ts +1428 -0
  203. package/dist/generated/prisma/models/RegistryFetch.js +1 -0
  204. package/dist/generated/prisma/models/RegistryPlanRefusal.d.ts +1294 -0
  205. package/dist/generated/prisma/models/RegistryPlanRefusal.js +1 -0
  206. package/dist/generated/prisma/models/RegistryVersionFact.d.ts +1085 -0
  207. package/dist/generated/prisma/models/RegistryVersionFact.js +1 -0
  208. package/dist/generated/prisma/models/ResourceGrant.d.ts +1437 -0
  209. package/dist/generated/prisma/models/ResourceGrant.js +1 -0
  210. package/dist/generated/prisma/models/Run.d.ts +2669 -0
  211. package/dist/generated/prisma/models/Run.js +1 -0
  212. package/dist/generated/prisma/models/RunHostCheck.d.ts +1239 -0
  213. package/dist/generated/prisma/models/RunHostCheck.js +1 -0
  214. package/dist/generated/prisma/models/RunHostStatus.d.ts +1315 -0
  215. package/dist/generated/prisma/models/RunHostStatus.js +1 -0
  216. package/dist/generated/prisma/models/SchedulerLease.d.ts +970 -0
  217. package/dist/generated/prisma/models/SchedulerLease.js +1 -0
  218. package/dist/generated/prisma/models/Secret.d.ts +1399 -0
  219. package/dist/generated/prisma/models/Secret.js +1 -0
  220. package/dist/generated/prisma/models/SecretElicitationOutcome.d.ts +973 -0
  221. package/dist/generated/prisma/models/SecretElicitationOutcome.js +1 -0
  222. package/dist/generated/prisma/models/Task.d.ts +1176 -0
  223. package/dist/generated/prisma/models/Task.js +1 -0
  224. package/dist/generated/prisma/models/Tool.d.ts +1490 -0
  225. package/dist/generated/prisma/models/Tool.js +1 -0
  226. package/dist/generated/prisma/models/Webhook.d.ts +1386 -0
  227. package/dist/generated/prisma/models/Webhook.js +1 -0
  228. package/dist/generated/prisma/models.d.ts +45 -0
  229. package/dist/generated/prisma/models.js +1 -0
  230. package/dist/help/build.d.ts +1 -0
  231. package/dist/help/build.js +9 -0
  232. package/dist/help/catalog.d.ts +24 -0
  233. package/dist/help/catalog.js +160 -0
  234. package/dist/help/cli.d.ts +2 -0
  235. package/dist/help/cli.js +65 -0
  236. package/dist/help/runtime.d.ts +3 -0
  237. package/dist/help/runtime.js +44 -0
  238. package/dist/help/search.d.ts +9 -0
  239. package/dist/help/search.js +104 -0
  240. package/dist/help-index.json +660 -0
  241. package/dist/import/cli-args.js +3 -2
  242. package/dist/import/create.d.ts +6 -1
  243. package/dist/import/create.js +68 -14
  244. package/dist/import/index.d.ts +1 -1
  245. package/dist/import/index.js +19 -9
  246. package/dist/import/neutral-schema.d.ts +11 -11
  247. package/dist/mcp/auth/access.d.ts +70 -0
  248. package/dist/mcp/auth/access.js +58 -0
  249. package/dist/mcp/auth/grants-cli.d.ts +149 -0
  250. package/dist/mcp/auth/grants-cli.js +518 -0
  251. package/dist/mcp/auth/host-account-cli.d.ts +2 -0
  252. package/dist/mcp/auth/host-account-cli.js +47 -0
  253. package/dist/mcp/auth/ownership.d.ts +37 -63
  254. package/dist/mcp/auth/ownership.js +19 -14
  255. package/dist/mcp/auth/principal.d.ts +1 -1
  256. package/dist/mcp/auth/repo-authorization.d.ts +22 -0
  257. package/dist/mcp/auth/repo-authorization.js +51 -0
  258. package/dist/mcp/auth/resource-server.d.ts +32 -3
  259. package/dist/mcp/auth/resource-server.js +84 -3
  260. package/dist/mcp/auth/self-hosted/browser.js +22 -8
  261. package/dist/mcp/auth/self-hosted/cli.d.ts +1 -1
  262. package/dist/mcp/auth/self-hosted/cli.js +47 -13
  263. package/dist/mcp/auth/self-hosted/credentials.d.ts +21 -3
  264. package/dist/mcp/auth/self-hosted/credentials.js +62 -4
  265. package/dist/mcp/auth/self-hosted/rate-limit.d.ts +1 -1
  266. package/dist/mcp/auth/self-hosted/session.d.ts +3 -2
  267. package/dist/mcp/context.d.ts +28 -2
  268. package/dist/mcp/errors.d.ts +25 -6
  269. package/dist/mcp/errors.js +98 -0
  270. package/dist/mcp/host-events/github-ingress.d.ts +36 -0
  271. package/dist/mcp/host-events/github-ingress.js +92 -0
  272. package/dist/mcp/host-events/github-user-callback.d.ts +18 -0
  273. package/dist/mcp/host-events/github-user-callback.js +50 -0
  274. package/dist/mcp/index.d.ts +8 -1
  275. package/dist/mcp/index.js +106 -16
  276. package/dist/mcp/server.d.ts +1 -1
  277. package/dist/mcp/server.js +27 -9
  278. package/dist/mcp/shared/page-style.d.ts +16 -0
  279. package/dist/mcp/shared/page-style.js +129 -0
  280. package/dist/mcp/tasks/manager.d.ts +1 -1
  281. package/dist/mcp/tools/agents.js +447 -49
  282. package/dist/mcp/tools/budget-groups.js +3 -3
  283. package/dist/mcp/tools/datastore.js +23 -16
  284. package/dist/mcp/tools/grants.d.ts +2 -0
  285. package/dist/mcp/tools/grants.js +239 -0
  286. package/dist/mcp/tools/help.d.ts +5 -0
  287. package/dist/mcp/tools/help.js +67 -0
  288. package/dist/mcp/tools/host-accounts.d.ts +2 -0
  289. package/dist/mcp/tools/host-accounts.js +114 -0
  290. package/dist/mcp/tools/memory.d.ts +7 -1
  291. package/dist/mcp/tools/memory.js +5 -5
  292. package/dist/mcp/tools/repositories.d.ts +2 -0
  293. package/dist/mcp/tools/repositories.js +181 -0
  294. package/dist/mcp/tools/runs.d.ts +6 -0
  295. package/dist/mcp/tools/runs.js +60 -6
  296. package/dist/mcp/tools/scheduling.js +4 -7
  297. package/dist/mcp/tools/secret-elicitation-form.d.ts +1 -1
  298. package/dist/mcp/tools/secret-elicitation-form.js +10 -28
  299. package/dist/mcp/tools/secret-elicitation.d.ts +1 -1
  300. package/dist/mcp/tools/secrets.js +18 -6
  301. package/dist/mcp/tools/services.d.ts +2 -0
  302. package/dist/mcp/tools/services.js +222 -0
  303. package/dist/mcp/tools/subagents.js +53 -17
  304. package/dist/mcp/tools/tools.d.ts +41 -0
  305. package/dist/mcp/tools/tools.js +202 -41
  306. package/dist/mcp/tools/trigger.js +36 -6
  307. package/dist/mcp/tools/webhooks.js +15 -4
  308. package/dist/mcp/transport/streamable-http.d.ts +11 -1
  309. package/dist/mcp/transport/streamable-http.js +32 -2
  310. package/dist/mcp/unattended-schedules.d.ts +1 -1
  311. package/dist/mcp/webhooks/ingress.d.ts +1 -1
  312. package/dist/providers/auth/delegating.d.ts +19 -0
  313. package/dist/providers/auth/delegating.js +71 -0
  314. package/dist/providers/auth/index.d.ts +3 -1
  315. package/dist/providers/auth/index.js +11 -0
  316. package/dist/providers/auth/self-hosted.d.ts +4 -3
  317. package/dist/providers/auth/self-hosted.js +16 -4
  318. package/dist/providers/auth/types.d.ts +6 -0
  319. package/dist/providers/coding-proxy/memory-ledger.d.ts +3 -0
  320. package/dist/providers/coding-proxy/memory-ledger.js +21 -2
  321. package/dist/providers/coding-proxy/metering.d.ts +4 -0
  322. package/dist/providers/coding-proxy/metering.js +28 -2
  323. package/dist/providers/coding-proxy/prisma-ledger.d.ts +18 -1
  324. package/dist/providers/coding-proxy/prisma-ledger.js +50 -5
  325. package/dist/providers/coding-proxy/proxy.d.ts +13 -0
  326. package/dist/providers/coding-proxy/proxy.js +479 -18
  327. package/dist/providers/coding-proxy/registry/audit.d.ts +131 -0
  328. package/dist/providers/coding-proxy/registry/audit.js +380 -0
  329. package/dist/providers/coding-proxy/registry/bounded-fetch.d.ts +16 -0
  330. package/dist/providers/coding-proxy/registry/bounded-fetch.js +77 -0
  331. package/dist/providers/coding-proxy/registry/plan.d.ts +58 -0
  332. package/dist/providers/coding-proxy/registry/plan.js +304 -0
  333. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +34 -0
  334. package/dist/providers/coding-proxy/registry/prisma-store.js +151 -0
  335. package/dist/providers/coding-proxy/registry/service.d.ts +213 -0
  336. package/dist/providers/coding-proxy/registry/service.js +1137 -0
  337. package/dist/providers/coding-proxy/registry/store.d.ts +127 -0
  338. package/dist/providers/coding-proxy/registry/store.js +70 -0
  339. package/dist/providers/coding-proxy/runtime.d.ts +18 -1
  340. package/dist/providers/coding-proxy/runtime.js +63 -0
  341. package/dist/providers/coding-proxy/secure-fetch.js +0 -1
  342. package/dist/providers/coding-proxy/server.d.ts +11 -0
  343. package/dist/providers/coding-proxy/server.js +163 -0
  344. package/dist/providers/coding-proxy/types.d.ts +15 -0
  345. package/dist/providers/datastore/postgres.d.ts +1 -1
  346. package/dist/providers/engine/types.d.ts +10 -0
  347. package/dist/providers/executor/build.d.ts +3 -3
  348. package/dist/providers/executor/composition.d.ts +4 -1
  349. package/dist/providers/executor/composition.js +19 -0
  350. package/dist/providers/executor/container.d.ts +106 -4
  351. package/dist/providers/executor/container.js +305 -22
  352. package/dist/providers/executor/dbos.d.ts +3 -4
  353. package/dist/providers/executor/in-process.d.ts +2 -3
  354. package/dist/providers/executor/routing.d.ts +7 -0
  355. package/dist/providers/executor/routing.js +13 -0
  356. package/dist/providers/executor/types.d.ts +22 -0
  357. package/dist/providers/jobs/claude-tool-setup.d.ts +23 -0
  358. package/dist/providers/jobs/claude-tool-setup.js +50 -0
  359. package/dist/providers/jobs/collect-prune.d.ts +7 -0
  360. package/dist/providers/jobs/collect-prune.js +27 -0
  361. package/dist/providers/jobs/docker-isolation.d.ts +48 -3
  362. package/dist/providers/jobs/docker-isolation.js +213 -22
  363. package/dist/providers/jobs/docker-services.d.ts +35 -0
  364. package/dist/providers/jobs/docker-services.js +191 -0
  365. package/dist/providers/jobs/docker.d.ts +60 -2
  366. package/dist/providers/jobs/docker.js +313 -50
  367. package/dist/providers/jobs/fake-kubernetes-api.d.ts +1 -0
  368. package/dist/providers/jobs/fake-kubernetes-api.js +12 -3
  369. package/dist/providers/jobs/kubernetes-isolation.d.ts +17 -2
  370. package/dist/providers/jobs/kubernetes-isolation.js +238 -57
  371. package/dist/providers/jobs/kubernetes-platform.d.ts +10 -4
  372. package/dist/providers/jobs/kubernetes-platform.js +11 -5
  373. package/dist/providers/jobs/kubernetes-preflight.js +3 -0
  374. package/dist/providers/jobs/kubernetes.d.ts +21 -2
  375. package/dist/providers/jobs/kubernetes.js +117 -31
  376. package/dist/providers/jobs/types.d.ts +20 -0
  377. package/dist/providers/llm/anthropic.js +6 -2
  378. package/dist/providers/llm/bedrock.js +2 -1
  379. package/dist/providers/llm/claude-messages.d.ts +5 -1
  380. package/dist/providers/llm/claude-messages.js +1 -0
  381. package/dist/providers/llm/claude-provider.d.ts +3 -1
  382. package/dist/providers/llm/claude-provider.js +5 -1
  383. package/dist/providers/llm/index.d.ts +1 -1
  384. package/dist/providers/llm/index.js +1 -1
  385. package/dist/providers/llm/pricing-anthropic.d.ts +10 -0
  386. package/dist/providers/llm/pricing-anthropic.js +32 -14
  387. package/dist/providers/llm/pricing-bedrock-claude.d.ts +8 -0
  388. package/dist/providers/llm/pricing-bedrock-claude.js +9 -0
  389. package/dist/providers/llm/routing.d.ts +10 -1
  390. package/dist/providers/llm/routing.js +18 -0
  391. package/dist/providers/llm/types.d.ts +12 -0
  392. package/dist/providers/llm/types.js +8 -1
  393. package/dist/providers/memory/postgres.d.ts +1 -1
  394. package/dist/providers/review-host/diff-lines.d.ts +16 -0
  395. package/dist/providers/review-host/diff-lines.js +59 -0
  396. package/dist/providers/review-host/github-events.d.ts +6 -0
  397. package/dist/providers/review-host/github-events.js +180 -0
  398. package/dist/providers/review-host/github-user-auth.d.ts +38 -0
  399. package/dist/providers/review-host/github-user-auth.js +128 -0
  400. package/dist/providers/review-host/github.d.ts +57 -0
  401. package/dist/providers/review-host/github.js +567 -0
  402. package/dist/providers/review-host/index.d.ts +12 -0
  403. package/dist/providers/review-host/index.js +30 -0
  404. package/dist/providers/review-host/review-format.d.ts +19 -0
  405. package/dist/providers/review-host/review-format.js +59 -0
  406. package/dist/providers/review-host/types.d.ts +284 -0
  407. package/dist/providers/review-host/types.js +24 -0
  408. package/dist/providers/vcs/git.d.ts +16 -6
  409. package/dist/providers/vcs/git.js +79 -14
  410. package/dist/providers/vcs/github.d.ts +74 -3
  411. package/dist/providers/vcs/github.js +195 -15
  412. package/dist/providers/vcs/types.d.ts +42 -4
  413. package/dist/quickstart/index.js +34 -32
  414. package/dist/quickstart/migrate.d.ts +23 -0
  415. package/dist/quickstart/migrate.js +125 -0
  416. package/dist/sandbox/fetch-policy.d.ts +20 -2
  417. package/dist/sandbox/fetch-policy.js +64 -3
  418. package/dist/sandbox/host-functions.d.ts +9 -1
  419. package/dist/sandbox/host-functions.js +12 -5
  420. package/dist/serve.js +1 -1
  421. package/dist/wardby-bin.js +6 -0
  422. package/docs/README.md +30 -0
  423. package/docs/architecture-runtime.md +90 -0
  424. package/docs/assets/brand/wardby-icon-512.png +0 -0
  425. package/docs/assets/brand/wardby-icon.svg +16 -0
  426. package/docs/assets/brand/wardby-mascot-profile-512.png +0 -0
  427. package/docs/assets/brand/wardby-mascot.png +0 -0
  428. package/docs/assets/brand/wardby-mascot.svg +5 -0
  429. package/docs/assets/wardby-workflow.svg +106 -0
  430. package/docs/code-review-agents.md +481 -0
  431. package/docs/coding-agent-setup.md +172 -0
  432. package/docs/coding-packages.md +455 -0
  433. package/docs/coding-services.md +300 -0
  434. package/docs/coding-worker-byo-images.md +98 -0
  435. package/docs/coding-worker-isolation.md +1061 -0
  436. package/docs/getting-started-gke.md +615 -0
  437. package/docs/getting-started-identity-provider.md +308 -0
  438. package/docs/getting-started.md +133 -0
  439. package/docs/observability.md +53 -0
  440. package/docs/release-verification.md +66 -0
  441. package/docs/security-deployment.md +657 -0
  442. package/help/code-review-agents.md +31 -0
  443. package/help/coding-packages.md +31 -0
  444. package/help/coding-services.md +71 -0
  445. package/help/creating-agents.md +68 -0
  446. package/help/deploy-gke.md +39 -0
  447. package/help/deployment-targets.md +39 -0
  448. package/help/errors/budget-group-exhausted.md +25 -0
  449. package/help/errors/docker-isolation-unsupported.md +26 -0
  450. package/help/errors/protected-path.md +45 -0
  451. package/help/errors/repo-access.md +27 -0
  452. package/help/errors/service-declaration-invalid.md +27 -0
  453. package/help/errors/service-declaration-unavailable.md +25 -0
  454. package/help/errors/service-launcher-unsupported.md +30 -0
  455. package/help/errors/service-not-allowed.md +27 -0
  456. package/help/errors/service-unknown.md +23 -0
  457. package/help/errors/service-unready.md +49 -0
  458. package/help/getting-started.md +31 -0
  459. package/help/github.md +30 -0
  460. package/help/identity-and-access.md +39 -0
  461. package/help/mcp.md +30 -0
  462. package/help/native-capabilities.md +30 -0
  463. package/help/observability.md +41 -0
  464. package/help/operating-agents.md +30 -0
  465. package/help/security.md +27 -0
  466. package/help/troubleshooting/budgets.md +26 -0
  467. package/help/troubleshooting/coding-workers.md +47 -0
  468. package/help/troubleshooting/repository-access.md +27 -0
  469. package/package.json +30 -11
  470. package/prisma/migrate.config.mjs +20 -0
  471. package/prisma/migrations/20260925010000_coding_collect_exclude/migration.sql +8 -0
  472. package/prisma/migrations/20260925015000_allowed_egress_default/migration.sql +8 -0
  473. package/prisma/migrations/20260925020000_coding_package_registry/migration.sql +55 -0
  474. package/prisma/migrations/20260925030000_tool_name_per_owner/migration.sql +11 -0
  475. package/prisma/migrations/20260926010000_run_trigger_host_event/migration.sql +7 -0
  476. package/prisma/migrations/20260926020000_code_review_hosts/migration.sql +53 -0
  477. package/prisma/migrations/20260926030000_auth_user_roles/migration.sql +9 -0
  478. package/prisma/migrations/20260926040000_agent_effort/migration.sql +6 -0
  479. package/prisma/migrations/20260926050000_registry_lockfile_plan/migration.sql +32 -0
  480. package/prisma/migrations/20260926050000_repo_access_authorization/migration.sql +82 -0
  481. package/prisma/migrations/20260926060000_registry_plan_refusal/migration.sql +19 -0
  482. package/prisma/migrations/20260926100000_registry_plan_refusal_published_at/migration.sql +5 -0
  483. package/prisma/migrations/20260926190000_run_host_status/migration.sql +18 -0
  484. package/prisma/migrations/20260926210000_run_host_status_at_dispatch/migration.sql +5 -0
  485. package/prisma/migrations/20260927010000_resource_grants/migration.sql +72 -0
  486. package/prisma/migrations/20260927020000_proxy_session_budget_exhausted/migration.sql +3 -0
  487. package/prisma/migrations/20260927030000_coding_debug_trace/migration.sql +4 -0
  488. package/prisma/migrations/20260927040000_proxy_session_upstream_failure/migration.sql +3 -0
  489. package/prisma/migrations/20260927050000_coding_run_services/migration.sql +74 -0
  490. package/prisma/migrations/20260928000000_coding_run_tool_image/migration.sql +5 -0
  491. package/prisma/schema.prisma +417 -23
@@ -0,0 +1,300 @@
1
+ # Services for coding runs
2
+
3
+ A coding run can have the services its project's tests need — a PostgreSQL
4
+ database, a Redis cache — next to it for the length of the run. The repository
5
+ says which services it needs; wardby's service catalog says what each one is;
6
+ the agent's owner says which ones the agent may use. Every run gets its own
7
+ fresh, empty instance, and the run's sandbox and network policy do not change.
8
+
9
+ Services work on the Kubernetes job launcher (`JOB_LAUNCHER=kubernetes`,
10
+ running Kubernetes 1.29 or later, which its native sidecars need) and on the
11
+ Docker job launcher (`JOB_LAUNCHER=docker`), for Codex and Claude Code agents
12
+ on both; see [coding-worker-isolation.md](coding-worker-isolation.md). A run
13
+ whose agent allows at least one service is refused if its repository declares
14
+ one and the deployment can't start services (for example
15
+ `JOB_LAUNCHER=local`) — an agent that allows none never reads the declaration
16
+ in the first place (see "Allowing services for an agent" below), so its runs
17
+ are unaffected by this and start normally on any launcher.
18
+
19
+ ## How it works
20
+
21
+ 1. The repository declares its services in `.wardby/services.yaml` on its base
22
+ branch.
23
+ 2. When a coding run is dispatched, wardby reads that file from the run's base
24
+ branch through the GitHub App (never from the run's own branch), checks each
25
+ entry against the service catalog and the agent's allowed services, and
26
+ either refuses the run or records the resolved services on it.
27
+ 3. The run starts each service before anything else in the run. On
28
+ Kubernetes each is a native sidecar in the run's pod (an init container
29
+ with `restartPolicy: Always`, which needs Kubernetes 1.29 or later). On
30
+ Docker each is its own container sharing the run's network namespace. The
31
+ coding agent does not start until every service reports ready.
32
+ 4. The agent's shells receive each service's variables (such as
33
+ `DATABASE_URL`), and its instructions gain a short note listing the services,
34
+ their variables, and that they start empty. Claude Code runs work the same
35
+ way on both launchers: its tool runner, which actually runs shell commands
36
+ in the repository, reaches every service on `127.0.0.1` with the same
37
+ variables. On Kubernetes the tool runner starts before the service
38
+ sidecars, and the keeper and the agent wait for every service to be ready;
39
+ on Docker the tool runner and the agent are created only after every
40
+ service is ready.
41
+ 5. When the run ends, its pod (Kubernetes) or its containers (Docker) are
42
+ deleted, and each service and its data go with them.
43
+
44
+ `get_run` lists a run's services, for example `"services": ["postgres 16"]`.
45
+
46
+ ## Declaring services in a repository
47
+
48
+ Commit `.wardby/services.yaml` at the repository root:
49
+
50
+ ```yaml
51
+ # Services wardby starts next to coding runs for this repository.
52
+ services:
53
+ postgres: "16"
54
+ redis: "7"
55
+ ```
56
+
57
+ - `services` is the only key. Each entry is a catalog name and a version.
58
+ Names are lowercase letters, digits and hyphens; versions are short strings
59
+ (quote them, so `"8.0"` stays `8.0`).
60
+ - At most five services; the file must be under 8 KiB.
61
+ - The file names services only. Images, ports, commands, volumes and
62
+ environment come from the catalog, never from the repository.
63
+ - No file means no services.
64
+
65
+ The file is read from the run's base branch — the agent's `baseRef`, or a
66
+ `baseRef` given to `trigger_agent` for that run — never from the run's own
67
+ branch. So a builder agent's edit to the declaration in its own pull request
68
+ takes effect once that pull request is merged into the base branch, not
69
+ before. A coding agent may propose a change in a pull request (see "Letting a
70
+ coding agent change the declaration" below).
71
+
72
+ ### Telling your tests where the services are
73
+
74
+ Tests should read the variables rather than hard-code connection details. A
75
+ short note in the repository's `AGENTS.md` helps coding agents and people alike:
76
+
77
+ ```markdown
78
+ ## Tests
79
+
80
+ Integration tests need PostgreSQL. They read `DATABASE_URL`
81
+ (for example `postgres://test:test@127.0.0.1:5432/test`). In wardby coding
82
+ runs it is set for you; locally, start a database and export it yourself.
83
+ ```
84
+
85
+ ## The service catalog
86
+
87
+ Anyone with the `agents:read` scope can read the catalog, so an agent's owner
88
+ can see which services exist and what variables they provide. Changing it needs
89
+ the `services:manage` scope plus a Wardby role that grants it — `service-manager`,
90
+ or `admin` (see [roles and privileged operations](security-deployment.md#roles-and-privileged-operations)) —
91
+ and every change is written to the control-plane log
92
+ (`event: coding.service_catalog.create|update|delete`, with the entry and the
93
+ caller's principal id).
94
+
95
+ | Tool | What it does |
96
+ | ------------------------------------ | ----------------------------------------------------------------------------------------- |
97
+ | `list_services` (`agents:read`) | Every entry: name, version, image, whether it is built in. |
98
+ | `get_service` (`agents:read`) | One entry in full, including `testEnv`, the variables a run's shells receive. |
99
+ | `create_service` (`services:manage`) | Adds an entry. The image must be pinned by digest (`repo@sha256:...`). |
100
+ | `update_service` (`services:manage`) | Changes an entry that is not built in. Runs already dispatched keep what they began with. |
101
+ | `delete_service` (`services:manage`) | Removes an entry that is not built in. |
102
+
103
+ An entry has:
104
+
105
+ | Field | Meaning |
106
+ | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
107
+ | `name`, `version` | What a repository declares. Unique together. |
108
+ | `kind` | `sidecar`: a fresh instance next to each run. |
109
+ | `image` | The image, pinned by digest. |
110
+ | `port` | The port it listens on. |
111
+ | `serviceEnv` | Environment for the service container. Per-run throwaway values only; never put a secret here. |
112
+ | `testEnv` | Variables the agent's shells receive. Upper-case names; names wardby uses itself (`PATH`, `HOME`, `PIP_*`, `WARDBY_*`, proxy settings, ...) are refused. |
113
+ | `readiness` | A command in the image that succeeds once the service accepts connections on `127.0.0.1`, with its period, timeout and failure threshold. |
114
+ | `resources` | CPU (millicores), memory (MiB) and disk (MiB). Requests equal limits. |
115
+ | `dataPath` | The directory the service writes its data to; an empty volume in every run (memory-backed on Docker). |
116
+ | `writablePaths` | Other directories the image writes to (a socket directory, `/tmp`). The service's root filesystem is read-only. |
117
+
118
+ ### Built-in services
119
+
120
+ wardby ships these entries, pinned to the official images by digest. They
121
+ change only with a wardby release and cannot be updated or deleted over MCP.
122
+
123
+ | Service | Variables the agent's shells receive |
124
+ | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
125
+ | `postgres` `15`, `16`, `17` | `DATABASE_URL=postgres://test:test@127.0.0.1:5432/test`, `PGHOST`, `PGPORT`, `PGUSER`, `PGPASSWORD`, `PGDATABASE` |
126
+ | `redis` `7` | `REDIS_URL=redis://127.0.0.1:6379/0`, `REDIS_HOST`, `REDIS_PORT` |
127
+ | `mysql` `8` | `DATABASE_URL=mysql://test:test@127.0.0.1:3306/test`, `MYSQL_HOST`, `MYSQL_TCP_PORT`, `MYSQL_USER`, `MYSQL_PASSWORD`, `MYSQL_DATABASE` |
128
+
129
+ The credentials are fixed test values, visible to anyone who can read the
130
+ catalog: each instance exists only inside one run's pod and is reachable only
131
+ from it. Never put a real secret in `serviceEnv` or `testEnv`.
132
+
133
+ ### Adding your own entry
134
+
135
+ Use `create_service` for another database version, an extension image, or an
136
+ image mirrored into your own registry (for example to avoid Docker Hub pull
137
+ limits):
138
+
139
+ ```json
140
+ {
141
+ "name": "postgres-postgis",
142
+ "version": "16",
143
+ "image": "registry.example.com/mirror/postgis@sha256:<64 hex digits>",
144
+ "port": 5432,
145
+ "serviceEnv": {
146
+ "POSTGRES_USER": "test",
147
+ "POSTGRES_PASSWORD": "test",
148
+ "POSTGRES_DB": "test",
149
+ "PGDATA": "/var/lib/postgresql/data/pgdata"
150
+ },
151
+ "testEnv": { "DATABASE_URL": "postgres://test:test@127.0.0.1:5432/test" },
152
+ "readiness": {
153
+ "command": ["pg_isready", "-h", "127.0.0.1", "-p", "5432", "-U", "test", "-d", "test"],
154
+ "periodSeconds": 2,
155
+ "timeoutSeconds": 2,
156
+ "failureThreshold": 30
157
+ },
158
+ "resources": { "cpuMillicores": 500, "memoryMib": 512, "diskMib": 1024 },
159
+ "dataPath": "/var/lib/postgresql/data",
160
+ "writablePaths": ["/var/run/postgresql", "/tmp"]
161
+ }
162
+ ```
163
+
164
+ The image runs as the run pod's non-root user with a read-only root
165
+ filesystem and no Linux capabilities, so list every directory it writes to.
166
+ Probe the service over TCP on `127.0.0.1` rather than a Unix socket: database
167
+ images commonly start a temporary socket-only server while they initialize.
168
+
169
+ On the Docker launcher, every directory the image declares as a `VOLUME` must
170
+ be its `dataPath` or one of its `writablePaths`. Any other `VOLUME` would be an
171
+ unbounded volume on the host's disk, so the run fails its isolation check
172
+ instead.
173
+
174
+ ## Allowing services for an agent
175
+
176
+ The agent's owner lists the catalog names its runs may use (any version the
177
+ catalog has):
178
+
179
+ ```json
180
+ { "id": "<agent id>", "codingProfile": { "services": ["postgres", "redis"] } }
181
+ ```
182
+
183
+ sent with `update_agent` (or `create_agent`'s `codingProfile`). A name the
184
+ catalog doesn't have is refused. An empty list, the default, means no services.
185
+
186
+ An agent with an empty list never reads `.wardby/services.yaml` at all —
187
+ dispatch only looks at the file when the agent allows at least one service.
188
+ So an agent that allows no services just starts its runs without services,
189
+ whatever a repository declares; every refusal in "Errors" below applies only
190
+ to an agent that allows at least one service.
191
+
192
+ A [bring-your-own worker image](coding-worker-byo-images.md) must be built on
193
+ driver v11 or later to run with services; an agent whose `workerImageRef`
194
+ predates driver v11 rejects the run input once services are on it.
195
+
196
+ ## Letting a coding agent change the declaration
197
+
198
+ Wardby always protects `.wardby/` in coding runs, except
199
+ `.wardby/services.yaml`: whatever an agent's own `protectedPaths` say, a coding
200
+ run may not change other files under `.wardby/`, and any coding agent may
201
+ propose a change to the declaration in its pull request. The change takes
202
+ effect only after a person merges it, because runs read the declaration from
203
+ the base branch. If a code-review agent reviews the repository's pull
204
+ requests, add a line to its instructions asking it to call out any change to
205
+ `.wardby/services.yaml`.
206
+
207
+ Protected-path entries also accept a leading `!` for your own exceptions:
208
+ `["docs/**", "!docs/changelog.md"]` protects `docs/` except the changelog.
209
+
210
+ - An exception is one literal file path: no `*`, `?`, `[ ]` or `{ }`. Entries
211
+ such as `!**` or `!.github/**` are refused, so an exception can never switch
212
+ off a whole protected tree.
213
+ - An exception wins over the agent's own patterns, whatever its position.
214
+ - Exceptions never apply to the `.wardby/` baseline: nothing under `.wardby/`
215
+ other than `services.yaml` can be unprotected, and `services.yaml` cannot be
216
+ protected again.
217
+ - A list must protect at least one path.
218
+
219
+ ## Errors
220
+
221
+ | Problem | When | Run | What the requester sees |
222
+ | ---------------------------------------------- | -------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
223
+ | `services.yaml` is invalid | Dispatch | refused, `service_declaration_invalid` | "`.wardby/services.yaml` is invalid: <line and reason>." |
224
+ | The file couldn't be read | Dispatch | refused, `service_declaration_unavailable` | "wardby couldn't read `.wardby/services.yaml` from the base branch, so the run was not started. Try again." |
225
+ | A name and version the catalog doesn't have | Dispatch | refused, `service_unknown` | "This repository asks for `<name> <version>`, which wardby's service catalog doesn't have." |
226
+ | A service the agent isn't allowed | Dispatch | refused, `service_not_allowed` | "This repository asks for `<name>`, which this agent isn't allowed to use. An admin or the agent's owner can allow it." |
227
+ | Services on a deployment that can't start them | Dispatch | refused, `service_launcher_unsupported` | "This repository asks for services, which this wardby deployment can't start: services need the Kubernetes or Docker job launcher." |
228
+ | A service never became ready | Launch | failed, category `service_unready` | "The `<name>` service didn't become ready, so the run couldn't start." |
229
+ | The run's changes touched a protected path | Collect | failed, category `protected_path` | "its changes include `<path>`, which this agent may not edit, so none of its changes were kept. Ask again without changing that file, or have the repository owner make that change." |
230
+
231
+ A refused run's `error` (from `get_run`) is the code followed by that sentence.
232
+ The sentence reaches the requester on the run's status comment and, for a
233
+ coding run started by another agent, in that agent's tool result. A
234
+ `protected_path` failure is not a service error -- see
235
+ [Run changed a protected path](../help/errors/protected-path.md) -- but is
236
+ listed here because it uses the same category/sentence mechanism.
237
+
238
+ On Kubernetes, a service is "not ready" when its readiness command keeps
239
+ failing past its failure threshold (the sidecar restarts), its image can't be
240
+ pulled or started, or it has still not started when the launcher's pod-start
241
+ bound (`KUBERNETES_READY_TIMEOUT_MS`, default 120000) is reached. So an entry's
242
+ readiness is bounded by that timeout: a `failureThreshold` × `periodSeconds`
243
+ longer than it never takes effect. Pulling a service image adds to pod start
244
+ time; raise that bound if first pulls on new nodes are slow.
245
+
246
+ On Docker, the launcher starts the services one at a time and runs each
247
+ readiness command with `docker exec` every `periodSeconds`, each attempt
248
+ bounded by `timeoutSeconds`. A service is "not ready" after `failureThreshold`
249
+ consecutive failures, when its container can't be created or started or
250
+ exits, when its image can't be pulled within 5 minutes, or when the run's
251
+ services are still not all ready after 120 seconds. Unlike Kubernetes's
252
+ pod-start bound, that 120-second limit is fixed: it has no environment
253
+ variable, so raising it means switching to the Kubernetes launcher. It covers
254
+ creating, starting and probing every service of the run together, not image
255
+ pulls, and start-up never runs past the run's own timeout either. So an
256
+ entry's readiness settings apply within that limit: a `failureThreshold` ×
257
+ (`periodSeconds` + `timeoutSeconds`) longer than it never takes effect. The
258
+ launcher uses a local copy of the digest-pinned image when the Docker host
259
+ has one and otherwise pulls it without registry credentials. For a private
260
+ registry, or to avoid public pull limits, pull the image on the Docker host
261
+ beforehand (`docker pull <image>@sha256:<digest>`).
262
+
263
+ ## Cost and capacity
264
+
265
+ Each service reserves its catalog resources for the whole run, on top of the
266
+ worker's: CPU and memory at their requests (equal to limits), and ephemeral
267
+ storage for its data volume plus 64 MiB for each writable path. They count
268
+ toward the namespace's ResourceQuota and, on GKE Autopilot, toward what you are
269
+ billed for the run's pod and its 10 GiB pod ephemeral-storage ceiling. A run
270
+ whose workspace and services together exceed that ceiling fails before its pod
271
+ is created.
272
+
273
+ On the Docker launcher everything a service stores is in memory: its data
274
+ path and each writable path are tmpfs mounts, so its memory limit is its
275
+ catalog memory plus its disk (its data volume and 64 MiB for each writable
276
+ path) plus 64 MiB of shared memory, with its catalog CPU and at most 512
277
+ processes. Size the Docker host's RAM for `CODING_MAX_CONCURRENT` runs with
278
+ their services. A service that exits during a run is not restarted on Docker;
279
+ the run's tests see it gone.
280
+
281
+ Unlike a managed Kubernetes tier such as GKE Autopilot, which checks a
282
+ resource ceiling per pod, the Docker launcher does not cap the combined memory
283
+ of a single run's services. Size a Docker host's RAM for the worker plus the
284
+ worst case a repository could declare in one run: up to five services, each
285
+ at its catalog entry's memory plus disk plus 64 MiB. A custom catalog entry's
286
+ `resources` (`create_service`/`update_service`) is what sets those numbers, so
287
+ review them before allowing a repository to declare more or larger services.
288
+
289
+ ## Upgrading an existing deployment
290
+
291
+ `services:manage` is a new scope. If your deployment delegates to an
292
+ identity provider, define `services:manage` in the provider before you deploy
293
+ this release: clients that request every advertised scope otherwise fail with
294
+ `invalid_scope`. Map the `service-manager` role (or use `admin`) for the people
295
+ who maintain the catalog; see
296
+ [getting-started-identity-provider.md](getting-started-identity-provider.md#wardby-roles).
297
+
298
+ Existing agents are allowed no services until their owners add
299
+ `codingProfile.services`, and every existing agent gets the `.wardby/`
300
+ protected-path baseline without any change to its settings.
@@ -0,0 +1,98 @@
1
+ # Bring-Your-Own Coding-Worker Images
2
+
3
+ wardby ships worker images for `node` and `node-python` toolchains
4
+ (`src/coding-worker/Dockerfile`, `Dockerfile.node-python`). For any other
5
+ language toolchain (Ruby, PHP, .NET, ...), build your own image on top of
6
+ wardby's published **driver base image** and point your agent's
7
+ `workerImageRef` at it, instead of waiting for wardby to hand-author a new
8
+ `Dockerfile.<toolchain>`.
9
+
10
+ ## The driver image
11
+
12
+ `ghcr.io/wardby/wardby/wardby-coding-worker-driver` contains wardby's
13
+ compiled Node.js coding-worker driver, `git`, `ca-certificates`, and the
14
+ `wardby` user (uid/gid 10001) — nothing language-specific. It's built from
15
+ `src/coding-worker/Dockerfile.driver` and published on `driver-vN` git tags;
16
+ each release's GitHub Release notes carry the resolved
17
+ `@sha256:...` digest to pin.
18
+
19
+ The image deliberately stops before setting `USER`, `WORKDIR`, or
20
+ `ENTRYPOINT`, and before any of the hardened binary-absence checks wardby's
21
+ own images run. Those depend on what you install on top — some toolchains
22
+ (Ruby native gems, .NET native interop) legitimately need a compiler, so
23
+ there's no one-size-fits-all hardening rule. Your derived Dockerfile owns
24
+ that decision and must finish the job itself.
25
+
26
+ ## Writing your Dockerfile
27
+
28
+ `src/coding-worker/Dockerfile.node-python` in this repo is the reference
29
+ example — it's a real, CI-built image built this same way. The shape is:
30
+
31
+ ```dockerfile
32
+ FROM ghcr.io/wardby/wardby/wardby-coding-worker-driver@sha256:<pin the real digest from a driver-vN release>
33
+ RUN apt-get update \
34
+ && apt-get install -y --no-install-recommends <your toolchain packages> \
35
+ && rm -rf /var/lib/apt/lists/*
36
+ # Assert the binaries your sandbox must not contain are absent. Adjust the
37
+ # list to what your toolchain actually needs — e.g. a native-extension
38
+ # ecosystem may need to keep a compiler and drop this line for it.
39
+ RUN test ! -e /usr/bin/docker \
40
+ && test ! -e /usr/bin/ssh \
41
+ && test ! -e /usr/bin/curl \
42
+ && test ! -e /usr/bin/wget \
43
+ && test ! -e /usr/bin/sudo
44
+ USER 10001:10001
45
+ ENV NODE_ENV=production HOME=/home/wardby
46
+ WORKDIR /workspace
47
+ ENTRYPOINT ["node", "/opt/wardby/coding-worker/main.js"]
48
+ ```
49
+
50
+ Provide the command names your ecosystem's tooling and docs actually use.
51
+ A worker only has what you install: Debian's `python3` package ships no
52
+ `python`, so a task that runs `python -m pytest` — as most Python projects'
53
+ own READMEs tell it to — reports a failed command even when the suite is
54
+ green. `Dockerfile.node-python` symlinks `python` to `python3` for exactly
55
+ that reason, and asserts both work.
56
+
57
+ Build it, push it to your own registry, and note the resulting digest —
58
+ `docker inspect --format '{{index .RepoDigests 0}}' <your-tag>` after a push,
59
+ or read it straight from `docker buildx build --push`'s output.
60
+
61
+ ## Pointing an agent at it
62
+
63
+ Set `CodingAgentProfile.workerImageRef` to your image's digest (a mutable
64
+ tag is rejected — see `isImmutableDockerImage` in
65
+ `src/providers/jobs/docker-isolation.ts`). Through the MCP API, that means
66
+ passing `workerImageRef` inside `codingProfile` on `create_agent` or
67
+ `update_agent`.
68
+
69
+ **This requires the `agents:admin` scope**, not just `agents:write` —
70
+ `workerImageRef` bypasses wardby's own curated toolchain matrix entirely, so
71
+ setting or changing it is gated the same way `make_owner` is: a caller with
72
+ only `agents:write` can still manage coding agents normally (including
73
+ picking `toolchain`/`toolchainVersion` from wardby's own images), but cannot
74
+ point one at an arbitrary image without the step-up scope. The scope alone
75
+ isn't enough: the caller must also hold the admin role (see
76
+ [roles and privileged operations](security-deployment.md#roles-and-privileged-operations)).
77
+
78
+ ## Running services with a BYO image
79
+
80
+ An agent whose `codingProfile.services` allows a service ([coding
81
+ services](coding-services.md)) needs a worker image built on **driver v11 or
82
+ later**. The driver validates the run input it receives with a strict schema:
83
+ a worker built on an older driver base doesn't recognize the input's
84
+ `services` field and rejects the run outright, rather than silently starting
85
+ without them. Rebuild your image on a current `driver-vN` digest (see "The
86
+ driver image" above) before allowing any service on an agent that uses it.
87
+
88
+ ## What this doesn't cover
89
+
90
+ wardby does not re-validate the contents of your built image beyond the
91
+ digest-pinning check above. The mitigant is architectural, not a scan: the
92
+ guardrails that actually matter for a sandboxed run — protected paths, the
93
+ single-commit-per-run invariant, branch/PR scoping, hardened git config —
94
+ live in wardby's own orchestration code (`src/providers/vcs/git.ts`,
95
+ `src/providers/executor/container.ts`), not inside the worker image. A
96
+ compromised or careless BYO image changes the blast radius of the one job
97
+ running inside it; it can't reach past those checks, since the image only
98
+ ever talks git through that code path.