@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
@@ -43,6 +43,7 @@ import type {
43
43
  ChangeRequestApplyFailureKind,
44
44
  ChangeRequestComment,
45
45
  ChangeRequestDetail,
46
+ ChangeRequestUpdateResult,
46
47
  ChangeRequestState,
47
48
  ChangedFile,
48
49
  FileApproval,
@@ -57,16 +58,16 @@ import type {
57
58
  RemoteSyncPullResult,
58
59
  } from '@bevel-software/platform-shared';
59
60
  import {
60
- isProtectedBranch,
61
- DEFAULT_BRANCH,
62
61
  isFolderPlaceholder,
63
62
  folderPlaceholderPath,
64
63
  isPlatformRestoreShape,
65
64
  } from '@bevel-software/platform-shared';
66
- import { and, eq, inArray, isNotNull, isNull, lt, or } from 'drizzle-orm';
65
+ import type { KbContext } from '../../shared/kb-context.js';
66
+ import { and, desc, eq, inArray, isNotNull, isNull, lt, ne, or } from 'drizzle-orm';
67
67
  import type { Database } from '../database/connection.js';
68
68
  import { changeRequests } from '../database/schema.js';
69
69
  import type { GitService } from './git/git.service.js';
70
+ import { redactSecret } from '../../shared/redact-secret.js';
70
71
  import type { PullRequestService } from './git/pull-request.service.js';
71
72
  import type { IReviewWorkflowService } from './review-workflow/review-workflow.interface.js';
72
73
  import type { WorkspaceService } from '../workspace/workspace.service.js';
@@ -156,12 +157,13 @@ export function syncConflictMessage(branch: string, conflictedPaths: string[]):
156
157
  /** How many conflicted files the sync-conflict sentence names before "and N more". */
157
158
  const SYNC_CONFLICT_FILES_NAMED = 3;
158
159
 
159
- /** Redact the shared GitHub token from any error string before surfacing it. */
160
- function redactTokens(msg: string): string {
161
- const tokens = [process.env.GITHUB_TOKEN, process.env.GH_TOKEN].filter(
162
- (t): t is string => !!t && t.length > 0,
163
- );
164
- return tokens.reduce((m, t) => m.replaceAll(t, '***'), msg);
160
+ /**
161
+ * Redact a git token from an error string before surfacing it: the one the
162
+ * knowledge base's runner authenticates with, plus whatever the environment
163
+ * holds (`redactSecret` names those itself).
164
+ */
165
+ function redactTokens(msg: string, token: string | null | undefined): string {
166
+ return redactSecret(msg, [token]);
165
167
  }
166
168
 
167
169
  /**
@@ -275,6 +277,10 @@ export class WorkflowService implements IWorkflowService {
275
277
  * implementation detail of the workflow auto-merge story; nothing outside
276
278
  * the facade should call it directly.
277
279
  */
280
+ private get kbDirName(): string {
281
+ return this.kb.kbDirName;
282
+ }
283
+
278
284
  constructor(
279
285
  private readonly db: Database,
280
286
  private readonly git: GitService,
@@ -291,7 +297,7 @@ export class WorkflowService implements IWorkflowService {
291
297
  * See `lock-decoupling-plan.md` for the full design.
292
298
  */
293
299
  private readonly pendingCommits: PendingCommitsService,
294
- private readonly kbDirName: string,
300
+ private readonly kb: KbContext,
295
301
  /**
296
302
  * The read-before-write gate `acquireLock` asks on every branch (see
297
303
  * `access-model/change-gate.ts`). Required, and checked at construction:
@@ -419,7 +425,7 @@ export class WorkflowService implements IWorkflowService {
419
425
  fn: () => Promise<T>,
420
426
  ): Promise<T> {
421
427
  const keys = [`branch:${source}`];
422
- if (!isProtectedBranch(target)) keys.push(`branch:${target}`);
428
+ if (!this.kb.isProtectedBranch(target)) keys.push(`branch:${target}`);
423
429
  return this.branchLifecycle.runAll(keys, fn);
424
430
  }
425
431
 
@@ -571,10 +577,14 @@ export class WorkflowService implements IWorkflowService {
571
577
  * and nothing else. The pull itself reports the change, since it is the
572
578
  * only code that can observe it under the workspace mutex.
573
579
  */
574
- private async pullWorkspace(workspaceId: string): Promise<boolean> {
575
- const { treeChanged } = await this.git.pull(workspaceId);
576
- if (treeChanged && branchForWorkspaceId(workspaceId) === DEFAULT_BRANCH) {
577
- this.events?.emit({ kind: 'fs-tree-changed', workspaceId, branch: DEFAULT_BRANCH });
580
+ private async pullWorkspace(
581
+ workspaceId: string,
582
+ opts: { preserveMerges?: boolean } = {},
583
+ ): Promise<boolean> {
584
+ const { treeChanged } = await this.git.pull(workspaceId, opts);
585
+ const defaultBranch = this.kb.defaultBranch;
586
+ if (treeChanged && branchForWorkspaceId(workspaceId) === defaultBranch) {
587
+ this.events?.emit({ kind: 'fs-tree-changed', workspaceId, branch: defaultBranch });
578
588
  return true;
579
589
  }
580
590
  return false;
@@ -961,7 +971,7 @@ export class WorkflowService implements IWorkflowService {
961
971
  // future caller can make that claim by passing a flag.
962
972
  if (
963
973
  typeof platformRestore?.source === 'string' &&
964
- isPlatformRestoreShape(toRepoRelative(platformRestore.source), repoRelative) &&
974
+ isPlatformRestoreShape(toRepoRelative(platformRestore.source), repoRelative, this.kb.layout) &&
965
975
  (await this.accessControl.canRestorePlatformFile(workspaceId, userEmail, repoRelative))
966
976
  ) {
967
977
  return 'restore';
@@ -1037,7 +1047,7 @@ export class WorkflowService implements IWorkflowService {
1037
1047
  // coordination hold as write possession (see those methods).
1038
1048
  if (!opts?.coordination) {
1039
1049
  let via: 'granted' | 'restore' = 'granted';
1040
- if (isProtectedBranch(branch)) {
1050
+ if (this.kb.isProtectedBranch(branch)) {
1041
1051
  // `assertCanWriteAtPath` throws AccessDeniedError on denial, with the
1042
1052
  // eligible-writers payload so the frontend can render a useful refusal.
1043
1053
  via = await this.assertCanWriteAtPath(
@@ -1321,7 +1331,8 @@ export class WorkflowService implements IWorkflowService {
1321
1331
  branch: string,
1322
1332
  targetPath: string,
1323
1333
  user: AuthUser,
1324
- opts?: { systemAuthorized?: boolean; skipValidation?: boolean },
1334
+ /** `summary` overrides the path-derived commit subject; see `commitFile`. */
1335
+ opts?: { systemAuthorized?: boolean; skipValidation?: boolean; summary?: string },
1325
1336
  ): Promise<void> {
1326
1337
  // `skipValidation` is the worker telling us this commit is not the last of
1327
1338
  // a burst. The validator is advisory — it parses the whole KB to produce a
@@ -1332,7 +1343,7 @@ export class WorkflowService implements IWorkflowService {
1332
1343
  workspaceId,
1333
1344
  user,
1334
1345
  targetPath,
1335
- undefined,
1346
+ opts?.summary,
1336
1347
  opts?.skipValidation,
1337
1348
  );
1338
1349
  if (!change) {
@@ -1722,6 +1733,38 @@ export class WorkflowService implements IWorkflowService {
1722
1733
  return this.prs.getPr(number);
1723
1734
  }
1724
1735
 
1736
+ /**
1737
+ * The newest non-open change request from `sourceBranch` by `authorEmail`.
1738
+ *
1739
+ * Read straight off `change_requests` rather than through the PR listing,
1740
+ * which serves OPEN requests only: the whole point here is the closed ones.
1741
+ * `author_email` is stored lowercased at insert, so the needle is too.
1742
+ * Ordered by `closed_at` with `created_at` as the tiebreak, because a row
1743
+ * closed before the column existed (or by a path that forgot to stamp it)
1744
+ * still has a creation time and must not sort as the oldest.
1745
+ */
1746
+ async latestClosedChangeRequest(
1747
+ authorEmail: string,
1748
+ sourceBranch: string,
1749
+ ): Promise<{ number: number; state: ChangeRequestState } | null> {
1750
+ const email = authorEmail.trim().toLowerCase();
1751
+ if (!email || !sourceBranch) return null;
1752
+ const [row] = await this.db
1753
+ .select({ number: changeRequests.number, state: changeRequests.state })
1754
+ .from(changeRequests)
1755
+ .where(
1756
+ and(
1757
+ eq(changeRequests.authorEmail, email),
1758
+ eq(changeRequests.sourceBranch, sourceBranch),
1759
+ ne(changeRequests.state, 'open'),
1760
+ ),
1761
+ )
1762
+ .orderBy(desc(changeRequests.closedAt), desc(changeRequests.createdAt))
1763
+ .limit(1);
1764
+ if (!row) return null;
1765
+ return { number: row.number, state: row.state as ChangeRequestState };
1766
+ }
1767
+
1725
1768
  getChangeRequestDetail(
1726
1769
  number: number,
1727
1770
  opts?: { fresh?: boolean; workspaceId?: string; viewerEmail?: string; patches?: boolean },
@@ -1759,7 +1802,7 @@ export class WorkflowService implements IWorkflowService {
1759
1802
  throw new WorkflowValidationError('source and target branches must differ');
1760
1803
  }
1761
1804
  if (!input.title?.trim()) throw new WorkflowValidationError('title is required');
1762
- if (isProtectedBranch(input.sourceBranch)) {
1805
+ if (this.kb.isProtectedBranch(input.sourceBranch)) {
1763
1806
  throw new WorkflowValidationError(
1764
1807
  `Cannot open a change request *from* a protected branch ("${input.sourceBranch}").`,
1765
1808
  { kind: 'source-is-protected', sourceBranch: input.sourceBranch },
@@ -1897,7 +1940,7 @@ export class WorkflowService implements IWorkflowService {
1897
1940
  // up-to-date) auto-merge, and inserts the row.
1898
1941
  const rawMsg = err instanceof Error ? err.message : String(err);
1899
1942
  throw new WorkflowValidationError(
1900
- `Failed to open change request: ${redactTokens(rawMsg)}`,
1943
+ `Failed to open change request: ${redactTokens(rawMsg, this.git.credentials?.token())}`,
1901
1944
  { kind: 'open-change-request-failed' },
1902
1945
  );
1903
1946
  }
@@ -1946,13 +1989,29 @@ export class WorkflowService implements IWorkflowService {
1946
1989
  * the enforcement read one predicate. A conflicting merge is aborted
1947
1990
  * inside `mergeFromOrigin`: nothing is committed or pushed, and the branch
1948
1991
  * is exactly what it was.
1992
+ *
1993
+ * ONE detail read after the merge. The read before it exists only to
1994
+ * decide authority and to name the two branches, so it asks for no patches
1995
+ * — that is one git subprocess per changed file it does not spend. The
1996
+ * approvals carry-forward runs BEFORE the final read rather than after it,
1997
+ * against a head resolved with `resolvePrShas` (two rev-parses) instead of
1998
+ * a whole second detail, so the detail that goes back already describes the
1999
+ * approvals it carried. What used to be three detail reads is now one.
1949
2000
  */
1950
2001
  async updateFromTarget(
1951
2002
  workspaceId: string,
1952
2003
  user: AuthUser,
1953
2004
  number: number,
1954
- ): Promise<ChangeRequestDetail> {
1955
- const detail = await this.prs.getPrDetail(number, { fresh: true, workspaceId, viewerEmail: user.email });
2005
+ ): Promise<ChangeRequestUpdateResult> {
2006
+ // No patches: all this read decides is authority, state and the two
2007
+ // branch names. Asking for patch text here would diff every changed file
2008
+ // in a request that is about to be merged and read in full anyway.
2009
+ const detail = await this.prs.getPrDetail(number, {
2010
+ fresh: true,
2011
+ workspaceId,
2012
+ viewerEmail: user.email,
2013
+ patches: false,
2014
+ });
1956
2015
  if (!detail) {
1957
2016
  throw new WorkflowValidationError(
1958
2017
  `Change request #${number} not found.`,
@@ -1980,8 +2039,15 @@ export class WorkflowService implements IWorkflowService {
1980
2039
  // merge commit that then cannot push, stranding it in the workspace. A
1981
2040
  // rebase conflict hands the stranded saves to recovery, as every other
1982
2041
  // pull does, before the refusal reaches the caller.
2042
+ //
2043
+ // `preserveMerges`: this is the one pull whose unpushed commit may be a
2044
+ // MERGE — the update that ran before this one and could not push. A plain
2045
+ // rebase replays it as cherry-picks of the target's commits, which drops
2046
+ // the target as a parent, so the branch never contains the target's head
2047
+ // however many times the update runs. Replayed with `--rebase-merges` it
2048
+ // stays a merge and the next push ends the loop.
1983
2049
  try {
1984
- await this.pullWorkspace(workspaceId);
2050
+ await this.pullWorkspace(workspaceId, { preserveMerges: true });
1985
2051
  } catch (err) {
1986
2052
  if (err instanceof PullRebaseConflictError) {
1987
2053
  await this.queuePullConflictRecovery(workspaceId, err, user);
@@ -2019,24 +2085,53 @@ export class WorkflowService implements IWorkflowService {
2019
2085
  if (outcome.kind === 'conflicts') {
2020
2086
  throw new ChangeRequestConflictsError(detail.branch, detail.base, outcome.paths);
2021
2087
  }
2022
- // If a new merge commit landed, push so the CR picks it up. When
2023
- // already up to date there's nothing to share — short-circuit the push.
2024
- if (!outcome.alreadyUpToDate) {
2088
+ // Push whenever the CLONE holds a commit origin has not seen — not when
2089
+ // THIS merge authored one. The two differ in exactly the case that keeps
2090
+ // a request behind for good: an earlier update merged, its push failed,
2091
+ // and the merge is sitting in the workspace. That merge already contains
2092
+ // the target, so this call's `mergeFromOrigin` reports
2093
+ // `alreadyUpToDate` and the old gate skipped the push — leaving the
2094
+ // request behind on the remote, and the next open with the same work to
2095
+ // do. Asking git what is unpushed retries it instead.
2096
+ //
2097
+ // A failed probe falls back to the old gate rather than to "push
2098
+ // anyway": `trackedPush` on a clone with nothing to push is a wasted
2099
+ // round trip on every single update.
2100
+ const hasUnpushed = await this.git
2101
+ .hasUnpushedCommits(workspaceId)
2102
+ .catch((err: unknown) => {
2103
+ log.warn(
2104
+ `could not tell whether change request #${number} has unpushed commits; falling back to whether this merge authored one`,
2105
+ { err },
2106
+ );
2107
+ return !outcome.alreadyUpToDate;
2108
+ });
2109
+ if (hasUnpushed) {
2025
2110
  await this.trackedPush(workspaceId, user);
2026
- // The source head moved: the refusal described a revision that is gone.
2027
- await this.clearApplyFailure(number, { recordedBefore: headMovedAfter });
2028
2111
  }
2029
- this.prs.invalidateDetailCache(number);
2030
- const refreshed = await this.prs.getPrDetail(number, {
2031
- fresh: true,
2032
- workspaceId,
2033
- viewerEmail: user.email,
2034
- });
2035
- if (!refreshed) {
2036
- throw new WorkflowValidationError(
2037
- `Refreshed change request #${number} but could not re-fetch its detail.`,
2112
+ // Where the branch ended up, as PUBLISHED — two rev-parses, not a second
2113
+ // detail read. Everything below needs only the sha, and the detail that
2114
+ // goes back to the caller is read once, at the end, after the approvals
2115
+ // it should describe have been carried.
2116
+ let headAfterMerge = headBeforeMerge;
2117
+ try {
2118
+ const at = await this.git.resolvePrShas(workspaceId, detail.base, detail.branch);
2119
+ headAfterMerge = at.headSha;
2120
+ } catch (err) {
2121
+ log.warn(
2122
+ `could not resolve the published head of change request #${number} after updating it from target`,
2123
+ { err },
2038
2124
  );
2039
2125
  }
2126
+ const headMoved = Boolean(headBeforeMerge) && headAfterMerge !== headBeforeMerge;
2127
+ // The source head moved: the refusal described a revision that is gone.
2128
+ // `hasUnpushed` counts as well as the sha comparison, and deliberately —
2129
+ // a push that just landed moved the published head by definition, and
2130
+ // reading the sha to confirm it is a call that can fail. A refusal left
2131
+ // standing over a revision nobody can apply any more is the worse error.
2132
+ if (headMoved || hasUnpushed) {
2133
+ await this.clearApplyFailure(number, { recordedBefore: headMovedAfter });
2134
+ }
2040
2135
  // The merge is a commit the APPROVERS did not make. Re-pin their
2041
2136
  // approvals onto the new head for every file whose bytes it left alone —
2042
2137
  // git's own two-dot diff between the two heads is the verdict on which
@@ -2044,45 +2139,61 @@ export class WorkflowService implements IWorkflowService {
2044
2139
  // than the bookkeeping, so a failure here is logged and the fresh detail
2045
2140
  // still goes back.
2046
2141
  //
2047
- // `alreadyUpToDate` is the real gate: no merge commit, no head to compare,
2048
- // nothing moved under anyone. The other two conditions are belt-and-braces
2049
- // over a sha that is not a sha — a resolve that failed onto a detail with
2050
- // no head, or two heads that somehow read equal — both of which
2051
- // `pathsChangedBetween` and `carryApprovalsForward` would refuse anyway.
2052
- // A merge that authored a commit cannot leave the head where it was.
2053
- if (!outcome.alreadyUpToDate && headBeforeMerge && refreshed.headSha !== headBeforeMerge) {
2142
+ // The head moving is the real gate: nothing moved, nothing moved under
2143
+ // anyone. It also covers the sha that is not a sha — a resolve that
2144
+ // failed onto a detail with no head — which `pathsChangedBetween` and
2145
+ // `carryApprovalsForward` would refuse anyway.
2146
+ //
2147
+ // This runs BEFORE the detail read, not after it. The rows it writes are
2148
+ // what the caller's `approvals` must describe, so doing it first means
2149
+ // the one read at the end is already correct — where carrying afterwards
2150
+ // needed a THIRD read to correct a detail assembled before the rows
2151
+ // existed.
2152
+ //
2153
+ // The same list answers the caller's `updatedPaths`: "which files did
2154
+ // this merge change" is one question, and the two answers must not be
2155
+ // allowed to differ — a file whose approval was carried (so: untouched)
2156
+ // that the dialog then re-read would be the dialog discarding content the
2157
+ // server just called unchanged.
2158
+ let updatedPaths: string[] = [];
2159
+ if (headMoved) {
2054
2160
  try {
2055
- const changedPaths = await this.git.pathsChangedBetween(
2161
+ updatedPaths = await this.git.pathsChangedBetween(
2056
2162
  workspaceId,
2057
2163
  headBeforeMerge,
2058
- refreshed.headSha,
2164
+ headAfterMerge,
2059
2165
  );
2060
- const carried = await this.reviewWorkflow.carryApprovalsForward(
2166
+ await this.reviewWorkflow.carryApprovalsForward(
2061
2167
  number,
2062
2168
  headBeforeMerge,
2063
- refreshed.headSha,
2064
- changedPaths,
2169
+ headAfterMerge,
2170
+ updatedPaths,
2065
2171
  );
2066
- // The detail above was assembled before those rows existed, so its
2067
- // `approvals` (and the merge gate derived from them) still describe
2068
- // the pre-merge head. Only re-read when something actually carried.
2069
- if (carried > 0) {
2070
- this.prs.invalidateDetailCache(number);
2071
- const withApprovals = await this.prs.getPrDetail(number, {
2072
- fresh: true,
2073
- workspaceId,
2074
- viewerEmail: user.email,
2075
- });
2076
- if (withApprovals) return withApprovals;
2077
- }
2078
2172
  } catch (err) {
2079
2173
  log.warn(
2080
2174
  `could not carry approvals forward on change request #${number} after updating from target`,
2081
2175
  { err },
2082
2176
  );
2177
+ // The diff is what failed, so which files moved is unknown. Say so as
2178
+ // "every file this request had", which is every file a caller can
2179
+ // already be showing: slow beats a dialog that goes on presenting
2180
+ // pre-merge text as current. Anything the merge ADDED is not on the
2181
+ // list and does not need to be — no caller has read it yet.
2182
+ updatedPaths = (detail.files ?? []).map((f) => f.path);
2083
2183
  }
2084
2184
  }
2085
- return refreshed;
2185
+ this.prs.invalidateDetailCache(number);
2186
+ const refreshed = await this.prs.getPrDetail(number, {
2187
+ fresh: true,
2188
+ workspaceId,
2189
+ viewerEmail: user.email,
2190
+ });
2191
+ if (!refreshed) {
2192
+ throw new WorkflowValidationError(
2193
+ `Refreshed change request #${number} but could not re-fetch its detail.`,
2194
+ );
2195
+ }
2196
+ return { ...refreshed, updatedPaths };
2086
2197
  }
2087
2198
 
2088
2199
  listComments(number: number): Promise<ChangeRequestComment[]> {
@@ -2644,11 +2755,16 @@ export class WorkflowService implements IWorkflowService {
2644
2755
  /**
2645
2756
  * DELETE a change request outright: close it (whatever its diff says) and
2646
2757
  * retire its source branch — the request, its proposal, and the branch that
2647
- * carried it are gone in one verb. Admin-only, resolved the same way every
2648
- * other admin check here is (write on `roles.yaml` at `origin/<base>`,
2649
- * never a local ref): this is the moderation verb for a shared deployment,
2650
- * stronger than reject (which the author or the files' owners can do, and
2651
- * which leaves the branch for a second round).
2758
+ * carried it are gone in one verb. The request's AUTHOR or an admin, and
2759
+ * nobody else: it is the author's own proposal and their own branch to throw
2760
+ * away, and it is the moderation verb for a shared deployment. Admin rights
2761
+ * resolve the same way every other admin check here does (write on
2762
+ * `roles.yaml` at `origin/<base>`, never a local ref); authorship is the
2763
+ * STORED `authorId` hash, never anything the caller sends.
2764
+ *
2765
+ * Stronger than reject, which the changed files' owners may also do and which
2766
+ * leaves the branch for a second round. They keep reject and do not get this:
2767
+ * an owner must not be able to destroy someone else's text and branch.
2652
2768
  */
2653
2769
  async deleteChangeRequest(number: number, user: AuthUser): Promise<void> {
2654
2770
  const summary = await this.prs.getPr(number);
@@ -2707,8 +2823,17 @@ export class WorkflowService implements IWorkflowService {
2707
2823
  409,
2708
2824
  );
2709
2825
  }
2710
- if (isAdmin !== true) {
2711
- throw new WorkflowDomainError('Only an admin can delete a change request.', 403);
2826
+ // Authorship is decided from the STORED author hash, never from anything
2827
+ // the caller sends. Note what is deliberately NOT short-circuited for an
2828
+ // author: the strict fetch and the `null` check above still run. An
2829
+ // author's grant needs no `roles.yaml` read, so skipping them would look
2830
+ // free — but it would let a delete close the request while the branch
2831
+ // removal silently failed against an unreachable origin, and "the shared
2832
+ // repository was down, so nothing changed" is the one refusal that has to
2833
+ // stay honest.
2834
+ const callerIsAuthor = !!(summary.authorId && summary.authorId === hashEmail(user.email));
2835
+ if (!callerIsAuthor && isAdmin !== true) {
2836
+ throw new WorkflowDomainError("Only the request's author or an admin can delete it.", 403);
2712
2837
  }
2713
2838
 
2714
2839
  // Close first (idempotent: an already-closed request just skips to the
@@ -2851,7 +2976,7 @@ export class WorkflowService implements IWorkflowService {
2851
2976
 
2852
2977
  let live: Set<string>;
2853
2978
  try {
2854
- const branches = await this.git.listBranches(workspaceIdForBranch(DEFAULT_BRANCH), {
2979
+ const branches = await this.git.listBranches(this.kb.defaultWorkspaceId(), {
2855
2980
  freshFetch: true,
2856
2981
  // The list is used to PROVE absence, and the listing's normal
2857
2982
  // degrade-to-stale behaviour would report every branch created since
@@ -3166,8 +3291,8 @@ export class WorkflowService implements IWorkflowService {
3166
3291
  // outright if it disagrees with the request's own base.) The failure the
3167
3292
  // pull reports is about OTHER people's commits not arriving, which leaves
3168
3293
  // the catalogs no staler than they were.
3169
- if (!announced && targetWorkspaceId && targetBranch === DEFAULT_BRANCH) {
3170
- this.events?.emit({ kind: 'fs-tree-changed', workspaceId: targetWorkspaceId, branch: DEFAULT_BRANCH });
3294
+ if (!announced && targetWorkspaceId && targetBranch === this.kb.defaultBranch) {
3295
+ this.events?.emit({ kind: 'fs-tree-changed', workspaceId: targetWorkspaceId, branch: targetBranch });
3171
3296
  }
3172
3297
  }
3173
3298
 
@@ -3234,7 +3359,7 @@ export class WorkflowService implements IWorkflowService {
3234
3359
  // change request's merge, nothing strips it here — so its presence
3235
3360
  // is what the hook refuses on) and both sides of a rename, since the
3236
3361
  // old name is a file this merge deletes.
3237
- authorize: isProtectedBranch(targetBranch)
3362
+ authorize: this.kb.isProtectedBranch(targetBranch)
3238
3363
  ? async ({ sha, changedPaths }) => {
3239
3364
  if (changedPaths.length === 0) return;
3240
3365
  // roles.yaml never changes through a merge. A change request's
@@ -3445,7 +3570,7 @@ export class WorkflowService implements IWorkflowService {
3445
3570
  .where(eq(changeRequests.number, number))
3446
3571
  .limit(1);
3447
3572
  const sourceBranch = rows[0]?.sourceBranch;
3448
- if (!sourceBranch || isProtectedBranch(sourceBranch)) return;
3573
+ if (!sourceBranch || this.kb.isProtectedBranch(sourceBranch)) return;
3449
3574
  // The open-check and the deletion hold the branch's lifecycle lock
3450
3575
  // TOGETHER — `openChangeRequest` holds the same lock across its own
3451
3576
  // check-then-insert, so a request being opened from this branch either
@@ -3620,7 +3745,7 @@ export class WorkflowService implements IWorkflowService {
3620
3745
  return stdout.split('\n').map((s) => s.trim()).filter(Boolean);
3621
3746
  } catch (err) {
3622
3747
  log.warn('listChangedPathsBetweenBranches failed:', {
3623
- detail: redactTokens(err instanceof Error ? err.message : String(err)),
3748
+ detail: redactTokens(err instanceof Error ? err.message : String(err), this.git.credentials?.token()),
3624
3749
  });
3625
3750
  return [];
3626
3751
  }
@@ -4,6 +4,7 @@ import { tmpdir } from 'node:os';
4
4
  import { dirname, join } from 'node:path';
5
5
  import express from 'express';
6
6
  import { afterAll, beforeAll, describe, expect, it } from 'vitest';
7
+ import { testKbContext } from '../../../__tests__/kb-context.js';
7
8
  import { LocalFilesystem } from '@mastra/core/workspace';
8
9
  import { ToolRegistry } from '../../tool-registry/tool-registry.js';
9
10
  import { createToolHandlerFactory } from '../../tool-helpers/tool-handler.js';
@@ -86,8 +87,8 @@ beforeAll(async () => {
86
87
  new SpillStore(join(tmpdir(), 'bevel-test-spills')),
87
88
  new DocExtractService(docCache),
88
89
  service,
89
- KB,
90
- { service: {} as never, enabled: false, kbDirName: KB, recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
90
+ testKbContext({ kbDirName: KB }),
91
+ { service: {} as never, enabled: false, kb: testKbContext({ kbDirName: KB }), recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
91
92
  new RoutineWritePolicyService(),
92
93
  {} as never,
93
94
  );
@@ -6,6 +6,7 @@ import { join } from 'node:path';
6
6
  import AdmZip from 'adm-zip';
7
7
  import express from 'express';
8
8
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
9
+ import { testKbContext } from '../../../__tests__/kb-context.js';
9
10
  import type { IWorkflowService } from '@bevel-software/platform-shared';
10
11
  import { GIT_INTERNALS_MESSAGE, GitInternalsError } from '../../../shared/domain-errors.js';
11
12
  import { workspaceIdForBranch } from '../../../shared/workspace-id.js';
@@ -241,7 +242,7 @@ describe('workspace tools refuse the git folder', () => {
241
242
 
242
243
  beforeEach(async () => {
243
244
  workflow = makeWorkflow();
244
- const service = new WorkspaceService(root, 'https://example.invalid/kb.git', KB, new NodeFs());
245
+ const service = new WorkspaceService(root, 'https://example.invalid/kb.git', testKbContext({ kbDirName: KB }), new NodeFs());
245
246
  unzipSpy = vi.spyOn(service, 'unzipFile');
246
247
  bootstrappedSpy = vi.spyOn(service, 'hasBootstrappedWorkspace');
247
248
  const lockingFs = new LockingFilesystem(
@@ -275,8 +276,8 @@ describe('workspace tools refuse the git folder', () => {
275
276
  new SpillStore(join(root, 'spills')),
276
277
  new DocExtractService(join(root, 'doc-cache')),
277
278
  allowAll,
278
- KB,
279
- { service: {} as never, enabled: false, kbDirName: KB, recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
279
+ testKbContext({ kbDirName: KB }),
280
+ { service: {} as never, enabled: false, kb: testKbContext({ kbDirName: KB }), recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
280
281
  new RoutineWritePolicyService(),
281
282
  {} as never,
282
283
  );
@@ -416,7 +417,7 @@ describe('workspace routes refuse the git folder', () => {
416
417
 
417
418
  beforeEach(async () => {
418
419
  workflow = makeWorkflow();
419
- service = new WorkspaceService(root, 'https://example.invalid/kb.git', KB, new NodeFs());
420
+ service = new WorkspaceService(root, 'https://example.invalid/kb.git', testKbContext({ kbDirName: KB }), new NodeFs());
420
421
  const app = express();
421
422
  app.use(express.json());
422
423
  app.use('/api', (req, _res, next) => {
@@ -436,7 +437,7 @@ describe('workspace routes refuse the git folder', () => {
436
437
  workflow as unknown as IWorkflowService,
437
438
  { emit: vi.fn() } as unknown as WorkflowEventBus,
438
439
  allowAll,
439
- KB,
440
+ testKbContext({ kbDirName: KB }),
440
441
  stubCreatorAccess,
441
442
  { isAdmin: async () => true } as unknown as IAdminAccessService,
442
443
  new NodeFs(),
@@ -563,7 +564,7 @@ describe('WorkspaceService refuses the git folder on its own', () => {
563
564
  let service: WorkspaceService;
564
565
 
565
566
  beforeEach(() => {
566
- service = new WorkspaceService(root, 'https://example.invalid/kb.git', KB, new NodeFs());
567
+ service = new WorkspaceService(root, 'https://example.invalid/kb.git', testKbContext({ kbDirName: KB }), new NodeFs());
567
568
  });
568
569
 
569
570
  afterEach(async () => {
@@ -620,7 +621,7 @@ describe('WorkspaceService refuses the git folder on its own', () => {
620
621
  return { stdout: '.git\n', stderr: '', code: 0 };
621
622
  }),
622
623
  };
623
- const refService = new WorkspaceService(root, 'https://example.invalid/kb.git', KB, new NodeFs(), 'x-access-token', gitRunner as never);
624
+ const refService = new WorkspaceService(root, 'https://example.invalid/kb.git', testKbContext({ kbDirName: KB }), new NodeFs(), gitRunner as never);
624
625
 
625
626
  for (const [form, raw] of Object.entries(fileForms('config'))) {
626
627
  if (!form.startsWith('symlinked')) continue;
@@ -674,7 +675,7 @@ describe('the route guard on its own', () => {
674
675
  beforeEach(async () => {
675
676
  reached = 0;
676
677
  userId = USER.id;
677
- const service = new WorkspaceService(root, 'https://example.invalid/kb.git', KB, new NodeFs());
678
+ const service = new WorkspaceService(root, 'https://example.invalid/kb.git', testKbContext({ kbDirName: KB }), new NodeFs());
678
679
  const app = express();
679
680
  // The server's own order: the guard ahead of the body parser, then again
680
681
  // on the parsed body, then again once the caller is known.
@@ -774,7 +775,7 @@ describe('DiffService refuses the git folder on its own', () => {
774
775
  let diffService: DiffService;
775
776
 
776
777
  beforeEach(() => {
777
- const service = new WorkspaceService(root, 'https://example.invalid/kb.git', KB, new NodeFs());
778
+ const service = new WorkspaceService(root, 'https://example.invalid/kb.git', testKbContext({ kbDirName: KB }), new NodeFs());
778
779
  diffService = new DiffService(service, new WorkspaceMutex(), root, join(root, 'backups'), KB, new NodeFs());
779
780
  });
780
781
 
@@ -11,8 +11,10 @@ import type { ToolContext } from '../../tool-helpers/tool.contract.js';
11
11
  import type { ISessionOntologyService, OperationDecision } from '../../workflow/session-ontology.service.js';
12
12
  import { WorkflowHooks } from '../../workflow/workflow-hooks.js';
13
13
  import { ontologyOf } from '../../../shared/kb-layout.js';
14
+ import { testKbContext } from '../../../__tests__/kb-context.js';
14
15
 
15
16
  const KB = 'knowledge-base';
17
+ const kbContext = testKbContext({ kbDirName: KB });
16
18
  const P_FILE = 'KnowledgeBase/Product/Knowledge/Foo.md';
17
19
  const PL_FILE = 'KnowledgeBase/Platform/Knowledge/Bar.md';
18
20
  const NEUTRAL = 'access.md';
@@ -28,7 +30,7 @@ function makeFakeService(): ISessionOntologyService {
28
30
  const setFor = (s: string) => touched.get(s) ?? new Set<string>();
29
31
  return {
30
32
  async checkOperation(sessionId, wsPath, isWrite): Promise<OperationDecision> {
31
- const ont = ontologyOf(wsPath, KB);
33
+ const ont = ontologyOf(wsPath, kbContext.layout, KB);
32
34
  const set = setFor(sessionId);
33
35
  if (ont === null) return { allow: true, touched: [...set].sort() };
34
36
  if (isWrite) {
@@ -63,7 +65,7 @@ function makeFakeService(): ISessionOntologyService {
63
65
  function makeGate(): SessionOntologyGate {
64
66
  const service = makeFakeService();
65
67
  const hooks = new WorkflowHooks();
66
- return { service, enabled: true, kbDirName: KB, recoveryBotEmail: RECOVERY_EMAIL, hooks };
68
+ return { service, enabled: true, kb: kbContext, recoveryBotEmail: RECOVERY_EMAIL, hooks };
67
69
  }
68
70
 
69
71
  function ctx(overrides: Partial<ToolContext> = {}): ToolContext {
@@ -7,6 +7,7 @@ import { fileURLToPath } from 'node:url';
7
7
  import AdmZip from 'adm-zip';
8
8
  import express from 'express';
9
9
  import { describe, it, expect, afterEach, vi } from 'vitest';
10
+ import { testKbContext } from '../../../__tests__/kb-context.js';
10
11
  import type { IWorkflowService } from '@bevel-software/platform-shared';
11
12
  import { NodeFs } from '../../kb-fs/node-fs.js';
12
13
  import type { IAccessControl } from '../../access/access-control.interface.js';
@@ -55,7 +56,7 @@ async function makeHarness(): Promise<Harness> {
55
56
  const workspaceDir = path.join(root, workspaceId);
56
57
  // The inner `.git` lets the service accept the workspace without cloning.
57
58
  await fs.mkdir(path.join(workspaceDir, KB, '.git'), { recursive: true });
58
- const workspaceService = new WorkspaceService(root, 'https://example.invalid/kb.git', KB, new NodeFs());
59
+ const workspaceService = new WorkspaceService(root, 'https://example.invalid/kb.git', testKbContext({ kbDirName: KB }), new NodeFs());
59
60
  await workspaceService.getWorkspacePath(workspaceId);
60
61
 
61
62
  const asked: string[] = [];
@@ -102,7 +103,7 @@ async function makeHarness(): Promise<Harness> {
102
103
  workflowService,
103
104
  { emit: vi.fn() } as unknown as WorkflowEventBus,
104
105
  accessControl,
105
- KB,
106
+ testKbContext({ kbDirName: KB }),
106
107
  stubCreatorAccess,
107
108
  { isAdmin: async () => false } as unknown as IAdminAccessService,
108
109
  new NodeFs(),
@@ -2,6 +2,7 @@ import type { Server } from 'node:http';
2
2
  import type { AddressInfo } from 'node:net';
3
3
  import express from 'express';
4
4
  import { describe, it, expect, afterEach, vi } from 'vitest';
5
+ import { testKbContext } from '../../../__tests__/kb-context.js';
5
6
  import { NodeFs } from '../../kb-fs/node-fs.js';
6
7
  import type { FileTreeEntry, IWorkflowService } from '@bevel-software/platform-shared';
7
8
  import type { IAccessControl } from '../../access/access-control.interface.js';
@@ -55,7 +56,7 @@ async function makeHarness(
55
56
  {} as unknown as IWorkflowService,
56
57
  { emit: vi.fn() } as unknown as WorkflowEventBus,
57
58
  accessControl,
58
- 'knowledge-base',
59
+ testKbContext(),
59
60
  stubCreatorAccess,
60
61
  { isAdmin: async () => false } as unknown as IAdminAccessService,
61
62
  new NodeFs(),