@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
@@ -2,9 +2,9 @@ import path from 'node:path';
2
2
  import { logger } from '../../shared/logging.js';
3
3
 
4
4
  const log = logger('plugins');
5
- import { DEFAULT_BRANCH, pluginManifestName, skillUnderRoot } from '@bevel-software/platform-shared';
5
+ import { pluginManifestName, skillUnderRoot } from '@bevel-software/platform-shared';
6
6
  import type { WorkspaceService } from '../workspace/workspace.service.js';
7
- import { workspaceIdForBranch } from '../../shared/workspace-id.js';
7
+ import type { KbContext } from '../../shared/kb-context.js';
8
8
  import type { IAccessControl } from '../access/access-control.interface.js';
9
9
  import type { ISkillService } from '../skills/skills.contract.js';
10
10
  import { TtlCache } from '../../shared/ttl-cache.js';
@@ -26,10 +26,35 @@ export interface PluginLinks {
26
26
  linkedSkills: string[];
27
27
  /** Roots that resolve to no released skill — a typo, or a skill not yet merged. */
28
28
  unresolvedRoots: string[];
29
+ /**
30
+ * The declared roots whose OWN access file does not carry this plugin's two
31
+ * grant lines, each with the linked skills its members cannot read through
32
+ * it — the automatic repair's work list, and the only thing that says WHICH
33
+ * file to write (`brokenLinks` counts skills, and a root holding twenty of
34
+ * them is still one file). Empty for an unmanaged (dialect) plugin, whose
35
+ * links grant nothing, and for a plugin whose links are all healthy.
36
+ */
37
+ ungrantedRoots: UngrantedRoot[];
29
38
  /** Whether hexis writes these links and checks their grants — see `DiscoveredPlugin`. */
30
39
  linksAreManaged: boolean;
31
40
  }
32
41
 
42
+ /** One declared root missing its grants, with the skills that go without. */
43
+ export interface UngrantedRoot {
44
+ /** Repo-relative root, exactly as the manifest declares it. */
45
+ root: string;
46
+ /** The released skill folders under it the plugin's members cannot read. */
47
+ skills: string[];
48
+ }
49
+
50
+ /**
51
+ * The two verbs a link grants — the pair `PluginLinksService.grantTokens`
52
+ * writes and this index looks for. `owner` is deliberately not one of them: a
53
+ * link shares a skill and lets the plugin's managers edit it; it never hands
54
+ * over who validates it.
55
+ */
56
+ export const LINK_GRANT_VERBS = ['read', 'write'] as const;
57
+
33
58
  export interface LinkMembership {
34
59
  /** skill path → every plugin that holds it, inline or by link. */
35
60
  bySkill: Map<string, PluginMembership[]>;
@@ -49,10 +74,15 @@ export interface LinkMembership {
49
74
  * and the global-name dedup, and a second walk here would be a second
50
75
  * opinion about what a skill is.
51
76
  *
52
- * `granted` is the consistency check the amber dot renders: a linked skill
53
- * whose own access rules DO grant the plugin's `plugin/<Name>/read`
54
- * principal (directly or from a scope above it). The link service writes
55
- * that grant with the link; only a hand edit takes it away.
77
+ * `granted` is the consistency check the amber dot renders, and it is a
78
+ * question about the FILE, not about who happens to be able to read the skill
79
+ * today: a link is granted when the declared ROOT's own access file carries
80
+ * both `plugin/<Name>/read` and `plugin/<Name>/write`, and neither is denied
81
+ * at that root or between it and the skill. A root that is readable by
82
+ * everyone, or that inherits a plugin grant from a folder above, is NOT
83
+ * granted — the grant is the link's contract, and a public root merely hides
84
+ * its absence until the day someone restricts the tree. The link service
85
+ * writes those two lines with the link; only a hand edit takes them away.
56
86
  *
57
87
  * Cached briefly, dropped by `invalidate()` from the same file-change
58
88
  * subscriber that drops the plugin index, so a link committed on the default
@@ -65,7 +95,7 @@ export class PluginLinkIndex {
65
95
  private readonly workspaceService: WorkspaceService,
66
96
  private readonly skillService: ISkillService,
67
97
  private readonly accessControl: IAccessControl,
68
- private readonly kbDirName: string,
98
+ private readonly kb: KbContext,
69
99
  /** Where plugins come from — the one discovery every catalog shares. */
70
100
  private readonly source: PluginSource,
71
101
  now: () => number = Date.now,
@@ -73,6 +103,10 @@ export class PluginLinkIndex {
73
103
  this.cache = new TtlCache(CACHE_TTL_MS, now);
74
104
  }
75
105
 
106
+ private get kbDirName(): string {
107
+ return this.kb.kbDirName;
108
+ }
109
+
76
110
  invalidate(): void {
77
111
  this.cache.invalidate();
78
112
  }
@@ -104,7 +138,7 @@ export class PluginLinkIndex {
104
138
  let wsId: string;
105
139
  let kbRoot: string;
106
140
  try {
107
- wsId = (await this.workspaceService.getOrCreateForBranch(DEFAULT_BRANCH)).id;
141
+ wsId = (await this.workspaceService.getOrCreateForBranch(this.kb.defaultBranch)).id;
108
142
  kbRoot = path.join(await this.workspaceService.getWorkspacePath(wsId), this.kbDirName);
109
143
  } catch {
110
144
  return null;
@@ -140,10 +174,58 @@ export class PluginLinkIndex {
140
174
  const roots = plugin.linkedRoots;
141
175
  const linkedSkills: string[] = [];
142
176
  const unresolvedRoots: string[] = [];
177
+ /** Which declared roots each linked skill arrives through. */
178
+ const rootsOfSkill = new Map<string, string[]>();
143
179
  for (const root of roots) {
144
180
  const hits = skills.filter((s) => skillUnderRoot(s.path, root)).map((s) => s.path);
145
181
  if (hits.length === 0) unresolvedRoots.push(root);
146
- for (const hit of hits) if (!linkedSkills.includes(hit)) linkedSkills.push(hit);
182
+ for (const hit of hits) {
183
+ if (!linkedSkills.includes(hit)) linkedSkills.push(hit);
184
+ rootsOfSkill.set(hit, [...(rootsOfSkill.get(hit) ?? []), root]);
185
+ }
186
+ }
187
+ // A skill — or a root — that sits INSIDE this plugin's folder is inline:
188
+ // its membership already stands, and no grant is written for it.
189
+ const inline = (p: string) => p === plugin.folder || p.startsWith(`${plugin.folder}/`);
190
+ const slug = pluginManifestName(plugin.name);
191
+ // Root by root FIRST, skill by skill second: the grant lives on the
192
+ // root's access file, so a root holding twenty skills is one question to
193
+ // the resolver, not twenty. An unmanaged (dialect) link is a plain
194
+ // reference — nothing to grant, nothing to repair — so it asks none.
195
+ const carriesGrants = new Map<string, boolean>();
196
+ if (plugin.linksAreManaged) {
197
+ for (const root of roots) {
198
+ if (inline(root)) continue;
199
+ carriesGrants.set(root, await this.rootCarriesGrants(wsId, root, slug));
200
+ }
201
+ }
202
+ const grantedSkills = new Map<string, boolean>();
203
+ for (const skillPath of linkedSkills) {
204
+ if (inline(skillPath)) continue;
205
+ if (!plugin.linksAreManaged) {
206
+ grantedSkills.set(skillPath, true);
207
+ continue;
208
+ }
209
+ let granted = false;
210
+ for (const root of rootsOfSkill.get(skillPath) ?? []) {
211
+ if (!carriesGrants.get(root)) continue;
212
+ if (await this.deniedBetween(wsId, root, skillPath, slug)) continue;
213
+ granted = true;
214
+ break;
215
+ }
216
+ grantedSkills.set(skillPath, granted);
217
+ }
218
+ // What the automatic repair has to write: a root missing its lines, with
219
+ // the skills that are actually going without because of it. A root whose
220
+ // skills all reach the plugin through ANOTHER declared root is nothing to
221
+ // repair — there is no broken link to fix, and a write would be noise.
222
+ const ungrantedRoots: UngrantedRoot[] = [];
223
+ for (const root of roots) {
224
+ if (inline(root) || carriesGrants.get(root) !== false) continue;
225
+ const without = linkedSkills.filter(
226
+ (s) => !inline(s) && (rootsOfSkill.get(s) ?? []).includes(root) && grantedSkills.get(s) === false,
227
+ );
228
+ if (without.length > 0) ungrantedRoots.push({ root, skills: without });
147
229
  }
148
230
  byPlugin.set(plugin.name, {
149
231
  name: plugin.name,
@@ -151,37 +233,75 @@ export class PluginLinkIndex {
151
233
  roots,
152
234
  linkedSkills,
153
235
  unresolvedRoots,
236
+ ungrantedRoots,
154
237
  linksAreManaged: plugin.linksAreManaged,
155
238
  });
156
- if (linkedSkills.length === 0) continue;
157
- const token = pluginPrincipalKey(pluginManifestName(plugin.name), 'read');
158
239
  for (const skillPath of linkedSkills) {
159
- // A skill that also sits INSIDE this plugin folder is inline, and its
160
- // inline membership already stands.
161
- if (skillPath.startsWith(`${plugin.folder}/`)) continue;
162
- // An unmanaged (dialect) link is a plain reference: nothing to grant,
163
- // nothing to repair — the skill's own scope decides who reads it.
164
- const granted = plugin.linksAreManaged ? await this.isGranted(wsId, skillPath, token) : true;
165
- add(skillPath, { name: plugin.name, linked: true, granted });
240
+ if (inline(skillPath)) continue;
241
+ add(skillPath, { name: plugin.name, linked: true, granted: grantedSkills.get(skillPath) === true });
166
242
  }
167
243
  }
168
244
  return { bySkill, byPlugin };
169
245
  }
170
246
 
171
- /** Whether the skill folder's effective readers include the plugin's read principal. */
172
- private async isGranted(wsId: string, skillPath: string, token: string): Promise<boolean> {
247
+ /**
248
+ * Whether the ROOT's own access file carries both of the link's grant lines.
249
+ *
250
+ * "Its own" is the whole rule: `grantSources` reports every scope that
251
+ * grants the principal, closest-first, so `[0].kind === 'direct'` is
252
+ * "granted by the file this root's link writes" — a grant inherited from a
253
+ * folder above is an `ancestor` source and does not count, and a root that
254
+ * is simply public names the principal nowhere and yields no source at all.
255
+ * `tokenMatch: 'exact'` pins the comparison to the canonical token the
256
+ * grant is written as, the same spelling `grantTokens` splices.
257
+ *
258
+ * A `deny` of either token in that same file is not granted either, whatever
259
+ * the resolver makes of a grant beside it: the deny is the operator's, the
260
+ * repair never removes it, and reporting the link as healthy would hide the
261
+ * one thing the banner exists to say. `locallyDeniedPrincipals` is what sees
262
+ * it — the per-verb denial walk cannot, since a grant in the same scope wins
263
+ * there and ends the walk.
264
+ */
265
+ private async rootCarriesGrants(wsId: string, root: string, slug: string): Promise<boolean> {
173
266
  try {
174
- const readers = await this.accessControl.eligibleReaders(wsId, skillPath);
175
- if (!readers.restricted) return true; // readable by everyone — the plugin's members included
267
+ for (const verb of LINK_GRANT_VERBS) {
268
+ const principal = { kind: 'role' as const, role: pluginPrincipalKey(slug, verb) };
269
+ const sources = await this.accessControl.grantSources(wsId, 'folder', root, principal, {
270
+ tokenMatch: 'exact',
271
+ });
272
+ if (sources[verb]?.[0]?.kind !== 'direct') return false;
273
+ }
274
+ const denied = await this.accessControl.locallyDeniedPrincipals?.(wsId, 'folder', root);
275
+ const tokens: string[] = LINK_GRANT_VERBS.map((verb) => pluginPrincipalKey(slug, verb));
176
276
  // The resolver reports display names; compare through the one canonicaliser.
177
- return (readers.principals ?? []).some((p) => p.kind === 'plugin' && canonicalRoleName(p.name) === token);
277
+ return !(denied?.principals ?? []).some((p) => tokens.includes(canonicalRoleName(p.name)));
178
278
  } catch {
179
279
  return false; // fail closed: an unreadable tree reports the link as needing repair
180
280
  }
181
281
  }
182
- }
183
282
 
184
- /** The default-branch workspace id every link resolution runs against. */
185
- export function linksWorkspaceId(): string {
186
- return workspaceIdForBranch(DEFAULT_BRANCH);
283
+ /**
284
+ * Whether either grant is DENIED below the root — at the skill's own folder
285
+ * or at anything between it and the root.
286
+ *
287
+ * The denial walk stops at a closer grant, and the root's grant is what
288
+ * brought us here, so what this reports is exactly the scopes under the
289
+ * root: a `deny` above the root is dead under closeness-first and is not
290
+ * this link's problem.
291
+ */
292
+ private async deniedBetween(wsId: string, root: string, skillPath: string, slug: string): Promise<boolean> {
293
+ if (skillPath === root) return false; // the root's own file is `rootCarriesGrants`' business
294
+ try {
295
+ for (const verb of LINK_GRANT_VERBS) {
296
+ const principal = { kind: 'role' as const, role: pluginPrincipalKey(slug, verb) };
297
+ const denials = await this.accessControl.denialSources?.(wsId, 'folder', skillPath, principal, {
298
+ tokenMatch: 'exact',
299
+ });
300
+ if ((denials?.[verb] ?? []).length > 0) return true;
301
+ }
302
+ return false;
303
+ } catch {
304
+ return true; // fail closed, as above
305
+ }
306
+ }
187
307
  }
@@ -38,8 +38,6 @@ import type { IFsProbe } from '../../shared/fs.contract.js';
38
38
  import type { Discovery, PluginSource } from './discovery/plugin-source.js';
39
39
 
40
40
  import {
41
- DEFAULT_BRANCH,
42
- PLUGINS_DIR,
43
41
  PLUGIN_MANIFEST_FILE,
44
42
  PLUGIN_SKILLS_DIR,
45
43
  pluginDisplayNameOf,
@@ -52,6 +50,7 @@ import {
52
50
  validateFilename,
53
51
  type AuthUser,
54
52
  } from '@bevel-software/platform-shared';
53
+ import type { KbContext } from '../../shared/kb-context.js';
55
54
  import type { WorkspaceService } from '../workspace/workspace.service.js';
56
55
  import type { IAccessControl } from '../access/access-control.interface.js';
57
56
  import { creatorPrincipal } from '../access-model/creator.js';
@@ -65,7 +64,8 @@ export interface ProvisionCommitDriver {
65
64
  branch: string,
66
65
  targetPath: string,
67
66
  user: AuthUser,
68
- opts?: { systemAuthorized?: boolean },
67
+ /** `summary` overrides the path-derived commit subject — see `GitService.commitFile`. */
68
+ opts?: { systemAuthorized?: boolean; summary?: string },
69
69
  ): Promise<void>;
70
70
  }
71
71
 
@@ -129,8 +129,14 @@ export class PluginProvisionError extends Error {
129
129
  }
130
130
 
131
131
  /** The one shape every provisioning answer has: the folder in both spellings, and where its skills go. */
132
- function provisioned(folder: string, name: string, displayName: string, created: boolean): ProvisionedPlugin {
133
- const path = `${PLUGINS_DIR}/${folder}`;
132
+ function provisioned(
133
+ pluginsDir: string,
134
+ folder: string,
135
+ name: string,
136
+ displayName: string,
137
+ created: boolean,
138
+ ): ProvisionedPlugin {
139
+ const path = `${pluginsDir}/${folder}`;
134
140
  return { folder, path, skillsDir: `${path}/${PLUGIN_SKILLS_DIR}`, name, displayName, created };
135
141
  }
136
142
 
@@ -149,13 +155,22 @@ export class PluginProvisionService {
149
155
  private readonly workspaceService: WorkspaceService,
150
156
  private readonly commits: ProvisionCommitDriver,
151
157
  private readonly accessControl: IAccessControl,
152
- private readonly kbDirName: string,
158
+ private readonly kb: KbContext,
153
159
  private readonly events: { emit(event: { kind: 'fs-tree-changed'; workspaceId: string; branch: string }): void } | undefined,
154
160
  /** Which names are TAKEN is discovery's answer — the same one every catalog gets. */
155
161
  private readonly source: PluginSource,
156
162
  private readonly disk: IFsProbe,
157
163
  ) {}
158
164
 
165
+ private get kbDirName(): string {
166
+ return this.kb.kbDirName;
167
+ }
168
+
169
+ /** The plugins root's name, read per use: a deployment may rename it from the setup screen. */
170
+ private get pluginsRoot(): string {
171
+ return this.kb.layout.pluginsDir;
172
+ }
173
+
159
174
  /**
160
175
  * Create `Plugins/<name>/` — or `Plugins/<parent>/<name>/` — for `user`.
161
176
  * Throws `PluginProvisionError` 422 on a name the filesystem or the model
@@ -226,7 +241,7 @@ export class PluginProvisionService {
226
241
  // `name` is the creator's own spelling, trimmed — the folder's leaf AND
227
242
  // the display name persisted for it, whether or not it equals either.
228
243
  await this.provision(user, folder, name, pluginAccessMd(user));
229
- return provisioned(folder, pluginManifestName(name), name, true);
244
+ return provisioned(this.pluginsRoot, folder, pluginManifestName(name), name, true);
230
245
  });
231
246
  }
232
247
 
@@ -246,7 +261,7 @@ export class PluginProvisionService {
246
261
  if (segments.some((s) => validateFilename(s) !== null || s.startsWith('.'))) {
247
262
  throw new PluginProvisionError(`"${rawParent}" is not a folder name the knowledge base can carry.`, 422);
248
263
  }
249
- const rel = `${PLUGINS_DIR}/${rawParent}`;
264
+ const rel = `${this.pluginsRoot}/${rawParent}`;
250
265
  // The personal namespace is the FIRST segment below the root — the same
251
266
  // structural rule as `isPersonalPluginDir`, applied to the parent and
252
267
  // everything under it. A `personal-*` folder there is a personal space
@@ -257,8 +272,8 @@ export class PluginProvisionService {
257
272
  }
258
273
  const wsId = await this.readyWorkspaceId();
259
274
  const wsDir = await this.workspaceService.getWorkspacePath(wsId);
260
- if (!(await this.exactFolderExists(path.join(wsDir, this.kbDirName, PLUGINS_DIR), segments))) {
261
- throw new PluginProvisionError(`There is no folder "${rawParent}" under ${PLUGINS_DIR}/.`, 404);
275
+ if (!(await this.exactFolderExists(path.join(wsDir, this.kbDirName, this.pluginsRoot), segments))) {
276
+ throw new PluginProvisionError(`There is no folder "${rawParent}" under ${this.pluginsRoot}/.`, 404);
262
277
  }
263
278
  // Judged against every folder discovery CLAIMS, not only the plugins it
264
279
  // lists: a twin skipped for its slug still owns its subtree, and a
@@ -287,7 +302,13 @@ export class PluginProvisionService {
287
302
  return this.creations.run(`plugin:${pluginManifestName(folder)}`, async () => {
288
303
  const existing = await this.existingFolder(folder);
289
304
  if (existing !== null) {
290
- return provisioned(folder, pluginManifestName(folder), await this.persistedDisplayName(existing, folder), false);
305
+ return provisioned(
306
+ this.pluginsRoot,
307
+ folder,
308
+ pluginManifestName(folder),
309
+ await this.persistedDisplayName(existing, folder),
310
+ false,
311
+ );
291
312
  }
292
313
  try {
293
314
  await this.provision(user, folder, folder, personalAccessMd(user));
@@ -296,11 +317,17 @@ export class PluginProvisionService {
296
317
  // process, a checkout that appeared between check and write): the
297
318
  // folder existing is this method's success case, never its error.
298
319
  if (err instanceof PluginProvisionError && err.status === 409) {
299
- return provisioned(folder, pluginManifestName(folder), await this.persistedDisplayName(folder, folder), false);
320
+ return provisioned(
321
+ this.pluginsRoot,
322
+ folder,
323
+ pluginManifestName(folder),
324
+ await this.persistedDisplayName(folder, folder),
325
+ false,
326
+ );
300
327
  }
301
328
  throw err;
302
329
  }
303
- return provisioned(folder, pluginManifestName(folder), folder, true);
330
+ return provisioned(this.pluginsRoot, folder, pluginManifestName(folder), folder, true);
304
331
  });
305
332
  }
306
333
 
@@ -343,14 +370,14 @@ export class PluginProvisionService {
343
370
  if (!name || segments.some((s) => validateFilename(s) !== null || s.startsWith('.'))) {
344
371
  throw new PluginProvisionError('A plugin needs a name.', 422);
345
372
  }
346
- if (isPersonalPluginDir(`${PLUGINS_DIR}/${name}`)) {
373
+ if (isPersonalPluginDir(`${this.pluginsRoot}/${name}`, this.kb.layout)) {
347
374
  // Personal folders are not plugins (the catalog never lists them), and
348
375
  // nobody deletes somebody's private shelf through the plugin door.
349
376
  throw new PluginProvisionError('Unknown plugin', 404);
350
377
  }
351
378
  const wsId = await this.readyWorkspaceId();
352
379
  const wsDir = await this.workspaceService.getWorkspacePath(wsId);
353
- const pluginsDir = path.join(wsDir, this.kbDirName, PLUGINS_DIR);
380
+ const pluginsDir = path.join(wsDir, this.kbDirName, this.pluginsRoot);
354
381
  const folderDir = path.join(pluginsDir, ...segments);
355
382
  // Locked on the plugin's IDENTITY — the same key a creation of that name
356
383
  // takes — not on a slug of the folder path, which for a nested plugin is a
@@ -361,7 +388,7 @@ export class PluginProvisionService {
361
388
  // discovery refuses, as it does for creation. A folder discovery does not
362
389
  // list (no manifest at all) locks on its own slug — nothing else can
363
390
  // claim that identity either.
364
- const identity = await this.discoveredIdentity(`${PLUGINS_DIR}/${name}`, segments[segments.length - 1]!);
391
+ const identity = await this.discoveredIdentity(`${this.pluginsRoot}/${name}`, segments[segments.length - 1]!);
365
392
  return this.creations.run(`plugin:${identity}`, async () => {
366
393
  // Exact spelling of EVERY component — the catalog hands the route the
367
394
  // on-disk spelling, so a mismatch means the plugin is gone (or was
@@ -392,8 +419,8 @@ export class PluginProvisionService {
392
419
  // deletion under it: one commit, one removed plugin.
393
420
  await this.commits.runPendingCommit(
394
421
  wsId,
395
- DEFAULT_BRANCH,
396
- `${this.kbDirName}/${PLUGINS_DIR}/${name}`,
422
+ this.kb.defaultBranch,
423
+ `${this.kbDirName}/${this.pluginsRoot}/${name}`,
397
424
  user,
398
425
  { systemAuthorized: true },
399
426
  );
@@ -411,7 +438,7 @@ export class PluginProvisionService {
411
438
  // The folder's rules left the access model — drop the resolver cache
412
439
  // so the very next check runs against a tree without them.
413
440
  this.accessControl.invalidate(wsId);
414
- this.events?.emit({ kind: 'fs-tree-changed', workspaceId: wsId, branch: DEFAULT_BRANCH });
441
+ this.events?.emit({ kind: 'fs-tree-changed', workspaceId: wsId, branch: this.kb.defaultBranch });
415
442
  });
416
443
  }
417
444
 
@@ -422,7 +449,7 @@ export class PluginProvisionService {
422
449
  */
423
450
  private async exactFolderExists(root: string, segments: string[]): Promise<boolean> {
424
451
  let dir = root;
425
- let rel = PLUGINS_DIR;
452
+ let rel = this.pluginsRoot;
426
453
  for (const segment of segments) {
427
454
  const entries = await listDirOrIncomplete(this.disk, dir, rel);
428
455
  if (!entries?.some((e) => e.isDirectory() && e.name === segment)) return false;
@@ -439,7 +466,7 @@ export class PluginProvisionService {
439
466
  private async existingFolder(name: string, parent = ''): Promise<string | null> {
440
467
  const wsId = await this.readyWorkspaceId();
441
468
  const wsDir = await this.workspaceService.getWorkspacePath(wsId);
442
- const rel = parent ? `${PLUGINS_DIR}/${parent}` : PLUGINS_DIR;
469
+ const rel = parent ? `${this.pluginsRoot}/${parent}` : this.pluginsRoot;
443
470
  // No Plugins/ root yet — nothing can collide.
444
471
  const children = await listDirOrIncomplete(this.disk, path.join(wsDir, this.kbDirName, rel), rel);
445
472
  if (!children) return null;
@@ -461,7 +488,7 @@ export class PluginProvisionService {
461
488
  const wsId = await this.readyWorkspaceId();
462
489
  const wsDir = await this.workspaceService.getWorkspacePath(wsId);
463
490
  const manifest = await this.disk.readJsonObject(
464
- path.join(wsDir, this.kbDirName, PLUGINS_DIR, ...folder.split('/'), PLUGIN_MANIFEST_FILE),
491
+ path.join(wsDir, this.kbDirName, this.pluginsRoot, ...folder.split('/'), PLUGIN_MANIFEST_FILE),
465
492
  );
466
493
  return pluginDisplayNameOf(manifest) || fallback;
467
494
  }
@@ -518,7 +545,7 @@ export class PluginProvisionService {
518
545
  */
519
546
  private async provision(user: AuthUser, folder: string, leaf: string, accessMd: string): Promise<void> {
520
547
  const wsId = await this.readyWorkspaceId();
521
- const folderPath = `${this.kbDirName}/${PLUGINS_DIR}/${folder}`;
548
+ const folderPath = `${this.kbDirName}/${this.pluginsRoot}/${folder}`;
522
549
  const wsRelPath = `${folderPath}/access.md`;
523
550
  try {
524
551
  // Exclusive create — the fs is the arbiter of a same-name race, not
@@ -557,7 +584,7 @@ export class PluginProvisionService {
557
584
  // rule this endpoint exists to carve through. The endpoint has already
558
585
  // authorized the write (any signed-in user, unused name, exclusive
559
586
  // create), so the per-user gate is skipped for exactly this commit.
560
- await this.commits.runPendingCommit(wsId, DEFAULT_BRANCH, folderPath, user, {
587
+ await this.commits.runPendingCommit(wsId, this.kb.defaultBranch, folderPath, user, {
561
588
  systemAuthorized: true,
562
589
  });
563
590
  } catch (err) {
@@ -568,7 +595,7 @@ export class PluginProvisionService {
568
595
  // so a concurrent writer's bytes can't be collateral.
569
596
  try {
570
597
  const wsDir = await this.workspaceService.getWorkspacePath(wsId);
571
- const folderDir = path.join(wsDir, this.kbDirName, PLUGINS_DIR, folder);
598
+ const folderDir = path.join(wsDir, this.kbDirName, this.pluginsRoot, folder);
572
599
  await fs.rm(path.join(folderDir, 'access.md'), { force: true });
573
600
  await fs.rm(path.join(folderDir, PLUGIN_MANIFEST_FILE), { force: true });
574
601
  await fs.rmdir(folderDir).catch(() => {});
@@ -580,11 +607,11 @@ export class PluginProvisionService {
580
607
  // The folder's rules changed the access model — drop the resolver cache
581
608
  // so the very next check (the creator's first skill write) sees them.
582
609
  this.accessControl.invalidate(wsId);
583
- this.events?.emit({ kind: 'fs-tree-changed', workspaceId: wsId, branch: DEFAULT_BRANCH });
610
+ this.events?.emit({ kind: 'fs-tree-changed', workspaceId: wsId, branch: this.kb.defaultBranch });
584
611
  }
585
612
 
586
613
  private async readyWorkspaceId(): Promise<string> {
587
- const ws = await this.workspaceService.getOrCreateForBranch(DEFAULT_BRANCH);
614
+ const ws = await this.workspaceService.getOrCreateForBranch(this.kb.defaultBranch);
588
615
  return ws.id;
589
616
  }
590
617
  }
@@ -18,8 +18,8 @@ import {
18
18
  parsePluginPrincipalKey,
19
19
  } from '../access-model/access-grammar.js';
20
20
  import type { WorkspaceService } from '../workspace/workspace.service.js';
21
+ import type { KbContext } from '../../shared/kb-context.js';
21
22
  import type { PluginSource } from './discovery/plugin-source.js';
22
- import { linksWorkspaceId } from './plugin-links.js';
23
23
 
24
24
  export class PluginRenameError extends Error {
25
25
  constructor(
@@ -70,15 +70,19 @@ export class PluginRenameService {
70
70
  private readonly accessControl: IAccessControl,
71
71
  private readonly source: PluginSource,
72
72
  private readonly disk: ITreeWalker,
73
- private readonly kbDirName: string,
73
+ private readonly kb: KbContext,
74
74
  private readonly events?: {
75
75
  emit(event: { kind: 'fs-tree-changed'; workspaceId: string; branch: string }): void;
76
76
  },
77
77
  private readonly onChanged?: () => void,
78
78
  ) {}
79
79
 
80
+ private get kbDirName(): string {
81
+ return this.kb.kbDirName;
82
+ }
83
+
80
84
  private noteChanged(wsId: string): void {
81
- noteChangedFor(this.accessControl, this.events, this.onChanged, wsId);
85
+ noteChangedFor(this.accessControl, this.events, this.onChanged, wsId, this.kb.defaultBranch);
82
86
  }
83
87
 
84
88
  /** The READ phase must have seen everything it needed; a hole refuses the rename before any write. */
@@ -96,7 +100,7 @@ export class PluginRenameService {
96
100
  current: string,
97
101
  patch: { name?: unknown; displayName?: unknown },
98
102
  ): Promise<RenameResult> {
99
- const wsId = linksWorkspaceId();
103
+ const wsId = this.kb.defaultWorkspaceId();
100
104
  const kbRoot = path.join(await this.workspaceService.getWorkspacePath(wsId), this.kbDirName);
101
105
  // ONE walk of the checkout for everything the rename needs to know:
102
106
  // the plugins (discovery's listener) and every file that can carry a
@@ -277,9 +281,10 @@ function noteChangedFor(
277
281
  events: PluginRenameService['events'],
278
282
  onChanged: (() => void) | undefined,
279
283
  wsId: string,
284
+ branch: string,
280
285
  ): void {
281
286
  accessControl.invalidate(wsId);
282
- events?.emit({ kind: 'fs-tree-changed', workspaceId: wsId, branch: linksWorkspaceIdBranch() });
287
+ events?.emit({ kind: 'fs-tree-changed', workspaceId: wsId, branch });
283
288
  onChanged?.();
284
289
  }
285
290
 
@@ -303,8 +308,3 @@ export function renamePluginPrincipalInText(text: string, oldName: string, nextN
303
308
  })
304
309
  .join('\n');
305
310
  }
306
-
307
- function linksWorkspaceIdBranch(): string {
308
- // The default branch's workspace id IS its encoded branch name.
309
- return decodeURIComponent(linksWorkspaceId());
310
- }