@wascartech/devbot 0.0.0-stage → 2.1.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 (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 +141 -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 +73 -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 +157 -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,200 @@
1
+ // Project-scope path policy (work item #46). One forge-free source of truth for
2
+ // "which paths may the agent (and the tools acting on its behalf) touch?".
3
+ //
4
+ // The policy is intentionally lexical here: the host process never has the run
5
+ // volume mounted, so canonicalisation (realpath) happens where the filesystem
6
+ // actually lives — the container shell in volume-files.ts. This module owns the
7
+ // *rules*; the host validator, the container shell deny cases, the opencode
8
+ // permission globs, and the in-container guard plugin are all derived from it,
9
+ // so they can never drift.
10
+ //
11
+ // Denied by design: hidden/system state that can hold credentials or forge
12
+ // access — `.xdg-*` (legacy in-repo xdg dirs plus the mount name), `.git`
13
+ // (config can carry tokens), `.ssh`, and `.env`/`.env.*` (except `.env.example`).
14
+ // Allowed by design: `.devbot-out/` and `.devbot-peers/` (agent staging dirs,
15
+ // git-excluded) and `.devbot/` (repo init scripts) — the agent is meant to use
16
+ // them.
17
+ export const PROJECT_ROOT = "/workspace";
18
+ export const PATH_POLICY_ENV = "DEVBOT_PATH_POLICY";
19
+ export const PATH_POLICY = {
20
+ root: PROJECT_ROOT,
21
+ denied: [".git", ".ssh"],
22
+ deniedPrefixes: [".xdg"],
23
+ deniedFiles: [".env"],
24
+ allowedFiles: [".env.example"],
25
+ masked: [
26
+ "/home/devbot/.xdg",
27
+ "/home/devbot/.config",
28
+ "$XDG_DATA_HOME",
29
+ "$XDG_CONFIG_HOME",
30
+ "$XDG_STATE_HOME",
31
+ "$XDG_CACHE_HOME",
32
+ "~/.xdg",
33
+ "~/.config",
34
+ ],
35
+ };
36
+ /** A path that the policy refuses to operate on. Carries a user-readable reason. */
37
+ export class PathDeniedError extends Error {
38
+ constructor(message) {
39
+ super(message);
40
+ this.name = "PathDeniedError";
41
+ }
42
+ }
43
+ /** JSON form of the policy, injected into the run container as
44
+ * `--env DEVBOT_PATH_POLICY=...` for the guard plugin to read. */
45
+ export function pathPolicyJson(policy = PATH_POLICY) {
46
+ return JSON.stringify(policy);
47
+ }
48
+ // ---- Matching --------------------------------------------------------------
49
+ /** True when a single path segment is denied by the policy. */
50
+ export function isDeniedSegment(seg, policy = PATH_POLICY) {
51
+ if (seg === "")
52
+ return false;
53
+ if (policy.allowedFiles.includes(seg))
54
+ return false;
55
+ if (policy.denied.includes(seg))
56
+ return true;
57
+ if (policy.deniedPrefixes.some((p) => seg === p || seg.startsWith(`${p}-`)))
58
+ return true;
59
+ if (policy.deniedFiles.includes(seg))
60
+ return true;
61
+ if (seg.startsWith(".env.") && !policy.allowedFiles.includes(seg))
62
+ return true;
63
+ return false;
64
+ }
65
+ /** True when any segment of an absolute (or `/`-rooted) path is denied. */
66
+ export function isDeniedPath(absPath, policy = PATH_POLICY) {
67
+ return absPath.split("/").some((seg) => isDeniedSegment(seg, policy));
68
+ }
69
+ // ---- Host-side resolution --------------------------------------------------
70
+ /** Resolve a tool-supplied path to an absolute path under the project root and
71
+ * reject traversal, escapes, and denied segments. Pure; no IO (the container
72
+ * shell re-checks the real path to catch symlink escapes). */
73
+ export function resolveProjectPath(raw, policy = PATH_POLICY) {
74
+ const trimmed = raw.trim();
75
+ if (!trimmed)
76
+ throw new PathDeniedError("path is required");
77
+ if (trimmed.includes("\0"))
78
+ throw new PathDeniedError("path contains a NUL byte");
79
+ const joined = trimmed.startsWith("/") ? trimmed : `${policy.root}/${trimmed}`;
80
+ const parts = [];
81
+ for (const seg of joined.split("/")) {
82
+ if (seg === "" || seg === ".")
83
+ continue;
84
+ if (seg === "..")
85
+ throw new PathDeniedError(`path must stay inside ${policy.root}`);
86
+ if (isDeniedSegment(seg, policy))
87
+ throw new PathDeniedError(`path is restricted: ${seg}`);
88
+ parts.push(seg);
89
+ }
90
+ const abs = `/${parts.join("/")}`;
91
+ if (abs !== policy.root && !abs.startsWith(`${policy.root}/`)) {
92
+ throw new PathDeniedError(`path must stay inside ${policy.root}`);
93
+ }
94
+ if (abs === policy.root)
95
+ throw new PathDeniedError("path must point at a file, not the project root");
96
+ return abs;
97
+ }
98
+ /** Validate a slash-separated *relative* path used to build a path under the
99
+ * root (e.g. a peer project's namespace). Rejects absolute paths, `..`,
100
+ * empty/denied segments. Returns the normalized relative path. */
101
+ export function validateProjectRelativePath(raw, policy = PATH_POLICY) {
102
+ const trimmed = raw.trim();
103
+ if (!trimmed)
104
+ throw new PathDeniedError("path is required");
105
+ if (trimmed.startsWith("/"))
106
+ throw new PathDeniedError("path must be relative");
107
+ const parts = [];
108
+ for (const seg of trimmed.split("/")) {
109
+ if (seg === "" || seg === ".")
110
+ continue;
111
+ if (seg === "..")
112
+ throw new PathDeniedError("path must stay inside the project root");
113
+ if (isDeniedSegment(seg, policy))
114
+ throw new PathDeniedError(`path is restricted: ${seg}`);
115
+ parts.push(seg);
116
+ }
117
+ if (parts.length === 0)
118
+ throw new PathDeniedError("path is required");
119
+ return parts.join("/");
120
+ }
121
+ // ---- Derived views ---------------------------------------------------------
122
+ /** Relative globs for opencode's `read`/`edit`/`glob`/`grep`/`list` permission
123
+ * objects. Put these after a `"*": "allow"` and before the allow globs so the
124
+ * last matching rule wins. */
125
+ export function denyGlobs(policy = PATH_POLICY) {
126
+ const globs = [];
127
+ for (const p of policy.deniedPrefixes) {
128
+ globs.push(`**/${p}`, `**/${p}/**`, `**/${p}-*`, `**/${p}-*/**`);
129
+ }
130
+ for (const d of policy.denied) {
131
+ globs.push(`**/${d}`, `**/${d}/**`);
132
+ }
133
+ for (const f of policy.deniedFiles) {
134
+ globs.push(`**/${f}`, `**/${f}.*`);
135
+ }
136
+ return globs;
137
+ }
138
+ /** Allow globs that must be evaluated *after* denyGlobs (last match wins). */
139
+ export function allowGlobs(policy = PATH_POLICY) {
140
+ return policy.allowedFiles.map((f) => `**/${f}`);
141
+ }
142
+ /** Permission object used by the generated and static opencode configs. */
143
+ export function permissionGlobRule(policy = PATH_POLICY) {
144
+ const rule = { "*": "allow" };
145
+ for (const g of denyGlobs(policy))
146
+ rule[g] = "deny";
147
+ for (const g of allowGlobs(policy))
148
+ rule[g] = "allow";
149
+ return rule;
150
+ }
151
+ /** `case` glob patterns for the container shell. The allow patterns must be
152
+ * tried first (`.env.example` also matches the `.env.*` deny pattern). */
153
+ export function denyShellCasePatterns(policy = PATH_POLICY) {
154
+ const pats = [];
155
+ for (const p of policy.deniedPrefixes) {
156
+ pats.push(`*/${p}`, `*/${p}/*`, `*/${p}-*`, `*/${p}-*/*`);
157
+ }
158
+ for (const d of policy.denied) {
159
+ pats.push(`*/${d}`, `*/${d}/*`);
160
+ }
161
+ for (const f of policy.deniedFiles) {
162
+ pats.push(`*/${f}`, `*/${f}.*`);
163
+ }
164
+ return pats;
165
+ }
166
+ export function allowShellCasePatterns(policy = PATH_POLICY) {
167
+ return policy.allowedFiles.map((f) => `*/${f}`);
168
+ }
169
+ /** Best-effort bash guard: a command string that references a masked root or a
170
+ * `..` escape is refused by the plugin. Shell cannot be fully parsed; this
171
+ * catches the obvious literal exfiltration commands.
172
+ *
173
+ * A masked root is a violation when it is used *as a path*: a literal path
174
+ * (`/home/devbot/.xdg`, `~/.config`) anywhere, or an environment-variable
175
+ * expansion followed by `/` (`$XDG_DATA_HOME/...`, `${XDG_CONFIG_HOME}/...`).
176
+ * A bare mention of a variable name — `echo $XDG_DATA_HOME`, a `grep` pattern,
177
+ * a heredoc — is not an access and must not be blocked, or an agent merely
178
+ * inspecting the repo's own docs loops on false positives (work item #96). */
179
+ export function bashGuardReason(command, policy = PATH_POLICY) {
180
+ for (const m of policy.masked) {
181
+ if (m.startsWith("$")) {
182
+ const name = m.slice(1).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
183
+ if (new RegExp(`\\$\\{?${name}\\}?(?=/)`).test(command)) {
184
+ return `command references restricted path ${m}`;
185
+ }
186
+ continue;
187
+ }
188
+ if (command.includes(m))
189
+ return `command references restricted path ${m}`;
190
+ }
191
+ // A `..` path segment anywhere is almost always an attempt to leave the root.
192
+ if (/(^|[\s'"=])\.\.(\/|[\s'"]|$)/.test(command))
193
+ return "command references a parent path (..)";
194
+ return null;
195
+ }
196
+ /** Convenience for the runner: `--env DEVBOT_PATH_POLICY=<json>`. */
197
+ export function pathPolicyEnvArgs(policy = PATH_POLICY) {
198
+ return ["--env", `${PATH_POLICY_ENV}=${pathPolicyJson(policy)}`];
199
+ }
200
+ //# sourceMappingURL=path-sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-sandbox.js","sourceRoot":"","sources":["../src/path-sandbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ // Git auth helper shared by drivers. GitLab's smart-HTTP endpoint requires HTTP
2
+ // Basic (`oauth2:<token>`); Gitea/ForgeJo accept Basic with any username, with
3
+ // the token as password (common convention: the bot username); GitHub accepts
4
+ // any username with the token as password but conventionally uses
5
+ // `x-access-token` for installation/PAT auth.
6
+ //
7
+ // The header is URL-SCOPED to the forge host (`http.<url>/.extraHeader`)
8
+ // whenever a scope URL is supplied, so git only sends the bot token to the
9
+ // configured forge — a submodule on an external host is fetched without the
10
+ // token instead of leaking it. Scoping is the default for every driver.
11
+ import { config } from "../config.js";
12
+ import { shq } from "../redact.js";
13
+ /** Strip trailing slashes so the URL-scoped config key stays well-formed. */
14
+ export function normalizeScopeUrl(url) {
15
+ return url.replace(/\/+$/, "");
16
+ }
17
+ export function gitExtraHeaderFor(token, username = "git", scopeUrl) {
18
+ const basic = Buffer.from(`${username}:${token}`).toString("base64");
19
+ const key = scopeUrl ? `http.${normalizeScopeUrl(scopeUrl)}/.extraHeader` : "http.extraHeader";
20
+ return `git -c ${key}=${shq(`Authorization: Basic ${basic}`)}`;
21
+ }
22
+ /** GitLab convention (`oauth2` username), scoped to the forge host. */
23
+ export function gitExtraHeaderGitlab(token, url = config.PLATFORM_URL) {
24
+ return gitExtraHeaderFor(token, "oauth2", url);
25
+ }
26
+ /** Gitea/ForgeJo convention (bot username, token as password), scoped. */
27
+ export function gitExtraHeaderGitea(token, botUsername = config.BOT_USERNAME, url = config.PLATFORM_URL) {
28
+ return gitExtraHeaderFor(token, botUsername, url);
29
+ }
30
+ /** GitHub convention (`x-access-token` username for PAT/OAuth tokens), scoped. */
31
+ export function gitExtraHeaderGithub(token, url = config.PLATFORM_URL) {
32
+ return gitExtraHeaderFor(token, "x-access-token", url);
33
+ }
34
+ //# sourceMappingURL=git-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-auth.js","sourceRoot":"","sources":["../../src/platform/git-auth.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,+EAA+E;AAC/E,8EAA8E;AAC9E,kEAAkE;AAClE,8CAA8C;AAC9C,EAAE;AACF,yEAAyE;AACzE,2EAA2E;AAC3E,4EAA4E;AAC5E,wEAAwE;AAExE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,6EAA6E;AAC7E,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,QAAQ,GAAG,KAAK,EAAE,QAAiB;IAClF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,IAAI,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrE,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,iBAAiB,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,kBAAkB,CAAC;IAC/F,OAAO,UAAU,GAAG,IAAI,GAAG,CAAC,wBAAwB,KAAK,EAAE,CAAC,EAAE,CAAC;AACjE,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,oBAAoB,CAAC,KAAa,EAAE,GAAG,GAAG,MAAM,CAAC,YAAY;IAC3E,OAAO,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;AACjD,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,WAAW,GAAG,MAAM,CAAC,YAAY,EAAE,GAAG,GAAG,MAAM,CAAC,YAAY;IAC7G,OAAO,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;AACpD,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,oBAAoB,CAAC,KAAa,EAAE,GAAG,GAAG,MAAM,CAAC,YAAY;IAC3E,OAAO,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,CAAC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,62 @@
1
+ // Gitea/ForgeJo attachment discovery + fetch. Issue-comment attachments are
2
+ // Markdown links to `/attachments/{uuid}` (with or without a filename suffix),
3
+ // e.g. `[name](/attachments/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee)` or
4
+ // `![alt](https://host/attachments/<uuid>)`. The uuid is the stable id; the
5
+ // download endpoint is the raw URL itself. Discovery is Gitea-specific; the
6
+ // extraction engine lives in ../../attachments.ts.
7
+ import { runtime } from "../../runtime-state.js";
8
+ import { giteaFetchRaw, giteaUpload } from "./http.js";
9
+ import { GiteaAttachmentSchema } from "./schemas.js";
10
+ import { MD_LINK, safeDecode, stripCodeSpans, } from "../../attachments.js";
11
+ const GITEA_ATTACHMENT = /\/attachments\/([0-9a-fA-F-]{8,})\/?([^)\s]*)/;
12
+ export function findGiteaAttachmentRefs(body) {
13
+ const stripped = stripCodeSpans(body);
14
+ const refs = [];
15
+ const seen = new Set();
16
+ for (const m of stripped.matchAll(MD_LINK)) {
17
+ const url = m[2] ?? "";
18
+ const hit = GITEA_ATTACHMENT.exec(url);
19
+ if (!hit)
20
+ continue;
21
+ const uuid = hit[1] ?? "";
22
+ if (!uuid || seen.has(uuid))
23
+ continue;
24
+ seen.add(uuid);
25
+ const tail = safeDecode((hit[2] ?? "").replace(/^\//, ""));
26
+ refs.push({
27
+ raw: m[0] ?? "",
28
+ secret: uuid,
29
+ filename: tail || uuid,
30
+ absolute: /^https?:\/\//i.test(url),
31
+ });
32
+ }
33
+ for (const m of stripped.matchAll(new RegExp(GITEA_ATTACHMENT.source, "g"))) {
34
+ const uuid = m[1] ?? "";
35
+ if (!uuid || seen.has(uuid))
36
+ continue;
37
+ seen.add(uuid);
38
+ const tail = safeDecode((m[2] ?? "").replace(/^\//, ""));
39
+ refs.push({ raw: m[0] ?? "", secret: uuid, filename: tail || uuid, absolute: false });
40
+ }
41
+ return refs;
42
+ }
43
+ /** Fetch one Gitea/ForgeJo attachment's full bytes. */
44
+ export async function downloadGiteaAttachment(ref) {
45
+ const { bytes, contentType } = await giteaFetchRaw(`/attachments/${ref.secret}`, { kind: "bot" }, runtime().attachmentMaxBytes);
46
+ return { bytes, contentType };
47
+ }
48
+ // Outbound upload via the issue/assets API. Gitea/ForgeJo accept multipart field
49
+ // `attachment` at POST /repos/:owner/:repo/issues/:index/assets and return the
50
+ // stored uuid + browser_download_url. The owner/repo split is done by the driver
51
+ // (it already resolves the numeric repo id to a full_name).
52
+ export async function uploadGiteaAttachment(owner, repo, number, file) {
53
+ const form = new FormData();
54
+ form.append("attachment", new Blob([file.bytes], { type: file.contentType }), file.filename);
55
+ const r = await giteaUpload(`/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/issues/${number}/assets`, form, GiteaAttachmentSchema, { kind: "bot" });
56
+ return {
57
+ markdown: `![${r.name}](/attachments/${r.uuid})`,
58
+ url: r.browser_download_url,
59
+ filename: r.name,
60
+ };
61
+ }
62
+ //# sourceMappingURL=attachments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../../src/platform/gitealike/attachments.ts"],"names":[],"mappings":"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"}