@wascartech/devbot 0.0.0-stage → 2.1.1

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 (376) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +638 -2
  3. package/dist/access-grant-store.js +99 -0
  4. package/dist/access-grant-store.js.map +1 -0
  5. package/dist/access-resolve.js +11 -0
  6. package/dist/access-resolve.js.map +1 -0
  7. package/dist/access-rule-store.js +99 -0
  8. package/dist/access-rule-store.js.map +1 -0
  9. package/dist/admin/access-routes.js +73 -0
  10. package/dist/admin/access-routes.js.map +1 -0
  11. package/dist/admin/access-rule-routes.js +107 -0
  12. package/dist/admin/access-rule-routes.js.map +1 -0
  13. package/dist/admin/custom-repos-routes.js +93 -0
  14. package/dist/admin/custom-repos-routes.js.map +1 -0
  15. package/dist/admin/env-routes.js +74 -0
  16. package/dist/admin/env-routes.js.map +1 -0
  17. package/dist/admin/global-settings-routes.js +254 -0
  18. package/dist/admin/global-settings-routes.js.map +1 -0
  19. package/dist/admin/mcp-cleanup.js +12 -0
  20. package/dist/admin/mcp-cleanup.js.map +1 -0
  21. package/dist/admin/mcp-routes.js +169 -0
  22. package/dist/admin/mcp-routes.js.map +1 -0
  23. package/dist/admin/query-params.js +80 -0
  24. package/dist/admin/query-params.js.map +1 -0
  25. package/dist/admin/routes.js +150 -0
  26. package/dist/admin/routes.js.map +1 -0
  27. package/dist/admin/run-history-routes.js +44 -0
  28. package/dist/admin/run-history-routes.js.map +1 -0
  29. package/dist/admin/run-routes.js +99 -0
  30. package/dist/admin/run-routes.js.map +1 -0
  31. package/dist/admin/settings-routes.js +119 -0
  32. package/dist/admin/settings-routes.js.map +1 -0
  33. package/dist/admin/stats-routes.js +51 -0
  34. package/dist/admin/stats-routes.js.map +1 -0
  35. package/dist/admin/task-routes.js +213 -0
  36. package/dist/admin/task-routes.js.map +1 -0
  37. package/dist/admin/test-routes.js +38 -0
  38. package/dist/admin/test-routes.js.map +1 -0
  39. package/dist/admin/volume-routes.js +82 -0
  40. package/dist/admin/volume-routes.js.map +1 -0
  41. package/dist/admin/webhook-routes.js +174 -0
  42. package/dist/admin/webhook-routes.js.map +1 -0
  43. package/dist/agents.js +48 -0
  44. package/dist/agents.js.map +1 -0
  45. package/dist/assignee-value.js +6 -0
  46. package/dist/assignee-value.js.map +1 -0
  47. package/dist/attachments.js +76 -0
  48. package/dist/attachments.js.map +1 -0
  49. package/dist/auto-commands.js +88 -0
  50. package/dist/auto-commands.js.map +1 -0
  51. package/dist/auto-features.js +32 -0
  52. package/dist/auto-features.js.map +1 -0
  53. package/dist/base-branch-store.js +40 -0
  54. package/dist/base-branch-store.js.map +1 -0
  55. package/dist/base-branches.js +9 -0
  56. package/dist/base-branches.js.map +1 -0
  57. package/dist/build-workflow.js +116 -0
  58. package/dist/build-workflow.js.map +1 -0
  59. package/dist/change-request-lifecycle.js +16 -0
  60. package/dist/change-request-lifecycle.js.map +1 -0
  61. package/dist/change-request-store.js +72 -0
  62. package/dist/change-request-store.js.map +1 -0
  63. package/dist/ci-failure.js +80 -0
  64. package/dist/ci-failure.js.map +1 -0
  65. package/dist/cli.js +3 -0
  66. package/dist/cli.js.map +1 -0
  67. package/dist/config.js +17 -0
  68. package/dist/config.js.map +1 -0
  69. package/dist/conflict-fix.js +178 -0
  70. package/dist/conflict-fix.js.map +1 -0
  71. package/dist/cookie.js +70 -0
  72. package/dist/cookie.js.map +1 -0
  73. package/dist/crypto-util.js +40 -0
  74. package/dist/crypto-util.js.map +1 -0
  75. package/dist/custom-repos-store.js +90 -0
  76. package/dist/custom-repos-store.js.map +1 -0
  77. package/dist/custom-repos-sync.js +118 -0
  78. package/dist/custom-repos-sync.js.map +1 -0
  79. package/dist/db.js +12 -0
  80. package/dist/db.js.map +1 -0
  81. package/dist/devbot-scripts.js +18 -0
  82. package/dist/devbot-scripts.js.map +1 -0
  83. package/dist/devcontainer.js +150 -0
  84. package/dist/devcontainer.js.map +1 -0
  85. package/dist/env-config-store.js +132 -0
  86. package/dist/env-config-store.js.map +1 -0
  87. package/dist/error-log-store.js +193 -0
  88. package/dist/error-log-store.js.map +1 -0
  89. package/dist/git.js +605 -0
  90. package/dist/git.js.map +1 -0
  91. package/dist/global-queue.js +127 -0
  92. package/dist/global-queue.js.map +1 -0
  93. package/dist/global-settings-store.js +307 -0
  94. package/dist/global-settings-store.js.map +1 -0
  95. package/dist/help.js +41 -0
  96. package/dist/help.js.map +1 -0
  97. package/dist/http-csp.js +15 -0
  98. package/dist/http-csp.js.map +1 -0
  99. package/dist/http-util.js +40 -0
  100. package/dist/http-util.js.map +1 -0
  101. package/dist/idempotency.js +50 -0
  102. package/dist/idempotency.js.map +1 -0
  103. package/dist/lifecycle.js +234 -0
  104. package/dist/lifecycle.js.map +1 -0
  105. package/dist/logger.js +33 -0
  106. package/dist/logger.js.map +1 -0
  107. package/dist/lsp-servers.js +81 -0
  108. package/dist/lsp-servers.js.map +1 -0
  109. package/dist/mcp/auth.js +62 -0
  110. package/dist/mcp/auth.js.map +1 -0
  111. package/dist/mcp/effective-mcp.js +42 -0
  112. package/dist/mcp/effective-mcp.js.map +1 -0
  113. package/dist/mcp/oauth-refresh.js +138 -0
  114. package/dist/mcp/oauth-refresh.js.map +1 -0
  115. package/dist/mcp/peer-sync.js +109 -0
  116. package/dist/mcp/peer-sync.js.map +1 -0
  117. package/dist/mcp/registry.js +54 -0
  118. package/dist/mcp/registry.js.map +1 -0
  119. package/dist/mcp/runner-bridge.js +93 -0
  120. package/dist/mcp/runner-bridge.js.map +1 -0
  121. package/dist/mcp/server.js +173 -0
  122. package/dist/mcp/server.js.map +1 -0
  123. package/dist/mcp/tools/_helpers.js +88 -0
  124. package/dist/mcp/tools/_helpers.js.map +1 -0
  125. package/dist/mcp/tools/attachments.js +117 -0
  126. package/dist/mcp/tools/attachments.js.map +1 -0
  127. package/dist/mcp/tools/cicd.js +105 -0
  128. package/dist/mcp/tools/cicd.js.map +1 -0
  129. package/dist/mcp/tools/discovery.js +34 -0
  130. package/dist/mcp/tools/discovery.js.map +1 -0
  131. package/dist/mcp/tools/issues.js +56 -0
  132. package/dist/mcp/tools/issues.js.map +1 -0
  133. package/dist/mcp/tools/merge_requests.js +67 -0
  134. package/dist/mcp/tools/merge_requests.js.map +1 -0
  135. package/dist/mcp/tools/metadata.js +127 -0
  136. package/dist/mcp/tools/metadata.js.map +1 -0
  137. package/dist/mcp/tools/peer_sync.js +43 -0
  138. package/dist/mcp/tools/peer_sync.js.map +1 -0
  139. package/dist/mcp/tools/repository.js +178 -0
  140. package/dist/mcp/tools/repository.js.map +1 -0
  141. package/dist/mcp/tools/work_tracking.js +125 -0
  142. package/dist/mcp/tools/work_tracking.js.map +1 -0
  143. package/dist/mcp/tools/workitems.js +30 -0
  144. package/dist/mcp/tools/workitems.js.map +1 -0
  145. package/dist/mcp/volume-files.js +187 -0
  146. package/dist/mcp/volume-files.js.map +1 -0
  147. package/dist/mcp-auth-store.js +134 -0
  148. package/dist/mcp-auth-store.js.map +1 -0
  149. package/dist/mcp-config-store.js +83 -0
  150. package/dist/mcp-config-store.js.map +1 -0
  151. package/dist/mention.js +512 -0
  152. package/dist/mention.js.map +1 -0
  153. package/dist/migrate.js +438 -0
  154. package/dist/migrate.js.map +1 -0
  155. package/dist/mr-assignee.js +71 -0
  156. package/dist/mr-assignee.js.map +1 -0
  157. package/dist/mr-content.js +90 -0
  158. package/dist/mr-content.js.map +1 -0
  159. package/dist/oauth-routes.js +54 -0
  160. package/dist/oauth-routes.js.map +1 -0
  161. package/dist/onboarding-allowlist.js +32 -0
  162. package/dist/onboarding-allowlist.js.map +1 -0
  163. package/dist/opencode.js +291 -0
  164. package/dist/opencode.js.map +1 -0
  165. package/dist/outbound-webhook-store.js +229 -0
  166. package/dist/outbound-webhook-store.js.map +1 -0
  167. package/dist/outbound-webhook.js +314 -0
  168. package/dist/outbound-webhook.js.map +1 -0
  169. package/dist/path-sandbox.js +200 -0
  170. package/dist/path-sandbox.js.map +1 -0
  171. package/dist/platform/git-auth.js +34 -0
  172. package/dist/platform/git-auth.js.map +1 -0
  173. package/dist/platform/gitealike/attachments.js +62 -0
  174. package/dist/platform/gitealike/attachments.js.map +1 -0
  175. package/dist/platform/gitealike/base.js +935 -0
  176. package/dist/platform/gitealike/base.js.map +1 -0
  177. package/dist/platform/gitealike/forgejo.js +16 -0
  178. package/dist/platform/gitealike/forgejo.js.map +1 -0
  179. package/dist/platform/gitealike/gitea.js +16 -0
  180. package/dist/platform/gitealike/gitea.js.map +1 -0
  181. package/dist/platform/gitealike/http.js +152 -0
  182. package/dist/platform/gitealike/http.js.map +1 -0
  183. package/dist/platform/gitealike/schemas.js +284 -0
  184. package/dist/platform/gitealike/schemas.js.map +1 -0
  185. package/dist/platform/github/attachments.js +52 -0
  186. package/dist/platform/github/attachments.js.map +1 -0
  187. package/dist/platform/github/http.js +153 -0
  188. package/dist/platform/github/http.js.map +1 -0
  189. package/dist/platform/github/index.js +936 -0
  190. package/dist/platform/github/index.js.map +1 -0
  191. package/dist/platform/github/schemas.js +308 -0
  192. package/dist/platform/github/schemas.js.map +1 -0
  193. package/dist/platform/github/zip.js +85 -0
  194. package/dist/platform/github/zip.js.map +1 -0
  195. package/dist/platform/gitlab/admin.js +105 -0
  196. package/dist/platform/gitlab/admin.js.map +1 -0
  197. package/dist/platform/gitlab/api.js +229 -0
  198. package/dist/platform/gitlab/api.js.map +1 -0
  199. package/dist/platform/gitlab/attachments.js +79 -0
  200. package/dist/platform/gitlab/attachments.js.map +1 -0
  201. package/dist/platform/gitlab/http.js +165 -0
  202. package/dist/platform/gitlab/http.js.map +1 -0
  203. package/dist/platform/gitlab/index.js +630 -0
  204. package/dist/platform/gitlab/index.js.map +1 -0
  205. package/dist/platform/gitlab/oauth.js +58 -0
  206. package/dist/platform/gitlab/oauth.js.map +1 -0
  207. package/dist/platform/gitlab/read.js +182 -0
  208. package/dist/platform/gitlab/read.js.map +1 -0
  209. package/dist/platform/gitlab/schemas-read.js +274 -0
  210. package/dist/platform/gitlab/schemas-read.js.map +1 -0
  211. package/dist/platform/gitlab/schemas.js +251 -0
  212. package/dist/platform/gitlab/schemas.js.map +1 -0
  213. package/dist/platform/gitlab/signature.js +52 -0
  214. package/dist/platform/gitlab/signature.js.map +1 -0
  215. package/dist/platform/index.js +38 -0
  216. package/dist/platform/index.js.map +1 -0
  217. package/dist/platform/port.js +26 -0
  218. package/dist/platform/port.js.map +1 -0
  219. package/dist/platform/types.js +80 -0
  220. package/dist/platform/types.js.map +1 -0
  221. package/dist/podman.js +119 -0
  222. package/dist/podman.js.map +1 -0
  223. package/dist/project-sync.js +69 -0
  224. package/dist/project-sync.js.map +1 -0
  225. package/dist/prompt.js +47 -0
  226. package/dist/prompt.js.map +1 -0
  227. package/dist/queue-store.js +236 -0
  228. package/dist/queue-store.js.map +1 -0
  229. package/dist/queue.js +129 -0
  230. package/dist/queue.js.map +1 -0
  231. package/dist/redact.js +23 -0
  232. package/dist/redact.js.map +1 -0
  233. package/dist/run-files.js +297 -0
  234. package/dist/run-files.js.map +1 -0
  235. package/dist/run-filters.js +54 -0
  236. package/dist/run-filters.js.map +1 -0
  237. package/dist/run-history-store.js +229 -0
  238. package/dist/run-history-store.js.map +1 -0
  239. package/dist/run-log-sink.js +270 -0
  240. package/dist/run-log-sink.js.map +1 -0
  241. package/dist/run-log.js +97 -0
  242. package/dist/run-log.js.map +1 -0
  243. package/dist/run-usage.js +29 -0
  244. package/dist/run-usage.js.map +1 -0
  245. package/dist/run-view.js +112 -0
  246. package/dist/run-view.js.map +1 -0
  247. package/dist/runner.js +1094 -0
  248. package/dist/runner.js.map +1 -0
  249. package/dist/runtime-apply.js +26 -0
  250. package/dist/runtime-apply.js.map +1 -0
  251. package/dist/runtime-settings.js +71 -0
  252. package/dist/runtime-settings.js.map +1 -0
  253. package/dist/runtime-state.js +19 -0
  254. package/dist/runtime-state.js.map +1 -0
  255. package/dist/server.js +119 -0
  256. package/dist/server.js.map +1 -0
  257. package/dist/settings-store.js +320 -0
  258. package/dist/settings-store.js.map +1 -0
  259. package/dist/status.js +121 -0
  260. package/dist/status.js.map +1 -0
  261. package/dist/stop.js +56 -0
  262. package/dist/stop.js.map +1 -0
  263. package/dist/sweeps.js +87 -0
  264. package/dist/sweeps.js.map +1 -0
  265. package/dist/task-log.js +279 -0
  266. package/dist/task-log.js.map +1 -0
  267. package/dist/task-view.js +62 -0
  268. package/dist/task-view.js.map +1 -0
  269. package/dist/token-store.js +68 -0
  270. package/dist/token-store.js.map +1 -0
  271. package/dist/types/access.js +74 -0
  272. package/dist/types/access.js.map +1 -0
  273. package/dist/types/custom-repos.js +28 -0
  274. package/dist/types/custom-repos.js.map +1 -0
  275. package/dist/types/env-config.js +25 -0
  276. package/dist/types/env-config.js.map +1 -0
  277. package/dist/types/env.js +190 -0
  278. package/dist/types/env.js.map +1 -0
  279. package/dist/types/global-settings.js +178 -0
  280. package/dist/types/global-settings.js.map +1 -0
  281. package/dist/types/lsp-servers.js +145 -0
  282. package/dist/types/lsp-servers.js.map +1 -0
  283. package/dist/types/mcp-config.js +77 -0
  284. package/dist/types/mcp-config.js.map +1 -0
  285. package/dist/types/opencode.js +59 -0
  286. package/dist/types/opencode.js.map +1 -0
  287. package/dist/types/outbound-webhook.js +56 -0
  288. package/dist/types/outbound-webhook.js.map +1 -0
  289. package/dist/types/project-settings.js +114 -0
  290. package/dist/types/project-settings.js.map +1 -0
  291. package/dist/types/provider-registry.js +37 -0
  292. package/dist/types/provider-registry.js.map +1 -0
  293. package/dist/types/runtime-settings.js +78 -0
  294. package/dist/types/runtime-settings.js.map +1 -0
  295. package/dist/usage-stats.js +159 -0
  296. package/dist/usage-stats.js.map +1 -0
  297. package/dist/version.js +19 -0
  298. package/dist/version.js.map +1 -0
  299. package/dist/volume-gc.js +193 -0
  300. package/dist/volume-gc.js.map +1 -0
  301. package/dist/volume-manage.js +191 -0
  302. package/dist/volume-manage.js.map +1 -0
  303. package/dist/volume-store.js +122 -0
  304. package/dist/volume-store.js.map +1 -0
  305. package/dist/webhook.js +1106 -0
  306. package/dist/webhook.js.map +1 -0
  307. package/dist/work-item-auto-store.js +75 -0
  308. package/dist/work-item-auto-store.js.map +1 -0
  309. package/dist/work-item-branch-store.js +37 -0
  310. package/dist/work-item-branch-store.js.map +1 -0
  311. package/migrations/0001_initial.sql +59 -0
  312. package/migrations/0002_queue_status.sql +15 -0
  313. package/migrations/0003_work_item_base_branch.sql +14 -0
  314. package/migrations/0004_project_settings.sql +15 -0
  315. package/migrations/0005_global_settings.sql +34 -0
  316. package/migrations/0006_model_variants.sql +8 -0
  317. package/migrations/0007_container_error_logs.sql +21 -0
  318. package/migrations/0008_project_access_grants.sql +16 -0
  319. package/migrations/0009_drop_imported_legacy.sql +4 -0
  320. package/migrations/0010_container_error_log_model.sql +6 -0
  321. package/migrations/0011_container_error_log_title.sql +5 -0
  322. package/migrations/0012_pending_task_cancel.sql +6 -0
  323. package/migrations/0013_builder_image.sql +6 -0
  324. package/migrations/0014_build_workflow.sql +7 -0
  325. package/migrations/0015_access_rules.sql +24 -0
  326. package/migrations/0016_trigger_policy.sql +17 -0
  327. package/migrations/0017_attachment_upload.sql +8 -0
  328. package/migrations/0018_work_item_branch.sql +11 -0
  329. package/migrations/0019_auto_push_mr.sql +18 -0
  330. package/migrations/0020_outbound_webhooks.sql +47 -0
  331. package/migrations/0021_runtime_settings.sql +12 -0
  332. package/migrations/0022_auto_resolve_conflicts.sql +17 -0
  333. package/migrations/0023_ci_fail_auto_report.sql +27 -0
  334. package/migrations/0024_work_item_auto_override.sql +22 -0
  335. package/migrations/0025_run_history.sql +37 -0
  336. package/migrations/0026_run_history_task_seq.sql +6 -0
  337. package/migrations/0027_custom_repos.sql +11 -0
  338. package/migrations/0028_run_usage.sql +14 -0
  339. package/migrations/0029_drop_ocr_langs.sql +6 -0
  340. package/migrations/0030_mr_assignee.sql +9 -0
  341. package/migrations/0031_lsp_servers.sql +14 -0
  342. package/opencode-config/managed/devbot-agent-policy.md +61 -0
  343. package/opencode-config/managed/opencode.json +77 -0
  344. package/opencode-config/opencode.json +211 -0
  345. package/opencode-config/plugins/devbot-path-guard.js +224 -0
  346. package/package.json +158 -4
  347. package/public/assets/DashboardSidebarCollapse-rIuzCmVm.js +1 -0
  348. package/public/assets/DashboardToolbar-DFCUqZ4Z.js +1 -0
  349. package/public/assets/ErrorLogModal.vue_vue_type_script_setup_true_lang-BCyNIf1E.js +1 -0
  350. package/public/assets/ErrorLogsPage-DyYK2Rop.js +1 -0
  351. package/public/assets/LogSlideover.vue_vue_type_script_setup_true_lang-33xie7TE.js +1 -0
  352. package/public/assets/OverviewPage-CFfa0uwg.js +1 -0
  353. package/public/assets/PageGrid-CBROIU87.js +1 -0
  354. package/public/assets/PeriodRangePicker.vue_vue_type_script_setup_true_lang-DiFUNem7.js +1 -0
  355. package/public/assets/ProjectDetailPage-CreyvUit.js +1 -0
  356. package/public/assets/ProjectsPage-CFx8-elJ.js +1 -0
  357. package/public/assets/RunDetailSlideover.vue_vue_type_script_setup_true_lang-DopYYmCT.js +1 -0
  358. package/public/assets/RunsPage-CRnnXU4P.js +1 -0
  359. package/public/assets/Select-Bvx32Diz.js +1 -0
  360. package/public/assets/SelectMenu-BjMxc4VB.js +1 -0
  361. package/public/assets/SettingsPage-Bb6LM3wO.js +60 -0
  362. package/public/assets/TimeCell.vue_vue_type_script_setup_true_lang-DW_UB0Fu.js +1 -0
  363. package/public/assets/UsagePage-BLMDEsv-.js +332 -0
  364. package/public/assets/UsagePage-DodEeAjB.css +1 -0
  365. package/public/assets/VolumesPage-CxcLc3L2.js +1 -0
  366. package/public/assets/WebhookConfigPanel.vue_vue_type_script_setup_true_lang-B2V2GF6b.js +1 -0
  367. package/public/assets/WorkItemCell.vue_vue_type_script_setup_true_lang-BQn6vTjd.js +1 -0
  368. package/public/assets/index-BMbMibyb.js +4 -0
  369. package/public/assets/index-C5RBBrPj.js +30 -0
  370. package/public/assets/index-CgX29UgC.css +1 -0
  371. package/public/assets/usage-format-jsb31_O8.js +1 -0
  372. package/public/assets/useManagedProjects-8rtjRqVJ.js +1 -0
  373. package/public/assets/useRouteTab-DfwrcMic.js +1 -0
  374. package/public/favicon.ico +0 -0
  375. package/public/favicon.png +0 -0
  376. package/public/index.html +15 -0
@@ -0,0 +1,54 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { logReq } from "./http-util.js";
3
+ import { config } from "./config.js";
4
+ import { getPlatform } from "./platform/index.js";
5
+ import { isOnboardingAllowed } from "./onboarding-allowlist.js";
6
+ import { signCookie, cookieOptions, SESSION_COOKIE, STATE_COOKIE, } from "./cookie.js";
7
+ export function mountOauthRoutes(app) {
8
+ const platform = getPlatform();
9
+ app.get("/oauth/start", (_req, res) => {
10
+ const state = randomBytes(16).toString("hex");
11
+ res.cookie(STATE_COOKIE, state, cookieOptions(600));
12
+ return res.redirect(302, platform.onboarding.authorizeUrl(state));
13
+ });
14
+ app.get("/oauth/callback", async (req, res) => {
15
+ const code = req.query.code;
16
+ const state = req.query.state;
17
+ const cookies = req.cookies;
18
+ const expectedState = cookies?.[STATE_COOKIE];
19
+ if (!code || !state || state !== expectedState) {
20
+ logReq(req, "warn", "oauth invalid state", {
21
+ hasCode: !!code,
22
+ stateType: typeof state,
23
+ hasExpectedState: !!expectedState,
24
+ match: typeof state === "string" && state === expectedState,
25
+ cookieHeaderPresent: !!req.headers.cookie,
26
+ cookieKeys: Object.keys(req.cookies ?? {}),
27
+ });
28
+ return res.status(403).send("invalid state");
29
+ }
30
+ // ponytail: clear state cookie immediately after validation — single-use
31
+ // CSRF token, consumed whether the callback succeeds or fails.
32
+ res.clearCookie(STATE_COOKIE, { path: "/" });
33
+ try {
34
+ const { accessToken } = await platform.onboarding.exchangeCode(String(code));
35
+ const user = await platform.onboarding.currentUser(accessToken);
36
+ // The allowlist is the single authorization gate for all drivers —
37
+ // per-forge admin status is no longer checked. Fails closed when
38
+ // ONBOARDING_USERS is empty.
39
+ if (!isOnboardingAllowed(user.username, config.ONBOARDING_USERS)) {
40
+ logReq(req, "warn", "oauth user not allowlisted", { userId: user.id, username: user.username });
41
+ return res.status(403).send("user not authorized to onboard");
42
+ }
43
+ const exp = Math.floor(Date.now() / 1000) + 3600;
44
+ const cookie = signCookie({ accessToken, userId: user.id, username: user.username, exp });
45
+ res.cookie(SESSION_COOKIE, cookie, cookieOptions(3600));
46
+ return res.redirect(302, "/");
47
+ }
48
+ catch (e) {
49
+ logReq(req, "error", "oauth callback failed", { err: e });
50
+ return res.status(500).send("oauth failed");
51
+ }
52
+ });
53
+ }
54
+ //# sourceMappingURL=oauth-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-routes.js","sourceRoot":"","sources":["../src/oauth-routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ // WebUI onboarding authorization gate.
2
+ //
3
+ // A single, platform-neutral allowlist replaces the per-forge instance-admin
4
+ // check: the operator lists the forge usernames allowed to complete onboarding
5
+ // in ONBOARDING_USERS (comma-separated). This is required because github.com
6
+ // has no instance-admin concept, and keeping one gate for every driver makes
7
+ // GitLab/ForgeJo/Gitea behave exactly like GitHub. The gate FAILS CLOSED: an
8
+ // unset/empty allowlist denies everyone, so a misconfigured deploy cannot be
9
+ // onboarded by an arbitrary user.
10
+ /** Parse the raw env value into a normalized, de-duplicated username set. */
11
+ export function parseOnboardingUsers(raw) {
12
+ const set = new Set();
13
+ if (!raw)
14
+ return set;
15
+ for (const part of raw.split(",")) {
16
+ const username = part.trim().toLowerCase();
17
+ if (username)
18
+ set.add(username);
19
+ }
20
+ return set;
21
+ }
22
+ /**
23
+ * True when `username` is permitted to onboard. Forge usernames are treated
24
+ * case-insensitively, so both sides are lowercased. An empty allowlist denies
25
+ * everyone (fail closed).
26
+ */
27
+ export function isOnboardingAllowed(username, raw) {
28
+ if (!username)
29
+ return false;
30
+ return parseOnboardingUsers(raw).has(username.trim().toLowerCase());
31
+ }
32
+ //# sourceMappingURL=onboarding-allowlist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboarding-allowlist.js","sourceRoot":"","sources":["../src/onboarding-allowlist.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,EAAE;AACF,6EAA6E;AAC7E,+EAA+E;AAC/E,6EAA6E;AAC7E,6EAA6E;AAC7E,6EAA6E;AAC7E,6EAA6E;AAC7E,kCAAkC;AAElC,6EAA6E;AAC7E,MAAM,UAAU,oBAAoB,CAAC,GAA8B;IACjE,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,IAAI,CAAC,GAAG;QAAE,OAAO,GAAG,CAAC;IACrB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,IAAI,QAAQ;YAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAmC,EAAE,GAA8B;IACrG,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,OAAO,oBAAoB,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AACtE,CAAC"}
@@ -0,0 +1,291 @@
1
+ import { spawn, spawnSync } from "node:child_process";
2
+ import { log } from "./logger.js";
3
+ import { redact } from "./redact.js";
4
+ import { OpencodeEventSchema, EventWithPartSchema, TextPartSchema, ErrorEventSchema, StepFinishPartSchema, } from "./types/opencode.js";
5
+ export function zeroUsage() {
6
+ return { input: 0, output: 0, reasoning: 0, cacheRead: 0, cacheWrite: 0, costUsd: 0 };
7
+ }
8
+ // Sum the step-finish parts of a run's NDJSON events. Pure; a malformed part is
9
+ // skipped so a bad upstream shape can never inject NaN into the totals.
10
+ export function extractUsage(events) {
11
+ const total = zeroUsage();
12
+ for (const raw of events) {
13
+ const ev = OpencodeEventSchema.safeParse(raw);
14
+ if (!ev.success)
15
+ continue;
16
+ const withPart = EventWithPartSchema.safeParse(ev.data);
17
+ if (!withPart.success)
18
+ continue;
19
+ const part = StepFinishPartSchema.safeParse(withPart.data.part);
20
+ if (!part.success)
21
+ continue;
22
+ const t = part.data.tokens;
23
+ total.input += t?.input ?? 0;
24
+ total.output += t?.output ?? 0;
25
+ total.reasoning += t?.reasoning ?? 0;
26
+ total.cacheRead += t?.cache?.read ?? 0;
27
+ total.cacheWrite += t?.cache?.write ?? 0;
28
+ total.costUsd += part.data.cost ?? 0;
29
+ }
30
+ return total;
31
+ }
32
+ function isTextPart(p) {
33
+ return TextPartSchema.safeParse(p).success;
34
+ }
35
+ function truncate(s, max = 2000) {
36
+ return s.length > max ? s.slice(0, max) + "…[truncated]" : s;
37
+ }
38
+ export function extractText(events) {
39
+ const texts = [];
40
+ for (const raw of events) {
41
+ const parsed = OpencodeEventSchema.safeParse(raw);
42
+ if (!parsed.success)
43
+ continue;
44
+ const errorEvent = ErrorEventSchema.safeParse(parsed.data);
45
+ if (errorEvent.success) {
46
+ const msg = errorEvent.data.error.data?.message ?? errorEvent.data.error.message;
47
+ if (msg)
48
+ texts.push(`⚠️ ${msg}`);
49
+ continue;
50
+ }
51
+ const withPart = EventWithPartSchema.safeParse(parsed.data);
52
+ if (!withPart.success)
53
+ continue;
54
+ if (isTextPart(withPart.data.part))
55
+ texts.push(withPart.data.part.text);
56
+ }
57
+ // ponytail: post only the last text/error entry to the forge (one note per run,
58
+ // not the whole transcript). Upgrade to a richer formatter if summaries
59
+ // ever need multi-part composition.
60
+ return texts.at(-1) ?? "";
61
+ }
62
+ // ponytail: spawnSync blocks the loop briefly on timeout (error path only).
63
+ // If many concurrent timeouts fire, switch to async spawn fire-and-forget.
64
+ export function killContainerByName(name) {
65
+ try {
66
+ spawnSync("podman", ["rm", "-f", name], { stdio: "ignore" });
67
+ }
68
+ catch {
69
+ /* best-effort; container may already be gone */
70
+ }
71
+ }
72
+ function containerNameFromArgs(args) {
73
+ const i = args.indexOf("--name");
74
+ return i >= 0 && i + 1 < args.length ? args[i + 1] : undefined;
75
+ }
76
+ export function runPodmanCapture(opts) {
77
+ return new Promise((resolve) => {
78
+ const child = spawn("podman", opts.args, {
79
+ cwd: opts.cwd,
80
+ env: { ...process.env, ...opts.env },
81
+ stdio: ["ignore", "pipe", "pipe"],
82
+ });
83
+ const stderrChunks = [];
84
+ const stdoutChunks = [];
85
+ const events = [];
86
+ const rawStdout = () => redact(Buffer.concat(stdoutChunks).toString("utf8"));
87
+ let lineBuf = "";
88
+ let timedOut = false;
89
+ let stalled = false;
90
+ let settled = false;
91
+ let lastOutputAt = Date.now();
92
+ const timer = setTimeout(() => {
93
+ timedOut = true;
94
+ try {
95
+ child.kill("SIGKILL");
96
+ }
97
+ catch { /* already dead */ }
98
+ const cname = containerNameFromArgs(opts.args);
99
+ if (cname)
100
+ killContainerByName(cname);
101
+ }, opts.timeoutMs);
102
+ // Inactivity watchdog (work item #96): a fully silent run is killed early
103
+ // instead of sitting "running" until timeoutMs. Checked a few times per
104
+ // stall window (bounded) so the kill lands promptly without busy-polling.
105
+ const stallMs = opts.stallMs ?? 0;
106
+ const stallTimer = stallMs > 0
107
+ ? setInterval(() => {
108
+ if (settled || stalled)
109
+ return;
110
+ if (Date.now() - lastOutputAt < stallMs)
111
+ return;
112
+ stalled = true;
113
+ try {
114
+ child.kill("SIGKILL");
115
+ }
116
+ catch { /* already dead */ }
117
+ const cname = containerNameFromArgs(opts.args);
118
+ if (cname)
119
+ killContainerByName(cname);
120
+ }, Math.max(1_000, Math.min(30_000, Math.floor(stallMs / 4))))
121
+ : undefined;
122
+ const clearTimers = () => {
123
+ clearTimeout(timer);
124
+ if (stallTimer)
125
+ clearInterval(stallTimer);
126
+ };
127
+ // ponytail: log each event as it arrives so a long run is observable in
128
+ // realtime. One log line per event across all part types — upgrade to
129
+ // debounce/batch or a LOG_OPENCODE_* flag if a chatty model floods.
130
+ function handleLine(raw) {
131
+ const trimmed = raw.trim();
132
+ if (!trimmed)
133
+ return;
134
+ let parsed;
135
+ try {
136
+ parsed = JSON.parse(trimmed);
137
+ }
138
+ catch {
139
+ return;
140
+ }
141
+ events.push(parsed);
142
+ const ev = OpencodeEventSchema.safeParse(parsed);
143
+ if (!ev.success)
144
+ return;
145
+ const errEv = ErrorEventSchema.safeParse(ev.data);
146
+ if (errEv.success) {
147
+ const msg = errEv.data.error.data?.message ?? errEv.data.error.message;
148
+ if (msg)
149
+ log.warn("opencode error event", { ...opts.context, msg });
150
+ return;
151
+ }
152
+ const withPart = EventWithPartSchema.safeParse(ev.data);
153
+ if (!withPart.success)
154
+ return;
155
+ const p = withPart.data.part;
156
+ // ponytail: log every part type as it arrives — previously only text/error
157
+ // were logged and every other part (tools, steps, reasoning, files, …)
158
+ // was silently dropped in realtime (the raw stdout dump at run end was
159
+ // the only record, at debug level, post-exit). One log line per event;
160
+ // add a LOG_OPENCODE_* flag if a chatty model floods.
161
+ switch (p.type) {
162
+ case "text":
163
+ log.debug("opencode text", { ...opts.context, text: p.text });
164
+ break;
165
+ case "tool": {
166
+ const st = p.state;
167
+ log.debug("opencode tool", {
168
+ ...opts.context,
169
+ tool: p.tool,
170
+ status: st?.status,
171
+ input: st?.input,
172
+ output: st?.output ? truncate(st.output) : undefined,
173
+ error: st?.error,
174
+ });
175
+ break;
176
+ }
177
+ case "step-start":
178
+ log.debug("opencode step-start", { ...opts.context });
179
+ break;
180
+ case "step-finish": {
181
+ const sf = StepFinishPartSchema.safeParse(p);
182
+ log.debug("opencode step-finish", {
183
+ ...opts.context,
184
+ reason: p.reason,
185
+ tokens: sf.success ? sf.data.tokens : undefined,
186
+ cost: sf.success ? sf.data.cost : undefined,
187
+ });
188
+ break;
189
+ }
190
+ case "reasoning":
191
+ log.debug("opencode reasoning", { ...opts.context, text: p.text });
192
+ break;
193
+ case "file":
194
+ log.debug("opencode file", { ...opts.context, mime: p.mime, filename: p.filename, url: p.url });
195
+ break;
196
+ case "subtask":
197
+ log.debug("opencode subtask", { ...opts.context, agent: p.agent, description: p.description });
198
+ break;
199
+ case "agent":
200
+ log.debug("opencode agent", { ...opts.context, name: p.name });
201
+ break;
202
+ case "retry":
203
+ log.warn("opencode retry", { ...opts.context, attempt: p.attempt, error: p.error });
204
+ break;
205
+ case "compaction":
206
+ log.debug("opencode compaction", { ...opts.context, auto: p.auto });
207
+ break;
208
+ case "snapshot":
209
+ log.debug("opencode snapshot", { ...opts.context });
210
+ break;
211
+ case "patch":
212
+ log.debug("opencode patch", { ...opts.context, files: p.files });
213
+ break;
214
+ default:
215
+ // ponytail: unknown part type — log the FULL body (not truncated) so
216
+ // no part is ever silently dropped again. Large if a future version
217
+ // emits a big-blob unknown type; that's the cost of completeness.
218
+ log.debug("opencode part", { ...opts.context, type: p.type, part: p });
219
+ }
220
+ }
221
+ child.stdout.on("data", (b) => {
222
+ lastOutputAt = Date.now();
223
+ stdoutChunks.push(b);
224
+ opts.onChunk?.("stdout", b.toString("utf8"));
225
+ lineBuf += b.toString("utf8");
226
+ let nl;
227
+ while ((nl = lineBuf.indexOf("\n")) >= 0) {
228
+ handleLine(lineBuf.slice(0, nl));
229
+ lineBuf = lineBuf.slice(nl + 1);
230
+ }
231
+ });
232
+ child.stderr.on("data", (b) => {
233
+ lastOutputAt = Date.now();
234
+ stderrChunks.push(b);
235
+ opts.onChunk?.("stderr", b.toString("utf8"));
236
+ });
237
+ child.on("error", (err) => {
238
+ if (settled)
239
+ return;
240
+ settled = true;
241
+ clearTimers();
242
+ log.error("podman spawn error", { ...opts.context, err: err.message });
243
+ resolve({ text: `⚠️ Failed to start container: ${err.message}`, error: true, exitCode: -1, kind: "spawn", rawOutput: rawStdout(), stderrTail: "", usage: zeroUsage() });
244
+ });
245
+ child.on("close", (code) => {
246
+ if (settled)
247
+ return;
248
+ settled = true;
249
+ clearTimers();
250
+ const exitCode = code ?? -1;
251
+ if (timedOut || stalled) {
252
+ const text = stalled
253
+ ? `⚠️ Run stalled — no output for ${Math.floor(stallMs / 60_000)}min, killed`
254
+ : `⚠️ Run timed out after ${Math.floor(opts.timeoutMs / 60_000)}min`;
255
+ log.warn(stalled ? "opencode stalled" : "opencode timed out", { ...opts.context, stallMs, timeoutMs: opts.timeoutMs });
256
+ resolve({
257
+ text,
258
+ error: true,
259
+ exitCode,
260
+ kind: "timeout",
261
+ rawOutput: rawStdout(),
262
+ stderrTail: redact(Buffer.concat(stderrChunks).toString("utf8")),
263
+ usage: extractUsage(events),
264
+ });
265
+ return;
266
+ }
267
+ const stderr = Buffer.concat(stderrChunks).toString("utf8");
268
+ // Flush any trailing partial line (opencode may exit without a final \n).
269
+ if (lineBuf.length > 0)
270
+ handleLine(lineBuf);
271
+ const stderrTail = redact(stderr.length > 1024 ? stderr.slice(-1024) : stderr);
272
+ const text = extractText(events);
273
+ if (exitCode !== 0 || (text.length === 0 && events.length === 0)) {
274
+ log.warn("opencode run failed", { ...opts.context, exitCode, eventCount: events.length, stderrTail });
275
+ resolve({
276
+ text: text.length > 0 ? text : `⚠️ opencode exited (${exitCode})\n\`\`\`\n${stderrTail}\n\`\`\``,
277
+ error: true,
278
+ exitCode,
279
+ kind: "exit",
280
+ rawOutput: redact(Buffer.concat(stdoutChunks).toString("utf8")),
281
+ stderrTail,
282
+ usage: extractUsage(events),
283
+ });
284
+ return;
285
+ }
286
+ log.debug("opencode ok", { ...opts.context, exitCode, eventCount: events.length });
287
+ resolve({ text: text || "✅ Done (no text output)", error: false, exitCode, kind: "ok", rawOutput: "", stderrTail: "", usage: extractUsage(events) });
288
+ });
289
+ });
290
+ }
291
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../src/opencode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,229 @@
1
+ import { db } from "./db.js";
2
+ import { log } from "./logger.js";
3
+ import { encrypt, decryptOrPlaintext } from "./crypto-util.js";
4
+ import { randomBytes } from "node:crypto";
5
+ import { WebhookEndpointSchema, } from "./types/outbound-webhook.js";
6
+ // Outbound webhook endpoints + their delivery queue. Same DB file as the other
7
+ // stores (devbot.db, 0600). Endpoints are keyed by (project_id, name); global
8
+ // endpoints reuse the sentinel scope id 0 (GLOBAL_SCOPE_ID), exactly like
9
+ // global MCP servers. The signing secret is encrypted at rest with SESSION_KEY.
10
+ //
11
+ // Deliveries are durable rows: emit() inserts one per matching endpoint, a
12
+ // worker claims due rows (atomic pending→delivering CAS), and settles them.
13
+ // A failed delivery is re-queued with a backoff until retries are exhausted.
14
+ const SEC = () => Math.floor(Date.now() / 1000);
15
+ export function initOutboundWebhookTables() {
16
+ // Belt-and-braces: migration 0020 is authoritative; keep the idempotent
17
+ // CREATE so a test DB opened without migrate() still works.
18
+ db.exec(`
19
+ CREATE TABLE IF NOT EXISTS outbound_webhooks (
20
+ project_id INTEGER NOT NULL,
21
+ name TEXT NOT NULL,
22
+ url TEXT NOT NULL,
23
+ events TEXT NOT NULL,
24
+ headers TEXT NOT NULL DEFAULT '{}',
25
+ enabled INTEGER NOT NULL DEFAULT 1,
26
+ secret TEXT NOT NULL,
27
+ created_at INTEGER NOT NULL,
28
+ updated_at INTEGER NOT NULL,
29
+ PRIMARY KEY (project_id, name)
30
+ )
31
+ `);
32
+ db.exec(`
33
+ CREATE TABLE IF NOT EXISTS outbound_webhook_deliveries (
34
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
35
+ project_id INTEGER NOT NULL,
36
+ webhook_name TEXT NOT NULL,
37
+ event TEXT NOT NULL,
38
+ payload TEXT NOT NULL,
39
+ status TEXT NOT NULL DEFAULT 'pending',
40
+ attempts INTEGER NOT NULL DEFAULT 0,
41
+ next_attempt_at INTEGER NOT NULL,
42
+ response_status INTEGER,
43
+ response_body TEXT NOT NULL DEFAULT '',
44
+ last_error TEXT NOT NULL DEFAULT '',
45
+ created_at INTEGER NOT NULL,
46
+ updated_at INTEGER NOT NULL
47
+ )
48
+ `);
49
+ db.exec("CREATE INDEX IF NOT EXISTS idx_outbound_deliveries_due ON outbound_webhook_deliveries(status, next_attempt_at)");
50
+ db.exec("CREATE INDEX IF NOT EXISTS idx_outbound_deliveries_webhook ON outbound_webhook_deliveries(project_id, webhook_name)");
51
+ }
52
+ export function newWebhookSecret() {
53
+ return `whsec_${randomBytes(32).toString("base64url")}`;
54
+ }
55
+ function parseEvents(raw) {
56
+ try {
57
+ const parsed = JSON.parse(raw);
58
+ return Array.isArray(parsed) ? parsed : [];
59
+ }
60
+ catch {
61
+ return [];
62
+ }
63
+ }
64
+ function parseHeaders(raw) {
65
+ try {
66
+ const parsed = JSON.parse(raw);
67
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed)
68
+ ? parsed
69
+ : {};
70
+ }
71
+ catch {
72
+ return {};
73
+ }
74
+ }
75
+ function toStored(r) {
76
+ return {
77
+ projectId: r.project_id,
78
+ name: r.name,
79
+ url: r.url,
80
+ events: parseEvents(r.events),
81
+ headers: parseHeaders(r.headers),
82
+ enabled: r.enabled === 1,
83
+ secret: decryptOrPlaintext(r.secret),
84
+ createdAt: r.created_at,
85
+ updatedAt: r.updated_at,
86
+ };
87
+ }
88
+ export function upsertWebhook(projectId, name, endpoint, secret) {
89
+ // Re-validate at the store boundary — the API layer validates too, but this
90
+ // is the trust boundary for the delivery worker.
91
+ const v = WebhookEndpointSchema.safeParse(endpoint);
92
+ if (!v.success)
93
+ throw new Error("invalid webhook endpoint");
94
+ const now = SEC();
95
+ db.prepare(`INSERT OR REPLACE INTO outbound_webhooks
96
+ (project_id, name, url, events, headers, enabled, secret, created_at, updated_at)
97
+ VALUES (?, ?, ?, ?, ?, ?, ?,
98
+ COALESCE((SELECT created_at FROM outbound_webhooks WHERE project_id = ? AND name = ?), ?),
99
+ ?)`).run(projectId, name, v.data.url, JSON.stringify(v.data.events), JSON.stringify(v.data.headers), v.data.enabled ? 1 : 0, encrypt(secret), projectId, name, now, now);
100
+ }
101
+ export function getWebhook(projectId, name) {
102
+ const row = db
103
+ .prepare("SELECT * FROM outbound_webhooks WHERE project_id = ? AND name = ?")
104
+ .get(projectId, name);
105
+ return row ? toStored(row) : null;
106
+ }
107
+ export function listWebhooks(projectId) {
108
+ const rows = db
109
+ .prepare("SELECT * FROM outbound_webhooks WHERE project_id = ? ORDER BY name")
110
+ .all(projectId);
111
+ return rows.map(toStored);
112
+ }
113
+ export function deleteWebhook(projectId, name) {
114
+ const r = db
115
+ .prepare("DELETE FROM outbound_webhooks WHERE project_id = ? AND name = ?")
116
+ .run(projectId, name);
117
+ return r.changes > 0;
118
+ }
119
+ export function deleteAllOutboundWebhooksForProject(projectId) {
120
+ db.prepare("DELETE FROM outbound_webhooks WHERE project_id = ?").run(projectId);
121
+ db.prepare("DELETE FROM outbound_webhook_deliveries WHERE project_id = ?").run(projectId);
122
+ }
123
+ // Enabled endpoints in this project's scope (project + global) subscribed to
124
+ // `event`. Global endpoints use scope id 0, which is never a real project id.
125
+ export function matchingWebhooks(projectId, event) {
126
+ const rows = db
127
+ .prepare("SELECT * FROM outbound_webhooks WHERE enabled = 1 AND project_id IN (?, 0) ORDER BY project_id, name")
128
+ .all(projectId);
129
+ return rows.map(toStored).filter((w) => w.events.includes(event));
130
+ }
131
+ // ---- Delivery queue --------------------------------------------------------
132
+ export function enqueueDelivery(projectId, webhookName, event, payload) {
133
+ const now = SEC();
134
+ const r = db
135
+ .prepare(`INSERT INTO outbound_webhook_deliveries
136
+ (project_id, webhook_name, event, payload, status, attempts, next_attempt_at, created_at, updated_at)
137
+ VALUES (?, ?, ?, ?, 'pending', 0, ?, ?, ?)`)
138
+ .run(projectId, webhookName, event, payload, Date.now(), now, now);
139
+ return Number(r.lastInsertRowid);
140
+ }
141
+ function toDeliverySummary(r) {
142
+ return {
143
+ id: r.id,
144
+ projectId: r.project_id,
145
+ webhookName: r.webhook_name,
146
+ event: r.event,
147
+ status: r.status,
148
+ attempts: r.attempts,
149
+ nextAttemptAt: r.next_attempt_at,
150
+ responseStatus: r.response_status,
151
+ lastError: r.last_error,
152
+ createdAt: r.created_at,
153
+ updatedAt: r.updated_at,
154
+ };
155
+ }
156
+ function toDeliveryRow(r) {
157
+ return { ...toDeliverySummary(r), payload: r.payload, responseBody: r.response_body };
158
+ }
159
+ // Claim due pending rows (atomic pending→delivering CAS). Returns the claimed
160
+ // rows so the worker can deliver them. `nowMs` is explicit for testability.
161
+ export function claimDueDeliveries(limit, nowMs) {
162
+ const rows = db
163
+ .prepare(`SELECT * FROM outbound_webhook_deliveries
164
+ WHERE status = 'pending' AND next_attempt_at <= ?
165
+ ORDER BY id ASC LIMIT ?`)
166
+ .all(nowMs, limit);
167
+ const claimed = [];
168
+ const upd = db.prepare("UPDATE outbound_webhook_deliveries SET status = 'delivering', updated_at = ? WHERE id = ? AND status = 'pending'");
169
+ for (const r of rows) {
170
+ if (upd.run(SEC(), r.id).changes === 0)
171
+ continue; // CAS lost
172
+ claimed.push(toDeliveryRow({ ...r, status: "delivering" }));
173
+ }
174
+ return claimed;
175
+ }
176
+ export function settleDeliverySucceeded(id, responseStatus, responseBody) {
177
+ db.prepare(`UPDATE outbound_webhook_deliveries
178
+ SET status = 'succeeded', attempts = attempts + 1, response_status = ?, response_body = ?,
179
+ last_error = '', updated_at = ?
180
+ WHERE id = ?`).run(responseStatus, responseBody.slice(0, 2000), SEC(), id);
181
+ }
182
+ // Settle a failed attempt. `retryAt` non-null re-queues as pending for that
183
+ // time; null marks the delivery terminally failed (retries exhausted).
184
+ export function settleDeliveryFailed(id, input) {
185
+ db.prepare(`UPDATE outbound_webhook_deliveries
186
+ SET status = ?, attempts = attempts + 1, response_status = ?, response_body = ?,
187
+ last_error = ?, next_attempt_at = ?, updated_at = ?
188
+ WHERE id = ?`).run(input.retryAt === null ? "failed" : "pending", input.responseStatus, input.responseBody.slice(0, 2000), input.error.slice(0, 2000), input.retryAt ?? Date.now(), SEC(), id);
189
+ }
190
+ // Crash recovery: a delivery claimed but never settled goes back to pending.
191
+ export function resetStuckDeliveries() {
192
+ const r = db
193
+ .prepare("UPDATE outbound_webhook_deliveries SET status = 'pending', updated_at = ? WHERE status = 'delivering'")
194
+ .run(SEC());
195
+ return Number(r.changes);
196
+ }
197
+ export function listDeliveries(projectId, webhookName, limit, offset) {
198
+ const rows = db
199
+ .prepare(`SELECT * FROM outbound_webhook_deliveries
200
+ WHERE project_id = ? AND webhook_name = ?
201
+ ORDER BY id DESC LIMIT ? OFFSET ?`)
202
+ .all(projectId, webhookName, limit, offset);
203
+ return rows.map(toDeliverySummary);
204
+ }
205
+ export function countDeliveries(projectId, webhookName) {
206
+ const row = db
207
+ .prepare("SELECT COUNT(*) AS c FROM outbound_webhook_deliveries WHERE project_id = ? AND webhook_name = ?")
208
+ .get(projectId, webhookName);
209
+ return row.c;
210
+ }
211
+ export function getDelivery(id) {
212
+ const row = db.prepare("SELECT * FROM outbound_webhook_deliveries WHERE id = ?").get(id);
213
+ return row ? toDeliveryRow(row) : null;
214
+ }
215
+ // Re-queue a terminal delivery for another attempt (manual replay from the UI).
216
+ export function replayDelivery(id) {
217
+ const r = db
218
+ .prepare("UPDATE outbound_webhook_deliveries SET status = 'pending', next_attempt_at = ?, updated_at = ? WHERE id = ?")
219
+ .run(Date.now(), SEC(), id);
220
+ return r.changes > 0;
221
+ }
222
+ export function purgeDeliveriesOlderThan(days) {
223
+ const cutoff = SEC() - days * 24 * 3600;
224
+ const r = db.prepare("DELETE FROM outbound_webhook_deliveries WHERE created_at < ?").run(cutoff);
225
+ if (r.changes > 0)
226
+ log.debug("outbound delivery purge", { purged: r.changes, days });
227
+ return Number(r.changes);
228
+ }
229
+ //# sourceMappingURL=outbound-webhook-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbound-webhook-store.js","sourceRoot":"","sources":["../src/outbound-webhook-store.ts"],"names":[],"mappings":"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"}