@bevel-software/platform-core-backend 0.20.0 → 0.21.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 (576) 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 +23 -105
  11. package/dist/core/create-core-server.js.map +1 -1
  12. package/dist/core/create-core-services.d.ts +30 -5
  13. package/dist/core/create-core-services.d.ts.map +1 -1
  14. package/dist/core/create-core-services.js +136 -81
  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.routes.d.ts +2 -1
  37. package/dist/modules/access/access.routes.d.ts.map +1 -1
  38. package/dist/modules/access/access.routes.js +10 -10
  39. package/dist/modules/access/access.routes.js.map +1 -1
  40. package/dist/modules/access/change-read-gate.d.ts +6 -3
  41. package/dist/modules/access/change-read-gate.d.ts.map +1 -1
  42. package/dist/modules/access/change-read-gate.js +9 -6
  43. package/dist/modules/access/change-read-gate.js.map +1 -1
  44. package/dist/modules/access/creator-access.d.ts +4 -2
  45. package/dist/modules/access/creator-access.d.ts.map +1 -1
  46. package/dist/modules/access/creator-access.js +7 -4
  47. package/dist/modules/access/creator-access.js.map +1 -1
  48. package/dist/modules/agent-instructions/read-preamble.d.ts +2 -1
  49. package/dist/modules/agent-instructions/read-preamble.d.ts.map +1 -1
  50. package/dist/modules/agent-instructions/read-preamble.js +6 -9
  51. package/dist/modules/agent-instructions/read-preamble.js.map +1 -1
  52. package/dist/modules/auth/account-admission.d.ts +40 -0
  53. package/dist/modules/auth/account-admission.d.ts.map +1 -0
  54. package/dist/modules/auth/account-admission.js +17 -0
  55. package/dist/modules/auth/account-admission.js.map +1 -0
  56. package/dist/modules/auth/account.routes.d.ts.map +1 -1
  57. package/dist/modules/auth/account.routes.js +4 -1
  58. package/dist/modules/auth/account.routes.js.map +1 -1
  59. package/dist/modules/auth/auth.service.d.ts +19 -1
  60. package/dist/modules/auth/auth.service.d.ts.map +1 -1
  61. package/dist/modules/auth/auth.service.js +33 -1
  62. package/dist/modules/auth/auth.service.js.map +1 -1
  63. package/dist/modules/auth/oidc-auth-provider.d.ts.map +1 -1
  64. package/dist/modules/auth/oidc-auth-provider.js +9 -0
  65. package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
  66. package/dist/modules/connection-probe/connection-probe.service.d.ts +13 -1
  67. package/dist/modules/connection-probe/connection-probe.service.d.ts.map +1 -1
  68. package/dist/modules/connection-probe/connection-probe.service.js +10 -2
  69. package/dist/modules/connection-probe/connection-probe.service.js.map +1 -1
  70. package/dist/modules/database/advisory-lock.d.ts +17 -0
  71. package/dist/modules/database/advisory-lock.d.ts.map +1 -1
  72. package/dist/modules/database/advisory-lock.js +24 -3
  73. package/dist/modules/database/advisory-lock.js.map +1 -1
  74. package/dist/modules/database/connection.d.ts +67 -2
  75. package/dist/modules/database/connection.d.ts.map +1 -1
  76. package/dist/modules/database/connection.js +118 -12
  77. package/dist/modules/database/connection.js.map +1 -1
  78. package/dist/modules/database/migrate.d.ts +1 -1
  79. package/dist/modules/database/migrate.d.ts.map +1 -1
  80. package/dist/modules/database/migrate.js +27 -3
  81. package/dist/modules/database/migrate.js.map +1 -1
  82. package/dist/modules/kb-fs/branch-name.d.ts +0 -1
  83. package/dist/modules/kb-fs/branch-name.d.ts.map +1 -1
  84. package/dist/modules/kb-fs/branch-name.js +3 -3
  85. package/dist/modules/kb-fs/branch-name.js.map +1 -1
  86. package/dist/modules/kb-fs/clone-config.d.ts +9 -8
  87. package/dist/modules/kb-fs/clone-config.d.ts.map +1 -1
  88. package/dist/modules/kb-fs/clone-config.js +14 -12
  89. package/dist/modules/kb-fs/clone-config.js.map +1 -1
  90. package/dist/modules/mcp/mcp.service.d.ts +7 -0
  91. package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
  92. package/dist/modules/mcp/mcp.service.js +4 -4
  93. package/dist/modules/mcp/mcp.service.js.map +1 -1
  94. package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts +4 -4
  95. package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts.map +1 -1
  96. package/dist/modules/plugins/compile/marketplace-compiler.service.js +7 -10
  97. package/dist/modules/plugins/compile/marketplace-compiler.service.js.map +1 -1
  98. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts +4 -1
  99. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts.map +1 -1
  100. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js +5 -3
  101. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js.map +1 -1
  102. package/dist/modules/plugins/discovery/kb-plugin-source.d.ts +6 -1
  103. package/dist/modules/plugins/discovery/kb-plugin-source.d.ts.map +1 -1
  104. package/dist/modules/plugins/discovery/kb-plugin-source.js +14 -9
  105. package/dist/modules/plugins/discovery/kb-plugin-source.js.map +1 -1
  106. package/dist/modules/plugins/discovery/native.source.d.ts +4 -1
  107. package/dist/modules/plugins/discovery/native.source.d.ts.map +1 -1
  108. package/dist/modules/plugins/discovery/native.source.js +4 -2
  109. package/dist/modules/plugins/discovery/native.source.js.map +1 -1
  110. package/dist/modules/plugins/index.d.ts +1 -1
  111. package/dist/modules/plugins/index.d.ts.map +1 -1
  112. package/dist/modules/plugins/index.js +1 -1
  113. package/dist/modules/plugins/index.js.map +1 -1
  114. package/dist/modules/plugins/join-request-jobs.service.d.ts +3 -1
  115. package/dist/modules/plugins/join-request-jobs.service.d.ts.map +1 -1
  116. package/dist/modules/plugins/join-request-jobs.service.js +6 -6
  117. package/dist/modules/plugins/join-request-jobs.service.js.map +1 -1
  118. package/dist/modules/plugins/join-requests.service.d.ts +3 -1
  119. package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
  120. package/dist/modules/plugins/join-requests.service.js +9 -8
  121. package/dist/modules/plugins/join-requests.service.js.map +1 -1
  122. package/dist/modules/plugins/plugin-links.d.ts +65 -10
  123. package/dist/modules/plugins/plugin-links.d.ts.map +1 -1
  124. package/dist/modules/plugins/plugin-links.js +136 -31
  125. package/dist/modules/plugins/plugin-links.js.map +1 -1
  126. package/dist/modules/plugins/plugin-links.service.d.ts +107 -5
  127. package/dist/modules/plugins/plugin-links.service.d.ts.map +1 -1
  128. package/dist/modules/plugins/plugin-links.service.js +151 -21
  129. package/dist/modules/plugins/plugin-links.service.js.map +1 -1
  130. package/dist/modules/plugins/plugin-provision.service.d.ts +10 -3
  131. package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
  132. package/dist/modules/plugins/plugin-provision.service.js +33 -26
  133. package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
  134. package/dist/modules/plugins/plugin-rename.service.d.ts +4 -2
  135. package/dist/modules/plugins/plugin-rename.service.d.ts.map +1 -1
  136. package/dist/modules/plugins/plugin-rename.service.js +10 -12
  137. package/dist/modules/plugins/plugin-rename.service.js.map +1 -1
  138. package/dist/modules/plugins/plugins.routes.d.ts +3 -0
  139. package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
  140. package/dist/modules/plugins/plugins.routes.js +45 -15
  141. package/dist/modules/plugins/plugins.routes.js.map +1 -1
  142. package/dist/modules/plugins/plugins.service.d.ts +4 -4
  143. package/dist/modules/plugins/plugins.service.d.ts.map +1 -1
  144. package/dist/modules/plugins/plugins.service.js +7 -10
  145. package/dist/modules/plugins/plugins.service.js.map +1 -1
  146. package/dist/modules/plugins/teams.routes.d.ts +4 -1
  147. package/dist/modules/plugins/teams.routes.d.ts.map +1 -1
  148. package/dist/modules/plugins/teams.routes.js +11 -9
  149. package/dist/modules/plugins/teams.routes.js.map +1 -1
  150. package/dist/modules/secrets-vault/index.d.ts +1 -1
  151. package/dist/modules/secrets-vault/index.d.ts.map +1 -1
  152. package/dist/modules/secrets-vault/index.js +1 -1
  153. package/dist/modules/secrets-vault/index.js.map +1 -1
  154. package/dist/modules/secrets-vault/secrets-variable-loader.d.ts +29 -11
  155. package/dist/modules/secrets-vault/secrets-variable-loader.d.ts.map +1 -1
  156. package/dist/modules/secrets-vault/secrets-variable-loader.js +46 -21
  157. package/dist/modules/secrets-vault/secrets-variable-loader.js.map +1 -1
  158. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +3 -0
  159. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
  160. package/dist/modules/secrets-vault/secrets-vault.routes.js +4 -6
  161. package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
  162. package/dist/modules/settings/deployment-settings.service.d.ts +12 -8
  163. package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
  164. package/dist/modules/settings/deployment-settings.service.js +20 -22
  165. package/dist/modules/settings/deployment-settings.service.js.map +1 -1
  166. package/dist/modules/settings/setup.routes.d.ts +9 -2
  167. package/dist/modules/settings/setup.routes.d.ts.map +1 -1
  168. package/dist/modules/settings/setup.routes.js +20 -14
  169. package/dist/modules/settings/setup.routes.js.map +1 -1
  170. package/dist/modules/skills/allowed-tools-check.d.ts +4 -3
  171. package/dist/modules/skills/allowed-tools-check.d.ts.map +1 -1
  172. package/dist/modules/skills/allowed-tools-check.js +8 -8
  173. package/dist/modules/skills/allowed-tools-check.js.map +1 -1
  174. package/dist/modules/skills/pending-skills.service.d.ts +3 -1
  175. package/dist/modules/skills/pending-skills.service.d.ts.map +1 -1
  176. package/dist/modules/skills/pending-skills.service.js +9 -6
  177. package/dist/modules/skills/pending-skills.service.js.map +1 -1
  178. package/dist/modules/skills/skill-access-requests.routes.d.ts +2 -1
  179. package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -1
  180. package/dist/modules/skills/skill-access-requests.routes.js +6 -6
  181. package/dist/modules/skills/skill-access-requests.routes.js.map +1 -1
  182. package/dist/modules/skills/skills.routes.d.ts +4 -1
  183. package/dist/modules/skills/skills.routes.d.ts.map +1 -1
  184. package/dist/modules/skills/skills.routes.js +4 -4
  185. package/dist/modules/skills/skills.routes.js.map +1 -1
  186. package/dist/modules/skills/skills.service.d.ts +4 -2
  187. package/dist/modules/skills/skills.service.d.ts.map +1 -1
  188. package/dist/modules/skills/skills.service.js +13 -11
  189. package/dist/modules/skills/skills.service.js.map +1 -1
  190. package/dist/modules/tool-manuals/mcp-json-discovery.d.ts +2 -1
  191. package/dist/modules/tool-manuals/mcp-json-discovery.d.ts.map +1 -1
  192. package/dist/modules/tool-manuals/mcp-json-discovery.js +6 -5
  193. package/dist/modules/tool-manuals/mcp-json-discovery.js.map +1 -1
  194. package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts +4 -2
  195. package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts.map +1 -1
  196. package/dist/modules/tool-manuals/mcp-server-edit.service.js +12 -10
  197. package/dist/modules/tool-manuals/mcp-server-edit.service.js.map +1 -1
  198. package/dist/modules/tool-manuals/pending-tools.service.d.ts +3 -1
  199. package/dist/modules/tool-manuals/pending-tools.service.d.ts.map +1 -1
  200. package/dist/modules/tool-manuals/pending-tools.service.js +19 -16
  201. package/dist/modules/tool-manuals/pending-tools.service.js.map +1 -1
  202. package/dist/modules/tool-manuals/tool-delete.service.d.ts +4 -2
  203. package/dist/modules/tool-manuals/tool-delete.service.d.ts.map +1 -1
  204. package/dist/modules/tool-manuals/tool-delete.service.js +14 -12
  205. package/dist/modules/tool-manuals/tool-delete.service.js.map +1 -1
  206. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +3 -1
  207. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
  208. package/dist/modules/tool-manuals/tool-manuals.routes.js +7 -7
  209. package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
  210. package/dist/modules/tool-manuals/tool-manuals.service.d.ts +4 -2
  211. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
  212. package/dist/modules/tool-manuals/tool-manuals.service.js +15 -12
  213. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
  214. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +3 -0
  215. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
  216. package/dist/modules/tool-manuals/tool-manuals.tools.js +4 -6
  217. package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
  218. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +3 -2
  219. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  220. package/dist/modules/workflow/agent-tools/workflow.tools.js +9 -9
  221. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  222. package/dist/modules/workflow/git/git.service.d.ts +11 -5
  223. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  224. package/dist/modules/workflow/git/git.service.js +23 -14
  225. package/dist/modules/workflow/git/git.service.js.map +1 -1
  226. package/dist/modules/workflow/git/node-git-runner.d.ts +26 -2
  227. package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -1
  228. package/dist/modules/workflow/git/node-git-runner.js +35 -5
  229. package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
  230. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
  231. package/dist/modules/workflow/review-workflow/review-workflow.service.js +9 -4
  232. package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
  233. package/dist/modules/workflow/session-ontology.service.d.ts +6 -1
  234. package/dist/modules/workflow/session-ontology.service.d.ts.map +1 -1
  235. package/dist/modules/workflow/session-ontology.service.js +6 -2
  236. package/dist/modules/workflow/session-ontology.service.js.map +1 -1
  237. package/dist/modules/workflow/workflow.service.d.ts +8 -3
  238. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  239. package/dist/modules/workflow/workflow.service.js +33 -23
  240. package/dist/modules/workflow/workflow.service.js.map +1 -1
  241. package/dist/modules/workspace/session-ontology.gate.d.ts +3 -1
  242. package/dist/modules/workspace/session-ontology.gate.d.ts.map +1 -1
  243. package/dist/modules/workspace/session-ontology.gate.js +3 -3
  244. package/dist/modules/workspace/session-ontology.gate.js.map +1 -1
  245. package/dist/modules/workspace/startup/kb-git.d.ts +4 -3
  246. package/dist/modules/workspace/startup/kb-git.d.ts.map +1 -1
  247. package/dist/modules/workspace/startup/kb-git.js +15 -13
  248. package/dist/modules/workspace/startup/kb-git.js.map +1 -1
  249. package/dist/modules/workspace/startup/kb-startup-runner.d.ts +5 -8
  250. package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
  251. package/dist/modules/workspace/startup/kb-startup-runner.js +35 -38
  252. package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
  253. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts +7 -1
  254. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts.map +1 -1
  255. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js +23 -16
  256. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js.map +1 -1
  257. package/dist/modules/workspace/startup/steps/personal-spaces.step.d.ts +7 -1
  258. package/dist/modules/workspace/startup/steps/personal-spaces.step.d.ts.map +1 -1
  259. package/dist/modules/workspace/startup/steps/personal-spaces.step.js +12 -5
  260. package/dist/modules/workspace/startup/steps/personal-spaces.step.js.map +1 -1
  261. package/dist/modules/workspace/startup/steps/plugin-display-names.step.d.ts +7 -1
  262. package/dist/modules/workspace/startup/steps/plugin-display-names.step.d.ts.map +1 -1
  263. package/dist/modules/workspace/startup/steps/plugin-display-names.step.js +12 -5
  264. package/dist/modules/workspace/startup/steps/plugin-display-names.step.js.map +1 -1
  265. package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts +7 -1
  266. package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts.map +1 -1
  267. package/dist/modules/workspace/startup/steps/plugin-manifests.step.js +12 -5
  268. package/dist/modules/workspace/startup/steps/plugin-manifests.step.js.map +1 -1
  269. package/dist/modules/workspace/startup/steps/seed-tree.d.ts +4 -1
  270. package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
  271. package/dist/modules/workspace/startup/steps/seed-tree.js +14 -11
  272. package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
  273. package/dist/modules/workspace/startup/steps/template-files.step.d.ts +17 -3
  274. package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
  275. package/dist/modules/workspace/startup/steps/template-files.step.js +36 -30
  276. package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
  277. package/dist/modules/workspace/startup/steps/template-source.d.ts +6 -1
  278. package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
  279. package/dist/modules/workspace/startup/steps/template-source.js +10 -6
  280. package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
  281. package/dist/modules/workspace/workspace.routes.d.ts +2 -1
  282. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  283. package/dist/modules/workspace/workspace.routes.js +8 -7
  284. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  285. package/dist/modules/workspace/workspace.service.d.ts +18 -12
  286. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  287. package/dist/modules/workspace/workspace.service.js +32 -28
  288. package/dist/modules/workspace/workspace.service.js.map +1 -1
  289. package/dist/modules/workspace/workspace.tools.d.ts +2 -1
  290. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  291. package/dist/modules/workspace/workspace.tools.js +20 -18
  292. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  293. package/dist/modules/workspace/write-denial.d.ts +3 -2
  294. package/dist/modules/workspace/write-denial.d.ts.map +1 -1
  295. package/dist/modules/workspace/write-denial.js +6 -5
  296. package/dist/modules/workspace/write-denial.js.map +1 -1
  297. package/dist/shared/git.contract.d.ts +52 -7
  298. package/dist/shared/git.contract.d.ts.map +1 -1
  299. package/dist/shared/git.contract.js +30 -8
  300. package/dist/shared/git.contract.js.map +1 -1
  301. package/dist/shared/kb-context.d.ts +76 -0
  302. package/dist/shared/kb-context.d.ts.map +1 -0
  303. package/dist/shared/kb-context.js +108 -0
  304. package/dist/shared/kb-context.js.map +1 -0
  305. package/dist/shared/kb-layout.d.ts +3 -2
  306. package/dist/shared/kb-layout.d.ts.map +1 -1
  307. package/dist/shared/kb-layout.js +4 -3
  308. package/dist/shared/kb-layout.js.map +1 -1
  309. package/dist/shared/kb-layout.test.js +35 -27
  310. package/dist/shared/kb-layout.test.js.map +1 -1
  311. package/dist/shared/pending-proposals.d.ts +4 -1
  312. package/dist/shared/pending-proposals.d.ts.map +1 -1
  313. package/dist/shared/pending-proposals.js +3 -4
  314. package/dist/shared/pending-proposals.js.map +1 -1
  315. package/dist/shared/redact-secret.d.ts +5 -5
  316. package/dist/shared/redact-secret.js +5 -5
  317. package/dist/tenancy/index.d.ts +13 -0
  318. package/dist/tenancy/index.d.ts.map +1 -0
  319. package/dist/tenancy/index.js +13 -0
  320. package/dist/tenancy/index.js.map +1 -0
  321. package/dist/tenancy/static-tenant-source.d.ts +98 -0
  322. package/dist/tenancy/static-tenant-source.d.ts.map +1 -0
  323. package/dist/tenancy/static-tenant-source.js +220 -0
  324. package/dist/tenancy/static-tenant-source.js.map +1 -0
  325. package/dist/tenancy/tenant-host.d.ts +80 -0
  326. package/dist/tenancy/tenant-host.d.ts.map +1 -0
  327. package/dist/tenancy/tenant-host.js +217 -0
  328. package/dist/tenancy/tenant-host.js.map +1 -0
  329. package/dist/tenancy/tenant-runtime.d.ts +91 -0
  330. package/dist/tenancy/tenant-runtime.d.ts.map +1 -0
  331. package/dist/tenancy/tenant-runtime.js +174 -0
  332. package/dist/tenancy/tenant-runtime.js.map +1 -0
  333. package/dist/tenancy/tenant-secrets.d.ts +24 -0
  334. package/dist/tenancy/tenant-secrets.d.ts.map +1 -0
  335. package/dist/tenancy/tenant-secrets.js +30 -0
  336. package/dist/tenancy/tenant-secrets.js.map +1 -0
  337. package/dist/tenancy/tenant-source.contract.d.ts +45 -0
  338. package/dist/tenancy/tenant-source.contract.d.ts.map +1 -0
  339. package/dist/tenancy/tenant-source.contract.js +21 -0
  340. package/dist/tenancy/tenant-source.contract.js.map +1 -0
  341. package/migrations/0000_core_init.sql +14 -14
  342. package/migrations/0003_deployment_settings.sql +1 -1
  343. package/migrations/0005_github_facade.sql +1 -1
  344. package/migrations/0012_agent_audit.sql +6 -6
  345. package/package.json +3 -3
  346. package/src/__tests__/branch-model.test.ts +7 -6
  347. package/src/__tests__/kb-context.ts +30 -0
  348. package/src/__tests__/kb-layout-config.test.ts +35 -30
  349. package/src/core/__tests__/catalog-cache-invalidation.test.ts +2 -1
  350. package/src/core/__tests__/lifecycle.test.ts +78 -1
  351. package/src/core/__tests__/public-config.test.ts +5 -1
  352. package/src/core/catalog-cache-invalidation.ts +16 -11
  353. package/src/core/core-ports.ts +19 -0
  354. package/src/core/create-core-server.ts +27 -106
  355. package/src/core/create-core-services.ts +180 -95
  356. package/src/core/lifecycle.ts +214 -29
  357. package/src/core/public-config.ts +8 -5
  358. package/src/core-config.ts +107 -8
  359. package/src/index.ts +25 -2
  360. package/src/modules/access/__tests__/access-control.admin-root-floor.test.ts +2 -1
  361. package/src/modules/access/__tests__/access.routes.batch.test.ts +2 -1
  362. package/src/modules/access/__tests__/access.routes.folder-governs.test.ts +2 -1
  363. package/src/modules/access/__tests__/access.routes.group-grant.test.ts +2 -1
  364. package/src/modules/access/__tests__/access.routes.overrides.test.ts +2 -1
  365. package/src/modules/access/__tests__/access.routes.proposal-branch.test.ts +2 -1
  366. package/src/modules/access/__tests__/access.routes.prospective.test.ts +2 -1
  367. package/src/modules/access/__tests__/access.routes.revoke.test.ts +2 -1
  368. package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +2 -1
  369. package/src/modules/access/__tests__/change-read-gate.test.ts +13 -11
  370. package/src/modules/access/__tests__/creator-access.test.ts +3 -2
  371. package/src/modules/access/__tests__/roles.routes.test.ts +2 -1
  372. package/src/modules/access/access-control.service.ts +20 -6
  373. package/src/modules/access/access.routes.ts +10 -13
  374. package/src/modules/access/change-read-gate.ts +10 -4
  375. package/src/modules/access/creator-access.ts +7 -2
  376. package/src/modules/agent-instructions/__tests__/read-preamble.test.ts +13 -12
  377. package/src/modules/agent-instructions/read-preamble.ts +10 -12
  378. package/src/modules/auth/__tests__/account.routes.test.ts +15 -0
  379. package/src/modules/auth/__tests__/auth.service.test.ts +60 -0
  380. package/src/modules/auth/account-admission.ts +44 -0
  381. package/src/modules/auth/account.routes.ts +4 -1
  382. package/src/modules/auth/auth.service.ts +33 -1
  383. package/src/modules/auth/oidc-auth-provider.ts +9 -0
  384. package/src/modules/connection-probe/connection-probe.service.ts +7 -1
  385. package/src/modules/database/__tests__/advisory-lock.test.ts +23 -1
  386. package/src/modules/database/__tests__/connection.test.ts +98 -0
  387. package/src/modules/database/__tests__/migrations-unqualified.test.ts +32 -0
  388. package/src/modules/database/advisory-lock.ts +28 -4
  389. package/src/modules/database/connection.ts +143 -13
  390. package/src/modules/database/migrate.ts +48 -14
  391. package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +2 -1
  392. package/src/modules/diff/__tests__/diff.service.test.ts +2 -1
  393. package/src/modules/kb-fs/__tests__/branch-name.test.ts +6 -6
  394. package/src/modules/kb-fs/__tests__/clone-config.test.ts +24 -20
  395. package/src/modules/kb-fs/branch-name.ts +3 -3
  396. package/src/modules/kb-fs/clone-config.ts +15 -12
  397. package/src/modules/marketplace/__tests__/marketplace-repo.head.test.ts +2 -1
  398. package/src/modules/mcp/mcp.service.ts +11 -4
  399. package/src/modules/plugins/__tests__/bundle-dialect.e2e.test.ts +12 -11
  400. package/src/modules/plugins/__tests__/bundle-dialect.test.ts +2 -1
  401. package/src/modules/plugins/__tests__/compile-marketplace.test.ts +6 -4
  402. package/src/modules/plugins/__tests__/join-request-jobs.service.test.ts +2 -1
  403. package/src/modules/plugins/__tests__/join-requests.service.test.ts +2 -1
  404. package/src/modules/plugins/__tests__/plugin-creation-display-name.test.ts +4 -3
  405. package/src/modules/plugins/__tests__/plugin-index.service.test.ts +6 -4
  406. package/src/modules/plugins/__tests__/plugin-links.service.test.ts +220 -5
  407. package/src/modules/plugins/__tests__/plugin-provision.service.test.ts +3 -1
  408. package/src/modules/plugins/__tests__/plugin-rename.service.test.ts +7 -6
  409. package/src/modules/plugins/__tests__/plugins.routes.test.ts +11 -2
  410. package/src/modules/plugins/__tests__/teams.routes.test.ts +2 -1
  411. package/src/modules/plugins/compile/marketplace-compiler.service.ts +7 -9
  412. package/src/modules/plugins/discovery/__tests__/kb-plugin-source.test.ts +20 -16
  413. package/src/modules/plugins/discovery/bundle-dialect/bundle.source.ts +9 -2
  414. package/src/modules/plugins/discovery/kb-plugin-source.ts +15 -8
  415. package/src/modules/plugins/discovery/native.source.ts +4 -1
  416. package/src/modules/plugins/index.ts +1 -1
  417. package/src/modules/plugins/join-request-jobs.service.ts +8 -7
  418. package/src/modules/plugins/join-requests.service.ts +7 -7
  419. package/src/modules/plugins/plugin-links.service.ts +192 -19
  420. package/src/modules/plugins/plugin-links.ts +147 -27
  421. package/src/modules/plugins/plugin-provision.service.ts +54 -27
  422. package/src/modules/plugins/plugin-rename.service.ts +10 -10
  423. package/src/modules/plugins/plugins.routes.ts +45 -15
  424. package/src/modules/plugins/plugins.service.ts +7 -11
  425. package/src/modules/plugins/teams.routes.ts +16 -8
  426. package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +7 -0
  427. package/src/modules/secrets-vault/__tests__/secrets-variable-loader.test.ts +40 -0
  428. package/src/modules/secrets-vault/__tests__/tool-owner-gate.route.test.ts +2 -0
  429. package/src/modules/secrets-vault/index.ts +2 -0
  430. package/src/modules/secrets-vault/secrets-variable-loader.ts +51 -21
  431. package/src/modules/secrets-vault/secrets-vault.routes.ts +7 -6
  432. package/src/modules/settings/__tests__/deployment-settings.service.test.ts +24 -11
  433. package/src/modules/settings/__tests__/git-root-folders.test.ts +2 -1
  434. package/src/modules/settings/__tests__/setup.routes.boot-failure.test.ts +2 -1
  435. package/src/modules/settings/__tests__/setup.routes.layout-phase.test.ts +7 -4
  436. package/src/modules/settings/__tests__/setup.routes.oidc.test.ts +2 -0
  437. package/src/modules/settings/__tests__/setup.routes.sync-status.test.ts +2 -0
  438. package/src/modules/settings/__tests__/setup.routes.test.ts +33 -52
  439. package/src/modules/settings/deployment-settings.service.ts +21 -20
  440. package/src/modules/settings/setup.routes.ts +26 -16
  441. package/src/modules/skills/__tests__/allowed-tools-check.test.ts +11 -10
  442. package/src/modules/skills/__tests__/allowed-tools-warn.tools.test.ts +4 -3
  443. package/src/modules/skills/__tests__/pending-skills.service.test.ts +3 -1
  444. package/src/modules/skills/__tests__/skill-access-requests.routes.test.ts +2 -1
  445. package/src/modules/skills/__tests__/skills.routes.warnings.test.ts +2 -1
  446. package/src/modules/skills/__tests__/skills.service.test.ts +3 -2
  447. package/src/modules/skills/allowed-tools-check.ts +7 -6
  448. package/src/modules/skills/pending-skills.service.ts +9 -8
  449. package/src/modules/skills/skill-access-requests.routes.ts +7 -7
  450. package/src/modules/skills/skills.routes.ts +4 -3
  451. package/src/modules/skills/skills.service.ts +13 -9
  452. package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +3 -2
  453. package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +3 -2
  454. package/src/modules/tool-manuals/__tests__/mcp-json-discovery.test.ts +17 -12
  455. package/src/modules/tool-manuals/__tests__/mcp-server-edit.service.test.ts +2 -1
  456. package/src/modules/tool-manuals/__tests__/pending-tools.service.test.ts +4 -1
  457. package/src/modules/tool-manuals/__tests__/tool-delete.service.test.ts +2 -1
  458. package/src/modules/tool-manuals/__tests__/tool-manuals.archive.route.test.ts +2 -1
  459. package/src/modules/tool-manuals/__tests__/tool-manuals.cli.test.ts +5 -4
  460. package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +2 -1
  461. package/src/modules/tool-manuals/__tests__/tool-manuals.invalid.routes.test.ts +4 -2
  462. package/src/modules/tool-manuals/__tests__/tool-manuals.invalid.test.ts +13 -5
  463. package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +2 -1
  464. package/src/modules/tool-manuals/__tests__/tool-manuals.restart.test.ts +9 -1
  465. package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +3 -2
  466. package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +2 -0
  467. package/src/modules/tool-manuals/mcp-json-discovery.ts +6 -4
  468. package/src/modules/tool-manuals/mcp-server-edit.service.ts +13 -11
  469. package/src/modules/tool-manuals/pending-tools.service.ts +19 -16
  470. package/src/modules/tool-manuals/tool-delete.service.ts +13 -10
  471. package/src/modules/tool-manuals/tool-manuals.routes.ts +10 -8
  472. package/src/modules/tool-manuals/tool-manuals.service.ts +15 -13
  473. package/src/modules/tool-manuals/tool-manuals.tools.ts +7 -6
  474. package/src/modules/workflow/__tests__/apply-failure.test.ts +2 -1
  475. package/src/modules/workflow/__tests__/merge-announces-tree.test.ts +14 -26
  476. package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +2 -1
  477. package/src/modules/workflow/__tests__/session-ontology.service.test.ts +3 -2
  478. package/src/modules/workflow/__tests__/workflow.routes.lock-path.test.ts +2 -1
  479. package/src/modules/workflow/__tests__/workflow.service.branch-in-use.test.ts +3 -10
  480. package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +2 -1
  481. package/src/modules/workflow/__tests__/workflow.service.deleted-branch-sweep.test.ts +3 -10
  482. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +28 -27
  483. package/src/modules/workflow/__tests__/workflow.service.folder-proposals.test.ts +2 -1
  484. package/src/modules/workflow/__tests__/workflow.service.platform-restore.test.ts +2 -1
  485. package/src/modules/workflow/__tests__/workflow.service.read-gate.test.ts +3 -2
  486. package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +2 -1
  487. package/src/modules/workflow/__tests__/workflow.service.sync.test.ts +5 -4
  488. package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +2 -1
  489. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +2 -1
  490. package/src/modules/workflow/agent-tools/workflow.tools.ts +11 -9
  491. package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +5 -4
  492. package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +12 -11
  493. package/src/modules/workflow/git/__tests__/git.service.commitChanges.test.ts +9 -8
  494. package/src/modules/workflow/git/__tests__/git.service.commitFile.strayPath.test.ts +8 -7
  495. package/src/modules/workflow/git/__tests__/git.service.commitFile.test.ts +6 -5
  496. package/src/modules/workflow/git/__tests__/git.service.createBranch.test.ts +3 -2
  497. package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +3 -2
  498. package/src/modules/workflow/git/__tests__/git.service.diffFileAtCommit.test.ts +7 -6
  499. package/src/modules/workflow/git/__tests__/git.service.diffFileBetweenBranches.test.ts +16 -15
  500. package/src/modules/workflow/git/__tests__/git.service.fileContentsAtCommit.test.ts +3 -2
  501. package/src/modules/workflow/git/__tests__/git.service.forkPoint.test.ts +2 -1
  502. package/src/modules/workflow/git/__tests__/git.service.history-guards.test.ts +2 -1
  503. package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +10 -9
  504. package/src/modules/workflow/git/__tests__/git.service.listTrackedFiles.test.ts +2 -1
  505. package/src/modules/workflow/git/__tests__/git.service.logForFile.test.ts +6 -5
  506. package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +9 -8
  507. package/src/modules/workflow/git/__tests__/git.service.pendingChanges.test.ts +2 -1
  508. package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +4 -3
  509. package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +9 -8
  510. package/src/modules/workflow/git/__tests__/git.service.readFileAtRef.test.ts +2 -1
  511. package/src/modules/workflow/git/__tests__/git.service.revertPathsAndPush.test.ts +2 -1
  512. package/src/modules/workflow/git/__tests__/git.service.status.test.ts +4 -3
  513. package/src/modules/workflow/git/__tests__/git.service.syncFromRemote.test.ts +8 -7
  514. package/src/modules/workflow/git/__tests__/node-git-runner.test.ts +41 -3
  515. package/src/modules/workflow/git/git.service.ts +24 -13
  516. package/src/modules/workflow/git/node-git-runner.ts +37 -4
  517. package/src/modules/workflow/review-workflow/review-workflow.service.ts +9 -6
  518. package/src/modules/workflow/session-ontology.service.ts +7 -2
  519. package/src/modules/workflow/workflow.service.ts +31 -24
  520. package/src/modules/workspace/__tests__/file-stat-access.test.ts +3 -2
  521. package/src/modules/workspace/__tests__/git-internals.security.test.ts +10 -9
  522. package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +4 -2
  523. package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +3 -2
  524. package/src/modules/workspace/__tests__/workspace.routes.branch-errors.test.ts +2 -1
  525. package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +2 -1
  526. package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +2 -1
  527. package/src/modules/workspace/__tests__/workspace.routes.download-implies-read.test.ts +2 -1
  528. package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +2 -1
  529. package/src/modules/workspace/__tests__/workspace.routes.file-writes.test.ts +2 -1
  530. package/src/modules/workspace/__tests__/workspace.routes.folders.test.ts +5 -4
  531. package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +2 -1
  532. package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +2 -1
  533. package/src/modules/workspace/__tests__/workspace.service.ensure-remotes-fetched.test.ts +2 -2
  534. package/src/modules/workspace/__tests__/workspace.service.list-cloned.test.ts +6 -5
  535. package/src/modules/workspace/__tests__/workspace.service.move-never-overwrites.test.ts +2 -1
  536. package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +2 -1
  537. package/src/modules/workspace/__tests__/workspace.service.test.ts +84 -50
  538. package/src/modules/workspace/__tests__/workspace.service.unknown-branch.test.ts +2 -1
  539. package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +10 -7
  540. package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +4 -3
  541. package/src/modules/workspace/__tests__/workspace.tools.test.ts +9 -8
  542. package/src/modules/workspace/__tests__/write-denial.test.ts +5 -4
  543. package/src/modules/workspace/session-ontology.gate.ts +6 -4
  544. package/src/modules/workspace/startup/__tests__/kb-startup-runner.degraded.test.ts +6 -2
  545. package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +29 -21
  546. package/src/modules/workspace/startup/kb-git.ts +15 -22
  547. package/src/modules/workspace/startup/kb-startup-runner.ts +40 -46
  548. package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +104 -98
  549. package/src/modules/workspace/startup/steps/groups-to-plugins.step.ts +24 -16
  550. package/src/modules/workspace/startup/steps/personal-spaces.step.ts +14 -5
  551. package/src/modules/workspace/startup/steps/plugin-display-names.step.ts +13 -5
  552. package/src/modules/workspace/startup/steps/plugin-manifests.step.ts +14 -5
  553. package/src/modules/workspace/startup/steps/seed-tree.ts +11 -9
  554. package/src/modules/workspace/startup/steps/template-files.step.ts +43 -34
  555. package/src/modules/workspace/startup/steps/template-source.ts +8 -5
  556. package/src/modules/workspace/workspace.routes.ts +8 -7
  557. package/src/modules/workspace/workspace.service.ts +30 -27
  558. package/src/modules/workspace/workspace.tools.ts +21 -20
  559. package/src/modules/workspace/write-denial.ts +7 -5
  560. package/src/shared/__tests__/kb-layout.plugin.test.ts +19 -16
  561. package/src/shared/git.contract.ts +70 -8
  562. package/src/shared/kb-context.ts +130 -0
  563. package/src/shared/kb-layout.test.ts +37 -27
  564. package/src/shared/kb-layout.ts +4 -3
  565. package/src/shared/pending-proposals.ts +7 -4
  566. package/src/shared/redact-secret.ts +5 -5
  567. package/src/tenancy/__tests__/static-tenant-source.test.ts +177 -0
  568. package/src/tenancy/__tests__/tenant-host.test.ts +372 -0
  569. package/src/tenancy/__tests__/tenant-runtime.test.ts +221 -0
  570. package/src/tenancy/__tests__/tenant-secrets.test.ts +35 -0
  571. package/src/tenancy/index.ts +35 -0
  572. package/src/tenancy/static-tenant-source.ts +296 -0
  573. package/src/tenancy/tenant-host.ts +261 -0
  574. package/src/tenancy/tenant-runtime.ts +208 -0
  575. package/src/tenancy/tenant-secrets.ts +41 -0
  576. package/src/tenancy/tenant-source.contract.ts +59 -0
@@ -7,7 +7,7 @@ import path from 'node:path';
7
7
  import { promisify } from 'node:util';
8
8
  import express from 'express';
9
9
  import { afterEach, beforeEach, describe, expect, it } from 'vitest';
10
- import { DEFAULT_KB_LAYOUT, configureKbLayout } from '@bevel-software/platform-shared';
10
+ import { testKbContext } from '../../../__tests__/kb-context.js';
11
11
  import { createSetupRoutes } from '../setup.routes.js';
12
12
  import { DeploymentSettingsService } from '../deployment-settings.service.js';
13
13
  import { KbStartupRunner } from '../../workspace/startup/kb-startup-runner.js';
@@ -71,7 +71,6 @@ beforeEach(async () => {
71
71
  afterEach(async () => {
72
72
  server?.close();
73
73
  server = null;
74
- configureKbLayout({ ...DEFAULT_KB_LAYOUT });
75
74
  for (const k of KB_ENV) {
76
75
  const original = savedEnv[k];
77
76
  if (original === undefined) delete process.env[k];
@@ -102,17 +101,20 @@ function boot() {
102
101
  delete: () => ({ where: () => Promise.resolve() }),
103
102
  } as unknown as Database;
104
103
  const settings = new DeploymentSettingsService(db, ENC_KEY);
104
+ // ONE context for the step and the routes, as the composition root builds
105
+ // it: the completing save applies the admin's names to it, and the step
106
+ // reads them from it when the phase runs.
107
+ const kb = testKbContext();
105
108
  const runner = new KbStartupRunner({
106
109
  gitRunner: new NodeGitRunner(),
107
110
  kbRepoUrl: () => upstream,
108
- gitUsername: () => 'x-access-token',
109
111
  workspacesRoot: path.join(root, 'workspaces'),
110
112
  kbDirName: 'knowledge-base',
111
113
  templateDir: defaultKbTemplateDir(),
112
114
  defaultBranch: () => BRANCH,
113
115
  protectedBranches: () => [BRANCH],
114
116
  seedAdminEmails: ['admin@example.com'],
115
- steps: [new TemplateFilesStep(new NodeFs())],
117
+ steps: [new TemplateFilesStep(new NodeFs(), kb)],
116
118
  buildSeedTree: async () => [],
117
119
  });
118
120
  const app = express();
@@ -128,6 +130,7 @@ function boot() {
128
130
  settings,
129
131
  { isAdmin: async () => true } as IAdminAccessService,
130
132
  runner,
133
+ kb,
131
134
  undefined,
132
135
  // The save now proves the connection first; the remote here is local, so
133
136
  // the stand-in answers for the host the stored address names.
@@ -9,6 +9,7 @@ import { OidcAuthProvider, oidcSettingsFrom } from '../../auth/oidc-auth-provide
9
9
  import type { AuthService } from '../../auth/auth.service.js';
10
10
  import type { Database } from '../../database/connection.js';
11
11
  import type { IAdminAccessService } from '../../admin/admin.interface.js';
12
+ import { testKbContext } from '../../../__tests__/kb-context.js';
12
13
 
13
14
  const ENC_KEY = 'kToAi8FXWDpDn3A6yQ/60O39bv05N7XzVOIu/0CJrFc=';
14
15
  const ISSUER = 'https://login.example.com/tenant/v2.0';
@@ -118,6 +119,7 @@ function listen(opts: {
118
119
  settings,
119
120
  { isAdmin: async () => opts.isAdmin ?? true } as IAdminAccessService,
120
121
  { runAll: async () => {} },
122
+ testKbContext(),
121
123
  undefined,
122
124
  // No repository in these suites, so the connection check is never reached.
123
125
  async () => {
@@ -7,6 +7,7 @@ import { createSetupRoutes, type LastSyncStatus } from '../setup.routes.js';
7
7
  import { DeploymentSettingsService } from '../deployment-settings.service.js';
8
8
  import type { IAdminAccessService } from '../../admin/admin.interface.js';
9
9
  import type { Database } from '../../database/connection.js';
10
+ import { testKbContext } from '../../../__tests__/kb-context.js';
10
11
 
11
12
  /**
12
13
  * The remote-sync facts on `GET /setup/status`: the address a hook calls and
@@ -41,6 +42,7 @@ function listen(isAdmin: boolean, last: LastSyncStatus | null) {
41
42
  settings,
42
43
  { isAdmin: async () => isAdmin } as IAdminAccessService,
43
44
  { runAll: async () => {} },
45
+ testKbContext(),
44
46
  { url: 'https://hexis.example.test/api/sync', lastSync: () => last },
45
47
  ),
46
48
  );
@@ -1,34 +1,10 @@
1
1
  import type { Server as HttpServer } from 'node:http';
2
2
  import type { AddressInfo } from 'node:net';
3
3
  import express from 'express';
4
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
5
- import {
6
- DEFAULT_KB_LAYOUT,
7
- branchModelFromEnv,
8
- configureBranchModel,
9
- configureKbLayout,
10
- currentKbLayout,
11
- type KbLayout,
12
- } from '@bevel-software/platform-shared';
13
-
14
- /**
15
- * test-setup configures the branch model from the environment, and nothing
16
- * unconfigures it; a test that needs the first-run "no branch model yet" state
17
- * says so here. Everything else is the real module.
18
- */
19
- const branchModel = vi.hoisted(() => ({ pretendUnconfigured: false }));
20
- vi.mock('@bevel-software/platform-shared', async (importOriginal) => {
21
- const actual = await importOriginal<typeof import('@bevel-software/platform-shared')>();
22
- return {
23
- ...actual,
24
- isBranchModelConfigured: () => !branchModel.pretendUnconfigured && actual.isBranchModelConfigured(),
25
- // Applying a model configures it, as the real module does.
26
- configureBranchModel: (model: Parameters<typeof actual.configureBranchModel>[0]) => {
27
- actual.configureBranchModel(model);
28
- branchModel.pretendUnconfigured = false;
29
- },
30
- };
31
- });
4
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
+ import type { KbLayout } from '@bevel-software/platform-shared';
6
+ import { testKbContext } from '../../../__tests__/kb-context.js';
7
+ import type { KbContext } from '../../../shared/kb-context.js';
32
8
  import { createSetupRoutes } from '../setup.routes.js';
33
9
  import { DeploymentSettingsService } from '../deployment-settings.service.js';
34
10
  import type { Database } from '../../database/connection.js';
@@ -98,6 +74,12 @@ function listen(
98
74
  runAll: () => Promise<void> = async () => {},
99
75
  checkConnection?: (connection: RepositoryConnection) => Promise<ConnectionCheck>,
100
76
  listFolders?: (listing: RootFolderListing) => Promise<string[] | null>,
77
+ /**
78
+ * The running graph's knowledge-base context, which the completing save
79
+ * applies the admin's names to. The default is a configured deployment; a
80
+ * suite that needs the first-run "no branch model yet" state passes its own.
81
+ */
82
+ kb: KbContext = testKbContext(),
101
83
  ) {
102
84
  const db = {
103
85
  select: () => ({ from: () => Promise.resolve([]) }),
@@ -122,6 +104,7 @@ function listen(
122
104
  // Default no-op: most suites never complete setup, so the runner is
123
105
  // never reached. The completion-transition suite passes its own spy.
124
106
  { runAll },
107
+ kb,
125
108
  undefined,
126
109
  checkConnection,
127
110
  listFolders,
@@ -129,7 +112,7 @@ function listen(
129
112
  );
130
113
  server = app.listen(0);
131
114
  const { port } = server.address() as AddressInfo;
132
- return { base: `http://127.0.0.1:${port}`, settings };
115
+ return { base: `http://127.0.0.1:${port}`, settings, kb };
133
116
  }
134
117
 
135
118
  const post = (base: string, path: string, body: unknown) =>
@@ -576,13 +559,13 @@ describe('POST /setup/settings — the completion transition and the KB startup
576
559
  */
577
560
  describe('POST /setup/settings — the folder names on the completing save', () => {
578
561
  const completing = { kbRepoUrl: 'https://example.com/acme/kb.git', gitToken: 'ghp_x' };
579
- afterEach(() => configureKbLayout({ ...DEFAULT_KB_LAYOUT }));
580
562
 
581
563
  it('applies them before the phase runs, and asks for no restart over them', async () => {
582
564
  const seenByPhase: KbLayout[] = [];
565
+ const kb = testKbContext();
583
566
  const { base } = listen(true, async () => {
584
- seenByPhase.push(currentKbLayout());
585
- }, connectedCheck().check);
567
+ seenByPhase.push(kb.layout);
568
+ }, connectedCheck().check, undefined, kb);
586
569
  const res = await post(base, '/api/setup/settings', {
587
570
  settings: { ...completing, knowledgeBaseDir: 'Docs', skillsDir: 'skills' },
588
571
  });
@@ -592,35 +575,36 @@ describe('POST /setup/settings — the folder names on the completing save', ()
592
575
  expect(body.restartRequired).toBe(false);
593
576
  const applied = { knowledgeBaseDir: 'Docs', skillsDir: 'skills', pluginsDir: 'Plugins', agentsFile: 'AGENTS.md' };
594
577
  expect(seenByPhase).toEqual([applied]);
595
- expect(currentKbLayout()).toEqual(applied);
578
+ expect(kb.layout).toEqual(applied);
596
579
  });
597
580
 
598
581
  it('applies names stored by an earlier, incomplete save', async () => {
599
582
  const seenByPhase: KbLayout[] = [];
583
+ const kb = testKbContext();
600
584
  const { base } = listen(true, async () => {
601
- seenByPhase.push(currentKbLayout());
602
- }, connectedCheck().check);
585
+ seenByPhase.push(kb.layout);
586
+ }, connectedCheck().check, undefined, kb);
603
587
  await post(base, '/api/setup/settings', { settings: { pluginsDir: 'plugins' } });
604
- expect(currentKbLayout().pluginsDir).toBe('Plugins');
588
+ expect(kb.layout.pluginsDir).toBe('Plugins');
605
589
  await post(base, '/api/setup/settings', { settings: completing });
606
590
  expect(seenByPhase[0]?.pluginsDir).toBe('plugins');
607
591
  });
608
592
 
609
593
  it('leaves them restart-to-apply once setup is complete', async () => {
610
- const { base } = listen(true, undefined, connectedCheck().check);
594
+ const { base, kb } = listen(true, undefined, connectedCheck().check);
611
595
  await post(base, '/api/setup/settings', { settings: completing });
612
596
  const res = await post(base, '/api/setup/settings', { settings: { pluginsDir: 'plugins' } });
613
597
  expect(res.status).toBe(200);
614
598
  expect((await res.json()).restartRequired).toBe(true);
615
- expect(currentKbLayout().pluginsDir).toBe('Plugins');
599
+ expect(kb.layout.pluginsDir).toBe('Plugins');
616
600
  });
617
601
 
618
602
  it('does not replace a layout the process already runs', async () => {
619
- configureKbLayout({ knowledgeBaseDir: 'docs', skillsDir: 'skills', pluginsDir: 'plugins' });
603
+ const kb = testKbContext({ layout: { knowledgeBaseDir: 'docs', skillsDir: 'skills', pluginsDir: 'plugins' } });
620
604
  const seenByPhase: KbLayout[] = [];
621
605
  const { base } = listen(true, async () => {
622
- seenByPhase.push(currentKbLayout());
623
- }, connectedCheck().check);
606
+ seenByPhase.push(kb.layout);
607
+ }, connectedCheck().check, undefined, kb);
624
608
  const res = await post(base, '/api/setup/settings', {
625
609
  settings: { ...completing, skillsDir: 'capabilities' },
626
610
  });
@@ -634,10 +618,11 @@ describe('POST /setup/settings — the folder names on the completing save', ()
634
618
  try {
635
619
  const seenByPhase: KbLayout[] = [];
636
620
  let fail = true;
621
+ const kb = testKbContext();
637
622
  const { base } = listen(true, async () => {
638
- seenByPhase.push(currentKbLayout());
623
+ seenByPhase.push(kb.layout);
639
624
  if (fail) throw new Error('remote said no');
640
- }, connectedCheck().check);
625
+ }, connectedCheck().check, undefined, kb);
641
626
  const first = await post(base, '/api/setup/settings', {
642
627
  settings: { ...completing, skillsDir: 'skills' },
643
628
  });
@@ -650,7 +635,7 @@ describe('POST /setup/settings — the folder names on the completing save', ()
650
635
  expect(body.complete).toBe(true);
651
636
  expect(body.restartRequired).toBe(false);
652
637
  expect(seenByPhase.map((l) => l.skillsDir)).toEqual(['skills', 'capabilities']);
653
- expect(currentKbLayout().skillsDir).toBe('capabilities');
638
+ expect(kb.layout.skillsDir).toBe('capabilities');
654
639
  } finally {
655
640
  console.error = consoleError;
656
641
  }
@@ -671,16 +656,14 @@ describe('POST /setup/settings — the folder names on the completing save', ()
671
656
  if (value === undefined) delete process.env[key];
672
657
  else process.env[key] = value;
673
658
  }
674
- // Whatever the test applied, the rest of the worker runs on the pinned model.
675
- configureBranchModel(branchModelFromEnv());
676
659
  }
677
660
  }
678
661
 
679
662
  it('asks for no restart over a branch model the completing save also applied', () =>
680
663
  withoutBranchEnv(async () => {
681
- branchModel.pretendUnconfigured = true;
682
- try {
683
- const { base } = listen(true, undefined, connectedCheck().check);
664
+ // A fresh deployment: no branch model yet, so the save applies the one it carries.
665
+ const fresh = testKbContext({ branchModel: null });
666
+ const { base, kb } = listen(true, undefined, connectedCheck().check, undefined, fresh);
684
667
  const res = await post(base, '/api/setup/settings', {
685
668
  settings: {
686
669
  ...completing,
@@ -693,9 +676,7 @@ describe('POST /setup/settings — the folder names on the completing save', ()
693
676
  const body = await res.json();
694
677
  expect(body.complete).toBe(true);
695
678
  expect(body.restartRequired).toBe(false);
696
- } finally {
697
- branchModel.pretendUnconfigured = false;
698
- }
679
+ expect(kb.defaultBranch).toBe('production');
699
680
  }));
700
681
 
701
682
  it('still asks for a restart over a branch change once a branch model is in effect', () =>
@@ -181,7 +181,9 @@ export const CORE_SETTINGS: SettingDef[] = [
181
181
  */
182
182
  key: 'agentsFile',
183
183
  section: 'knowledge-base',
184
- validate: (v) => validateAgentsFileName(v),
184
+ // Judged against the default roots here; the quartet check in `plan`
185
+ // judges it against the roots the same save puts in effect.
186
+ validate: (v) => validateAgentsFileName(v, DEFAULT_KB_LAYOUT),
185
187
  restartToApply: true,
186
188
  unsetMeans: DEFAULT_KB_LAYOUT.agentsFile,
187
189
  },
@@ -422,11 +424,23 @@ export class DeploymentSettingsService {
422
424
  private stored = new Map<string, string>();
423
425
  private readonly crypto: TokenCrypto | null;
424
426
 
427
+ /**
428
+ * The environment the env-first layer reads. The process's own for a
429
+ * single-tenant deployment; a host serving several knowledge bases hands
430
+ * each graph one built from its tenant record, so a variable set on the
431
+ * host process can never leak into every tenant, and a record's values
432
+ * behave exactly as environment-pinned ones do (they win over the setup
433
+ * screen and the screen shows them as such).
434
+ */
435
+ private readonly env: NodeJS.ProcessEnv;
436
+
425
437
  constructor(
426
438
  private readonly db: Database,
427
439
  private readonly secretsEncKey: string,
428
440
  defs: SettingDef[] = CORE_SETTINGS,
441
+ options: { env?: NodeJS.ProcessEnv } = {},
429
442
  ) {
443
+ this.env = options.env ?? process.env;
430
444
  for (const def of defs) this.defs.set(def.key, def);
431
445
  // No key configured means secrets cannot be stored — surfaced when someone
432
446
  // tries, rather than pretended away by writing plaintext.
@@ -470,7 +484,7 @@ export class DeploymentSettingsService {
470
484
  resolve(key: string): string {
471
485
  const def = this.defs.get(key);
472
486
  if (!def) return '';
473
- const fromEnv = def.envVar ? (process.env[def.envVar] ?? '').trim() : '';
487
+ const fromEnv = def.envVar ? (this.env[def.envVar] ?? '').trim() : '';
474
488
  if (fromEnv) return fromEnv;
475
489
  return (this.stored.get(key) ?? '').trim();
476
490
  }
@@ -521,7 +535,7 @@ export class DeploymentSettingsService {
521
535
  */
522
536
  async importLegacyLayoutEnv(): Promise<void> {
523
537
  for (const [key, envVar] of Object.entries(LEGACY_LAYOUT_ENV_VARS)) {
524
- const fromEnv = (process.env[envVar] ?? '').trim();
538
+ const fromEnv = (this.env[envVar] ?? '').trim();
525
539
  if (!fromEnv) continue;
526
540
  const saved = (this.stored.get(key) ?? '').trim();
527
541
  if (saved) {
@@ -559,7 +573,7 @@ export class DeploymentSettingsService {
559
573
  // A setting with no variable can never read `env`, whatever the process
560
574
  // environment happens to hold — which is what makes the layout fields
561
575
  // editable in the app on a deployment that still sets the old variables.
562
- if (def.envVar && (process.env[def.envVar] ?? '').trim()) return 'env';
576
+ if (def.envVar && (this.env[def.envVar] ?? '').trim()) return 'env';
563
577
  return (this.stored.get(key) ?? '').trim() ? 'stored' : 'unset';
564
578
  }
565
579
 
@@ -629,10 +643,9 @@ export class DeploymentSettingsService {
629
643
  this.stored.set(key, value);
630
644
  }
631
645
 
632
- // The git token is consumed through the environment (the credential helper
633
- // reads `$GITHUB_TOKEN` at call time, so it never appears in argv). Putting
634
- // it there is what makes a token saved here work without a restart.
635
- this.syncGitTokenEnv();
646
+ // A token saved here is in effect at once: the git runner's credentials
647
+ // read `resolve('gitToken')` on every call, so nothing is published to
648
+ // the process environment and no restart is needed.
636
649
  return { restartRequired: restartKeys.length > 0, restartKeys };
637
650
  }
638
651
 
@@ -777,18 +790,6 @@ export class DeploymentSettingsService {
777
790
  }
778
791
  }
779
792
 
780
- /**
781
- * Publish the resolved git token as `GITHUB_TOKEN`, the name the credential
782
- * helper and every redaction path already read. Only when the environment did
783
- * not supply one — otherwise this would overwrite the operator's value with
784
- * a stored fallback, inverting the precedence everything else here obeys.
785
- */
786
- syncGitTokenEnv(): void {
787
- if (this.sourceOf('gitToken') !== 'stored') return;
788
- const token = this.resolve('gitToken');
789
- if (token) process.env.GITHUB_TOKEN = token;
790
- }
791
-
792
793
  /** The single sign-on values in effect, issuer normalized the way the provider uses it. */
793
794
  resolveOidcCredentials(): OidcCredentials {
794
795
  return {
@@ -23,13 +23,11 @@ import {
23
23
  type RepositoryConnection,
24
24
  } from './connection-check.js';
25
25
  import {
26
- configureBranchModel,
27
- configureKbLayout,
28
- isBranchModelConfigured,
29
26
  isDefaultKbLayout,
30
27
  validateBranchModel,
31
28
  validateKbLayout,
32
29
  } from '@bevel-software/platform-shared';
30
+ import type { KbContext } from '../../shared/kb-context.js';
33
31
  import { failureOf, type GitFailure } from '../../shared/git-failure.js';
34
32
  import { redactSecret, urlQuerySecrets } from '../../shared/redact-secret.js';
35
33
  import { listRootFolders, pickListingBranch } from './git-root-folders.js';
@@ -105,6 +103,12 @@ export function createSetupRoutes(
105
103
  /** That failure classified, for the setup screen; absent, the message is read instead. */
106
104
  lastFailureKind?(): GitFailure | null;
107
105
  },
106
+ /**
107
+ * The knowledge base's context as the running graph holds it: the save
108
+ * that completes setup applies the branch model and the layout to it, so
109
+ * every service reads the admin's answer without a restart.
110
+ */
111
+ kb: KbContext,
108
112
  /**
109
113
  * The remote-sync facts the Deployment page shows beside the sync secret:
110
114
  * the address a webhook or pipeline must call, and what the last call did.
@@ -180,7 +184,7 @@ export function createSetupRoutes(
180
184
  };
181
185
  /** The app-gate answer: settings complete AND the KB phase settled clean, whoever ran it. */
182
186
  const kbReady = () =>
183
- isComplete(settings) && kbInit === null && kbInitInFlight === null && bootFailure() === null;
187
+ isComplete(settings, kb) && kbInit === null && kbInitInFlight === null && bootFailure() === null;
184
188
 
185
189
  const requireAdmin: express.RequestHandler = async (req, res, next) => {
186
190
  if (!(await adminAccess.isAdmin(req.userEmail))) {
@@ -215,7 +219,7 @@ export function createSetupRoutes(
215
219
  }
216
220
  res.json({
217
221
  complete: kbReady(),
218
- awaitingRestart: awaitingRestart(settings),
222
+ awaitingRestart: awaitingRestart(settings, kb),
219
223
  isAdmin: true,
220
224
  settings: settings.describe(),
221
225
  oidcVerification: await settings.oidcVerification(),
@@ -261,7 +265,7 @@ export function createSetupRoutes(
261
265
  // save that flips it false→true — whichever field arrives last — is the
262
266
  // one that must run the KB startup phase, regardless of which save
263
267
  // configured the branch model.
264
- const wasComplete = isComplete(settings);
268
+ const wasComplete = isComplete(settings, kb);
265
269
  if (!(await connectionHoldsFor(entries, wasComplete, res))) return;
266
270
  const oidc = await signInHoldsFor(entries, res);
267
271
  if (!oidc) return;
@@ -292,13 +296,13 @@ export function createSetupRoutes(
292
296
  * capturing it at construction, which is what makes applying it here
293
297
  * enough.
294
298
  */
295
- if (!isBranchModelConfigured()) {
299
+ if (!kb.isBranchModelConfigured()) {
296
300
  const model = {
297
301
  defaultBranch: settings.resolve('defaultBranch'),
298
302
  protectedBranches: settings.resolve('protectedBranches'),
299
303
  };
300
304
  if (!validateBranchModel(model)) {
301
- configureBranchModel(model);
305
+ kb.applyBranchModel(model);
302
306
  branchModelApplied = true;
303
307
  }
304
308
  }
@@ -316,7 +320,7 @@ export function createSetupRoutes(
316
320
  * on a re-save of a complete, healthy setup: with the gate open,
317
321
  * sessions may be live and that is no longer a quiet moment.
318
322
  */
319
- if ((!wasComplete || kbInit !== null || bootFailure() !== null) && isComplete(settings)) {
323
+ if ((!wasComplete || kbInit !== null || bootFailure() !== null) && isComplete(settings, kb)) {
320
324
  /**
321
325
  * The folder names, applied BEFORE the phase for the same reason as
322
326
  * the branch model above: they are otherwise applied once at boot, so
@@ -327,10 +331,10 @@ export function createSetupRoutes(
327
331
  * the names an earlier setup save applied before a run that failed:
328
332
  * the gate never opened, so the retry initializes what is saved now.
329
333
  */
330
- if (isDefaultKbLayout() || (kbInit !== null && layoutAppliedBySetup)) {
334
+ if (isDefaultKbLayout(kb.layout) || (kbInit !== null && layoutAppliedBySetup)) {
331
335
  const layout = settings.resolveKbLayout();
332
336
  if (!validateKbLayout(layout)) {
333
- configureKbLayout(layout);
337
+ kb.applyLayout(layout);
334
338
  layoutApplied = true;
335
339
  layoutAppliedBySetup = true;
336
340
  }
@@ -382,7 +386,7 @@ export function createSetupRoutes(
382
386
  )
383
387
  : restartRequired,
384
388
  complete: kbReady(),
385
- awaitingRestart: awaitingRestart(settings),
389
+ awaitingRestart: awaitingRestart(settings, kb),
386
390
  settings: settings.describe(),
387
391
  oidcVerification: await settings.oidcVerification(),
388
392
  });
@@ -784,11 +788,17 @@ export function settingsAnswered(settings: DeploymentSettingsService): boolean {
784
788
  * that puts it there. {@link awaitingRestart} is what tells the screen to ask
785
789
  * for one rather than claim a field is missing.
786
790
  */
787
- export function isComplete(settings: DeploymentSettingsService): boolean {
788
- return settingsAnswered(settings) && isBranchModelConfigured();
791
+ export function isComplete(
792
+ settings: DeploymentSettingsService,
793
+ kb: Pick<KbContext, 'isBranchModelConfigured'>,
794
+ ): boolean {
795
+ return settingsAnswered(settings) && kb.isBranchModelConfigured();
789
796
  }
790
797
 
791
798
  /** Answered, but not yet in effect: everything is stored, the process is stale. */
792
- export function awaitingRestart(settings: DeploymentSettingsService): boolean {
793
- return settingsAnswered(settings) && !isBranchModelConfigured();
799
+ export function awaitingRestart(
800
+ settings: DeploymentSettingsService,
801
+ kb: Pick<KbContext, 'isBranchModelConfigured'>,
802
+ ): boolean {
803
+ return settingsAnswered(settings) && !kb.isBranchModelConfigured();
794
804
  }
@@ -7,6 +7,7 @@ import {
7
7
  } from '../allowed-tools-check.js';
8
8
  import type { UtcpTool } from '../../tool-registry/tool.contract.js';
9
9
  import type { ToolManualDetail, ToolManualSummary } from '../../tool-manuals/tool-manuals.contract.js';
10
+ import { testKbContext } from '../../../__tests__/kb-context.js';
10
11
 
11
12
  const visible: VisibleTools = {
12
13
  core: ['read_file', 'get_skill', 'list_skills'],
@@ -110,10 +111,10 @@ describe('checkAllowedTools', () => {
110
111
 
111
112
  describe('skillFileRepoPath', () => {
112
113
  test('recognises skill files under the plugin and skills roots only', () => {
113
- expect(skillFileRepoPath('knowledge-base', 'knowledge-base/Plugins/Sales/rfi/SKILL.md')).toBe('Plugins/Sales/rfi/SKILL.md');
114
- expect(skillFileRepoPath('knowledge-base', './knowledge-base/Skills/triage/SKILL.md')).toBe('Skills/triage/SKILL.md');
115
- expect(skillFileRepoPath('knowledge-base', 'knowledge-base/Plugins/Sales/rfi/notes.md')).toBeNull();
116
- expect(skillFileRepoPath('knowledge-base', 'knowledge-base/Data/SKILL.md')).toBeNull();
114
+ expect(skillFileRepoPath(testKbContext(),'knowledge-base/Plugins/Sales/rfi/SKILL.md')).toBe('Plugins/Sales/rfi/SKILL.md');
115
+ expect(skillFileRepoPath(testKbContext(),'./knowledge-base/Skills/triage/SKILL.md')).toBe('Skills/triage/SKILL.md');
116
+ expect(skillFileRepoPath(testKbContext(),'knowledge-base/Plugins/Sales/rfi/notes.md')).toBeNull();
117
+ expect(skillFileRepoPath(testKbContext(),'knowledge-base/Data/SKILL.md')).toBeNull();
117
118
  });
118
119
  });
119
120
 
@@ -138,7 +139,7 @@ describe('AllowedToolsChecker', () => {
138
139
  }
139
140
  : null,
140
141
  };
141
- const checker = new AllowedToolsChecker(registry, manuals, 'knowledge-base');
142
+ const checker = new AllowedToolsChecker(registry, manuals, testKbContext());
142
143
 
143
144
  const skill = (tools: string) => `---\nname: rfi\ndescription: RFI.\nallowed-tools: ${tools}\n---\n\n# RFI\n`;
144
145
 
@@ -160,7 +161,7 @@ describe('AllowedToolsChecker', () => {
160
161
  const broken = new AllowedToolsChecker(
161
162
  { listExternal: async () => { throw new Error('down'); } },
162
163
  manuals,
163
- 'knowledge-base',
164
+ testKbContext(),
164
165
  );
165
166
  await expect(
166
167
  broken.checkSave('a@x.com', 'knowledge-base/Plugins/Sales/rfi/SKILL.md', skill('hubspot.serch')),
@@ -168,7 +169,7 @@ describe('AllowedToolsChecker', () => {
168
169
  });
169
170
 
170
171
  test('a capped capability list is treated as unknown, never as proof of absence', async () => {
171
- const capped = new AllowedToolsChecker(registry, manuals, 'knowledge-base', 1);
172
+ const capped = new AllowedToolsChecker(registry, manuals, testKbContext(), 1);
172
173
  expect(await capped.check('a@x.com', ['hubspot.whatever'])).toEqual([]);
173
174
  });
174
175
 
@@ -179,7 +180,7 @@ describe('AllowedToolsChecker', () => {
179
180
  const listExternal = vi.fn(registry.listExternal);
180
181
  const listAccessible = vi.fn(manuals.listAccessible);
181
182
  const getDetail = vi.fn(manuals.getDetail);
182
- const spying = new AllowedToolsChecker({ listExternal }, { listAccessible, getDetail }, 'knowledge-base');
183
+ const spying = new AllowedToolsChecker({ listExternal }, { listAccessible, getDetail }, testKbContext());
183
184
 
184
185
  expect(entries(await spying.check('alice@example.com', ['hubspot.serch']))).toEqual(['hubspot.serch']);
185
186
  expect(listExternal).toHaveBeenCalledWith({ userEmail: 'alice@example.com' });
@@ -193,7 +194,7 @@ describe('AllowedToolsChecker', () => {
193
194
  const listExternal = vi.fn(registry.listExternal);
194
195
  const listAccessible = vi.fn(manuals.listAccessible);
195
196
  const getDetail = vi.fn(manuals.getDetail);
196
- const spying = new AllowedToolsChecker({ listExternal }, { listAccessible, getDetail }, 'knowledge-base');
197
+ const spying = new AllowedToolsChecker({ listExternal }, { listAccessible, getDetail }, testKbContext());
197
198
 
198
199
  const results = await spying.checkSaves('a@x.com', [
199
200
  { path: 'knowledge-base/Plugins/Sales/rfi/SKILL.md', content: skill('hubspot.serch') },
@@ -214,7 +215,7 @@ describe('AllowedToolsChecker', () => {
214
215
  const listExternal = vi.fn(registry.listExternal);
215
216
  const listAccessible = vi.fn(manuals.listAccessible);
216
217
  const getDetail = vi.fn(manuals.getDetail);
217
- const spying = new AllowedToolsChecker({ listExternal }, { listAccessible, getDetail }, 'knowledge-base');
218
+ const spying = new AllowedToolsChecker({ listExternal }, { listAccessible, getDetail }, testKbContext());
218
219
 
219
220
  expect(await spying.check('a@x.com', ['Bash', 'Read', 'Bash(git:*)', 'mcp__github__create_issue', 'shell'])).toEqual([]);
220
221
  expect(listExternal).not.toHaveBeenCalled();
@@ -19,6 +19,7 @@ import type { ToolManualDetail, ToolManualSummary } from '../../tool-manuals/too
19
19
  import { registerSkillsTools } from '../skills.tools.js';
20
20
  import type { ISkillService } from '../skills.contract.js';
21
21
  import { AllowedToolsChecker } from '../allowed-tools-check.js';
22
+ import { testKbContext } from '../../../__tests__/kb-context.js';
22
23
 
23
24
  /**
24
25
  * The agent surfaces end to end: a SKILL.md written through the file tools
@@ -41,7 +42,7 @@ const checker = new AllowedToolsChecker(
41
42
  capabilities: [{ name: 'search', description: null }],
42
43
  }),
43
44
  },
44
- KB_DIR,
45
+ testKbContext({ kbDirName: KB_DIR }),
45
46
  );
46
47
 
47
48
  /** What the tool handed the service on its last `getSkill` — the tool's one job is to pass it on. */
@@ -109,8 +110,8 @@ async function start(): Promise<string> {
109
110
  const router = express.Router();
110
111
  registerWorkspaceTools(
111
112
  registry, router, fakeAuth, toolHandler,
112
- new SpillStore(join(tmpdir(), 'bevel-test-spills')), new DocExtractService(join(tmpdir(), 'bevel-test-doc-extract')), allowAll, KB_DIR,
113
- { service: {} as never, enabled: false, kbDirName: KB_DIR, recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
113
+ new SpillStore(join(tmpdir(), 'bevel-test-spills')), new DocExtractService(join(tmpdir(), 'bevel-test-doc-extract')), allowAll, testKbContext({ kbDirName: KB_DIR }),
114
+ { service: {} as never, enabled: false, kb: testKbContext({ kbDirName: KB_DIR }), recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
114
115
  new RoutineWritePolicyService(),
115
116
  {} as never,
116
117
  checker,
@@ -5,6 +5,7 @@ import { hashEmail } from '../../../shared/email-identity.js';
5
5
  import type { WorkspaceService } from '../../workspace/workspace.service.js';
6
6
  import type { IAccessControl } from '../../access/access-control.interface.js';
7
7
  import type { ISkillService, SkillSummary } from '../skills.contract.js';
8
+ import { testKbContext } from '../../../__tests__/kb-context.js';
8
9
 
9
10
  /**
10
11
  * The half of the catalog that is NOT on the default branch.
@@ -77,7 +78,7 @@ function harness(opts: {
77
78
  listChangeRequests: async () => opts.crs,
78
79
  } as unknown as IWorkflowService;
79
80
 
80
- return new PendingSkillsService(workspaceService, accessControl, skillService, workflow);
81
+ return new PendingSkillsService(workspaceService, accessControl, skillService, workflow, testKbContext());
81
82
  }
82
83
 
83
84
  const ADMIN_WRITES = {
@@ -210,6 +211,7 @@ describe('PendingSkillsService', () => {
210
211
  {} as unknown as IAccessControl,
211
212
  { listSkills: async () => [] } as unknown as ISkillService,
212
213
  workflow,
214
+ testKbContext(),
213
215
  );
214
216
  await expect(svc.listPendingSkills(AUTHOR)).resolves.toEqual([]);
215
217
  });
@@ -11,6 +11,7 @@ import type { IAccessControl } from '../../access/access-control.interface.js';
11
11
  import type { JoinRequestsService } from '../../plugins/join-requests.service.js';
12
12
  import type { ISkillService } from '../skills.contract.js';
13
13
  import { createSkillAccessRequestRoutes } from '../skill-access-requests.routes.js';
14
+ import { testKbContext } from '../../../__tests__/kb-context.js';
14
15
 
15
16
  /**
16
17
  * The branch probe behind an access request: the listing is used to PROVE a
@@ -52,7 +53,7 @@ async function makeHarness(listBranches: IWorkflowService['listBranches']) {
52
53
  workflow,
53
54
  workspaceService,
54
55
  joinRequests: { list: vi.fn(), reconcile: vi.fn() } as unknown as JoinRequestsService,
55
- kbDirName: KB,
56
+ kb: testKbContext({ kbDirName: KB }),
56
57
  resolveUser: async () => MIA,
57
58
  }),
58
59
  );
@@ -5,6 +5,7 @@ import '../../auth/auth.middleware.js'; // Express Request.userEmail augmentatio
5
5
  import { createSkillsRoutes } from '../skills.routes.js';
6
6
  import type { ISkillService } from '../skills.contract.js';
7
7
  import type { IAllowedToolsChecker } from '../allowed-tools-check.js';
8
+ import { testKbContext } from '../../../__tests__/kb-context.js';
8
9
 
9
10
  /**
10
11
  * The browser's skill read carries the same `allowed-tools` warnings as
@@ -42,7 +43,7 @@ async function start(checker?: IAllowedToolsChecker): Promise<string> {
42
43
  req.userEmail = EMAIL;
43
44
  next();
44
45
  });
45
- app.use('/api', createSkillsRoutes(skillService, undefined, undefined, undefined, checker));
46
+ app.use('/api', createSkillsRoutes(skillService, testKbContext(), undefined, undefined, undefined, checker));
46
47
  server = await new Promise<Server>((resolve) => {
47
48
  const s = app.listen(0, () => resolve(s));
48
49
  });