@wardby/cli 0.5.2 → 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 (411) 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/local-git.js +9 -1
  17. package/dist/coding/profile.d.ts +12 -0
  18. package/dist/coding/profile.js +6 -0
  19. package/dist/coding/protocol.d.ts +104 -0
  20. package/dist/coding/protocol.js +87 -3
  21. package/dist/coding/registry/pypi.d.ts +25 -1
  22. package/dist/coding/registry/pypi.js +140 -16
  23. package/dist/coding/registry/types.d.ts +17 -3
  24. package/dist/coding-worker/artifact.d.ts +8 -0
  25. package/dist/coding-worker/artifact.js +2 -2
  26. package/dist/coding-worker/driver.js +2 -0
  27. package/dist/coding-worker/sdk.d.ts +6 -0
  28. package/dist/coding-worker/sdk.js +1 -0
  29. package/dist/coding-worker/skills.d.ts +23 -0
  30. package/dist/coding-worker/skills.js +117 -0
  31. package/dist/coding-worker/types.d.ts +2 -0
  32. package/dist/config/github-allowed-accounts.d.ts +15 -0
  33. package/dist/config/github-allowed-accounts.js +36 -0
  34. package/dist/config/low-power.d.ts +12 -0
  35. package/dist/config/low-power.js +18 -0
  36. package/dist/config/mobile.d.ts +12 -0
  37. package/dist/config/mobile.js +18 -0
  38. package/dist/config/providers.d.ts +56 -2
  39. package/dist/config/providers.js +92 -6
  40. package/dist/core/db.d.ts +16 -6
  41. package/dist/core/db.js +12 -10
  42. package/dist/core/dispatch.d.ts +11 -0
  43. package/dist/core/dispatch.js +36 -1
  44. package/dist/core/engine-native.js +9 -5
  45. package/dist/core/host-events.d.ts +49 -3
  46. package/dist/core/host-events.js +289 -15
  47. package/dist/core/http-runtime.js +13 -6
  48. package/dist/core/issue-bridge.js +42 -2
  49. package/dist/core/issue-events.js +12 -1
  50. package/dist/core/issue-status.js +14 -3
  51. package/dist/core/merge-order-check.d.ts +129 -0
  52. package/dist/core/merge-order-check.js +336 -0
  53. package/dist/core/notification-dispatcher.d.ts +70 -0
  54. package/dist/core/notification-dispatcher.js +368 -0
  55. package/dist/core/notification-templates.d.ts +25 -0
  56. package/dist/core/notification-templates.js +105 -0
  57. package/dist/core/notifications.d.ts +10 -0
  58. package/dist/core/notifications.js +38 -0
  59. package/dist/core/pg-auth.d.ts +22 -0
  60. package/dist/core/pg-auth.js +152 -0
  61. package/dist/core/power-composition.d.ts +16 -0
  62. package/dist/core/power-composition.js +37 -0
  63. package/dist/core/power-idle.d.ts +14 -0
  64. package/dist/core/power-idle.js +30 -0
  65. package/dist/core/power.d.ts +71 -0
  66. package/dist/core/power.js +202 -0
  67. package/dist/core/reconciler.d.ts +4 -2
  68. package/dist/core/reconciler.js +29 -5
  69. package/dist/core/related-pull-requests.d.ts +48 -4
  70. package/dist/core/related-pull-requests.js +113 -11
  71. package/dist/core/repo-access.d.ts +15 -0
  72. package/dist/core/repo-access.js +66 -0
  73. package/dist/core/review-fix.d.ts +37 -0
  74. package/dist/core/review-fix.js +207 -6
  75. package/dist/core/review-host-tools.d.ts +20 -0
  76. package/dist/core/review-host-tools.js +58 -2
  77. package/dist/core/runner.d.ts +336 -3
  78. package/dist/core/runner.js +894 -317
  79. package/dist/core/secret-broker-config.d.ts +103 -0
  80. package/dist/core/secret-broker-config.js +112 -0
  81. package/dist/core/secrets.d.ts +39 -4
  82. package/dist/core/secrets.js +148 -40
  83. package/dist/core/workflow-event-recorder.d.ts +14 -0
  84. package/dist/core/workflow-event-recorder.js +120 -0
  85. package/dist/core/workflow-events.d.ts +82 -0
  86. package/dist/core/workflow-events.js +44 -0
  87. package/dist/core/workflow-run-events.d.ts +16 -0
  88. package/dist/core/workflow-run-events.js +40 -0
  89. package/dist/generated/prisma/browser.d.ts +58 -0
  90. package/dist/generated/prisma/client.d.ts +58 -0
  91. package/dist/generated/prisma/commonInputTypes.d.ts +150 -0
  92. package/dist/generated/prisma/enums.d.ts +27 -0
  93. package/dist/generated/prisma/enums.js +23 -0
  94. package/dist/generated/prisma/internal/class.d.ts +88 -0
  95. package/dist/generated/prisma/internal/class.js +4 -4
  96. package/dist/generated/prisma/internal/prismaNamespace.d.ts +772 -1
  97. package/dist/generated/prisma/internal/prismaNamespace.js +135 -4
  98. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +139 -0
  99. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +135 -4
  100. package/dist/generated/prisma/models/Agent.d.ts +360 -1
  101. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +73 -1
  102. package/dist/generated/prisma/models/CodingRun.d.ts +205 -1
  103. package/dist/generated/prisma/models/DeferredReview.d.ts +78 -1
  104. package/dist/generated/prisma/models/NativeGatewayCall.d.ts +1675 -0
  105. package/dist/generated/prisma/models/NativeGatewayCall.js +1 -0
  106. package/dist/generated/prisma/models/NativeGatewaySession.d.ts +1517 -0
  107. package/dist/generated/prisma/models/NativeGatewaySession.js +1 -0
  108. package/dist/generated/prisma/models/NativeWarmWorker.d.ts +1296 -0
  109. package/dist/generated/prisma/models/NativeWarmWorker.js +1 -0
  110. package/dist/generated/prisma/models/NotificationChannel.d.ts +1543 -0
  111. package/dist/generated/prisma/models/NotificationChannel.js +1 -0
  112. package/dist/generated/prisma/models/NotificationDelivery.d.ts +1502 -0
  113. package/dist/generated/prisma/models/NotificationDelivery.js +1 -0
  114. package/dist/generated/prisma/models/NotificationThread.d.ts +1090 -0
  115. package/dist/generated/prisma/models/NotificationThread.js +1 -0
  116. package/dist/generated/prisma/models/Run.d.ts +826 -1
  117. package/dist/generated/prisma/models/RunHostCheck.d.ts +36 -1
  118. package/dist/generated/prisma/models/Secret.d.ts +37 -1
  119. package/dist/generated/prisma/models/SecretBrokerChange.d.ts +1101 -0
  120. package/dist/generated/prisma/models/SecretBrokerChange.js +1 -0
  121. package/dist/generated/prisma/models/WorkflowEvent.d.ts +1422 -0
  122. package/dist/generated/prisma/models/WorkflowEvent.js +1 -0
  123. package/dist/generated/prisma/models.d.ts +8 -0
  124. package/dist/help/build.js +4 -2
  125. package/dist/help/catalog.d.ts +1 -1
  126. package/dist/help/catalog.js +31 -6
  127. package/dist/help-index.json +1492 -113
  128. package/dist/import/create.js +17 -0
  129. package/dist/import/neutral-schema.d.ts +6 -2
  130. package/dist/import/neutral-schema.js +2 -0
  131. package/dist/mcp/auth/access.d.ts +1 -0
  132. package/dist/mcp/auth/ownership.d.ts +1 -1
  133. package/dist/mcp/auth/repo-authorization.js +14 -0
  134. package/dist/mcp/auth/resource-server.d.ts +2 -1
  135. package/dist/mcp/auth/resource-server.js +7 -2
  136. package/dist/mcp/auth/self-hosted/browser.d.ts +1 -1
  137. package/dist/mcp/auth/self-hosted/browser.js +19 -6
  138. package/dist/mcp/context.d.ts +6 -0
  139. package/dist/mcp/host-events/github-ingress.d.ts +23 -1
  140. package/dist/mcp/host-events/github-ingress.js +68 -0
  141. package/dist/mcp/index.d.ts +13 -0
  142. package/dist/mcp/index.js +59 -10
  143. package/dist/mcp/tools/agents.js +83 -12
  144. package/dist/mcp/tools/notification-channels.d.ts +2 -0
  145. package/dist/mcp/tools/notification-channels.js +293 -0
  146. package/dist/mcp/tools/power.d.ts +2 -0
  147. package/dist/mcp/tools/power.js +77 -0
  148. package/dist/mcp/tools/runs.d.ts +0 -6
  149. package/dist/mcp/tools/runs.js +7 -2
  150. package/dist/mcp/tools/secret-broker-compat.d.ts +12 -0
  151. package/dist/mcp/tools/secret-broker-compat.js +23 -0
  152. package/dist/mcp/tools/secret-elicitation-form.d.ts +22 -2
  153. package/dist/mcp/tools/secret-elicitation-form.js +200 -10
  154. package/dist/mcp/tools/secret-elicitation-server.js +8 -1
  155. package/dist/mcp/tools/secret-elicitation.d.ts +38 -3
  156. package/dist/mcp/tools/secret-elicitation.js +110 -12
  157. package/dist/mcp/tools/secrets.js +184 -7
  158. package/dist/mcp/tools/tools.d.ts +1 -1
  159. package/dist/mcp/tools/tools.js +22 -2
  160. package/dist/native-worker/composition.d.ts +23 -0
  161. package/dist/native-worker/composition.js +77 -0
  162. package/dist/native-worker/docker-isolation.d.ts +65 -0
  163. package/dist/native-worker/docker-isolation.js +183 -0
  164. package/dist/native-worker/docker-launcher.d.ts +74 -0
  165. package/dist/native-worker/docker-launcher.js +237 -0
  166. package/dist/native-worker/gateway-server.d.ts +39 -0
  167. package/dist/native-worker/gateway-server.js +315 -0
  168. package/dist/native-worker/gateway.d.ts +44 -0
  169. package/dist/native-worker/gateway.js +197 -0
  170. package/dist/native-worker/http-server.d.ts +22 -0
  171. package/dist/native-worker/http-server.js +109 -0
  172. package/dist/native-worker/http-transport.d.ts +17 -0
  173. package/dist/native-worker/http-transport.js +88 -0
  174. package/dist/native-worker/kubernetes-isolation.d.ts +90 -0
  175. package/dist/native-worker/kubernetes-isolation.js +218 -0
  176. package/dist/native-worker/kubernetes-launcher.d.ts +102 -0
  177. package/dist/native-worker/kubernetes-launcher.js +335 -0
  178. package/dist/native-worker/launch.d.ts +45 -0
  179. package/dist/native-worker/launch.js +44 -0
  180. package/dist/native-worker/ledger.d.ts +109 -0
  181. package/dist/native-worker/ledger.js +192 -0
  182. package/dist/native-worker/loopback.d.ts +12 -0
  183. package/dist/native-worker/loopback.js +49 -0
  184. package/dist/native-worker/main.d.ts +7 -0
  185. package/dist/native-worker/main.js +74 -0
  186. package/dist/native-worker/protocol.d.ts +744 -0
  187. package/dist/native-worker/protocol.js +200 -0
  188. package/dist/native-worker/sandbox-executor.d.ts +68 -0
  189. package/dist/native-worker/sandbox-executor.js +210 -0
  190. package/dist/native-worker/stdio.d.ts +29 -0
  191. package/dist/native-worker/stdio.js +188 -0
  192. package/dist/native-worker/warm-delivery.d.ts +16 -0
  193. package/dist/native-worker/warm-delivery.js +33 -0
  194. package/dist/native-worker/warm-pool-ledger.d.ts +39 -0
  195. package/dist/native-worker/warm-pool-ledger.js +73 -0
  196. package/dist/native-worker/warm-pool.d.ts +107 -0
  197. package/dist/native-worker/warm-pool.js +283 -0
  198. package/dist/native-worker/worker.d.ts +17 -0
  199. package/dist/native-worker/worker.js +115 -0
  200. package/dist/providers/auth/authorization-server.d.ts +3 -0
  201. package/dist/providers/auth/index.js +2 -0
  202. package/dist/providers/auth/self-hosted.d.ts +13 -1
  203. package/dist/providers/auth/self-hosted.js +54 -4
  204. package/dist/providers/chat/fake.d.ts +46 -0
  205. package/dist/providers/chat/fake.js +39 -0
  206. package/dist/providers/chat/index.d.ts +4 -0
  207. package/dist/providers/chat/index.js +8 -0
  208. package/dist/providers/chat/slack.d.ts +37 -0
  209. package/dist/providers/chat/slack.js +105 -0
  210. package/dist/providers/chat/types.d.ts +42 -0
  211. package/dist/providers/chat/types.js +19 -0
  212. package/dist/providers/coding-proxy/mock-upstream.d.ts +33 -0
  213. package/dist/providers/coding-proxy/mock-upstream.js +116 -0
  214. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +3 -0
  215. package/dist/providers/coding-proxy/registry/prisma-store.js +17 -0
  216. package/dist/providers/coding-proxy/registry/service.d.ts +4 -0
  217. package/dist/providers/coding-proxy/registry/service.js +20 -3
  218. package/dist/providers/coding-proxy/registry/store.d.ts +18 -1
  219. package/dist/providers/coding-proxy/registry/store.js +33 -0
  220. package/dist/providers/coding-proxy/runtime.js +12 -1
  221. package/dist/providers/coding-proxy/types.d.ts +2 -0
  222. package/dist/providers/engine/types.d.ts +19 -0
  223. package/dist/providers/engine/types.js +22 -0
  224. package/dist/providers/executor/composition.d.ts +24 -1
  225. package/dist/providers/executor/composition.js +39 -6
  226. package/dist/providers/executor/container.d.ts +24 -1
  227. package/dist/providers/executor/container.js +101 -11
  228. package/dist/providers/executor/dbos.d.ts +42 -0
  229. package/dist/providers/executor/dbos.js +118 -12
  230. package/dist/providers/executor/deferred.d.ts +56 -0
  231. package/dist/providers/executor/deferred.js +119 -0
  232. package/dist/providers/executor/routing.d.ts +37 -10
  233. package/dist/providers/executor/routing.js +73 -32
  234. package/dist/providers/executor/types.d.ts +12 -0
  235. package/dist/providers/jobs/docker.js +3 -3
  236. package/dist/providers/jobs/fake-kubernetes-api.d.ts +21 -2
  237. package/dist/providers/jobs/fake-kubernetes-api.js +42 -1
  238. package/dist/providers/jobs/kubernetes-api.d.ts +17 -1
  239. package/dist/providers/jobs/kubernetes-api.js +7 -0
  240. package/dist/providers/jobs/kubernetes-client.d.ts +10 -1
  241. package/dist/providers/jobs/kubernetes-client.js +52 -3
  242. package/dist/providers/jobs/kubernetes-dry-run-fixture.d.ts +6 -1
  243. package/dist/providers/jobs/kubernetes-dry-run-fixture.js +6 -3
  244. package/dist/providers/jobs/kubernetes-isolation.d.ts +16 -1
  245. package/dist/providers/jobs/kubernetes-isolation.js +58 -5
  246. package/dist/providers/jobs/kubernetes-platform.d.ts +4 -1
  247. package/dist/providers/jobs/kubernetes-platform.js +38 -1
  248. package/dist/providers/jobs/kubernetes-preflight.d.ts +2 -1
  249. package/dist/providers/jobs/kubernetes-preflight.js +4 -2
  250. package/dist/providers/jobs/kubernetes.d.ts +56 -7
  251. package/dist/providers/jobs/kubernetes.js +117 -36
  252. package/dist/providers/jobs/metadata-probes.d.ts +11 -0
  253. package/dist/providers/jobs/metadata-probes.js +13 -0
  254. package/dist/providers/jobs/types.d.ts +9 -0
  255. package/dist/providers/llm/openai.js +0 -1
  256. package/dist/providers/review-host/github.d.ts +11 -1
  257. package/dist/providers/review-host/github.js +50 -0
  258. package/dist/providers/review-host/types.d.ts +23 -0
  259. package/dist/providers/vcs/github.d.ts +32 -6
  260. package/dist/providers/vcs/github.js +74 -16
  261. package/dist/quickstart/coding-db.js +14 -2
  262. package/dist/quickstart/coding-doctor.d.ts +3 -0
  263. package/dist/quickstart/coding-doctor.js +3 -0
  264. package/dist/quickstart/coding-images.d.ts +9 -0
  265. package/dist/quickstart/coding-images.js +39 -0
  266. package/dist/quickstart/coding-seed.d.ts +20 -1
  267. package/dist/quickstart/coding-seed.js +96 -7
  268. package/dist/quickstart/coding.d.ts +2 -0
  269. package/dist/quickstart/coding.js +75 -3
  270. package/dist/quickstart/config.d.ts +2 -0
  271. package/dist/quickstart/config.js +4 -0
  272. package/dist/quickstart/images.d.ts +13 -0
  273. package/dist/quickstart/images.js +80 -12
  274. package/dist/quickstart/index.d.ts +0 -2
  275. package/dist/quickstart/index.js +10 -14
  276. package/dist/quickstart/manifests.d.ts +56 -0
  277. package/dist/quickstart/manifests.js +523 -0
  278. package/dist/quickstart/python-detect.d.ts +10 -0
  279. package/dist/quickstart/python-detect.js +32 -0
  280. package/dist/quickstart/repo-packages.d.ts +10 -0
  281. package/dist/quickstart/repo-packages.js +132 -0
  282. package/dist/quickstart/reviewer-prompt.d.ts +12 -0
  283. package/dist/quickstart/reviewer-prompt.js +84 -0
  284. package/dist/quickstart/scenarios.d.ts +19 -0
  285. package/dist/quickstart/scenarios.js +28 -0
  286. package/dist/quickstart/sync-reviewer-prompt.d.ts +1 -0
  287. package/dist/quickstart/sync-reviewer-prompt.js +10 -0
  288. package/dist/quickstart-images.json +1 -1
  289. package/dist/sandbox/brokered-fetch.d.ts +23 -0
  290. package/dist/sandbox/brokered-fetch.js +37 -0
  291. package/dist/sandbox/host-functions.d.ts +34 -0
  292. package/dist/sandbox/host-functions.js +144 -80
  293. package/dist/sandbox/prelude.js +7 -1
  294. package/dist/sandbox/run-in-sandbox.d.ts +19 -0
  295. package/dist/sandbox/run-in-sandbox.js +28 -10
  296. package/dist/sandbox/safe-fetch.d.ts +2 -0
  297. package/dist/sandbox/safe-fetch.js +3 -1
  298. package/dist/sandbox/secret-broker-sigv4.d.ts +2 -0
  299. package/dist/sandbox/secret-broker-sigv4.js +49 -0
  300. package/dist/sandbox/secret-broker.d.ts +34 -0
  301. package/dist/sandbox/secret-broker.js +162 -0
  302. package/dist/sandbox/user-tool.d.ts +14 -0
  303. package/dist/sandbox/user-tool.js +32 -0
  304. package/dist/serve.js +18 -0
  305. package/dist/viewer/api-schema.d.ts +214 -18
  306. package/dist/viewer/api-schema.js +22 -0
  307. package/dist/viewer/build-schemas.js +4 -1
  308. package/dist/viewer/event-bus.d.ts +6 -0
  309. package/dist/viewer/event-bus.js +16 -7
  310. package/dist/viewer/graph.d.ts +5 -2
  311. package/dist/viewer/graph.js +7 -2
  312. package/dist/viewer/http.d.ts +0 -1
  313. package/dist/viewer/http.js +2 -2
  314. package/dist/viewer/infra.js +25 -2
  315. package/dist/viewer/limits.d.ts +4 -0
  316. package/dist/viewer/limits.js +4 -0
  317. package/dist/viewer/openapi.d.ts +15 -0
  318. package/dist/viewer/openapi.js +172 -0
  319. package/docs/README.md +7 -0
  320. package/docs/agent-recipes.md +57 -8
  321. package/docs/architecture-runtime.md +16 -1
  322. package/docs/code-review-agents.md +139 -5
  323. package/docs/coding-agent-setup.md +127 -2
  324. package/docs/coding-packages.md +105 -5
  325. package/docs/coding-services.md +3 -1
  326. package/docs/coding-worker-byo-images.md +239 -2
  327. package/docs/coding-worker-isolation.md +88 -23
  328. package/docs/getting-started-gke.md +225 -9
  329. package/docs/getting-started-identity-provider.md +21 -10
  330. package/docs/getting-started.md +140 -11
  331. package/docs/jira-agents.md +5 -1
  332. package/docs/knowledge.md +11 -0
  333. package/docs/native-sandbox.md +635 -0
  334. package/docs/release-verification.md +9 -0
  335. package/docs/security-deployment.md +113 -12
  336. package/docs/slack-notifications.md +252 -0
  337. package/docs/tool-secrets.md +252 -0
  338. package/docs/viewer-api.md +46 -5
  339. package/docs/viewer-api.openapi.yml +1404 -0
  340. package/help/admin-viewer.md +6 -2
  341. package/help/agent-recipes.md +27 -0
  342. package/help/architecture-agent.md +136 -0
  343. package/help/brokered-secrets.md +79 -0
  344. package/help/build-claude-code-image.md +131 -0
  345. package/help/build-worker-image.md +195 -0
  346. package/help/code-review-agents.md +68 -6
  347. package/help/coding-packages.md +31 -2
  348. package/help/creating-agents.md +14 -0
  349. package/help/deploy-gke.md +37 -6
  350. package/help/deployment-targets.md +24 -13
  351. package/help/errors/coding-provider-not-configured.md +2 -2
  352. package/help/errors/database-auth-invalid.md +28 -0
  353. package/help/errors/github-account-not-allowed.md +25 -0
  354. package/help/errors/low-power-disabled.md +29 -0
  355. package/help/errors/low-power-scale-forbidden.md +35 -0
  356. package/help/errors/low-power-wake-timeout.md +30 -0
  357. package/help/errors/mobile-disabled.md +31 -0
  358. package/help/errors/native-sandbox-capacity.md +22 -0
  359. package/help/errors/native-sandbox-deadline-exceeded.md +19 -0
  360. package/help/errors/native-sandbox-docker-failed.md +20 -0
  361. package/help/errors/native-sandbox-gateway-unavailable.md +21 -0
  362. package/help/errors/native-sandbox-image-not-pinned.md +19 -0
  363. package/help/errors/native-sandbox-isolation-mismatch.md +20 -0
  364. package/help/errors/native-sandbox-network-unenforced.md +22 -0
  365. package/help/errors/native-sandbox-requires-catalog.md +31 -0
  366. package/help/errors/native-sandbox-unavailable.md +19 -0
  367. package/help/errors/native-sandbox-warm-delivery-failed.md +21 -0
  368. package/help/errors/native-sandbox-worker-exited.md +20 -0
  369. package/help/errors/native-sandbox-worker-lost.md +20 -0
  370. package/help/errors/native-sandbox-worker-unready.md +22 -0
  371. package/help/errors/secret-broker-body-invalid.md +26 -0
  372. package/help/errors/secret-broker-changed.md +20 -0
  373. package/help/errors/secret-broker-config-invalid.md +30 -0
  374. package/help/errors/secret-broker-conflict.md +27 -0
  375. package/help/errors/secret-broker-destination-denied.md +28 -0
  376. package/help/errors/secret-broker-value-invalid.md +28 -0
  377. package/help/errors/secret-brokered.md +24 -0
  378. package/help/errors/secret-not-brokered.md +25 -0
  379. package/help/errors/slack-auth-failed.md +48 -0
  380. package/help/errors/slack-channel-unreachable.md +39 -0
  381. package/help/errors/slack-not-configured.md +33 -0
  382. package/help/getting-started.md +18 -0
  383. package/help/github.md +18 -1
  384. package/help/identity-and-access.md +5 -1
  385. package/help/local-repositories.md +35 -5
  386. package/help/low-power-mode.md +125 -0
  387. package/help/merge-order-check.md +117 -0
  388. package/help/mobile-app.md +54 -0
  389. package/help/native-sandbox.md +136 -0
  390. package/help/observability.md +8 -0
  391. package/help/related-pull-requests.md +70 -9
  392. package/help/repo-instructions-and-skills.md +91 -0
  393. package/help/review-fix-rounds.md +10 -0
  394. package/help/slack-notifications.md +62 -0
  395. package/help/troubleshooting/coding-workers.md +21 -0
  396. package/package.json +13 -5
  397. package/prisma/migrations/20261009000003_native_execution_mode/migration.sql +12 -0
  398. package/prisma/migrations/20261009000004_native_gateway_ledger/migration.sql +65 -0
  399. package/prisma/migrations/20261009000005_native_gateway_call_child_agent/migration.sql +5 -0
  400. package/prisma/migrations/20261009000006_run_deferred_start_stop/migration.sql +14 -0
  401. package/prisma/migrations/20261009000007_native_gateway_network_ready/migration.sql +5 -0
  402. package/prisma/migrations/20261010000001_workflow_notifications/migration.sql +99 -0
  403. package/prisma/migrations/20261011000001_native_gateway_session_status_index/migration.sql +2 -0
  404. package/prisma/migrations/20261012000001_native_warm_worker/migration.sql +32 -0
  405. package/prisma/migrations/20261013000001_coding_run_merge_order/migration.sql +2 -0
  406. package/prisma/migrations/20261013000001_secret_broker/migration.sql +17 -0
  407. package/prisma/migrations/20261013000002_deferred_review_request/migration.sql +4 -0
  408. package/prisma/migrations/20261014000000_repo_skills/migration.sql +15 -0
  409. package/prisma/migrations/20261015000001_coding_run_merge_order_index/migration.sql +2 -0
  410. package/prisma/migrations/20261015000002_no_change_rereview/migration.sql +2 -0
  411. package/prisma/schema.prisma +362 -91
@@ -79,15 +79,15 @@ Scopes and roles do different jobs:
79
79
  - **Roles authorize.** A user has a set of roles. With no roles, the user is a
80
80
  member:
81
81
 
82
- | Role | Grants |
83
- | ------------------ | -------------------------------------------------------------------------------------- |
84
- | `admin` | `agents:admin`, `packages:approve`, `services:manage`, `admin:view` and `models:admin` |
85
- | `package-approver` | `packages:approve` |
86
- | `service-manager` | `services:manage` |
87
- | `model-manager` | `models:admin` |
88
- | (none) | nothing privileged; every other scope works as the token allows |
82
+ | Role | Grants |
83
+ | ------------------ | ------------------------------------------------------------------------------------------------------ |
84
+ | `admin` | `agents:admin`, `packages:approve`, `services:manage`, `admin:view`, `models:admin` and `power:manage` |
85
+ | `package-approver` | `packages:approve` |
86
+ | `service-manager` | `services:manage` |
87
+ | `model-manager` | `models:admin` |
88
+ | (none) | nothing privileged; every other scope works as the token allows |
89
89
 
90
- Seven operations are privileged:
90
+ Eight operations are privileged:
91
91
 
92
92
  - `make_owner`, which reassigns any agent's owner, including another
93
93
  principal's private agent (see [Sharing agents](#sharing-agents) for what
@@ -104,7 +104,10 @@ Seven operations are privileged:
104
104
  (`set_model`, `disable_model`, `reset_model`; reading the catalog is
105
105
  `agents:read`, see [models.md](models.md));
106
106
  - reading every owner's runs through the admin viewer API (see
107
- [viewer-api.md](viewer-api.md)).
107
+ [viewer-api.md](viewer-api.md));
108
+ - reading low-power state and scaling the coding proxy and native gateway to
109
+ zero now (`power_status`, `power_sleep`; see
110
+ [Low-power mode](getting-started-gke.md#low-power-mode)).
108
111
 
109
112
  Each needs **both** its scope on the token **and** a role that grants that
110
113
  permission:
@@ -114,10 +117,12 @@ permission:
114
117
  - Service catalog changes need `services:manage`.
115
118
  - Model catalog changes need `models:admin`.
116
119
  - The admin viewer API needs `admin:view`, which only the `admin` role grants.
120
+ - `power_status` and `power_sleep` need `power:manage`, which only the `admin`
121
+ role grants.
117
122
 
118
123
  In practice:
119
124
 
120
- - an `admin` can do all seven;
125
+ - an `admin` can do all eight;
121
126
  - a `package-approver` can approve packages only;
122
127
  - a `service-manager` can change the service catalog only;
123
128
  - a `model-manager` can change the model catalog only;
@@ -190,7 +195,10 @@ See the [Fetch standard](https://fetch.spec.whatwg.org/#append-a-request-origin-
190
195
 
191
196
  Clients must re-register as public clients (`token_endpoint_auth_method=none`).
192
197
  Only S256 PKCE and exact registered redirect strings are accepted. Redirects
193
- must be HTTPS or loopback HTTP, without credentials or fragments. Registration
198
+ must be HTTPS or loopback HTTP, or, only with `WARDBY_MOBILE_ENABLED=true`,
199
+ exactly the configured mobile redirect (`WARDBY_MOBILE_REDIRECT_URI`, default
200
+ `com.wardby.mobile:/oauth`; see the `mobile-app` help article), without
201
+ credentials or fragments. Registration
194
202
  allows 1-10 redirects and a bounded client name. `AUTH_MAX_CLIENTS` defaults to
195
203
  1000; PostgreSQL serializes capacity checks and shares rate limits across
196
204
  processes. There is no confidential-client support or client secret.
@@ -456,6 +464,15 @@ stale, whichever executor id owns it. Set a fixed id only for a single,
456
464
  long-lived process that should re-drive its own runs at launch rather than
457
465
  after the heartbeat timeout.
458
466
 
467
+ An owner that is stalled but still alive (event-loop or database-pool
468
+ starvation long enough for its heartbeat to go stale) can overlap the attempt
469
+ another process adopted. The first attempt to record a step keeps the run; the
470
+ other stops at that step without writing the run or sending any
471
+ notifications, and DBOS parks it as a duplicate execution. That stopped step's
472
+ model spend is discarded rather than counted against the run, so look for the
473
+ `run_ownership_lost` warning in the server logs (it carries the run id, the
474
+ step, and the discarded usage when known) to see how often this happens.
475
+
459
476
  **New data at rest.** Durable execution checkpoints every step's result into
460
477
  `dbos.operation_outputs`: each turn's assistant text, every tool call's
461
478
  arguments, every tool result in full, and the `load` step's pinned agent
@@ -543,6 +560,23 @@ bound connection pools and concurrent invocations, and review a cancellable
543
560
  database adapter or isolated worker if strict immediate termination is required.
544
561
  Do not claim these per-invocation caps establish a whole-process memory ceiling.
545
562
 
563
+ ## Slack workflow notifications
564
+
565
+ This integration requires Wardby 0.6.0 or later.
566
+
567
+ Optional Slack workflow notifications add no inbound endpoint: wardby only
568
+ ever calls out to Slack's `chat.postMessage`/`chat.update`/`conversations.info`,
569
+ and the app manifest requests no event subscriptions or interactivity, so
570
+ nothing posted in Slack can start or affect a run. What reaches Slack is
571
+ limited to issue keys/titles and their links, pull request numbers and
572
+ links, agent names, review verdicts, fix-round numbers, a failed run's
573
+ reason (its first line, at most 200 characters), and (only when a link opts
574
+ in) the run's spend line — never code, diffs, review bodies, or run output.
575
+ Issue titles are posted regardless of Jira issue security, so link a project
576
+ only to a channel whose members may see every issue in it. The bot token is a provider credential like any other and never
577
+ reaches a sandboxed tool or coding-run worker. See
578
+ [Send workflow updates to Slack](slack-notifications.md).
579
+
546
580
  ## Coding runs on Kubernetes
547
581
 
548
582
  `JOB_LAUNCHER=kubernetes` runs each coding agent in its own pod instead of a
@@ -565,7 +599,7 @@ connects from inside the pod to a destination that must be blocked and requires
565
599
  three consecutive refusals. A cluster that does not enforce policy, or has not
566
600
  yet programmed this pod's rules, never reaches the point of running agent code.
567
601
  The same check runs at startup against a throwaway canary pod, which also
568
- verifies the pod cannot reach DNS, the internet or the cloud metadata endpoint.
602
+ verifies the pod cannot reach DNS, the internet or the cloud metadata endpoints.
569
603
 
570
604
  **RBAC.** The control plane needs a namespace Role (`pods`, `pods/exec`,
571
605
  `pods/log`, `secrets`, `configmaps`, `networkpolicies`, `services`) and a
@@ -579,6 +613,15 @@ has none, so that configuration is development-only and says so. Set
579
613
  `KUBERNETES_RUNTIME_CLASS` to the cluster's sandboxed runtime class in
580
614
  production; the launcher warns loudly when it is unset.
581
615
 
616
+ The `eks` platform profile (Amazon EKS with a gVisor node group) also requires
617
+ the `gvisor` runtime class. The cluster supplies a RuntimeClass `gvisor`
618
+ (handler `runsc`) whose scheduling block targets nodes labelled
619
+ `wardby.dev/sandbox=gvisor` and tainted `sandbox=gvisor:NoSchedule`; coding-pod attestation
620
+ forgives that node selector and toleration and nothing else. The startup canary
621
+ and the native sandbox gate probe the cloud metadata endpoints
622
+ `169.254.169.254`, `169.254.170.23` and `fd00:ec2::23` (EKS Pod Identity agent, IPv4 and IPv6) and
623
+ `fd00:ec2::254` (EC2 IPv6), all on port 80, and require every one to be unreachable.
624
+
582
625
  The `gke-autopilot` platform profile contains narrow admission allowances
583
626
  captured from a real cluster and requires the `gvisor` runtime class. A dry-run
584
627
  capture cannot observe labels added after pod scheduling, so live-run behavior
@@ -592,6 +635,52 @@ Per-run record ConfigMaps currently require operator-managed garbage collection,
592
635
  and the real-cluster suite does not yet cover every Docker containment
593
636
  scenario.
594
637
 
638
+ ## Database authentication
639
+
640
+ By default `DATABASE_URL` carries the database password. On Amazon RDS (or
641
+ Aurora) for PostgreSQL, set `DATABASE_AUTH=rds-iam` to authenticate with IAM
642
+ database authentication instead: the password is a short-lived token signed with
643
+ the workload's AWS credentials (for example EKS Pod Identity), minted when a
644
+ connection opens. Any other value is refused with
645
+ [`database_auth_invalid`](../help/errors/database-auth-invalid.md).
646
+
647
+ Under `rds-iam`:
648
+
649
+ - `DATABASE_URL` must be `postgresql://` (or `postgres://`) with the database
650
+ user and no password, and must contain `sslmode=verify-full` and
651
+ `sslrootcert=<path to the RDS CA bundle>`. The port defaults to 5432.
652
+ - The region comes from `DATABASE_AWS_REGION`, else `AWS_REGION`.
653
+ - The database user must be granted `rds_iam` and the workload's IAM role must
654
+ allow `rds-db:connect` for it.
655
+ - Tokens are valid for 15 minutes and only for opening a connection; Wardby
656
+ reuses one for 10 minutes, and open connections outlive their token.
657
+ - It applies to every app connection: the Prisma clients (server, scheduler,
658
+ coding proxy, native gateway), the DBOS system database
659
+ (`DBOS_SYSTEM_DATABASE_URL`, else `DATABASE_URL`, under the same rules) and
660
+ the viewer's LISTEN connection. The DBOS system pool holds up to 10
661
+ connections; count it in the database's connection budget.
662
+ - URL parameters that are carried over: `application_name`,
663
+ `fallback_application_name`, `options`, `client_encoding`,
664
+ `statement_timeout`, `lock_timeout`, `idle_in_transaction_session_timeout`,
665
+ `query_timeout`. `connection_limit` and `pool_timeout` still size and bound
666
+ the pool, `connect_timeout` (seconds) applies to the DBOS pool, and `schema`
667
+ is accepted with no run-time effect, as in password mode. Every other
668
+ parameter is refused by name, including `sslcert`, `sslkey`, `ssl`, `host` and
669
+ `pgbouncer`; the Cloud SQL `sslcert=` advice does not apply to RDS.
670
+ - A misconfigured setup fails at process start, for every `wardby` command,
671
+ because the database module is loaded at start.
672
+ - `prisma migrate deploy` and `dbos schema` take a URL, not a connection
673
+ config, so they are not covered. Mint a short-lived URL with the helper
674
+ shipped in the migration image and run them within its 15 minutes:
675
+
676
+ ```bash
677
+ DATABASE_URL="$(node scripts/rds-iam-url.mjs)" && export DATABASE_URL && npm run prisma:migrate && npm run dbos:migrate
678
+ ```
679
+
680
+ The helper reads `DATABASE_URL`, `DATABASE_AWS_REGION`/`AWS_REGION` and the
681
+ ambient AWS credentials, and prints a URL containing a credential: never log
682
+ its output. `wardby quickstart` does not support `rds-iam`.
683
+
595
684
  ## Coding package registry
596
685
 
597
686
  Enabling a coding agent's package allowlist widens the trusted proxy's own
@@ -613,6 +702,18 @@ guarantee; and the OSV vulnerability audit fails **closed**
613
702
  operator explicitly sets `REGISTRY_AUDIT_FAIL_OPEN=true` to allow installs
614
703
  through unaudited during an OSV outage.
615
704
 
705
+ ## Native sandbox
706
+
707
+ A native agent set to `nativeExecutionMode=sandbox` runs its turn loop and user
708
+ tools in a single-use container with no credentials, database access, Docker
709
+ socket, or network except the native gateway. The gateway is a trusted
710
+ component: it holds the LLM credentials and integration settings, so give it
711
+ the database and provider settings it needs and nothing else, never the Docker
712
+ socket, and do not publish its port outside the Docker host. Only the server,
713
+ which launches workers, needs Docker access (or, on Kubernetes, permission to
714
+ create pods in the run namespace). See
715
+ [Native sandbox](native-sandbox.md).
716
+
616
717
  ## Images and dependencies
617
718
 
618
719
  ```sh
@@ -0,0 +1,252 @@
1
+ # Send workflow updates to Slack
2
+
3
+ > **Requires Wardby 0.6.0 or later.**
4
+
5
+ Link a Slack channel to a Jira project or to an agent (native or coding), and wardby posts
6
+ that project's or agent's workflow updates there: a card picked up, a pull
7
+ request opened, a review verdict, fix rounds, and the merge — one thread per
8
+ card. This is outbound only: nothing in Slack starts or affects a run, and
9
+ wardby exposes no new inbound endpoint for it.
10
+
11
+ ## What it does
12
+
13
+ ### Events
14
+
15
+ Six kinds of lifecycle event can post to a linked channel:
16
+
17
+ | Kind | Posts when | Content |
18
+ | ----------------- | ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------- |
19
+ | `issue_picked_up` | A Jira event starts a run on a linked issue | Issue key, title, and link; agent name; trigger kind |
20
+ | `run_failed` | A top-level run ends `failed`, `refused`, `budget_exhausted`, `cancelled`, or `lost` | Agent name, status, a short first-line reason (never the full error) |
21
+ | `pr_opened` | A coding run opens a pull request | Repository#number and link, the issue it is for, any Jira status move |
22
+ | `review_posted` | wardby's own review check posts a verdict | `APPROVE` / `CHANGES_REQUESTED` / `COMMENT`, the reviewer agent, the PR link |
23
+ | `review_fix` | An automatic [fix round](../help/review-fix-rounds.md) starts or hits the cap | Round number of the cap, started or capped |
24
+ | `pr_closed` | A pull request is merged or closed | Merged or closed, any Jira status move |
25
+
26
+ A run finishing successfully is not its own event — on the workflow it shows
27
+ up as `pr_opened` or `review_posted` already. Child coding runs started by a
28
+ parent surface through the parent's own `run_failed`, not their own.
29
+
30
+ Some runs do not post `run_failed` at all:
31
+
32
+ - a coding agent's run triggered directly (rather than as a child of a
33
+ native agent's run),
34
+ - a review verdict or failure from a coding agent acting as the reviewer, and
35
+ - runs started from the `wardby run` CLI command.
36
+
37
+ A pull request linked to several issues posts `pr_opened` and `pr_closed`
38
+ only to the first linked issue's thread.
39
+
40
+ ### Threads
41
+
42
+ Each channel gets one thread per card: one per Jira issue (when the event has
43
+ one) or one per pull request (when it doesn't). The first event for a card
44
+ posts a parent message naming the issue or pull request; every later event
45
+ for the same card is a reply in that thread, and the parent is kept updated
46
+ with a short status line. The statuses are:
47
+
48
+ | Status | Set by |
49
+ | ---------------------- | ---------------------------------------------------------------- |
50
+ | `picked up` | `issue_picked_up` on a new thread, or after `merged ✅`/`closed` |
51
+ | `PR open` | `pr_opened` |
52
+ | `changes requested` | a `CHANGES_REQUESTED` review |
53
+ | `approved` | an `APPROVE` review |
54
+ | `fixing` | a fix round starting (the round number is in the thread reply) |
55
+ | `fix rounds exhausted` | fix rounds reaching the cap with changes still requested |
56
+ | `merged ✅` | the pull request merged |
57
+ | `closed` | the pull request closed without merging |
58
+ | `failed ❌` | `run_failed` |
59
+
60
+ A `COMMENT` review leaves the status as it was. `merged ✅` and `closed` stick:
61
+ a late review, fix round, failure, or repeated close does not change them.
62
+ Only a new start does — the card picked up again, or a new pull request
63
+ opened for it — which sets `picked up` or `PR open` again.
64
+
65
+ Most events only post as a thread reply. A merge and a top-level run failure
66
+ also post to the channel itself, so they are visible without opening the
67
+ thread.
68
+
69
+ ### What is never sent
70
+
71
+ wardby never posts code, diffs, review bodies, or run output to Slack. Error
72
+ messages shown in Slack are a short first line only (at most 200 characters),
73
+ never a full error or stack trace.
74
+
75
+ ## 1. Create the Slack app
76
+
77
+ Use the manifest in [`deploy/slack/app-manifest.yaml`](../deploy/slack/app-manifest.yaml):
78
+
79
+ 1. Open [api.slack.com/apps](https://api.slack.com/apps), choose **Create New
80
+ App → From a manifest**, pick your workspace, and paste the manifest.
81
+ 2. On **OAuth & Permissions**, click **Install to Workspace** and approve the
82
+ requested scopes.
83
+ 3. Copy the **Bot User OAuth Token** (starts `xoxb-`).
84
+
85
+ See [`deploy/slack/README.md`](../deploy/slack/README.md) for the full
86
+ walkthrough, including the optional per-agent display-name scope.
87
+
88
+ ## 2. Configure wardby
89
+
90
+ | Variable | Value |
91
+ | --------------------------- | ------------------------------------------------------------------------------------------------- |
92
+ | `WARDBY_SLACK_BOT_TOKEN` | The bot token from step 1 (`xoxb-…`). Unset = Slack notifications are disabled. |
93
+ | `WARDBY_SLACK_API_BASE_URL` | Optional. Overrides the Slack Web API base URL (`https://slack.com/api`); must be `https`. |
94
+ | `WARDBY_SLACK_CUSTOMIZE` | Optional, `true` or `false` (default `false`). Needs `chat:write.customize` in the installed app. |
95
+
96
+ Store `WARDBY_SLACK_BOT_TOKEN` in your secrets backend the same way you store
97
+ other provider credentials (`GITHUB_APP_PRIVATE_KEY`, `WARDBY_JIRA_API_TOKEN`)
98
+ — never in a committed file. On the GKE reference deployment, see
99
+ [Getting started on GKE](getting-started-gke.md). Restart wardby after setting
100
+ it. The startup log line `chat notifications acting as` names the Slack team
101
+ and bot user id wardby authenticated as. If that check fails instead, wardby
102
+ only logs an error and still starts: it does not fail to boot, and delivery
103
+ is not paused up front. Delivery pauses when the first actual delivery fails
104
+ authentication (see [Failure modes](#failure-modes)).
105
+
106
+ With `WARDBY_SLACK_CUSTOMIZE=true`, a message about an event that names an
107
+ agent (`issue_picked_up`, `run_failed`, `review_posted`) is posted under that
108
+ agent's name; every other message, and every message when the option is off,
109
+ posts as `wardby`. A thread's parent message uses the name of the event that
110
+ started the thread. wardby sets no icon.
111
+
112
+ Without `WARDBY_SLACK_BOT_TOKEN`, `link_notification_channel` and
113
+ `test_notification_channel` are refused and the dispatcher does not start;
114
+ `unlink_notification_channel` and `list_notification_channels` still work, so
115
+ you can clean up old links. See
116
+ [`errors/slack-not-configured`](../help/errors/slack-not-configured.md).
117
+
118
+ ## Scopes and why
119
+
120
+ | Scope | Required | Used for |
121
+ | ---------------------- | ----------- | --------------------------------------------------------------------------------------------------------- |
122
+ | `chat:write` | Yes | Posting and updating the bot's own messages, including threaded replies |
123
+ | `chat:write.public` | Recommended | Posting to public channels without inviting the bot first |
124
+ | `channels:read` | Recommended | Validating a channel id and recording its name when linking |
125
+ | `groups:read` | Recommended | The same, for private channels |
126
+ | `chat:write.customize` | Optional | Posting under the name of the agent an event is about instead of `wardby` (`WARDBY_SLACK_CUSTOMIZE=true`) |
127
+
128
+ Without `channels:read`/`groups:read`, linking still accepts a raw channel id
129
+ but skips validating it. Any other authentication error while linking (an
130
+ invalid or revoked token) refuses the link; see
131
+ [`errors/slack-auth-failed`](../help/errors/slack-auth-failed.md). Private channels always need `/invite @wardby` (or
132
+ whatever you named the app) regardless of scopes — Slack never lets a bot see
133
+ or post to a private channel it hasn't been invited to. `chat.postMessage` is
134
+ rate-limited to about one message per second per channel; wardby's dispatcher
135
+ paces its own posts to stay under that.
136
+
137
+ ## Link channels
138
+
139
+ Use the `link_notification_channel` MCP tool. It needs `agents:admin` with
140
+ the admin role, the same trust model as `link_issue_project`: wardby cannot
141
+ verify a caller's own Slack workspace access, so an administrator approves
142
+ every link.
143
+
144
+ Link a channel to a Jira project:
145
+
146
+ ```json
147
+ {
148
+ "channel": "C0123456789",
149
+ "projectKey": "PAY",
150
+ "issueProvider": "jira",
151
+ "events": ["issue_picked_up", "pr_opened", "review_posted", "pr_closed"],
152
+ "includeCost": true
153
+ }
154
+ ```
155
+
156
+ Link a channel to an agent instead (every event for that agent's runs, no
157
+ filter):
158
+
159
+ ```json
160
+ {
161
+ "channel": "C0123456789",
162
+ "agentId": "<agent id>"
163
+ }
164
+ ```
165
+
166
+ - Give exactly one of `projectKey` (with optional `issueProvider`, default
167
+ `jira`) or `agentId`.
168
+ - `channel` is the Slack channel id — `C…` for a public channel, `G…` for a
169
+ private one — never a `#name`. Find it in the channel's details in Slack
170
+ (**View channel details**, near the bottom). Passing a `#name` is refused.
171
+ - `events` narrows which of the six kinds post to this link; omit it (or pass
172
+ an empty list) for all six.
173
+ - `includeCost` appends the run's spend line to messages for this link.
174
+ - Invite the bot to any private channel before linking it:
175
+ `/invite @wardby` in that channel.
176
+ - Re-linking the same channel and subject replaces `events` and
177
+ `includeCost` and clears any previously recorded delivery error — send the
178
+ full desired state each time.
179
+
180
+ Then confirm delivery works before relying on it:
181
+
182
+ ```json
183
+ { "id": "<link id from link_notification_channel>" }
184
+ ```
185
+
186
+ `test_notification_channel` posts "✅ wardby is connected to this channel." —
187
+ if the bot can't write there, you get the error immediately instead of
188
+ finding out when the first real event is dropped. A successful test also
189
+ clears the link's `lastError`.
190
+
191
+ `list_notification_channels` shows every link's `lastError` and its pending
192
+ and failed delivery counts (counted per channel: two links to the same
193
+ channel show the same counts); filter by `projectKey`, `agentId`, or `channel`.
194
+ Listing your own agent's links needs read access to that agent; listing
195
+ everything (or filtering by `projectKey`) needs `agents:admin` with the admin
196
+ role. `unlink_notification_channel` removes a link by `id`.
197
+
198
+ ## Failure modes
199
+
200
+ - **Channel not found, bot not in channel, or channel archived.** That
201
+ channel's pending deliveries fail immediately and are never retried, and
202
+ every link to it shows the error in `lastError`. Invite the bot
203
+ (`/invite @wardby`) or otherwise fix the channel in Slack. New events
204
+ deliver as soon as the bot can post there again; the deliveries that
205
+ already failed are not resent. Re-linking the channel (or a successful
206
+ `test_notification_channel`) clears `lastError`. See
207
+ [`errors/slack-channel-unreachable`](../help/errors/slack-channel-unreachable.md).
208
+ - **Invalid or revoked token.** Delivery pauses for every linked channel (no
209
+ deliveries are lost — they stay pending), and wardby re-checks the token
210
+ every five minutes with Slack's `auth.test`; it resumes automatically once
211
+ the check succeeds. See
212
+ [`errors/slack-auth-failed`](../help/errors/slack-auth-failed.md).
213
+ - **A missing scope.** Delivery pauses the same way, but `auth.test` needs no
214
+ scope, so the five-minute check succeeds, the next delivery fails again,
215
+ and delivery pauses again. It does not fix itself: add the scope to the app
216
+ and reinstall it to the workspace (and if Slack issues a new token, set it
217
+ and restart wardby). Pending deliveries are kept and sent once it works.
218
+ - **Rate limits.** wardby paces its own posts to about one per second per
219
+ channel; if Slack still responds with a rate-limit error, that delivery is
220
+ retried after the delay Slack specifies, with no attempt counted against
221
+ the retry limit below.
222
+ - **Transient errors** (network issues, Slack 5xx responses) are retried with
223
+ increasing back-off, up to 10 attempts, before the delivery is marked
224
+ failed.
225
+ - **Events while Slack isn't configured.** An event recorded before
226
+ `WARDBY_SLACK_BOT_TOKEN` is set is not queued and is not delivered once you
227
+ configure it — only events recorded after Slack notifications are enabled
228
+ reach Slack.
229
+ - **Duplicates.** Delivery is at least once: if wardby crashes or loses its
230
+ database connection right after Slack accepts a message, that message can
231
+ be posted again. A rare duplicate thread reply is possible.
232
+ - **Retention.** Delivery records are kept for 30 days and then pruned.
233
+
234
+ ## Security
235
+
236
+ Phase 1 is outbound only: wardby requests no event subscriptions and no
237
+ interactivity in the manifest, so there is no new inbound endpoint and
238
+ nothing posted in Slack can start or affect a run.
239
+
240
+ What leaves to Slack: issue keys, titles, and their links; pull request
241
+ numbers and links; agent names; review verdicts; fix-round numbers; a failed
242
+ run's reason (its first line, at most 200 characters); and, only when a
243
+ link's `includeCost` is on, the run's spend line. wardby never posts code,
244
+ diffs, review bodies, or run output, and an error message shown in Slack is a
245
+ short first line only, never a full error or stack trace.
246
+
247
+ Issue titles go to the linked channel regardless of Jira issue security: an
248
+ issue restricted by a Jira security level still has its key and title posted.
249
+ Link a project only to a channel whose members may see every issue in it.
250
+
251
+ The bot token stays on the wardby server; agents, sandboxed tools, and
252
+ coding-run workers never see it.