@bevel-software/platform-core-backend 0.20.0 → 0.22.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 (666) hide show
  1. package/dist/core/catalog-cache-invalidation.d.ts +7 -2
  2. package/dist/core/catalog-cache-invalidation.d.ts.map +1 -1
  3. package/dist/core/catalog-cache-invalidation.js +8 -9
  4. package/dist/core/catalog-cache-invalidation.js.map +1 -1
  5. package/dist/core/core-ports.d.ts +19 -0
  6. package/dist/core/core-ports.d.ts.map +1 -1
  7. package/dist/core/core-ports.js.map +1 -1
  8. package/dist/core/create-core-server.d.ts +2 -0
  9. package/dist/core/create-core-server.d.ts.map +1 -1
  10. package/dist/core/create-core-server.js +55 -107
  11. package/dist/core/create-core-server.js.map +1 -1
  12. package/dist/core/create-core-services.d.ts +41 -4
  13. package/dist/core/create-core-services.d.ts.map +1 -1
  14. package/dist/core/create-core-services.js +183 -82
  15. package/dist/core/create-core-services.js.map +1 -1
  16. package/dist/core/lifecycle.d.ts +74 -28
  17. package/dist/core/lifecycle.d.ts.map +1 -1
  18. package/dist/core/lifecycle.js +157 -20
  19. package/dist/core/lifecycle.js.map +1 -1
  20. package/dist/core/public-config.d.ts +5 -1
  21. package/dist/core/public-config.d.ts.map +1 -1
  22. package/dist/core/public-config.js +7 -5
  23. package/dist/core/public-config.js.map +1 -1
  24. package/dist/core-config.d.ts +95 -1
  25. package/dist/core-config.d.ts.map +1 -1
  26. package/dist/core-config.js +24 -8
  27. package/dist/core-config.js.map +1 -1
  28. package/dist/index.d.ts +5 -3
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +6 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/modules/access/access-control.service.d.ts +18 -1
  33. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  34. package/dist/modules/access/access-control.service.js +19 -8
  35. package/dist/modules/access/access-control.service.js.map +1 -1
  36. package/dist/modules/access/access-requests.contract.d.ts +75 -0
  37. package/dist/modules/access/access-requests.contract.d.ts.map +1 -0
  38. package/dist/modules/access/access-requests.contract.js +20 -0
  39. package/dist/modules/access/access-requests.contract.js.map +1 -0
  40. package/dist/modules/access/access-requests.routes.d.ts +35 -0
  41. package/dist/modules/access/access-requests.routes.d.ts.map +1 -0
  42. package/dist/modules/access/access-requests.routes.js +237 -0
  43. package/dist/modules/access/access-requests.routes.js.map +1 -0
  44. package/dist/modules/access/access-requests.service.d.ts +123 -0
  45. package/dist/modules/access/access-requests.service.d.ts.map +1 -0
  46. package/dist/modules/access/access-requests.service.js +337 -0
  47. package/dist/modules/access/access-requests.service.js.map +1 -0
  48. package/dist/modules/access/access.routes.d.ts +2 -1
  49. package/dist/modules/access/access.routes.d.ts.map +1 -1
  50. package/dist/modules/access/access.routes.js +10 -10
  51. package/dist/modules/access/access.routes.js.map +1 -1
  52. package/dist/modules/access/change-read-gate.d.ts +6 -3
  53. package/dist/modules/access/change-read-gate.d.ts.map +1 -1
  54. package/dist/modules/access/change-read-gate.js +9 -6
  55. package/dist/modules/access/change-read-gate.js.map +1 -1
  56. package/dist/modules/access/creator-access.d.ts +4 -2
  57. package/dist/modules/access/creator-access.d.ts.map +1 -1
  58. package/dist/modules/access/creator-access.js +7 -4
  59. package/dist/modules/access/creator-access.js.map +1 -1
  60. package/dist/modules/access-model/access-grammar.d.ts +12 -0
  61. package/dist/modules/access-model/access-grammar.d.ts.map +1 -1
  62. package/dist/modules/access-model/access-grammar.js +24 -0
  63. package/dist/modules/access-model/access-grammar.js.map +1 -1
  64. package/dist/modules/agent-instructions/read-preamble.d.ts +2 -1
  65. package/dist/modules/agent-instructions/read-preamble.d.ts.map +1 -1
  66. package/dist/modules/agent-instructions/read-preamble.js +6 -9
  67. package/dist/modules/agent-instructions/read-preamble.js.map +1 -1
  68. package/dist/modules/auth/account-admission.d.ts +40 -0
  69. package/dist/modules/auth/account-admission.d.ts.map +1 -0
  70. package/dist/modules/auth/account-admission.js +17 -0
  71. package/dist/modules/auth/account-admission.js.map +1 -0
  72. package/dist/modules/auth/account.routes.d.ts.map +1 -1
  73. package/dist/modules/auth/account.routes.js +4 -1
  74. package/dist/modules/auth/account.routes.js.map +1 -1
  75. package/dist/modules/auth/auth.service.d.ts +45 -2
  76. package/dist/modules/auth/auth.service.d.ts.map +1 -1
  77. package/dist/modules/auth/auth.service.js +44 -3
  78. package/dist/modules/auth/auth.service.js.map +1 -1
  79. package/dist/modules/auth/oidc-auth-provider.d.ts.map +1 -1
  80. package/dist/modules/auth/oidc-auth-provider.js +9 -0
  81. package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
  82. package/dist/modules/connection-probe/connection-probe.service.d.ts +13 -1
  83. package/dist/modules/connection-probe/connection-probe.service.d.ts.map +1 -1
  84. package/dist/modules/connection-probe/connection-probe.service.js +10 -2
  85. package/dist/modules/connection-probe/connection-probe.service.js.map +1 -1
  86. package/dist/modules/database/advisory-lock.d.ts +17 -0
  87. package/dist/modules/database/advisory-lock.d.ts.map +1 -1
  88. package/dist/modules/database/advisory-lock.js +24 -3
  89. package/dist/modules/database/advisory-lock.js.map +1 -1
  90. package/dist/modules/database/connection.d.ts +67 -2
  91. package/dist/modules/database/connection.d.ts.map +1 -1
  92. package/dist/modules/database/connection.js +118 -12
  93. package/dist/modules/database/connection.js.map +1 -1
  94. package/dist/modules/database/migrate.d.ts +1 -1
  95. package/dist/modules/database/migrate.d.ts.map +1 -1
  96. package/dist/modules/database/migrate.js +27 -3
  97. package/dist/modules/database/migrate.js.map +1 -1
  98. package/dist/modules/github-app/github-app.client.d.ts +101 -0
  99. package/dist/modules/github-app/github-app.client.d.ts.map +1 -0
  100. package/dist/modules/github-app/github-app.client.js +222 -0
  101. package/dist/modules/github-app/github-app.client.js.map +1 -0
  102. package/dist/modules/github-app/github-app.connection.d.ts +102 -0
  103. package/dist/modules/github-app/github-app.connection.d.ts.map +1 -0
  104. package/dist/modules/github-app/github-app.connection.js +185 -0
  105. package/dist/modules/github-app/github-app.connection.js.map +1 -0
  106. package/dist/modules/github-app/github-app.routes.d.ts +59 -0
  107. package/dist/modules/github-app/github-app.routes.d.ts.map +1 -0
  108. package/dist/modules/github-app/github-app.routes.js +323 -0
  109. package/dist/modules/github-app/github-app.routes.js.map +1 -0
  110. package/dist/modules/github-app/index.d.ts +4 -0
  111. package/dist/modules/github-app/index.d.ts.map +1 -0
  112. package/dist/modules/github-app/index.js +4 -0
  113. package/dist/modules/github-app/index.js.map +1 -0
  114. package/dist/modules/kb-fs/branch-name.d.ts +0 -1
  115. package/dist/modules/kb-fs/branch-name.d.ts.map +1 -1
  116. package/dist/modules/kb-fs/branch-name.js +3 -3
  117. package/dist/modules/kb-fs/branch-name.js.map +1 -1
  118. package/dist/modules/kb-fs/clone-config.d.ts +9 -8
  119. package/dist/modules/kb-fs/clone-config.d.ts.map +1 -1
  120. package/dist/modules/kb-fs/clone-config.js +14 -12
  121. package/dist/modules/kb-fs/clone-config.js.map +1 -1
  122. package/dist/modules/kb-fs/remote-url.d.ts +22 -0
  123. package/dist/modules/kb-fs/remote-url.d.ts.map +1 -0
  124. package/dist/modules/kb-fs/remote-url.js +35 -0
  125. package/dist/modules/kb-fs/remote-url.js.map +1 -0
  126. package/dist/modules/mcp/mcp.service.d.ts +7 -0
  127. package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
  128. package/dist/modules/mcp/mcp.service.js +4 -4
  129. package/dist/modules/mcp/mcp.service.js.map +1 -1
  130. package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts +4 -4
  131. package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts.map +1 -1
  132. package/dist/modules/plugins/compile/marketplace-compiler.service.js +7 -10
  133. package/dist/modules/plugins/compile/marketplace-compiler.service.js.map +1 -1
  134. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts +4 -1
  135. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts.map +1 -1
  136. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js +5 -3
  137. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js.map +1 -1
  138. package/dist/modules/plugins/discovery/kb-plugin-source.d.ts +6 -1
  139. package/dist/modules/plugins/discovery/kb-plugin-source.d.ts.map +1 -1
  140. package/dist/modules/plugins/discovery/kb-plugin-source.js +14 -9
  141. package/dist/modules/plugins/discovery/kb-plugin-source.js.map +1 -1
  142. package/dist/modules/plugins/discovery/native.source.d.ts +4 -1
  143. package/dist/modules/plugins/discovery/native.source.d.ts.map +1 -1
  144. package/dist/modules/plugins/discovery/native.source.js +4 -2
  145. package/dist/modules/plugins/discovery/native.source.js.map +1 -1
  146. package/dist/modules/plugins/index.d.ts +1 -1
  147. package/dist/modules/plugins/index.d.ts.map +1 -1
  148. package/dist/modules/plugins/index.js +1 -1
  149. package/dist/modules/plugins/index.js.map +1 -1
  150. package/dist/modules/plugins/join-proposals.d.ts +17 -5
  151. package/dist/modules/plugins/join-proposals.d.ts.map +1 -1
  152. package/dist/modules/plugins/join-proposals.js +76 -22
  153. package/dist/modules/plugins/join-proposals.js.map +1 -1
  154. package/dist/modules/plugins/join-request-jobs.service.d.ts +3 -1
  155. package/dist/modules/plugins/join-request-jobs.service.d.ts.map +1 -1
  156. package/dist/modules/plugins/join-request-jobs.service.js +6 -6
  157. package/dist/modules/plugins/join-request-jobs.service.js.map +1 -1
  158. package/dist/modules/plugins/join-requests.service.d.ts +113 -18
  159. package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
  160. package/dist/modules/plugins/join-requests.service.js +178 -33
  161. package/dist/modules/plugins/join-requests.service.js.map +1 -1
  162. package/dist/modules/plugins/plugin-links.d.ts +65 -10
  163. package/dist/modules/plugins/plugin-links.d.ts.map +1 -1
  164. package/dist/modules/plugins/plugin-links.js +136 -31
  165. package/dist/modules/plugins/plugin-links.js.map +1 -1
  166. package/dist/modules/plugins/plugin-links.service.d.ts +107 -5
  167. package/dist/modules/plugins/plugin-links.service.d.ts.map +1 -1
  168. package/dist/modules/plugins/plugin-links.service.js +151 -21
  169. package/dist/modules/plugins/plugin-links.service.js.map +1 -1
  170. package/dist/modules/plugins/plugin-provision.service.d.ts +10 -3
  171. package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
  172. package/dist/modules/plugins/plugin-provision.service.js +33 -26
  173. package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
  174. package/dist/modules/plugins/plugin-rename.service.d.ts +4 -2
  175. package/dist/modules/plugins/plugin-rename.service.d.ts.map +1 -1
  176. package/dist/modules/plugins/plugin-rename.service.js +10 -12
  177. package/dist/modules/plugins/plugin-rename.service.js.map +1 -1
  178. package/dist/modules/plugins/plugins.routes.d.ts +3 -0
  179. package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
  180. package/dist/modules/plugins/plugins.routes.js +48 -17
  181. package/dist/modules/plugins/plugins.routes.js.map +1 -1
  182. package/dist/modules/plugins/plugins.service.d.ts +4 -4
  183. package/dist/modules/plugins/plugins.service.d.ts.map +1 -1
  184. package/dist/modules/plugins/plugins.service.js +7 -10
  185. package/dist/modules/plugins/plugins.service.js.map +1 -1
  186. package/dist/modules/plugins/teams.routes.d.ts +4 -1
  187. package/dist/modules/plugins/teams.routes.d.ts.map +1 -1
  188. package/dist/modules/plugins/teams.routes.js +11 -9
  189. package/dist/modules/plugins/teams.routes.js.map +1 -1
  190. package/dist/modules/secrets-vault/index.d.ts +1 -1
  191. package/dist/modules/secrets-vault/index.d.ts.map +1 -1
  192. package/dist/modules/secrets-vault/index.js +1 -1
  193. package/dist/modules/secrets-vault/index.js.map +1 -1
  194. package/dist/modules/secrets-vault/secrets-variable-loader.d.ts +29 -11
  195. package/dist/modules/secrets-vault/secrets-variable-loader.d.ts.map +1 -1
  196. package/dist/modules/secrets-vault/secrets-variable-loader.js +46 -21
  197. package/dist/modules/secrets-vault/secrets-variable-loader.js.map +1 -1
  198. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +3 -0
  199. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
  200. package/dist/modules/secrets-vault/secrets-vault.routes.js +4 -6
  201. package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
  202. package/dist/modules/settings/deployment-settings.service.d.ts +34 -9
  203. package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
  204. package/dist/modules/settings/deployment-settings.service.js +113 -26
  205. package/dist/modules/settings/deployment-settings.service.js.map +1 -1
  206. package/dist/modules/settings/managed-repository.d.ts +43 -0
  207. package/dist/modules/settings/managed-repository.d.ts.map +1 -0
  208. package/dist/modules/settings/managed-repository.js +60 -0
  209. package/dist/modules/settings/managed-repository.js.map +1 -0
  210. package/dist/modules/settings/repository-source.d.ts +128 -0
  211. package/dist/modules/settings/repository-source.d.ts.map +1 -0
  212. package/dist/modules/settings/repository-source.js +150 -0
  213. package/dist/modules/settings/repository-source.js.map +1 -0
  214. package/dist/modules/settings/setup.routes.d.ts +34 -4
  215. package/dist/modules/settings/setup.routes.d.ts.map +1 -1
  216. package/dist/modules/settings/setup.routes.js +198 -18
  217. package/dist/modules/settings/setup.routes.js.map +1 -1
  218. package/dist/modules/skills/allowed-tools-check.d.ts +4 -3
  219. package/dist/modules/skills/allowed-tools-check.d.ts.map +1 -1
  220. package/dist/modules/skills/allowed-tools-check.js +8 -8
  221. package/dist/modules/skills/allowed-tools-check.js.map +1 -1
  222. package/dist/modules/skills/pending-skills.service.d.ts +3 -1
  223. package/dist/modules/skills/pending-skills.service.d.ts.map +1 -1
  224. package/dist/modules/skills/pending-skills.service.js +9 -6
  225. package/dist/modules/skills/pending-skills.service.js.map +1 -1
  226. package/dist/modules/skills/skill-access-requests.routes.d.ts +8 -9
  227. package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -1
  228. package/dist/modules/skills/skill-access-requests.routes.js +26 -65
  229. package/dist/modules/skills/skill-access-requests.routes.js.map +1 -1
  230. package/dist/modules/skills/skills.routes.d.ts +4 -1
  231. package/dist/modules/skills/skills.routes.d.ts.map +1 -1
  232. package/dist/modules/skills/skills.routes.js +4 -4
  233. package/dist/modules/skills/skills.routes.js.map +1 -1
  234. package/dist/modules/skills/skills.service.d.ts +4 -2
  235. package/dist/modules/skills/skills.service.d.ts.map +1 -1
  236. package/dist/modules/skills/skills.service.js +13 -11
  237. package/dist/modules/skills/skills.service.js.map +1 -1
  238. package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -1
  239. package/dist/modules/tool-helpers/tool-context.js +15 -0
  240. package/dist/modules/tool-helpers/tool-context.js.map +1 -1
  241. package/dist/modules/tool-manuals/mcp-json-discovery.d.ts +2 -1
  242. package/dist/modules/tool-manuals/mcp-json-discovery.d.ts.map +1 -1
  243. package/dist/modules/tool-manuals/mcp-json-discovery.js +6 -5
  244. package/dist/modules/tool-manuals/mcp-json-discovery.js.map +1 -1
  245. package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts +4 -2
  246. package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts.map +1 -1
  247. package/dist/modules/tool-manuals/mcp-server-edit.service.js +12 -10
  248. package/dist/modules/tool-manuals/mcp-server-edit.service.js.map +1 -1
  249. package/dist/modules/tool-manuals/pending-tools.service.d.ts +3 -1
  250. package/dist/modules/tool-manuals/pending-tools.service.d.ts.map +1 -1
  251. package/dist/modules/tool-manuals/pending-tools.service.js +19 -16
  252. package/dist/modules/tool-manuals/pending-tools.service.js.map +1 -1
  253. package/dist/modules/tool-manuals/tool-delete.service.d.ts +4 -2
  254. package/dist/modules/tool-manuals/tool-delete.service.d.ts.map +1 -1
  255. package/dist/modules/tool-manuals/tool-delete.service.js +14 -12
  256. package/dist/modules/tool-manuals/tool-delete.service.js.map +1 -1
  257. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +3 -1
  258. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
  259. package/dist/modules/tool-manuals/tool-manuals.routes.js +7 -7
  260. package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
  261. package/dist/modules/tool-manuals/tool-manuals.service.d.ts +4 -2
  262. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
  263. package/dist/modules/tool-manuals/tool-manuals.service.js +15 -12
  264. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
  265. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +3 -0
  266. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
  267. package/dist/modules/tool-manuals/tool-manuals.tools.js +4 -6
  268. package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
  269. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +3 -2
  270. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  271. package/dist/modules/workflow/agent-tools/workflow.tools.js +47 -11
  272. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  273. package/dist/modules/workflow/git/git.service.d.ts +14 -6
  274. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  275. package/dist/modules/workflow/git/git.service.js +40 -18
  276. package/dist/modules/workflow/git/git.service.js.map +1 -1
  277. package/dist/modules/workflow/git/node-git-runner.d.ts +26 -2
  278. package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -1
  279. package/dist/modules/workflow/git/node-git-runner.js +40 -5
  280. package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
  281. package/dist/modules/workflow/git/pull-request.service.d.ts +45 -0
  282. package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
  283. package/dist/modules/workflow/git/pull-request.service.js +99 -0
  284. package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
  285. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
  286. package/dist/modules/workflow/review-workflow/review-workflow.service.js +9 -4
  287. package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
  288. package/dist/modules/workflow/session-ontology.service.d.ts +6 -1
  289. package/dist/modules/workflow/session-ontology.service.d.ts.map +1 -1
  290. package/dist/modules/workflow/session-ontology.service.js +6 -2
  291. package/dist/modules/workflow/session-ontology.service.js.map +1 -1
  292. package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
  293. package/dist/modules/workflow/workflow.routes.js +3 -1
  294. package/dist/modules/workflow/workflow.routes.js.map +1 -1
  295. package/dist/modules/workflow/workflow.service.d.ts +42 -10
  296. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  297. package/dist/modules/workflow/workflow.service.js +181 -71
  298. package/dist/modules/workflow/workflow.service.js.map +1 -1
  299. package/dist/modules/workspace/session-ontology.gate.d.ts +3 -1
  300. package/dist/modules/workspace/session-ontology.gate.d.ts.map +1 -1
  301. package/dist/modules/workspace/session-ontology.gate.js +3 -3
  302. package/dist/modules/workspace/session-ontology.gate.js.map +1 -1
  303. package/dist/modules/workspace/startup/kb-git.d.ts +4 -3
  304. package/dist/modules/workspace/startup/kb-git.d.ts.map +1 -1
  305. package/dist/modules/workspace/startup/kb-git.js +15 -13
  306. package/dist/modules/workspace/startup/kb-git.js.map +1 -1
  307. package/dist/modules/workspace/startup/kb-startup-runner.d.ts +70 -7
  308. package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
  309. package/dist/modules/workspace/startup/kb-startup-runner.js +183 -38
  310. package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
  311. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts +7 -1
  312. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts.map +1 -1
  313. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js +23 -16
  314. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js.map +1 -1
  315. package/dist/modules/workspace/startup/steps/personal-spaces.step.d.ts +7 -1
  316. package/dist/modules/workspace/startup/steps/personal-spaces.step.d.ts.map +1 -1
  317. package/dist/modules/workspace/startup/steps/personal-spaces.step.js +12 -5
  318. package/dist/modules/workspace/startup/steps/personal-spaces.step.js.map +1 -1
  319. package/dist/modules/workspace/startup/steps/plugin-display-names.step.d.ts +7 -1
  320. package/dist/modules/workspace/startup/steps/plugin-display-names.step.d.ts.map +1 -1
  321. package/dist/modules/workspace/startup/steps/plugin-display-names.step.js +12 -5
  322. package/dist/modules/workspace/startup/steps/plugin-display-names.step.js.map +1 -1
  323. package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts +7 -1
  324. package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts.map +1 -1
  325. package/dist/modules/workspace/startup/steps/plugin-manifests.step.js +12 -5
  326. package/dist/modules/workspace/startup/steps/plugin-manifests.step.js.map +1 -1
  327. package/dist/modules/workspace/startup/steps/seed-tree.d.ts +4 -1
  328. package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
  329. package/dist/modules/workspace/startup/steps/seed-tree.js +14 -11
  330. package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
  331. package/dist/modules/workspace/startup/steps/template-files.step.d.ts +17 -3
  332. package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
  333. package/dist/modules/workspace/startup/steps/template-files.step.js +36 -30
  334. package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
  335. package/dist/modules/workspace/startup/steps/template-source.d.ts +6 -1
  336. package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
  337. package/dist/modules/workspace/startup/steps/template-source.js +10 -6
  338. package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
  339. package/dist/modules/workspace/workspace.routes.d.ts +2 -1
  340. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  341. package/dist/modules/workspace/workspace.routes.js +8 -7
  342. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  343. package/dist/modules/workspace/workspace.service.d.ts +18 -12
  344. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  345. package/dist/modules/workspace/workspace.service.js +49 -29
  346. package/dist/modules/workspace/workspace.service.js.map +1 -1
  347. package/dist/modules/workspace/workspace.tools.d.ts +2 -1
  348. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  349. package/dist/modules/workspace/workspace.tools.js +48 -20
  350. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  351. package/dist/modules/workspace/write-denial.d.ts +3 -2
  352. package/dist/modules/workspace/write-denial.d.ts.map +1 -1
  353. package/dist/modules/workspace/write-denial.js +6 -5
  354. package/dist/modules/workspace/write-denial.js.map +1 -1
  355. package/dist/shared/domain-errors.d.ts +39 -0
  356. package/dist/shared/domain-errors.d.ts.map +1 -1
  357. package/dist/shared/domain-errors.js +55 -0
  358. package/dist/shared/domain-errors.js.map +1 -1
  359. package/dist/shared/git.contract.d.ts +62 -7
  360. package/dist/shared/git.contract.d.ts.map +1 -1
  361. package/dist/shared/git.contract.js +30 -8
  362. package/dist/shared/git.contract.js.map +1 -1
  363. package/dist/shared/kb-context.d.ts +76 -0
  364. package/dist/shared/kb-context.d.ts.map +1 -0
  365. package/dist/shared/kb-context.js +108 -0
  366. package/dist/shared/kb-context.js.map +1 -0
  367. package/dist/shared/kb-layout.d.ts +3 -2
  368. package/dist/shared/kb-layout.d.ts.map +1 -1
  369. package/dist/shared/kb-layout.js +4 -3
  370. package/dist/shared/kb-layout.js.map +1 -1
  371. package/dist/shared/kb-layout.test.js +35 -27
  372. package/dist/shared/kb-layout.test.js.map +1 -1
  373. package/dist/shared/pending-proposals.d.ts +4 -1
  374. package/dist/shared/pending-proposals.d.ts.map +1 -1
  375. package/dist/shared/pending-proposals.js +3 -4
  376. package/dist/shared/pending-proposals.js.map +1 -1
  377. package/dist/shared/redact-secret.d.ts +5 -5
  378. package/dist/shared/redact-secret.js +5 -5
  379. package/dist/tenancy/index.d.ts +13 -0
  380. package/dist/tenancy/index.d.ts.map +1 -0
  381. package/dist/tenancy/index.js +13 -0
  382. package/dist/tenancy/index.js.map +1 -0
  383. package/dist/tenancy/static-tenant-source.d.ts +98 -0
  384. package/dist/tenancy/static-tenant-source.d.ts.map +1 -0
  385. package/dist/tenancy/static-tenant-source.js +220 -0
  386. package/dist/tenancy/static-tenant-source.js.map +1 -0
  387. package/dist/tenancy/tenant-host.d.ts +80 -0
  388. package/dist/tenancy/tenant-host.d.ts.map +1 -0
  389. package/dist/tenancy/tenant-host.js +217 -0
  390. package/dist/tenancy/tenant-host.js.map +1 -0
  391. package/dist/tenancy/tenant-runtime.d.ts +91 -0
  392. package/dist/tenancy/tenant-runtime.d.ts.map +1 -0
  393. package/dist/tenancy/tenant-runtime.js +174 -0
  394. package/dist/tenancy/tenant-runtime.js.map +1 -0
  395. package/dist/tenancy/tenant-secrets.d.ts +24 -0
  396. package/dist/tenancy/tenant-secrets.d.ts.map +1 -0
  397. package/dist/tenancy/tenant-secrets.js +30 -0
  398. package/dist/tenancy/tenant-secrets.js.map +1 -0
  399. package/dist/tenancy/tenant-source.contract.d.ts +45 -0
  400. package/dist/tenancy/tenant-source.contract.d.ts.map +1 -0
  401. package/dist/tenancy/tenant-source.contract.js +21 -0
  402. package/dist/tenancy/tenant-source.contract.js.map +1 -0
  403. package/migrations/0000_core_init.sql +14 -14
  404. package/migrations/0003_deployment_settings.sql +1 -1
  405. package/migrations/0005_github_facade.sql +1 -1
  406. package/migrations/0012_agent_audit.sql +6 -6
  407. package/package.json +3 -3
  408. package/src/__tests__/branch-model.test.ts +7 -6
  409. package/src/__tests__/kb-context.ts +30 -0
  410. package/src/__tests__/kb-layout-config.test.ts +35 -30
  411. package/src/core/__tests__/catalog-cache-invalidation.test.ts +2 -1
  412. package/src/core/__tests__/lifecycle.test.ts +78 -1
  413. package/src/core/__tests__/public-config.test.ts +5 -1
  414. package/src/core/catalog-cache-invalidation.ts +16 -11
  415. package/src/core/core-ports.ts +19 -0
  416. package/src/core/create-core-server.ts +64 -107
  417. package/src/core/create-core-services.ts +238 -96
  418. package/src/core/lifecycle.ts +214 -29
  419. package/src/core/public-config.ts +8 -5
  420. package/src/core-config.ts +107 -8
  421. package/src/index.ts +25 -2
  422. package/src/modules/access/__tests__/access-control.admin-root-floor.test.ts +2 -1
  423. package/src/modules/access/__tests__/access-requests.recut.test.ts +134 -0
  424. package/src/modules/access/__tests__/access-requests.routes.test.ts +610 -0
  425. package/src/modules/access/__tests__/access.routes.batch.test.ts +2 -1
  426. package/src/modules/access/__tests__/access.routes.folder-governs.test.ts +2 -1
  427. package/src/modules/access/__tests__/access.routes.group-grant.test.ts +2 -1
  428. package/src/modules/access/__tests__/access.routes.overrides.test.ts +2 -1
  429. package/src/modules/access/__tests__/access.routes.proposal-branch.test.ts +2 -1
  430. package/src/modules/access/__tests__/access.routes.prospective.test.ts +2 -1
  431. package/src/modules/access/__tests__/access.routes.revoke.test.ts +2 -1
  432. package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +2 -1
  433. package/src/modules/access/__tests__/change-read-gate.test.ts +13 -11
  434. package/src/modules/access/__tests__/creator-access.test.ts +3 -2
  435. package/src/modules/access/__tests__/roles.routes.test.ts +2 -1
  436. package/src/modules/access/access-control.service.ts +20 -6
  437. package/src/modules/access/access-requests.contract.ts +93 -0
  438. package/src/modules/access/access-requests.routes.ts +286 -0
  439. package/src/modules/access/access-requests.service.ts +420 -0
  440. package/src/modules/access/access.routes.ts +10 -13
  441. package/src/modules/access/change-read-gate.ts +10 -4
  442. package/src/modules/access/creator-access.ts +7 -2
  443. package/src/modules/access-model/access-grammar.ts +22 -0
  444. package/src/modules/agent-instructions/__tests__/read-preamble.test.ts +13 -12
  445. package/src/modules/agent-instructions/read-preamble.ts +10 -12
  446. package/src/modules/auth/__tests__/account.routes.test.ts +15 -0
  447. package/src/modules/auth/__tests__/auth.service.test.ts +98 -0
  448. package/src/modules/auth/account-admission.ts +44 -0
  449. package/src/modules/auth/account.routes.ts +4 -1
  450. package/src/modules/auth/auth.service.ts +61 -2
  451. package/src/modules/auth/oidc-auth-provider.ts +9 -0
  452. package/src/modules/connection-probe/connection-probe.service.ts +7 -1
  453. package/src/modules/database/__tests__/advisory-lock.test.ts +23 -1
  454. package/src/modules/database/__tests__/connection.test.ts +98 -0
  455. package/src/modules/database/__tests__/migrations-unqualified.test.ts +32 -0
  456. package/src/modules/database/advisory-lock.ts +28 -4
  457. package/src/modules/database/connection.ts +143 -13
  458. package/src/modules/database/migrate.ts +48 -14
  459. package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +2 -1
  460. package/src/modules/diff/__tests__/diff.service.test.ts +2 -1
  461. package/src/modules/github-app/__tests__/github-app.test.ts +848 -0
  462. package/src/modules/github-app/github-app.client.ts +268 -0
  463. package/src/modules/github-app/github-app.connection.ts +204 -0
  464. package/src/modules/github-app/github-app.routes.ts +359 -0
  465. package/src/modules/github-app/index.ts +19 -0
  466. package/src/modules/kb-fs/__tests__/branch-name.test.ts +6 -6
  467. package/src/modules/kb-fs/__tests__/clone-config.test.ts +24 -20
  468. package/src/modules/kb-fs/__tests__/remote-url.test.ts +38 -0
  469. package/src/modules/kb-fs/branch-name.ts +3 -3
  470. package/src/modules/kb-fs/clone-config.ts +15 -12
  471. package/src/modules/kb-fs/remote-url.ts +35 -0
  472. package/src/modules/marketplace/__tests__/marketplace-repo.head.test.ts +2 -1
  473. package/src/modules/mcp/mcp.service.ts +11 -4
  474. package/src/modules/plugins/__tests__/bundle-dialect.e2e.test.ts +12 -11
  475. package/src/modules/plugins/__tests__/bundle-dialect.test.ts +2 -1
  476. package/src/modules/plugins/__tests__/compile-marketplace.test.ts +6 -4
  477. package/src/modules/plugins/__tests__/join-proposals.test.ts +100 -19
  478. package/src/modules/plugins/__tests__/join-request-jobs.service.test.ts +2 -1
  479. package/src/modules/plugins/__tests__/join-requests.service.test.ts +28 -11
  480. package/src/modules/plugins/__tests__/join-requests.settlement.test.ts +371 -0
  481. package/src/modules/plugins/__tests__/plugin-creation-display-name.test.ts +4 -3
  482. package/src/modules/plugins/__tests__/plugin-index.service.test.ts +6 -4
  483. package/src/modules/plugins/__tests__/plugin-links.service.test.ts +220 -5
  484. package/src/modules/plugins/__tests__/plugin-provision.service.test.ts +3 -1
  485. package/src/modules/plugins/__tests__/plugin-rename.service.test.ts +7 -6
  486. package/src/modules/plugins/__tests__/plugins.routes.test.ts +12 -3
  487. package/src/modules/plugins/__tests__/teams.routes.test.ts +2 -1
  488. package/src/modules/plugins/compile/marketplace-compiler.service.ts +7 -9
  489. package/src/modules/plugins/discovery/__tests__/kb-plugin-source.test.ts +20 -16
  490. package/src/modules/plugins/discovery/bundle-dialect/bundle.source.ts +9 -2
  491. package/src/modules/plugins/discovery/kb-plugin-source.ts +15 -8
  492. package/src/modules/plugins/discovery/native.source.ts +4 -1
  493. package/src/modules/plugins/index.ts +1 -1
  494. package/src/modules/plugins/join-proposals.ts +87 -19
  495. package/src/modules/plugins/join-request-jobs.service.ts +8 -7
  496. package/src/modules/plugins/join-requests.service.ts +203 -43
  497. package/src/modules/plugins/plugin-links.service.ts +192 -19
  498. package/src/modules/plugins/plugin-links.ts +147 -27
  499. package/src/modules/plugins/plugin-provision.service.ts +54 -27
  500. package/src/modules/plugins/plugin-rename.service.ts +10 -10
  501. package/src/modules/plugins/plugins.routes.ts +48 -17
  502. package/src/modules/plugins/plugins.service.ts +7 -11
  503. package/src/modules/plugins/teams.routes.ts +16 -8
  504. package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +7 -0
  505. package/src/modules/secrets-vault/__tests__/secrets-variable-loader.test.ts +40 -0
  506. package/src/modules/secrets-vault/__tests__/tool-owner-gate.route.test.ts +2 -0
  507. package/src/modules/secrets-vault/index.ts +2 -0
  508. package/src/modules/secrets-vault/secrets-variable-loader.ts +51 -21
  509. package/src/modules/secrets-vault/secrets-vault.routes.ts +7 -6
  510. package/src/modules/settings/__tests__/deployment-settings.service.test.ts +24 -11
  511. package/src/modules/settings/__tests__/git-root-folders.test.ts +2 -1
  512. package/src/modules/settings/__tests__/repository-source.test.ts +191 -0
  513. package/src/modules/settings/__tests__/setup.routes.boot-failure.test.ts +2 -1
  514. package/src/modules/settings/__tests__/setup.routes.git-mode.test.ts +353 -0
  515. package/src/modules/settings/__tests__/setup.routes.github-app.test.ts +282 -0
  516. package/src/modules/settings/__tests__/setup.routes.layout-phase.test.ts +7 -4
  517. package/src/modules/settings/__tests__/setup.routes.managed-phase.test.ts +233 -0
  518. package/src/modules/settings/__tests__/setup.routes.oidc.test.ts +2 -0
  519. package/src/modules/settings/__tests__/setup.routes.sync-status.test.ts +2 -0
  520. package/src/modules/settings/__tests__/setup.routes.test.ts +33 -52
  521. package/src/modules/settings/deployment-settings.service.ts +130 -23
  522. package/src/modules/settings/managed-repository.ts +68 -0
  523. package/src/modules/settings/repository-source.ts +197 -0
  524. package/src/modules/settings/setup.routes.ts +233 -19
  525. package/src/modules/skills/__tests__/allowed-tools-check.test.ts +11 -10
  526. package/src/modules/skills/__tests__/allowed-tools-warn.tools.test.ts +4 -3
  527. package/src/modules/skills/__tests__/pending-skills.service.test.ts +3 -1
  528. package/src/modules/skills/__tests__/skill-access-requests.routes.test.ts +7 -2
  529. package/src/modules/skills/__tests__/skills.routes.warnings.test.ts +2 -1
  530. package/src/modules/skills/__tests__/skills.service.test.ts +3 -2
  531. package/src/modules/skills/allowed-tools-check.ts +7 -6
  532. package/src/modules/skills/pending-skills.service.ts +9 -8
  533. package/src/modules/skills/skill-access-requests.routes.ts +29 -79
  534. package/src/modules/skills/skills.routes.ts +4 -3
  535. package/src/modules/skills/skills.service.ts +13 -9
  536. package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +3 -2
  537. package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +3 -2
  538. package/src/modules/tool-helpers/tool-context.ts +15 -0
  539. package/src/modules/tool-manuals/__tests__/mcp-json-discovery.test.ts +17 -12
  540. package/src/modules/tool-manuals/__tests__/mcp-server-edit.service.test.ts +2 -1
  541. package/src/modules/tool-manuals/__tests__/pending-tools.service.test.ts +4 -1
  542. package/src/modules/tool-manuals/__tests__/tool-delete.service.test.ts +2 -1
  543. package/src/modules/tool-manuals/__tests__/tool-manuals.archive.route.test.ts +2 -1
  544. package/src/modules/tool-manuals/__tests__/tool-manuals.cli.test.ts +5 -4
  545. package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +2 -1
  546. package/src/modules/tool-manuals/__tests__/tool-manuals.invalid.routes.test.ts +4 -2
  547. package/src/modules/tool-manuals/__tests__/tool-manuals.invalid.test.ts +13 -5
  548. package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +2 -1
  549. package/src/modules/tool-manuals/__tests__/tool-manuals.restart.test.ts +9 -1
  550. package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +3 -2
  551. package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +2 -0
  552. package/src/modules/tool-manuals/mcp-json-discovery.ts +6 -4
  553. package/src/modules/tool-manuals/mcp-server-edit.service.ts +13 -11
  554. package/src/modules/tool-manuals/pending-tools.service.ts +19 -16
  555. package/src/modules/tool-manuals/tool-delete.service.ts +13 -10
  556. package/src/modules/tool-manuals/tool-manuals.routes.ts +10 -8
  557. package/src/modules/tool-manuals/tool-manuals.service.ts +15 -13
  558. package/src/modules/tool-manuals/tool-manuals.tools.ts +7 -6
  559. package/src/modules/workflow/__tests__/apply-failure.test.ts +11 -2
  560. package/src/modules/workflow/__tests__/merge-announces-tree.test.ts +14 -26
  561. package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +2 -1
  562. package/src/modules/workflow/__tests__/session-ontology.service.test.ts +3 -2
  563. package/src/modules/workflow/__tests__/workflow.routes.lock-path.test.ts +2 -1
  564. package/src/modules/workflow/__tests__/workflow.service.branch-in-use.test.ts +3 -10
  565. package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +2 -1
  566. package/src/modules/workflow/__tests__/workflow.service.deleted-branch-sweep.test.ts +3 -10
  567. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +187 -35
  568. package/src/modules/workflow/__tests__/workflow.service.folder-proposals.test.ts +2 -1
  569. package/src/modules/workflow/__tests__/workflow.service.platform-restore.test.ts +2 -1
  570. package/src/modules/workflow/__tests__/workflow.service.read-gate.test.ts +3 -2
  571. package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +2 -1
  572. package/src/modules/workflow/__tests__/workflow.service.sync.test.ts +5 -4
  573. package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +148 -41
  574. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +143 -2
  575. package/src/modules/workflow/agent-tools/workflow.tools.ts +60 -12
  576. package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +5 -4
  577. package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +12 -11
  578. package/src/modules/workflow/git/__tests__/git.service.commitChanges.test.ts +9 -8
  579. package/src/modules/workflow/git/__tests__/git.service.commitFile.strayPath.test.ts +8 -7
  580. package/src/modules/workflow/git/__tests__/git.service.commitFile.test.ts +6 -5
  581. package/src/modules/workflow/git/__tests__/git.service.createBranch.test.ts +3 -2
  582. package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +3 -2
  583. package/src/modules/workflow/git/__tests__/git.service.diffFileAtCommit.test.ts +7 -6
  584. package/src/modules/workflow/git/__tests__/git.service.diffFileBetweenBranches.test.ts +16 -15
  585. package/src/modules/workflow/git/__tests__/git.service.fileContentsAtCommit.test.ts +3 -2
  586. package/src/modules/workflow/git/__tests__/git.service.forkPoint.test.ts +2 -1
  587. package/src/modules/workflow/git/__tests__/git.service.history-guards.test.ts +2 -1
  588. package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +10 -9
  589. package/src/modules/workflow/git/__tests__/git.service.listTrackedFiles.test.ts +2 -1
  590. package/src/modules/workflow/git/__tests__/git.service.logForFile.test.ts +6 -5
  591. package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +9 -8
  592. package/src/modules/workflow/git/__tests__/git.service.pendingChanges.test.ts +2 -1
  593. package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +4 -3
  594. package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +130 -8
  595. package/src/modules/workflow/git/__tests__/git.service.readFileAtRef.test.ts +2 -1
  596. package/src/modules/workflow/git/__tests__/git.service.revertPathsAndPush.test.ts +2 -1
  597. package/src/modules/workflow/git/__tests__/git.service.status.test.ts +4 -3
  598. package/src/modules/workflow/git/__tests__/git.service.syncFromRemote.test.ts +8 -7
  599. package/src/modules/workflow/git/__tests__/node-git-runner.test.ts +41 -3
  600. package/src/modules/workflow/git/__tests__/pull-request.service.getPrDetail.test.ts +145 -2
  601. package/src/modules/workflow/git/__tests__/pull-request.service.viewer-can-delete.test.ts +166 -0
  602. package/src/modules/workflow/git/git.service.ts +49 -17
  603. package/src/modules/workflow/git/node-git-runner.ts +43 -4
  604. package/src/modules/workflow/git/pull-request.service.ts +119 -0
  605. package/src/modules/workflow/review-workflow/review-workflow.service.ts +9 -6
  606. package/src/modules/workflow/session-ontology.service.ts +7 -2
  607. package/src/modules/workflow/workflow.routes.ts +3 -1
  608. package/src/modules/workflow/workflow.service.ts +201 -76
  609. package/src/modules/workspace/__tests__/file-stat-access.test.ts +3 -2
  610. package/src/modules/workspace/__tests__/git-internals.security.test.ts +10 -9
  611. package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +4 -2
  612. package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +3 -2
  613. package/src/modules/workspace/__tests__/workspace.routes.branch-errors.test.ts +2 -1
  614. package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +2 -1
  615. package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +2 -1
  616. package/src/modules/workspace/__tests__/workspace.routes.download-implies-read.test.ts +2 -1
  617. package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +2 -1
  618. package/src/modules/workspace/__tests__/workspace.routes.file-writes.test.ts +2 -1
  619. package/src/modules/workspace/__tests__/workspace.routes.folders.test.ts +5 -4
  620. package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +2 -1
  621. package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +2 -1
  622. package/src/modules/workspace/__tests__/workspace.service.ensure-remotes-fetched.test.ts +2 -2
  623. package/src/modules/workspace/__tests__/workspace.service.list-cloned.test.ts +6 -5
  624. package/src/modules/workspace/__tests__/workspace.service.move-never-overwrites.test.ts +2 -1
  625. package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +2 -1
  626. package/src/modules/workspace/__tests__/workspace.service.test.ts +84 -50
  627. package/src/modules/workspace/__tests__/workspace.service.unknown-branch.test.ts +45 -1
  628. package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +10 -7
  629. package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +237 -10
  630. package/src/modules/workspace/__tests__/workspace.tools.test.ts +44 -11
  631. package/src/modules/workspace/__tests__/write-denial.test.ts +5 -4
  632. package/src/modules/workspace/session-ontology.gate.ts +6 -4
  633. package/src/modules/workspace/startup/__tests__/kb-startup-runner.degraded.test.ts +6 -2
  634. package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +240 -21
  635. package/src/modules/workspace/startup/kb-git.ts +15 -22
  636. package/src/modules/workspace/startup/kb-startup-runner.ts +198 -45
  637. package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +104 -98
  638. package/src/modules/workspace/startup/steps/groups-to-plugins.step.ts +24 -16
  639. package/src/modules/workspace/startup/steps/personal-spaces.step.ts +14 -5
  640. package/src/modules/workspace/startup/steps/plugin-display-names.step.ts +13 -5
  641. package/src/modules/workspace/startup/steps/plugin-manifests.step.ts +14 -5
  642. package/src/modules/workspace/startup/steps/seed-tree.ts +11 -9
  643. package/src/modules/workspace/startup/steps/template-files.step.ts +43 -34
  644. package/src/modules/workspace/startup/steps/template-source.ts +8 -5
  645. package/src/modules/workspace/workspace.routes.ts +8 -7
  646. package/src/modules/workspace/workspace.service.ts +47 -28
  647. package/src/modules/workspace/workspace.tools.ts +56 -20
  648. package/src/modules/workspace/write-denial.ts +7 -5
  649. package/src/shared/__tests__/kb-layout.plugin.test.ts +19 -16
  650. package/src/shared/domain-errors.ts +58 -0
  651. package/src/shared/git.contract.ts +80 -8
  652. package/src/shared/kb-context.ts +130 -0
  653. package/src/shared/kb-layout.test.ts +37 -27
  654. package/src/shared/kb-layout.ts +4 -3
  655. package/src/shared/pending-proposals.ts +7 -4
  656. package/src/shared/redact-secret.ts +5 -5
  657. package/src/tenancy/__tests__/static-tenant-source.test.ts +177 -0
  658. package/src/tenancy/__tests__/tenant-host.test.ts +372 -0
  659. package/src/tenancy/__tests__/tenant-runtime.test.ts +221 -0
  660. package/src/tenancy/__tests__/tenant-secrets.test.ts +35 -0
  661. package/src/tenancy/index.ts +35 -0
  662. package/src/tenancy/static-tenant-source.ts +296 -0
  663. package/src/tenancy/tenant-host.ts +261 -0
  664. package/src/tenancy/tenant-runtime.ts +208 -0
  665. package/src/tenancy/tenant-secrets.ts +41 -0
  666. package/src/tenancy/tenant-source.contract.ts +59 -0
@@ -9,7 +9,6 @@ import type { IAdminAccessService } from '../admin/admin.interface.js';
9
9
  import express from 'express';
10
10
  import type { AuthUser, IWorkflowService } from '@bevel-software/platform-shared';
11
11
  import {
12
- DEFAULT_BRANCH,
13
12
  KNOWLEDGE_DIR,
14
13
  canonicalRelativePath,
15
14
  folderPlaceholderPath,
@@ -21,6 +20,7 @@ import {
21
20
  } from '@bevel-software/platform-shared';
22
21
  import { FolderTooLargeError, type ReadTreeFilter } from './workspace.service.js';
23
22
  import { branchForWorkspaceId } from '../../shared/workspace-id.js';
23
+ import type { KbContext } from '../../shared/kb-context.js';
24
24
  import { EntryExistsError, type WorkspaceService } from './workspace.service.js';
25
25
  import type { AuthService } from '../auth/auth.service.js';
26
26
  import type { IAccessControl } from '../access/access-control.interface.js';
@@ -82,7 +82,7 @@ export function createWorkspaceRoutes(
82
82
  workflowService: IWorkflowService,
83
83
  eventBus: WorkflowEventBus,
84
84
  accessControl: IAccessControl,
85
- kbDirName: string,
85
+ kb: KbContext,
86
86
  creatorAccess: ICreatorAccess,
87
87
  adminAccess: IAdminAccessService,
88
88
  disk: ITreeWalker,
@@ -97,6 +97,7 @@ export function createWorkspaceRoutes(
97
97
  changeGate?: IChangeReadGate,
98
98
  ): express.Router {
99
99
  const router = express.Router();
100
+ const { kbDirName } = kb;
100
101
  const gitInternalsRouteGuard = createGitInternalsRouteGuard(workspaceService);
101
102
 
102
103
  // The git folder is refused ahead of every route here by
@@ -463,7 +464,7 @@ export function createWorkspaceRoutes(
463
464
  }
464
465
  const branch = typeof req.query.branch === 'string' && req.query.branch.length > 0
465
466
  ? req.query.branch
466
- : DEFAULT_BRANCH;
467
+ : kb.defaultBranch;
467
468
  const workspace = await workspaceService.getOrCreateForBranch(branch);
468
469
  // Bootstrap must use the same read-filtered tree as GET /workspace/:id/files.
469
470
  // Otherwise the first sidebar render can expose restricted nodes until the
@@ -663,7 +664,7 @@ export function createWorkspaceRoutes(
663
664
  // same treatment so legacy clones don't collapse. Only the folders
664
665
  // themselves are forced visible — their contents stay gated by the
665
666
  // verdict above.
666
- const structuralRoots = new Set([...reservedRootDirNames(), KNOWLEDGE_DIR]);
667
+ const structuralRoots = new Set([...reservedRootDirNames(kb.layout), KNOWLEDGE_DIR]);
667
668
  for (const wp of wsRelPaths) {
668
669
  const rel = toKbRelative(wp, kbDirName);
669
670
  if (rel !== null && structuralRoots.has(rel)) verdict.set(wp, true);
@@ -1128,11 +1129,11 @@ export function createWorkspaceRoutes(
1128
1129
  const oldRel = toKbRelative(oldPath, kbDirName);
1129
1130
  const newRel = toKbRelative(newPath, kbDirName);
1130
1131
  let platformRestore = false;
1131
- if (oldRel !== null && newRel !== null && isPlatformRestoreShape(oldRel, newRel)) {
1132
+ if (oldRel !== null && newRel !== null && isPlatformRestoreShape(oldRel, newRel, kb.layout)) {
1132
1133
  platformRestore = await accessControl.canRestorePlatformFile(id, user.email, newRel);
1133
1134
  }
1134
1135
  // A platform file stays where the platform reads it …
1135
- if (oldRel !== null && isPlatformFile(oldRel) && !platformRestore) {
1136
+ if (oldRel !== null && isPlatformFile(oldRel, kb.layout) && !platformRestore) {
1136
1137
  res.status(409).json({ error: platformFileRefusal(oldRel) });
1137
1138
  return;
1138
1139
  }
@@ -1145,7 +1146,7 @@ export function createWorkspaceRoutes(
1145
1146
  // from the same place. Only the restore lands on a platform path, and
1146
1147
  // only where the file is missing (`canRestorePlatformFile` checked the
1147
1148
  // disk; the destination lock below checks it again, under the lock).
1148
- if (newRel !== null && isPlatformFile(newRel) && !platformRestore) {
1149
+ if (newRel !== null && isPlatformFile(newRel, kb.layout) && !platformRestore) {
1149
1150
  res.status(409).json({ error: platformFileCreationRefusal(newRel) });
1150
1151
  return;
1151
1152
  }
@@ -9,7 +9,6 @@ import { AsyncLocalStorage } from 'node:async_hooks';
9
9
  import {
10
10
  validateRelativePath,
11
11
  validateFilename,
12
- DEFAULT_BRANCH,
13
12
  FOLDER_PLACEHOLDER,
14
13
  isFolderPlaceholder,
15
14
  entryExistsMessage,
@@ -22,6 +21,7 @@ import {
22
21
  renameNoReplace,
23
22
  } from '../../shared/rename-no-replace.js';
24
23
  import type { IGitRunner } from '../../shared/git.contract.js';
24
+ import type { KbContext } from '../../shared/kb-context.js';
25
25
  import { NodeGitRunner } from '../workflow/git/node-git-runner.js';
26
26
  import { assertWithinDirectory } from '../../shared/path-containment.js';
27
27
  import { assertRepoRootNameFree, normalizeWorkspacePath } from '../kb-fs/repo-path.js';
@@ -149,9 +149,8 @@ const CLONE_TIMEOUT_MS = 600_000;
149
149
  const BOT_NAME = 'Bevel Workflow';
150
150
  const BOT_EMAIL = 'bevel-workflow@bevel.software';
151
151
 
152
- /** Redact any token that might leak into an error message. */
153
- function redactError(err: unknown): string {
154
- const token = process.env.GITHUB_TOKEN;
152
+ /** Redact the token the runner authenticates with from an error message. */
153
+ function redactError(err: unknown, token: string | null): string {
155
154
  const msg = err instanceof Error ? err.message : String(err);
156
155
  return token ? msg.replaceAll(token, '***') : msg;
157
156
  }
@@ -297,23 +296,26 @@ export class WorkspaceService implements IWorkspaceService {
297
296
  * buy an inconsistency rather than a feature.
298
297
  */
299
298
  kbRepoUrl: string | (() => string),
300
- private readonly kbDirName: string,
299
+ /** The checkout folder's name, and which branch a caller lands on when naming none. */
300
+ private readonly kb: Pick<KbContext, 'kbDirName' | 'defaultBranch'>,
301
301
  private readonly disk: ITreeWalker,
302
- gitUsername: string | (() => string) = 'x-access-token',
303
302
  /**
304
303
  * How git is run — see `shared/git.contract.ts`. The composition root
305
- * passes the one runner carrying the deployment's deadline; the default
306
- * is the same runner on its default deadline, for a directly constructed
307
- * service.
304
+ * passes the one runner carrying the deployment's deadline and the
305
+ * credentials every clone authenticates with; the default is the same
306
+ * runner on its default deadline and no token, for a directly
307
+ * constructed service.
308
308
  */
309
309
  private readonly gitRunner: IGitRunner = new NodeGitRunner(),
310
310
  ) {
311
311
  this.kbRepoUrl = typeof kbRepoUrl === 'function' ? kbRepoUrl : () => kbRepoUrl;
312
- this.gitUsername = typeof gitUsername === 'function' ? gitUsername : () => gitUsername;
312
+ }
313
+
314
+ private get kbDirName(): string {
315
+ return this.kb.kbDirName;
313
316
  }
314
317
 
315
318
  private readonly kbRepoUrl: () => string;
316
- private readonly gitUsername: () => string;
317
319
 
318
320
  setDiffService(diffService: IDiffService): void {
319
321
  this.diffService = diffService;
@@ -417,7 +419,7 @@ export class WorkspaceService implements IWorkspaceService {
417
419
  // Persisted into the new repo's config (`clone --config`), not just applied
418
420
  // to this invocation — every later push from this clone depends on finding
419
421
  // the helper there. See `cloneCredentialArgs`.
420
- args.push(...cloneCredentialArgs(this.gitUsername()));
422
+ args.push(...cloneCredentialArgs(this.gitRunner.credentials));
421
423
  args.push(this.kbRepoUrl(), targetDir);
422
424
  return args;
423
425
  }
@@ -531,7 +533,7 @@ export class WorkspaceService implements IWorkspaceService {
531
533
  cloned.push({
532
534
  id: entry.name,
533
535
  branch,
534
- unreadable: `Could not read this branch's clone: ${redactError(err)}`,
536
+ unreadable: `Could not read this branch's clone: ${redactError(err, this.gitRunner.credentials.token())}`,
535
537
  });
536
538
  continue;
537
539
  }
@@ -566,7 +568,7 @@ export class WorkspaceService implements IWorkspaceService {
566
568
  return;
567
569
  } catch (err) {
568
570
  log.warn(`referenced clone for "${branch}" failed, retrying without reference:`, {
569
- detail: redactError(err),
571
+ detail: redactError(err, this.gitRunner.credentials.token()),
570
572
  });
571
573
  // Clear any partial output so the retry clones into a clean dir.
572
574
  await fs.rm(targetDir, { recursive: true, force: true }).catch(() => {});
@@ -647,15 +649,31 @@ export class WorkspaceService implements IWorkspaceService {
647
649
  }
648
650
  this.inFlightBootstraps.set(branch, bootstrap);
649
651
 
652
+ // `mkdir --recursive` answers with the first path it CREATED, or undefined
653
+ // when the directory was already there. That is the only honest signal for
654
+ // what the rollback below may remove: a directory this attempt made is ours
655
+ // to take back, one that predates us belongs to whatever put it there.
656
+ let createdWorkspaceDir: string | undefined;
650
657
  try {
651
658
  // A clone with `-b <branch>` against a never-seeded remote fails
652
659
  // naturally; seeding the remote is the KB startup phase's job, at boot.
653
- await fs.mkdir(workspaceDir, { recursive: true });
660
+ createdWorkspaceDir = await fs.mkdir(workspaceDir, { recursive: true });
654
661
  await this.cloneProcessMapForBranch(workspaceDir, branch);
655
662
  this.registerBranchDir(branch, workspaceDir);
656
663
  resolveBootstrap();
657
664
  } catch (err) {
658
665
  this.branchDirs.delete(branch);
666
+ // A bootstrap that failed leaves NOTHING behind. The clone rolls its own
667
+ // target back, but the workspace directory around it would survive as an
668
+ // empty shell named after the branch — and a directory named after a
669
+ // branch is read as the platform having known that branch: by
670
+ // `hasHeardOfBranch`, which would turn the next attempt's honest 404 into
671
+ // "no longer exists on the remote" (410), and by anyone reading the
672
+ // workspaces root. Best-effort: a rollback that cannot delete must not
673
+ // replace the real failure (the clone's) with its own.
674
+ if (createdWorkspaceDir !== undefined) {
675
+ await fs.rm(workspaceDir, { recursive: true, force: true }).catch(() => {});
676
+ }
659
677
  rejectBootstrap(err);
660
678
  throw err;
661
679
  } finally {
@@ -675,7 +693,7 @@ export class WorkspaceService implements IWorkspaceService {
675
693
  * `branch` is passed.
676
694
  */
677
695
  async getOrCreateForUser(_user: AuthUser, branch?: string): Promise<WorkspaceInfo> {
678
- return this.getOrCreateForBranch(branch ?? DEFAULT_BRANCH);
696
+ return this.getOrCreateForBranch(branch ?? this.kb.defaultBranch);
679
697
  }
680
698
 
681
699
  private buildWorkspaceInfo(branch: string, workspaceDir: string): WorkspaceInfo {
@@ -741,7 +759,7 @@ export class WorkspaceService implements IWorkspaceService {
741
759
  } catch (err) {
742
760
  // One line per branch, not per key: every key writes to the same
743
761
  // `.git/config`, so what fails for one fails for all.
744
- log.warn(`could not normalize the config of the "${branch}" clone:`, { detail: redactError(err) });
762
+ log.warn(`could not normalize the config of the "${branch}" clone:`, { detail: redactError(err, this.gitRunner.credentials.token()) });
745
763
  }
746
764
  await this.stampCredentialHelper(repoDir, branch);
747
765
  }
@@ -750,12 +768,13 @@ export class WorkspaceService implements IWorkspaceService {
750
768
  * Fingerprint of the credential state a clone's helper is derived from: the
751
769
  * username (baked into the helper literal) and whether a token exists at all
752
770
  * (the helper is present-or-absent on that). The token VALUE is deliberately
753
- * excluded — the helper reads `$GITHUB_TOKEN` at call time, so rotating the
754
- * token needs no re-stamp; only a username change or a token appearing /
755
- * disappearing does.
771
+ * excluded — the helper reads `$GITHUB_TOKEN` from the environment the
772
+ * runner hands each git call, so rotating the token needs no re-stamp; only
773
+ * a username change or a token appearing / disappearing does.
756
774
  */
757
775
  private credentialFingerprint(): string {
758
- return `${this.gitUsername()}::${process.env.GITHUB_TOKEN ? '1' : '0'}`;
776
+ const { credentials } = this.gitRunner;
777
+ return `${credentials.username()}::${credentials.token() ? '1' : '0'}`;
759
778
  }
760
779
 
761
780
  /** Last credential fingerprint stamped into each branch's clone, this process. */
@@ -772,7 +791,7 @@ export class WorkspaceService implements IWorkspaceService {
772
791
  private async stampCredentialHelper(repoDir: string, branch: string): Promise<void> {
773
792
  let argLists: string[][];
774
793
  try {
775
- argLists = cloneCredentialConfigArgs(this.gitUsername());
794
+ argLists = cloneCredentialConfigArgs(this.gitRunner.credentials);
776
795
  } catch (err) {
777
796
  // `credentialHelperValue` fails closed on a username outside its safe
778
797
  // charset. Normally unreachable (CoreConfig and the settings service
@@ -782,7 +801,7 @@ export class WorkspaceService implements IWorkspaceService {
782
801
  // re-clone that fails on the same validation — masking the real cause.
783
802
  // Contain it as a loud non-stamp instead; `normalizeCloneConfig`'s
784
803
  // never-throws contract stays true.
785
- log.warn(`refusing to stamp the credential helper of the "${branch}" clone:`, { detail: redactError(err) });
804
+ log.warn(`refusing to stamp the credential helper of the "${branch}" clone:`, { detail: redactError(err, this.gitRunner.credentials.token()) });
786
805
  this.stampedCredentialFingerprint.delete(branch);
787
806
  return;
788
807
  }
@@ -798,7 +817,7 @@ export class WorkspaceService implements IWorkspaceService {
798
817
  if (!(args.includes('--unset-all') && code === 5)) {
799
818
  stamped = false;
800
819
  log.warn(`could not stamp the credential helper of the "${branch}" clone:`, {
801
- detail: redactError(err),
820
+ detail: redactError(err, this.gitRunner.credentials.token()),
802
821
  });
803
822
  }
804
823
  }
@@ -914,11 +933,11 @@ export class WorkspaceService implements IWorkspaceService {
914
933
  this.onWorkspaceCloned?.(workspaceIdForBranch(branch));
915
934
  } catch (listenerErr) {
916
935
  log.error(`onWorkspaceCloned listener failed for branch "${branch}":`, {
917
- detail: redactError(listenerErr),
936
+ detail: redactError(listenerErr, this.gitRunner.credentials.token()),
918
937
  });
919
938
  }
920
939
  } catch (err) {
921
- const redacted = redactError(err);
940
+ const redacted = redactError(err, this.gitRunner.credentials.token());
922
941
  // Roll back partial state so the next bootstrap retries cleanly.
923
942
  await fs.rm(targetDir, { recursive: true, force: true }).catch(() => {});
924
943
  // A branch origin does not have is a fact about the branch, not a
@@ -936,7 +955,7 @@ export class WorkspaceService implements IWorkspaceService {
936
955
  // two stories this is — and guessing either one states something
937
956
  // about the branch that we do not know. Our failure, so: 500.
938
957
  log.error(`Could not tell whether branch "${branch}" was ever known here:`, {
939
- detail: redactError(probeErr),
958
+ detail: redactError(probeErr, this.gitRunner.credentials.token()),
940
959
  });
941
960
  throw new Error(`Failed to clone process map: ${redacted}`);
942
961
  }
@@ -1255,7 +1274,7 @@ export class WorkspaceService implements IWorkspaceService {
1255
1274
  })
1256
1275
  .catch((err) => {
1257
1276
  this.lastFetchOk.set(repoDir, false);
1258
- log.warn('git fetch origin failed:', { detail: redactError(err) });
1277
+ log.warn('git fetch origin failed:', { detail: redactError(err, this.gitRunner.credentials.token()) });
1259
1278
  })
1260
1279
  .finally(() => {
1261
1280
  if (this.inFlightFetches.get(repoDir) === promise) {
@@ -18,6 +18,7 @@ import type { IRoutineWritePolicy } from './routine-write-policy.js';
18
18
  import type { ToolHandlerFactory } from '../tool-helpers/tool-handler.js';
19
19
  import { requireInternalSource, requireExternalSource } from '../tool-auth/tool-auth.middleware.js';
20
20
  import { workspaceIdForBranch } from '../../shared/workspace-id.js';
21
+ import { assertBranchProvided } from '../../shared/domain-errors.js';
21
22
  // Leaf-level shared primitive (same exception `workspace.service.ts` already
22
23
  // relies on) — not a workflow service, so this stays inside the module boundary.
23
24
  import { assertValidBranchName } from '../kb-fs/branch-name.js';
@@ -39,21 +40,20 @@ import { createFileReaderRegistry } from './file-readers/file-reader.registry.js
39
40
  import { DocumentReader } from './file-readers/document-reader.js';
40
41
  import { mcpImageResult } from '@bevel-software/platform-mcp-core';
41
42
  import {
42
- AGENTS_FILE,
43
43
  LEGACY_AGENTS_FILE,
44
44
  folderPlaceholderPath,
45
45
  isFolderPlaceholder,
46
46
  isPlatformFile,
47
47
  isPlatformFolder,
48
- isProtectedBranch,
49
- onKbLayoutApplied,
50
48
  platformFileCreationRefusal,
51
49
  platformFileNames,
52
50
  platformFileRefusal,
53
51
  platformFolderRefusal,
54
52
  entryExistsMessage,
55
53
  type ExistingEntryKind,
54
+ type KbLayout,
56
55
  } from '@bevel-software/platform-shared';
56
+ import type { KbContext } from '../../shared/kb-context.js';
57
57
  import { AccessDeniedError } from '../access-model/access-errors.js';
58
58
  import { removeEmptyDirs } from './empty-dirs.js';
59
59
  import { PROPOSAL_ROUTE_NOTE, rethrowAsWriteDenial } from './write-denial.js';
@@ -216,22 +216,23 @@ async function keepFolderOf(
216
216
  * working in their knowledge base. Under the default name the wording collapses
217
217
  * to the one file it has always named.
218
218
  *
219
- * A FUNCTION, called at mount time: the name is a deployment setting applied at
220
- * boot, and a module-scope string would snapshot the default.
219
+ * A FUNCTION of the layout, called when a description is built: the name is a
220
+ * deployment setting, and a module-scope string would snapshot the default.
221
221
  */
222
- function kbConventionsNote(): string {
223
- if (AGENTS_FILE === LEGACY_AGENTS_FILE) {
222
+ function kbConventionsNote(layout: KbLayout): string {
223
+ const agentsFile = layout.agentsFile ?? LEGACY_AGENTS_FILE;
224
+ if (agentsFile === LEGACY_AGENTS_FILE) {
224
225
  return ' Before your first read or change in a workspace, read `AGENTS.md` at the KB root — or `CLAUDE.md` on a knowledge base seeded before it was renamed — if either exists: it holds the author\'s conventions for this knowledge base, and you should follow them.';
225
226
  }
226
227
  return (
227
- ` Before your first read or change in a workspace, read \`${AGENTS_FILE}\` at the KB root, then ` +
228
+ ` Before your first read or change in a workspace, read \`${agentsFile}\` at the KB root, then ` +
228
229
  '`AGENTS.md` if it also exists (the organisation\'s own conventions) — or `CLAUDE.md` on a knowledge base seeded before it was renamed: together they hold the conventions for this knowledge base, and you should follow them.'
229
230
  );
230
231
  }
231
232
 
232
233
  /** The platform files as a tool description lists them — the guide under its own name. */
233
- function platformFileList(): string {
234
- return platformFileNames()
234
+ function platformFileList(layout: KbLayout): string {
235
+ return platformFileNames(layout)
235
236
  .map((name) => `\`${name}\``)
236
237
  .join(', ');
237
238
  }
@@ -679,7 +680,7 @@ export function registerWorkspaceTools(
679
680
  spillStore: SpillStore,
680
681
  docExtract: DocExtractService,
681
682
  accessControl: IAccessControl,
682
- kbDirName: string,
683
+ kb: KbContext,
683
684
  sessionOntologyGate: SessionOntologyGate,
684
685
  writePolicy: IRoutineWritePolicy,
685
686
  sessionSink: ISessionSink,
@@ -697,6 +698,7 @@ export function registerWorkspaceTools(
697
698
  */
698
699
  changeGate?: IChangeReadGate,
699
700
  ): void {
701
+ const { kbDirName } = kb;
700
702
  /**
701
703
  * The one extension→reader registry every read-shaped decision routes
702
704
  * through: read_file dispatches on it, grep asks it for searchable text,
@@ -871,7 +873,7 @@ export function registerWorkspaceTools(
871
873
  * branch only through a change request.
872
874
  */
873
875
  const writeBlocked = async (branch: string, ctx: ToolContext, paths: string[]): Promise<string[]> => {
874
- if (!isProtectedBranch(branch)) return [];
876
+ if (!kb.isProtectedBranch(branch)) return [];
875
877
  const byRel = new Map<string, string>();
876
878
  for (const p of paths) {
877
879
  const rel = toKbRelative(p, kbDirName);
@@ -934,11 +936,11 @@ export function registerWorkspaceTools(
934
936
  if (isGitMetadata(norm)) return `"${norm}" is git metadata and cannot be moved or deleted.`;
935
937
  if (kind === 'file') {
936
938
  const rel = toKbRelative(norm, kbDirName);
937
- return rel !== null && isPlatformFile(rel) ? platformFileRefusal(rel) : undefined;
939
+ return rel !== null && isPlatformFile(rel, kb.layout) ? platformFileRefusal(rel) : undefined;
938
940
  }
939
941
  if (norm === '' || norm === kbDirName) return platformFolderRefusal('');
940
942
  const rel = toKbRelative(norm, kbDirName);
941
- return rel !== null && isPlatformFolder(rel) ? platformFolderRefusal(rel) : undefined;
943
+ return rel !== null && isPlatformFolder(rel, kb.layout) ? platformFolderRefusal(rel) : undefined;
942
944
  };
943
945
 
944
946
  /** The workspace root on disk for `branch`. */
@@ -1170,6 +1172,15 @@ export function registerWorkspaceTools(
1170
1172
  proposable?: boolean;
1171
1173
  /** False for a tool that is not a file tool (the shell), which the content rule does not describe. */
1172
1174
  fileTool?: boolean;
1175
+ /**
1176
+ * This tool resolves `branch` ITSELF and must not be pre-checked here.
1177
+ * Only `execute_command` sets it: for an internal session that leaves the
1178
+ * argument off, it falls back to the caller's own focused branch (from its
1179
+ * signed token) rather than refusing. It still answers the same
1180
+ * `branch-required` kind when there is nothing to fall back on — see its
1181
+ * handler. Every other tool takes the check below.
1182
+ */
1183
+ resolvesBranchItself?: boolean;
1173
1184
  handler: ToolHandler;
1174
1185
  }): void => {
1175
1186
  const path = `/api/agent/tools/${spec.name}`;
@@ -1177,11 +1188,17 @@ export function registerWorkspaceTools(
1177
1188
  // tool the one content rule, and every tool a permission can refuse the
1178
1189
  // proposal route — appended once here so no tool (especially the
1179
1190
  // read-only ones a session hits first) can miss them.
1191
+ // Whether a call to this tool MUST name a branch, read off the tool's own
1192
+ // declaration rather than assumed of the family. Every tool mounted here
1193
+ // requires `branch` today; keying on the schema means a tool that declares
1194
+ // it optional (and resolves absence itself, as `list_tool_setup` does on its
1195
+ // own route) is not handed a refusal it never asked for.
1196
+ const requiresBranch = ((spec.inputs as { required?: string[] }).required ?? []).includes('branch');
1180
1197
  const describe = (): string =>
1181
1198
  (typeof spec.description === 'function' ? spec.description() : spec.description) +
1182
1199
  (spec.proposable ? PROPOSAL_ROUTE_NOTE : '') +
1183
1200
  (spec.fileTool === false ? '' : CONTENT_RULE) +
1184
- kbConventionsNote();
1201
+ kbConventionsNote(kb.layout);
1185
1202
  const def = toolDef({
1186
1203
  name: spec.name,
1187
1204
  description: describe(),
@@ -1199,7 +1216,7 @@ export function registerWorkspaceTools(
1199
1216
  // move the text with them. Rewritten in place: the registry holds this
1200
1217
  // object, both surfaces hold the same one, and re-registering would be a
1201
1218
  // duplicate name.
1202
- onKbLayoutApplied(() => {
1219
+ kb.onLayoutApplied(() => {
1203
1220
  def.description = describe();
1204
1221
  });
1205
1222
  // Internal-only tools (e.g. `execute_command`) keep their route mounted —
@@ -1222,6 +1239,16 @@ export function registerWorkspaceTools(
1222
1239
  // never reached the repository — the whole bug, spelled with a prefix.
1223
1240
  toolHandler(
1224
1241
  async (args, ctx) => {
1242
+ // FIRST, before the path work and before any handler: every tool
1243
+ // mounted here declares `branch` as a required, non-empty string, and
1244
+ // nothing enforced that, so a call that named none was carried down
1245
+ // until `workspaceIdForBranch` made a workspace directory out of the
1246
+ // missing value. Most of these tools would meet the same refusal one
1247
+ // layer down at `getFilesystem`, but not all of them do — `unzip`
1248
+ // hands `branch` straight to the workspace service by id — so the
1249
+ // check belongs on the mount every one of them shares rather than on
1250
+ // the resolver only some of them reach.
1251
+ if (requiresBranch && !spec.resolvesBranchItself) assertBranchProvided(args.branch);
1225
1252
  // BEFORE the normaliser: see `assertToolPathsNotGitInternals`.
1226
1253
  if (spec.fileTool !== false) await assertToolPathsNotGitInternals(args, ctx);
1227
1254
  const normalized = normalizePathArgs(
@@ -1250,7 +1277,7 @@ export function registerWorkspaceTools(
1250
1277
  err,
1251
1278
  { tool: spec.name, branch: args.branch, userEmail: ctx.user.email, userId: ctx.user.id },
1252
1279
  accessControl,
1253
- kbDirName,
1280
+ kb,
1254
1281
  changeGate,
1255
1282
  );
1256
1283
  }
@@ -1432,7 +1459,7 @@ export function registerWorkspaceTools(
1432
1459
  description: () =>
1433
1460
  'Get a file/directory\'s metadata (name, type, size, …) without returning content. A file also reports `contentMode`: `text` (read, write and edit it as text), `document` (read returns an extraction; replace it by upload) or `binary` (bytes: copy, move, delete, or replace by upload), plus `kind` (`text` | `document` | `image` | `binary`), `mime`, `mimeSource` and `textEditable` — decided by the same file readers read_file, grep and the write tools use, so an extensionless text file is `text/plain`.' +
1434
1461
  ' Every entry also reports what you may DO with it. ' +
1435
- `\`managed\` is true for a platform item — a platform file (${platformFileList()}) or a platform folder (the repository root or a reserved root folder such as \`KnowledgeBase/\`); managed items are never movable or deletable through these tools. ` +
1462
+ `\`managed\` is true for a platform item — a platform file (${platformFileList(kb.layout)}) or a platform folder (the repository root or a reserved root folder such as \`KnowledgeBase/\`); managed items are never movable or deletable through these tools. ` +
1436
1463
  '`access: { read, write, download, owner }` is your own verdict under the access rules; pass `explainAccess: true` to learn why, and who else holds each verb. `movable` and `deletable` say whether `move_file` / `delete_file` / `delete_folder` would be allowed for you, judged like their dry runs: not managed, no symbolic link, and on a protected branch you hold write on the item AND on every file under a folder (on a draft branch writes are not gated). `movable` judges the source side only; the destination is judged by a `move_file` dry run. ' +
1437
1464
  'For a folder, `descendants` is the number of files under it at any depth; counting stops at 10000 and `descendantsTruncated` says so, and past that point `movable` and `deletable` are false because a folder that large was not judged in full — run the `move_file` or `delete_folder` dry run for the real verdict. ' +
1438
1465
  'Call this before a move or delete to see what it would touch.' +
@@ -2042,7 +2069,7 @@ export function registerWorkspaceTools(
2042
2069
  name: 'delete_file',
2043
2070
  description: () =>
2044
2071
  'Delete ONE workspace file (a symbolic link is refused: links are never followed or removed). Committed + pushed as you. Its folder stays, even when this was its last file. Files only: a folder is refused with a pointer to `delete_folder`. ' +
2045
- `A platform file (\`access.md\` or \`.bevelignore\` in any folder, \`roles.yaml\` or \`${AGENTS_FILE}\` at the repository root) and git metadata are refused.` +
2072
+ `A platform file (\`access.md\` or \`.bevelignore\` in any folder, \`roles.yaml\` or \`${kb.layout.agentsFile}\` at the repository root) and git metadata are refused.` +
2046
2073
  ONTOLOGY_BOUNDARY_NOTE,
2047
2074
  inputs: {
2048
2075
  type: 'object',
@@ -2262,7 +2289,7 @@ export function registerWorkspaceTools(
2262
2289
  name: 'move_file',
2263
2290
  description: () =>
2264
2291
  'Move or rename a workspace FILE or FOLDER; a folder moves recursively, with everything under it. `dest` is the full new path, not the folder to move into. Lands as a delete + create, committed + pushed as you. ' +
2265
- `Rules: the destination must not exist — a move never overwrites a file or merges into a folder; a platform file (\`access.md\` or \`.bevelignore\` in any folder, \`roles.yaml\` or \`${AGENTS_FILE}\` at the repository root) is refused with "<name> is a platform file and stays in its folder." — a folder that moves takes its own platform files along, still in their folder; a platform folder (the repository root or a reserved root folder such as \`KnowledgeBase/\`) and git metadata are refused; a move cannot create a platform file or folder at \`dest\` either (renaming a note to \`access.md\` is refused); a path through a symbolic link is refused, since links are never followed; on a protected branch you must be able to write both ends — for a folder, every file under it at its old and its new path. ` +
2292
+ `Rules: the destination must not exist — a move never overwrites a file or merges into a folder; a platform file (\`access.md\` or \`.bevelignore\` in any folder, \`roles.yaml\` or \`${kb.layout.agentsFile}\` at the repository root) is refused with "<name> is a platform file and stays in its folder." — a folder that moves takes its own platform files along, still in their folder; a platform folder (the repository root or a reserved root folder such as \`KnowledgeBase/\`) and git metadata are refused; a move cannot create a platform file or folder at \`dest\` either (renaming a note to \`access.md\` is refused); a path through a symbolic link is refused, since links are never followed; on a protected branch you must be able to write both ends — for a folder, every file under it at its old and its new path. ` +
2266
2293
  'Access follows the destination folder. Preflight first: `dryRun: true` changes nothing and answers `{ src, dest, kind, descendants, access: { before, after }, accessChanges, allowed, reason? }` — `access` is your own `{ read, write, download, owner }` at the source and at the destination. ' +
2267
2294
  'A move whose `accessChanges` is true runs only with `confirm: true`; without it the call moves nothing and returns the same impact with `confirmationRequired: true`. Do NOT set `confirm: true` on your first call — dry-run, check the impact, then confirm.' +
2268
2295
  ONTOLOGY_BOUNDARY_NOTE,
@@ -2593,6 +2620,9 @@ export function registerWorkspaceTools(
2593
2620
  ONTOLOGY_BOUNDARY_NOTE,
2594
2621
  internalOnly: true,
2595
2622
  fileTool: false,
2623
+ // The one tool the mount's branch check skips: the handler below resolves an
2624
+ // omitted `branch` to the internal caller's focused branch before refusing.
2625
+ resolvesBranchItself: true,
2596
2626
  inputs: {
2597
2627
  type: 'object',
2598
2628
  properties: {
@@ -2649,6 +2679,11 @@ export function registerWorkspaceTools(
2649
2679
  throw new ToolError(
2650
2680
  'execute_command requires a `branch`: pass the branch (draft) whose workspace to run the command in — the one you are currently working on.',
2651
2681
  400,
2682
+ // The same discriminator every other KB tool answers a branch-less
2683
+ // call with, so a client switches on one kind across the surface.
2684
+ // The MESSAGE stays this tool's own: it can name the focused-branch
2685
+ // fallback that only applies here.
2686
+ { kind: 'branch-required' },
2652
2687
  );
2653
2688
  }
2654
2689
  // A stringified absent value. Both are syntactically valid git branch names,
@@ -2661,6 +2696,7 @@ export function registerWorkspaceTools(
2661
2696
  `execute_command got the literal string "${branch}" as \`branch\` — that is a stringified absent value, not a branch. ` +
2662
2697
  'Pass the real branch (draft) whose workspace to run the command in.',
2663
2698
  400,
2699
+ { kind: 'branch-required' },
2664
2700
  );
2665
2701
  }
2666
2702
  // Then the SHAPE, via the one canonical validator every other branch path
@@ -1,4 +1,5 @@
1
- import { branchAuthorLocalpart, isProtectedBranch, suggestionsBranchPrefixFor } from '@bevel-software/platform-shared';
1
+ import { branchAuthorLocalpart, suggestionsBranchPrefixFor } from '@bevel-software/platform-shared';
2
+ import type { KbContext } from '../../shared/kb-context.js';
2
3
  import { ToolError } from '../tool-helpers/tool.contract.js';
3
4
  import { AccessDeniedError } from '../access-model/access-errors.js';
4
5
  import type { IChangeReadGate } from '../access-model/change-gate.js';
@@ -111,9 +112,10 @@ export async function writeDenial(
111
112
  err: AccessDeniedError,
112
113
  input: { tool: string; branch: string; userEmail: string; userId: string },
113
114
  accessControl: IAccessControl,
114
- kbDirName: string,
115
+ kb: Pick<KbContext, 'kbDirName' | 'isProtectedBranch'>,
115
116
  changeGate?: IChangeReadGate,
116
117
  ): Promise<ToolError> {
118
+ const { kbDirName } = kb;
117
119
  const path = err.access.path;
118
120
  const base = { kind: 'write-denied' as const, path, reason: reasonOf(err) };
119
121
  const refuse = (cannotProposeReason: string): ToolError => {
@@ -121,7 +123,7 @@ export async function writeDenial(
121
123
  return new ToolError(`${err.message} ${cannotProposeReason}`, 403, { ...details });
122
124
  };
123
125
 
124
- if (!isProtectedBranch(input.branch)) {
126
+ if (!kb.isProtectedBranch(input.branch)) {
125
127
  return refuse(`Proposing is not available: "${input.branch}" is not a branch that accepts change requests.`);
126
128
  }
127
129
  // The lock gate reports workspace paths, the git gates repo-relative ones.
@@ -179,11 +181,11 @@ export async function rethrowAsWriteDenial(
179
181
  err: unknown,
180
182
  input: { tool: string; branch: unknown; userEmail: string; userId: string },
181
183
  accessControl: IAccessControl,
182
- kbDirName: string,
184
+ kb: Pick<KbContext, 'kbDirName' | 'isProtectedBranch'>,
183
185
  changeGate?: IChangeReadGate,
184
186
  ): Promise<never> {
185
187
  if (err instanceof AccessDeniedError && typeof input.branch === 'string') {
186
- throw await writeDenial(err, { ...input, branch: input.branch }, accessControl, kbDirName, changeGate);
188
+ throw await writeDenial(err, { ...input, branch: input.branch }, accessControl, kb, changeGate);
187
189
  }
188
190
  throw err;
189
191
  }
@@ -1,5 +1,8 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { pluginOfPath, PLUGINS_DIR } from '@bevel-software/platform-shared';
2
+ import { DEFAULT_KB_LAYOUT, pluginOfPath, PLUGINS_DIR } from '@bevel-software/platform-shared';
3
+
4
+ /** `pluginOfPath` under the default layout, which these cases are written against. */
5
+ const plugin = (path: string) => pluginOfPath(path, DEFAULT_KB_LAYOUT);
3
6
 
4
7
  /**
5
8
  * `pluginOfPath` is the whole of the grouping contract — the sidebar, the
@@ -9,9 +12,9 @@ import { pluginOfPath, PLUGINS_DIR } from '@bevel-software/platform-shared';
9
12
  */
10
13
  describe('pluginOfPath', () => {
11
14
  it('reads the plugin from the Plugins root', () => {
12
- expect(pluginOfPath(`${PLUGINS_DIR}/GTM/heyreach-campaign/SKILL.md`)).toBe('GTM');
13
- expect(pluginOfPath(`${PLUGINS_DIR}/GTM/heyreach.tool`)).toBe('GTM');
14
- expect(pluginOfPath(`${PLUGINS_DIR}/Engineering/review/architecture-review`)).toBe(
15
+ expect(plugin(`${PLUGINS_DIR}/GTM/heyreach-campaign/SKILL.md`)).toBe('GTM');
16
+ expect(plugin(`${PLUGINS_DIR}/GTM/heyreach.tool`)).toBe('GTM');
17
+ expect(plugin(`${PLUGINS_DIR}/Engineering/review/architecture-review`)).toBe(
15
18
  'Engineering',
16
19
  );
17
20
  });
@@ -19,27 +22,27 @@ describe('pluginOfPath', () => {
19
22
  it('returns null for content directly under the root — it has no plugin folder', () => {
20
23
  // The regression this guards: `Plugins/slack.tool` must NOT report a plugin
21
24
  // called "slack.tool", and `Plugins/GTM` must not report itself.
22
- expect(pluginOfPath(`${PLUGINS_DIR}/slack.tool`)).toBeNull();
23
- expect(pluginOfPath(`${PLUGINS_DIR}/GTM`)).toBeNull();
24
- expect(pluginOfPath(PLUGINS_DIR)).toBeNull();
25
+ expect(plugin(`${PLUGINS_DIR}/slack.tool`)).toBeNull();
26
+ expect(plugin(`${PLUGINS_DIR}/GTM`)).toBeNull();
27
+ expect(plugin(PLUGINS_DIR)).toBeNull();
25
28
  });
26
29
 
27
30
  it('returns null outside the plugin root', () => {
28
- expect(pluginOfPath('KnowledgeBase/Product/Knowledge/Foo.md')).toBeNull();
29
- expect(pluginOfPath('Data/Engineering/Knowledge/Bar.md')).toBeNull();
31
+ expect(plugin('KnowledgeBase/Product/Knowledge/Foo.md')).toBeNull();
32
+ expect(plugin('Data/Engineering/Knowledge/Bar.md')).toBeNull();
30
33
  // The retired pre-merge roots are ordinary non-plugin folders now.
31
- expect(pluginOfPath('Skills/GTM/heyreach-campaign')).toBeNull();
32
- expect(pluginOfPath('Tools/NewsAgent/serper.tool')).toBeNull();
33
- expect(pluginOfPath('access.md')).toBeNull();
34
- expect(pluginOfPath('')).toBeNull();
34
+ expect(plugin('Skills/GTM/heyreach-campaign')).toBeNull();
35
+ expect(plugin('Tools/NewsAgent/serper.tool')).toBeNull();
36
+ expect(plugin('access.md')).toBeNull();
37
+ expect(plugin('')).toBeNull();
35
38
  });
36
39
 
37
40
  it('is not fooled by a prefix match on the root name', () => {
38
- expect(pluginOfPath('PluginsOld/GTM/x')).toBeNull();
41
+ expect(plugin('PluginsOld/GTM/x')).toBeNull();
39
42
  });
40
43
 
41
44
  it('tolerates leading and doubled separators', () => {
42
- expect(pluginOfPath(`/${PLUGINS_DIR}/GTM/x`)).toBe('GTM');
43
- expect(pluginOfPath(`${PLUGINS_DIR}//GTM//x`)).toBe('GTM');
45
+ expect(plugin(`/${PLUGINS_DIR}/GTM/x`)).toBe('GTM');
46
+ expect(plugin(`${PLUGINS_DIR}//GTM//x`)).toBe('GTM');
44
47
  });
45
48
  });