@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
@@ -0,0 +1,632 @@
1
+ # Getting started on GKE
2
+
3
+ This is the supported Google Cloud deployment path for Wardby. It creates a
4
+ GKE Autopilot cluster, Artifact Registry, private-IP Cloud SQL for PostgreSQL,
5
+ isolated coding workers, an HTTPS Gateway, and the Wardby control plane.
6
+
7
+ The older `deploy/gcp` Cloud Run module is deprecated. New deployments should
8
+ use `deploy/gke` and the `gke-autopilot` Kubernetes overlay described here.
9
+
10
+ > This deployment creates billable Google Cloud resources. Use a dedicated
11
+ > project, review `terraform plan`, configure budgets and alerts, and understand
12
+ > the teardown procedure before applying it.
13
+
14
+ ## Architecture
15
+
16
+ - The Wardby control plane and coding proxy run in GKE Autopilot.
17
+ - Each Codex coding run uses an ephemeral gVisor-backed pod.
18
+ - Cloud SQL PostgreSQL has no public IP and is reached through private services
19
+ access on the cluster's VPC.
20
+ - Runtime, migration, and worker images are stored in Artifact Registry and
21
+ deployed by immutable digest. Two worker images are published: the default
22
+ `node` toolchain and `node-python` (Debian's Python 3 with pytest and ruff).
23
+ Coding agents select the latter with `toolchain: "node-python"` and
24
+ `toolchainVersion: "3.12"`, the key it is registered under.
25
+ - A global GKE Gateway terminates TLS with Certificate Manager and applies a
26
+ Cloud Armor rate-limit policy.
27
+ - Namespace RBAC and default-deny network policies constrain the launcher,
28
+ proxy, control plane, and worker pods.
29
+ - Native runs use the durable executor (`EXECUTOR=dbos`), so a run survives
30
+ the control-plane pod being preempted or rescheduled. See "Durable executor"
31
+ below.
32
+
33
+ The Kubernetes launcher runs both Codex and Claude Code coding workers; see
34
+ [Coding worker isolation](coding-worker-isolation.md#pod-layout) for the
35
+ Claude Code pod's extra tool-runner sidecar and its image requirements.
36
+
37
+ ## 1. Prerequisites
38
+
39
+ Install and authenticate:
40
+
41
+ - Google Cloud CLI (`gcloud`)
42
+ - Terraform 1.10 or newer
43
+ - Docker with the `buildx` plugin and `linux/amd64` build support
44
+ - `kubectl`
45
+ - Helm 3 or later (installs External Secrets Operator)
46
+ - Node.js 24 and npm
47
+
48
+ You also need:
49
+
50
+ - a Google Cloud project with billing enabled;
51
+ - a DNS hostname you control, such as `wardby.example.com`;
52
+ - an OpenAI API key and an Anthropic API key (the current deployment script
53
+ provisions both proxy routes);
54
+ - a dedicated GitHub App installed on the repositories coding agents may use;
55
+ and
56
+ - permission to create GKE, Cloud SQL, networking, Artifact Registry,
57
+ Certificate Manager, and Cloud Armor resources.
58
+
59
+ Clone the repository because the cloud deployment assets are not exposed as an
60
+ `npx` deployment command:
61
+
62
+ ```sh
63
+ git clone https://github.com/wardby/wardby.git
64
+ cd wardby
65
+ npm ci
66
+ ```
67
+
68
+ Authenticate both Terraform and Docker:
69
+
70
+ ```sh
71
+ gcloud auth login
72
+ gcloud auth application-default login
73
+ gcloud config set project YOUR_PROJECT_ID
74
+ gcloud auth configure-docker YOUR_REGION-docker.pkg.dev
75
+ ```
76
+
77
+ ## 2. Enable Google Cloud APIs
78
+
79
+ ```sh
80
+ gcloud services enable \
81
+ artifactregistry.googleapis.com \
82
+ certificatemanager.googleapis.com \
83
+ cloudresourcemanager.googleapis.com \
84
+ compute.googleapis.com \
85
+ container.googleapis.com \
86
+ iam.googleapis.com \
87
+ networksecurity.googleapis.com \
88
+ secretmanager.googleapis.com \
89
+ servicenetworking.googleapis.com \
90
+ sqladmin.googleapis.com
91
+ ```
92
+
93
+ API enablement can take several minutes to propagate.
94
+
95
+ ## 3. Configure Terraform
96
+
97
+ ```sh
98
+ cp deploy/gke/terraform.tfvars.example deploy/gke/terraform.tfvars
99
+ ```
100
+
101
+ Set `project_id`, `region`, and the VPC/subnetwork. The selected network **must
102
+ be the network used by the cluster** because private-services peering is not
103
+ transitive.
104
+
105
+ Use a remote Terraform backend for shared or production deployments: state
106
+ tracks real infrastructure, and losing it is expensive to reconstruct even
107
+ though it holds no secret. Every workload logs in through Cloud SQL IAM, so
108
+ state contains no database password; Terraform creates the Secret Manager
109
+ secrets empty too.
110
+
111
+ Review before applying:
112
+
113
+ ```sh
114
+ terraform -chdir=deploy/gke init
115
+ terraform -chdir=deploy/gke validate
116
+ terraform -chdir=deploy/gke plan
117
+ terraform -chdir=deploy/gke apply
118
+ ```
119
+
120
+ Terraform creates the Autopilot cluster with the standard Gateway API channel,
121
+ Artifact Registry, private service range, Cloud SQL instance, database, and
122
+ database user.
123
+
124
+ Fetch the cluster context and verify the Gateway classes:
125
+
126
+ ```sh
127
+ $(terraform -chdir=deploy/gke output -raw kubectl_context_command)
128
+ kubectl get gatewayclass
129
+ ```
130
+
131
+ `gke-l7-global-external-managed` must report `ACCEPTED=True` before continuing.
132
+ Google notes that Gateway API enablement can take significant time to reconcile.
133
+
134
+ ## 4. Prepare secrets
135
+
136
+ Create `.env.local` at the repository root and keep it untracked:
137
+
138
+ ```dotenv
139
+ OPENAI_API_KEY="..."
140
+ ANTHROPIC_API_KEY="..."
141
+ SECRET_APP_KEY="64_HEX_CHARACTERS"
142
+ GITHUB_APP_ID="..."
143
+ GITHUB_APP_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----
144
+ ...
145
+ -----END PRIVATE KEY-----"
146
+ GITHUB_APP_CLIENT_ID="..."
147
+ GITHUB_APP_CLIENT_SECRET="..."
148
+ ```
149
+
150
+ `GITHUB_APP_CLIENT_ID` and `GITHUB_APP_CLIENT_SECRET` are the App's OAuth
151
+ Client ID (not the App ID) and a client secret generated under the App's
152
+ **Client secrets**. Users link their GitHub accounts with them, which is how
153
+ wardby checks that an agent's owner may use a repository. Also set the App's
154
+ **Callback URL** to `https://<your hostname>/hosts/github/user-callback` and
155
+ leave **Request user authorization (OAuth) during installation** unchecked; see
156
+ [code-review-agents.md](code-review-agents.md#registering-the-github-app).
157
+ Seeding stops, with nothing written, if either value is missing.
158
+
159
+ Generate `SECRET_APP_KEY` with:
160
+
161
+ ```sh
162
+ openssl rand -hex 32
163
+ ```
164
+
165
+ `.env.local` is only the **first-time source**. On its first run `up.sh`
166
+ copies each value into Google Secret Manager, over stdin and never in a process
167
+ argument, and External Secrets Operator syncs them into the cluster from then
168
+ on. A value already in Secret Manager is never overwritten, so after the first
169
+ deployment Secret Manager is the source of truth. You can then remove the
170
+ production values from `.env.local`.
171
+
172
+ Redeploying onto a cluster that already runs Wardby carries its existing
173
+ `SECRET_APP_KEY` and login signing keys over, so stored credentials still
174
+ decrypt and nobody has to sign in again.
175
+
176
+ ## 5. Prepare the public edge
177
+
178
+ The committed Gateway expects three global resources named
179
+ `wardby-control-plane`: a static address, Certificate Manager certificate map,
180
+ and Cloud Armor security policy.
181
+
182
+ Reserve the address and create the policy:
183
+
184
+ ```sh
185
+ gcloud compute addresses create wardby-control-plane --global
186
+ gcloud compute security-policies create wardby-control-plane
187
+ gcloud compute security-policies rules create 1000 \
188
+ --security-policy=wardby-control-plane \
189
+ --src-ip-ranges='*' \
190
+ --action=throttle \
191
+ --rate-limit-threshold-count=300 \
192
+ --rate-limit-threshold-interval-sec=60 \
193
+ --conform-action=allow \
194
+ --exceed-action=deny-429 \
195
+ --enforce-on-key=IP
196
+ ```
197
+
198
+ Create a DNS authorization for your hostname:
199
+
200
+ ```sh
201
+ gcloud certificate-manager dns-authorizations create wardby-control-plane \
202
+ --domain=wardby.example.com
203
+ gcloud certificate-manager dns-authorizations describe wardby-control-plane
204
+ ```
205
+
206
+ Add the returned `dnsResourceRecord` CNAME to your DNS provider. Then create
207
+ the certificate and map:
208
+
209
+ ```sh
210
+ gcloud certificate-manager certificates create wardby-control-plane \
211
+ --domains=wardby.example.com \
212
+ --dns-authorizations=wardby-control-plane
213
+ gcloud certificate-manager maps create wardby-control-plane
214
+ gcloud certificate-manager maps entries create wardby-control-plane \
215
+ --map=wardby-control-plane \
216
+ --certificates=wardby-control-plane \
217
+ --hostname=wardby.example.com
218
+ ```
219
+
220
+ Wait for the certificate and map entry to become active. These steps follow
221
+ Google's [Certificate Manager DNS-authorization
222
+ procedure](https://cloud.google.com/certificate-manager/docs/deploy-google-managed-dns-auth)
223
+ and [GKE Gateway guidance](https://cloud.google.com/kubernetes-engine/docs/how-to/deploying-gateways).
224
+
225
+ ## 6. Deploy Wardby
226
+
227
+ The deployment script is idempotent. It converges Terraform, builds and pushes
228
+ `linux/amd64` images, resolves immutable digests, seeds Secret Manager and installs External Secrets Operator to sync it,
229
+ renders the GKE overlay, and waits for the proxy and control plane:
230
+
231
+ ```sh
232
+ HOSTNAME=wardby.example.com deploy/gke/up.sh
233
+ ```
234
+
235
+ Point the hostname's public A record at the reserved address:
236
+
237
+ ```sh
238
+ gcloud compute addresses describe wardby-control-plane \
239
+ --global --format='value(address)'
240
+ ```
241
+
242
+ Allow DNS and the managed certificate to converge before treating an HTTPS
243
+ failure as an application failure.
244
+
245
+ On a brand-new project, run `terraform apply` and then
246
+ `bootstrap-database-iam.sh` before `up.sh`: the bootstrap has to grant the
247
+ migrator before any migration can run. See "Database login" below for the
248
+ exact order, including the database check `up.sh` doesn't pass until a second
249
+ bootstrap run has granted the coding proxy too.
250
+
251
+ ### Database login
252
+
253
+ Each workload authenticates to Cloud SQL as its own Google service account,
254
+ through the Cloud SQL Auth Proxy, via Workload Identity from one Kubernetes
255
+ service account. What each may do inside the database comes from a `NOLOGIN`
256
+ group role in `deploy/gke/database-grants.sql`:
257
+
258
+ | Workload | Google service account | Kubernetes service account | May do |
259
+ | ------------- | ------------------------ | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
260
+ | Control plane | `<name_prefix>-app` | `wardby-control-plane` | `wardby_app`: read/write every table, including the durable executor's in schema `dbos`; never change a schema |
261
+ | Coding proxy | `<name_prefix>-proxy` | `wardby-coding-proxy` | `wardby_proxy`: only its budget ledger — `CodingProxySession`/`CodingProxyRequest`/`RunModelUsage`, plus update `tokensIn`, `tokensOut`, `costUsd` and `turns` on `Run`, and read only its `id` |
262
+ | Migrations | `<name_prefix>-migrator` | `wardby-migrator` | Acts as the table owner (`SET ROLE`), so `prisma migrate deploy` and `dbos schema` can alter and create tables |
263
+
264
+ `deploy/gke/bootstrap-database-iam.sh` applies the grants as the built-in
265
+ owner, from a short-lived Job inside the cluster. Run it whenever
266
+ `database-grants.sql` changes, before deploying the release that needs the new
267
+ grants (`bootstrap-database-iam.sh --check`, then `bootstrap-database-iam.sh`,
268
+ then `up.sh`), and as part of the orders below. A release deployed ahead of its
269
+ grants fails with "permission denied" wherever it uses one it doesn't have yet.
270
+ The grants run in one transaction, so a statement the database refuses leaves
271
+ nothing applied.
272
+
273
+ The built-in owner is not a Terraform resource: `bootstrap-database-iam.sh`
274
+ creates it if it's missing, sets a one-time password on it through the Cloud
275
+ SQL Admin API, uses that password once to apply the grants, and resets it to
276
+ a value nobody holds on every exit, including a failed grant. No password is
277
+ ever stored, printed, or passed as a process argument.
278
+
279
+ A brand-new project runs, in this order:
280
+
281
+ 1. `terraform -chdir=deploy/gke apply` — creates the cluster, the instance
282
+ and the three IAM database users. Run it yourself rather than through
283
+ `up.sh`, which would go on to the migrations before the migrator has its
284
+ grants.
285
+ 2. `deploy/gke/bootstrap-database-iam.sh` (default mode) — fetches the
286
+ cluster's kubectl credentials if you don't have them yet, creates the
287
+ owner, and applies the migrator's (and the app's) grants. The coding
288
+ proxy's ledger tables don't exist yet, so its grants are skipped: expected.
289
+ 3. `deploy/gke/up.sh` — applies the migrations and rolls out, then stops at
290
+ the database check: the coding proxy's grants are on tables that did not
291
+ exist in step 2.
292
+ 4. `deploy/gke/bootstrap-database-iam.sh` again — now that the tables exist,
293
+ also applies the coding proxy's ledger grants.
294
+ 5. `deploy/gke/up.sh` — rolls out again and passes every check.
295
+
296
+ Two bootstrap runs, not one: a grant on a named table can't apply before the
297
+ migration that creates that table has run.
298
+
299
+ The same applies to every later release that adds a table the coding proxy
300
+ uses: run `bootstrap-database-iam.sh` again after its migration. `up.sh`
301
+ checks this for you. After the rollout it asks the database, as the proxy's
302
+ own role, for every privilege `database-grants.sql` gives `wardby_proxy`
303
+ (`deploy/gke/proxy-grant-checks.mjs`), and stops with the list of missing
304
+ grants instead of letting the proxy fail registry requests with "permission
305
+ denied".
306
+
307
+ After upgrading an existing deployment to a release with cost attribution,
308
+ re-run `bootstrap-database-iam.sh` so the coding proxy can record per-model
309
+ usage for coding runs (used by the `cost_report` tool's `model` grouping).
310
+ Until then coding runs still work, but their per-model breakdown isn't
311
+ recorded.
312
+
313
+ `bootstrap-database-iam.sh --check` runs the grants inside a transaction that
314
+ is then rolled back, and reports success or the exact statement the database
315
+ refused, without changing anything. Run it before the real run on a live
316
+ deployment.
317
+
318
+ `connector_enforcement` (the Cloud SQL instance setting) defaults to
319
+ `REQUIRED`: it refuses any connection that does not come through the Auth
320
+ Proxy or a Cloud SQL connector, and with port 5432 to the instance closed in
321
+ every NetworkPolicy, there's no route left for a plain Postgres connection to
322
+ even attempt. Leave it at the default; an older deployment still on password
323
+ login moves off it on an earlier revision of this module, below.
324
+
325
+ ### Moving an older deployment
326
+
327
+ A deployment still on password login — from before this module retired it —
328
+ can't adopt this revision directly: this revision no longer syncs the
329
+ password `DATABASE_URL`, closes port 5432 and refuses non-Auth-Proxy
330
+ connections, which would cut off pods still logging in with the password.
331
+ It moves over in stages, because real pods are already serving traffic
332
+ throughout.
333
+
334
+ **1–2. Cut the running pods to IAM login, on the revision before this one.**
335
+ Check out the revision of this module that added IAM login, before the
336
+ password was retired: the merge of pull request #83 into `main`.
337
+ `git log --oneline --first-parent main -- deploy/gke` lists the merges that
338
+ changed this module, newest first; it's the one titled
339
+ `Merge pull request #83 ...`, just below the merge that retired the password
340
+ (`git log --oneline --merges --grep='#83' main` finds it directly). Then
341
+ `git checkout <that commit>` and follow that revision's own
342
+ `docs/getting-started-gke.md`, "Database login", and its order for "an
343
+ existing deployment still on password login": `bootstrap-database-iam.sh
344
+ --password-from-stdin --check`, the same without `--check`, then `up.sh`.
345
+ That rolls out password-less pods while the password still works as a
346
+ fallback, and proves the control plane and the coding proxy each read the
347
+ database through their own IAM login. That revision's
348
+ `connector_enforcement` default is still `NOT_REQUIRED`, so nothing that
349
+ still uses the password is cut off. Then return to this revision
350
+ (`git checkout main`) for the last stage.
351
+
352
+ **3. Retire the password**, once every pod speaks IAM login and this change
353
+ has merged to `main`:
354
+
355
+ 1. Confirm nothing still uses the password: both Deployments' pods log in as
356
+ IAM users, and no pod has a password `DATABASE_URL` in its effective env.
357
+ 2. Delete the `database-url` Secret Manager secret:
358
+ `gcloud secrets delete <name_prefix>-database-url --quiet` — this module no
359
+ longer creates or reads it. Deleting it by hand first, before the next
360
+ step, is what lets Terraform drop it from state instead of trying to
361
+ destroy it.
362
+ 3. Remove any `connector_enforcement` line from `terraform.tfvars` (or set
363
+ it to `REQUIRED`), so the new default takes effect. Then `terraform plan`:
364
+ expect the generated password destroyed, the `database-url` secret and
365
+ its IAM binding gone from state (already deleted by hand), the old
366
+ password-login user forgotten (not destroyed), `connector_enforcement`
367
+ moving to `REQUIRED` on the instance (updated in place, not replaced),
368
+ and no other destroy. Review
369
+ the plan, then apply only once it matches that. If apply still fails
370
+ trying to destroy the `database-url` secret, the secret wasn't actually
371
+ deleted in step 2 — delete it and re-apply. Never turn off
372
+ `secrets_deletion_protection` to get past that error: it unprotects every
373
+ other secret in the same set, including `SECRET_APP_KEY` and the auth
374
+ keys, and losing `SECRET_APP_KEY` makes every credential already stored
375
+ in the database unreadable.
376
+ 4. `deploy/gke/up.sh` — new ExternalSecrets carry no `DATABASE_URL`,
377
+ NetworkPolicies no longer allow 5432, migrations, rollout, and the
378
+ database and endpoint checks.
379
+ 5. `deploy/gke/bootstrap-database-iam.sh` (default mode) — the guard now
380
+ passes, since the Secret no longer has a `DATABASE_URL`: it sets a
381
+ one-time owner password, reapplies the grants, and resets the password to
382
+ a value nobody holds.
383
+ 6. Verify: a direct password connection is refused (NetworkPolicy blocks
384
+ 5432, and the instance refuses it too), the pods still log in through
385
+ IAM, and the Terraform state holds no database password.
386
+
387
+ ## 7. Verify
388
+
389
+ ```sh
390
+ kubectl -n wardby-coding get pods
391
+ kubectl -n wardby-coding get gateway,httproute
392
+ kubectl -n wardby-coding describe gateway wardby-control-plane
393
+
394
+ curl -sS -o /dev/null -w '%{http_code}\n' \
395
+ https://wardby.example.com/.well-known/oauth-protected-resource
396
+ curl -sS -o /dev/null -w '%{http_code}\n' -X POST \
397
+ -H 'content-type: application/json' \
398
+ -H 'accept: application/json, text/event-stream' \
399
+ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
400
+ https://wardby.example.com/mcp
401
+ ```
402
+
403
+ The discovery request should return `200`; an unauthenticated MCP
404
+ `initialize` request should return `401`. Send the JSON body: without it the
405
+ server answers `415`, because it checks the content type before the token.
406
+
407
+ Create the first self-hosted login credential. It is printed once.
408
+ `--role admin` makes this operator account an admin. Only admins can use all
409
+ the privileged operations: `make_owner`, BYO `workerImageRef`, package
410
+ approval, service catalog changes, and model catalog changes. A
411
+ `package-approver` can approve packages only, a `service-manager` can change
412
+ the service catalog only, and a `model-manager` can change the model catalog
413
+ only. Users created without `--role` have no roles. See
414
+ [roles and privileged operations](security-deployment.md#roles-and-privileged-operations).
415
+
416
+ ```sh
417
+ kubectl exec -n wardby-coding deploy/wardby-control-plane \
418
+ -c control-plane -- \
419
+ node dist/cli.js auth user create --subject YOUR_SUBJECT --role admin
420
+ ```
421
+
422
+ When you upgrade a deployment created before roles existed, every existing
423
+ user has no roles, including you. Grant the admin role to yourself, then
424
+ reconnect your MCP client:
425
+
426
+ ```sh
427
+ kubectl exec -n wardby-coding deploy/wardby-control-plane \
428
+ -c control-plane -- \
429
+ node dist/cli.js auth user grant --subject YOUR_SUBJECT --role admin
430
+ ```
431
+
432
+ The deployment helper configures Wardby's self-hosted authorization server by
433
+ default. To use your organization's OAuth/OIDC provider instead, configure the
434
+ control-plane secret for delegated authentication and follow
435
+ [Bring your own identity provider](getting-started-identity-provider.md). In
436
+ delegated mode, users and clients belong to the external provider and you do
437
+ not create Wardby login credentials.
438
+
439
+ Run the coding boundary preflight inside the configured control-plane pod:
440
+
441
+ ```sh
442
+ kubectl exec -n wardby-coding deploy/wardby-control-plane \
443
+ -c control-plane -- \
444
+ node dist/cli.js coding preflight
445
+ ```
446
+
447
+ Before production use, complete the [release verification](release-verification.md)
448
+ and [security deployment](security-deployment.md) checklists.
449
+
450
+ ## 8. Operate and update
451
+
452
+ Re-run `deploy/gke/up.sh` after a source or configuration change. It rebuilds
453
+ images, pushes them, substitutes immutable digests, leaves Secret Manager values
454
+ as they are, waits for rollouts, and then checks the public endpoint: discovery
455
+ must answer `200` and an unauthenticated MCP request `401`, or the deploy fails.
456
+
457
+ `up.sh` builds every image in one `docker buildx bake` run
458
+ (`deploy/gke/docker-bake.hcl`), so Docker's `buildx` plugin is required (Docker
459
+ Desktop includes it). The images build concurrently, and the stages that only
460
+ compile JavaScript run on your machine's own architecture, so building the
461
+ `linux/amd64` images from an arm64 machine emulates only what actually ships.
462
+
463
+ A control-plane restart is designed not to drop requests, at the cost of a
464
+ slower rollout. A new pod must stay Ready for three minutes before the old one
465
+ is retired, because the load balancer can take well over a minute to start
466
+ routing to a new pod even after its health check passes; the old pod then keeps
467
+ serving for 30 seconds while the load balancer drains it. `up.sh` checks the
468
+ endpoint only after the old pod is gone, and requires a steady minute of
469
+ successful responses.
470
+
471
+ Migrations run as a `wardby-migrate-<unix time>` Job before the Deployments
472
+ roll; if it fails, `up.sh` prints the `migrate` and `cloud-sql-proxy` container
473
+ logs (and, if those are empty or the Job timed out, the Job's and pod's
474
+ events), then stops.
475
+
476
+ ### Durable executor
477
+
478
+ The control plane runs native runs on the durable executor (`EXECUTOR=dbos`):
479
+ each LLM turn and tool call is checkpointed in Postgres, in schema `dbos`. If
480
+ the control-plane pod is preempted, evicted or rescheduled, its replacement
481
+ picks each interrupted run up from its last completed step once the run's
482
+ heartbeat times out (about a minute after the replacement is running). Only
483
+ the step that was in flight runs again. Coding runs are Kubernetes Jobs and are unaffected.
484
+
485
+ - **Schema.** The migration Job creates and migrates `dbos` as the migrator
486
+ (`npm run dbos:migrate`) after the Prisma migrations, so it always runs
487
+ before the control plane starts. The control plane's role only reads and
488
+ writes it: `database-grants.sql` grants `wardby_app` `USAGE` on the schema,
489
+ `SELECT`/`INSERT`/`UPDATE`/`DELETE` on its tables, and the same through the
490
+ owner's default privileges for tables a later DBOS version adds.
491
+ - **Executor id.** `DBOS_EXECUTOR_ID` is left unset, so every process gets a
492
+ random one. A replacement pod does not need the old pod's id: the
493
+ reconciler adopts any interrupted run, whichever process started it. This is
494
+ also what makes the overlapping rolling update safe.
495
+ - **Version.** `up.sh` sets `DBOS__APPVERSION` to the runtime image digest. A
496
+ run resumes only under the version that started it: across a pod move, or an
497
+ `up.sh` re-run whose source did not change, runs continue. When you deploy
498
+ new code, the old pod first **drains**: after its 30-second `preStop` it
499
+ stops the scheduler and waits for the runs it is executing to finish, up to
500
+ `SHUTDOWN_DRAIN_SECONDS` (default 600), while the new pod serves traffic.
501
+ An idle pod exits at once. A run still going after that limit is marked
502
+ `lost`; if an `@`-mention started it, its status comment on GitHub says the
503
+ request was interrupted and should be repeated. The manifest's
504
+ `terminationGracePeriodSeconds` (720) must stay above the drain limit plus
505
+ the `preStop` delay.
506
+ - **Data at rest and retention.** `dbos.operation_outputs` holds every step's
507
+ output — prompts, model responses and full tool results — with no retention
508
+ limit. Pruning finished workflows is the operator's job; see
509
+ [Durable executor](security-deployment.md#durable-executor) for what is
510
+ stored and how to prune it with `DBOS.deleteWorkflow`.
511
+
512
+ **Enabling it on an existing deployment.** The grants changed, so apply them
513
+ before deploying: run `deploy/gke/bootstrap-database-iam.sh --check`, then
514
+ `deploy/gke/bootstrap-database-iam.sh`, then `deploy/gke/up.sh`. Without the
515
+ grants the new control-plane pod crash-loops with "permission denied" while
516
+ the old one keeps serving, and `up.sh` stops at the rollout. On a brand-new
517
+ project the order under "Database login" already covers it.
518
+
519
+ **Switching back** to the in-process executor: set `EXECUTOR` to `in-process`
520
+ in `deploy/kind-coding/manifests/overlays/gke-autopilot/control-plane.yaml`
521
+ and re-run `up.sh`. Runs in flight at that moment end `lost`.
522
+
523
+ ### Pod priority and headroom
524
+
525
+ The GKE overlay defines three PriorityClasses so that, when a node runs short,
526
+ the scheduler evicts the cheapest pods first instead of an arbitrary one:
527
+
528
+ | Class | Value | Used by | Preempts others |
529
+ | ---------------------- | ------- | ---------------------------------------- | --------------- |
530
+ | `wardby-control-plane` | 1000000 | control plane and coding proxy | yes |
531
+ | `wardby-coding-run` | 1000 | coding-run pods and the preflight canary | no |
532
+ | `wardby-headroom` | -10 | the `wardby-headroom` placeholder | no |
533
+
534
+ Coding runs get their class through `KUBERNETES_RUN_PRIORITY_CLASS` on the
535
+ control plane. GKE's own `system-*` classes still outrank all three: priority
536
+ decides who is evicted first, not whether anything can be.
537
+
538
+ `wardby-headroom` is a one-replica Deployment of the `pause` image that
539
+ reserves spare capacity, preferably on the control plane's node. A
540
+ higher-priority pod that cannot fit takes that capacity by evicting the
541
+ placeholder rather than a Wardby pod, and Autopilot then provisions a node for
542
+ the placeholder. Autopilot bills for its requests (250m CPU and 512 MiB of
543
+ memory), and it counts against the `wardby-coding` ResourceQuota. To disable
544
+ it, set `replicas: 0` in
545
+ `deploy/kind-coding/manifests/overlays/gke-autopilot/priority.yaml` and re-run
546
+ `up.sh`; raise its requests to reserve more.
547
+
548
+ A PriorityClass's value and preemption policy cannot be changed in place:
549
+ delete the class and re-run `up.sh` to change them.
550
+
551
+ ### Coding-run services
552
+
553
+ A coding run whose agent allows [services](coding-services.md) waits for each
554
+ service's sidecar to become ready before its pod starts the coding agent, up
555
+ to `KUBERNETES_READY_TIMEOUT_MS` (default 120000, i.e. 120 seconds) on the
556
+ control plane. Pulling a service's image adds to that wait, so the first run
557
+ that schedules onto a fresh node — one that has never pulled the image before
558
+ — can need more of the bound than a run on a node that already has it
559
+ cached. Raise `KUBERNETES_READY_TIMEOUT_MS` if you see runs fail
560
+ `service_unready` only on new nodes.
561
+
562
+ ### Roll back
563
+
564
+ Images are pinned by digest, so undoing a rollout restores exactly what ran
565
+ before. `up.sh` prints the previous digests at the end of every deploy.
566
+
567
+ ```sh
568
+ kubectl -n wardby-coding rollout undo deploy/wardby-control-plane
569
+ kubectl -n wardby-coding rollout undo deploy/wardby-coding-proxy
570
+ ```
571
+
572
+ `rollout undo` restores only the Deployments' images and pod templates — there
573
+ is no password path to fall back to any more, so a rollback is safe only for
574
+ a version that still speaks IAM login. It does not touch any NetworkPolicy: a
575
+ change to the database egress rules themselves is not undone by `rollout
576
+ undo`.
577
+
578
+ Database migrations only go forward: a rollback does not undo a schema change.
579
+ That is safe while every migration is additive (new tables, nullable columns,
580
+ indexes), which is the rule for this repository. Secrets are not part of a
581
+ rollout either; they come from Secret Manager whichever version is running.
582
+
583
+ Useful diagnostics:
584
+
585
+ ```sh
586
+ kubectl -n wardby-coding get events --sort-by=.lastTimestamp
587
+ kubectl -n wardby-coding logs deploy/wardby-control-plane -c control-plane
588
+ kubectl -n wardby-coding logs deploy/wardby-coding-proxy
589
+ terraform -chdir=deploy/gke plan
590
+ ```
591
+
592
+ ### Rotate a secret
593
+
594
+ Add a version in Secret Manager, force both ExternalSecrets to sync and wait
595
+ for them, then restart both Deployments. The names below assume the default
596
+ `name_prefix` of `wardby`; substitute yours if you changed it.
597
+
598
+ ```sh
599
+ printf '%s' "$NEW_VALUE" | gcloud secrets versions add wardby-openai-api-key --project=YOUR_PROJECT_ID --data-file=-
600
+ KUBE_CONTEXT="$(kubectl config current-context)" NAMESPACE=wardby-coding bash -c 'source deploy/gke/lib-secrets.sh && wait_external_secrets_synced 120s wardby-coding-proxy-env wardby-control-plane-env' && \
601
+ kubectl -n wardby-coding rollout restart deploy/wardby-coding-proxy deploy/wardby-control-plane
602
+ ```
603
+
604
+ Pods read their environment only at start, hence the restart. The LLM API
605
+ keys and the database URL are read by both Deployments; the other secrets only
606
+ by the control plane. Do **not** rotate `SECRET_APP_KEY` this way: it encrypts
607
+ credentials already stored in the database, and a new key leaves them
608
+ unreadable.
609
+
610
+ See [Observability](observability.md) for Prometheus, Grafana, and cloud metric
611
+ collection options.
612
+
613
+ ## 9. Teardown
614
+
615
+ The cluster, Cloud SQL and the Secret Manager secrets use deletion protection. Disable all three flags and
616
+ apply that change before destroying:
617
+
618
+ ```hcl
619
+ deletion_protection = false
620
+ cluster_deletion_protection = false
621
+ secrets_deletion_protection = false
622
+ ```
623
+
624
+ ```sh
625
+ terraform -chdir=deploy/gke apply
626
+ terraform -chdir=deploy/gke destroy
627
+ ```
628
+
629
+ The static address, Certificate Manager resources, DNS records, and Cloud Armor
630
+ policy were created outside Terraform and must be removed separately after the
631
+ Gateway is gone. Review the project for retained Artifact Registry images and
632
+ remote Terraform state before deleting the project.