@bevel-software/platform-core-backend 0.22.0 → 0.24.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 (466) hide show
  1. package/dist/core/core-ports.d.ts +11 -1
  2. package/dist/core/core-ports.d.ts.map +1 -1
  3. package/dist/core/core-ports.js.map +1 -1
  4. package/dist/core/create-core-server.d.ts +3 -3
  5. package/dist/core/create-core-server.d.ts.map +1 -1
  6. package/dist/core/create-core-server.js +46 -13
  7. package/dist/core/create-core-server.js.map +1 -1
  8. package/dist/core/create-core-services.d.ts +12 -2
  9. package/dist/core/create-core-services.d.ts.map +1 -1
  10. package/dist/core/create-core-services.js +137 -24
  11. package/dist/core/create-core-services.js.map +1 -1
  12. package/dist/core/lifecycle.d.ts +46 -1
  13. package/dist/core/lifecycle.d.ts.map +1 -1
  14. package/dist/core/lifecycle.js +99 -13
  15. package/dist/core/lifecycle.js.map +1 -1
  16. package/dist/core-config.d.ts +16 -12
  17. package/dist/core-config.d.ts.map +1 -1
  18. package/dist/core-config.js +28 -13
  19. package/dist/core-config.js.map +1 -1
  20. package/dist/index.d.ts +6 -4
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +12 -3
  23. package/dist/index.js.map +1 -1
  24. package/dist/modules/access/access-control.interface.d.ts +42 -12
  25. package/dist/modules/access/access-control.interface.d.ts.map +1 -1
  26. package/dist/modules/access/access-control.service.d.ts +67 -10
  27. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  28. package/dist/modules/access/access-control.service.js +214 -35
  29. package/dist/modules/access/access-control.service.js.map +1 -1
  30. package/dist/modules/access/access.routes.d.ts.map +1 -1
  31. package/dist/modules/access/access.routes.js +17 -16
  32. package/dist/modules/access/access.routes.js.map +1 -1
  33. package/dist/modules/access/directory-sync-bot.d.ts.map +1 -1
  34. package/dist/modules/access/directory-sync-bot.js +7 -3
  35. package/dist/modules/access/directory-sync-bot.js.map +1 -1
  36. package/dist/modules/agent-instructions/agent-instructions.routes.d.ts +8 -1
  37. package/dist/modules/agent-instructions/agent-instructions.routes.d.ts.map +1 -1
  38. package/dist/modules/agent-instructions/agent-instructions.routes.js +8 -2
  39. package/dist/modules/agent-instructions/agent-instructions.routes.js.map +1 -1
  40. package/dist/modules/agent-instructions/compose.d.ts +38 -6
  41. package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
  42. package/dist/modules/agent-instructions/compose.js +39 -6
  43. package/dist/modules/agent-instructions/compose.js.map +1 -1
  44. package/dist/modules/agent-instructions/index.d.ts +2 -1
  45. package/dist/modules/agent-instructions/index.d.ts.map +1 -1
  46. package/dist/modules/agent-instructions/index.js +2 -1
  47. package/dist/modules/agent-instructions/index.js.map +1 -1
  48. package/dist/modules/agent-instructions/shared-file-rules.d.ts +115 -0
  49. package/dist/modules/agent-instructions/shared-file-rules.d.ts.map +1 -0
  50. package/dist/modules/agent-instructions/shared-file-rules.js +272 -0
  51. package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -0
  52. package/dist/modules/audit/agent-audit.service.d.ts.map +1 -1
  53. package/dist/modules/audit/agent-audit.service.js +4 -2
  54. package/dist/modules/audit/agent-audit.service.js.map +1 -1
  55. package/dist/modules/auth/account-admission.d.ts +58 -7
  56. package/dist/modules/auth/account-admission.d.ts.map +1 -1
  57. package/dist/modules/auth/account-admission.js +44 -1
  58. package/dist/modules/auth/account-admission.js.map +1 -1
  59. package/dist/modules/auth/account-erasure.service.d.ts.map +1 -1
  60. package/dist/modules/auth/account-erasure.service.js +57 -16
  61. package/dist/modules/auth/account-erasure.service.js.map +1 -1
  62. package/dist/modules/auth/account.routes.d.ts +1 -1
  63. package/dist/modules/auth/account.routes.d.ts.map +1 -1
  64. package/dist/modules/auth/account.routes.js +61 -5
  65. package/dist/modules/auth/account.routes.js.map +1 -1
  66. package/dist/modules/auth/auth.middleware.d.ts +1 -1
  67. package/dist/modules/auth/auth.middleware.d.ts.map +1 -1
  68. package/dist/modules/auth/auth.middleware.js +18 -7
  69. package/dist/modules/auth/auth.middleware.js.map +1 -1
  70. package/dist/modules/auth/auth.routes.d.ts.map +1 -1
  71. package/dist/modules/auth/auth.routes.js +8 -0
  72. package/dist/modules/auth/auth.routes.js.map +1 -1
  73. package/dist/modules/auth/auth.service.d.ts +70 -2
  74. package/dist/modules/auth/auth.service.d.ts.map +1 -1
  75. package/dist/modules/auth/auth.service.js +197 -18
  76. package/dist/modules/auth/auth.service.js.map +1 -1
  77. package/dist/modules/auth/oidc-auth-provider.d.ts.map +1 -1
  78. package/dist/modules/auth/oidc-auth-provider.js +7 -2
  79. package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
  80. package/dist/modules/code-mode/code-mode.tool.d.ts +20 -2
  81. package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -1
  82. package/dist/modules/code-mode/code-mode.tool.js +66 -35
  83. package/dist/modules/code-mode/code-mode.tool.js.map +1 -1
  84. package/dist/modules/database/connection.d.ts +16 -0
  85. package/dist/modules/database/connection.d.ts.map +1 -1
  86. package/dist/modules/database/connection.js +117 -0
  87. package/dist/modules/database/connection.js.map +1 -1
  88. package/dist/modules/database/core-schema.d.ts +337 -120
  89. package/dist/modules/database/core-schema.d.ts.map +1 -1
  90. package/dist/modules/database/core-schema.js +116 -58
  91. package/dist/modules/database/core-schema.js.map +1 -1
  92. package/dist/modules/database/migrate.d.ts +8 -0
  93. package/dist/modules/database/migrate.d.ts.map +1 -1
  94. package/dist/modules/database/migrate.js +271 -1
  95. package/dist/modules/database/migrate.js.map +1 -1
  96. package/dist/modules/kb-fs/branch-name.d.ts.map +1 -1
  97. package/dist/modules/kb-fs/branch-name.js +12 -2
  98. package/dist/modules/kb-fs/branch-name.js.map +1 -1
  99. package/dist/modules/kb-fs/repo-path.d.ts +11 -16
  100. package/dist/modules/kb-fs/repo-path.d.ts.map +1 -1
  101. package/dist/modules/kb-fs/repo-path.js +79 -0
  102. package/dist/modules/kb-fs/repo-path.js.map +1 -1
  103. package/dist/modules/kb-sync/kb-sync.routes.d.ts +2 -2
  104. package/dist/modules/kb-sync/kb-sync.routes.d.ts.map +1 -1
  105. package/dist/modules/kb-sync/kb-sync.routes.js +14 -3
  106. package/dist/modules/kb-sync/kb-sync.routes.js.map +1 -1
  107. package/dist/modules/kb-sync/sync-auth.d.ts +3 -1
  108. package/dist/modules/kb-sync/sync-auth.d.ts.map +1 -1
  109. package/dist/modules/kb-sync/sync-auth.js +1 -1
  110. package/dist/modules/kb-sync/sync-auth.js.map +1 -1
  111. package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
  112. package/dist/modules/mcp/mcp-auth.middleware.js +21 -6
  113. package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
  114. package/dist/modules/mcp/mcp.service.d.ts +8 -0
  115. package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
  116. package/dist/modules/mcp/mcp.service.js +38 -8
  117. package/dist/modules/mcp/mcp.service.js.map +1 -1
  118. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
  119. package/dist/modules/mcp/oauth/bevel-oauth-provider.js +3 -2
  120. package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
  121. package/dist/modules/plugins/join-request-records.store.d.ts.map +1 -1
  122. package/dist/modules/plugins/join-request-records.store.js +7 -4
  123. package/dist/modules/plugins/join-request-records.store.js.map +1 -1
  124. package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
  125. package/dist/modules/settings/deployment-settings.service.js +8 -3
  126. package/dist/modules/settings/deployment-settings.service.js.map +1 -1
  127. package/dist/modules/settings/setup.routes.d.ts +52 -1
  128. package/dist/modules/settings/setup.routes.d.ts.map +1 -1
  129. package/dist/modules/settings/setup.routes.js +207 -19
  130. package/dist/modules/settings/setup.routes.js.map +1 -1
  131. package/dist/modules/skills/skills.contract.d.ts +90 -18
  132. package/dist/modules/skills/skills.contract.d.ts.map +1 -1
  133. package/dist/modules/skills/skills.contract.js +4 -1
  134. package/dist/modules/skills/skills.contract.js.map +1 -1
  135. package/dist/modules/skills/skills.service.d.ts +98 -9
  136. package/dist/modules/skills/skills.service.d.ts.map +1 -1
  137. package/dist/modules/skills/skills.service.js +239 -37
  138. package/dist/modules/skills/skills.service.js.map +1 -1
  139. package/dist/modules/skills/skills.tools.d.ts +7 -0
  140. package/dist/modules/skills/skills.tools.d.ts.map +1 -1
  141. package/dist/modules/skills/skills.tools.js +71 -7
  142. package/dist/modules/skills/skills.tools.js.map +1 -1
  143. package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
  144. package/dist/modules/tool-auth/external-api-key.service.js +12 -4
  145. package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
  146. package/dist/modules/tool-auth/internal-token.service.d.ts +3 -3
  147. package/dist/modules/tool-auth/tool-auth.middleware.d.ts +16 -7
  148. package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
  149. package/dist/modules/tool-auth/tool-auth.middleware.js +34 -12
  150. package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
  151. package/dist/modules/tool-helpers/tool-handler.d.ts +2 -1
  152. package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -1
  153. package/dist/modules/tool-helpers/tool-handler.js +25 -4
  154. package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
  155. package/dist/modules/tool-helpers/tool.contract.d.ts +3 -2
  156. package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
  157. package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
  158. package/dist/modules/tool-helpers/validate-token.js +1 -1
  159. package/dist/modules/tool-helpers/validate-token.js.map +1 -1
  160. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
  161. package/dist/modules/tool-manuals/tool-manuals.tools.js +42 -31
  162. package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
  163. package/dist/modules/tool-registry/description-length.d.ts +80 -0
  164. package/dist/modules/tool-registry/description-length.d.ts.map +1 -0
  165. package/dist/modules/tool-registry/description-length.js +108 -0
  166. package/dist/modules/tool-registry/description-length.js.map +1 -0
  167. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts +98 -0
  168. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts.map +1 -0
  169. package/dist/modules/workflow/agent-tools/change-request-summary.js +81 -0
  170. package/dist/modules/workflow/agent-tools/change-request-summary.js.map +1 -0
  171. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  172. package/dist/modules/workflow/agent-tools/workflow.tools.js +75 -35
  173. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  174. package/dist/modules/workflow/file-lock.service.d.ts +24 -0
  175. package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
  176. package/dist/modules/workflow/file-lock.service.js +30 -0
  177. package/dist/modules/workflow/file-lock.service.js.map +1 -1
  178. package/dist/modules/workflow/git/git.service.d.ts +94 -0
  179. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  180. package/dist/modules/workflow/git/git.service.js +193 -3
  181. package/dist/modules/workflow/git/git.service.js.map +1 -1
  182. package/dist/modules/workflow/pending-commits.service.d.ts +38 -0
  183. package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
  184. package/dist/modules/workflow/pending-commits.service.js +60 -1
  185. package/dist/modules/workflow/pending-commits.service.js.map +1 -1
  186. package/dist/modules/workflow/recovery-bot.d.ts.map +1 -1
  187. package/dist/modules/workflow/recovery-bot.js +7 -3
  188. package/dist/modules/workflow/recovery-bot.js.map +1 -1
  189. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
  190. package/dist/modules/workflow/review-workflow/review-workflow.service.js +12 -3
  191. package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
  192. package/dist/modules/workflow/workflow-hooks.d.ts +54 -32
  193. package/dist/modules/workflow/workflow-hooks.d.ts.map +1 -1
  194. package/dist/modules/workflow/workflow-hooks.js +16 -1
  195. package/dist/modules/workflow/workflow-hooks.js.map +1 -1
  196. package/dist/modules/workflow/workflow.service.d.ts +60 -6
  197. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  198. package/dist/modules/workflow/workflow.service.js +115 -5
  199. package/dist/modules/workflow/workflow.service.js.map +1 -1
  200. package/dist/modules/workspace/agent-access.gate.d.ts +94 -0
  201. package/dist/modules/workspace/agent-access.gate.d.ts.map +1 -0
  202. package/dist/modules/workspace/agent-access.gate.js +123 -0
  203. package/dist/modules/workspace/agent-access.gate.js.map +1 -0
  204. package/dist/modules/workspace/agent-upload.routes.d.ts +77 -0
  205. package/dist/modules/workspace/agent-upload.routes.d.ts.map +1 -0
  206. package/dist/modules/workspace/agent-upload.routes.js +210 -0
  207. package/dist/modules/workspace/agent-upload.routes.js.map +1 -0
  208. package/dist/modules/workspace/agent-upload.store.d.ts +284 -0
  209. package/dist/modules/workspace/agent-upload.store.d.ts.map +1 -0
  210. package/dist/modules/workspace/agent-upload.store.js +553 -0
  211. package/dist/modules/workspace/agent-upload.store.js.map +1 -0
  212. package/dist/modules/workspace/routine-write-policy.d.ts +5 -6
  213. package/dist/modules/workspace/routine-write-policy.d.ts.map +1 -1
  214. package/dist/modules/workspace/routine-write-policy.js +5 -6
  215. package/dist/modules/workspace/routine-write-policy.js.map +1 -1
  216. package/dist/modules/workspace/session-sink.d.ts +5 -5
  217. package/dist/modules/workspace/set-aside-clone.d.ts +46 -0
  218. package/dist/modules/workspace/set-aside-clone.d.ts.map +1 -0
  219. package/dist/modules/workspace/set-aside-clone.js +92 -0
  220. package/dist/modules/workspace/set-aside-clone.js.map +1 -0
  221. package/dist/modules/workspace/startup/kb-startup-runner.d.ts +59 -9
  222. package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
  223. package/dist/modules/workspace/startup/kb-startup-runner.js +65 -24
  224. package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
  225. package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
  226. package/dist/modules/workspace/startup/steps/seed-tree.js +3 -3
  227. package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
  228. package/dist/modules/workspace/startup/steps/template-source.d.ts +40 -0
  229. package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
  230. package/dist/modules/workspace/startup/steps/template-source.js +46 -4
  231. package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
  232. package/dist/modules/workspace/upload-limits.d.ts +13 -0
  233. package/dist/modules/workspace/upload-limits.d.ts.map +1 -0
  234. package/dist/modules/workspace/upload-limits.js +13 -0
  235. package/dist/modules/workspace/upload-limits.js.map +1 -0
  236. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  237. package/dist/modules/workspace/workspace.routes.js +93 -4
  238. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  239. package/dist/modules/workspace/workspace.service.d.ts +128 -5
  240. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  241. package/dist/modules/workspace/workspace.service.js +316 -58
  242. package/dist/modules/workspace/workspace.service.js.map +1 -1
  243. package/dist/modules/workspace/workspace.tools.d.ts +13 -11
  244. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  245. package/dist/modules/workspace/workspace.tools.js +791 -198
  246. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  247. package/dist/modules/workspace/write-denial.d.ts +0 -6
  248. package/dist/modules/workspace/write-denial.d.ts.map +1 -1
  249. package/dist/modules/workspace/write-denial.js +0 -6
  250. package/dist/modules/workspace/write-denial.js.map +1 -1
  251. package/dist/modules/workspace/zip-entry-rules.d.ts +114 -0
  252. package/dist/modules/workspace/zip-entry-rules.d.ts.map +1 -0
  253. package/dist/modules/workspace/zip-entry-rules.js +154 -0
  254. package/dist/modules/workspace/zip-entry-rules.js.map +1 -0
  255. package/dist/modules/write-access/write-access.d.ts +60 -0
  256. package/dist/modules/write-access/write-access.d.ts.map +1 -0
  257. package/dist/modules/write-access/write-access.js +129 -0
  258. package/dist/modules/write-access/write-access.js.map +1 -0
  259. package/dist/shared/column-crypto.d.ts +194 -0
  260. package/dist/shared/column-crypto.d.ts.map +1 -0
  261. package/dist/shared/column-crypto.js +144 -0
  262. package/dist/shared/column-crypto.js.map +1 -0
  263. package/dist/shared/domain-errors.d.ts +25 -0
  264. package/dist/shared/domain-errors.d.ts.map +1 -1
  265. package/dist/shared/domain-errors.js +28 -0
  266. package/dist/shared/domain-errors.js.map +1 -1
  267. package/dist/shared/git.contract.d.ts +20 -0
  268. package/dist/shared/git.contract.d.ts.map +1 -1
  269. package/dist/shared/git.contract.js +26 -0
  270. package/dist/shared/git.contract.js.map +1 -1
  271. package/dist/shared/token-crypto.d.ts.map +1 -1
  272. package/dist/shared/token-crypto.js +25 -1
  273. package/dist/shared/token-crypto.js.map +1 -1
  274. package/dist/tenancy/static-tenant-source.d.ts +0 -1
  275. package/dist/tenancy/static-tenant-source.d.ts.map +1 -1
  276. package/dist/tenancy/static-tenant-source.js +1 -2
  277. package/dist/tenancy/static-tenant-source.js.map +1 -1
  278. package/dist/tenancy/tenant-secrets.d.ts +5 -1
  279. package/dist/tenancy/tenant-secrets.d.ts.map +1 -1
  280. package/dist/tenancy/tenant-secrets.js +4 -0
  281. package/dist/tenancy/tenant-secrets.js.map +1 -1
  282. package/kb-template/AGENTS.md +2 -0
  283. package/migrations/0014_change_request_closed_reason.sql +1 -0
  284. package/migrations/0015_account_deactivation.sql +3 -0
  285. package/migrations/0016_pii_encryption.sql +20 -0
  286. package/migrations/meta/0014_snapshot.json +2265 -0
  287. package/migrations/meta/0015_snapshot.json +2271 -0
  288. package/migrations/meta/0016_snapshot.json +2327 -0
  289. package/migrations/meta/_journal.json +21 -0
  290. package/package.json +3 -3
  291. package/src/__tests__/kb-layout-config.test.ts +0 -2
  292. package/src/__tests__/retired-settings.test.ts +96 -0
  293. package/src/core/__tests__/gated-boot.test.ts +132 -0
  294. package/src/core/__tests__/lifecycle.test.ts +241 -5
  295. package/src/core/__tests__/set-aside-root-is-one-place.test.ts +63 -0
  296. package/src/core/core-ports.ts +11 -1
  297. package/src/core/create-core-server.ts +52 -16
  298. package/src/core/create-core-services.ts +156 -24
  299. package/src/core/lifecycle.ts +117 -13
  300. package/src/core-config.ts +31 -14
  301. package/src/index.ts +30 -1
  302. package/src/modules/access/__tests__/access-control.preview-relocation.test.ts +385 -0
  303. package/src/modules/access/__tests__/access-control.prospective.test.ts +94 -18
  304. package/src/modules/access/__tests__/access.routes.prospective.test.ts +6 -7
  305. package/src/modules/access/__tests__/users-db-double.ts +21 -12
  306. package/src/modules/access/access-control.interface.ts +43 -12
  307. package/src/modules/access/access-control.service.ts +234 -36
  308. package/src/modules/access/access.routes.ts +17 -16
  309. package/src/modules/access/directory-sync-bot.ts +7 -3
  310. package/src/modules/agent-instructions/__tests__/agent-instructions.route.test.ts +11 -5
  311. package/src/modules/agent-instructions/__tests__/compose.test.ts +19 -10
  312. package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +238 -0
  313. package/src/modules/agent-instructions/agent-instructions.routes.ts +12 -2
  314. package/src/modules/agent-instructions/compose.ts +50 -7
  315. package/src/modules/agent-instructions/index.ts +12 -0
  316. package/src/modules/agent-instructions/shared-file-rules.ts +314 -0
  317. package/src/modules/audit/agent-audit.service.ts +4 -2
  318. package/src/modules/auth/__tests__/account-deactivation.test.ts +253 -0
  319. package/src/modules/auth/__tests__/account-erasure.approval-gate.test.ts +6 -2
  320. package/src/modules/auth/__tests__/account.routes.test.ts +87 -6
  321. package/src/modules/auth/__tests__/auth.middleware.test.ts +45 -22
  322. package/src/modules/auth/__tests__/auth.service.test.ts +4 -2
  323. package/src/modules/auth/account-admission.ts +78 -9
  324. package/src/modules/auth/account-erasure.service.ts +69 -18
  325. package/src/modules/auth/account.routes.ts +63 -7
  326. package/src/modules/auth/auth.middleware.ts +19 -8
  327. package/src/modules/auth/auth.routes.ts +8 -0
  328. package/src/modules/auth/auth.service.ts +206 -23
  329. package/src/modules/auth/oidc-auth-provider.ts +7 -2
  330. package/src/modules/code-mode/__tests__/chain-runtime.e2e.test.ts +335 -0
  331. package/src/modules/code-mode/__tests__/code-mode.tool.test.ts +46 -2
  332. package/src/modules/code-mode/code-mode.tool.ts +80 -34
  333. package/src/modules/database/__tests__/connection.test.ts +12 -0
  334. package/src/modules/database/__tests__/pii-backfill.pg.test.ts +561 -0
  335. package/src/modules/database/connection.ts +117 -0
  336. package/src/modules/database/core-schema.ts +116 -58
  337. package/src/modules/database/migrate.ts +353 -1
  338. package/src/modules/kb-fs/__tests__/branch-name.test.ts +10 -0
  339. package/src/modules/kb-fs/__tests__/repo-path.test.ts +123 -0
  340. package/src/modules/kb-fs/branch-name.ts +14 -1
  341. package/src/modules/kb-fs/repo-path.ts +85 -0
  342. package/src/modules/kb-sync/__tests__/kb-sync.routes.test.ts +26 -1
  343. package/src/modules/kb-sync/kb-sync.routes.ts +14 -4
  344. package/src/modules/kb-sync/sync-auth.ts +2 -2
  345. package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +60 -3
  346. package/src/modules/mcp/__tests__/mcp.e2e.test.ts +4 -3
  347. package/src/modules/mcp/__tests__/mcp.service.test.ts +115 -13
  348. package/src/modules/mcp/mcp-auth.middleware.ts +20 -6
  349. package/src/modules/mcp/mcp.service.ts +46 -7
  350. package/src/modules/mcp/oauth/bevel-oauth-provider.ts +3 -1
  351. package/src/modules/plugins/__tests__/plugins.tools.test.ts +2 -1
  352. package/src/modules/plugins/join-request-records.store.ts +7 -4
  353. package/src/modules/settings/__tests__/deployment-settings.service.test.ts +16 -0
  354. package/src/modules/settings/__tests__/setup.routes.git-mode.test.ts +91 -58
  355. package/src/modules/settings/__tests__/setup.routes.github-app.test.ts +25 -8
  356. package/src/modules/settings/__tests__/setup.routes.managed-phase.test.ts +14 -11
  357. package/src/modules/settings/__tests__/setup.routes.repository-change.test.ts +390 -0
  358. package/src/modules/settings/__tests__/setup.routes.test.ts +3 -0
  359. package/src/modules/settings/deployment-settings.service.ts +8 -3
  360. package/src/modules/settings/setup.routes.ts +263 -19
  361. package/src/modules/skills/__tests__/allowed-tools-warn.tools.test.ts +2 -1
  362. package/src/modules/skills/__tests__/branch-skills.tools.test.ts +218 -0
  363. package/src/modules/skills/__tests__/skills.service.test.ts +229 -5
  364. package/src/modules/skills/skills.contract.ts +91 -18
  365. package/src/modules/skills/skills.service.ts +278 -41
  366. package/src/modules/skills/skills.tools.ts +80 -8
  367. package/src/modules/tool-auth/__tests__/manual-auth.middleware.test.ts +14 -1
  368. package/src/modules/tool-auth/external-api-key.service.ts +12 -4
  369. package/src/modules/tool-auth/internal-token.service.ts +3 -3
  370. package/src/modules/tool-auth/tool-auth.middleware.ts +34 -11
  371. package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +5 -3
  372. package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +3 -3
  373. package/src/modules/tool-helpers/__tests__/validate-token.test.ts +11 -1
  374. package/src/modules/tool-helpers/tool-handler.ts +24 -4
  375. package/src/modules/tool-helpers/tool.contract.ts +3 -2
  376. package/src/modules/tool-helpers/validate-token.ts +1 -1
  377. package/src/modules/tool-manuals/tool-manuals.tools.ts +44 -31
  378. package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +378 -0
  379. package/src/modules/tool-registry/description-length.ts +111 -0
  380. package/src/modules/workflow/__tests__/pending-commits.repository-replaced.test.ts +111 -0
  381. package/src/modules/workflow/__tests__/workflow.routes.history-read-gate.test.ts +25 -0
  382. package/src/modules/workflow/__tests__/workflow.service.repository-replaced.test.ts +249 -0
  383. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +264 -6
  384. package/src/modules/workflow/agent-tools/change-request-summary.ts +182 -0
  385. package/src/modules/workflow/agent-tools/workflow.tools.ts +86 -35
  386. package/src/modules/workflow/file-lock.service.ts +31 -0
  387. package/src/modules/workflow/git/__tests__/git.service.fileBytesAtCommit.test.ts +260 -0
  388. package/src/modules/workflow/git/__tests__/git.service.prFetchFailure.test.ts +170 -0
  389. package/src/modules/workflow/git/git.service.ts +215 -1
  390. package/src/modules/workflow/pending-commits.service.ts +64 -2
  391. package/src/modules/workflow/recovery-bot.ts +7 -3
  392. package/src/modules/workflow/review-workflow/__tests__/carry-approvals-forward.test.ts +4 -0
  393. package/src/modules/workflow/review-workflow/__tests__/erase-approver.test.ts +25 -3
  394. package/src/modules/workflow/review-workflow/review-workflow.service.ts +12 -3
  395. package/src/modules/workflow/workflow-hooks.ts +64 -26
  396. package/src/modules/workflow/workflow.service.ts +125 -5
  397. package/src/modules/workspace/__tests__/agent-access.gate.test.ts +208 -0
  398. package/src/modules/workspace/__tests__/agent-uploads.test.ts +1604 -0
  399. package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +394 -0
  400. package/src/modules/workspace/__tests__/file-stat-access.test.ts +2 -1
  401. package/src/modules/workspace/__tests__/git-internals.security.test.ts +2 -1
  402. package/src/modules/workspace/__tests__/set-aside-clone.test.ts +52 -0
  403. package/src/modules/workspace/__tests__/workspace.routes.at-ref.test.ts +305 -0
  404. package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +2 -0
  405. package/src/modules/workspace/__tests__/workspace.service.any-workspace-credentials.test.ts +156 -0
  406. package/src/modules/workspace/__tests__/workspace.service.forget-clone-races.test.ts +147 -0
  407. package/src/modules/workspace/__tests__/workspace.service.replaced-repository.test.ts +402 -0
  408. package/src/modules/workspace/__tests__/workspace.service.test.ts +77 -9
  409. package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +41 -39
  410. package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +2 -3
  411. package/src/modules/workspace/__tests__/workspace.tools.test.ts +766 -56
  412. package/src/modules/workspace/agent-access.gate.ts +164 -0
  413. package/src/modules/workspace/agent-upload.routes.ts +214 -0
  414. package/src/modules/workspace/agent-upload.store.ts +668 -0
  415. package/src/modules/workspace/routine-write-policy.ts +5 -6
  416. package/src/modules/workspace/session-sink.ts +5 -5
  417. package/src/modules/workspace/set-aside-clone.ts +96 -0
  418. package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +86 -0
  419. package/src/modules/workspace/startup/kb-startup-runner.ts +115 -34
  420. package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +9 -9
  421. package/src/modules/workspace/startup/steps/seed-tree.ts +3 -6
  422. package/src/modules/workspace/startup/steps/template-source.ts +53 -5
  423. package/src/modules/workspace/upload-limits.ts +12 -0
  424. package/src/modules/workspace/workspace.routes.ts +96 -5
  425. package/src/modules/workspace/workspace.service.ts +319 -61
  426. package/src/modules/workspace/workspace.tools.ts +894 -214
  427. package/src/modules/workspace/write-denial.ts +0 -8
  428. package/src/modules/workspace/zip-entry-rules.ts +173 -0
  429. package/src/modules/write-access/__tests__/write-access.test.ts +248 -0
  430. package/src/modules/write-access/write-access.ts +153 -0
  431. package/src/shared/__tests__/column-crypto.test.ts +217 -0
  432. package/src/shared/column-crypto.ts +218 -0
  433. package/src/shared/domain-errors.ts +31 -0
  434. package/src/shared/git.contract.ts +27 -0
  435. package/src/shared/token-crypto.ts +28 -1
  436. package/src/tenancy/__tests__/static-tenant-source.test.ts +4 -1
  437. package/src/tenancy/static-tenant-source.ts +1 -3
  438. package/src/tenancy/tenant-secrets.ts +5 -1
  439. package/dist/modules/workflow/session-ontology.policy.d.ts +0 -52
  440. package/dist/modules/workflow/session-ontology.policy.d.ts.map +0 -1
  441. package/dist/modules/workflow/session-ontology.policy.js +0 -62
  442. package/dist/modules/workflow/session-ontology.policy.js.map +0 -1
  443. package/dist/modules/workflow/session-ontology.service.d.ts +0 -105
  444. package/dist/modules/workflow/session-ontology.service.d.ts.map +0 -1
  445. package/dist/modules/workflow/session-ontology.service.js +0 -147
  446. package/dist/modules/workflow/session-ontology.service.js.map +0 -1
  447. package/dist/modules/workspace/session-ontology.gate.d.ts +0 -114
  448. package/dist/modules/workspace/session-ontology.gate.d.ts.map +0 -1
  449. package/dist/modules/workspace/session-ontology.gate.js +0 -161
  450. package/dist/modules/workspace/session-ontology.gate.js.map +0 -1
  451. package/dist/shared/kb-layout.d.ts +0 -39
  452. package/dist/shared/kb-layout.d.ts.map +0 -1
  453. package/dist/shared/kb-layout.js +0 -103
  454. package/dist/shared/kb-layout.js.map +0 -1
  455. package/dist/shared/kb-layout.test.d.ts +0 -2
  456. package/dist/shared/kb-layout.test.d.ts.map +0 -1
  457. package/dist/shared/kb-layout.test.js +0 -75
  458. package/dist/shared/kb-layout.test.js.map +0 -1
  459. package/src/modules/workflow/__tests__/session-ontology.policy.test.ts +0 -62
  460. package/src/modules/workflow/__tests__/session-ontology.service.test.ts +0 -201
  461. package/src/modules/workflow/session-ontology.policy.ts +0 -70
  462. package/src/modules/workflow/session-ontology.service.ts +0 -183
  463. package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +0 -239
  464. package/src/modules/workspace/session-ontology.gate.ts +0 -191
  465. package/src/shared/kb-layout.test.ts +0 -98
  466. package/src/shared/kb-layout.ts +0 -102
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Agent access gate — the per-call seam every gated agent tool runs through.
3
+ *
4
+ * It decides nothing of its own. It calls the hooks a DEPLOYMENT registered
5
+ * (`WorkflowHooks`): one before an agent read of a knowledge-base path, one
6
+ * before an agent write. A hook that throws refuses the operation and the
7
+ * caller sees that hook's own message and status. With no hook registered —
8
+ * every core-only deployment — nothing is refused and nothing is recorded, and
9
+ * a call that carries no `sessionId` is an ordinary call.
10
+ *
11
+ * The gate owns exactly two skips, and they are the ones core can decide on
12
+ * its own identity model: the caller is not an agent (a person in the app, a
13
+ * browser JWT), or the caller is the recovery/merge bot. Everything else —
14
+ * which paths matter, whether a session id is required, what the refusal says
15
+ * — belongs to the hook.
16
+ *
17
+ * Lives beside `assertCanRead` in the workspace tools; it does NOT touch
18
+ * `acquireLock` (that gate is protected-branch-only, and this one applies on
19
+ * all branches and to reads).
20
+ */
21
+ import type { JsonSchema } from '../tool-registry/tool.contract.js';
22
+ import type { ToolContext } from '../tool-helpers/tool.contract.js';
23
+ import type { WorkflowHooks } from '../workflow/workflow-hooks.js';
24
+ /**
25
+ * What the `sessionId` input says on its own, before any deployment note. The
26
+ * id is the CONVERSATION's id: the in-process agent supplies its thread id
27
+ * automatically (via its per-run internal token), and an external agent mints
28
+ * one with `start_session` and passes it explicitly, because the MCP proxy is
29
+ * a pure passthrough and never injects args. The same id is the one `ask`
30
+ * takes, so a run's reads and its questions share one conversation.
31
+ */
32
+ export declare const SESSION_ID_DESCRIPTION = "This conversation's id, so the server can tell one run's calls apart. External agents (direct MCP calls and `call_tool_chain` alike): call the `start_session` tool ONCE at the very start of your work to obtain it, then pass that id here \u2014 the same id `ask` takes. The in-process agent runtime supplies this automatically (do not set it yourself).";
33
+ /**
34
+ * The `sessionId` input every gated tool declares. The description a MOUNTED
35
+ * tool ends up advertising is {@link ToolDescriptionNotes.sessionIdDescription},
36
+ * which appends whatever note the deployment registered; this constant is the
37
+ * unadorned default the notes are applied on top of.
38
+ */
39
+ export declare const SESSION_ID_INPUT: JsonSchema;
40
+ /**
41
+ * The registration point for the wording a DEPLOYMENT wants agents to read
42
+ * about the gated tools — the counterpart of the hooks, which carry its rule.
43
+ * A deployment that refuses some calls can say so here; core registers
44
+ * nothing, so a core-only deployment advertises the plain descriptions.
45
+ *
46
+ * Registration may land AFTER the tools are mounted (an overlay registers from
47
+ * the tool-surface hook), so mounted tools subscribe with {@link onChange} and
48
+ * rewrite their own description and `sessionId` input when a note arrives.
49
+ */
50
+ export declare class ToolDescriptionNotes {
51
+ private gatedTool;
52
+ private sessionId;
53
+ private readonly listeners;
54
+ /** Append `note` to the description of every gated tool. */
55
+ registerGatedToolNote(note: string): void;
56
+ /** Append `note` to the description of the `sessionId` input. */
57
+ registerSessionIdNote(note: string): void;
58
+ /** The registered gated-tool note, `''` when none is registered. */
59
+ gatedToolNote(): string;
60
+ /** The `sessionId` input's description, with any registered note appended. */
61
+ sessionIdDescription(): string;
62
+ /** Re-run `listener` whenever a note is registered (mounted tools re-describe). */
63
+ onChange(listener: () => void): void;
64
+ private announce;
65
+ }
66
+ /** The per-deployment configuration the gate needs, built once in the composition root. */
67
+ export interface AgentAccessGate {
68
+ /** Lowercased email of the recovery/merge bot, which never reaches the hooks. */
69
+ recoveryBotEmail: string;
70
+ /**
71
+ * The workflow lifecycle-hook registry holding the BLOCKING `agentRead` and
72
+ * `preWrite` hooks. Core registers none; a deployment registers against
73
+ * `workflowService.hooks` — pass that same instance here.
74
+ */
75
+ hooks: WorkflowHooks;
76
+ /** The notes a deployment adds to what agents read about these tools. */
77
+ notes: ToolDescriptionNotes;
78
+ }
79
+ /**
80
+ * Tell the registered read hooks about an agent read of `wsPath`. A hook that
81
+ * throws refuses the read with its own message and status; with none
82
+ * registered this is a no-op.
83
+ */
84
+ export declare function notifyAgentRead(gate: AgentAccessGate, ctx: ToolContext, branch: string, wsPath: string): Promise<void>;
85
+ /**
86
+ * Ask the registered write hooks whether an agent write may proceed. A hook
87
+ * that throws refuses it with its own message and status; with none registered
88
+ * this is a no-op.
89
+ *
90
+ * `wsPath` is omitted by the one write-capable tool with no resolvable target,
91
+ * `execute_command` — the hook then decides at the coarser session level.
92
+ */
93
+ export declare function assertAgentWriteAllowed(gate: AgentAccessGate, ctx: ToolContext, branch: string, wsPath?: string): Promise<void>;
94
+ //# sourceMappingURL=agent-access.gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-access.gate.d.ts","sourceRoot":"","sources":["../../../src/modules/workspace/agent-access.gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAEnE;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,oWAC2T,CAAC;AAE/V;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,UAG9B,CAAC;AAEF;;;;;;;;;GASG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IAEnD,4DAA4D;IAC5D,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKzC,iEAAiE;IACjE,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKzC,oEAAoE;IACpE,aAAa,IAAI,MAAM;IAIvB,8EAA8E;IAC9E,oBAAoB,IAAI,MAAM;IAI9B,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAIpC,OAAO,CAAC,QAAQ;CAGjB;AAED,2FAA2F;AAC3F,MAAM,WAAW,eAAe;IAC9B,iFAAiF;IACjF,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,KAAK,EAAE,aAAa,CAAC;IACrB,yEAAyE;IACzE,KAAK,EAAE,oBAAoB,CAAC;CAC7B;AAwBD;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,eAAe,EACrB,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,eAAe,EACrB,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAIf"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Agent access gate — the per-call seam every gated agent tool runs through.
3
+ *
4
+ * It decides nothing of its own. It calls the hooks a DEPLOYMENT registered
5
+ * (`WorkflowHooks`): one before an agent read of a knowledge-base path, one
6
+ * before an agent write. A hook that throws refuses the operation and the
7
+ * caller sees that hook's own message and status. With no hook registered —
8
+ * every core-only deployment — nothing is refused and nothing is recorded, and
9
+ * a call that carries no `sessionId` is an ordinary call.
10
+ *
11
+ * The gate owns exactly two skips, and they are the ones core can decide on
12
+ * its own identity model: the caller is not an agent (a person in the app, a
13
+ * browser JWT), or the caller is the recovery/merge bot. Everything else —
14
+ * which paths matter, whether a session id is required, what the refusal says
15
+ * — belongs to the hook.
16
+ *
17
+ * Lives beside `assertCanRead` in the workspace tools; it does NOT touch
18
+ * `acquireLock` (that gate is protected-branch-only, and this one applies on
19
+ * all branches and to reads).
20
+ */
21
+ /**
22
+ * What the `sessionId` input says on its own, before any deployment note. The
23
+ * id is the CONVERSATION's id: the in-process agent supplies its thread id
24
+ * automatically (via its per-run internal token), and an external agent mints
25
+ * one with `start_session` and passes it explicitly, because the MCP proxy is
26
+ * a pure passthrough and never injects args. The same id is the one `ask`
27
+ * takes, so a run's reads and its questions share one conversation.
28
+ */
29
+ export const SESSION_ID_DESCRIPTION = "This conversation's id, so the server can tell one run's calls apart. External agents (direct MCP calls and `call_tool_chain` alike): call the `start_session` tool ONCE at the very start of your work to obtain it, then pass that id here — the same id `ask` takes. The in-process agent runtime supplies this automatically (do not set it yourself).";
30
+ /**
31
+ * The `sessionId` input every gated tool declares. The description a MOUNTED
32
+ * tool ends up advertising is {@link ToolDescriptionNotes.sessionIdDescription},
33
+ * which appends whatever note the deployment registered; this constant is the
34
+ * unadorned default the notes are applied on top of.
35
+ */
36
+ export const SESSION_ID_INPUT = {
37
+ type: 'string',
38
+ description: SESSION_ID_DESCRIPTION,
39
+ };
40
+ /**
41
+ * The registration point for the wording a DEPLOYMENT wants agents to read
42
+ * about the gated tools — the counterpart of the hooks, which carry its rule.
43
+ * A deployment that refuses some calls can say so here; core registers
44
+ * nothing, so a core-only deployment advertises the plain descriptions.
45
+ *
46
+ * Registration may land AFTER the tools are mounted (an overlay registers from
47
+ * the tool-surface hook), so mounted tools subscribe with {@link onChange} and
48
+ * rewrite their own description and `sessionId` input when a note arrives.
49
+ */
50
+ export class ToolDescriptionNotes {
51
+ gatedTool = '';
52
+ sessionId = '';
53
+ listeners = new Set();
54
+ /** Append `note` to the description of every gated tool. */
55
+ registerGatedToolNote(note) {
56
+ this.gatedTool = note;
57
+ this.announce();
58
+ }
59
+ /** Append `note` to the description of the `sessionId` input. */
60
+ registerSessionIdNote(note) {
61
+ this.sessionId = note;
62
+ this.announce();
63
+ }
64
+ /** The registered gated-tool note, `''` when none is registered. */
65
+ gatedToolNote() {
66
+ return this.gatedTool;
67
+ }
68
+ /** The `sessionId` input's description, with any registered note appended. */
69
+ sessionIdDescription() {
70
+ return SESSION_ID_DESCRIPTION + this.sessionId;
71
+ }
72
+ /** Re-run `listener` whenever a note is registered (mounted tools re-describe). */
73
+ onChange(listener) {
74
+ this.listeners.add(listener);
75
+ }
76
+ announce() {
77
+ for (const listener of this.listeners)
78
+ listener();
79
+ }
80
+ }
81
+ /** Only agent callers are gated; `session` (browser JWT) and humans are not. */
82
+ function agentSourceOf(ctx) {
83
+ return ctx.source === 'internal' || ctx.source === 'external' ? ctx.source : null;
84
+ }
85
+ /**
86
+ * The hook context for this call, or `null` when the call never reaches a hook:
87
+ * the caller is a person rather than an agent, or is the recovery/merge bot,
88
+ * which legitimately spans everything.
89
+ */
90
+ function operationContext(gate, ctx, branch, wsPath) {
91
+ const source = agentSourceOf(ctx);
92
+ if (source === null)
93
+ return null;
94
+ if (ctx.user.email.toLowerCase() === gate.recoveryBotEmail)
95
+ return null;
96
+ return { sessionId: ctx.sessionId, wsPath, branch, user: ctx.user, source };
97
+ }
98
+ /**
99
+ * Tell the registered read hooks about an agent read of `wsPath`. A hook that
100
+ * throws refuses the read with its own message and status; with none
101
+ * registered this is a no-op.
102
+ */
103
+ export async function notifyAgentRead(gate, ctx, branch, wsPath) {
104
+ const op = operationContext(gate, ctx, branch, wsPath);
105
+ if (op === null)
106
+ return;
107
+ await gate.hooks.runAgentRead(op);
108
+ }
109
+ /**
110
+ * Ask the registered write hooks whether an agent write may proceed. A hook
111
+ * that throws refuses it with its own message and status; with none registered
112
+ * this is a no-op.
113
+ *
114
+ * `wsPath` is omitted by the one write-capable tool with no resolvable target,
115
+ * `execute_command` — the hook then decides at the coarser session level.
116
+ */
117
+ export async function assertAgentWriteAllowed(gate, ctx, branch, wsPath) {
118
+ const op = operationContext(gate, ctx, branch, wsPath);
119
+ if (op === null)
120
+ return;
121
+ await gate.hooks.runPreWrite(op);
122
+ }
123
+ //# sourceMappingURL=agent-access.gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-access.gate.js","sourceRoot":"","sources":["../../../src/modules/workspace/agent-access.gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,sBAAsB,GACjC,4VAA4V,CAAC;AAE/V;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAe;IAC1C,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,sBAAsB;CACpC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,OAAO,oBAAoB;IACvB,SAAS,GAAG,EAAE,CAAC;IACf,SAAS,GAAG,EAAE,CAAC;IACN,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IAEnD,4DAA4D;IAC5D,qBAAqB,CAAC,IAAY;QAChC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,QAAQ,EAAE,CAAC;IAClB,CAAC;IAED,iEAAiE;IACjE,qBAAqB,CAAC,IAAY;QAChC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,QAAQ,EAAE,CAAC;IAClB,CAAC;IAED,oEAAoE;IACpE,aAAa;QACX,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,8EAA8E;IAC9E,oBAAoB;QAClB,OAAO,sBAAsB,GAAG,IAAI,CAAC,SAAS,CAAC;IACjD,CAAC;IAED,mFAAmF;IACnF,QAAQ,CAAC,QAAoB;QAC3B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAEO,QAAQ;QACd,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS;YAAE,QAAQ,EAAE,CAAC;IACpD,CAAC;CACF;AAgBD,gFAAgF;AAChF,SAAS,aAAa,CAAC,GAAgB;IACrC,OAAO,GAAG,CAAC,MAAM,KAAK,UAAU,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACpF,CAAC;AAED;;;;GAIG;AACH,SAAS,gBAAgB,CACvB,IAAqB,EACrB,GAAgB,EAChB,MAAc,EACd,MAAe;IAEf,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjC,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,gBAAgB;QAAE,OAAO,IAAI,CAAC;IACxE,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;AAC9E,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAqB,EACrB,GAAgB,EAChB,MAAc,EACd,MAAc;IAEd,MAAM,EAAE,GAAG,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACvD,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO;IACxB,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,IAAqB,EACrB,GAAgB,EAChB,MAAc,EACd,MAAe;IAEf,MAAM,EAAE,GAAG,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACvD,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO;IACxB,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,77 @@
1
+ import express from 'express';
2
+ import { AgentUploadStore } from './agent-upload.store.js';
3
+ /** The route's own prefix, under `/api`. One spelling, shared with the raw-body test below. */
4
+ export declare const AGENT_UPLOAD_ROUTE = "/agent/uploads/:token";
5
+ /**
6
+ * The same endpoint with the token in the `x-upload-token` HEADER instead of
7
+ * the path — the address `uploadUrl` is, without its last segment.
8
+ *
9
+ * Two spellings because a token in a URL is a credential in a place that keeps
10
+ * copies: an access log, a proxy log, a shell history, a `ps` listing of the
11
+ * `curl` that sent it. The path form is what `request_file_upload` answers,
12
+ * because one address an agent can paste into any client is the thing that
13
+ * makes this route usable at all; the header form is for a caller that would
14
+ * rather its credential not be written down on the way. Both reach the same
15
+ * handler and are judged identically — same token, same single use.
16
+ */
17
+ export declare const AGENT_UPLOAD_HEADER_ROUTE = "/agent/uploads";
18
+ /**
19
+ * Whether `path` is the agent upload route, and so must reach its handler with
20
+ * the body still a STREAM.
21
+ *
22
+ * The app installs a global `express.json()`. It only claims a JSON
23
+ * content-type, but `curl --data-binary @file.zip -H 'content-type:
24
+ * application/json'` is a request an agent can and will make — and once the
25
+ * parser has drained the stream there are no bytes left to store, so the
26
+ * upload would answer "0 bytes received" for a file that was sent in full.
27
+ * Exempting the path is the same move `/api/sync` makes for its HMAC body, and
28
+ * for the same reason: whoever needs the exact bytes has to see them first.
29
+ *
30
+ * Case-insensitive, because Express routing is: `/api/Agent/uploads/x` reaches
31
+ * this router, and a check that said no would let the parser eat that body.
32
+ */
33
+ export declare function isAgentUploadRawBodyPath(path: string): boolean;
34
+ export interface AgentUploadRouteDeps {
35
+ uploads: AgentUploadStore;
36
+ }
37
+ /**
38
+ * `POST /api/agent/uploads/:token` — the one endpoint on this server
39
+ * authenticated by a single-use token and nothing else.
40
+ *
41
+ * It exists because MCP tool arguments are JSON, so every byte an agent sends
42
+ * through a tool passes through the model first. A 37 KB page gets truncated
43
+ * mid-response; a file of regex backslashes fails to parse as a JSON string; a
44
+ * PNG cannot be sent at all. Here the agent asks for a token, sends the file
45
+ * with any HTTP client it has, and then names the token in
46
+ * `apply_file_upload`. The bytes never enter a prompt.
47
+ *
48
+ * What the route itself may do is deliberately almost nothing: it stores bytes
49
+ * against a token, in a directory beside the workspaces root, and answers what
50
+ * it received. It resolves no workspace, writes nothing into one, and commits
51
+ * nothing — every access, platform-file and branch rule is applied later, by
52
+ * the apply tool, against the branch the caller then names. A token that is
53
+ * unknown, spent, expired or someone else's gets one 404 that says which of
54
+ * those it was: none of them.
55
+ */
56
+ export declare function createAgentUploadRoutes(deps: AgentUploadRouteDeps): express.Router;
57
+ /**
58
+ * The `filename` a `content-disposition` names, or null when it names none.
59
+ *
60
+ * A QUOTED value is read to its closing quote, not to the first semicolon: a
61
+ * semicolon separates the header's parameters only OUTSIDE the quotes, and
62
+ * `filename="report;final.md"` is one perfectly ordinary name that a
63
+ * semicolon-first reading landed as `report`. An unquoted value ends at the
64
+ * next parameter, as it must.
65
+ *
66
+ * Percent-decoded only in the extended `filename*=UTF-8''…` form, which is the
67
+ * only one where the encoding is part of the grammar. A plain `filename=` value
68
+ * is the name itself, so `50%20off.md` stays `50%20off.md` rather than losing
69
+ * its `%20` to a decode nobody asked for.
70
+ *
71
+ * The parameter name is matched at a boundary — the start of the header or a
72
+ * `;` — because `filename` is a suffix of other perfectly legal parameter
73
+ * names: without it, `inline; xfilename=wrong.md` read `wrong.md` as the name
74
+ * the sender gave, from a parameter that says nothing of the kind.
75
+ */
76
+ export declare function dispositionFilename(disposition: string): string | null;
77
+ //# sourceMappingURL=agent-upload.routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-upload.routes.d.ts","sourceRoot":"","sources":["../../../src/modules/workspace/agent-upload.routes.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAG9B,OAAO,EAAE,gBAAgB,EAA+B,MAAM,yBAAyB,CAAC;AAIxF,+FAA+F;AAC/F,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAE1D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,yBAAyB,mBAAmB,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAO9D;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAmElF;AAwCD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgBtE"}
@@ -0,0 +1,210 @@
1
+ import express from 'express';
2
+ import { validateFilename } from '@bevel-software/platform-shared';
3
+ import { logger } from '../../shared/logging.js';
4
+ import { UploadTokenError, overLimit } from './agent-upload.store.js';
5
+ const log = logger('agent-uploads');
6
+ /** The route's own prefix, under `/api`. One spelling, shared with the raw-body test below. */
7
+ export const AGENT_UPLOAD_ROUTE = '/agent/uploads/:token';
8
+ /**
9
+ * The same endpoint with the token in the `x-upload-token` HEADER instead of
10
+ * the path — the address `uploadUrl` is, without its last segment.
11
+ *
12
+ * Two spellings because a token in a URL is a credential in a place that keeps
13
+ * copies: an access log, a proxy log, a shell history, a `ps` listing of the
14
+ * `curl` that sent it. The path form is what `request_file_upload` answers,
15
+ * because one address an agent can paste into any client is the thing that
16
+ * makes this route usable at all; the header form is for a caller that would
17
+ * rather its credential not be written down on the way. Both reach the same
18
+ * handler and are judged identically — same token, same single use.
19
+ */
20
+ export const AGENT_UPLOAD_HEADER_ROUTE = '/agent/uploads';
21
+ /**
22
+ * Whether `path` is the agent upload route, and so must reach its handler with
23
+ * the body still a STREAM.
24
+ *
25
+ * The app installs a global `express.json()`. It only claims a JSON
26
+ * content-type, but `curl --data-binary @file.zip -H 'content-type:
27
+ * application/json'` is a request an agent can and will make — and once the
28
+ * parser has drained the stream there are no bytes left to store, so the
29
+ * upload would answer "0 bytes received" for a file that was sent in full.
30
+ * Exempting the path is the same move `/api/sync` makes for its HMAC body, and
31
+ * for the same reason: whoever needs the exact bytes has to see them first.
32
+ *
33
+ * Case-insensitive, because Express routing is: `/api/Agent/uploads/x` reaches
34
+ * this router, and a check that said no would let the parser eat that body.
35
+ */
36
+ export function isAgentUploadRawBodyPath(path) {
37
+ // Trailing slashes trimmed first, so the header form's bare address matches
38
+ // in every spelling Express routes to it (`/api/agent/uploads` and
39
+ // `/api/agent/uploads/` are one route): missing one of them would hand that
40
+ // request to the JSON parser, and the bytes it drains are gone.
41
+ const lower = path.toLowerCase().replace(/\/+$/, '');
42
+ return lower === '/api/agent/uploads' || lower.startsWith('/api/agent/uploads/');
43
+ }
44
+ /**
45
+ * `POST /api/agent/uploads/:token` — the one endpoint on this server
46
+ * authenticated by a single-use token and nothing else.
47
+ *
48
+ * It exists because MCP tool arguments are JSON, so every byte an agent sends
49
+ * through a tool passes through the model first. A 37 KB page gets truncated
50
+ * mid-response; a file of regex backslashes fails to parse as a JSON string; a
51
+ * PNG cannot be sent at all. Here the agent asks for a token, sends the file
52
+ * with any HTTP client it has, and then names the token in
53
+ * `apply_file_upload`. The bytes never enter a prompt.
54
+ *
55
+ * What the route itself may do is deliberately almost nothing: it stores bytes
56
+ * against a token, in a directory beside the workspaces root, and answers what
57
+ * it received. It resolves no workspace, writes nothing into one, and commits
58
+ * nothing — every access, platform-file and branch rule is applied later, by
59
+ * the apply tool, against the branch the caller then names. A token that is
60
+ * unknown, spent, expired or someone else's gets one 404 that says which of
61
+ * those it was: none of them.
62
+ */
63
+ export function createAgentUploadRoutes(deps) {
64
+ const router = express.Router();
65
+ const { uploads } = deps;
66
+ const handle = async (req, res) => {
67
+ const token = tokenOf(req);
68
+ try {
69
+ // THE TOKEN FIRST, before anything about the request is read, parsed,
70
+ // judged or quoted back. This route is authenticated by the token and
71
+ // nothing else, which cuts two ways. Without the check up here, anyone
72
+ // could make the process buffer the deployment's whole upload limit per
73
+ // request against tokens they invented, as many at a time as they liked;
74
+ // and a caller holding no token could learn which of its OTHER guesses
75
+ // were well formed — "that is not a usable file name" is an answer only
76
+ // somebody entitled to send a file should get. One refusal, nothing else.
77
+ // `receive` below asks again, under the same record, because that is
78
+ // where the token is actually spent.
79
+ uploads.assertOpen(token);
80
+ const filename = fileNameOf(req);
81
+ if (filename === null) {
82
+ res.status(400).json({
83
+ error: 'Name the file you are sending: add `?filename=<name>` to the upload URL (or send it as the ' +
84
+ '`x-upload-filename` header). A single file lands under that name, and a name ending in `.zip` is ' +
85
+ 'read as an archive.',
86
+ });
87
+ return;
88
+ }
89
+ const invalid = validateFilename(filename);
90
+ if (invalid !== null || filename.includes('/')) {
91
+ res.status(400).json({
92
+ error: `"${filename}" is not a usable file name: ${invalid ?? 'a name cannot contain "/"'}. Send one plain file name.`,
93
+ });
94
+ return;
95
+ }
96
+ // Then the declared length, so a caller sending something far too large
97
+ // is told the limit before it spends the bandwidth. The real total is
98
+ // counted by the store as the bytes arrive — `content-length` is the
99
+ // sender's claim, not a fact.
100
+ const declared = Number.parseInt(req.headers['content-length'] ?? '', 10);
101
+ if (Number.isFinite(declared) && declared > uploads.maxBytes) {
102
+ res.status(413).json({ error: overLimit(declared, uploads.maxBytes) });
103
+ return;
104
+ }
105
+ // The request itself, as a stream: the store writes the bytes to disk as
106
+ // they arrive and never holds the body. It refuses an empty body, one
107
+ // past the limit and an unreadable archive with its own status.
108
+ res.json(await uploads.receive(token, filename, req));
109
+ }
110
+ catch (err) {
111
+ if (err instanceof UploadTokenError) {
112
+ res.status(err.status).json({ error: err.message });
113
+ return;
114
+ }
115
+ // The detail stays in the log. An unexpected failure here is a
116
+ // filesystem error, and its message quotes the absolute path of the
117
+ // store's root — a place the caller is told nothing else about.
118
+ log.error('upload failed:', { err });
119
+ res.status(500).json({ error: 'Upload failed' });
120
+ }
121
+ };
122
+ // Both spellings of the one endpoint: the token in the path, or in the
123
+ // `x-upload-token` header on the bare address.
124
+ router.post(AGENT_UPLOAD_ROUTE, handle);
125
+ router.post(AGENT_UPLOAD_HEADER_ROUTE, handle);
126
+ return router;
127
+ }
128
+ /**
129
+ * The token the sender presented: the `:token` path segment, or the
130
+ * `x-upload-token` header when the bytes went to the bare address.
131
+ *
132
+ * The path wins when both are present — it is the address the sender actually
133
+ * POSTed to, and a header left over from an earlier upload must not quietly
134
+ * redirect these bytes onto a different token.
135
+ *
136
+ * No token at all answers the empty string rather than its own refusal, so it
137
+ * goes through `assertOpen` like any other unusable token and gets the same
138
+ * single 404. A caller holding nothing is told nothing it did not already
139
+ * know — not even whether this endpoint wanted a header.
140
+ */
141
+ function tokenOf(req) {
142
+ const inPath = req.params.token;
143
+ if (typeof inPath === 'string' && inPath.trim() !== '')
144
+ return inPath.trim();
145
+ const header = req.headers['x-upload-token'];
146
+ if (typeof header === 'string' && header.trim() !== '')
147
+ return header.trim();
148
+ return '';
149
+ }
150
+ /**
151
+ * The name the sender gave the file: the `filename` query parameter, the
152
+ * `x-upload-filename` header, or a `content-disposition`'s own `filename=`.
153
+ * Three spellings because three kinds of client are expected to use this —
154
+ * `curl` with a query string, a scripted `fetch` with a header, and a client
155
+ * that sends the disposition it would send to any upload endpoint.
156
+ */
157
+ function fileNameOf(req) {
158
+ const query = req.query.filename;
159
+ if (typeof query === 'string' && query.trim() !== '')
160
+ return query.trim();
161
+ const header = req.headers['x-upload-filename'];
162
+ if (typeof header === 'string' && header.trim() !== '')
163
+ return header.trim();
164
+ const disposition = req.headers['content-disposition'];
165
+ if (typeof disposition === 'string')
166
+ return dispositionFilename(disposition);
167
+ return null;
168
+ }
169
+ /**
170
+ * The `filename` a `content-disposition` names, or null when it names none.
171
+ *
172
+ * A QUOTED value is read to its closing quote, not to the first semicolon: a
173
+ * semicolon separates the header's parameters only OUTSIDE the quotes, and
174
+ * `filename="report;final.md"` is one perfectly ordinary name that a
175
+ * semicolon-first reading landed as `report`. An unquoted value ends at the
176
+ * next parameter, as it must.
177
+ *
178
+ * Percent-decoded only in the extended `filename*=UTF-8''…` form, which is the
179
+ * only one where the encoding is part of the grammar. A plain `filename=` value
180
+ * is the name itself, so `50%20off.md` stays `50%20off.md` rather than losing
181
+ * its `%20` to a decode nobody asked for.
182
+ *
183
+ * The parameter name is matched at a boundary — the start of the header or a
184
+ * `;` — because `filename` is a suffix of other perfectly legal parameter
185
+ * names: without it, `inline; xfilename=wrong.md` read `wrong.md` as the name
186
+ * the sender gave, from a parameter that says nothing of the kind.
187
+ */
188
+ export function dispositionFilename(disposition) {
189
+ const match = /(?:^|;)\s*filename(\*?)\s*=\s*(?:"([^"]*)"|([^;]*))/i.exec(disposition);
190
+ if (!match)
191
+ return null;
192
+ const extended = match[1] === '*';
193
+ const raw = (match[2] ?? match[3] ?? '').trim();
194
+ if (!extended)
195
+ return raw === '' ? null : raw;
196
+ // `UTF-8''name`, or any other charset and language the sender declares.
197
+ const encoded = raw.replace(/^[^']*'[^']*'/, '');
198
+ try {
199
+ const decoded = decodeURIComponent(encoded).trim();
200
+ if (decoded !== '')
201
+ return decoded;
202
+ }
203
+ catch {
204
+ const kept = encoded.trim();
205
+ if (kept !== '')
206
+ return kept;
207
+ }
208
+ return null;
209
+ }
210
+ //# sourceMappingURL=agent-upload.routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-upload.routes.js","sourceRoot":"","sources":["../../../src/modules/workspace/agent-upload.routes.ts"],"names":[],"mappings":"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"}