@bevel-software/platform-core-backend 0.21.0 → 0.23.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 (434) 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 +62 -13
  7. package/dist/core/create-core-server.js.map +1 -1
  8. package/dist/core/create-core-services.d.ts +22 -3
  9. package/dist/core/create-core-services.d.ts.map +1 -1
  10. package/dist/core/create-core-services.js +158 -23
  11. package/dist/core/create-core-services.js.map +1 -1
  12. package/dist/core/lifecycle.d.ts +34 -1
  13. package/dist/core/lifecycle.d.ts.map +1 -1
  14. package/dist/core/lifecycle.js +89 -13
  15. package/dist/core/lifecycle.js.map +1 -1
  16. package/dist/core-config.d.ts +0 -12
  17. package/dist/core-config.d.ts.map +1 -1
  18. package/dist/core-config.js +11 -13
  19. package/dist/core-config.js.map +1 -1
  20. package/dist/index.d.ts +3 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +2 -1
  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-requests.contract.d.ts +75 -0
  31. package/dist/modules/access/access-requests.contract.d.ts.map +1 -0
  32. package/dist/modules/access/access-requests.contract.js +20 -0
  33. package/dist/modules/access/access-requests.contract.js.map +1 -0
  34. package/dist/modules/access/access-requests.routes.d.ts +35 -0
  35. package/dist/modules/access/access-requests.routes.d.ts.map +1 -0
  36. package/dist/modules/access/access-requests.routes.js +237 -0
  37. package/dist/modules/access/access-requests.routes.js.map +1 -0
  38. package/dist/modules/access/access-requests.service.d.ts +123 -0
  39. package/dist/modules/access/access-requests.service.d.ts.map +1 -0
  40. package/dist/modules/access/access-requests.service.js +337 -0
  41. package/dist/modules/access/access-requests.service.js.map +1 -0
  42. package/dist/modules/access/access.routes.d.ts.map +1 -1
  43. package/dist/modules/access/access.routes.js +13 -15
  44. package/dist/modules/access/access.routes.js.map +1 -1
  45. package/dist/modules/access-model/access-grammar.d.ts +12 -0
  46. package/dist/modules/access-model/access-grammar.d.ts.map +1 -1
  47. package/dist/modules/access-model/access-grammar.js +24 -0
  48. package/dist/modules/access-model/access-grammar.js.map +1 -1
  49. package/dist/modules/auth/account-admission.d.ts +58 -7
  50. package/dist/modules/auth/account-admission.d.ts.map +1 -1
  51. package/dist/modules/auth/account-admission.js +44 -1
  52. package/dist/modules/auth/account-admission.js.map +1 -1
  53. package/dist/modules/auth/account.routes.d.ts +1 -1
  54. package/dist/modules/auth/account.routes.d.ts.map +1 -1
  55. package/dist/modules/auth/account.routes.js +61 -5
  56. package/dist/modules/auth/account.routes.js.map +1 -1
  57. package/dist/modules/auth/auth.middleware.d.ts +1 -1
  58. package/dist/modules/auth/auth.middleware.d.ts.map +1 -1
  59. package/dist/modules/auth/auth.middleware.js +18 -7
  60. package/dist/modules/auth/auth.middleware.js.map +1 -1
  61. package/dist/modules/auth/auth.routes.d.ts.map +1 -1
  62. package/dist/modules/auth/auth.routes.js +8 -0
  63. package/dist/modules/auth/auth.routes.js.map +1 -1
  64. package/dist/modules/auth/auth.service.d.ts +96 -3
  65. package/dist/modules/auth/auth.service.d.ts.map +1 -1
  66. package/dist/modules/auth/auth.service.js +187 -9
  67. package/dist/modules/auth/auth.service.js.map +1 -1
  68. package/dist/modules/auth/oidc-auth-provider.d.ts.map +1 -1
  69. package/dist/modules/auth/oidc-auth-provider.js +7 -2
  70. package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
  71. package/dist/modules/database/core-schema.d.ts +41 -24
  72. package/dist/modules/database/core-schema.d.ts.map +1 -1
  73. package/dist/modules/database/core-schema.js +35 -27
  74. package/dist/modules/database/core-schema.js.map +1 -1
  75. package/dist/modules/github-app/github-app.client.d.ts +101 -0
  76. package/dist/modules/github-app/github-app.client.d.ts.map +1 -0
  77. package/dist/modules/github-app/github-app.client.js +222 -0
  78. package/dist/modules/github-app/github-app.client.js.map +1 -0
  79. package/dist/modules/github-app/github-app.connection.d.ts +102 -0
  80. package/dist/modules/github-app/github-app.connection.d.ts.map +1 -0
  81. package/dist/modules/github-app/github-app.connection.js +185 -0
  82. package/dist/modules/github-app/github-app.connection.js.map +1 -0
  83. package/dist/modules/github-app/github-app.routes.d.ts +59 -0
  84. package/dist/modules/github-app/github-app.routes.d.ts.map +1 -0
  85. package/dist/modules/github-app/github-app.routes.js +323 -0
  86. package/dist/modules/github-app/github-app.routes.js.map +1 -0
  87. package/dist/modules/github-app/index.d.ts +4 -0
  88. package/dist/modules/github-app/index.d.ts.map +1 -0
  89. package/dist/modules/github-app/index.js +4 -0
  90. package/dist/modules/github-app/index.js.map +1 -0
  91. package/dist/modules/kb-fs/branch-name.d.ts.map +1 -1
  92. package/dist/modules/kb-fs/branch-name.js +12 -2
  93. package/dist/modules/kb-fs/branch-name.js.map +1 -1
  94. package/dist/modules/kb-fs/remote-url.d.ts +22 -0
  95. package/dist/modules/kb-fs/remote-url.d.ts.map +1 -0
  96. package/dist/modules/kb-fs/remote-url.js +35 -0
  97. package/dist/modules/kb-fs/remote-url.js.map +1 -0
  98. package/dist/modules/kb-fs/repo-path.d.ts +11 -16
  99. package/dist/modules/kb-fs/repo-path.d.ts.map +1 -1
  100. package/dist/modules/kb-fs/repo-path.js +79 -0
  101. package/dist/modules/kb-fs/repo-path.js.map +1 -1
  102. package/dist/modules/kb-sync/kb-sync.routes.d.ts +2 -2
  103. package/dist/modules/kb-sync/kb-sync.routes.d.ts.map +1 -1
  104. package/dist/modules/kb-sync/kb-sync.routes.js +14 -3
  105. package/dist/modules/kb-sync/kb-sync.routes.js.map +1 -1
  106. package/dist/modules/kb-sync/sync-auth.d.ts +3 -1
  107. package/dist/modules/kb-sync/sync-auth.d.ts.map +1 -1
  108. package/dist/modules/kb-sync/sync-auth.js +1 -1
  109. package/dist/modules/kb-sync/sync-auth.js.map +1 -1
  110. package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
  111. package/dist/modules/mcp/mcp-auth.middleware.js +21 -6
  112. package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
  113. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
  114. package/dist/modules/mcp/oauth/bevel-oauth-provider.js +3 -2
  115. package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
  116. package/dist/modules/plugins/join-proposals.d.ts +17 -5
  117. package/dist/modules/plugins/join-proposals.d.ts.map +1 -1
  118. package/dist/modules/plugins/join-proposals.js +76 -22
  119. package/dist/modules/plugins/join-proposals.js.map +1 -1
  120. package/dist/modules/plugins/join-requests.service.d.ts +111 -18
  121. package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
  122. package/dist/modules/plugins/join-requests.service.js +173 -29
  123. package/dist/modules/plugins/join-requests.service.js.map +1 -1
  124. package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
  125. package/dist/modules/plugins/plugins.routes.js +3 -2
  126. package/dist/modules/plugins/plugins.routes.js.map +1 -1
  127. package/dist/modules/settings/deployment-settings.service.d.ts +22 -1
  128. package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
  129. package/dist/modules/settings/deployment-settings.service.js +101 -7
  130. package/dist/modules/settings/deployment-settings.service.js.map +1 -1
  131. package/dist/modules/settings/managed-repository.d.ts +43 -0
  132. package/dist/modules/settings/managed-repository.d.ts.map +1 -0
  133. package/dist/modules/settings/managed-repository.js +60 -0
  134. package/dist/modules/settings/managed-repository.js.map +1 -0
  135. package/dist/modules/settings/repository-source.d.ts +128 -0
  136. package/dist/modules/settings/repository-source.d.ts.map +1 -0
  137. package/dist/modules/settings/repository-source.js +150 -0
  138. package/dist/modules/settings/repository-source.js.map +1 -0
  139. package/dist/modules/settings/setup.routes.d.ts +78 -4
  140. package/dist/modules/settings/setup.routes.d.ts.map +1 -1
  141. package/dist/modules/settings/setup.routes.js +379 -17
  142. package/dist/modules/settings/setup.routes.js.map +1 -1
  143. package/dist/modules/skills/skill-access-requests.routes.d.ts +6 -8
  144. package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -1
  145. package/dist/modules/skills/skill-access-requests.routes.js +24 -63
  146. package/dist/modules/skills/skill-access-requests.routes.js.map +1 -1
  147. package/dist/modules/skills/skills.contract.d.ts +90 -18
  148. package/dist/modules/skills/skills.contract.d.ts.map +1 -1
  149. package/dist/modules/skills/skills.contract.js +4 -1
  150. package/dist/modules/skills/skills.contract.js.map +1 -1
  151. package/dist/modules/skills/skills.service.d.ts +98 -9
  152. package/dist/modules/skills/skills.service.d.ts.map +1 -1
  153. package/dist/modules/skills/skills.service.js +239 -37
  154. package/dist/modules/skills/skills.service.js.map +1 -1
  155. package/dist/modules/skills/skills.tools.d.ts +7 -0
  156. package/dist/modules/skills/skills.tools.d.ts.map +1 -1
  157. package/dist/modules/skills/skills.tools.js +71 -7
  158. package/dist/modules/skills/skills.tools.js.map +1 -1
  159. package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
  160. package/dist/modules/tool-auth/external-api-key.service.js +4 -2
  161. package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
  162. package/dist/modules/tool-auth/internal-token.service.d.ts +3 -3
  163. package/dist/modules/tool-auth/tool-auth.middleware.d.ts +16 -7
  164. package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
  165. package/dist/modules/tool-auth/tool-auth.middleware.js +34 -12
  166. package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
  167. package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -1
  168. package/dist/modules/tool-helpers/tool-context.js +15 -0
  169. package/dist/modules/tool-helpers/tool-context.js.map +1 -1
  170. package/dist/modules/tool-helpers/tool-handler.d.ts +2 -1
  171. package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -1
  172. package/dist/modules/tool-helpers/tool-handler.js +25 -4
  173. package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
  174. package/dist/modules/tool-helpers/tool.contract.d.ts +3 -2
  175. package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
  176. package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
  177. package/dist/modules/tool-helpers/validate-token.js +1 -1
  178. package/dist/modules/tool-helpers/validate-token.js.map +1 -1
  179. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts +98 -0
  180. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts.map +1 -0
  181. package/dist/modules/workflow/agent-tools/change-request-summary.js +81 -0
  182. package/dist/modules/workflow/agent-tools/change-request-summary.js.map +1 -0
  183. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  184. package/dist/modules/workflow/agent-tools/workflow.tools.js +113 -37
  185. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  186. package/dist/modules/workflow/file-lock.service.d.ts +24 -0
  187. package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
  188. package/dist/modules/workflow/file-lock.service.js +30 -0
  189. package/dist/modules/workflow/file-lock.service.js.map +1 -1
  190. package/dist/modules/workflow/git/git.service.d.ts +72 -1
  191. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  192. package/dist/modules/workflow/git/git.service.js +170 -6
  193. package/dist/modules/workflow/git/git.service.js.map +1 -1
  194. package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -1
  195. package/dist/modules/workflow/git/node-git-runner.js +5 -0
  196. package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
  197. package/dist/modules/workflow/git/pull-request.service.d.ts +45 -0
  198. package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
  199. package/dist/modules/workflow/git/pull-request.service.js +99 -0
  200. package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
  201. package/dist/modules/workflow/pending-commits.service.d.ts +38 -0
  202. package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
  203. package/dist/modules/workflow/pending-commits.service.js +55 -0
  204. package/dist/modules/workflow/pending-commits.service.js.map +1 -1
  205. package/dist/modules/workflow/workflow-hooks.d.ts +54 -32
  206. package/dist/modules/workflow/workflow-hooks.d.ts.map +1 -1
  207. package/dist/modules/workflow/workflow-hooks.js +16 -1
  208. package/dist/modules/workflow/workflow-hooks.js.map +1 -1
  209. package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
  210. package/dist/modules/workflow/workflow.routes.js +3 -1
  211. package/dist/modules/workflow/workflow.routes.js.map +1 -1
  212. package/dist/modules/workflow/workflow.service.d.ts +94 -13
  213. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  214. package/dist/modules/workflow/workflow.service.js +258 -51
  215. package/dist/modules/workflow/workflow.service.js.map +1 -1
  216. package/dist/modules/workspace/agent-access.gate.d.ts +94 -0
  217. package/dist/modules/workspace/agent-access.gate.d.ts.map +1 -0
  218. package/dist/modules/workspace/agent-access.gate.js +123 -0
  219. package/dist/modules/workspace/agent-access.gate.js.map +1 -0
  220. package/dist/modules/workspace/routine-write-policy.d.ts +5 -6
  221. package/dist/modules/workspace/routine-write-policy.d.ts.map +1 -1
  222. package/dist/modules/workspace/routine-write-policy.js +5 -6
  223. package/dist/modules/workspace/routine-write-policy.js.map +1 -1
  224. package/dist/modules/workspace/session-sink.d.ts +5 -5
  225. package/dist/modules/workspace/set-aside-clone.d.ts +46 -0
  226. package/dist/modules/workspace/set-aside-clone.d.ts.map +1 -0
  227. package/dist/modules/workspace/set-aside-clone.js +92 -0
  228. package/dist/modules/workspace/set-aside-clone.js.map +1 -0
  229. package/dist/modules/workspace/startup/kb-startup-runner.d.ts +117 -1
  230. package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
  231. package/dist/modules/workspace/startup/kb-startup-runner.js +190 -1
  232. package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
  233. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  234. package/dist/modules/workspace/workspace.routes.js +92 -3
  235. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  236. package/dist/modules/workspace/workspace.service.d.ts +115 -5
  237. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  238. package/dist/modules/workspace/workspace.service.js +272 -26
  239. package/dist/modules/workspace/workspace.service.js.map +1 -1
  240. package/dist/modules/workspace/workspace.tools.d.ts +2 -2
  241. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  242. package/dist/modules/workspace/workspace.tools.js +337 -117
  243. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  244. package/dist/modules/write-access/write-access.d.ts +60 -0
  245. package/dist/modules/write-access/write-access.d.ts.map +1 -0
  246. package/dist/modules/write-access/write-access.js +129 -0
  247. package/dist/modules/write-access/write-access.js.map +1 -0
  248. package/dist/shared/domain-errors.d.ts +64 -0
  249. package/dist/shared/domain-errors.d.ts.map +1 -1
  250. package/dist/shared/domain-errors.js +83 -0
  251. package/dist/shared/domain-errors.js.map +1 -1
  252. package/dist/shared/git.contract.d.ts +30 -0
  253. package/dist/shared/git.contract.d.ts.map +1 -1
  254. package/dist/shared/git.contract.js +26 -0
  255. package/dist/shared/git.contract.js.map +1 -1
  256. package/dist/tenancy/static-tenant-source.d.ts +0 -1
  257. package/dist/tenancy/static-tenant-source.d.ts.map +1 -1
  258. package/dist/tenancy/static-tenant-source.js +0 -2
  259. package/dist/tenancy/static-tenant-source.js.map +1 -1
  260. package/migrations/0014_change_request_closed_reason.sql +1 -0
  261. package/migrations/0015_account_deactivation.sql +3 -0
  262. package/migrations/meta/0014_snapshot.json +2265 -0
  263. package/migrations/meta/0015_snapshot.json +2271 -0
  264. package/migrations/meta/_journal.json +14 -0
  265. package/package.json +3 -3
  266. package/src/__tests__/kb-layout-config.test.ts +0 -2
  267. package/src/__tests__/retired-settings.test.ts +96 -0
  268. package/src/core/__tests__/gated-boot.test.ts +132 -0
  269. package/src/core/__tests__/lifecycle.test.ts +170 -1
  270. package/src/core/__tests__/set-aside-root-is-one-place.test.ts +63 -0
  271. package/src/core/core-ports.ts +11 -1
  272. package/src/core/create-core-server.ts +69 -15
  273. package/src/core/create-core-services.ts +190 -27
  274. package/src/core/lifecycle.ts +98 -13
  275. package/src/core-config.ts +13 -14
  276. package/src/index.ts +12 -1
  277. package/src/modules/access/__tests__/access-control.preview-relocation.test.ts +385 -0
  278. package/src/modules/access/__tests__/access-control.prospective.test.ts +94 -18
  279. package/src/modules/access/__tests__/access-requests.recut.test.ts +134 -0
  280. package/src/modules/access/__tests__/access-requests.routes.test.ts +610 -0
  281. package/src/modules/access/__tests__/access.routes.prospective.test.ts +6 -7
  282. package/src/modules/access/access-control.interface.ts +43 -12
  283. package/src/modules/access/access-control.service.ts +234 -36
  284. package/src/modules/access/access-requests.contract.ts +93 -0
  285. package/src/modules/access/access-requests.routes.ts +286 -0
  286. package/src/modules/access/access-requests.service.ts +420 -0
  287. package/src/modules/access/access.routes.ts +13 -15
  288. package/src/modules/access-model/access-grammar.ts +22 -0
  289. package/src/modules/agent-instructions/__tests__/agent-instructions.route.test.ts +3 -1
  290. package/src/modules/auth/__tests__/account-deactivation.test.ts +252 -0
  291. package/src/modules/auth/__tests__/account.routes.test.ts +81 -3
  292. package/src/modules/auth/__tests__/auth.middleware.test.ts +45 -22
  293. package/src/modules/auth/__tests__/auth.service.test.ts +39 -1
  294. package/src/modules/auth/account-admission.ts +78 -9
  295. package/src/modules/auth/account.routes.ts +63 -7
  296. package/src/modules/auth/auth.middleware.ts +19 -8
  297. package/src/modules/auth/auth.routes.ts +8 -0
  298. package/src/modules/auth/auth.service.ts +207 -7
  299. package/src/modules/auth/oidc-auth-provider.ts +7 -2
  300. package/src/modules/database/core-schema.ts +35 -27
  301. package/src/modules/github-app/__tests__/github-app.test.ts +848 -0
  302. package/src/modules/github-app/github-app.client.ts +268 -0
  303. package/src/modules/github-app/github-app.connection.ts +204 -0
  304. package/src/modules/github-app/github-app.routes.ts +359 -0
  305. package/src/modules/github-app/index.ts +19 -0
  306. package/src/modules/kb-fs/__tests__/branch-name.test.ts +10 -0
  307. package/src/modules/kb-fs/__tests__/remote-url.test.ts +38 -0
  308. package/src/modules/kb-fs/__tests__/repo-path.test.ts +123 -0
  309. package/src/modules/kb-fs/branch-name.ts +14 -1
  310. package/src/modules/kb-fs/remote-url.ts +35 -0
  311. package/src/modules/kb-fs/repo-path.ts +85 -0
  312. package/src/modules/kb-sync/__tests__/kb-sync.routes.test.ts +26 -1
  313. package/src/modules/kb-sync/kb-sync.routes.ts +14 -4
  314. package/src/modules/kb-sync/sync-auth.ts +2 -2
  315. package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +60 -3
  316. package/src/modules/mcp/__tests__/mcp.service.test.ts +68 -6
  317. package/src/modules/mcp/mcp-auth.middleware.ts +20 -6
  318. package/src/modules/mcp/oauth/bevel-oauth-provider.ts +3 -1
  319. package/src/modules/plugins/__tests__/join-proposals.test.ts +100 -19
  320. package/src/modules/plugins/__tests__/join-requests.service.test.ts +27 -11
  321. package/src/modules/plugins/__tests__/join-requests.settlement.test.ts +371 -0
  322. package/src/modules/plugins/__tests__/plugins.routes.test.ts +1 -1
  323. package/src/modules/plugins/__tests__/plugins.tools.test.ts +2 -1
  324. package/src/modules/plugins/join-proposals.ts +87 -19
  325. package/src/modules/plugins/join-requests.service.ts +199 -39
  326. package/src/modules/plugins/plugins.routes.ts +3 -2
  327. package/src/modules/settings/__tests__/deployment-settings.service.test.ts +16 -0
  328. package/src/modules/settings/__tests__/repository-source.test.ts +191 -0
  329. package/src/modules/settings/__tests__/setup.routes.git-mode.test.ts +386 -0
  330. package/src/modules/settings/__tests__/setup.routes.github-app.test.ts +299 -0
  331. package/src/modules/settings/__tests__/setup.routes.managed-phase.test.ts +236 -0
  332. package/src/modules/settings/__tests__/setup.routes.repository-change.test.ts +390 -0
  333. package/src/modules/settings/__tests__/setup.routes.test.ts +3 -0
  334. package/src/modules/settings/deployment-settings.service.ts +117 -6
  335. package/src/modules/settings/managed-repository.ts +68 -0
  336. package/src/modules/settings/repository-source.ts +197 -0
  337. package/src/modules/settings/setup.routes.ts +463 -15
  338. package/src/modules/skills/__tests__/allowed-tools-warn.tools.test.ts +2 -1
  339. package/src/modules/skills/__tests__/branch-skills.tools.test.ts +218 -0
  340. package/src/modules/skills/__tests__/skill-access-requests.routes.test.ts +5 -1
  341. package/src/modules/skills/__tests__/skills.service.test.ts +229 -5
  342. package/src/modules/skills/skill-access-requests.routes.ts +25 -75
  343. package/src/modules/skills/skills.contract.ts +91 -18
  344. package/src/modules/skills/skills.service.ts +278 -41
  345. package/src/modules/skills/skills.tools.ts +80 -8
  346. package/src/modules/tool-auth/__tests__/manual-auth.middleware.test.ts +14 -1
  347. package/src/modules/tool-auth/external-api-key.service.ts +4 -2
  348. package/src/modules/tool-auth/internal-token.service.ts +3 -3
  349. package/src/modules/tool-auth/tool-auth.middleware.ts +34 -11
  350. package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +5 -3
  351. package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +3 -3
  352. package/src/modules/tool-helpers/__tests__/validate-token.test.ts +11 -1
  353. package/src/modules/tool-helpers/tool-context.ts +15 -0
  354. package/src/modules/tool-helpers/tool-handler.ts +24 -4
  355. package/src/modules/tool-helpers/tool.contract.ts +3 -2
  356. package/src/modules/tool-helpers/validate-token.ts +1 -1
  357. package/src/modules/workflow/__tests__/apply-failure.test.ts +9 -1
  358. package/src/modules/workflow/__tests__/pending-commits.repository-replaced.test.ts +111 -0
  359. package/src/modules/workflow/__tests__/workflow.routes.history-read-gate.test.ts +25 -0
  360. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +159 -8
  361. package/src/modules/workflow/__tests__/workflow.service.repository-replaced.test.ts +249 -0
  362. package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +146 -40
  363. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +405 -7
  364. package/src/modules/workflow/agent-tools/change-request-summary.ts +182 -0
  365. package/src/modules/workflow/agent-tools/workflow.tools.ts +135 -38
  366. package/src/modules/workflow/file-lock.service.ts +31 -0
  367. package/src/modules/workflow/git/__tests__/git.service.fileBytesAtCommit.test.ts +260 -0
  368. package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +121 -0
  369. package/src/modules/workflow/git/__tests__/pull-request.service.getPrDetail.test.ts +145 -2
  370. package/src/modules/workflow/git/__tests__/pull-request.service.viewer-can-delete.test.ts +166 -0
  371. package/src/modules/workflow/git/git.service.ts +193 -4
  372. package/src/modules/workflow/git/node-git-runner.ts +6 -0
  373. package/src/modules/workflow/git/pull-request.service.ts +119 -0
  374. package/src/modules/workflow/pending-commits.service.ts +59 -1
  375. package/src/modules/workflow/workflow-hooks.ts +64 -26
  376. package/src/modules/workflow/workflow.routes.ts +3 -1
  377. package/src/modules/workflow/workflow.service.ts +290 -55
  378. package/src/modules/workspace/__tests__/agent-access.gate.test.ts +208 -0
  379. package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +384 -0
  380. package/src/modules/workspace/__tests__/file-stat-access.test.ts +2 -1
  381. package/src/modules/workspace/__tests__/git-internals.security.test.ts +2 -1
  382. package/src/modules/workspace/__tests__/set-aside-clone.test.ts +52 -0
  383. package/src/modules/workspace/__tests__/workspace.routes.at-ref.test.ts +305 -0
  384. package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +2 -0
  385. package/src/modules/workspace/__tests__/workspace.service.forget-clone-races.test.ts +147 -0
  386. package/src/modules/workspace/__tests__/workspace.service.replaced-repository.test.ts +326 -0
  387. package/src/modules/workspace/__tests__/workspace.service.test.ts +20 -9
  388. package/src/modules/workspace/__tests__/workspace.service.unknown-branch.test.ts +43 -0
  389. package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +2 -3
  390. package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +235 -10
  391. package/src/modules/workspace/__tests__/workspace.tools.test.ts +720 -17
  392. package/src/modules/workspace/agent-access.gate.ts +164 -0
  393. package/src/modules/workspace/routine-write-policy.ts +5 -6
  394. package/src/modules/workspace/session-sink.ts +5 -5
  395. package/src/modules/workspace/set-aside-clone.ts +96 -0
  396. package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +297 -0
  397. package/src/modules/workspace/startup/kb-startup-runner.ts +242 -2
  398. package/src/modules/workspace/workspace.routes.ts +95 -3
  399. package/src/modules/workspace/workspace.service.ts +273 -25
  400. package/src/modules/workspace/workspace.tools.ts +373 -119
  401. package/src/modules/write-access/__tests__/write-access.test.ts +248 -0
  402. package/src/modules/write-access/write-access.ts +153 -0
  403. package/src/shared/domain-errors.ts +89 -0
  404. package/src/shared/git.contract.ts +37 -0
  405. package/src/tenancy/__tests__/static-tenant-source.test.ts +0 -1
  406. package/src/tenancy/static-tenant-source.ts +0 -3
  407. package/dist/modules/workflow/session-ontology.policy.d.ts +0 -52
  408. package/dist/modules/workflow/session-ontology.policy.d.ts.map +0 -1
  409. package/dist/modules/workflow/session-ontology.policy.js +0 -62
  410. package/dist/modules/workflow/session-ontology.policy.js.map +0 -1
  411. package/dist/modules/workflow/session-ontology.service.d.ts +0 -105
  412. package/dist/modules/workflow/session-ontology.service.d.ts.map +0 -1
  413. package/dist/modules/workflow/session-ontology.service.js +0 -147
  414. package/dist/modules/workflow/session-ontology.service.js.map +0 -1
  415. package/dist/modules/workspace/session-ontology.gate.d.ts +0 -114
  416. package/dist/modules/workspace/session-ontology.gate.d.ts.map +0 -1
  417. package/dist/modules/workspace/session-ontology.gate.js +0 -161
  418. package/dist/modules/workspace/session-ontology.gate.js.map +0 -1
  419. package/dist/shared/kb-layout.d.ts +0 -39
  420. package/dist/shared/kb-layout.d.ts.map +0 -1
  421. package/dist/shared/kb-layout.js +0 -103
  422. package/dist/shared/kb-layout.js.map +0 -1
  423. package/dist/shared/kb-layout.test.d.ts +0 -2
  424. package/dist/shared/kb-layout.test.d.ts.map +0 -1
  425. package/dist/shared/kb-layout.test.js +0 -75
  426. package/dist/shared/kb-layout.test.js.map +0 -1
  427. package/src/modules/workflow/__tests__/session-ontology.policy.test.ts +0 -62
  428. package/src/modules/workflow/__tests__/session-ontology.service.test.ts +0 -201
  429. package/src/modules/workflow/session-ontology.policy.ts +0 -70
  430. package/src/modules/workflow/session-ontology.service.ts +0 -183
  431. package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +0 -239
  432. package/src/modules/workspace/session-ontology.gate.ts +0 -191
  433. package/src/shared/kb-layout.test.ts +0 -98
  434. package/src/shared/kb-layout.ts +0 -102
@@ -1,11 +1,15 @@
1
1
  import type { Server as HttpServer } from 'node:http';
2
2
  import { execFile } from 'node:child_process';
3
- import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
3
+ import { mkdir, mkdtemp, readdir, rm, writeFile } from 'node:fs/promises';
4
4
  import { tmpdir } from 'node:os';
5
5
  import { join } from 'node:path';
6
6
  import { promisify } from 'node:util';
7
7
  import express from 'express';
8
8
  import { afterEach, describe, expect, it } from 'vitest';
9
+ import '@utcp/http'; // registers the http CallTemplate serializer + protocol
10
+ import { UtcpManualSerializer } from '@utcp/sdk';
11
+ import { HttpCallTemplateSerializer } from '@utcp/http';
12
+ import { CodeModeUtcpClient } from '../../code-mode/index.js';
9
13
  import { testKbContext } from '../../../__tests__/kb-context.js';
10
14
  import { NodeFs } from '../../kb-fs/node-fs.js';
11
15
  import { ToolRegistry } from '../../tool-registry/tool-registry.js';
@@ -17,6 +21,7 @@ import type { IAccessControl } from '../../access/access-control.interface.js';
17
21
  import type { ICreatorAccess } from '../../access-model/creator.js';
18
22
  import type { WorkflowEventBus } from '../../workflow/event-bus.js';
19
23
  import { WorkflowHooks } from '../../workflow/workflow-hooks.js';
24
+ import { ToolDescriptionNotes } from '../../workspace/agent-access.gate.js';
20
25
  import { RoutineWritePolicyService } from '../routine-write-policy.js';
21
26
  import { SpillStore } from '../spill-store.js';
22
27
  import { DocExtractService } from '../file-readers/doc-extract.service.js';
@@ -86,7 +91,12 @@ describe('workspace tools — a branch that cannot be opened', () => {
86
91
  * real tool-context resolver — so a tool call clones (or fails to clone)
87
92
  * exactly as it does in production.
88
93
  */
89
- async function start(opts: { repoUrl?: 'origin' | 'unreachable' } = {}): Promise<string> {
94
+ /** The tool defs the mounted registry serves, kept for the sweep below. */
95
+ let internalTools: { name: string; inputs: unknown }[] = [];
96
+
97
+ async function start(
98
+ opts: { repoUrl?: 'origin' | 'unreachable'; scope?: 'read' | 'write'; source?: 'internal' | 'external' } = {},
99
+ ): Promise<string> {
90
100
  root = await mkdtemp(join(tmpdir(), 'ws-tools-branch-'));
91
101
  spillRoot = await mkdtemp(join(tmpdir(), 'ws-tools-spill-'));
92
102
  docCacheDir = await mkdtemp(join(tmpdir(), 'ws-tools-doc-'));
@@ -128,11 +138,33 @@ describe('workspace tools — a branch that cannot be opened', () => {
128
138
  const app = express();
129
139
  app.use(express.json());
130
140
  const router = express.Router();
141
+ const registry = new ToolRegistry();
142
+ // The internal discovery endpoint, exactly as `manual.routes` serves it —
143
+ // what a real `CodeModeUtcpClient` reads to learn the tools it can call
144
+ // from inside a chain. Served here so the chain test below drives the SAME
145
+ // routes as every direct call in this file.
146
+ router.get('/agent/internal/utcp', async (_req, res) => {
147
+ res.json(
148
+ new UtcpManualSerializer().validateDict({
149
+ utcp_version: '1.1.0',
150
+ manual_version: '1.0.0',
151
+ tools: await registry.listInternal(),
152
+ }),
153
+ );
154
+ });
131
155
  registerWorkspaceTools(
132
- new ToolRegistry(),
156
+ registry,
133
157
  router,
134
158
  (req: express.Request, _res: express.Response, next: express.NextFunction) => {
135
- req.toolAuth = { source: 'external', userId: 'u', scope: 'read' } as ToolAuth;
159
+ req.toolAuth = {
160
+ // The sweep below asks for `internal` + `write`, which is what reaches
161
+ // the internal-only tools and gets past the write-scope refusal that
162
+ // sits in FRONT of every handler. Everything else in this file stays
163
+ // on the external read surface the bug was reported from.
164
+ source: opts.source ?? 'external',
165
+ userId: 'u',
166
+ scope: opts.scope ?? 'read',
167
+ } as ToolAuth;
136
168
  next();
137
169
  },
138
170
  createToolHandlerFactory(resolve),
@@ -141,31 +173,42 @@ describe('workspace tools — a branch that cannot be opened', () => {
141
173
  allowAll,
142
174
  testKbContext({ kbDirName: KB_DIR }),
143
175
  {
144
- service: {} as never,
145
- enabled: false,
146
- kb: testKbContext({ kbDirName: KB_DIR }),
147
176
  recoveryBotEmail: 'recovery-bot@bevel.local',
148
177
  hooks: new WorkflowHooks(),
178
+ notes: new ToolDescriptionNotes(),
149
179
  },
150
180
  new RoutineWritePolicyService(),
151
181
  {} as never,
152
182
  );
153
183
  app.use('/api', router);
184
+ internalTools = (await registry.listInternal()) as unknown as { name: string; inputs: unknown }[];
154
185
  httpServer = await new Promise<HttpServer>((r) => {
155
186
  const s = app.listen(0, () => r(s));
156
187
  });
157
188
  return `http://127.0.0.1:${(httpServer.address() as { port: number }).port}`;
158
189
  }
159
190
 
160
- const listFiles = async (base: string, branch: string): Promise<{ status: number; body: Record<string, unknown> }> => {
161
- const res = await fetch(`${base}/api/agent/tools/list_files`, {
191
+ /** Call a tool with an arbitrary body — including one that omits `branch`. */
192
+ const callTool = async (
193
+ base: string,
194
+ tool: string,
195
+ body: unknown,
196
+ ): Promise<{ status: number; body: Record<string, unknown> }> => {
197
+ const res = await fetch(`${base}/api/agent/tools/${tool}`, {
162
198
  method: 'POST',
163
199
  headers: { 'content-type': 'application/json', authorization: 'Bearer x' },
164
- body: JSON.stringify({ branch, path: '' }),
200
+ body: JSON.stringify(body),
165
201
  });
166
202
  return { status: res.status, body: (await res.json()) as Record<string, unknown> };
167
203
  };
168
204
 
205
+ const listFiles = async (base: string, branch: string): Promise<{ status: number; body: Record<string, unknown> }> =>
206
+ callTool(base, 'list_files', { branch, path: '' });
207
+
208
+ /** Every entry currently under the workspaces root. */
209
+ const workspaceDirs = async (): Promise<string[]> =>
210
+ (await readdir(join(root, 'workspaces'))).sort();
211
+
169
212
  const deleteOnHost = (branch: string): Promise<void> =>
170
213
  runGit(join(root, 'upstream.git'), ['branch', '-D', branch]);
171
214
 
@@ -182,6 +225,188 @@ describe('workspace tools — a branch that cannot be opened', () => {
182
225
  });
183
226
  });
184
227
 
228
+ /**
229
+ * The reported bug, from the outside: every tool call made without a
230
+ * `branch` answered `Branch "undefined" no longer exists on the remote.` —
231
+ * the missing input was carried all the way down, turned into a workspace
232
+ * directory named `undefined`, and the failed clone of that "branch" was
233
+ * then explained as a branch that had been deleted.
234
+ *
235
+ * The input is refused BY NAME instead, at the boundary, before any of that
236
+ * can happen. `list_files` stands in for every knowledge-base tool here
237
+ * because they share the one choke point (`getFilesystem`) — the refusal is
238
+ * the context resolver's, not this tool's.
239
+ */
240
+ describe('a call that names no branch', () => {
241
+ // Every shape of "the caller sent no branch". The literals are in here
242
+ // because a client that interpolates a variable it never set sends the
243
+ // STRING "undefined" — indistinguishable, in intent, from omitting it, and
244
+ // the one value that must never reach a clone.
245
+ const absent: Array<[label: string, body: Record<string, unknown>]> = [
246
+ ['the field is missing entirely', { path: '' }],
247
+ ['the field is empty', { branch: '', path: '' }],
248
+ ['the field is null', { branch: null, path: '' }],
249
+ ['the field is a number', { branch: 42, path: '' }],
250
+ ['the field is an object', { branch: { name: 'main' }, path: '' }],
251
+ ['the field is an array', { branch: ['main'], path: '' }],
252
+ ['the field is the literal "undefined"', { branch: 'undefined', path: '' }],
253
+ ['the field is the literal "null"', { branch: 'null', path: '' }],
254
+ ];
255
+
256
+ for (const [label, body] of absent) {
257
+ it(`400s branch-required when ${label}`, async () => {
258
+ const base = await start();
259
+
260
+ const res = await callTool(base, 'list_files', body);
261
+
262
+ expect(res.status).toBe(400);
263
+ expect(res.body).toEqual({
264
+ kind: 'branch-required',
265
+ error: '`branch` is required: pass the branch (draft) you are working on.',
266
+ });
267
+ // The refusal is the whole story: nothing was created and nothing was
268
+ // cloned. An empty workspaces root is the strongest form of that
269
+ // claim — there is no directory named for any branch, least of all one
270
+ // named `undefined`.
271
+ expect(await workspaceDirs()).toEqual([]);
272
+ });
273
+ }
274
+
275
+ it('never writes `undefined` or `null` as a branch name into the answer', async () => {
276
+ const base = await start();
277
+
278
+ const res = await callTool(base, 'list_files', { path: '' });
279
+
280
+ // AC3, checked against the whole response rather than one field: the
281
+ // message names the INPUT and what to pass, never a stringified value of
282
+ // what was missing. `Branch "undefined" no longer exists` is exactly the
283
+ // sentence this must never produce again.
284
+ const serialized = JSON.stringify(res.body);
285
+ expect(serialized).not.toContain('undefined');
286
+ expect(serialized).not.toContain('null');
287
+ });
288
+
289
+ /**
290
+ * `call_tool_chain` is the other way every one of these tools gets called,
291
+ * and it is where the bug was reported from just as often. It is not a
292
+ * second implementation to guard: the chain's UTCP http transport POSTs to
293
+ * the SAME `/agent/tools/...` route this file has been calling directly, so
294
+ * the one refusal covers both. This test is what proves that claim rather
295
+ * than assuming it — with a real `CodeModeUtcpClient` reading a real
296
+ * manual and running real JavaScript.
297
+ */
298
+ it('400s branch-required from inside call_tool_chain, and creates no workspace', async () => {
299
+ const base = await start();
300
+ const client = await CodeModeUtcpClient.create(process.cwd(), {
301
+ variables: { bevel_API_URL: base, bevel_CONNECTION_KEY: 'internal-token' },
302
+ } as never);
303
+ await client.registerManual(
304
+ new HttpCallTemplateSerializer().validateDict({
305
+ name: 'bevel',
306
+ call_template_type: 'http',
307
+ http_method: 'GET',
308
+ url: '${API_URL}/api/agent/internal/utcp',
309
+ content_type: 'application/json',
310
+ headers: { Authorization: 'Bearer ${CONNECTION_KEY}' },
311
+ }),
312
+ );
313
+
314
+ // The exact call from the specification: a chain that names the path and
315
+ // forgets the branch. The tool THROWS inside the chain, so the failure is
316
+ // caught and its message returned — the runtime's own contract for
317
+ // surfacing a tool error to the model.
318
+ const { result } = await client.callToolChain(
319
+ `try { return { ok: bevel.list_files({ body: { path: 'knowledge-base' } }) }; }
320
+ catch (err) { return { failed: err.message }; }`,
321
+ 30_000,
322
+ );
323
+
324
+ // The tool did not run.
325
+ expect(result.ok).toBeUndefined();
326
+ // The message the chain hands the model carries the whole refusal: the
327
+ // status, the sentence, and the `kind` the direct caller switches on.
328
+ // (The status and payload are IN the message rather than on the thrown
329
+ // object — the sandboxed error exposes no own properties — which is why
330
+ // this asserts on the text the model actually reads.)
331
+ expect(result.failed).toContain('HTTP 400');
332
+ expect(result.failed).toContain('`branch` is required: pass the branch (draft) you are working on.');
333
+ expect(result.failed).toContain('"kind":"branch-required"');
334
+ // Not the sentence the bug produced — and no invented branch name in it.
335
+ expect(result.failed).not.toContain('no longer exists');
336
+ expect(result.failed).not.toContain('undefined');
337
+ // And the chain path refuses just as early: nothing was cloned.
338
+ expect(await workspaceDirs()).toEqual([]);
339
+ });
340
+
341
+ /**
342
+ * AC1 says "any knowledge-base tool", so this asserts it of EVERY tool the
343
+ * module mounts rather than of the one this file otherwise drives. The list
344
+ * comes from the registry, so a tool added later is swept in automatically
345
+ * and cannot quietly reintroduce the bug on its own route. The guard runs
346
+ * ahead of every other check, which is what lets one empty body stand in
347
+ * for a valid call to each of them.
348
+ */
349
+ it('400s branch-required on every mounted tool that declares `branch`', async () => {
350
+ const base = await start({ source: 'internal', scope: 'write' });
351
+ const declaresBranch = internalTools
352
+ .filter((t) => {
353
+ const body = (t.inputs as { properties?: { body?: { required?: string[] } } }).properties?.body;
354
+ return (body?.required ?? []).includes('branch');
355
+ })
356
+ .map((t) => t.name);
357
+
358
+ // The whole branch-taking surface, not a sample of it.
359
+ expect(declaresBranch.length).toBeGreaterThan(10);
360
+
361
+ for (const tool of declaresBranch) {
362
+ const res = await callTool(base, tool, {});
363
+ expect(res.status, `${tool} must 400 on a branch-less call`).toBe(400);
364
+ expect(res.body.kind, `${tool} must answer kind branch-required`).toBe('branch-required');
365
+ // No tool's refusal may name the value it did not get.
366
+ expect(JSON.stringify(res.body), `${tool} must not echo an absent value`).not.toContain('undefined');
367
+ }
368
+ expect(await workspaceDirs()).toEqual([]);
369
+ });
370
+
371
+ it('still serves the same tool once a branch is named', async () => {
372
+ const base = await start();
373
+ // The guard refuses an absent input, not the tool: the same call with a
374
+ // real branch works, so the refusal cannot be a tool that simply broke.
375
+ expect((await callTool(base, 'list_files', { path: '' })).status).toBe(400);
376
+
377
+ const { status, body } = await listFiles(base, 'alice/draft');
378
+
379
+ expect(status).toBe(200);
380
+ expect((body.entries as { name: string }[]).map((e) => e.name)).toContain(KB_DIR);
381
+ });
382
+ });
383
+
384
+ /**
385
+ * The second half of the bug: a bootstrap that failed to clone used to leave
386
+ * a directory behind, and a directory named after a branch is how the
387
+ * platform remembers having known one. The first attempt's leftovers turned
388
+ * the second attempt's honest "no such branch" into "it was deleted".
389
+ */
390
+ it('answers 404 again on a second attempt at a name that never existed', async () => {
391
+ const base = await start();
392
+
393
+ const first = await listFiles(base, 'nobody/never-made-this');
394
+ expect(first.status).toBe(404);
395
+ // Nothing survived the failed clone — not the repo directory, not the
396
+ // workspace shell around it. This is what keeps the next attempt honest.
397
+ expect(await workspaceDirs()).toEqual([]);
398
+
399
+ const second = await listFiles(base, 'nobody/never-made-this');
400
+
401
+ expect(second.status).toBe(404);
402
+ expect(second.body).toEqual({
403
+ kind: 'branch-not-found',
404
+ branch: 'nobody/never-made-this',
405
+ error: 'There is no branch named nobody/never-made-this.',
406
+ });
407
+ expect(await workspaceDirs()).toEqual([]);
408
+ });
409
+
185
410
  it('410s a branch a listing showed us and origin no longer has', async () => {
186
411
  const base = await start();
187
412
  workspaces!.noteBranchesListed(['target-company-state', 'alice/draft']);