@bevel-software/platform-core-backend 0.19.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 (799) 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 +45 -105
  11. package/dist/core/create-core-server.js.map +1 -1
  12. package/dist/core/create-core-services.d.ts +33 -5
  13. package/dist/core/create-core-services.d.ts.map +1 -1
  14. package/dist/core/create-core-services.js +146 -82
  15. package/dist/core/create-core-services.js.map +1 -1
  16. package/dist/core/lifecycle.d.ts +74 -28
  17. package/dist/core/lifecycle.d.ts.map +1 -1
  18. package/dist/core/lifecycle.js +157 -20
  19. package/dist/core/lifecycle.js.map +1 -1
  20. package/dist/core/public-config.d.ts +5 -1
  21. package/dist/core/public-config.d.ts.map +1 -1
  22. package/dist/core/public-config.js +7 -5
  23. package/dist/core/public-config.js.map +1 -1
  24. package/dist/core-config.d.ts +95 -1
  25. package/dist/core-config.d.ts.map +1 -1
  26. package/dist/core-config.js +24 -8
  27. package/dist/core-config.js.map +1 -1
  28. package/dist/index.d.ts +5 -3
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +6 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/modules/access/access-control.service.d.ts +18 -1
  33. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  34. package/dist/modules/access/access-control.service.js +19 -8
  35. package/dist/modules/access/access-control.service.js.map +1 -1
  36. package/dist/modules/access/access.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/audit/agent-audit.service.d.ts +54 -0
  53. package/dist/modules/audit/agent-audit.service.d.ts.map +1 -0
  54. package/dist/modules/audit/agent-audit.service.js +290 -0
  55. package/dist/modules/audit/agent-audit.service.js.map +1 -0
  56. package/dist/modules/audit/agent-rest-audit.middleware.d.ts +40 -0
  57. package/dist/modules/audit/agent-rest-audit.middleware.d.ts.map +1 -0
  58. package/dist/modules/audit/agent-rest-audit.middleware.js +75 -0
  59. package/dist/modules/audit/agent-rest-audit.middleware.js.map +1 -0
  60. package/dist/modules/audit/audit.contract.d.ts +145 -0
  61. package/dist/modules/audit/audit.contract.d.ts.map +1 -0
  62. package/dist/modules/audit/audit.contract.js +35 -0
  63. package/dist/modules/audit/audit.contract.js.map +1 -0
  64. package/dist/modules/audit/audit.routes.d.ts +21 -0
  65. package/dist/modules/audit/audit.routes.d.ts.map +1 -0
  66. package/dist/modules/audit/audit.routes.js +157 -0
  67. package/dist/modules/audit/audit.routes.js.map +1 -0
  68. package/dist/modules/audit/event-classifier.d.ts +52 -0
  69. package/dist/modules/audit/event-classifier.d.ts.map +1 -0
  70. package/dist/modules/audit/event-classifier.js +123 -0
  71. package/dist/modules/audit/event-classifier.js.map +1 -0
  72. package/dist/modules/audit/index.d.ts +7 -0
  73. package/dist/modules/audit/index.d.ts.map +1 -0
  74. package/dist/modules/audit/index.js +7 -0
  75. package/dist/modules/audit/index.js.map +1 -0
  76. package/dist/modules/audit/request-audit.d.ts +57 -0
  77. package/dist/modules/audit/request-audit.d.ts.map +1 -0
  78. package/dist/modules/audit/request-audit.js +117 -0
  79. package/dist/modules/audit/request-audit.js.map +1 -0
  80. package/dist/modules/auth/account-admission.d.ts +40 -0
  81. package/dist/modules/auth/account-admission.d.ts.map +1 -0
  82. package/dist/modules/auth/account-admission.js +17 -0
  83. package/dist/modules/auth/account-admission.js.map +1 -0
  84. package/dist/modules/auth/account.routes.d.ts.map +1 -1
  85. package/dist/modules/auth/account.routes.js +4 -1
  86. package/dist/modules/auth/account.routes.js.map +1 -1
  87. package/dist/modules/auth/auth.service.d.ts +19 -1
  88. package/dist/modules/auth/auth.service.d.ts.map +1 -1
  89. package/dist/modules/auth/auth.service.js +33 -1
  90. package/dist/modules/auth/auth.service.js.map +1 -1
  91. package/dist/modules/auth/oidc-auth-provider.d.ts.map +1 -1
  92. package/dist/modules/auth/oidc-auth-provider.js +9 -0
  93. package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
  94. package/dist/modules/connection-probe/connection-probe.service.d.ts +13 -1
  95. package/dist/modules/connection-probe/connection-probe.service.d.ts.map +1 -1
  96. package/dist/modules/connection-probe/connection-probe.service.js +10 -2
  97. package/dist/modules/connection-probe/connection-probe.service.js.map +1 -1
  98. package/dist/modules/database/advisory-lock.d.ts +17 -0
  99. package/dist/modules/database/advisory-lock.d.ts.map +1 -1
  100. package/dist/modules/database/advisory-lock.js +24 -3
  101. package/dist/modules/database/advisory-lock.js.map +1 -1
  102. package/dist/modules/database/connection.d.ts +67 -2
  103. package/dist/modules/database/connection.d.ts.map +1 -1
  104. package/dist/modules/database/connection.js +118 -12
  105. package/dist/modules/database/connection.js.map +1 -1
  106. package/dist/modules/database/core-schema.d.ts +414 -0
  107. package/dist/modules/database/core-schema.d.ts.map +1 -1
  108. package/dist/modules/database/core-schema.js +99 -0
  109. package/dist/modules/database/core-schema.js.map +1 -1
  110. package/dist/modules/database/migrate.d.ts +1 -1
  111. package/dist/modules/database/migrate.d.ts.map +1 -1
  112. package/dist/modules/database/migrate.js +27 -3
  113. package/dist/modules/database/migrate.js.map +1 -1
  114. package/dist/modules/diff/diff.service.d.ts.map +1 -1
  115. package/dist/modules/diff/diff.service.js +6 -1
  116. package/dist/modules/diff/diff.service.js.map +1 -1
  117. package/dist/modules/kb-fs/branch-name.d.ts +0 -1
  118. package/dist/modules/kb-fs/branch-name.d.ts.map +1 -1
  119. package/dist/modules/kb-fs/branch-name.js +3 -3
  120. package/dist/modules/kb-fs/branch-name.js.map +1 -1
  121. package/dist/modules/kb-fs/clone-config.d.ts +9 -8
  122. package/dist/modules/kb-fs/clone-config.d.ts.map +1 -1
  123. package/dist/modules/kb-fs/clone-config.js +14 -12
  124. package/dist/modules/kb-fs/clone-config.js.map +1 -1
  125. package/dist/modules/kb-fs/git-guarded-filesystem.d.ts +9 -1
  126. package/dist/modules/kb-fs/git-guarded-filesystem.d.ts.map +1 -1
  127. package/dist/modules/kb-fs/git-guarded-filesystem.js +16 -3
  128. package/dist/modules/kb-fs/git-guarded-filesystem.js.map +1 -1
  129. package/dist/modules/mcp/mcp-auth.middleware.d.ts +1 -0
  130. package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
  131. package/dist/modules/mcp/mcp-auth.middleware.js +32 -0
  132. package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
  133. package/dist/modules/mcp/mcp.routes.d.ts.map +1 -1
  134. package/dist/modules/mcp/mcp.routes.js +8 -1
  135. package/dist/modules/mcp/mcp.routes.js.map +1 -1
  136. package/dist/modules/mcp/mcp.service.d.ts +16 -1
  137. package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
  138. package/dist/modules/mcp/mcp.service.js +52 -9
  139. package/dist/modules/mcp/mcp.service.js.map +1 -1
  140. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +59 -0
  141. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
  142. package/dist/modules/mcp/oauth/bevel-oauth-provider.js +180 -8
  143. package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
  144. package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts +4 -4
  145. package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts.map +1 -1
  146. package/dist/modules/plugins/compile/marketplace-compiler.service.js +7 -10
  147. package/dist/modules/plugins/compile/marketplace-compiler.service.js.map +1 -1
  148. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts +4 -1
  149. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts.map +1 -1
  150. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js +5 -3
  151. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js.map +1 -1
  152. package/dist/modules/plugins/discovery/kb-plugin-source.d.ts +6 -1
  153. package/dist/modules/plugins/discovery/kb-plugin-source.d.ts.map +1 -1
  154. package/dist/modules/plugins/discovery/kb-plugin-source.js +14 -9
  155. package/dist/modules/plugins/discovery/kb-plugin-source.js.map +1 -1
  156. package/dist/modules/plugins/discovery/native.source.d.ts +4 -1
  157. package/dist/modules/plugins/discovery/native.source.d.ts.map +1 -1
  158. package/dist/modules/plugins/discovery/native.source.js +4 -2
  159. package/dist/modules/plugins/discovery/native.source.js.map +1 -1
  160. package/dist/modules/plugins/index.d.ts +1 -1
  161. package/dist/modules/plugins/index.d.ts.map +1 -1
  162. package/dist/modules/plugins/index.js +1 -1
  163. package/dist/modules/plugins/index.js.map +1 -1
  164. package/dist/modules/plugins/join-request-jobs.service.d.ts +3 -1
  165. package/dist/modules/plugins/join-request-jobs.service.d.ts.map +1 -1
  166. package/dist/modules/plugins/join-request-jobs.service.js +6 -6
  167. package/dist/modules/plugins/join-request-jobs.service.js.map +1 -1
  168. package/dist/modules/plugins/join-requests.service.d.ts +3 -1
  169. package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
  170. package/dist/modules/plugins/join-requests.service.js +9 -8
  171. package/dist/modules/plugins/join-requests.service.js.map +1 -1
  172. package/dist/modules/plugins/plugin-links.d.ts +65 -10
  173. package/dist/modules/plugins/plugin-links.d.ts.map +1 -1
  174. package/dist/modules/plugins/plugin-links.js +136 -31
  175. package/dist/modules/plugins/plugin-links.js.map +1 -1
  176. package/dist/modules/plugins/plugin-links.service.d.ts +107 -5
  177. package/dist/modules/plugins/plugin-links.service.d.ts.map +1 -1
  178. package/dist/modules/plugins/plugin-links.service.js +151 -21
  179. package/dist/modules/plugins/plugin-links.service.js.map +1 -1
  180. package/dist/modules/plugins/plugin-provision.service.d.ts +10 -3
  181. package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
  182. package/dist/modules/plugins/plugin-provision.service.js +33 -26
  183. package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
  184. package/dist/modules/plugins/plugin-rename.service.d.ts +4 -2
  185. package/dist/modules/plugins/plugin-rename.service.d.ts.map +1 -1
  186. package/dist/modules/plugins/plugin-rename.service.js +10 -12
  187. package/dist/modules/plugins/plugin-rename.service.js.map +1 -1
  188. package/dist/modules/plugins/plugins.routes.d.ts +3 -0
  189. package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
  190. package/dist/modules/plugins/plugins.routes.js +45 -15
  191. package/dist/modules/plugins/plugins.routes.js.map +1 -1
  192. package/dist/modules/plugins/plugins.service.d.ts +4 -4
  193. package/dist/modules/plugins/plugins.service.d.ts.map +1 -1
  194. package/dist/modules/plugins/plugins.service.js +7 -10
  195. package/dist/modules/plugins/plugins.service.js.map +1 -1
  196. package/dist/modules/plugins/teams.routes.d.ts +4 -1
  197. package/dist/modules/plugins/teams.routes.d.ts.map +1 -1
  198. package/dist/modules/plugins/teams.routes.js +11 -9
  199. package/dist/modules/plugins/teams.routes.js.map +1 -1
  200. package/dist/modules/secrets-vault/index.d.ts +1 -1
  201. package/dist/modules/secrets-vault/index.d.ts.map +1 -1
  202. package/dist/modules/secrets-vault/index.js +1 -1
  203. package/dist/modules/secrets-vault/index.js.map +1 -1
  204. package/dist/modules/secrets-vault/secrets-variable-loader.d.ts +29 -11
  205. package/dist/modules/secrets-vault/secrets-variable-loader.d.ts.map +1 -1
  206. package/dist/modules/secrets-vault/secrets-variable-loader.js +46 -21
  207. package/dist/modules/secrets-vault/secrets-variable-loader.js.map +1 -1
  208. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +3 -0
  209. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
  210. package/dist/modules/secrets-vault/secrets-vault.routes.js +4 -6
  211. package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
  212. package/dist/modules/settings/deployment-settings.service.d.ts +22 -10
  213. package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
  214. package/dist/modules/settings/deployment-settings.service.js +52 -28
  215. package/dist/modules/settings/deployment-settings.service.js.map +1 -1
  216. package/dist/modules/settings/setup.routes.d.ts +9 -2
  217. package/dist/modules/settings/setup.routes.d.ts.map +1 -1
  218. package/dist/modules/settings/setup.routes.js +20 -14
  219. package/dist/modules/settings/setup.routes.js.map +1 -1
  220. package/dist/modules/skills/allowed-tools-check.d.ts +4 -3
  221. package/dist/modules/skills/allowed-tools-check.d.ts.map +1 -1
  222. package/dist/modules/skills/allowed-tools-check.js +8 -8
  223. package/dist/modules/skills/allowed-tools-check.js.map +1 -1
  224. package/dist/modules/skills/pending-skills.service.d.ts +3 -1
  225. package/dist/modules/skills/pending-skills.service.d.ts.map +1 -1
  226. package/dist/modules/skills/pending-skills.service.js +9 -6
  227. package/dist/modules/skills/pending-skills.service.js.map +1 -1
  228. package/dist/modules/skills/skill-access-requests.routes.d.ts +2 -1
  229. package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -1
  230. package/dist/modules/skills/skill-access-requests.routes.js +6 -6
  231. package/dist/modules/skills/skill-access-requests.routes.js.map +1 -1
  232. package/dist/modules/skills/skills.routes.d.ts +4 -1
  233. package/dist/modules/skills/skills.routes.d.ts.map +1 -1
  234. package/dist/modules/skills/skills.routes.js +4 -4
  235. package/dist/modules/skills/skills.routes.js.map +1 -1
  236. package/dist/modules/skills/skills.service.d.ts +4 -2
  237. package/dist/modules/skills/skills.service.d.ts.map +1 -1
  238. package/dist/modules/skills/skills.service.js +13 -11
  239. package/dist/modules/skills/skills.service.js.map +1 -1
  240. package/dist/modules/tool-auth/external-api-key.interface.d.ts +21 -5
  241. package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -1
  242. package/dist/modules/tool-auth/external-api-key.interface.js.map +1 -1
  243. package/dist/modules/tool-auth/external-api-key.service.d.ts +1 -0
  244. package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
  245. package/dist/modules/tool-auth/external-api-key.service.js +22 -9
  246. package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
  247. package/dist/modules/tool-auth/internal-token.service.d.ts +10 -0
  248. package/dist/modules/tool-auth/internal-token.service.d.ts.map +1 -1
  249. package/dist/modules/tool-auth/internal-token.service.js +1 -0
  250. package/dist/modules/tool-auth/internal-token.service.js.map +1 -1
  251. package/dist/modules/tool-auth/tool-auth.middleware.d.ts +8 -0
  252. package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
  253. package/dist/modules/tool-auth/tool-auth.middleware.js +9 -1
  254. package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
  255. package/dist/modules/tool-manuals/mcp-json-discovery.d.ts +2 -1
  256. package/dist/modules/tool-manuals/mcp-json-discovery.d.ts.map +1 -1
  257. package/dist/modules/tool-manuals/mcp-json-discovery.js +6 -5
  258. package/dist/modules/tool-manuals/mcp-json-discovery.js.map +1 -1
  259. package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts +4 -2
  260. package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts.map +1 -1
  261. package/dist/modules/tool-manuals/mcp-server-edit.service.js +12 -10
  262. package/dist/modules/tool-manuals/mcp-server-edit.service.js.map +1 -1
  263. package/dist/modules/tool-manuals/pending-tools.service.d.ts +3 -1
  264. package/dist/modules/tool-manuals/pending-tools.service.d.ts.map +1 -1
  265. package/dist/modules/tool-manuals/pending-tools.service.js +19 -16
  266. package/dist/modules/tool-manuals/pending-tools.service.js.map +1 -1
  267. package/dist/modules/tool-manuals/tool-delete.service.d.ts +4 -2
  268. package/dist/modules/tool-manuals/tool-delete.service.d.ts.map +1 -1
  269. package/dist/modules/tool-manuals/tool-delete.service.js +14 -12
  270. package/dist/modules/tool-manuals/tool-delete.service.js.map +1 -1
  271. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +3 -1
  272. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
  273. package/dist/modules/tool-manuals/tool-manuals.routes.js +7 -7
  274. package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
  275. package/dist/modules/tool-manuals/tool-manuals.service.d.ts +4 -2
  276. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
  277. package/dist/modules/tool-manuals/tool-manuals.service.js +15 -12
  278. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
  279. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +3 -0
  280. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
  281. package/dist/modules/tool-manuals/tool-manuals.tools.js +4 -6
  282. package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
  283. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +3 -2
  284. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  285. package/dist/modules/workflow/agent-tools/workflow.tools.js +9 -9
  286. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  287. package/dist/modules/workflow/git/git.service.d.ts +11 -5
  288. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  289. package/dist/modules/workflow/git/git.service.js +23 -14
  290. package/dist/modules/workflow/git/git.service.js.map +1 -1
  291. package/dist/modules/workflow/git/node-git-runner.d.ts +26 -2
  292. package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -1
  293. package/dist/modules/workflow/git/node-git-runner.js +35 -5
  294. package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
  295. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
  296. package/dist/modules/workflow/review-workflow/review-workflow.service.js +9 -4
  297. package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
  298. package/dist/modules/workflow/session-ontology.service.d.ts +6 -1
  299. package/dist/modules/workflow/session-ontology.service.d.ts.map +1 -1
  300. package/dist/modules/workflow/session-ontology.service.js +6 -2
  301. package/dist/modules/workflow/session-ontology.service.js.map +1 -1
  302. package/dist/modules/workflow/workflow.service.d.ts +8 -3
  303. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  304. package/dist/modules/workflow/workflow.service.js +33 -23
  305. package/dist/modules/workflow/workflow.service.js.map +1 -1
  306. package/dist/modules/workspace/session-ontology.gate.d.ts +3 -1
  307. package/dist/modules/workspace/session-ontology.gate.d.ts.map +1 -1
  308. package/dist/modules/workspace/session-ontology.gate.js +3 -3
  309. package/dist/modules/workspace/session-ontology.gate.js.map +1 -1
  310. package/dist/modules/workspace/startup/kb-git.d.ts +4 -3
  311. package/dist/modules/workspace/startup/kb-git.d.ts.map +1 -1
  312. package/dist/modules/workspace/startup/kb-git.js +15 -13
  313. package/dist/modules/workspace/startup/kb-git.js.map +1 -1
  314. package/dist/modules/workspace/startup/kb-startup-runner.d.ts +5 -8
  315. package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
  316. package/dist/modules/workspace/startup/kb-startup-runner.js +35 -38
  317. package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
  318. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts +7 -1
  319. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts.map +1 -1
  320. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js +23 -16
  321. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js.map +1 -1
  322. package/dist/modules/workspace/startup/steps/personal-spaces.step.d.ts +7 -1
  323. package/dist/modules/workspace/startup/steps/personal-spaces.step.d.ts.map +1 -1
  324. package/dist/modules/workspace/startup/steps/personal-spaces.step.js +12 -5
  325. package/dist/modules/workspace/startup/steps/personal-spaces.step.js.map +1 -1
  326. package/dist/modules/workspace/startup/steps/plugin-display-names.step.d.ts +7 -1
  327. package/dist/modules/workspace/startup/steps/plugin-display-names.step.d.ts.map +1 -1
  328. package/dist/modules/workspace/startup/steps/plugin-display-names.step.js +12 -5
  329. package/dist/modules/workspace/startup/steps/plugin-display-names.step.js.map +1 -1
  330. package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts +7 -1
  331. package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts.map +1 -1
  332. package/dist/modules/workspace/startup/steps/plugin-manifests.step.js +12 -5
  333. package/dist/modules/workspace/startup/steps/plugin-manifests.step.js.map +1 -1
  334. package/dist/modules/workspace/startup/steps/seed-tree.d.ts +4 -1
  335. package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
  336. package/dist/modules/workspace/startup/steps/seed-tree.js +14 -11
  337. package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
  338. package/dist/modules/workspace/startup/steps/template-files.step.d.ts +17 -3
  339. package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
  340. package/dist/modules/workspace/startup/steps/template-files.step.js +36 -30
  341. package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
  342. package/dist/modules/workspace/startup/steps/template-source.d.ts +6 -1
  343. package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
  344. package/dist/modules/workspace/startup/steps/template-source.js +10 -6
  345. package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
  346. package/dist/modules/workspace/workspace.routes.d.ts +2 -1
  347. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  348. package/dist/modules/workspace/workspace.routes.js +8 -7
  349. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  350. package/dist/modules/workspace/workspace.service.d.ts +26 -12
  351. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  352. package/dist/modules/workspace/workspace.service.js +41 -28
  353. package/dist/modules/workspace/workspace.service.js.map +1 -1
  354. package/dist/modules/workspace/workspace.tools.d.ts +2 -1
  355. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  356. package/dist/modules/workspace/workspace.tools.js +69 -31
  357. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  358. package/dist/modules/workspace/write-denial.d.ts +3 -2
  359. package/dist/modules/workspace/write-denial.d.ts.map +1 -1
  360. package/dist/modules/workspace/write-denial.js +6 -5
  361. package/dist/modules/workspace/write-denial.js.map +1 -1
  362. package/dist/shared/git-internals.d.ts +7 -1
  363. package/dist/shared/git-internals.d.ts.map +1 -1
  364. package/dist/shared/git-internals.js +67 -9
  365. package/dist/shared/git-internals.js.map +1 -1
  366. package/dist/shared/git.contract.d.ts +52 -7
  367. package/dist/shared/git.contract.d.ts.map +1 -1
  368. package/dist/shared/git.contract.js +30 -8
  369. package/dist/shared/git.contract.js.map +1 -1
  370. package/dist/shared/kb-context.d.ts +76 -0
  371. package/dist/shared/kb-context.d.ts.map +1 -0
  372. package/dist/shared/kb-context.js +108 -0
  373. package/dist/shared/kb-context.js.map +1 -0
  374. package/dist/shared/kb-layout.d.ts +3 -2
  375. package/dist/shared/kb-layout.d.ts.map +1 -1
  376. package/dist/shared/kb-layout.js +4 -3
  377. package/dist/shared/kb-layout.js.map +1 -1
  378. package/dist/shared/kb-layout.test.js +35 -27
  379. package/dist/shared/kb-layout.test.js.map +1 -1
  380. package/dist/shared/pending-proposals.d.ts +4 -1
  381. package/dist/shared/pending-proposals.d.ts.map +1 -1
  382. package/dist/shared/pending-proposals.js +3 -4
  383. package/dist/shared/pending-proposals.js.map +1 -1
  384. package/dist/shared/redact-secret.d.ts +5 -5
  385. package/dist/shared/redact-secret.js +5 -5
  386. package/dist/tenancy/index.d.ts +13 -0
  387. package/dist/tenancy/index.d.ts.map +1 -0
  388. package/dist/tenancy/index.js +13 -0
  389. package/dist/tenancy/index.js.map +1 -0
  390. package/dist/tenancy/static-tenant-source.d.ts +98 -0
  391. package/dist/tenancy/static-tenant-source.d.ts.map +1 -0
  392. package/dist/tenancy/static-tenant-source.js +220 -0
  393. package/dist/tenancy/static-tenant-source.js.map +1 -0
  394. package/dist/tenancy/tenant-host.d.ts +80 -0
  395. package/dist/tenancy/tenant-host.d.ts.map +1 -0
  396. package/dist/tenancy/tenant-host.js +217 -0
  397. package/dist/tenancy/tenant-host.js.map +1 -0
  398. package/dist/tenancy/tenant-runtime.d.ts +91 -0
  399. package/dist/tenancy/tenant-runtime.d.ts.map +1 -0
  400. package/dist/tenancy/tenant-runtime.js +174 -0
  401. package/dist/tenancy/tenant-runtime.js.map +1 -0
  402. package/dist/tenancy/tenant-secrets.d.ts +24 -0
  403. package/dist/tenancy/tenant-secrets.d.ts.map +1 -0
  404. package/dist/tenancy/tenant-secrets.js +30 -0
  405. package/dist/tenancy/tenant-secrets.js.map +1 -0
  406. package/dist/tenancy/tenant-source.contract.d.ts +45 -0
  407. package/dist/tenancy/tenant-source.contract.d.ts.map +1 -0
  408. package/dist/tenancy/tenant-source.contract.js +21 -0
  409. package/dist/tenancy/tenant-source.contract.js.map +1 -0
  410. package/migrations/0000_core_init.sql +14 -14
  411. package/migrations/0003_deployment_settings.sql +1 -1
  412. package/migrations/0005_github_facade.sql +1 -1
  413. package/migrations/0012_agent_audit.sql +41 -0
  414. package/migrations/0013_agent_identity_and_key_soft_delete.sql +29 -0
  415. package/migrations/meta/0012_snapshot.json +2247 -0
  416. package/migrations/meta/0013_snapshot.json +2259 -0
  417. package/migrations/meta/_journal.json +14 -0
  418. package/package.json +4 -4
  419. package/src/__tests__/branch-model.test.ts +7 -6
  420. package/src/__tests__/kb-context.ts +30 -0
  421. package/src/__tests__/kb-layout-config.test.ts +35 -30
  422. package/src/core/__tests__/catalog-cache-invalidation.test.ts +2 -1
  423. package/src/core/__tests__/lifecycle.test.ts +78 -1
  424. package/src/core/__tests__/public-config.test.ts +5 -1
  425. package/src/core/catalog-cache-invalidation.ts +16 -11
  426. package/src/core/core-ports.ts +19 -0
  427. package/src/core/create-core-server.ts +55 -106
  428. package/src/core/create-core-services.ts +193 -95
  429. package/src/core/lifecycle.ts +214 -29
  430. package/src/core/public-config.ts +8 -5
  431. package/src/core-config.ts +107 -8
  432. package/src/index.ts +25 -2
  433. package/src/modules/access/__tests__/access-control.admin-root-floor.test.ts +2 -1
  434. package/src/modules/access/__tests__/access.routes.batch.test.ts +2 -1
  435. package/src/modules/access/__tests__/access.routes.folder-governs.test.ts +2 -1
  436. package/src/modules/access/__tests__/access.routes.group-grant.test.ts +2 -1
  437. package/src/modules/access/__tests__/access.routes.overrides.test.ts +2 -1
  438. package/src/modules/access/__tests__/access.routes.proposal-branch.test.ts +2 -1
  439. package/src/modules/access/__tests__/access.routes.prospective.test.ts +2 -1
  440. package/src/modules/access/__tests__/access.routes.revoke.test.ts +2 -1
  441. package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +2 -1
  442. package/src/modules/access/__tests__/change-read-gate.test.ts +13 -11
  443. package/src/modules/access/__tests__/creator-access.test.ts +3 -2
  444. package/src/modules/access/__tests__/roles.routes.test.ts +2 -1
  445. package/src/modules/access/access-control.service.ts +20 -6
  446. package/src/modules/access/access.routes.ts +10 -13
  447. package/src/modules/access/change-read-gate.ts +10 -4
  448. package/src/modules/access/creator-access.ts +7 -2
  449. package/src/modules/agent-instructions/__tests__/read-preamble.test.ts +13 -12
  450. package/src/modules/agent-instructions/read-preamble.ts +10 -12
  451. package/src/modules/audit/__tests__/agent-audit.service.test.ts +370 -0
  452. package/src/modules/audit/__tests__/agent-rest-audit.middleware.test.ts +113 -0
  453. package/src/modules/audit/__tests__/audit.routes.test.ts +201 -0
  454. package/src/modules/audit/__tests__/event-classifier.test.ts +121 -0
  455. package/src/modules/audit/agent-audit.service.ts +316 -0
  456. package/src/modules/audit/agent-rest-audit.middleware.ts +83 -0
  457. package/src/modules/audit/audit.contract.ts +164 -0
  458. package/src/modules/audit/audit.routes.ts +168 -0
  459. package/src/modules/audit/event-classifier.ts +155 -0
  460. package/src/modules/audit/index.ts +14 -0
  461. package/src/modules/audit/request-audit.ts +141 -0
  462. package/src/modules/auth/__tests__/account.routes.test.ts +15 -0
  463. package/src/modules/auth/__tests__/auth.service.test.ts +60 -0
  464. package/src/modules/auth/account-admission.ts +44 -0
  465. package/src/modules/auth/account.routes.ts +4 -1
  466. package/src/modules/auth/auth.service.ts +33 -1
  467. package/src/modules/auth/oidc-auth-provider.ts +9 -0
  468. package/src/modules/connection-probe/connection-probe.service.ts +7 -1
  469. package/src/modules/database/__tests__/advisory-lock.test.ts +23 -1
  470. package/src/modules/database/__tests__/connection.test.ts +98 -0
  471. package/src/modules/database/__tests__/migrations-unqualified.test.ts +32 -0
  472. package/src/modules/database/advisory-lock.ts +28 -4
  473. package/src/modules/database/connection.ts +143 -13
  474. package/src/modules/database/core-schema.ts +104 -0
  475. package/src/modules/database/migrate.ts +48 -14
  476. package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +2 -1
  477. package/src/modules/diff/__tests__/diff.service.test.ts +2 -1
  478. package/src/modules/diff/diff.service.ts +6 -1
  479. package/src/modules/kb-fs/__tests__/branch-name.test.ts +6 -6
  480. package/src/modules/kb-fs/__tests__/clone-config.test.ts +24 -20
  481. package/src/modules/kb-fs/branch-name.ts +3 -3
  482. package/src/modules/kb-fs/clone-config.ts +15 -12
  483. package/src/modules/kb-fs/git-guarded-filesystem.ts +16 -3
  484. package/src/modules/marketplace/__tests__/marketplace-repo.head.test.ts +2 -1
  485. package/src/modules/mcp/__tests__/bevel-oauth-provider.test.ts +183 -13
  486. package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +60 -2
  487. package/src/modules/mcp/__tests__/mcp.routes.local-token.test.ts +24 -4
  488. package/src/modules/mcp/__tests__/mcp.routes.stateless.test.ts +1 -1
  489. package/src/modules/mcp/__tests__/mcp.service.test.ts +120 -3
  490. package/src/modules/mcp/mcp-auth.middleware.ts +31 -0
  491. package/src/modules/mcp/mcp.routes.ts +11 -1
  492. package/src/modules/mcp/mcp.service.ts +73 -8
  493. package/src/modules/mcp/oauth/bevel-oauth-provider.ts +184 -6
  494. package/src/modules/plugins/__tests__/bundle-dialect.e2e.test.ts +12 -11
  495. package/src/modules/plugins/__tests__/bundle-dialect.test.ts +2 -1
  496. package/src/modules/plugins/__tests__/compile-marketplace.test.ts +6 -4
  497. package/src/modules/plugins/__tests__/join-request-jobs.service.test.ts +2 -1
  498. package/src/modules/plugins/__tests__/join-requests.service.test.ts +2 -1
  499. package/src/modules/plugins/__tests__/plugin-creation-display-name.test.ts +4 -3
  500. package/src/modules/plugins/__tests__/plugin-index.service.test.ts +6 -4
  501. package/src/modules/plugins/__tests__/plugin-links.service.test.ts +220 -5
  502. package/src/modules/plugins/__tests__/plugin-provision.service.test.ts +3 -1
  503. package/src/modules/plugins/__tests__/plugin-rename.service.test.ts +7 -6
  504. package/src/modules/plugins/__tests__/plugins.routes.test.ts +11 -2
  505. package/src/modules/plugins/__tests__/teams.routes.test.ts +2 -1
  506. package/src/modules/plugins/compile/marketplace-compiler.service.ts +7 -9
  507. package/src/modules/plugins/discovery/__tests__/kb-plugin-source.test.ts +20 -16
  508. package/src/modules/plugins/discovery/bundle-dialect/bundle.source.ts +9 -2
  509. package/src/modules/plugins/discovery/kb-plugin-source.ts +15 -8
  510. package/src/modules/plugins/discovery/native.source.ts +4 -1
  511. package/src/modules/plugins/index.ts +1 -1
  512. package/src/modules/plugins/join-request-jobs.service.ts +8 -7
  513. package/src/modules/plugins/join-requests.service.ts +7 -7
  514. package/src/modules/plugins/plugin-links.service.ts +192 -19
  515. package/src/modules/plugins/plugin-links.ts +147 -27
  516. package/src/modules/plugins/plugin-provision.service.ts +54 -27
  517. package/src/modules/plugins/plugin-rename.service.ts +10 -10
  518. package/src/modules/plugins/plugins.routes.ts +45 -15
  519. package/src/modules/plugins/plugins.service.ts +7 -11
  520. package/src/modules/plugins/teams.routes.ts +16 -8
  521. package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +7 -0
  522. package/src/modules/secrets-vault/__tests__/secrets-variable-loader.test.ts +40 -0
  523. package/src/modules/secrets-vault/__tests__/tool-owner-gate.route.test.ts +2 -0
  524. package/src/modules/secrets-vault/index.ts +2 -0
  525. package/src/modules/secrets-vault/secrets-variable-loader.ts +51 -21
  526. package/src/modules/secrets-vault/secrets-vault.routes.ts +7 -6
  527. package/src/modules/settings/__tests__/deployment-settings.service.test.ts +59 -11
  528. package/src/modules/settings/__tests__/git-root-folders.test.ts +2 -1
  529. package/src/modules/settings/__tests__/setup.routes.boot-failure.test.ts +2 -1
  530. package/src/modules/settings/__tests__/setup.routes.layout-phase.test.ts +7 -4
  531. package/src/modules/settings/__tests__/setup.routes.oidc.test.ts +2 -0
  532. package/src/modules/settings/__tests__/setup.routes.sync-status.test.ts +2 -0
  533. package/src/modules/settings/__tests__/setup.routes.test.ts +33 -52
  534. package/src/modules/settings/deployment-settings.service.ts +68 -28
  535. package/src/modules/settings/setup.routes.ts +26 -16
  536. package/src/modules/skills/__tests__/allowed-tools-check.test.ts +11 -10
  537. package/src/modules/skills/__tests__/allowed-tools-warn.tools.test.ts +4 -3
  538. package/src/modules/skills/__tests__/pending-skills.service.test.ts +3 -1
  539. package/src/modules/skills/__tests__/skill-access-requests.routes.test.ts +2 -1
  540. package/src/modules/skills/__tests__/skills.routes.warnings.test.ts +2 -1
  541. package/src/modules/skills/__tests__/skills.service.test.ts +3 -2
  542. package/src/modules/skills/allowed-tools-check.ts +7 -6
  543. package/src/modules/skills/pending-skills.service.ts +9 -8
  544. package/src/modules/skills/skill-access-requests.routes.ts +7 -7
  545. package/src/modules/skills/skills.routes.ts +4 -3
  546. package/src/modules/skills/skills.service.ts +13 -9
  547. package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +29 -8
  548. package/src/modules/tool-auth/__tests__/internal-token.service.test.ts +6 -0
  549. package/src/modules/tool-auth/external-api-key.interface.ts +22 -5
  550. package/src/modules/tool-auth/external-api-key.service.ts +25 -8
  551. package/src/modules/tool-auth/internal-token.service.ts +11 -0
  552. package/src/modules/tool-auth/tool-auth.middleware.ts +17 -1
  553. package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +3 -2
  554. package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +3 -2
  555. package/src/modules/tool-manuals/__tests__/mcp-json-discovery.test.ts +17 -12
  556. package/src/modules/tool-manuals/__tests__/mcp-server-edit.service.test.ts +2 -1
  557. package/src/modules/tool-manuals/__tests__/pending-tools.service.test.ts +4 -1
  558. package/src/modules/tool-manuals/__tests__/tool-delete.service.test.ts +2 -1
  559. package/src/modules/tool-manuals/__tests__/tool-manuals.archive.route.test.ts +2 -1
  560. package/src/modules/tool-manuals/__tests__/tool-manuals.cli.test.ts +5 -4
  561. package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +2 -1
  562. package/src/modules/tool-manuals/__tests__/tool-manuals.invalid.routes.test.ts +4 -2
  563. package/src/modules/tool-manuals/__tests__/tool-manuals.invalid.test.ts +13 -5
  564. package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +2 -1
  565. package/src/modules/tool-manuals/__tests__/tool-manuals.restart.test.ts +9 -1
  566. package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +3 -2
  567. package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +2 -0
  568. package/src/modules/tool-manuals/mcp-json-discovery.ts +6 -4
  569. package/src/modules/tool-manuals/mcp-server-edit.service.ts +13 -11
  570. package/src/modules/tool-manuals/pending-tools.service.ts +19 -16
  571. package/src/modules/tool-manuals/tool-delete.service.ts +13 -10
  572. package/src/modules/tool-manuals/tool-manuals.routes.ts +10 -8
  573. package/src/modules/tool-manuals/tool-manuals.service.ts +15 -13
  574. package/src/modules/tool-manuals/tool-manuals.tools.ts +7 -6
  575. package/src/modules/workflow/__tests__/apply-failure.test.ts +2 -1
  576. package/src/modules/workflow/__tests__/merge-announces-tree.test.ts +14 -26
  577. package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +2 -1
  578. package/src/modules/workflow/__tests__/session-ontology.service.test.ts +3 -2
  579. package/src/modules/workflow/__tests__/workflow.routes.lock-path.test.ts +2 -1
  580. package/src/modules/workflow/__tests__/workflow.service.branch-in-use.test.ts +3 -10
  581. package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +2 -1
  582. package/src/modules/workflow/__tests__/workflow.service.deleted-branch-sweep.test.ts +3 -10
  583. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +28 -27
  584. package/src/modules/workflow/__tests__/workflow.service.folder-proposals.test.ts +2 -1
  585. package/src/modules/workflow/__tests__/workflow.service.platform-restore.test.ts +2 -1
  586. package/src/modules/workflow/__tests__/workflow.service.read-gate.test.ts +3 -2
  587. package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +2 -1
  588. package/src/modules/workflow/__tests__/workflow.service.sync.test.ts +5 -4
  589. package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +2 -1
  590. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +2 -1
  591. package/src/modules/workflow/agent-tools/workflow.tools.ts +11 -9
  592. package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +5 -4
  593. package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +12 -11
  594. package/src/modules/workflow/git/__tests__/git.service.commitChanges.test.ts +9 -8
  595. package/src/modules/workflow/git/__tests__/git.service.commitFile.strayPath.test.ts +8 -7
  596. package/src/modules/workflow/git/__tests__/git.service.commitFile.test.ts +6 -5
  597. package/src/modules/workflow/git/__tests__/git.service.createBranch.test.ts +3 -2
  598. package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +3 -2
  599. package/src/modules/workflow/git/__tests__/git.service.diffFileAtCommit.test.ts +7 -6
  600. package/src/modules/workflow/git/__tests__/git.service.diffFileBetweenBranches.test.ts +16 -15
  601. package/src/modules/workflow/git/__tests__/git.service.fileContentsAtCommit.test.ts +3 -2
  602. package/src/modules/workflow/git/__tests__/git.service.forkPoint.test.ts +2 -1
  603. package/src/modules/workflow/git/__tests__/git.service.history-guards.test.ts +2 -1
  604. package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +10 -9
  605. package/src/modules/workflow/git/__tests__/git.service.listTrackedFiles.test.ts +2 -1
  606. package/src/modules/workflow/git/__tests__/git.service.logForFile.test.ts +6 -5
  607. package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +9 -8
  608. package/src/modules/workflow/git/__tests__/git.service.pendingChanges.test.ts +2 -1
  609. package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +4 -3
  610. package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +9 -8
  611. package/src/modules/workflow/git/__tests__/git.service.readFileAtRef.test.ts +2 -1
  612. package/src/modules/workflow/git/__tests__/git.service.revertPathsAndPush.test.ts +2 -1
  613. package/src/modules/workflow/git/__tests__/git.service.status.test.ts +4 -3
  614. package/src/modules/workflow/git/__tests__/git.service.syncFromRemote.test.ts +8 -7
  615. package/src/modules/workflow/git/__tests__/node-git-runner.test.ts +41 -3
  616. package/src/modules/workflow/git/git.service.ts +24 -13
  617. package/src/modules/workflow/git/node-git-runner.ts +37 -4
  618. package/src/modules/workflow/review-workflow/review-workflow.service.ts +9 -6
  619. package/src/modules/workflow/session-ontology.service.ts +7 -2
  620. package/src/modules/workflow/workflow.service.ts +31 -24
  621. package/src/modules/workspace/__tests__/file-stat-access.test.ts +3 -2
  622. package/src/modules/workspace/__tests__/git-internals.security.test.ts +144 -52
  623. package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +4 -2
  624. package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +3 -2
  625. package/src/modules/workspace/__tests__/workspace.routes.branch-errors.test.ts +2 -1
  626. package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +2 -1
  627. package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +2 -1
  628. package/src/modules/workspace/__tests__/workspace.routes.download-implies-read.test.ts +2 -1
  629. package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +2 -1
  630. package/src/modules/workspace/__tests__/workspace.routes.file-writes.test.ts +2 -1
  631. package/src/modules/workspace/__tests__/workspace.routes.folders.test.ts +5 -4
  632. package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +2 -1
  633. package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +2 -1
  634. package/src/modules/workspace/__tests__/workspace.service.ensure-remotes-fetched.test.ts +2 -2
  635. package/src/modules/workspace/__tests__/workspace.service.list-cloned.test.ts +6 -5
  636. package/src/modules/workspace/__tests__/workspace.service.move-never-overwrites.test.ts +2 -1
  637. package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +2 -1
  638. package/src/modules/workspace/__tests__/workspace.service.test.ts +84 -50
  639. package/src/modules/workspace/__tests__/workspace.service.unknown-branch.test.ts +2 -1
  640. package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +10 -7
  641. package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +4 -3
  642. package/src/modules/workspace/__tests__/workspace.tools.test.ts +9 -8
  643. package/src/modules/workspace/__tests__/write-denial.test.ts +5 -4
  644. package/src/modules/workspace/session-ontology.gate.ts +6 -4
  645. package/src/modules/workspace/startup/__tests__/kb-startup-runner.degraded.test.ts +6 -2
  646. package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +29 -21
  647. package/src/modules/workspace/startup/kb-git.ts +15 -22
  648. package/src/modules/workspace/startup/kb-startup-runner.ts +40 -46
  649. package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +104 -98
  650. package/src/modules/workspace/startup/steps/groups-to-plugins.step.ts +24 -16
  651. package/src/modules/workspace/startup/steps/personal-spaces.step.ts +14 -5
  652. package/src/modules/workspace/startup/steps/plugin-display-names.step.ts +13 -5
  653. package/src/modules/workspace/startup/steps/plugin-manifests.step.ts +14 -5
  654. package/src/modules/workspace/startup/steps/seed-tree.ts +11 -9
  655. package/src/modules/workspace/startup/steps/template-files.step.ts +43 -34
  656. package/src/modules/workspace/startup/steps/template-source.ts +8 -5
  657. package/src/modules/workspace/workspace.routes.ts +8 -7
  658. package/src/modules/workspace/workspace.service.ts +39 -27
  659. package/src/modules/workspace/workspace.tools.ts +68 -31
  660. package/src/modules/workspace/write-denial.ts +7 -5
  661. package/src/shared/__tests__/git-internals.test.ts +41 -0
  662. package/src/shared/__tests__/kb-layout.plugin.test.ts +19 -16
  663. package/src/shared/git-internals.ts +61 -6
  664. package/src/shared/git.contract.ts +70 -8
  665. package/src/shared/kb-context.ts +130 -0
  666. package/src/shared/kb-layout.test.ts +37 -27
  667. package/src/shared/kb-layout.ts +4 -3
  668. package/src/shared/pending-proposals.ts +7 -4
  669. package/src/shared/redact-secret.ts +5 -5
  670. package/src/tenancy/__tests__/static-tenant-source.test.ts +177 -0
  671. package/src/tenancy/__tests__/tenant-host.test.ts +372 -0
  672. package/src/tenancy/__tests__/tenant-runtime.test.ts +221 -0
  673. package/src/tenancy/__tests__/tenant-secrets.test.ts +35 -0
  674. package/src/tenancy/index.ts +35 -0
  675. package/src/tenancy/static-tenant-source.ts +296 -0
  676. package/src/tenancy/tenant-host.ts +261 -0
  677. package/src/tenancy/tenant-runtime.ts +208 -0
  678. package/src/tenancy/tenant-secrets.ts +41 -0
  679. package/src/tenancy/tenant-source.contract.ts +59 -0
  680. package/dist/modules/access/access-errors.d.ts +0 -34
  681. package/dist/modules/access/access-errors.d.ts.map +0 -1
  682. package/dist/modules/access/access-errors.js +0 -40
  683. package/dist/modules/access/access-errors.js.map +0 -1
  684. package/dist/modules/access/access-splice.d.ts +0 -140
  685. package/dist/modules/access/access-splice.d.ts.map +0 -1
  686. package/dist/modules/access/access-splice.js +0 -389
  687. package/dist/modules/access/access-splice.js.map +0 -1
  688. package/dist/modules/access/group-files.d.ts +0 -83
  689. package/dist/modules/access/group-files.d.ts.map +0 -1
  690. package/dist/modules/access/group-files.js +0 -167
  691. package/dist/modules/access/group-files.js.map +0 -1
  692. package/dist/modules/access/kb-read-filter.d.ts +0 -41
  693. package/dist/modules/access/kb-read-filter.d.ts.map +0 -1
  694. package/dist/modules/access/kb-read-filter.js +0 -60
  695. package/dist/modules/access/kb-read-filter.js.map +0 -1
  696. package/dist/modules/access/render-roles-yaml.d.ts +0 -22
  697. package/dist/modules/access/render-roles-yaml.d.ts.map +0 -1
  698. package/dist/modules/access/render-roles-yaml.js +0 -56
  699. package/dist/modules/access/render-roles-yaml.js.map +0 -1
  700. package/dist/modules/access/roles-yaml-guard.d.ts +0 -56
  701. package/dist/modules/access/roles-yaml-guard.d.ts.map +0 -1
  702. package/dist/modules/access/roles-yaml-guard.js +0 -79
  703. package/dist/modules/access/roles-yaml-guard.js.map +0 -1
  704. package/dist/modules/diff/diff-paths.d.ts +0 -2
  705. package/dist/modules/diff/diff-paths.d.ts.map +0 -1
  706. package/dist/modules/diff/diff-paths.js +0 -9
  707. package/dist/modules/diff/diff-paths.js.map +0 -1
  708. package/dist/modules/groups/group-provision.service.d.ts +0 -130
  709. package/dist/modules/groups/group-provision.service.d.ts.map +0 -1
  710. package/dist/modules/groups/group-provision.service.js +0 -288
  711. package/dist/modules/groups/group-provision.service.js.map +0 -1
  712. package/dist/modules/groups/groups.contract.d.ts +0 -106
  713. package/dist/modules/groups/groups.contract.d.ts.map +0 -1
  714. package/dist/modules/groups/groups.contract.js +0 -36
  715. package/dist/modules/groups/groups.contract.js.map +0 -1
  716. package/dist/modules/groups/groups.routes.d.ts +0 -42
  717. package/dist/modules/groups/groups.routes.d.ts.map +0 -1
  718. package/dist/modules/groups/groups.routes.js +0 -379
  719. package/dist/modules/groups/groups.routes.js.map +0 -1
  720. package/dist/modules/groups/groups.service.d.ts +0 -60
  721. package/dist/modules/groups/groups.service.d.ts.map +0 -1
  722. package/dist/modules/groups/groups.service.js +0 -172
  723. package/dist/modules/groups/groups.service.js.map +0 -1
  724. package/dist/modules/groups/index.d.ts +0 -7
  725. package/dist/modules/groups/index.d.ts.map +0 -1
  726. package/dist/modules/groups/index.js +0 -6
  727. package/dist/modules/groups/index.js.map +0 -1
  728. package/dist/modules/groups/join-proposals.d.ts +0 -53
  729. package/dist/modules/groups/join-proposals.d.ts.map +0 -1
  730. package/dist/modules/groups/join-proposals.js +0 -67
  731. package/dist/modules/groups/join-proposals.js.map +0 -1
  732. package/dist/modules/groups/join-requests.service.d.ts +0 -81
  733. package/dist/modules/groups/join-requests.service.d.ts.map +0 -1
  734. package/dist/modules/groups/join-requests.service.js +0 -135
  735. package/dist/modules/groups/join-requests.service.js.map +0 -1
  736. package/dist/modules/mcp/mcp-session-store.d.ts +0 -74
  737. package/dist/modules/mcp/mcp-session-store.d.ts.map +0 -1
  738. package/dist/modules/mcp/mcp-session-store.js +0 -131
  739. package/dist/modules/mcp/mcp-session-store.js.map +0 -1
  740. package/dist/modules/workflow/file-change-notifier.d.ts +0 -38
  741. package/dist/modules/workflow/file-change-notifier.d.ts.map +0 -1
  742. package/dist/modules/workflow/file-change-notifier.js +0 -22
  743. package/dist/modules/workflow/file-change-notifier.js.map +0 -1
  744. package/dist/modules/workflow/git/branch-name.d.ts +0 -10
  745. package/dist/modules/workflow/git/branch-name.d.ts.map +0 -1
  746. package/dist/modules/workflow/git/branch-name.js +0 -76
  747. package/dist/modules/workflow/git/branch-name.js.map +0 -1
  748. package/dist/modules/workflow/git/clone-config.d.ts +0 -61
  749. package/dist/modules/workflow/git/clone-config.d.ts.map +0 -1
  750. package/dist/modules/workflow/git/clone-config.js +0 -69
  751. package/dist/modules/workflow/git/clone-config.js.map +0 -1
  752. package/dist/modules/workflow/git/mutex.d.ts +0 -11
  753. package/dist/modules/workflow/git/mutex.d.ts.map +0 -1
  754. package/dist/modules/workflow/git/mutex.js +0 -23
  755. package/dist/modules/workflow/git/mutex.js.map +0 -1
  756. package/dist/modules/workflow/locking-filesystem.d.ts +0 -137
  757. package/dist/modules/workflow/locking-filesystem.d.ts.map +0 -1
  758. package/dist/modules/workflow/locking-filesystem.js +0 -553
  759. package/dist/modules/workflow/locking-filesystem.js.map +0 -1
  760. package/dist/modules/workflow/read-only-filesystem.d.ts +0 -24
  761. package/dist/modules/workflow/read-only-filesystem.d.ts.map +0 -1
  762. package/dist/modules/workflow/read-only-filesystem.js +0 -39
  763. package/dist/modules/workflow/read-only-filesystem.js.map +0 -1
  764. package/dist/modules/workflow/workflow.errors.d.ts +0 -197
  765. package/dist/modules/workflow/workflow.errors.d.ts.map +0 -1
  766. package/dist/modules/workflow/workflow.errors.js +0 -298
  767. package/dist/modules/workflow/workflow.errors.js.map +0 -1
  768. package/dist/modules/workspace/bevel-ignore.d.ts +0 -30
  769. package/dist/modules/workspace/bevel-ignore.d.ts.map +0 -1
  770. package/dist/modules/workspace/bevel-ignore.js +0 -61
  771. package/dist/modules/workspace/bevel-ignore.js.map +0 -1
  772. package/dist/modules/workspace/kb-seed.interface.d.ts +0 -36
  773. package/dist/modules/workspace/kb-seed.interface.d.ts.map +0 -1
  774. package/dist/modules/workspace/kb-seed.interface.js +0 -2
  775. package/dist/modules/workspace/kb-seed.interface.js.map +0 -1
  776. package/dist/modules/workspace/kb-seed.service.d.ts +0 -125
  777. package/dist/modules/workspace/kb-seed.service.d.ts.map +0 -1
  778. package/dist/modules/workspace/kb-seed.service.js +0 -535
  779. package/dist/modules/workspace/kb-seed.service.js.map +0 -1
  780. package/dist/modules/workspace/plugins-migration.d.ts +0 -50
  781. package/dist/modules/workspace/plugins-migration.d.ts.map +0 -1
  782. package/dist/modules/workspace/plugins-migration.js +0 -379
  783. package/dist/modules/workspace/plugins-migration.js.map +0 -1
  784. package/dist/shared/fs-errors.d.ts +0 -8
  785. package/dist/shared/fs-errors.d.ts.map +0 -1
  786. package/dist/shared/fs-errors.js +0 -11
  787. package/dist/shared/fs-errors.js.map +0 -1
  788. package/dist/shared/fs-walk.d.ts +0 -23
  789. package/dist/shared/fs-walk.d.ts.map +0 -1
  790. package/dist/shared/fs-walk.js +0 -42
  791. package/dist/shared/fs-walk.js.map +0 -1
  792. package/dist/shared/hash-email.d.ts +0 -11
  793. package/dist/shared/hash-email.d.ts.map +0 -1
  794. package/dist/shared/hash-email.js +0 -14
  795. package/dist/shared/hash-email.js.map +0 -1
  796. package/dist/shared/kb-walk.d.ts +0 -52
  797. package/dist/shared/kb-walk.d.ts.map +0 -1
  798. package/dist/shared/kb-walk.js +0 -76
  799. package/dist/shared/kb-walk.js.map +0 -1
@@ -1,7 +1,6 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import {
4
- DEFAULT_BRANCH,
5
4
  PLUGIN_MANIFEST_FILE,
6
5
  linkedSkillRoots,
7
6
  normalizeSkillRoot,
@@ -19,8 +18,57 @@ import { pluginPrincipalKey } from '../access-model/access-grammar.js';
19
18
  import type { Principal } from '../access-model/access-splice.js';
20
19
  import { WorkspaceMutex } from '../kb-fs/mutex.js';
21
20
  import type { ISkillService } from '../skills/skills.contract.js';
21
+ import { logger } from '../../shared/logging.js';
22
22
  import type { ProvisionCommitDriver } from './plugin-provision.service.js';
23
- import { linksWorkspaceId, type PluginLinkIndex } from './plugin-links.js';
23
+ import type { PluginLinkIndex } from './plugin-links.js';
24
+ import type { KbContext } from '../../shared/kb-context.js';
25
+
26
+ const log = logger('plugins');
27
+
28
+ /** Who may edit one skill root's access file, in the terms the banner names them. */
29
+ export interface LinkEditors {
30
+ roles: string[];
31
+ users: { name: string; email: string }[];
32
+ }
33
+
34
+ /** One link the automatic repair left alone, and why — see `repairAll`. */
35
+ export interface UnrepairedLink {
36
+ /** Repo-relative root, as the manifest declares it. */
37
+ root: string;
38
+ /**
39
+ * `needs-skill-write` — the viewer may not write the root's access file, so
40
+ * nothing was attempted; `failed` — the write was attempted and did not
41
+ * land; `denied` — both lines are already in the file and the link is still
42
+ * not granted, which is a `deny` of the plugin at that root: nothing to
43
+ * write, and only an editor removing the deny would change it. All three
44
+ * leave the link broken and all three keep the banner.
45
+ */
46
+ reason: 'needs-skill-write' | 'failed' | 'denied';
47
+ /** The skills the plugin's members still cannot read through the root. */
48
+ skills: { path: string; name: string }[];
49
+ /** Who can repair it from the skill page. */
50
+ editors: LinkEditors;
51
+ }
52
+
53
+ /** What one page-open repair did and what it could not do. */
54
+ export interface LinkRepairReport {
55
+ /** Roots whose two grant lines are now in place (silent: nothing to show). */
56
+ repaired: string[];
57
+ /** What is still broken, and who can fix it. */
58
+ skipped: UnrepairedLink[];
59
+ }
60
+
61
+ /**
62
+ * The commit subject for an automatic repair. It names the plugin, the root
63
+ * and the fact that nobody asked for it — the commit is the ONLY trace a
64
+ * silent repair leaves, so the history has to explain itself. Falls back to
65
+ * the path-derived default when a very long root would blow the 200-character
66
+ * subject limit: a missed explanation is not worth a failed repair.
67
+ */
68
+ function repairSummary(plugin: string, root: string): string | undefined {
69
+ const subject = `Repair link: ${plugin} → ${root} (automatic, on opening the plugin page)`;
70
+ return subject.length <= 200 ? subject : undefined;
71
+ }
24
72
 
25
73
  /** A refusal the route passes through: message + HTTP status + a machine-readable kind. */
26
74
  export class PluginLinkError extends Error {
@@ -59,7 +107,9 @@ export class PluginLinkError extends Error {
59
107
  * skill page says so, for a skill editor to remove.
60
108
  *
61
109
  * Repair re-grants the tokens for a link that exists but whose grant was
62
- * hand-removed: the amber dot's one action.
110
+ * hand-removed — the amber dot's one action, run one link at a time from the
111
+ * skill page, or over a whole plugin's links by `repairAll` the moment
112
+ * somebody who may write that plugin opens its page.
63
113
  *
64
114
  * Every operation is serialised on BOTH sides it writes — the plugin's
65
115
  * manifest slug (the same key provisioning locks on) and the skill root whose
@@ -77,19 +127,23 @@ export class PluginLinksService {
77
127
  private readonly accessControl: IAccessControl,
78
128
  private readonly skillService: ISkillService,
79
129
  private readonly links: PluginLinkIndex,
80
- private readonly kbDirName: string,
130
+ private readonly kb: KbContext,
81
131
  private readonly events?: {
82
132
  emit(event: { kind: 'fs-tree-changed'; workspaceId: string; branch: string }): void;
83
133
  },
84
134
  private readonly onChanged?: () => void,
85
135
  ) {
86
- this.mutation = new AccessMutationService(workspaceService, accessControl, kbDirName);
136
+ this.mutation = new AccessMutationService(workspaceService, accessControl, kb.kbDirName);
137
+ }
138
+
139
+ private get kbDirName(): string {
140
+ return this.kb.kbDirName;
87
141
  }
88
142
 
89
143
  async link(user: AuthUser, plugin: string, rawRoot: string): Promise<{ root: string; skills: string[] }> {
90
144
  const folder = await this.pluginFolder(plugin);
91
145
  const root = this.rootOrThrow(rawRoot);
92
- const wsId = linksWorkspaceId();
146
+ const wsId = this.kb.defaultWorkspaceId();
93
147
  await this.requirePluginWrite(wsId, user, folder);
94
148
  const skills = await this.resolvedSkills(root);
95
149
  if (skills.length === 0) {
@@ -125,7 +179,7 @@ export class PluginLinksService {
125
179
  manifestRel,
126
180
  `${JSON.stringify(withLinkedSkillRoots(manifest, [...roots, root]), null, 2)}\n`,
127
181
  );
128
- await this.commits.runPendingCommit(wsId, DEFAULT_BRANCH, manifestRel, user);
182
+ await this.commits.runPendingCommit(wsId, this.kb.defaultBranch, manifestRel, user);
129
183
  }
130
184
  await this.grantTokens(wsId, user, folder, root);
131
185
  this.changed(wsId);
@@ -136,7 +190,7 @@ export class PluginLinksService {
136
190
  async unlink(user: AuthUser, plugin: string, rawRoot: string): Promise<{ root: string; revoked: boolean }> {
137
191
  const folder = await this.pluginFolder(plugin);
138
192
  const root = this.rootOrThrow(rawRoot);
139
- const wsId = linksWorkspaceId();
193
+ const wsId = this.kb.defaultWorkspaceId();
140
194
  await this.requirePluginWrite(wsId, user, folder);
141
195
  return this.locks.runAll(this.lockKeys(folder, root), async () => {
142
196
  const { manifest, manifestRel } = await this.readManifest(wsId, folder);
@@ -163,7 +217,7 @@ export class PluginLinksService {
163
217
  if (changed) {
164
218
  await this.commits.runPendingCommit(
165
219
  wsId,
166
- DEFAULT_BRANCH,
220
+ this.kb.defaultBranch,
167
221
  `${this.kbDirName}/${accessMdPathForFolder(root)}`,
168
222
  user,
169
223
  );
@@ -175,16 +229,36 @@ export class PluginLinksService {
175
229
  manifestRel,
176
230
  `${JSON.stringify(withLinkedSkillRoots(manifest, roots.filter((r) => r !== root)), null, 2)}\n`,
177
231
  );
178
- await this.commits.runPendingCommit(wsId, DEFAULT_BRANCH, manifestRel, user);
232
+ await this.commits.runPendingCommit(wsId, this.kb.defaultBranch, manifestRel, user);
179
233
  this.changed(wsId);
180
234
  return { root, revoked };
181
235
  });
182
236
  }
183
237
 
184
- async repair(user: AuthUser, plugin: string, rawRoot: string): Promise<{ root: string }> {
238
+ /**
239
+ * Re-grant one link's two tokens. The skill EDITOR's verb (the plugin side
240
+ * is not consulted): the amber dot's one manual action, and the single
241
+ * write the automatic repair runs too — see {@link repairAll}.
242
+ *
243
+ * `summary` is the commit subject when the caller has a better one than the
244
+ * path-derived default; the automatic repair passes one that says it was
245
+ * automatic, because the commit is the only trace it leaves.
246
+ *
247
+ * `written` says whether the file changed. A root that already carried
248
+ * both lines is left alone and reports false — which, for a root the index
249
+ * called ungranted, means the lines are not what is missing (a `deny`
250
+ * beside them is): the automatic repair reads it as "still broken", not as
251
+ * repaired.
252
+ */
253
+ async repair(
254
+ user: AuthUser,
255
+ plugin: string,
256
+ rawRoot: string,
257
+ opts?: { summary?: string },
258
+ ): Promise<{ root: string; written: boolean }> {
185
259
  const folder = await this.pluginFolder(plugin);
186
260
  const root = this.rootOrThrow(rawRoot);
187
- const wsId = linksWorkspaceId();
261
+ const wsId = this.kb.defaultWorkspaceId();
188
262
  // Everything under the lock, the manifest read included: a repair that
189
263
  // checked the link and then waited on an unlink would re-grant a root the
190
264
  // manifest no longer names.
@@ -199,14 +273,98 @@ export class PluginLinksService {
199
273
  root,
200
274
  });
201
275
  }
202
- await this.grantTokens(wsId, user, folder, root);
276
+ const written = await this.grantTokens(wsId, user, folder, root, opts?.summary);
203
277
  this.changed(wsId);
204
- return { root };
278
+ return { root, written };
205
279
  });
206
280
  }
207
281
 
282
+ /**
283
+ * Repair EVERY link of `plugin` that is missing its grants — what opening
284
+ * the plugin's page runs for someone who may write the plugin.
285
+ *
286
+ * Two gates, in this order: the caller must be able to write the PLUGIN
287
+ * (this is the plugin's page repairing its own links, not a way to write
288
+ * other people's access files), and then, per root, to write that root's
289
+ * access file. A root they cannot write is left exactly as it is and comes
290
+ * back in `skipped` with the people who CAN write it, which is the sentence
291
+ * the banner then says. Nothing comes back for a root that was repaired:
292
+ * the commit is the trace, the page simply renders with the link healthy.
293
+ *
294
+ * Root by root through {@link repair} — the same write, the same manifest
295
+ * check, the same pair of locks — so the automatic path and the button on
296
+ * the skill page can never write different things. Each root's failure is
297
+ * caught into `skipped`: one unwritable file must not cost the others their
298
+ * repair, nor the page its render.
299
+ *
300
+ * A root the repair did not have to write is NOT repaired. The work list
301
+ * holds only roots the index called ungranted, so a root whose two lines
302
+ * were already there is broken by something the lines cannot fix — a `deny`
303
+ * of the plugin in that same file — and reporting it repaired would hide
304
+ * the one link the writer opening this page could not see anywhere else.
305
+ */
306
+ async repairAll(user: AuthUser, plugin: string): Promise<LinkRepairReport> {
307
+ const folder = await this.pluginFolder(plugin);
308
+ const wsId = this.kb.defaultWorkspaceId();
309
+ await this.requirePluginWrite(wsId, user, folder);
310
+ // Read the work list ONCE, before the first write: `repair` invalidates
311
+ // the index, and re-reading it per root would rebuild the whole membership
312
+ // between every commit.
313
+ const work = (await this.links.membership()).byPlugin.get(folder)?.ungrantedRoots ?? [];
314
+ if (work.length === 0) return { repaired: [], skipped: [] };
315
+ const named = new Map((await this.skillService.listSkills(undefined)).map((s) => [s.path, s.name]));
316
+ const repaired: string[] = [];
317
+ const skipped: UnrepairedLink[] = [];
318
+ const leftBroken = async (item: (typeof work)[number], reason: UnrepairedLink['reason']) => {
319
+ skipped.push({
320
+ root: item.root,
321
+ reason,
322
+ skills: item.skills.map((path) => ({ path, name: named.get(path) ?? path.split('/').pop() ?? path })),
323
+ editors: await this.editorsOf(wsId, item.root),
324
+ });
325
+ };
326
+ for (const item of work) {
327
+ try {
328
+ const { written } = await this.repair(user, folder, item.root, { summary: repairSummary(folder, item.root) });
329
+ if (written) repaired.push(item.root);
330
+ else await leftBroken(item, 'denied');
331
+ } catch (err) {
332
+ const needsWrite = err instanceof PluginLinkError && err.payload.kind === 'needs-skill-write';
333
+ if (!needsWrite) log.warn('automatic link repair failed:', { plugin: folder, root: item.root, err });
334
+ await leftBroken(item, needsWrite ? 'needs-skill-write' : 'failed');
335
+ }
336
+ }
337
+ return { repaired, skipped };
338
+ }
339
+
208
340
  // --- internal --------------------------------------------------------------
209
341
 
342
+ /**
343
+ * Who may edit a root's access file — the principals the banner names as
344
+ * the people who can repair a link this viewer cannot.
345
+ *
346
+ * Plugin principals are dropped: `plugin/gtm/write` is a real holder of the
347
+ * verb, and naming it in a sentence addressed to a person says nothing they
348
+ * could act on. The eligible lists carry emails and no display names, so an
349
+ * email stands in — every name here has to be something a reader can go and
350
+ * ask. A lookup that fails names nobody rather than failing the whole
351
+ * repair — the banner has a sentence for that.
352
+ */
353
+ private async editorsOf(wsId: string, root: string): Promise<LinkEditors> {
354
+ try {
355
+ const writers = await this.accessControl.eligibleWriters(wsId, accessMdPathForFolder(root));
356
+ return {
357
+ roles: writers.principals
358
+ ? writers.principals.filter((p) => p.kind !== 'plugin').map((p) => p.name)
359
+ : writers.roles,
360
+ users: writers.users.map((u) => ({ name: u.name || u.email, email: u.email })),
361
+ };
362
+ } catch (err) {
363
+ log.warn("couldn't resolve a skill root's editors:", { root, err });
364
+ return { roles: [], users: [] };
365
+ }
366
+ }
367
+
210
368
  /**
211
369
  * ONE reservation for both sides of a link: the plugin's manifest AND the
212
370
  * skill root's access.md. Two plugins linking the same root write the same
@@ -232,13 +390,28 @@ export class PluginLinksService {
232
390
  ];
233
391
  }
234
392
 
235
- private async grantTokens(wsId: string, user: AuthUser, folder: string, root: string): Promise<void> {
393
+ /**
394
+ * The two lines, and a commit only if they were not already there — the
395
+ * `changed` check is what makes re-linking, Repair and the page-open repair
396
+ * idempotent rather than a stream of empty commits. Returns whether the
397
+ * file changed, so a caller can tell a repair that wrote from one that had
398
+ * nothing to write.
399
+ */
400
+ private async grantTokens(
401
+ wsId: string,
402
+ user: AuthUser,
403
+ folder: string,
404
+ root: string,
405
+ summary?: string,
406
+ ): Promise<boolean> {
236
407
  const [read, write] = this.tokens(folder);
237
408
  const a = await this.mutation.grant(wsId, 'folder', root, 'read', read);
238
409
  const b = await this.mutation.grant(wsId, 'folder', root, 'write', write);
239
- if (a.changed || b.changed) {
240
- await this.commits.runPendingCommit(wsId, DEFAULT_BRANCH, `${this.kbDirName}/${a.editPath}`, user);
241
- }
410
+ if (!(a.changed || b.changed)) return false;
411
+ await this.commits.runPendingCommit(wsId, this.kb.defaultBranch, `${this.kbDirName}/${a.editPath}`, user, {
412
+ summary,
413
+ });
414
+ return true;
242
415
  }
243
416
 
244
417
  private rootOrThrow(raw: string): string {
@@ -345,6 +518,6 @@ export class PluginLinksService {
345
518
  this.links.invalidate();
346
519
  this.accessControl.invalidate(wsId);
347
520
  this.onChanged?.();
348
- this.events?.emit({ kind: 'fs-tree-changed', workspaceId: wsId, branch: DEFAULT_BRANCH });
521
+ this.events?.emit({ kind: 'fs-tree-changed', workspaceId: wsId, branch: this.kb.defaultBranch });
349
522
  }
350
523
  }
@@ -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
  }