@bevel-software/platform-core-backend 0.14.0 → 0.15.1

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 (385) hide show
  1. package/THIRD-PARTY-NOTICES.md +6 -6
  2. package/dist/core/catalog-cache-invalidation.d.ts +29 -0
  3. package/dist/core/catalog-cache-invalidation.d.ts.map +1 -0
  4. package/dist/core/catalog-cache-invalidation.js +71 -0
  5. package/dist/core/catalog-cache-invalidation.js.map +1 -0
  6. package/dist/core/create-core-server.d.ts.map +1 -1
  7. package/dist/core/create-core-server.js +99 -8
  8. package/dist/core/create-core-server.js.map +1 -1
  9. package/dist/core/create-core-services.d.ts +18 -1
  10. package/dist/core/create-core-services.d.ts.map +1 -1
  11. package/dist/core/create-core-services.js +96 -43
  12. package/dist/core/create-core-services.js.map +1 -1
  13. package/dist/modules/access/access-control.interface.d.ts +18 -6
  14. package/dist/modules/access/access-control.interface.d.ts.map +1 -1
  15. package/dist/modules/access/access-control.service.d.ts +26 -1
  16. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  17. package/dist/modules/access/access-control.service.js +213 -71
  18. package/dist/modules/access/access-control.service.js.map +1 -1
  19. package/dist/modules/access/access.routes.d.ts.map +1 -1
  20. package/dist/modules/access/access.routes.js +59 -7
  21. package/dist/modules/access/access.routes.js.map +1 -1
  22. package/dist/modules/access-model/access-grammar.d.ts +51 -1
  23. package/dist/modules/access-model/access-grammar.d.ts.map +1 -1
  24. package/dist/modules/access-model/access-grammar.js +95 -1
  25. package/dist/modules/access-model/access-grammar.js.map +1 -1
  26. package/dist/modules/access-model/group-files.d.ts.map +1 -1
  27. package/dist/modules/access-model/group-files.js +4 -1
  28. package/dist/modules/access-model/group-files.js.map +1 -1
  29. package/dist/modules/access-model/plugin-principals.d.ts +49 -0
  30. package/dist/modules/access-model/plugin-principals.d.ts.map +1 -0
  31. package/dist/modules/access-model/plugin-principals.js +125 -0
  32. package/dist/modules/access-model/plugin-principals.js.map +1 -0
  33. package/dist/modules/database/core-schema.d.ts +326 -0
  34. package/dist/modules/database/core-schema.d.ts.map +1 -1
  35. package/dist/modules/database/core-schema.js +52 -0
  36. package/dist/modules/database/core-schema.js.map +1 -1
  37. package/dist/modules/kb-sync/index.d.ts +6 -0
  38. package/dist/modules/kb-sync/index.d.ts.map +1 -0
  39. package/dist/modules/kb-sync/index.js +5 -0
  40. package/dist/modules/kb-sync/index.js.map +1 -0
  41. package/dist/modules/kb-sync/kb-sync.interface.d.ts +77 -0
  42. package/dist/modules/kb-sync/kb-sync.interface.d.ts.map +1 -0
  43. package/dist/modules/kb-sync/kb-sync.interface.js +2 -0
  44. package/dist/modules/kb-sync/kb-sync.interface.js.map +1 -0
  45. package/dist/modules/kb-sync/kb-sync.routes.d.ts +70 -0
  46. package/dist/modules/kb-sync/kb-sync.routes.d.ts.map +1 -0
  47. package/dist/modules/kb-sync/kb-sync.routes.js +135 -0
  48. package/dist/modules/kb-sync/kb-sync.routes.js.map +1 -0
  49. package/dist/modules/kb-sync/kb-sync.service.d.ts +45 -0
  50. package/dist/modules/kb-sync/kb-sync.service.d.ts.map +1 -0
  51. package/dist/modules/kb-sync/kb-sync.service.js +183 -0
  52. package/dist/modules/kb-sync/kb-sync.service.js.map +1 -0
  53. package/dist/modules/kb-sync/sync-auth.d.ts +59 -0
  54. package/dist/modules/kb-sync/sync-auth.d.ts.map +1 -0
  55. package/dist/modules/kb-sync/sync-auth.js +62 -0
  56. package/dist/modules/kb-sync/sync-auth.js.map +1 -0
  57. package/dist/modules/kb-sync/sync-payload.d.ts +32 -0
  58. package/dist/modules/kb-sync/sync-payload.d.ts.map +1 -0
  59. package/dist/modules/kb-sync/sync-payload.js +105 -0
  60. package/dist/modules/kb-sync/sync-payload.js.map +1 -0
  61. package/dist/modules/marketplace/git-http.routes.d.ts +42 -0
  62. package/dist/modules/marketplace/git-http.routes.d.ts.map +1 -0
  63. package/dist/modules/marketplace/git-http.routes.js +190 -0
  64. package/dist/modules/marketplace/git-http.routes.js.map +1 -0
  65. package/dist/modules/marketplace/github-facade/github-facade-admin.routes.d.ts +23 -0
  66. package/dist/modules/marketplace/github-facade/github-facade-admin.routes.d.ts.map +1 -0
  67. package/dist/modules/marketplace/github-facade/github-facade-admin.routes.js +59 -0
  68. package/dist/modules/marketplace/github-facade/github-facade-admin.routes.js.map +1 -0
  69. package/dist/modules/marketplace/github-facade/github-facade-codes.store.d.ts +59 -0
  70. package/dist/modules/marketplace/github-facade/github-facade-codes.store.d.ts.map +1 -0
  71. package/dist/modules/marketplace/github-facade/github-facade-codes.store.js +96 -0
  72. package/dist/modules/marketplace/github-facade/github-facade-codes.store.js.map +1 -0
  73. package/dist/modules/marketplace/github-facade/github-facade-credentials.service.d.ts +99 -0
  74. package/dist/modules/marketplace/github-facade/github-facade-credentials.service.d.ts.map +1 -0
  75. package/dist/modules/marketplace/github-facade/github-facade-credentials.service.js +147 -0
  76. package/dist/modules/marketplace/github-facade/github-facade-credentials.service.js.map +1 -0
  77. package/dist/modules/marketplace/github-facade/github-facade.routes.d.ts +47 -0
  78. package/dist/modules/marketplace/github-facade/github-facade.routes.d.ts.map +1 -0
  79. package/dist/modules/marketplace/github-facade/github-facade.routes.js +228 -0
  80. package/dist/modules/marketplace/github-facade/github-facade.routes.js.map +1 -0
  81. package/dist/modules/marketplace/github-facade/github-facade.service.d.ts +109 -0
  82. package/dist/modules/marketplace/github-facade/github-facade.service.d.ts.map +1 -0
  83. package/dist/modules/marketplace/github-facade/github-facade.service.js +172 -0
  84. package/dist/modules/marketplace/github-facade/github-facade.service.js.map +1 -0
  85. package/dist/modules/marketplace/github-facade/index.d.ts +6 -0
  86. package/dist/modules/marketplace/github-facade/index.d.ts.map +1 -0
  87. package/dist/modules/marketplace/github-facade/index.js +6 -0
  88. package/dist/modules/marketplace/github-facade/index.js.map +1 -0
  89. package/dist/modules/marketplace/index.d.ts +4 -0
  90. package/dist/modules/marketplace/index.d.ts.map +1 -0
  91. package/dist/modules/marketplace/index.js +4 -0
  92. package/dist/modules/marketplace/index.js.map +1 -0
  93. package/dist/modules/marketplace/marketplace-repo.service.d.ts +122 -0
  94. package/dist/modules/marketplace/marketplace-repo.service.d.ts.map +1 -0
  95. package/dist/modules/marketplace/marketplace-repo.service.js +300 -0
  96. package/dist/modules/marketplace/marketplace-repo.service.js.map +1 -0
  97. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
  98. package/dist/modules/mcp/oauth/bevel-oauth-provider.js +4 -0
  99. package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
  100. package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts +14 -8
  101. package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts.map +1 -1
  102. package/dist/modules/mcp/oauth/oauth-consent.routes.js +13 -1
  103. package/dist/modules/mcp/oauth/oauth-consent.routes.js.map +1 -1
  104. package/dist/modules/mcp/oauth/oauth-state.d.ts +13 -2
  105. package/dist/modules/mcp/oauth/oauth-state.d.ts.map +1 -1
  106. package/dist/modules/mcp/oauth/oauth-state.js +3 -1
  107. package/dist/modules/mcp/oauth/oauth-state.js.map +1 -1
  108. package/dist/modules/plugins/compile/compile-marketplace.d.ts +97 -0
  109. package/dist/modules/plugins/compile/compile-marketplace.d.ts.map +1 -0
  110. package/dist/modules/plugins/compile/compile-marketplace.js +240 -0
  111. package/dist/modules/plugins/compile/compile-marketplace.js.map +1 -0
  112. package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts +66 -0
  113. package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts.map +1 -0
  114. package/dist/modules/plugins/compile/marketplace-compiler.service.js +132 -0
  115. package/dist/modules/plugins/compile/marketplace-compiler.service.js.map +1 -0
  116. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts +37 -0
  117. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts.map +1 -0
  118. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js +135 -0
  119. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js.map +1 -0
  120. package/dist/modules/plugins/discovery/bundle-dialect/registry.d.ts +45 -0
  121. package/dist/modules/plugins/discovery/bundle-dialect/registry.d.ts.map +1 -0
  122. package/dist/modules/plugins/discovery/bundle-dialect/registry.js +147 -0
  123. package/dist/modules/plugins/discovery/bundle-dialect/registry.js.map +1 -0
  124. package/dist/modules/plugins/discovery/kb-plugin-source.d.ts +37 -0
  125. package/dist/modules/plugins/discovery/kb-plugin-source.d.ts.map +1 -0
  126. package/dist/modules/plugins/discovery/kb-plugin-source.js +107 -0
  127. package/dist/modules/plugins/discovery/kb-plugin-source.js.map +1 -0
  128. package/dist/modules/plugins/discovery/native.source.d.ts +15 -0
  129. package/dist/modules/plugins/discovery/native.source.d.ts.map +1 -0
  130. package/dist/modules/plugins/discovery/native.source.js +102 -0
  131. package/dist/modules/plugins/discovery/native.source.js.map +1 -0
  132. package/dist/modules/plugins/discovery/plugin-source.d.ts +96 -0
  133. package/dist/modules/plugins/discovery/plugin-source.d.ts.map +1 -0
  134. package/dist/modules/plugins/discovery/plugin-source.js +2 -0
  135. package/dist/modules/plugins/discovery/plugin-source.js.map +1 -0
  136. package/dist/modules/plugins/index.d.ts +10 -1
  137. package/dist/modules/plugins/index.d.ts.map +1 -1
  138. package/dist/modules/plugins/index.js +8 -0
  139. package/dist/modules/plugins/index.js.map +1 -1
  140. package/dist/modules/plugins/plugin-links.d.ts +66 -0
  141. package/dist/modules/plugins/plugin-links.d.ts.map +1 -0
  142. package/dist/modules/plugins/plugin-links.js +160 -0
  143. package/dist/modules/plugins/plugin-links.js.map +1 -0
  144. package/dist/modules/plugins/plugin-links.service.d.ts +114 -0
  145. package/dist/modules/plugins/plugin-links.service.d.ts.map +1 -0
  146. package/dist/modules/plugins/plugin-links.service.js +304 -0
  147. package/dist/modules/plugins/plugin-links.service.js.map +1 -0
  148. package/dist/modules/plugins/plugin-provision.service.d.ts +39 -3
  149. package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
  150. package/dist/modules/plugins/plugin-provision.service.js +152 -52
  151. package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
  152. package/dist/modules/plugins/plugin-rename.service.d.ts +69 -0
  153. package/dist/modules/plugins/plugin-rename.service.d.ts.map +1 -0
  154. package/dist/modules/plugins/plugin-rename.service.js +245 -0
  155. package/dist/modules/plugins/plugin-rename.service.js.map +1 -0
  156. package/dist/modules/plugins/plugins.contract.d.ts +27 -1
  157. package/dist/modules/plugins/plugins.contract.d.ts.map +1 -1
  158. package/dist/modules/plugins/plugins.routes.d.ts +7 -1
  159. package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
  160. package/dist/modules/plugins/plugins.routes.js +120 -12
  161. package/dist/modules/plugins/plugins.routes.js.map +1 -1
  162. package/dist/modules/plugins/plugins.service.d.ts +50 -3
  163. package/dist/modules/plugins/plugins.service.d.ts.map +1 -1
  164. package/dist/modules/plugins/plugins.service.js +108 -47
  165. package/dist/modules/plugins/plugins.service.js.map +1 -1
  166. package/dist/modules/settings/deployment-settings.service.d.ts +9 -0
  167. package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
  168. package/dist/modules/settings/deployment-settings.service.js +82 -2
  169. package/dist/modules/settings/deployment-settings.service.js.map +1 -1
  170. package/dist/modules/settings/setup.routes.d.ts +26 -0
  171. package/dist/modules/settings/setup.routes.d.ts.map +1 -1
  172. package/dist/modules/settings/setup.routes.js +9 -1
  173. package/dist/modules/settings/setup.routes.js.map +1 -1
  174. package/dist/modules/skills/index.d.ts +1 -0
  175. package/dist/modules/skills/index.d.ts.map +1 -1
  176. package/dist/modules/skills/index.js +1 -0
  177. package/dist/modules/skills/index.js.map +1 -1
  178. package/dist/modules/skills/pending-skills.service.d.ts.map +1 -1
  179. package/dist/modules/skills/pending-skills.service.js +9 -4
  180. package/dist/modules/skills/pending-skills.service.js.map +1 -1
  181. package/dist/modules/skills/skill-access-requests.routes.d.ts +38 -0
  182. package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -0
  183. package/dist/modules/skills/skill-access-requests.routes.js +168 -0
  184. package/dist/modules/skills/skill-access-requests.routes.js.map +1 -0
  185. package/dist/modules/skills/skills.contract.d.ts +31 -0
  186. package/dist/modules/skills/skills.contract.d.ts.map +1 -1
  187. package/dist/modules/skills/skills.routes.d.ts +28 -3
  188. package/dist/modules/skills/skills.routes.d.ts.map +1 -1
  189. package/dist/modules/skills/skills.routes.js +42 -3
  190. package/dist/modules/skills/skills.routes.js.map +1 -1
  191. package/dist/modules/skills/skills.service.d.ts +4 -0
  192. package/dist/modules/skills/skills.service.d.ts.map +1 -1
  193. package/dist/modules/skills/skills.service.js +83 -22
  194. package/dist/modules/skills/skills.service.js.map +1 -1
  195. package/dist/modules/tool-auth/external-api-key.interface.d.ts +18 -1
  196. package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -1
  197. package/dist/modules/tool-auth/external-api-key.interface.js +2 -1
  198. package/dist/modules/tool-auth/external-api-key.interface.js.map +1 -1
  199. package/dist/modules/tool-auth/external-api-key.service.d.ts +13 -4
  200. package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
  201. package/dist/modules/tool-auth/external-api-key.service.js +26 -9
  202. package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
  203. package/dist/modules/tool-manuals/mcp-json-discovery.d.ts +36 -0
  204. package/dist/modules/tool-manuals/mcp-json-discovery.d.ts.map +1 -1
  205. package/dist/modules/tool-manuals/mcp-json-discovery.js +130 -92
  206. package/dist/modules/tool-manuals/mcp-json-discovery.js.map +1 -1
  207. package/dist/modules/tool-manuals/tool-manuals.service.d.ts +6 -1
  208. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
  209. package/dist/modules/tool-manuals/tool-manuals.service.js +18 -25
  210. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
  211. package/dist/modules/workflow/git/git.service.d.ts +40 -2
  212. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  213. package/dist/modules/workflow/git/git.service.js +227 -54
  214. package/dist/modules/workflow/git/git.service.js.map +1 -1
  215. package/dist/modules/workflow/git/pull-request.service.d.ts +6 -0
  216. package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
  217. package/dist/modules/workflow/git/pull-request.service.js +8 -0
  218. package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
  219. package/dist/modules/workflow/workflow.service.d.ts +52 -1
  220. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  221. package/dist/modules/workflow/workflow.service.js +242 -9
  222. package/dist/modules/workflow/workflow.service.js.map +1 -1
  223. package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts +35 -0
  224. package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts.map +1 -0
  225. package/dist/modules/workspace/startup/steps/plugin-manifests.step.js +121 -0
  226. package/dist/modules/workspace/startup/steps/plugin-manifests.step.js.map +1 -0
  227. package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
  228. package/dist/modules/workspace/startup/steps/seed-tree.js +46 -2
  229. package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
  230. package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
  231. package/dist/modules/workspace/startup/steps/template-files.step.js +112 -25
  232. package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
  233. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  234. package/dist/modules/workspace/workspace.routes.js +9 -9
  235. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  236. package/dist/modules/workspace/workspace.service.d.ts +33 -0
  237. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  238. package/dist/modules/workspace/workspace.service.js +110 -16
  239. package/dist/modules/workspace/workspace.service.js.map +1 -1
  240. package/dist/shared/domain-errors.d.ts +20 -0
  241. package/dist/shared/domain-errors.d.ts.map +1 -1
  242. package/dist/shared/domain-errors.js +29 -0
  243. package/dist/shared/domain-errors.js.map +1 -1
  244. package/dist/shared/fs-errors.d.ts +8 -0
  245. package/dist/shared/fs-errors.d.ts.map +1 -0
  246. package/dist/shared/fs-errors.js +11 -0
  247. package/dist/shared/fs-errors.js.map +1 -0
  248. package/dist/shared/fs-walk.d.ts +20 -6
  249. package/dist/shared/fs-walk.d.ts.map +1 -1
  250. package/dist/shared/fs-walk.js +35 -27
  251. package/dist/shared/fs-walk.js.map +1 -1
  252. package/dist/shared/kb-walk.d.ts +52 -0
  253. package/dist/shared/kb-walk.d.ts.map +1 -0
  254. package/dist/shared/kb-walk.js +76 -0
  255. package/dist/shared/kb-walk.js.map +1 -0
  256. package/dist/shared/path-order.d.ts +18 -0
  257. package/dist/shared/path-order.d.ts.map +1 -0
  258. package/dist/shared/path-order.js +35 -0
  259. package/dist/shared/path-order.js.map +1 -0
  260. package/dist/shared/ttl-cache.d.ts +28 -1
  261. package/dist/shared/ttl-cache.d.ts.map +1 -1
  262. package/dist/shared/ttl-cache.js +33 -1
  263. package/dist/shared/ttl-cache.js.map +1 -1
  264. package/kb-template/.bevelignore +1 -1
  265. package/kb-template/AGENTS.md +95 -30
  266. package/kb-template/Skills/.gitkeep +0 -0
  267. package/migrations/0005_github_facade.sql +25 -0
  268. package/migrations/meta/0005_snapshot.json +1717 -0
  269. package/migrations/meta/_journal.json +7 -0
  270. package/package.json +6 -6
  271. package/src/__tests__/kb-layout-config.test.ts +110 -0
  272. package/src/core/__tests__/catalog-cache-invalidation.test.ts +146 -0
  273. package/src/core/catalog-cache-invalidation.ts +92 -0
  274. package/src/core/create-core-server.ts +123 -7
  275. package/src/core/create-core-services.ts +162 -41
  276. package/src/modules/access/__tests__/access-control.invalidate-race.test.ts +86 -0
  277. package/src/modules/access/__tests__/access-control.service.test.ts +19 -3
  278. package/src/modules/access/__tests__/access-plugin-principals.test.ts +368 -0
  279. package/src/modules/access/__tests__/groups-admin.service.test.ts +8 -0
  280. package/src/modules/access/access-control.interface.ts +20 -9
  281. package/src/modules/access/access-control.service.ts +240 -78
  282. package/src/modules/access/access.routes.ts +96 -14
  283. package/src/modules/access-model/__tests__/access-grammar.test.ts +18 -0
  284. package/src/modules/access-model/__tests__/plugin-token-canonical.test.ts +40 -0
  285. package/src/modules/access-model/access-grammar.ts +114 -2
  286. package/src/modules/access-model/group-files.ts +4 -0
  287. package/src/modules/access-model/plugin-principals.ts +137 -0
  288. package/src/modules/database/core-schema.ts +54 -0
  289. package/src/modules/kb-sync/__tests__/kb-sync.routes.test.ts +297 -0
  290. package/src/modules/kb-sync/__tests__/kb-sync.service.test.ts +295 -0
  291. package/src/modules/kb-sync/__tests__/sync-auth.test.ts +118 -0
  292. package/src/modules/kb-sync/__tests__/sync-payload.test.ts +148 -0
  293. package/src/modules/kb-sync/index.ts +19 -0
  294. package/src/modules/kb-sync/kb-sync.interface.ts +79 -0
  295. package/src/modules/kb-sync/kb-sync.routes.ts +197 -0
  296. package/src/modules/kb-sync/kb-sync.service.ts +201 -0
  297. package/src/modules/kb-sync/sync-auth.ts +118 -0
  298. package/src/modules/kb-sync/sync-payload.ts +143 -0
  299. package/src/modules/marketplace/__tests__/github-facade.test.ts +443 -0
  300. package/src/modules/marketplace/__tests__/marketplace-git.test.ts +179 -0
  301. package/src/modules/marketplace/git-http.routes.ts +193 -0
  302. package/src/modules/marketplace/github-facade/github-facade-admin.routes.ts +78 -0
  303. package/src/modules/marketplace/github-facade/github-facade-codes.store.ts +145 -0
  304. package/src/modules/marketplace/github-facade/github-facade-credentials.service.ts +208 -0
  305. package/src/modules/marketplace/github-facade/github-facade.routes.ts +268 -0
  306. package/src/modules/marketplace/github-facade/github-facade.service.ts +221 -0
  307. package/src/modules/marketplace/github-facade/index.ts +25 -0
  308. package/src/modules/marketplace/index.ts +3 -0
  309. package/src/modules/marketplace/marketplace-repo.service.ts +337 -0
  310. package/src/modules/mcp/oauth/bevel-oauth-provider.ts +3 -0
  311. package/src/modules/mcp/oauth/oauth-consent.routes.ts +24 -2
  312. package/src/modules/mcp/oauth/oauth-state.ts +15 -3
  313. package/src/modules/plugins/__tests__/bundle-dialect.e2e.test.ts +163 -0
  314. package/src/modules/plugins/__tests__/compile-marketplace.test.ts +294 -0
  315. package/src/modules/plugins/__tests__/plugin-index.service.test.ts +56 -12
  316. package/src/modules/plugins/__tests__/plugin-links.service.test.ts +287 -0
  317. package/src/modules/plugins/__tests__/plugin-provision.service.test.ts +205 -5
  318. package/src/modules/plugins/__tests__/plugin-rename.service.test.ts +394 -0
  319. package/src/modules/plugins/__tests__/plugins.routes.test.ts +80 -33
  320. package/src/modules/plugins/compile/compile-marketplace.ts +403 -0
  321. package/src/modules/plugins/compile/marketplace-compiler.service.ts +150 -0
  322. package/src/modules/plugins/discovery/__tests__/kb-plugin-source.test.ts +329 -0
  323. package/src/modules/plugins/discovery/bundle-dialect/bundle.source.ts +140 -0
  324. package/src/modules/plugins/discovery/bundle-dialect/registry.ts +175 -0
  325. package/src/modules/plugins/discovery/kb-plugin-source.ts +114 -0
  326. package/src/modules/plugins/discovery/native.source.ts +122 -0
  327. package/src/modules/plugins/discovery/plugin-source.ts +99 -0
  328. package/src/modules/plugins/index.ts +10 -0
  329. package/src/modules/plugins/plugin-links.service.ts +363 -0
  330. package/src/modules/plugins/plugin-links.ts +184 -0
  331. package/src/modules/plugins/plugin-provision.service.ts +160 -54
  332. package/src/modules/plugins/plugin-rename.service.ts +298 -0
  333. package/src/modules/plugins/plugins.contract.ts +28 -1
  334. package/src/modules/plugins/plugins.routes.ts +128 -11
  335. package/src/modules/plugins/plugins.service.ts +106 -53
  336. package/src/modules/settings/__tests__/deployment-settings.service.test.ts +57 -0
  337. package/src/modules/settings/__tests__/setup.routes.sync-status.test.ts +77 -0
  338. package/src/modules/settings/deployment-settings.service.ts +95 -2
  339. package/src/modules/settings/setup.routes.ts +24 -0
  340. package/src/modules/skills/__tests__/skill-access-requests.routes.test.ts +128 -0
  341. package/src/modules/skills/__tests__/skills.service.test.ts +85 -0
  342. package/src/modules/skills/index.ts +1 -0
  343. package/src/modules/skills/pending-skills.service.ts +7 -5
  344. package/src/modules/skills/skill-access-requests.routes.ts +199 -0
  345. package/src/modules/skills/skills.contract.ts +32 -0
  346. package/src/modules/skills/skills.routes.ts +59 -3
  347. package/src/modules/skills/skills.service.ts +84 -22
  348. package/src/modules/tool-auth/external-api-key.interface.ts +20 -1
  349. package/src/modules/tool-auth/external-api-key.service.ts +31 -13
  350. package/src/modules/tool-manuals/__tests__/mcp-json-discovery.test.ts +24 -1
  351. package/src/modules/tool-manuals/__tests__/tool-manuals.cli.test.ts +2 -0
  352. package/src/modules/tool-manuals/mcp-json-discovery.ts +154 -88
  353. package/src/modules/tool-manuals/tool-manuals.service.ts +14 -23
  354. package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +1 -1
  355. package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +1 -0
  356. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +2 -2
  357. package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +119 -2
  358. package/src/modules/workflow/__tests__/workflow.service.sync.test.ts +437 -0
  359. package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +3 -3
  360. package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +47 -4
  361. package/src/modules/workflow/git/__tests__/git.service.syncFromRemote.test.ts +253 -0
  362. package/src/modules/workflow/git/git.service.ts +239 -56
  363. package/src/modules/workflow/git/pull-request.service.ts +9 -0
  364. package/src/modules/workflow/workflow.service.ts +260 -9
  365. package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +6 -7
  366. package/src/modules/workspace/__tests__/workspace.service.list-cloned.test.ts +93 -0
  367. package/src/modules/workspace/__tests__/workspace.service.missing-branch.test.ts +28 -0
  368. package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +42 -12
  369. package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +219 -4
  370. package/src/modules/workspace/startup/steps/plugin-manifests.step.ts +129 -0
  371. package/src/modules/workspace/startup/steps/seed-tree.ts +44 -2
  372. package/src/modules/workspace/startup/steps/template-files.step.ts +131 -27
  373. package/src/modules/workspace/workspace.routes.ts +9 -17
  374. package/src/modules/workspace/workspace.service.ts +107 -16
  375. package/src/shared/__tests__/filename.test.ts +0 -0
  376. package/src/shared/__tests__/fs-walk.test.ts +22 -1
  377. package/src/shared/__tests__/kb-walk.test.ts +107 -0
  378. package/src/shared/__tests__/path-order.test.ts +24 -0
  379. package/src/shared/__tests__/ttl-cache.test.ts +55 -0
  380. package/src/shared/domain-errors.ts +29 -0
  381. package/src/shared/fs-errors.ts +10 -0
  382. package/src/shared/fs-walk.ts +38 -23
  383. package/src/shared/kb-walk.ts +95 -0
  384. package/src/shared/path-order.ts +33 -0
  385. package/src/shared/ttl-cache.ts +33 -1
@@ -0,0 +1,135 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { isPersonalPluginDir, normalizeSkillRoot, pluginManifestName } from '@bevel-software/platform-shared';
4
+ import { isAbsence } from '../../../../shared/fs-errors.js';
5
+ import { expandProfile, parseRegistry } from './registry.js';
6
+ /**
7
+ * THE DETACHABLE PART — a customer's plugin file format, read as-is:
8
+ *
9
+ * <pluginsRoot>/<scope…>/<plugin>/plugin.bundle.json
10
+ * {
11
+ * "name": "example-plugin", "version": "1.3.1", "description": "…",
12
+ * "mcpProfile": "global",
13
+ * "interface": { "displayName": "Example Plugin", "category": "…" },
14
+ * "sourceSkillRoots": [ "skills/departments/engineering/shared/<cluster>" ]
15
+ * }
16
+ *
17
+ * A bundle is a LIST OF SKILL PATHS plus a pointer into an MCP registry —
18
+ * which is exactly the native model's "a plugin links skills" with different
19
+ * field names. So the reader maps:
20
+ *
21
+ * sourceSkillRoots → linkedRoots (a root is a skill or a folder of skills)
22
+ * mcpProfile → mcpServers (expanded through the registry)
23
+ * name/version/desc → a synthesised manifest
24
+ * interface.displayName → the plugin's display name
25
+ *
26
+ * The walker (`kb-plugin-source.ts`) calls this for every folder holding a
27
+ * bundle file; this reads the file and decides nothing else. READ-ONLY by
28
+ * construction: nothing in this directory writes. A bundle's links are plain
29
+ * references (`linksAreManaged: false`): no principal grant is written or
30
+ * checked, the skills' own scopes decide readability.
31
+ *
32
+ * Deleting the dialect later = this directory, the one `else if` in the
33
+ * walker that calls it, and the walker's registry load.
34
+ */
35
+ export const BUNDLE_FILE = 'plugin.bundle.json';
36
+ export const DEFAULT_REGISTRY_PATH = 'configs/mcp/registry.json';
37
+ /** The registry, when the repository has one; a missing file is null, a broken one warns. */
38
+ export async function loadRegistry(kbRoot, warnings) {
39
+ let text;
40
+ try {
41
+ text = await fs.readFile(path.join(kbRoot, DEFAULT_REGISTRY_PATH), 'utf-8');
42
+ }
43
+ catch (err) {
44
+ // No registry is a valid state: bundles without a profile are still
45
+ // plugins. A registry that exists but cannot be read is not.
46
+ if (!isAbsence(err)) {
47
+ const code = err?.code;
48
+ warnings.push(`${DEFAULT_REGISTRY_PATH} could not be read (${String(code ?? err)}) — every mcpProfile is unresolved`);
49
+ }
50
+ return null;
51
+ }
52
+ const registry = parseRegistry(text);
53
+ warnings.push(...registry.warnings);
54
+ return registry;
55
+ }
56
+ export async function readBundlePlugin(dir, folder, relFolder, registry, warnings, unreadable) {
57
+ // Reading and parsing are two failures with two meanings: a file that
58
+ // cannot be read is a plugin nobody could see (counted, so a writer can
59
+ // refuse); a file that is not a bundle is a plugin that is not there.
60
+ let text;
61
+ try {
62
+ text = await fs.readFile(path.join(dir, BUNDLE_FILE), 'utf-8');
63
+ }
64
+ catch (err) {
65
+ if (!isAbsence(err)) {
66
+ warnings.push(`${folder}/${BUNDLE_FILE} could not be read — ${err instanceof Error ? err.message : String(err)}`);
67
+ unreadable.push(`${folder}/${BUNDLE_FILE}`);
68
+ }
69
+ return null;
70
+ }
71
+ let bundle;
72
+ try {
73
+ const parsed = JSON.parse(text);
74
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
75
+ throw new Error('not an object');
76
+ bundle = parsed;
77
+ }
78
+ catch {
79
+ warnings.push(`${folder}/${BUNDLE_FILE} is not a JSON object — plugin skipped`);
80
+ return null;
81
+ }
82
+ const leaf = path.posix.basename(relFolder);
83
+ const name = typeof bundle.name === 'string' && bundle.name.trim() ? bundle.name.trim() : leaf;
84
+ const linkedRoots = [];
85
+ for (const raw of Array.isArray(bundle.sourceSkillRoots) ? bundle.sourceSkillRoots : []) {
86
+ const normalised = normalizeSkillRoot(typeof raw === 'string' ? raw : '');
87
+ if (normalised === null) {
88
+ warnings.push(`${folder}: sourceSkillRoots entry ${JSON.stringify(raw)} is not a folder path — ignored`);
89
+ }
90
+ else if (!linkedRoots.includes(normalised)) {
91
+ linkedRoots.push(normalised);
92
+ }
93
+ }
94
+ let mcpServers = null;
95
+ if (typeof bundle.mcpProfile === 'string' && bundle.mcpProfile.trim()) {
96
+ if (!registry) {
97
+ warnings.push(`${folder}: mcpProfile "${bundle.mcpProfile}" named but no registry could be read`);
98
+ }
99
+ else {
100
+ const expanded = expandProfile(registry, bundle.mcpProfile.trim());
101
+ warnings.push(...expanded.warnings.map((w) => `${folder}: ${w}`));
102
+ if (Object.keys(expanded.mcpServers).length > 0)
103
+ mcpServers = expanded.mcpServers;
104
+ }
105
+ }
106
+ const ui = typeof bundle.interface === 'object' && bundle.interface !== null
107
+ ? bundle.interface
108
+ : {};
109
+ const manifest = { name: pluginManifestName(name) };
110
+ if (typeof bundle.version === 'string')
111
+ manifest.version = bundle.version;
112
+ if (typeof bundle.description === 'string')
113
+ manifest.description = bundle.description;
114
+ if (typeof ui.displayName === 'string')
115
+ manifest.displayName = ui.displayName;
116
+ return {
117
+ name,
118
+ // The shared contract (`DiscoveredPlugin.displayName`): the declared
119
+ // display name, else the FOLDER — never the identity.
120
+ displayName: typeof ui.displayName === 'string' && ui.displayName.trim() ? ui.displayName.trim() : leaf,
121
+ folder,
122
+ relFolder,
123
+ // The same rule as the native reader: a reserved personal folder directly
124
+ // under the root is a place, not a plugin, whatever file it carries.
125
+ personal: isPersonalPluginDir(folder),
126
+ exists: true,
127
+ manifest,
128
+ manifestText: null,
129
+ linkedRoots,
130
+ mcpServers,
131
+ mcpJsonText: mcpServers ? JSON.stringify({ mcpServers }) : null,
132
+ linksAreManaged: false,
133
+ };
134
+ }
135
+ //# sourceMappingURL=bundle.source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.source.js","sourceRoot":"","sources":["../../../../../src/modules/plugins/discovery/bundle-dialect/bundle.source.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * The customer's MCP registry — `configs/mcp/registry.json` — and how a
3
+ * bundle's `mcpProfile` expands through it into an `mcpServers` map of the
4
+ * shape `mcp.json` carries.
5
+ *
6
+ * The file holds two lists:
7
+ *
8
+ * servers each with an `id`, a `name`, and the real config — either a
9
+ * stdio launch (`command`, `args`, `env`) or `type: http` + `url`;
10
+ * the config may sit under a `config` key or flat on the entry.
11
+ * profiles each with an `id`, the server ids it selects, and an optional
12
+ * `extends` naming another profile (a chain, never a cycle).
13
+ *
14
+ * Pure: parse once, expand many. Unknown ids and cycles are warnings, never
15
+ * throws — a registry typo must not take every plugin down.
16
+ */
17
+ import { type PortableHttpEntry, type PortableStdioEntry } from '../../../tool-manuals/mcp-json-discovery.js';
18
+ export interface RegistryServer {
19
+ id: string;
20
+ name?: string;
21
+ /** The server as one `mcp.json` entry — judged, and therefore usable, at parse time. */
22
+ entry: PortableStdioEntry | PortableHttpEntry;
23
+ }
24
+ export interface RegistryProfile {
25
+ id: string;
26
+ servers: string[];
27
+ extends?: string;
28
+ }
29
+ export interface McpRegistry {
30
+ servers: Map<string, RegistryServer>;
31
+ profiles: Map<string, RegistryProfile>;
32
+ warnings: string[];
33
+ }
34
+ export declare function parseRegistry(text: string): McpRegistry;
35
+ /**
36
+ * The `mcpServers` map a profile resolves to, in `mcp.json` terms. Keyed by
37
+ * server id — the namespace vault secrets bind to, so the same registry
38
+ * server in three plugins shares one credential, which is what a registry
39
+ * means.
40
+ */
41
+ export declare function expandProfile(registry: McpRegistry, profileId: string): {
42
+ mcpServers: Record<string, unknown>;
43
+ warnings: string[];
44
+ };
45
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../../../src/modules/plugins/discovery/bundle-dialect/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,6CAA6C,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,KAAK,EAAE,kBAAkB,GAAG,iBAAiB,CAAC;CAC/C;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACrC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACvC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAgDvD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,MAAM,GAChB;IAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA+B7D"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * The customer's MCP registry — `configs/mcp/registry.json` — and how a
3
+ * bundle's `mcpProfile` expands through it into an `mcpServers` map of the
4
+ * shape `mcp.json` carries.
5
+ *
6
+ * The file holds two lists:
7
+ *
8
+ * servers each with an `id`, a `name`, and the real config — either a
9
+ * stdio launch (`command`, `args`, `env`) or `type: http` + `url`;
10
+ * the config may sit under a `config` key or flat on the entry.
11
+ * profiles each with an `id`, the server ids it selects, and an optional
12
+ * `extends` naming another profile (a chain, never a cycle).
13
+ *
14
+ * Pure: parse once, expand many. Unknown ids and cycles are warnings, never
15
+ * throws — a registry typo must not take every plugin down.
16
+ */
17
+ import { judgeMcpServerEntry, } from '../../../tool-manuals/mcp-json-discovery.js';
18
+ export function parseRegistry(text) {
19
+ const warnings = [];
20
+ const servers = new Map();
21
+ const profiles = new Map();
22
+ let root;
23
+ try {
24
+ root = JSON.parse(text);
25
+ }
26
+ catch {
27
+ return { servers, profiles, warnings: ['registry.json is not valid JSON'] };
28
+ }
29
+ if (!isRecord(root))
30
+ return { servers, profiles, warnings: ['registry.json must be a JSON object'] };
31
+ for (const raw of asArray(root.servers)) {
32
+ if (!isRecord(raw) || typeof raw.id !== 'string' || !raw.id) {
33
+ warnings.push('registry.json: a server without an id was skipped');
34
+ continue;
35
+ }
36
+ if (servers.has(raw.id)) {
37
+ warnings.push(`registry.json: server "${raw.id}" is declared twice — the second declaration is ignored`);
38
+ continue;
39
+ }
40
+ // Converting IS the validation: a server the registry keeps is one whose
41
+ // entry a client can run — judged by the ONE rule every mcp.json entry
42
+ // meets (name, transport, required fields), after the customer's shape
43
+ // is translated into that of mcp.json.
44
+ const converted = mcpEntryOf(raw.id, isRecord(raw.config) ? raw.config : raw);
45
+ if ('reason' in converted) {
46
+ warnings.push(`registry.json: server "${raw.id}" ${converted.reason} — skipped`);
47
+ continue;
48
+ }
49
+ servers.set(raw.id, { id: raw.id, name: typeof raw.name === 'string' ? raw.name : undefined, entry: converted.entry });
50
+ }
51
+ for (const raw of asArray(root.profiles)) {
52
+ if (!isRecord(raw) || typeof raw.id !== 'string' || !raw.id) {
53
+ warnings.push('registry.json: a profile without an id was skipped');
54
+ continue;
55
+ }
56
+ if (profiles.has(raw.id)) {
57
+ warnings.push(`registry.json: profile "${raw.id}" is declared twice — the second declaration is ignored`);
58
+ continue;
59
+ }
60
+ profiles.set(raw.id, {
61
+ id: raw.id,
62
+ servers: asArray(raw.servers).filter((s) => typeof s === 'string'),
63
+ extends: typeof raw.extends === 'string' ? raw.extends : undefined,
64
+ });
65
+ }
66
+ return { servers, profiles, warnings };
67
+ }
68
+ /**
69
+ * The `mcpServers` map a profile resolves to, in `mcp.json` terms. Keyed by
70
+ * server id — the namespace vault secrets bind to, so the same registry
71
+ * server in three plugins shares one credential, which is what a registry
72
+ * means.
73
+ */
74
+ export function expandProfile(registry, profileId) {
75
+ const warnings = [];
76
+ const ids = [];
77
+ const seen = new Set();
78
+ let current = profileId;
79
+ while (current !== undefined) {
80
+ if (seen.has(current)) {
81
+ warnings.push(`registry.json: profile "${current}" extends itself through a cycle — chain cut`);
82
+ break;
83
+ }
84
+ seen.add(current);
85
+ const profile = registry.profiles.get(current);
86
+ if (!profile) {
87
+ warnings.push(`registry.json: profile "${current}" does not exist`);
88
+ break;
89
+ }
90
+ // Nearest profile first, so a base profile's servers come after the
91
+ // extending one's; the map below keeps the first occurrence of an id.
92
+ for (const id of profile.servers)
93
+ if (!ids.includes(id))
94
+ ids.push(id);
95
+ current = profile.extends;
96
+ }
97
+ const mcpServers = {};
98
+ for (const id of ids) {
99
+ const server = registry.servers.get(id);
100
+ if (!server) {
101
+ warnings.push(`registry.json: profile "${profileId}" selects unknown server "${id}"`);
102
+ continue;
103
+ }
104
+ mcpServers[id] = server.entry;
105
+ }
106
+ return { mcpServers, warnings };
107
+ }
108
+ /**
109
+ * A registry config → one `mcp.json` server entry, or why there is none.
110
+ *
111
+ * The registry's OWN knowledge is the customer's shape: a declared `type`
112
+ * names the transport (`http` is their spelling of `streamable-http`), an
113
+ * undeclared one is read off the fields — a `url` means http, else a
114
+ * `command` means stdio — and blank strings are absent. That translation
115
+ * done, whether the entry can work is the shared judgement's call, the same
116
+ * one every `mcp.json` entry meets: a name that can be a server name, a
117
+ * transport the client speaks (no `sse`), the field that transport needs.
118
+ */
119
+ function mcpEntryOf(id, config) {
120
+ const declared = typeof config.type === 'string' ? config.type.trim().toLowerCase() : undefined;
121
+ const url = nonBlank(config.url);
122
+ const command = nonBlank(config.command);
123
+ const type = declared === undefined ? (url ? 'streamable-http' : command ? 'stdio' : undefined) : declared === 'http' ? 'streamable-http' : declared;
124
+ if (type === undefined)
125
+ return { reason: 'has neither a url nor a command' };
126
+ const candidate = { type };
127
+ if (url)
128
+ candidate.url = url;
129
+ if (command)
130
+ candidate.command = command;
131
+ for (const key of ['args', 'env', 'cwd', 'headers']) {
132
+ if (config[key] !== undefined)
133
+ candidate[key] = config[key];
134
+ }
135
+ const verdict = judgeMcpServerEntry(id, candidate);
136
+ return verdict.ok ? { entry: verdict.entry } : { reason: verdict.reason };
137
+ }
138
+ function nonBlank(v) {
139
+ return typeof v === 'string' && v.trim() ? v : undefined;
140
+ }
141
+ function isRecord(v) {
142
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
143
+ }
144
+ function asArray(v) {
145
+ return Array.isArray(v) ? v : [];
146
+ }
147
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../../../src/modules/plugins/discovery/bundle-dialect/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { Discovery, PluginSource, PluginSourceWalk } from './plugin-source.js';
2
+ import { type KbWalkListener } from '../../../shared/kb-walk.js';
3
+ /**
4
+ * THE plugin source: a LISTENER on the one walk of the checkout
5
+ * (`walkKb`), reading every folder under the plugins root in whichever of
6
+ * the two file shapes it carries.
7
+ *
8
+ * plugin.json → a native plugin (this platform's layout)
9
+ * plugin.bundle.json → a bundle (the customer dialect, read-only)
10
+ *
11
+ * Nothing else is a plugin. A folder's POSITION means nothing: the legacy
12
+ * rule "everything directly under the root is a plugin" is retired by the
13
+ * `plugin-manifests` boot step, which writes the manifest into every such
14
+ * folder once, so discovery never has to guess.
15
+ *
16
+ * A folder that IS a plugin claims everything beneath it (its `skills/` are
17
+ * its own) — the walk still visits what lies beneath, for the other
18
+ * listeners; this one ignores it. When a folder carries both files the
19
+ * manifest wins, so a bundle migrated in place stops being read as a bundle
20
+ * the moment a `plugin.json` lands beside it. Two plugins with one name keep
21
+ * the first by path (the walk's order) and warn about the second — a name is
22
+ * an identity to people and URLs, and two folders answering to it would be
23
+ * two plugins with one key.
24
+ *
25
+ * Holes — a folder under the root that could not be listed, an identity
26
+ * file that could not be read — are counted in `unreadable`: nothing behind
27
+ * them is listed, and a writer refuses while they exist.
28
+ *
29
+ * No setting picks a dialect. Nothing to configure means nothing to document
30
+ * and nothing to remove but the `else if` that reads bundles.
31
+ */
32
+ export declare class KbPluginSource implements PluginSource {
33
+ readonly dialect = "kb";
34
+ discover(kbRoot: string): Promise<Discovery>;
35
+ walkWith(kbRoot: string, listeners: readonly KbWalkListener[]): Promise<PluginSourceWalk>;
36
+ }
37
+ //# sourceMappingURL=kb-plugin-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kb-plugin-source.d.ts","sourceRoot":"","sources":["../../../../src/modules/plugins/discovery/kb-plugin-source.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAoB,SAAS,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtG,OAAO,EAAU,KAAK,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAKzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,cAAe,YAAW,YAAY;IACjD,QAAQ,CAAC,OAAO,QAAQ;IAElB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAI5C,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,cAAc,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAOhG"}
@@ -0,0 +1,107 @@
1
+ import path from 'node:path';
2
+ import { PLUGINS_DIR, PLUGIN_MANIFEST_FILE, pluginManifestName } from '@bevel-software/platform-shared';
3
+ import { walkKb } from '../../../shared/kb-walk.js';
4
+ import { readNativePlugin } from './native.source.js';
5
+ import { BUNDLE_FILE, loadRegistry, readBundlePlugin } from './bundle-dialect/bundle.source.js';
6
+ /**
7
+ * THE plugin source: a LISTENER on the one walk of the checkout
8
+ * (`walkKb`), reading every folder under the plugins root in whichever of
9
+ * the two file shapes it carries.
10
+ *
11
+ * plugin.json → a native plugin (this platform's layout)
12
+ * plugin.bundle.json → a bundle (the customer dialect, read-only)
13
+ *
14
+ * Nothing else is a plugin. A folder's POSITION means nothing: the legacy
15
+ * rule "everything directly under the root is a plugin" is retired by the
16
+ * `plugin-manifests` boot step, which writes the manifest into every such
17
+ * folder once, so discovery never has to guess.
18
+ *
19
+ * A folder that IS a plugin claims everything beneath it (its `skills/` are
20
+ * its own) — the walk still visits what lies beneath, for the other
21
+ * listeners; this one ignores it. When a folder carries both files the
22
+ * manifest wins, so a bundle migrated in place stops being read as a bundle
23
+ * the moment a `plugin.json` lands beside it. Two plugins with one name keep
24
+ * the first by path (the walk's order) and warn about the second — a name is
25
+ * an identity to people and URLs, and two folders answering to it would be
26
+ * two plugins with one key.
27
+ *
28
+ * Holes — a folder under the root that could not be listed, an identity
29
+ * file that could not be read — are counted in `unreadable`: nothing behind
30
+ * them is listed, and a writer refuses while they exist.
31
+ *
32
+ * No setting picks a dialect. Nothing to configure means nothing to document
33
+ * and nothing to remove but the `else if` that reads bundles.
34
+ */
35
+ export class KbPluginSource {
36
+ dialect = 'kb';
37
+ async discover(kbRoot) {
38
+ return (await this.walkWith(kbRoot, [])).discovery;
39
+ }
40
+ async walkWith(kbRoot, listeners) {
41
+ const warnings = [];
42
+ const registry = await loadRegistry(kbRoot, warnings);
43
+ const listener = pluginListener(kbRoot, registry, warnings);
44
+ const { holes } = await walkKb(kbRoot, [listener.listener, ...listeners]);
45
+ return { discovery: listener.result(), holes };
46
+ }
47
+ }
48
+ /** The discovery listener over one walk, and the `Discovery` it has built once the walk is done. */
49
+ function pluginListener(kbRoot, registry, warnings) {
50
+ const unreadable = [];
51
+ const plugins = [];
52
+ const seen = new Map();
53
+ /** Folders claimed as plugins (or as holes standing where a plugin may be): nothing beneath is looked at. */
54
+ const claimed = [];
55
+ const underRoot = (rel) => rel === PLUGINS_DIR || rel.startsWith(`${PLUGINS_DIR}/`);
56
+ const beneathClaimed = (rel) => claimed.some((c) => rel === c || rel.startsWith(`${c}/`));
57
+ // Uniqueness is judged on the MANIFEST SLUG, not the raw name: `Sales Team`
58
+ // and `sales-team` fold to one slug, and the slug is what the compiled
59
+ // marketplace keys a plugin on — two folders sharing it would be two
60
+ // plugins with one key and one of them silently overwritten.
61
+ const claim = (plugin) => {
62
+ const key = pluginManifestName(plugin.name);
63
+ const twin = seen.get(key);
64
+ if (twin) {
65
+ warnings.push(`${plugin.folder}: plugin name "${plugin.name}" is already used by ${twin} — plugin skipped`);
66
+ return;
67
+ }
68
+ seen.set(key, plugin.folder);
69
+ plugins.push(plugin);
70
+ };
71
+ return {
72
+ listener: {
73
+ async onDir(rel, entries) {
74
+ if (!underRoot(rel) || rel === PLUGINS_DIR || beneathClaimed(rel))
75
+ return;
76
+ const has = (name) => entries.some((e) => e.isFile() && e.name === name);
77
+ const dir = path.join(kbRoot, rel);
78
+ const relFolder = rel.slice(PLUGINS_DIR.length + 1);
79
+ if (has(PLUGIN_MANIFEST_FILE)) {
80
+ claimed.push(rel);
81
+ // A manifest that could not be read: a hole, and still claimed.
82
+ const native = await readNativePlugin(dir, rel, relFolder, warnings, unreadable);
83
+ if (native)
84
+ claim(native);
85
+ }
86
+ else if (has(BUNDLE_FILE)) {
87
+ claimed.push(rel);
88
+ const bundle = await readBundlePlugin(dir, rel, relFolder, registry, warnings, unreadable);
89
+ if (bundle)
90
+ claim(bundle);
91
+ }
92
+ },
93
+ onHole(rel, err) {
94
+ // A folder under the root that could not be listed hides every plugin
95
+ // beneath it; said out loud rather than letting the catalog shrink in
96
+ // silence, and COUNTED so a writer can tell an incomplete listing from
97
+ // a complete one. (Holes elsewhere in the tree are the walk's to report.)
98
+ if (!underRoot(rel) || beneathClaimed(rel))
99
+ return;
100
+ warnings.push(`${rel}: could not be read — ${err instanceof Error ? err.message : String(err)}`);
101
+ unreadable.push(rel);
102
+ },
103
+ },
104
+ result: () => ({ plugins, warnings, unreadable }),
105
+ };
106
+ }
107
+ //# sourceMappingURL=kb-plugin-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kb-plugin-source.js","sourceRoot":"","sources":["../../../../src/modules/plugins/discovery/kb-plugin-source.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { DiscoveredPlugin } from './plugin-source.js';
2
+ /**
3
+ * A plugin in the layout this platform writes (see `kb-layout.ts`): a folder
4
+ * carrying `plugin.json`, optionally `mcp.json`, and the `access.md` that
5
+ * makes it exist to the index. Called by the walker for every folder it
6
+ * decides is a native plugin; reads the files, decides nothing else.
7
+ *
8
+ * Null when the manifest exists but could not be READ: the manifest is the
9
+ * identity, and a plugin whose identity nobody could see is not listed under
10
+ * a guessed one — it is a hole (`unreadable`), like a folder that could not
11
+ * be listed. The optional `mcp.json` carries no identity, so its read
12
+ * failure is a warning and nothing more.
13
+ */
14
+ export declare function readNativePlugin(dir: string, folder: string, relFolder: string, warnings: string[], unreadable: string[]): Promise<DiscoveredPlugin | null>;
15
+ //# sourceMappingURL=native.source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.source.d.ts","sourceRoot":"","sources":["../../../../src/modules/plugins/discovery/native.source.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAAE,EAClB,UAAU,EAAE,MAAM,EAAE,GACnB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CA0DlC"}
@@ -0,0 +1,102 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { PLUGIN_MANIFEST_FILE, PLUGIN_MCP_FILE, isPersonalPluginDir, isPluginIdentifier, linkedSkillRoots, pluginDisplayNameOf, pluginIdentityOf, } from '@bevel-software/platform-shared';
4
+ import { isAbsence } from '../../../shared/fs-errors.js';
5
+ /**
6
+ * A plugin in the layout this platform writes (see `kb-layout.ts`): a folder
7
+ * carrying `plugin.json`, optionally `mcp.json`, and the `access.md` that
8
+ * makes it exist to the index. Called by the walker for every folder it
9
+ * decides is a native plugin; reads the files, decides nothing else.
10
+ *
11
+ * Null when the manifest exists but could not be READ: the manifest is the
12
+ * identity, and a plugin whose identity nobody could see is not listed under
13
+ * a guessed one — it is a hole (`unreadable`), like a folder that could not
14
+ * be listed. The optional `mcp.json` carries no identity, so its read
15
+ * failure is a warning and nothing more.
16
+ */
17
+ export async function readNativePlugin(dir, folder, relFolder, warnings, unreadable) {
18
+ const folderName = path.posix.basename(relFolder);
19
+ const manifestRead = await readText(path.join(dir, PLUGIN_MANIFEST_FILE), folder, warnings);
20
+ if (manifestRead.failed) {
21
+ unreadable.push(`${folder}/${PLUGIN_MANIFEST_FILE}`);
22
+ return null;
23
+ }
24
+ // The walker probed the manifest a moment ago; gone now means it vanished
25
+ // between probe and read — then this is no plugin, not one under a guessed name.
26
+ if (manifestRead.text === null)
27
+ return null;
28
+ const manifestText = manifestRead.text;
29
+ const mcpJsonText = (await readText(path.join(dir, PLUGIN_MCP_FILE), folder, warnings)).text;
30
+ const manifest = parseObject(manifestText);
31
+ if (manifest === null) {
32
+ warnings.push(`${folder}/${PLUGIN_MANIFEST_FILE} is not a JSON object — treated as absent`);
33
+ }
34
+ // The manifest's `name` IS the identity — the grants, the URLs, the
35
+ // marketplace all spell it — when it is an identifier. One that is not
36
+ // (spaces, capitals) is never silently reinterpreted: the folder stands
37
+ // in, and the mismatch is said out loud so a grant written against the
38
+ // manifest's spelling is not a mystery.
39
+ const name = pluginIdentityOf(manifest, folderName);
40
+ const displayName = pluginDisplayNameOf(manifest, folderName);
41
+ // Any PRESENT name that is not an identifier is worth a word — a number or
42
+ // an object as much as a capitalised string. Only an absent name is silent.
43
+ if (manifest && manifest.name !== undefined && !isPluginIdentifier(manifest.name)) {
44
+ // A diagnostic must never be the thing that fails: a non-string name is
45
+ // described by its type, not serialised (a value nested deep enough
46
+ // would blow the stack on the way to a warning).
47
+ const spelled = typeof manifest.name === 'string'
48
+ ? `"${manifest.name}"`
49
+ : `a value of type ${Array.isArray(manifest.name) ? 'array' : typeof manifest.name}`;
50
+ warnings.push(`${folder}/${PLUGIN_MANIFEST_FILE} names ${spelled}, which is not a plugin identifier (lowercase kebab-case) — the folder stands in as "${name}"`);
51
+ }
52
+ const mcp = parseObject(mcpJsonText);
53
+ const mcpServers = mcp && typeof mcp.mcpServers === 'object' && mcp.mcpServers !== null && !Array.isArray(mcp.mcpServers)
54
+ ? mcp.mcpServers
55
+ : null;
56
+ const exists = await fs.stat(path.join(dir, 'access.md')).then((s) => s.isFile(), () => false);
57
+ return {
58
+ name,
59
+ displayName,
60
+ folder,
61
+ relFolder,
62
+ // The one structural rule: a direct child of the root with the prefix.
63
+ personal: isPersonalPluginDir(folder),
64
+ exists,
65
+ manifest,
66
+ manifestText,
67
+ linkedRoots: linkedSkillRoots(manifest),
68
+ mcpServers,
69
+ mcpJsonText,
70
+ linksAreManaged: true,
71
+ };
72
+ }
73
+ /**
74
+ * A file's text — null when there is no such file — and whether a file that
75
+ * IS there could not be read. Absence and failure are different answers;
76
+ * the caller decides what a failure means for the file in question.
77
+ */
78
+ async function readText(abs, folder, warnings) {
79
+ try {
80
+ return { text: await fs.readFile(abs, 'utf-8'), failed: false };
81
+ }
82
+ catch (err) {
83
+ if (isAbsence(err))
84
+ return { text: null, failed: false };
85
+ warnings.push(`${folder}/${path.basename(abs)} could not be read — ${err instanceof Error ? err.message : String(err)}`);
86
+ return { text: null, failed: true };
87
+ }
88
+ }
89
+ function parseObject(text) {
90
+ if (text === null)
91
+ return null;
92
+ try {
93
+ const parsed = JSON.parse(text);
94
+ return typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)
95
+ ? parsed
96
+ : null;
97
+ }
98
+ catch {
99
+ return null;
100
+ }
101
+ }
102
+ //# sourceMappingURL=native.source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.source.js","sourceRoot":"","sources":["../../../../src/modules/plugins/discovery/native.source.ts"],"names":[],"mappings":"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"}