@wardby/cli 0.5.3 → 0.6.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 (370) hide show
  1. package/.env.example +33 -0
  2. package/README.md +25 -14
  3. package/dist/claude-coding-worker/context.d.ts +22 -0
  4. package/dist/claude-coding-worker/context.js +92 -0
  5. package/dist/claude-coding-worker/driver.d.ts +7 -1
  6. package/dist/claude-coding-worker/driver.js +38 -5
  7. package/dist/claude-coding-worker/sdk.js +13 -4
  8. package/dist/cli-help.d.ts +1 -1
  9. package/dist/cli-help.js +5 -2
  10. package/dist/cli-native-mode.d.ts +9 -0
  11. package/dist/cli-native-mode.js +20 -0
  12. package/dist/cli.d.ts +3 -1
  13. package/dist/cli.js +141 -5
  14. package/dist/coding/claude-context.d.ts +45 -0
  15. package/dist/coding/claude-context.js +434 -0
  16. package/dist/coding/profile.d.ts +12 -0
  17. package/dist/coding/profile.js +6 -0
  18. package/dist/coding/protocol.d.ts +104 -0
  19. package/dist/coding/protocol.js +87 -3
  20. package/dist/coding-worker/artifact.d.ts +8 -0
  21. package/dist/coding-worker/artifact.js +2 -2
  22. package/dist/coding-worker/driver.js +2 -0
  23. package/dist/coding-worker/sdk.d.ts +6 -0
  24. package/dist/coding-worker/sdk.js +1 -0
  25. package/dist/coding-worker/skills.d.ts +23 -0
  26. package/dist/coding-worker/skills.js +117 -0
  27. package/dist/coding-worker/types.d.ts +2 -0
  28. package/dist/config/github-allowed-accounts.d.ts +15 -0
  29. package/dist/config/github-allowed-accounts.js +36 -0
  30. package/dist/config/low-power.d.ts +12 -0
  31. package/dist/config/low-power.js +18 -0
  32. package/dist/config/mobile.d.ts +12 -0
  33. package/dist/config/mobile.js +18 -0
  34. package/dist/config/providers.d.ts +53 -0
  35. package/dist/config/providers.js +92 -6
  36. package/dist/core/db.d.ts +16 -6
  37. package/dist/core/db.js +12 -10
  38. package/dist/core/dispatch.d.ts +11 -0
  39. package/dist/core/dispatch.js +36 -1
  40. package/dist/core/engine-native.js +9 -5
  41. package/dist/core/host-events.d.ts +49 -3
  42. package/dist/core/host-events.js +289 -15
  43. package/dist/core/issue-bridge.js +42 -2
  44. package/dist/core/issue-events.js +12 -1
  45. package/dist/core/issue-status.js +14 -3
  46. package/dist/core/merge-order-check.d.ts +129 -0
  47. package/dist/core/merge-order-check.js +336 -0
  48. package/dist/core/notification-dispatcher.d.ts +70 -0
  49. package/dist/core/notification-dispatcher.js +368 -0
  50. package/dist/core/notification-templates.d.ts +25 -0
  51. package/dist/core/notification-templates.js +105 -0
  52. package/dist/core/notifications.d.ts +10 -0
  53. package/dist/core/notifications.js +38 -0
  54. package/dist/core/pg-auth.d.ts +22 -0
  55. package/dist/core/pg-auth.js +152 -0
  56. package/dist/core/power-composition.d.ts +16 -0
  57. package/dist/core/power-composition.js +37 -0
  58. package/dist/core/power-idle.d.ts +14 -0
  59. package/dist/core/power-idle.js +30 -0
  60. package/dist/core/power.d.ts +71 -0
  61. package/dist/core/power.js +202 -0
  62. package/dist/core/reconciler.d.ts +4 -2
  63. package/dist/core/reconciler.js +29 -5
  64. package/dist/core/related-pull-requests.d.ts +48 -4
  65. package/dist/core/related-pull-requests.js +113 -11
  66. package/dist/core/repo-access.d.ts +15 -0
  67. package/dist/core/repo-access.js +66 -0
  68. package/dist/core/review-fix.d.ts +37 -0
  69. package/dist/core/review-fix.js +207 -6
  70. package/dist/core/review-host-tools.d.ts +20 -0
  71. package/dist/core/review-host-tools.js +58 -2
  72. package/dist/core/runner.d.ts +336 -3
  73. package/dist/core/runner.js +894 -317
  74. package/dist/core/secret-broker-config.d.ts +103 -0
  75. package/dist/core/secret-broker-config.js +112 -0
  76. package/dist/core/secrets.d.ts +39 -4
  77. package/dist/core/secrets.js +148 -40
  78. package/dist/core/workflow-event-recorder.d.ts +14 -0
  79. package/dist/core/workflow-event-recorder.js +120 -0
  80. package/dist/core/workflow-events.d.ts +82 -0
  81. package/dist/core/workflow-events.js +44 -0
  82. package/dist/core/workflow-run-events.d.ts +16 -0
  83. package/dist/core/workflow-run-events.js +40 -0
  84. package/dist/generated/prisma/browser.d.ts +58 -0
  85. package/dist/generated/prisma/client.d.ts +58 -0
  86. package/dist/generated/prisma/commonInputTypes.d.ts +150 -0
  87. package/dist/generated/prisma/enums.d.ts +27 -0
  88. package/dist/generated/prisma/enums.js +23 -0
  89. package/dist/generated/prisma/internal/class.d.ts +88 -0
  90. package/dist/generated/prisma/internal/class.js +4 -4
  91. package/dist/generated/prisma/internal/prismaNamespace.d.ts +772 -1
  92. package/dist/generated/prisma/internal/prismaNamespace.js +135 -4
  93. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +139 -0
  94. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +135 -4
  95. package/dist/generated/prisma/models/Agent.d.ts +360 -1
  96. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +73 -1
  97. package/dist/generated/prisma/models/CodingRun.d.ts +205 -1
  98. package/dist/generated/prisma/models/DeferredReview.d.ts +78 -1
  99. package/dist/generated/prisma/models/NativeGatewayCall.d.ts +1675 -0
  100. package/dist/generated/prisma/models/NativeGatewayCall.js +1 -0
  101. package/dist/generated/prisma/models/NativeGatewaySession.d.ts +1517 -0
  102. package/dist/generated/prisma/models/NativeGatewaySession.js +1 -0
  103. package/dist/generated/prisma/models/NativeWarmWorker.d.ts +1296 -0
  104. package/dist/generated/prisma/models/NativeWarmWorker.js +1 -0
  105. package/dist/generated/prisma/models/NotificationChannel.d.ts +1543 -0
  106. package/dist/generated/prisma/models/NotificationChannel.js +1 -0
  107. package/dist/generated/prisma/models/NotificationDelivery.d.ts +1502 -0
  108. package/dist/generated/prisma/models/NotificationDelivery.js +1 -0
  109. package/dist/generated/prisma/models/NotificationThread.d.ts +1090 -0
  110. package/dist/generated/prisma/models/NotificationThread.js +1 -0
  111. package/dist/generated/prisma/models/Run.d.ts +826 -1
  112. package/dist/generated/prisma/models/RunHostCheck.d.ts +36 -1
  113. package/dist/generated/prisma/models/Secret.d.ts +37 -1
  114. package/dist/generated/prisma/models/SecretBrokerChange.d.ts +1101 -0
  115. package/dist/generated/prisma/models/SecretBrokerChange.js +1 -0
  116. package/dist/generated/prisma/models/WorkflowEvent.d.ts +1422 -0
  117. package/dist/generated/prisma/models/WorkflowEvent.js +1 -0
  118. package/dist/generated/prisma/models.d.ts +8 -0
  119. package/dist/help/build.js +4 -2
  120. package/dist/help/catalog.d.ts +1 -1
  121. package/dist/help/catalog.js +31 -6
  122. package/dist/help-index.json +1363 -176
  123. package/dist/import/create.js +17 -0
  124. package/dist/import/neutral-schema.d.ts +6 -2
  125. package/dist/import/neutral-schema.js +2 -0
  126. package/dist/mcp/auth/access.d.ts +1 -0
  127. package/dist/mcp/auth/repo-authorization.js +14 -0
  128. package/dist/mcp/auth/resource-server.d.ts +2 -1
  129. package/dist/mcp/auth/resource-server.js +7 -2
  130. package/dist/mcp/auth/self-hosted/browser.d.ts +1 -1
  131. package/dist/mcp/auth/self-hosted/browser.js +19 -6
  132. package/dist/mcp/context.d.ts +6 -0
  133. package/dist/mcp/host-events/github-ingress.d.ts +23 -1
  134. package/dist/mcp/host-events/github-ingress.js +68 -0
  135. package/dist/mcp/index.d.ts +13 -0
  136. package/dist/mcp/index.js +59 -10
  137. package/dist/mcp/tools/agents.js +82 -11
  138. package/dist/mcp/tools/notification-channels.d.ts +2 -0
  139. package/dist/mcp/tools/notification-channels.js +293 -0
  140. package/dist/mcp/tools/power.d.ts +2 -0
  141. package/dist/mcp/tools/power.js +77 -0
  142. package/dist/mcp/tools/runs.d.ts +0 -6
  143. package/dist/mcp/tools/runs.js +7 -2
  144. package/dist/mcp/tools/secret-broker-compat.d.ts +12 -0
  145. package/dist/mcp/tools/secret-broker-compat.js +23 -0
  146. package/dist/mcp/tools/secret-elicitation-form.d.ts +22 -2
  147. package/dist/mcp/tools/secret-elicitation-form.js +200 -10
  148. package/dist/mcp/tools/secret-elicitation-server.js +8 -1
  149. package/dist/mcp/tools/secret-elicitation.d.ts +38 -3
  150. package/dist/mcp/tools/secret-elicitation.js +110 -12
  151. package/dist/mcp/tools/secrets.js +184 -7
  152. package/dist/mcp/tools/tools.d.ts +1 -1
  153. package/dist/mcp/tools/tools.js +22 -2
  154. package/dist/native-worker/composition.d.ts +23 -0
  155. package/dist/native-worker/composition.js +77 -0
  156. package/dist/native-worker/docker-isolation.d.ts +65 -0
  157. package/dist/native-worker/docker-isolation.js +183 -0
  158. package/dist/native-worker/docker-launcher.d.ts +74 -0
  159. package/dist/native-worker/docker-launcher.js +237 -0
  160. package/dist/native-worker/gateway-server.d.ts +39 -0
  161. package/dist/native-worker/gateway-server.js +315 -0
  162. package/dist/native-worker/gateway.d.ts +44 -0
  163. package/dist/native-worker/gateway.js +197 -0
  164. package/dist/native-worker/http-server.d.ts +22 -0
  165. package/dist/native-worker/http-server.js +109 -0
  166. package/dist/native-worker/http-transport.d.ts +17 -0
  167. package/dist/native-worker/http-transport.js +88 -0
  168. package/dist/native-worker/kubernetes-isolation.d.ts +90 -0
  169. package/dist/native-worker/kubernetes-isolation.js +218 -0
  170. package/dist/native-worker/kubernetes-launcher.d.ts +102 -0
  171. package/dist/native-worker/kubernetes-launcher.js +335 -0
  172. package/dist/native-worker/launch.d.ts +45 -0
  173. package/dist/native-worker/launch.js +44 -0
  174. package/dist/native-worker/ledger.d.ts +109 -0
  175. package/dist/native-worker/ledger.js +192 -0
  176. package/dist/native-worker/loopback.d.ts +12 -0
  177. package/dist/native-worker/loopback.js +49 -0
  178. package/dist/native-worker/main.d.ts +7 -0
  179. package/dist/native-worker/main.js +74 -0
  180. package/dist/native-worker/protocol.d.ts +744 -0
  181. package/dist/native-worker/protocol.js +200 -0
  182. package/dist/native-worker/sandbox-executor.d.ts +68 -0
  183. package/dist/native-worker/sandbox-executor.js +210 -0
  184. package/dist/native-worker/stdio.d.ts +29 -0
  185. package/dist/native-worker/stdio.js +188 -0
  186. package/dist/native-worker/warm-delivery.d.ts +16 -0
  187. package/dist/native-worker/warm-delivery.js +33 -0
  188. package/dist/native-worker/warm-pool-ledger.d.ts +39 -0
  189. package/dist/native-worker/warm-pool-ledger.js +73 -0
  190. package/dist/native-worker/warm-pool.d.ts +107 -0
  191. package/dist/native-worker/warm-pool.js +283 -0
  192. package/dist/native-worker/worker.d.ts +17 -0
  193. package/dist/native-worker/worker.js +115 -0
  194. package/dist/providers/auth/authorization-server.d.ts +3 -0
  195. package/dist/providers/auth/index.js +2 -0
  196. package/dist/providers/auth/self-hosted.d.ts +13 -1
  197. package/dist/providers/auth/self-hosted.js +54 -4
  198. package/dist/providers/chat/fake.d.ts +46 -0
  199. package/dist/providers/chat/fake.js +39 -0
  200. package/dist/providers/chat/index.d.ts +4 -0
  201. package/dist/providers/chat/index.js +8 -0
  202. package/dist/providers/chat/slack.d.ts +37 -0
  203. package/dist/providers/chat/slack.js +105 -0
  204. package/dist/providers/chat/types.d.ts +42 -0
  205. package/dist/providers/chat/types.js +19 -0
  206. package/dist/providers/engine/types.d.ts +19 -0
  207. package/dist/providers/engine/types.js +22 -0
  208. package/dist/providers/executor/composition.d.ts +24 -1
  209. package/dist/providers/executor/composition.js +39 -6
  210. package/dist/providers/executor/container.d.ts +24 -1
  211. package/dist/providers/executor/container.js +101 -11
  212. package/dist/providers/executor/dbos.d.ts +42 -0
  213. package/dist/providers/executor/dbos.js +118 -12
  214. package/dist/providers/executor/deferred.d.ts +56 -0
  215. package/dist/providers/executor/deferred.js +119 -0
  216. package/dist/providers/executor/routing.d.ts +37 -10
  217. package/dist/providers/executor/routing.js +73 -32
  218. package/dist/providers/executor/types.d.ts +12 -0
  219. package/dist/providers/jobs/docker.js +3 -3
  220. package/dist/providers/jobs/fake-kubernetes-api.d.ts +21 -2
  221. package/dist/providers/jobs/fake-kubernetes-api.js +42 -1
  222. package/dist/providers/jobs/kubernetes-api.d.ts +17 -1
  223. package/dist/providers/jobs/kubernetes-api.js +7 -0
  224. package/dist/providers/jobs/kubernetes-client.d.ts +10 -1
  225. package/dist/providers/jobs/kubernetes-client.js +52 -3
  226. package/dist/providers/jobs/kubernetes-dry-run-fixture.d.ts +6 -1
  227. package/dist/providers/jobs/kubernetes-dry-run-fixture.js +6 -3
  228. package/dist/providers/jobs/kubernetes-isolation.d.ts +3 -1
  229. package/dist/providers/jobs/kubernetes-isolation.js +6 -0
  230. package/dist/providers/jobs/kubernetes-platform.d.ts +4 -1
  231. package/dist/providers/jobs/kubernetes-platform.js +38 -1
  232. package/dist/providers/jobs/kubernetes-preflight.d.ts +2 -1
  233. package/dist/providers/jobs/kubernetes-preflight.js +4 -2
  234. package/dist/providers/jobs/kubernetes.d.ts +36 -1
  235. package/dist/providers/jobs/kubernetes.js +74 -4
  236. package/dist/providers/jobs/metadata-probes.d.ts +11 -0
  237. package/dist/providers/jobs/metadata-probes.js +13 -0
  238. package/dist/providers/jobs/types.d.ts +9 -0
  239. package/dist/providers/review-host/github.d.ts +11 -1
  240. package/dist/providers/review-host/github.js +50 -0
  241. package/dist/providers/review-host/types.d.ts +23 -0
  242. package/dist/providers/vcs/github.d.ts +32 -6
  243. package/dist/providers/vcs/github.js +74 -16
  244. package/dist/quickstart/coding-seed.d.ts +10 -3
  245. package/dist/quickstart/coding-seed.js +74 -3
  246. package/dist/quickstart/images.d.ts +2 -0
  247. package/dist/quickstart/images.js +7 -1
  248. package/dist/quickstart/reviewer-prompt.d.ts +1 -1
  249. package/dist/quickstart/reviewer-prompt.js +1 -1
  250. package/dist/quickstart-images.json +1 -1
  251. package/dist/sandbox/brokered-fetch.d.ts +23 -0
  252. package/dist/sandbox/brokered-fetch.js +37 -0
  253. package/dist/sandbox/host-functions.d.ts +34 -0
  254. package/dist/sandbox/host-functions.js +144 -80
  255. package/dist/sandbox/prelude.js +7 -1
  256. package/dist/sandbox/run-in-sandbox.d.ts +19 -0
  257. package/dist/sandbox/run-in-sandbox.js +28 -10
  258. package/dist/sandbox/safe-fetch.d.ts +2 -0
  259. package/dist/sandbox/safe-fetch.js +3 -1
  260. package/dist/sandbox/secret-broker-sigv4.d.ts +2 -0
  261. package/dist/sandbox/secret-broker-sigv4.js +49 -0
  262. package/dist/sandbox/secret-broker.d.ts +34 -0
  263. package/dist/sandbox/secret-broker.js +162 -0
  264. package/dist/sandbox/user-tool.d.ts +14 -0
  265. package/dist/sandbox/user-tool.js +32 -0
  266. package/dist/serve.js +18 -0
  267. package/dist/viewer/api-schema.d.ts +210 -14
  268. package/dist/viewer/api-schema.js +22 -0
  269. package/dist/viewer/build-schemas.js +4 -1
  270. package/dist/viewer/event-bus.d.ts +6 -0
  271. package/dist/viewer/event-bus.js +16 -7
  272. package/dist/viewer/graph.d.ts +5 -2
  273. package/dist/viewer/graph.js +7 -2
  274. package/dist/viewer/http.d.ts +0 -1
  275. package/dist/viewer/http.js +2 -2
  276. package/dist/viewer/infra.js +25 -2
  277. package/dist/viewer/limits.d.ts +4 -0
  278. package/dist/viewer/limits.js +4 -0
  279. package/dist/viewer/openapi.d.ts +15 -0
  280. package/dist/viewer/openapi.js +172 -0
  281. package/docs/README.md +7 -0
  282. package/docs/agent-recipes.md +57 -8
  283. package/docs/architecture-runtime.md +16 -1
  284. package/docs/code-review-agents.md +139 -5
  285. package/docs/coding-agent-setup.md +113 -5
  286. package/docs/coding-packages.md +4 -2
  287. package/docs/coding-services.md +3 -1
  288. package/docs/coding-worker-byo-images.md +198 -6
  289. package/docs/coding-worker-isolation.md +68 -14
  290. package/docs/getting-started-gke.md +225 -9
  291. package/docs/getting-started-identity-provider.md +21 -10
  292. package/docs/getting-started.md +5 -4
  293. package/docs/jira-agents.md +5 -1
  294. package/docs/native-sandbox.md +635 -0
  295. package/docs/release-verification.md +9 -0
  296. package/docs/security-deployment.md +113 -12
  297. package/docs/slack-notifications.md +252 -0
  298. package/docs/tool-secrets.md +252 -0
  299. package/docs/viewer-api.md +46 -5
  300. package/docs/viewer-api.openapi.yml +1404 -0
  301. package/help/admin-viewer.md +6 -2
  302. package/help/agent-recipes.md +27 -0
  303. package/help/architecture-agent.md +1 -1
  304. package/help/brokered-secrets.md +79 -0
  305. package/help/build-claude-code-image.md +131 -0
  306. package/help/build-worker-image.md +3 -6
  307. package/help/code-review-agents.md +68 -6
  308. package/help/deploy-gke.md +8 -1
  309. package/help/deployment-targets.md +25 -14
  310. package/help/errors/coding-provider-not-configured.md +2 -2
  311. package/help/errors/database-auth-invalid.md +28 -0
  312. package/help/errors/github-account-not-allowed.md +25 -0
  313. package/help/errors/low-power-disabled.md +29 -0
  314. package/help/errors/low-power-scale-forbidden.md +35 -0
  315. package/help/errors/low-power-wake-timeout.md +30 -0
  316. package/help/errors/mobile-disabled.md +31 -0
  317. package/help/errors/native-sandbox-capacity.md +22 -0
  318. package/help/errors/native-sandbox-deadline-exceeded.md +19 -0
  319. package/help/errors/native-sandbox-docker-failed.md +20 -0
  320. package/help/errors/native-sandbox-gateway-unavailable.md +21 -0
  321. package/help/errors/native-sandbox-image-not-pinned.md +19 -0
  322. package/help/errors/native-sandbox-isolation-mismatch.md +20 -0
  323. package/help/errors/native-sandbox-network-unenforced.md +22 -0
  324. package/help/errors/native-sandbox-requires-catalog.md +31 -0
  325. package/help/errors/native-sandbox-unavailable.md +19 -0
  326. package/help/errors/native-sandbox-warm-delivery-failed.md +21 -0
  327. package/help/errors/native-sandbox-worker-exited.md +20 -0
  328. package/help/errors/native-sandbox-worker-lost.md +20 -0
  329. package/help/errors/native-sandbox-worker-unready.md +22 -0
  330. package/help/errors/secret-broker-body-invalid.md +26 -0
  331. package/help/errors/secret-broker-changed.md +20 -0
  332. package/help/errors/secret-broker-config-invalid.md +30 -0
  333. package/help/errors/secret-broker-conflict.md +27 -0
  334. package/help/errors/secret-broker-destination-denied.md +28 -0
  335. package/help/errors/secret-broker-value-invalid.md +28 -0
  336. package/help/errors/secret-brokered.md +24 -0
  337. package/help/errors/secret-not-brokered.md +25 -0
  338. package/help/errors/slack-auth-failed.md +48 -0
  339. package/help/errors/slack-channel-unreachable.md +39 -0
  340. package/help/errors/slack-not-configured.md +33 -0
  341. package/help/getting-started.md +4 -5
  342. package/help/github.md +18 -1
  343. package/help/identity-and-access.md +5 -1
  344. package/help/local-repositories.md +2 -3
  345. package/help/low-power-mode.md +125 -0
  346. package/help/merge-order-check.md +117 -0
  347. package/help/mobile-app.md +54 -0
  348. package/help/native-sandbox.md +136 -0
  349. package/help/observability.md +8 -0
  350. package/help/related-pull-requests.md +70 -9
  351. package/help/repo-instructions-and-skills.md +91 -0
  352. package/help/review-fix-rounds.md +10 -0
  353. package/help/slack-notifications.md +62 -0
  354. package/help/troubleshooting/coding-workers.md +21 -0
  355. package/package.json +11 -4
  356. package/prisma/migrations/20261009000003_native_execution_mode/migration.sql +12 -0
  357. package/prisma/migrations/20261009000004_native_gateway_ledger/migration.sql +65 -0
  358. package/prisma/migrations/20261009000005_native_gateway_call_child_agent/migration.sql +5 -0
  359. package/prisma/migrations/20261009000006_run_deferred_start_stop/migration.sql +14 -0
  360. package/prisma/migrations/20261009000007_native_gateway_network_ready/migration.sql +5 -0
  361. package/prisma/migrations/20261010000001_workflow_notifications/migration.sql +99 -0
  362. package/prisma/migrations/20261011000001_native_gateway_session_status_index/migration.sql +2 -0
  363. package/prisma/migrations/20261012000001_native_warm_worker/migration.sql +32 -0
  364. package/prisma/migrations/20261013000001_coding_run_merge_order/migration.sql +2 -0
  365. package/prisma/migrations/20261013000001_secret_broker/migration.sql +17 -0
  366. package/prisma/migrations/20261013000002_deferred_review_request/migration.sql +4 -0
  367. package/prisma/migrations/20261014000000_repo_skills/migration.sql +15 -0
  368. package/prisma/migrations/20261015000001_coding_run_merge_order_index/migration.sql +2 -0
  369. package/prisma/migrations/20261015000002_no_change_rereview/migration.sql +2 -0
  370. package/prisma/schema.prisma +362 -91
@@ -3,6 +3,9 @@
3
3
  This is the supported Google Cloud deployment path for Wardby. It creates a
4
4
  GKE Autopilot cluster, Artifact Registry, private-IP Cloud SQL for PostgreSQL,
5
5
  isolated coding workers, an HTTPS Gateway, and the Wardby control plane.
6
+ Before accepting production work, complete the
7
+ [release verification](release-verification.md) and
8
+ [security deployment](security-deployment.md) checks.
6
9
 
7
10
  The older `deploy/gcp` Cloud Run module is deprecated. New deployments should
8
11
  use `deploy/gke` and the `gke-autopilot` Kubernetes overlay described here.
@@ -14,7 +17,10 @@ use `deploy/gke` and the `gke-autopilot` Kubernetes overlay described here.
14
17
  ## Architecture
15
18
 
16
19
  - The Wardby control plane and coding proxy run in GKE Autopilot.
17
- - Each Codex coding run uses an ephemeral gVisor-backed pod.
20
+ - Each Codex or Claude Code coding run uses an ephemeral gVisor-backed pod;
21
+ Claude Code adds a tool-runner sidecar in that pod.
22
+ - Native agents set to sandbox mode run in single-use gVisor pods behind the
23
+ native gateway (see "Native sandbox" below).
18
24
  - Cloud SQL PostgreSQL has no public IP and is reached through private services
19
25
  access on the cluster's VPC.
20
26
  - Runtime, migration, and worker images are stored in Artifact Registry and
@@ -176,6 +182,34 @@ seeded: add it to the control plane's `env` in
176
182
  `deploy/kind-coding/manifests/overlays/gke-autopilot/control-plane.yaml` if you
177
183
  need it.
178
184
 
185
+ To post [workflow notifications to Slack](slack-notifications.md), also add the
186
+ Slack app's bot token. This requires Wardby 0.6.0 or later. It is optional:
187
+
188
+ ```dotenv
189
+ WARDBY_SLACK_BOT_TOKEN="xoxb-..."
190
+ ```
191
+
192
+ When it is in Secret Manager, `up.sh` syncs it into a separate Secret,
193
+ `wardby-slack-env`, that only the control plane reads; when it is not, it
194
+ leaves that Secret out and Slack stays off. `WARDBY_SLACK_CUSTOMIZE` and
195
+ `WARDBY_SLACK_API_BASE_URL` are not secrets and are not seeded: add them to the
196
+ control plane's `env` in the same `control-plane.yaml` if you need them. If you
197
+ later remove the bot token, remove these two entries too: the control plane
198
+ refuses to start with either one set and no token.
199
+
200
+ `WARDBY_GITHUB_ALLOWED_ACCOUNTS` (optional, not a secret) adds GitHub accounts
201
+ the App serves besides its owner. Pass it to `up.sh` on every run, for example
202
+ `WARDBY_GITHUB_ALLOWED_ACCOUNTS=acme-labs WARDBY_HOSTNAME=app.example.com deploy/gke/up.sh`;
203
+ a run without it serves only the App's owner. See
204
+ [Which accounts the App serves](code-review-agents.md#which-accounts-the-app-serves-wardby_github_allowed_accounts).
205
+
206
+ `WARDBY_MOBILE_ENABLED=true` (optional, not a secret) lets the Wardby mobile app
207
+ sign in to the self-hosted OAuth server. Pass it to `up.sh` on every run, the
208
+ same way as `WARDBY_GITHUB_ALLOWED_ACCOUNTS`; a run without it turns mobile
209
+ sign-in off. It works for normal and low-power deploys. White-label builds that
210
+ use their own redirect URI add `WARDBY_MOBILE_REDIRECT_URI` to the control
211
+ plane's `env` themselves. See the help article `mobile-app`.
212
+
179
213
  Generate `SECRET_APP_KEY` with:
180
214
 
181
215
  ```sh
@@ -189,6 +223,13 @@ on. A value already in Secret Manager is never overwritten, so after the first
189
223
  deployment Secret Manager is the source of truth. You can then remove the
190
224
  production values from `.env.local`.
191
225
 
226
+ External Secrets Operator runs as three small pods in the `external-secrets`
227
+ namespace. `deploy/gke/eso-values.yaml` requests 100m CPU and 256 MiB of
228
+ memory for each (memory limited to the same), because Autopilot bills a pod
229
+ that requests nothing at 500m CPU and 2 GiB. If one is ever restarted for
230
+ exceeding its memory limit, raise the limit and request together in that file
231
+ and re-run `up.sh`; the Secrets it already synced are unaffected.
232
+
192
233
  Redeploying onto a cluster that already runs Wardby carries its existing
193
234
  `SECRET_APP_KEY` and login signing keys over, so stored credentials still
194
235
  decrypt and nobody has to sign in again.
@@ -249,9 +290,20 @@ The deployment script is idempotent. It converges Terraform, builds and pushes
249
290
  renders the GKE overlay, and waits for the proxy and control plane:
250
291
 
251
292
  ```sh
252
- HOSTNAME=wardby.example.com deploy/gke/up.sh
293
+ WARDBY_HOSTNAME=wardby.example.com deploy/gke/up.sh
253
294
  ```
254
295
 
296
+ Set `WARDBY_HOSTNAME`, not `HOSTNAME`: shells set `HOSTNAME` to the machine's own
297
+ name, so the script no longer reads it. It refuses a hostname with no dot, or a
298
+ local name such as `*.lan`, `*.local`, or `*.internal`. If you deployed with an
299
+ earlier version using `HOSTNAME=...`, pass the same value as `WARDBY_HOSTNAME`.
300
+
301
+ If the cluster is already published on a different hostname, the script stops
302
+ before building anything: moving the hostname breaks DNS, every client's
303
+ configured endpoint, and every issued token. In a terminal it asks you to type
304
+ the new hostname; elsewhere, set `WARDBY_HOSTNAME_CHANGE` to the new hostname to
305
+ confirm the move.
306
+
255
307
  Point the hostname's public A record at the reserved address:
256
308
 
257
309
  ```sh
@@ -275,11 +327,12 @@ through the Cloud SQL Auth Proxy, via Workload Identity from one Kubernetes
275
327
  service account. What each may do inside the database comes from a `NOLOGIN`
276
328
  group role in `deploy/gke/database-grants.sql`:
277
329
 
278
- | Workload | Google service account | Kubernetes service account | May do |
279
- | ------------- | ------------------------ | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
280
- | 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 |
281
- | 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` |
282
- | 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 |
330
+ | Workload | Google service account | Kubernetes service account | May do |
331
+ | -------------- | ------------------------ | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
332
+ | 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 |
333
+ | 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` |
334
+ | Native gateway | `<name_prefix>-gateway` | `wardby-native-gateway` | Member of `wardby_app`: the same data access as the control plane, under its own login (see [Native sandbox](#native-sandbox)) |
335
+ | 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 |
283
336
 
284
337
  `deploy/gke/bootstrap-database-iam.sh` applies the grants as the built-in
285
338
  owner, from a short-lived Job inside the cluster. Run it whenever
@@ -296,10 +349,16 @@ SQL Admin API, uses that password once to apply the grants, and resets it to
296
349
  a value nobody holds on every exit, including a failed grant. No password is
297
350
  ever stored, printed, or passed as a process argument.
298
351
 
352
+ A deployment that already runs and then gains the native gateway identity from
353
+ `terraform apply` runs `deploy/gke/bootstrap-database-iam.sh` once, so the
354
+ gateway's user gets its `wardby_app` membership, and then `deploy/gke/up.sh`.
355
+ `up.sh`'s database check also tests the native gateway and says so if the
356
+ grant is missing.
357
+
299
358
  A brand-new project runs, in this order:
300
359
 
301
360
  1. `terraform -chdir=deploy/gke apply` — creates the cluster, the instance
302
- and the three IAM database users. Run it yourself rather than through
361
+ and the four IAM database users. Run it yourself rather than through
303
362
  `up.sh`, which would go on to the migrations before the migrator has its
304
363
  grants.
305
364
  2. `deploy/gke/bootstrap-database-iam.sh` (default mode) — fetches the
@@ -568,6 +627,160 @@ it, set `replicas: 0` in
568
627
  A PriorityClass's value and preemption policy cannot be changed in place:
569
628
  delete the class and re-run `up.sh` to change them.
570
629
 
630
+ ### Native sandbox
631
+
632
+ Native sandbox requires Wardby 0.5.4 or later.
633
+
634
+ `up.sh` deploys everything the [native sandbox](native-sandbox.md) needs on
635
+ this cluster. It builds and pushes the `native-worker` image, checks it (Node is
636
+ present; `curl`, `wget`, `nc` and `ssh` are not), and pins it by digest as
637
+ `NATIVE_SANDBOX_WORKER_IMAGE`. It syncs the gateway's ExternalSecret, rolls out
638
+ `wardby-native-gateway`, waits for it, and checks its database round trip. The
639
+ control plane is configured with `NATIVE_SANDBOX_LAUNCHER=kubernetes`,
640
+ `NATIVE_SANDBOX_CPUS=0.5`, `NATIVE_SANDBOX_MEMORY_MB=512`,
641
+ `NATIVE_SANDBOX_MAX_CONCURRENT=4`, `NATIVE_SANDBOX_READY_TIMEOUT_MS=600000`
642
+ (a cold gVisor node takes about two minutes), and
643
+ `NATIVE_SANDBOX_ENFORCEMENT_TIMEOUT_MS=60000`. Worker pods use the gVisor runtime
644
+ class, `KUBERNETES_PLATFORM=gke-autopilot`, and the run priority class.
645
+
646
+ - **One-time bootstrap.** The gateway has its own database login. After
647
+ `terraform apply` adds its identity to an existing deployment, run
648
+ `deploy/gke/bootstrap-database-iam.sh` once, then `deploy/gke/up.sh`; see
649
+ [Database login](#database-login).
650
+ - **Enable per agent.** Nothing runs in the sandbox until you opt an agent in:
651
+ set its `nativeExecutionMode` to `sandbox` with the `update_agent` MCP tool
652
+ (native agents only).
653
+ - **Capacity.** At most `NATIVE_SANDBOX_MAX_CONCURRENT` sandbox runs are active
654
+ at once; a start past that fails with `native_sandbox_capacity` rather than
655
+ queuing. The `wardby-coding` ResourceQuota (26 pods, 11 CPU, 20Gi memory)
656
+ already covers the gateway's two replicas and that many 500m / 512Mi worker
657
+ pods. Raise the quota together with `NATIVE_SANDBOX_MAX_CONCURRENT` or
658
+ `CODING_MAX_CONCURRENT`.
659
+ - **Warm pool.** To keep idle, already-isolated workers ready so runs skip pod
660
+ scheduling and the isolation probe, set `NATIVE_SANDBOX_WARM_POOL_SIZE` (0 to
661
+ 50, default 0) in the control-plane manifest and raise the `wardby-coding`
662
+ ResourceQuota by that many 500m / 512Mi pods. Each idle worker is billed
663
+ continuously. See [Warm pool](native-sandbox.md#warm-pool).
664
+ - **Check isolation.** `npm run test:native-cluster` runs launcher-only
665
+ isolation checks against the deployed gateway; set `NATIVE_TEST_WORKER_IMAGE`
666
+ to the worker digest and `NATIVE_TEST_FORBIDDEN` to the database's private
667
+ `host:port` (for example `10.0.0.5:3307`).
668
+ - **Roll back.** Set an agent back to `control-plane` with `update_agent`; this
669
+ affects only new runs, and runs already started in sandbox mode finish there.
670
+ To undo a bad gateway release, run
671
+ `kubectl -n wardby-coding rollout undo deploy/wardby-native-gateway`.
672
+
673
+ ### Low-power mode
674
+
675
+ Low-power mode requires Wardby 0.6.0 or later.
676
+
677
+ Low-power mode cuts the idle cost of a deployment that runs agents only now and
678
+ then. The coding proxy and the native gateway scale to zero replicas when
679
+ nothing needs them, and wake on demand; the headroom placeholder is turned off;
680
+ and the control plane runs 1 copy, scaling to 2 under load. The database and
681
+ edge are unchanged.
682
+
683
+ Turn it on by deploying with the flag:
684
+
685
+ ```sh
686
+ WARDBY_HOSTNAME=wardby.example.com WARDBY_LOW_POWER=1 deploy/gke/up.sh
687
+ ```
688
+
689
+ To turn it off, re-run `up.sh` without the flag. That removes the autoscaler
690
+ (HorizontalPodAutoscaler `wardby-control-plane`) and the Role and RoleBinding
691
+ `wardby-power`, and restores the normal sizes: proxy 1, gateway 2, headroom 1,
692
+ control plane 1.
693
+
694
+ | Variable | Where it is set | Values | Meaning |
695
+ | ------------------------ | ---------------------------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
696
+ | `WARDBY_LOW_POWER` | `up.sh` environment; control plane | unset, `0` (off) or `1` (on) | Anything else fails `up.sh` and stops the control plane at start-up. Needs `JOB_LAUNCHER=kubernetes`, else it logs `low_power_ignored` and does nothing. |
697
+ | `LOW_POWER_IDLE_MINUTES` | Control-plane Deployment | integer 5 to 1440, default `30` | How long a target must be unused before it sleeps. Read only when `WARDBY_LOW_POWER=1`. |
698
+
699
+ **Sleeping.** Every minute the scheduler leader scales the coding proxy
700
+ (`wardby-coding-proxy`) to 0 when no coding run is pending or running and none
701
+ finished within the idle window. It scales the native gateway
702
+ (`wardby-native-gateway`) to 0 when no sandbox native run is pending, running or
703
+ recently finished and the gateway has no active session. Either target sleeps
704
+ only once at least one idle window has passed since it was last woken (recorded
705
+ in its `wardby.io/power-woke-at` annotation) and since the control plane
706
+ started, whichever is later. The condition is checked again immediately before
707
+ scaling. The control plane
708
+ logs `power: proxy slept (idle 30m)`.
709
+
710
+ **Waking.** Starting a coding run scales the proxy to 1 and waits for a ready
711
+ endpoint. Starting a sandbox run does the same for the gateway. The wait is at
712
+ least 5 minutes, because a cold Autopilot node can add 1 to 2 minutes of
713
+ start-up; a `KUBERNETES_READY_TIMEOUT_MS` (proxy) or
714
+ `NATIVE_SANDBOX_READY_TIMEOUT_MS` (gateway) above 5 minutes, set on the
715
+ control-plane Deployment, raises it to that value. The first coding run after a
716
+ control-plane restart also runs the cluster preflight canary, because start-up
717
+ preflight is deferred while the proxy sleeps (`kubernetes_preflight_deferred`).
718
+
719
+ **Deploys.** Every `up.sh` run marks the proxy and gateway as just woken before
720
+ it applies the manifests, which bring them back up. That includes a run that
721
+ turns low-power mode off: the control plane being replaced still runs in
722
+ low-power mode until its rollout ends, and the mark stops it scaling them back
723
+ down. With the mode on they stay up through the deploy (its database checks
724
+ need them) and sleep one idle window later if nothing uses them.
725
+
726
+ **Sleeping now.** To skip the idle window (for example right after a test), an
727
+ admin calls the MCP tool `power_sleep`, optionally with `target` set to `proxy`
728
+ or `gateway` (default both). It scales the target to 0 at once, but never stops
729
+ a run: a target with a pending or running run, or for the gateway an active
730
+ gateway session, is left up and its run ids are returned under `blocked`.
731
+ Recently finished runs do not block it. The next run wakes the target as usual.
732
+ `power_status` shows each target's replicas, readiness, last wake time and
733
+ blocking run ids. Both tools need the `power:manage` scope, which only the
734
+ `admin` role grants; with the mode off, `power_sleep` fails with
735
+ `409 low_power_disabled` and `power_status` returns `{ "enabled": false }`.
736
+ Each `power_sleep` is logged as `event: "power.sleep"` with the caller's
737
+ principal.
738
+
739
+ **Control-plane autoscaling.** The control plane scales between 1 and 2 copies
740
+ on CPU (20% target, scale-down after 10 minutes). A run executes on
741
+ the copy that started it, so scheduled runs stay on the scheduler leader, while
742
+ runs started by a webhook or over MCP spread across copies. While the mode is on
743
+ the autoscaler owns the replica count, so do not set it by hand.
744
+
745
+ **Trade-offs.**
746
+
747
+ - Headroom is off, so the control plane has less protection against being
748
+ preempted when the cluster is short of capacity (see
749
+ [Pod priority and headroom](#pod-priority-and-headroom)).
750
+ - The gateway runs 1 replica instead of 2 while awake, so there is no
751
+ redundancy.
752
+ - `NATIVE_SANDBOX_WARM_POOL_SIZE` must be 0; the control plane refuses to start
753
+ otherwise, because a warm pool needs the gateway running.
754
+ - The gateway must be in the same namespace as `KUBERNETES_NAMESPACE`.
755
+ - The control plane needs the `wardby-power` Role: `get` and `patch` on the
756
+ proxy and gateway Deployments, and `get` on their Endpoints (to tell when a
757
+ woken target is ready). If any of it is missing, start-up warns
758
+ `low_power_scale_forbidden: missing ...` naming each permission, and waking,
759
+ `power_status` and `power_sleep` fail with that error; re-run `up.sh` with
760
+ the flag.
761
+
762
+ **Cost.** Autopilot bills Pod requests while a Pod exists. The table uses
763
+ us-central1 list prices of $0.0445 per vCPU-hour and $0.0049225 per GiB-hour and
764
+ 730 hours a month; substitute your region's current rates. Requests include the
765
+ Cloud SQL sidecar.
766
+
767
+ | Workload | Requests per replica | Per hour | Per month, always on | In low-power mode |
768
+ | ---------------------------- | --------------------- | -------- | -------------------- | --------------------------------------- |
769
+ | Control plane | 1.1 vCPU / 2.125 GiB | $0.0594 | $43.37 | 1 copy always; $0.0594/h per extra copy |
770
+ | Coding proxy | 1.1 vCPU / 3.125 GiB | $0.0643 | $46.96 | $0.0643/h only while awake |
771
+ | Native gateway (per replica) | 0.35 vCPU / 0.625 GiB | $0.0187 | $13.62 (x2 = $27.23) | 1 replica, $0.0187/h only while awake |
772
+ | Headroom placeholder | 0.25 vCPU / 0.5 GiB | $0.0136 | $9.92 | $0 |
773
+
774
+ With the mode off, those four workloads cost about $127.48 a month at these
775
+ rates. In low-power mode the control plane is still always on, and a fully
776
+ awake moment costs about $0.142 an hour for one control-plane copy, the proxy
777
+ and one gateway replica. Your total depends on how many hours the proxy and
778
+ gateway stay awake. Cloud SQL, the static address, load balancer, Cloud Armor
779
+ and any other always-on component are unchanged.
780
+
781
+ For error codes and log lines, see the
782
+ [low-power mode help article](../help/low-power-mode.md).
783
+
571
784
  ### Coding-run services
572
785
 
573
786
  A coding run whose agent allows [services](coding-services.md) waits for each
@@ -587,6 +800,7 @@ before. `up.sh` prints the previous digests at the end of every deploy.
587
800
  ```sh
588
801
  kubectl -n wardby-coding rollout undo deploy/wardby-control-plane
589
802
  kubectl -n wardby-coding rollout undo deploy/wardby-coding-proxy
803
+ kubectl -n wardby-coding rollout undo deploy/wardby-native-gateway
590
804
  ```
591
805
 
592
806
  `rollout undo` restores only the Deployments' images and pod templates — there
@@ -623,7 +837,9 @@ kubectl -n wardby-coding rollout restart deploy/wardby-coding-proxy deploy/wardb
623
837
 
624
838
  For a Jira setting, add the version to its `wardby-jira-*` secret, wait on
625
839
  `wardby-jira-env` instead, and restart only `deploy/wardby-control-plane`.
626
- Rotate the token and its `jira-api-token-expires-at` together.
840
+ Rotate the token and its `jira-api-token-expires-at` together. The Slack bot
841
+ token works the same way: add the version to `wardby-slack-bot-token`, wait on
842
+ `wardby-slack-env`, and restart only `deploy/wardby-control-plane`.
627
843
 
628
844
  Pods read their environment only at start, hence the restart. The LLM API
629
845
  keys and the database URL are read by both Deployments; the other secrets only
@@ -70,9 +70,10 @@ Create these scopes in the provider:
70
70
  | `memory:write` | Set and delete agent memory entries. |
71
71
  | `admin:view` | Read every owner's runs through the admin viewer API; admins only. |
72
72
  | `models:admin` | Add, override, disable and reset model catalog entries. |
73
+ | `power:manage` | Read low-power state and sleep the proxy/gateway now; admins only. |
73
74
 
74
75
  MCP clients discover this list from Wardby's protected-resource metadata and
75
- may request every advertised scope. Define all fourteen in the provider even when
76
+ may request every advertised scope. Define all fifteen in the provider even when
76
77
  policy grants a particular client or user only a subset. Ensure granted scopes
77
78
  are emitted in the access token's `scope` or `scp` claim; defining them only in
78
79
  the provider UI is not sufficient.
@@ -92,17 +93,21 @@ otherwise clients that request every advertised scope fail with `invalid_scope`.
92
93
  deployment, define it in the provider too; otherwise clients that request
93
94
  every advertised scope fail with `invalid_scope`.
94
95
 
96
+ `power:manage` was added after `models:admin`. When you upgrade an existing
97
+ deployment, define it in the provider too and map it like `agents:admin`;
98
+ otherwise clients that request every advertised scope fail with `invalid_scope`.
99
+
95
100
  ### Wardby roles
96
101
 
97
102
  A scope only delegates. `agents:admin`, `packages:approve`, `services:manage`,
98
- `admin:view` and `models:admin` take effect only for a caller who also holds a Wardby role that grants them:
103
+ `admin:view`, `models:admin` and `power:manage` take effect only for a caller who also holds a Wardby role that grants them:
99
104
 
100
- | Wardby role | Grants |
101
- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
102
- | `admin` | `agents:admin` (`make_owner`, BYO `workerImageRef`), `packages:approve`, `services:manage`, `admin:view` (read every owner's runs, see [viewer-api.md](viewer-api.md)) and `models:admin` (model catalog) |
103
- | `package-approver` | `packages:approve` (package allowlist and policy approval) |
104
- | `service-manager` | `services:manage` (coding-run service catalog changes) |
105
- | `model-manager` | `models:admin` (model catalog changes: `set_model`, `disable_model`, `reset_model`; see [models.md](models.md)) |
105
+ | Wardby role | Grants |
106
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
107
+ | `admin` | `agents:admin` (`make_owner`, BYO `workerImageRef`), `packages:approve`, `services:manage`, `admin:view` (read every owner's runs, see [viewer-api.md](viewer-api.md)), `models:admin` (model catalog) and `power:manage` (`power_status`, `power_sleep`; see [getting-started-gke.md](getting-started-gke.md#low-power-mode)) |
108
+ | `package-approver` | `packages:approve` (package allowlist and policy approval) |
109
+ | `service-manager` | `services:manage` (coding-run service catalog changes) |
110
+ | `model-manager` | `models:admin` (model catalog changes: `set_model`, `disable_model`, `reset_model`; see [models.md](models.md)) |
106
111
 
107
112
  The roles come from a claim in the caller's **access token**, which you map to
108
113
  Wardby roles:
@@ -162,7 +167,7 @@ Provider examples:
162
167
  to the access token, filtered to those groups. Set `AUTH_ROLE_CLAIM=groups` and
163
168
  `AUTH_ROLE_MAP=wardby-admin=admin,wardby-packages=package-approver,wardby-services=service-manager,wardby-models=model-manager`.
164
169
  Optionally, add access policy rules so only those groups can obtain
165
- `agents:admin`, `packages:approve`, `services:manage`, `admin:view` and `models:admin`.
170
+ `agents:admin`, `packages:approve`, `services:manage`, `admin:view`, `models:admin` and `power:manage`.
166
171
  - **FusionAuth:** create four application roles, `admin`,
167
172
  `package-approver`, `service-manager` and `model-manager`. They appear in the
168
173
  access token's top-level `roles` claim. Set `AUTH_ROLE_CLAIM=roles` and
@@ -188,6 +193,11 @@ that case, register the MCP client manually as a **public/native application**:
188
193
  - register the client's exact loopback callback URI; and
189
194
  - allow it to request the Wardby audience and scopes.
190
195
 
196
+ To let the Wardby mobile app sign in, also register its private-use redirect
197
+ URI, `com.wardby.mobile:/oauth` (or your white-label build's redirect, such as
198
+ `com.example.app:/oauth`), as an allowed redirect URI on the IdP client that
199
+ requests `admin:view`. Wardby needs no setting for this in delegating mode.
200
+
191
201
  For Claude Code, a fixed callback port makes the redirect URI predictable:
192
202
 
193
203
  ```sh
@@ -253,7 +263,7 @@ Confirm that:
253
263
 
254
264
  - `resource` is the canonical MCP URI;
255
265
  - `authorization_servers` contains the external issuer; and
256
- - `scopes_supported` contains all fourteen Wardby scopes.
266
+ - `scopes_supported` contains all fifteen Wardby scopes.
257
267
 
258
268
  An unauthenticated MCP request must return `401` with a `WWW-Authenticate`
259
269
  challenge pointing back to that metadata document.
@@ -310,6 +320,7 @@ test procedure and cleanup.
310
320
  | Wardby returns `403 insufficient_scope` | The token is valid but `scope`/`scp` lacks the operation's required permission. |
311
321
  | Client registration returns `403` | Anonymous dynamic registration is disabled; pre-register a public client. |
312
322
  | Browser flow rejects the redirect | The provider's registered loopback callback does not exactly match the client. |
323
+ | Mobile sign-in fails with a redirect error | The IdP client doesn't list the mobile redirect URI. |
313
324
  | Wardby cannot validate any newly issued token | The control plane cannot reach the JWKS URI, or provider key rotation is incomplete. |
314
325
  | One person appears as multiple principals | The provider is emitting different or pairwise `sub` values for different clients. |
315
326
 
@@ -162,8 +162,9 @@ any local branch.
162
162
  Wardby's worker images have Node, or Node and Python 3.12. For a Go, Java, Rust
163
163
  or other project, build a worker image with that toolchain on Wardby's driver
164
164
  base image, and point the builder at it with `codingProfile.workerImageRef`.
165
- This works for **Codex** agents only today: a Claude Code agent runs its
166
- commands in its tool runner, which a custom worker image does not change.
165
+ These steps are for a **Codex** builder. For a Claude Code builder, the image
166
+ starts from Wardby's tool runner image instead; see
167
+ [Codex and Claude Code](coding-worker-byo-images.md#codex-and-claude-code).
167
168
 
168
169
  1. Complete path A with Codex (`--coding-provider codex`).
169
170
  2. Run `npx @wardby/cli@latest doctor`. It prints the base image to build on:
@@ -347,8 +348,8 @@ Python tests. Upgrade, or set the variable above.
347
348
  Other languages (Go, Rust, Java and so on) are not detected. Use a
348
349
  bring-your-own image through `workerImageRef`; see
349
350
  [Path D](#path-d-another-language-build-your-own-image) and
350
- [Bring-your-own worker images](coding-worker-byo-images.md). That is Codex-only
351
- today: a Claude Code agent cannot use a custom toolchain yet.
351
+ [Bring-your-own worker images](coding-worker-byo-images.md), for Codex or
352
+ Claude Code.
352
353
 
353
354
  #### Packages the repository declares
354
355
 
@@ -24,7 +24,7 @@ Jira Cloud only. One Jira site per wardby deployment.
24
24
  properties are not allowlisted.
25
25
  - **Status comments.** When an event starts a run, wardby posts a short
26
26
  "working on it" comment on the issue and edits it with the outcome when the
27
- run ends, including a line such as `Agent spend: $0.0123` for the run and
27
+ run ends, including a line such as `Agent spend: $0.012` for the run and
28
28
  its direct sub-runs. That one comment is the reply: when the run succeeds
29
29
  it shows the agent's final answer, so the agent is told not to post the
30
30
  answer again with `jira_comment` (it uses `jira_comment` only for other
@@ -478,6 +478,10 @@ What happens:
478
478
  [`code-review-agents.md`](code-review-agents.md)). Without them the pull
479
479
  request is still linked, but the issue is not updated on merge.
480
480
 
481
+ To mirror this lifecycle in Slack — picked up, pull request open, review
482
+ verdict, merge — link a channel to the project or agent; see
483
+ [Send workflow updates to Slack](slack-notifications.md).
484
+
481
485
  ## Recipe: scheduled JQL sweeps
482
486
 
483
487
  An agent linked to a project can also run on a schedule with no issue event: