@bevel-software/platform-core-backend 0.14.0 → 0.19.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 (1307) hide show
  1. package/THIRD-PARTY-NOTICES.md +8 -8
  2. package/dist/core/catalog-cache-invalidation.d.ts +45 -0
  3. package/dist/core/catalog-cache-invalidation.d.ts.map +1 -0
  4. package/dist/core/catalog-cache-invalidation.js +76 -0
  5. package/dist/core/catalog-cache-invalidation.js.map +1 -0
  6. package/dist/core/catalog-revision.d.ts +39 -0
  7. package/dist/core/catalog-revision.d.ts.map +1 -0
  8. package/dist/core/catalog-revision.js +94 -0
  9. package/dist/core/catalog-revision.js.map +1 -0
  10. package/dist/core/create-core-server.d.ts +7 -0
  11. package/dist/core/create-core-server.d.ts.map +1 -1
  12. package/dist/core/create-core-server.js +279 -64
  13. package/dist/core/create-core-server.js.map +1 -1
  14. package/dist/core/create-core-services.d.ts +66 -2
  15. package/dist/core/create-core-services.d.ts.map +1 -1
  16. package/dist/core/create-core-services.js +290 -111
  17. package/dist/core/create-core-services.js.map +1 -1
  18. package/dist/core/lifecycle.d.ts +138 -0
  19. package/dist/core/lifecycle.d.ts.map +1 -0
  20. package/dist/core/lifecycle.js +218 -0
  21. package/dist/core/lifecycle.js.map +1 -0
  22. package/dist/core/public-config.d.ts +82 -0
  23. package/dist/core/public-config.d.ts.map +1 -0
  24. package/dist/core/public-config.js +78 -0
  25. package/dist/core/public-config.js.map +1 -0
  26. package/dist/core/readiness.d.ts +86 -0
  27. package/dist/core/readiness.d.ts.map +1 -0
  28. package/dist/core/readiness.js +56 -0
  29. package/dist/core/readiness.js.map +1 -0
  30. package/dist/core-config.d.ts +30 -0
  31. package/dist/core-config.d.ts.map +1 -1
  32. package/dist/core-config.js +64 -2
  33. package/dist/core-config.js.map +1 -1
  34. package/dist/index.d.ts +4 -1
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +6 -0
  37. package/dist/index.js.map +1 -1
  38. package/dist/modules/access/access-control.interface.d.ts +231 -15
  39. package/dist/modules/access/access-control.interface.d.ts.map +1 -1
  40. package/dist/modules/access/access-control.service.d.ts +83 -12
  41. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  42. package/dist/modules/access/access-control.service.js +815 -212
  43. package/dist/modules/access/access-control.service.js.map +1 -1
  44. package/dist/modules/access/access-mutation.service.d.ts +71 -5
  45. package/dist/modules/access/access-mutation.service.d.ts.map +1 -1
  46. package/dist/modules/access/access-mutation.service.js +161 -13
  47. package/dist/modules/access/access-mutation.service.js.map +1 -1
  48. package/dist/modules/access/access-view.d.ts +147 -0
  49. package/dist/modules/access/access-view.d.ts.map +1 -0
  50. package/dist/modules/access/access-view.js +211 -0
  51. package/dist/modules/access/access-view.js.map +1 -0
  52. package/dist/modules/access/access.routes.d.ts.map +1 -1
  53. package/dist/modules/access/access.routes.js +312 -84
  54. package/dist/modules/access/access.routes.js.map +1 -1
  55. package/dist/modules/access/admin-locked-commit.d.ts +2 -3
  56. package/dist/modules/access/admin-locked-commit.d.ts.map +1 -1
  57. package/dist/modules/access/admin-locked-commit.js +9 -8
  58. package/dist/modules/access/admin-locked-commit.js.map +1 -1
  59. package/dist/modules/access/admin-route-helpers.d.ts.map +1 -1
  60. package/dist/modules/access/admin-route-helpers.js +4 -4
  61. package/dist/modules/access/admin-route-helpers.js.map +1 -1
  62. package/dist/modules/access/change-read-gate.d.ts +53 -0
  63. package/dist/modules/access/change-read-gate.d.ts.map +1 -0
  64. package/dist/modules/access/change-read-gate.js +134 -0
  65. package/dist/modules/access/change-read-gate.js.map +1 -0
  66. package/dist/modules/access/creator-access.d.ts +33 -39
  67. package/dist/modules/access/creator-access.d.ts.map +1 -1
  68. package/dist/modules/access/creator-access.js +92 -119
  69. package/dist/modules/access/creator-access.js.map +1 -1
  70. package/dist/modules/access/directory-sync-bot.d.ts.map +1 -1
  71. package/dist/modules/access/directory-sync-bot.js +3 -1
  72. package/dist/modules/access/directory-sync-bot.js.map +1 -1
  73. package/dist/modules/access/groups-admin.service.d.ts +3 -3
  74. package/dist/modules/access/groups-admin.service.js +2 -2
  75. package/dist/modules/access/reference-scan.d.ts +1 -1
  76. package/dist/modules/access/reference-scan.d.ts.map +1 -1
  77. package/dist/modules/access/reference-scan.js +5 -4
  78. package/dist/modules/access/reference-scan.js.map +1 -1
  79. package/dist/modules/access/roles-admin.service.d.ts +72 -13
  80. package/dist/modules/access/roles-admin.service.d.ts.map +1 -1
  81. package/dist/modules/access/roles-admin.service.js +71 -13
  82. package/dist/modules/access/roles-admin.service.js.map +1 -1
  83. package/dist/modules/access/synced-groups-committer.d.ts.map +1 -1
  84. package/dist/modules/access/synced-groups-committer.js +8 -6
  85. package/dist/modules/access/synced-groups-committer.js.map +1 -1
  86. package/dist/modules/access/synced-groups-writer.d.ts.map +1 -1
  87. package/dist/modules/access/synced-groups-writer.js +3 -8
  88. package/dist/modules/access/synced-groups-writer.js.map +1 -1
  89. package/dist/modules/access/user-access-removal.service.d.ts +209 -0
  90. package/dist/modules/access/user-access-removal.service.d.ts.map +1 -0
  91. package/dist/modules/access/user-access-removal.service.js +662 -0
  92. package/dist/modules/access/user-access-removal.service.js.map +1 -0
  93. package/dist/modules/access-model/access-errors.d.ts +32 -1
  94. package/dist/modules/access-model/access-errors.d.ts.map +1 -1
  95. package/dist/modules/access-model/access-errors.js +38 -11
  96. package/dist/modules/access-model/access-errors.js.map +1 -1
  97. package/dist/modules/access-model/access-grammar.d.ts +100 -25
  98. package/dist/modules/access-model/access-grammar.d.ts.map +1 -1
  99. package/dist/modules/access-model/access-grammar.js +162 -48
  100. package/dist/modules/access-model/access-grammar.js.map +1 -1
  101. package/dist/modules/access-model/access-splice.d.ts.map +1 -1
  102. package/dist/modules/access-model/access-splice.js +18 -18
  103. package/dist/modules/access-model/access-splice.js.map +1 -1
  104. package/dist/modules/access-model/access-template.d.ts +22 -0
  105. package/dist/modules/access-model/access-template.d.ts.map +1 -0
  106. package/dist/modules/access-model/access-template.js +42 -0
  107. package/dist/modules/access-model/access-template.js.map +1 -0
  108. package/dist/modules/access-model/change-gate.d.ts +65 -0
  109. package/dist/modules/access-model/change-gate.d.ts.map +1 -0
  110. package/dist/modules/access-model/change-gate.js +25 -0
  111. package/dist/modules/access-model/change-gate.js.map +1 -0
  112. package/dist/modules/access-model/creator.d.ts +13 -16
  113. package/dist/modules/access-model/creator.d.ts.map +1 -1
  114. package/dist/modules/access-model/creator.js.map +1 -1
  115. package/dist/modules/access-model/frontmatter-lines.d.ts +27 -0
  116. package/dist/modules/access-model/frontmatter-lines.d.ts.map +1 -0
  117. package/dist/modules/access-model/frontmatter-lines.js +74 -0
  118. package/dist/modules/access-model/frontmatter-lines.js.map +1 -0
  119. package/dist/modules/access-model/group-files.d.ts.map +1 -1
  120. package/dist/modules/access-model/group-files.js +4 -1
  121. package/dist/modules/access-model/group-files.js.map +1 -1
  122. package/dist/modules/access-model/plugin-principals.d.ts +51 -0
  123. package/dist/modules/access-model/plugin-principals.d.ts.map +1 -0
  124. package/dist/modules/access-model/plugin-principals.js +119 -0
  125. package/dist/modules/access-model/plugin-principals.js.map +1 -0
  126. package/dist/modules/access-model/roles-yaml-guard.d.ts +73 -2
  127. package/dist/modules/access-model/roles-yaml-guard.d.ts.map +1 -1
  128. package/dist/modules/access-model/roles-yaml-guard.js +153 -3
  129. package/dist/modules/access-model/roles-yaml-guard.js.map +1 -1
  130. package/dist/modules/admin/admin-access.service.d.ts.map +1 -1
  131. package/dist/modules/admin/admin-access.service.js +5 -2
  132. package/dist/modules/admin/admin-access.service.js.map +1 -1
  133. package/dist/modules/agent-instructions/agent-instructions.routes.d.ts +21 -0
  134. package/dist/modules/agent-instructions/agent-instructions.routes.d.ts.map +1 -0
  135. package/dist/modules/agent-instructions/agent-instructions.routes.js +38 -0
  136. package/dist/modules/agent-instructions/agent-instructions.routes.js.map +1 -0
  137. package/dist/modules/agent-instructions/compose.d.ts +71 -0
  138. package/dist/modules/agent-instructions/compose.d.ts.map +1 -0
  139. package/dist/modules/agent-instructions/compose.js +234 -0
  140. package/dist/modules/agent-instructions/compose.js.map +1 -0
  141. package/dist/modules/agent-instructions/index.d.ts +4 -0
  142. package/dist/modules/agent-instructions/index.d.ts.map +1 -0
  143. package/dist/modules/agent-instructions/index.js +4 -0
  144. package/dist/modules/agent-instructions/index.js.map +1 -0
  145. package/dist/modules/agent-instructions/read-preamble.d.ts +37 -0
  146. package/dist/modules/agent-instructions/read-preamble.d.ts.map +1 -0
  147. package/dist/modules/agent-instructions/read-preamble.js +81 -0
  148. package/dist/modules/agent-instructions/read-preamble.js.map +1 -0
  149. package/dist/modules/auth/account-erasure.service.d.ts +30 -4
  150. package/dist/modules/auth/account-erasure.service.d.ts.map +1 -1
  151. package/dist/modules/auth/account-erasure.service.js +96 -10
  152. package/dist/modules/auth/account-erasure.service.js.map +1 -1
  153. package/dist/modules/auth/account.routes.d.ts +6 -3
  154. package/dist/modules/auth/account.routes.d.ts.map +1 -1
  155. package/dist/modules/auth/account.routes.js +109 -10
  156. package/dist/modules/auth/account.routes.js.map +1 -1
  157. package/dist/modules/auth/auth.routes.d.ts +10 -3
  158. package/dist/modules/auth/auth.routes.d.ts.map +1 -1
  159. package/dist/modules/auth/auth.routes.js +9 -4
  160. package/dist/modules/auth/auth.routes.js.map +1 -1
  161. package/dist/modules/auth/auth.service.d.ts +89 -5
  162. package/dist/modules/auth/auth.service.d.ts.map +1 -1
  163. package/dist/modules/auth/auth.service.js +160 -25
  164. package/dist/modules/auth/auth.service.js.map +1 -1
  165. package/dist/modules/auth/oidc-auth-provider.d.ts +46 -3
  166. package/dist/modules/auth/oidc-auth-provider.d.ts.map +1 -1
  167. package/dist/modules/auth/oidc-auth-provider.js +99 -21
  168. package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
  169. package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -1
  170. package/dist/modules/code-mode/code-mode.tool.js +14 -2
  171. package/dist/modules/code-mode/code-mode.tool.js.map +1 -1
  172. package/dist/modules/connection-probe/connection-probe.service.d.ts.map +1 -1
  173. package/dist/modules/connection-probe/connection-probe.service.js +56 -7
  174. package/dist/modules/connection-probe/connection-probe.service.js.map +1 -1
  175. package/dist/modules/database/advisory-lock.d.ts +103 -0
  176. package/dist/modules/database/advisory-lock.d.ts.map +1 -0
  177. package/dist/modules/database/advisory-lock.js +320 -0
  178. package/dist/modules/database/advisory-lock.js.map +1 -0
  179. package/dist/modules/database/connection.d.ts.map +1 -1
  180. package/dist/modules/database/connection.js +9 -1
  181. package/dist/modules/database/connection.js.map +1 -1
  182. package/dist/modules/database/core-schema.d.ts +672 -0
  183. package/dist/modules/database/core-schema.d.ts.map +1 -1
  184. package/dist/modules/database/core-schema.js +171 -0
  185. package/dist/modules/database/core-schema.js.map +1 -1
  186. package/dist/modules/database/migrate.d.ts.map +1 -1
  187. package/dist/modules/database/migrate.js +26 -6
  188. package/dist/modules/database/migrate.js.map +1 -1
  189. package/dist/modules/declared-variables/declared-variables.routes.d.ts.map +1 -1
  190. package/dist/modules/declared-variables/declared-variables.routes.js +4 -2
  191. package/dist/modules/declared-variables/declared-variables.routes.js.map +1 -1
  192. package/dist/modules/diff/diff.routes.d.ts.map +1 -1
  193. package/dist/modules/diff/diff.routes.js +2 -4
  194. package/dist/modules/diff/diff.routes.js.map +1 -1
  195. package/dist/modules/diff/diff.service.d.ts +4 -1
  196. package/dist/modules/diff/diff.service.d.ts.map +1 -1
  197. package/dist/modules/diff/diff.service.js +79 -81
  198. package/dist/modules/diff/diff.service.js.map +1 -1
  199. package/dist/modules/kb-fs/bevel-ignore.d.ts +35 -0
  200. package/dist/modules/kb-fs/bevel-ignore.d.ts.map +1 -0
  201. package/dist/modules/kb-fs/bevel-ignore.js +71 -0
  202. package/dist/modules/kb-fs/bevel-ignore.js.map +1 -0
  203. package/dist/modules/kb-fs/file-change-notifier.d.ts.map +1 -1
  204. package/dist/modules/kb-fs/file-change-notifier.js +3 -1
  205. package/dist/modules/kb-fs/file-change-notifier.js.map +1 -1
  206. package/dist/modules/kb-fs/git-guarded-filesystem.d.ts +37 -0
  207. package/dist/modules/kb-fs/git-guarded-filesystem.d.ts.map +1 -0
  208. package/dist/modules/kb-fs/git-guarded-filesystem.js +104 -0
  209. package/dist/modules/kb-fs/git-guarded-filesystem.js.map +1 -0
  210. package/dist/modules/kb-fs/locking-filesystem.d.ts +113 -18
  211. package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
  212. package/dist/modules/kb-fs/locking-filesystem.js +353 -76
  213. package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
  214. package/dist/modules/kb-fs/node-fs.d.ts +23 -0
  215. package/dist/modules/kb-fs/node-fs.d.ts.map +1 -0
  216. package/dist/modules/kb-fs/node-fs.js +158 -0
  217. package/dist/modules/kb-fs/node-fs.js.map +1 -0
  218. package/dist/modules/kb-fs/read-only-filesystem.d.ts +10 -9
  219. package/dist/modules/kb-fs/read-only-filesystem.d.ts.map +1 -1
  220. package/dist/modules/kb-fs/read-only-filesystem.js +18 -9
  221. package/dist/modules/kb-fs/read-only-filesystem.js.map +1 -1
  222. package/dist/modules/kb-fs/repo-path.d.ts +100 -3
  223. package/dist/modules/kb-fs/repo-path.d.ts.map +1 -1
  224. package/dist/modules/kb-fs/repo-path.js +195 -3
  225. package/dist/modules/kb-fs/repo-path.js.map +1 -1
  226. package/dist/modules/kb-sync/index.d.ts +6 -0
  227. package/dist/modules/kb-sync/index.d.ts.map +1 -0
  228. package/dist/modules/kb-sync/index.js +5 -0
  229. package/dist/modules/kb-sync/index.js.map +1 -0
  230. package/dist/modules/kb-sync/kb-sync.interface.d.ts +77 -0
  231. package/dist/modules/kb-sync/kb-sync.interface.d.ts.map +1 -0
  232. package/dist/modules/kb-sync/kb-sync.interface.js +2 -0
  233. package/dist/modules/kb-sync/kb-sync.interface.js.map +1 -0
  234. package/dist/modules/kb-sync/kb-sync.routes.d.ts +70 -0
  235. package/dist/modules/kb-sync/kb-sync.routes.d.ts.map +1 -0
  236. package/dist/modules/kb-sync/kb-sync.routes.js +137 -0
  237. package/dist/modules/kb-sync/kb-sync.routes.js.map +1 -0
  238. package/dist/modules/kb-sync/kb-sync.service.d.ts +45 -0
  239. package/dist/modules/kb-sync/kb-sync.service.d.ts.map +1 -0
  240. package/dist/modules/kb-sync/kb-sync.service.js +185 -0
  241. package/dist/modules/kb-sync/kb-sync.service.js.map +1 -0
  242. package/dist/modules/kb-sync/sync-auth.d.ts +59 -0
  243. package/dist/modules/kb-sync/sync-auth.d.ts.map +1 -0
  244. package/dist/modules/kb-sync/sync-auth.js +62 -0
  245. package/dist/modules/kb-sync/sync-auth.js.map +1 -0
  246. package/dist/modules/kb-sync/sync-payload.d.ts +32 -0
  247. package/dist/modules/kb-sync/sync-payload.d.ts.map +1 -0
  248. package/dist/modules/kb-sync/sync-payload.js +105 -0
  249. package/dist/modules/kb-sync/sync-payload.js.map +1 -0
  250. package/dist/modules/marketplace/git-http.routes.d.ts +42 -0
  251. package/dist/modules/marketplace/git-http.routes.d.ts.map +1 -0
  252. package/dist/modules/marketplace/git-http.routes.js +192 -0
  253. package/dist/modules/marketplace/git-http.routes.js.map +1 -0
  254. package/dist/modules/marketplace/github-facade/github-facade-admin.routes.d.ts +33 -0
  255. package/dist/modules/marketplace/github-facade/github-facade-admin.routes.d.ts.map +1 -0
  256. package/dist/modules/marketplace/github-facade/github-facade-admin.routes.js +88 -0
  257. package/dist/modules/marketplace/github-facade/github-facade-admin.routes.js.map +1 -0
  258. package/dist/modules/marketplace/github-facade/github-facade-codes.store.d.ts +59 -0
  259. package/dist/modules/marketplace/github-facade/github-facade-codes.store.d.ts.map +1 -0
  260. package/dist/modules/marketplace/github-facade/github-facade-codes.store.js +96 -0
  261. package/dist/modules/marketplace/github-facade/github-facade-codes.store.js.map +1 -0
  262. package/dist/modules/marketplace/github-facade/github-facade-credentials.service.d.ts +126 -0
  263. package/dist/modules/marketplace/github-facade/github-facade-credentials.service.d.ts.map +1 -0
  264. package/dist/modules/marketplace/github-facade/github-facade-credentials.service.js +192 -0
  265. package/dist/modules/marketplace/github-facade/github-facade-credentials.service.js.map +1 -0
  266. package/dist/modules/marketplace/github-facade/github-facade.routes.d.ts +47 -0
  267. package/dist/modules/marketplace/github-facade/github-facade.routes.d.ts.map +1 -0
  268. package/dist/modules/marketplace/github-facade/github-facade.routes.js +252 -0
  269. package/dist/modules/marketplace/github-facade/github-facade.routes.js.map +1 -0
  270. package/dist/modules/marketplace/github-facade/github-facade.service.d.ts +121 -0
  271. package/dist/modules/marketplace/github-facade/github-facade.service.d.ts.map +1 -0
  272. package/dist/modules/marketplace/github-facade/github-facade.service.js +213 -0
  273. package/dist/modules/marketplace/github-facade/github-facade.service.js.map +1 -0
  274. package/dist/modules/marketplace/github-facade/index.d.ts +6 -0
  275. package/dist/modules/marketplace/github-facade/index.d.ts.map +1 -0
  276. package/dist/modules/marketplace/github-facade/index.js +6 -0
  277. package/dist/modules/marketplace/github-facade/index.js.map +1 -0
  278. package/dist/modules/marketplace/index.d.ts +4 -0
  279. package/dist/modules/marketplace/index.d.ts.map +1 -0
  280. package/dist/modules/marketplace/index.js +4 -0
  281. package/dist/modules/marketplace/index.js.map +1 -0
  282. package/dist/modules/marketplace/marketplace-repo.service.d.ts +135 -0
  283. package/dist/modules/marketplace/marketplace-repo.service.d.ts.map +1 -0
  284. package/dist/modules/marketplace/marketplace-repo.service.js +318 -0
  285. package/dist/modules/marketplace/marketplace-repo.service.js.map +1 -0
  286. package/dist/modules/mcp/downstream-pool.d.ts +107 -0
  287. package/dist/modules/mcp/downstream-pool.d.ts.map +1 -0
  288. package/dist/modules/mcp/downstream-pool.js +221 -0
  289. package/dist/modules/mcp/downstream-pool.js.map +1 -0
  290. package/dist/modules/mcp/downstream-token-refresh.d.ts +77 -0
  291. package/dist/modules/mcp/downstream-token-refresh.d.ts.map +1 -0
  292. package/dist/modules/mcp/downstream-token-refresh.js +166 -0
  293. package/dist/modules/mcp/downstream-token-refresh.js.map +1 -0
  294. package/dist/modules/mcp/first-call-probe.cli-args.d.ts +78 -0
  295. package/dist/modules/mcp/first-call-probe.cli-args.d.ts.map +1 -0
  296. package/dist/modules/mcp/first-call-probe.cli-args.js +151 -0
  297. package/dist/modules/mcp/first-call-probe.cli-args.js.map +1 -0
  298. package/dist/modules/mcp/first-call-probe.cli.d.ts +2 -0
  299. package/dist/modules/mcp/first-call-probe.cli.d.ts.map +1 -0
  300. package/dist/modules/mcp/first-call-probe.cli.js +62 -0
  301. package/dist/modules/mcp/first-call-probe.cli.js.map +1 -0
  302. package/dist/modules/mcp/first-call-probe.d.ts +165 -0
  303. package/dist/modules/mcp/first-call-probe.d.ts.map +1 -0
  304. package/dist/modules/mcp/first-call-probe.js +298 -0
  305. package/dist/modules/mcp/first-call-probe.js.map +1 -0
  306. package/dist/modules/mcp/manual-failure-memo.d.ts +42 -17
  307. package/dist/modules/mcp/manual-failure-memo.d.ts.map +1 -1
  308. package/dist/modules/mcp/manual-failure-memo.js +79 -23
  309. package/dist/modules/mcp/manual-failure-memo.js.map +1 -1
  310. package/dist/modules/mcp/mcp-auth.middleware.d.ts +9 -5
  311. package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
  312. package/dist/modules/mcp/mcp-auth.middleware.js +24 -16
  313. package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
  314. package/dist/modules/mcp/mcp.routes.d.ts +4 -4
  315. package/dist/modules/mcp/mcp.routes.d.ts.map +1 -1
  316. package/dist/modules/mcp/mcp.routes.js +83 -179
  317. package/dist/modules/mcp/mcp.routes.js.map +1 -1
  318. package/dist/modules/mcp/mcp.service.d.ts +218 -61
  319. package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
  320. package/dist/modules/mcp/mcp.service.js +713 -159
  321. package/dist/modules/mcp/mcp.service.js.map +1 -1
  322. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
  323. package/dist/modules/mcp/oauth/bevel-oauth-provider.js +8 -2
  324. package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
  325. package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts +14 -8
  326. package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts.map +1 -1
  327. package/dist/modules/mcp/oauth/oauth-consent.routes.js +16 -2
  328. package/dist/modules/mcp/oauth/oauth-consent.routes.js.map +1 -1
  329. package/dist/modules/mcp/oauth/oauth-state.d.ts +13 -2
  330. package/dist/modules/mcp/oauth/oauth-state.d.ts.map +1 -1
  331. package/dist/modules/mcp/oauth/oauth-state.js +3 -1
  332. package/dist/modules/mcp/oauth/oauth-state.js.map +1 -1
  333. package/dist/modules/mcp/surface-log-throttle.d.ts +59 -0
  334. package/dist/modules/mcp/surface-log-throttle.d.ts.map +1 -0
  335. package/dist/modules/mcp/surface-log-throttle.js +94 -0
  336. package/dist/modules/mcp/surface-log-throttle.js.map +1 -0
  337. package/dist/modules/plugins/compile/compile-marketplace.d.ts +104 -0
  338. package/dist/modules/plugins/compile/compile-marketplace.d.ts.map +1 -0
  339. package/dist/modules/plugins/compile/compile-marketplace.js +323 -0
  340. package/dist/modules/plugins/compile/compile-marketplace.js.map +1 -0
  341. package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts +73 -0
  342. package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts.map +1 -0
  343. package/dist/modules/plugins/compile/marketplace-compiler.service.js +135 -0
  344. package/dist/modules/plugins/compile/marketplace-compiler.service.js.map +1 -0
  345. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts +37 -0
  346. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts.map +1 -0
  347. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js +158 -0
  348. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js.map +1 -0
  349. package/dist/modules/plugins/discovery/bundle-dialect/registry.d.ts +65 -0
  350. package/dist/modules/plugins/discovery/bundle-dialect/registry.d.ts.map +1 -0
  351. package/dist/modules/plugins/discovery/bundle-dialect/registry.js +204 -0
  352. package/dist/modules/plugins/discovery/bundle-dialect/registry.js.map +1 -0
  353. package/dist/modules/plugins/discovery/kb-plugin-source.d.ts +39 -0
  354. package/dist/modules/plugins/discovery/kb-plugin-source.d.ts.map +1 -0
  355. package/dist/modules/plugins/discovery/kb-plugin-source.js +110 -0
  356. package/dist/modules/plugins/discovery/kb-plugin-source.js.map +1 -0
  357. package/dist/modules/plugins/discovery/native.source.d.ts +16 -0
  358. package/dist/modules/plugins/discovery/native.source.d.ts.map +1 -0
  359. package/dist/modules/plugins/discovery/native.source.js +120 -0
  360. package/dist/modules/plugins/discovery/native.source.js.map +1 -0
  361. package/dist/modules/plugins/discovery/plugin-source.d.ts +110 -0
  362. package/dist/modules/plugins/discovery/plugin-source.d.ts.map +1 -0
  363. package/dist/modules/plugins/discovery/plugin-source.js +2 -0
  364. package/dist/modules/plugins/discovery/plugin-source.js.map +1 -0
  365. package/dist/modules/plugins/index.d.ts +15 -3
  366. package/dist/modules/plugins/index.d.ts.map +1 -1
  367. package/dist/modules/plugins/index.js +13 -2
  368. package/dist/modules/plugins/index.js.map +1 -1
  369. package/dist/modules/plugins/join-request-jobs.service.d.ts +250 -0
  370. package/dist/modules/plugins/join-request-jobs.service.d.ts.map +1 -0
  371. package/dist/modules/plugins/join-request-jobs.service.js +602 -0
  372. package/dist/modules/plugins/join-request-jobs.service.js.map +1 -0
  373. package/dist/modules/plugins/join-request-records.store.d.ts +161 -0
  374. package/dist/modules/plugins/join-request-records.store.d.ts.map +1 -0
  375. package/dist/modules/plugins/join-request-records.store.js +179 -0
  376. package/dist/modules/plugins/join-request-records.store.js.map +1 -0
  377. package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
  378. package/dist/modules/plugins/join-requests.service.js +4 -2
  379. package/dist/modules/plugins/join-requests.service.js.map +1 -1
  380. package/dist/modules/plugins/plugin-links.d.ts +69 -0
  381. package/dist/modules/plugins/plugin-links.d.ts.map +1 -0
  382. package/dist/modules/plugins/plugin-links.js +163 -0
  383. package/dist/modules/plugins/plugin-links.js.map +1 -0
  384. package/dist/modules/plugins/plugin-links.service.d.ts +111 -0
  385. package/dist/modules/plugins/plugin-links.service.d.ts.map +1 -0
  386. package/dist/modules/plugins/plugin-links.service.js +295 -0
  387. package/dist/modules/plugins/plugin-links.service.js.map +1 -0
  388. package/dist/modules/plugins/plugin-provision.service.d.ts +129 -21
  389. package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
  390. package/dist/modules/plugins/plugin-provision.service.js +320 -75
  391. package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
  392. package/dist/modules/plugins/plugin-rename.service.d.ts +71 -0
  393. package/dist/modules/plugins/plugin-rename.service.d.ts.map +1 -0
  394. package/dist/modules/plugins/plugin-rename.service.js +254 -0
  395. package/dist/modules/plugins/plugin-rename.service.js.map +1 -0
  396. package/dist/modules/plugins/plugins.contract.d.ts +78 -4
  397. package/dist/modules/plugins/plugins.contract.d.ts.map +1 -1
  398. package/dist/modules/plugins/plugins.routes.d.ts +44 -5
  399. package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
  400. package/dist/modules/plugins/plugins.routes.js +297 -115
  401. package/dist/modules/plugins/plugins.routes.js.map +1 -1
  402. package/dist/modules/plugins/plugins.service.d.ts +82 -3
  403. package/dist/modules/plugins/plugins.service.d.ts.map +1 -1
  404. package/dist/modules/plugins/plugins.service.js +178 -48
  405. package/dist/modules/plugins/plugins.service.js.map +1 -1
  406. package/dist/modules/plugins/plugins.tools.d.ts +25 -0
  407. package/dist/modules/plugins/plugins.tools.d.ts.map +1 -0
  408. package/dist/modules/plugins/plugins.tools.js +82 -0
  409. package/dist/modules/plugins/plugins.tools.js.map +1 -0
  410. package/dist/modules/plugins/teams.routes.d.ts +42 -0
  411. package/dist/modules/plugins/teams.routes.d.ts.map +1 -0
  412. package/dist/modules/plugins/teams.routes.js +79 -0
  413. package/dist/modules/plugins/teams.routes.js.map +1 -0
  414. package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts +40 -1
  415. package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts.map +1 -1
  416. package/dist/modules/secrets-vault/db-secrets-vault.service.js +202 -37
  417. package/dist/modules/secrets-vault/db-secrets-vault.service.js.map +1 -1
  418. package/dist/modules/secrets-vault/index.d.ts +1 -1
  419. package/dist/modules/secrets-vault/index.d.ts.map +1 -1
  420. package/dist/modules/secrets-vault/index.js.map +1 -1
  421. package/dist/modules/secrets-vault/mcp-oauth-discovery.service.d.ts.map +1 -1
  422. package/dist/modules/secrets-vault/mcp-oauth-discovery.service.js +5 -3
  423. package/dist/modules/secrets-vault/mcp-oauth-discovery.service.js.map +1 -1
  424. package/dist/modules/secrets-vault/secrets-variable-loader.d.ts.map +1 -1
  425. package/dist/modules/secrets-vault/secrets-variable-loader.js +3 -1
  426. package/dist/modules/secrets-vault/secrets-variable-loader.js.map +1 -1
  427. package/dist/modules/secrets-vault/secrets-vault.contract.d.ts +78 -0
  428. package/dist/modules/secrets-vault/secrets-vault.contract.d.ts.map +1 -1
  429. package/dist/modules/secrets-vault/secrets-vault.contract.js +40 -0
  430. package/dist/modules/secrets-vault/secrets-vault.contract.js.map +1 -1
  431. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
  432. package/dist/modules/secrets-vault/secrets-vault.routes.js +106 -52
  433. package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
  434. package/dist/modules/settings/connection-check.d.ts +118 -0
  435. package/dist/modules/settings/connection-check.d.ts.map +1 -0
  436. package/dist/modules/settings/connection-check.js +287 -0
  437. package/dist/modules/settings/connection-check.js.map +1 -0
  438. package/dist/modules/settings/deployment-settings.service.d.ts +157 -2
  439. package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
  440. package/dist/modules/settings/deployment-settings.service.js +412 -35
  441. package/dist/modules/settings/deployment-settings.service.js.map +1 -1
  442. package/dist/modules/settings/git-root-folders.d.ts +54 -0
  443. package/dist/modules/settings/git-root-folders.d.ts.map +1 -0
  444. package/dist/modules/settings/git-root-folders.js +130 -0
  445. package/dist/modules/settings/git-root-folders.js.map +1 -0
  446. package/dist/modules/settings/oidc-check.d.ts +85 -0
  447. package/dist/modules/settings/oidc-check.d.ts.map +1 -0
  448. package/dist/modules/settings/oidc-check.js +172 -0
  449. package/dist/modules/settings/oidc-check.js.map +1 -0
  450. package/dist/modules/settings/setup.routes.d.ts +57 -1
  451. package/dist/modules/settings/setup.routes.d.ts.map +1 -1
  452. package/dist/modules/settings/setup.routes.js +408 -108
  453. package/dist/modules/settings/setup.routes.js.map +1 -1
  454. package/dist/modules/skills/allowed-tools-check.d.ts +132 -0
  455. package/dist/modules/skills/allowed-tools-check.d.ts.map +1 -0
  456. package/dist/modules/skills/allowed-tools-check.js +260 -0
  457. package/dist/modules/skills/allowed-tools-check.js.map +1 -0
  458. package/dist/modules/skills/index.d.ts +4 -1
  459. package/dist/modules/skills/index.d.ts.map +1 -1
  460. package/dist/modules/skills/index.js +2 -0
  461. package/dist/modules/skills/index.js.map +1 -1
  462. package/dist/modules/skills/pending-skills.service.d.ts +6 -11
  463. package/dist/modules/skills/pending-skills.service.d.ts.map +1 -1
  464. package/dist/modules/skills/pending-skills.service.js +24 -71
  465. package/dist/modules/skills/pending-skills.service.js.map +1 -1
  466. package/dist/modules/skills/skill-access-requests.routes.d.ts +38 -0
  467. package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -0
  468. package/dist/modules/skills/skill-access-requests.routes.js +171 -0
  469. package/dist/modules/skills/skill-access-requests.routes.js.map +1 -0
  470. package/dist/modules/skills/skills.contract.d.ts +67 -2
  471. package/dist/modules/skills/skills.contract.d.ts.map +1 -1
  472. package/dist/modules/skills/skills.routes.d.ts +35 -3
  473. package/dist/modules/skills/skills.routes.d.ts.map +1 -1
  474. package/dist/modules/skills/skills.routes.js +57 -4
  475. package/dist/modules/skills/skills.routes.js.map +1 -1
  476. package/dist/modules/skills/skills.service.d.ts +31 -3
  477. package/dist/modules/skills/skills.service.d.ts.map +1 -1
  478. package/dist/modules/skills/skills.service.js +236 -65
  479. package/dist/modules/skills/skills.service.js.map +1 -1
  480. package/dist/modules/skills/skills.tools.d.ts +4 -1
  481. package/dist/modules/skills/skills.tools.d.ts.map +1 -1
  482. package/dist/modules/skills/skills.tools.js +41 -6
  483. package/dist/modules/skills/skills.tools.js.map +1 -1
  484. package/dist/modules/tool-auth/connection-key-rejection.d.ts +18 -0
  485. package/dist/modules/tool-auth/connection-key-rejection.d.ts.map +1 -0
  486. package/dist/modules/tool-auth/connection-key-rejection.js +20 -0
  487. package/dist/modules/tool-auth/connection-key-rejection.js.map +1 -0
  488. package/dist/modules/tool-auth/connection-keys-admin.routes.d.ts +14 -0
  489. package/dist/modules/tool-auth/connection-keys-admin.routes.d.ts.map +1 -0
  490. package/dist/modules/tool-auth/connection-keys-admin.routes.js +67 -0
  491. package/dist/modules/tool-auth/connection-keys-admin.routes.js.map +1 -0
  492. package/dist/modules/tool-auth/external-api-key.interface.d.ts +66 -1
  493. package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -1
  494. package/dist/modules/tool-auth/external-api-key.interface.js +2 -1
  495. package/dist/modules/tool-auth/external-api-key.interface.js.map +1 -1
  496. package/dist/modules/tool-auth/external-api-key.service.d.ts +23 -4
  497. package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
  498. package/dist/modules/tool-auth/external-api-key.service.js +79 -19
  499. package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
  500. package/dist/modules/tool-auth/internal-token.service.d.ts +5 -2
  501. package/dist/modules/tool-auth/internal-token.service.d.ts.map +1 -1
  502. package/dist/modules/tool-auth/internal-token.service.js +5 -2
  503. package/dist/modules/tool-auth/internal-token.service.js.map +1 -1
  504. package/dist/modules/tool-auth/key-or-session.middleware.d.ts +23 -0
  505. package/dist/modules/tool-auth/key-or-session.middleware.d.ts.map +1 -0
  506. package/dist/modules/tool-auth/key-or-session.middleware.js +39 -0
  507. package/dist/modules/tool-auth/key-or-session.middleware.js.map +1 -0
  508. package/dist/modules/tool-auth/tool-auth.middleware.d.ts +7 -1
  509. package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
  510. package/dist/modules/tool-auth/tool-auth.middleware.js +8 -5
  511. package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
  512. package/dist/modules/tool-helpers/tool-context.d.ts +14 -0
  513. package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -1
  514. package/dist/modules/tool-helpers/tool-context.js +28 -6
  515. package/dist/modules/tool-helpers/tool-context.js.map +1 -1
  516. package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -1
  517. package/dist/modules/tool-helpers/tool-handler.js +22 -5
  518. package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
  519. package/dist/modules/tool-helpers/tool.contract.d.ts +6 -1
  520. package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
  521. package/dist/modules/tool-helpers/tool.contract.js +7 -1
  522. package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
  523. package/dist/modules/tool-manuals/index.d.ts +2 -1
  524. package/dist/modules/tool-manuals/index.d.ts.map +1 -1
  525. package/dist/modules/tool-manuals/index.js +1 -0
  526. package/dist/modules/tool-manuals/index.js.map +1 -1
  527. package/dist/modules/tool-manuals/mcp-json-discovery.d.ts +36 -0
  528. package/dist/modules/tool-manuals/mcp-json-discovery.d.ts.map +1 -1
  529. package/dist/modules/tool-manuals/mcp-json-discovery.js +136 -96
  530. package/dist/modules/tool-manuals/mcp-json-discovery.js.map +1 -1
  531. package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts +10 -2
  532. package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts.map +1 -1
  533. package/dist/modules/tool-manuals/mcp-server-edit.service.js +12 -15
  534. package/dist/modules/tool-manuals/mcp-server-edit.service.js.map +1 -1
  535. package/dist/modules/tool-manuals/pending-tools.service.d.ts +50 -0
  536. package/dist/modules/tool-manuals/pending-tools.service.d.ts.map +1 -0
  537. package/dist/modules/tool-manuals/pending-tools.service.js +149 -0
  538. package/dist/modules/tool-manuals/pending-tools.service.js.map +1 -0
  539. package/dist/modules/tool-manuals/tool-delete.service.d.ts +135 -0
  540. package/dist/modules/tool-manuals/tool-delete.service.d.ts.map +1 -0
  541. package/dist/modules/tool-manuals/tool-delete.service.js +303 -0
  542. package/dist/modules/tool-manuals/tool-delete.service.js.map +1 -0
  543. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +161 -0
  544. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
  545. package/dist/modules/tool-manuals/tool-manuals.contract.js +9 -0
  546. package/dist/modules/tool-manuals/tool-manuals.contract.js.map +1 -1
  547. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +19 -2
  548. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
  549. package/dist/modules/tool-manuals/tool-manuals.routes.js +127 -57
  550. package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
  551. package/dist/modules/tool-manuals/tool-manuals.service.d.ts +121 -2
  552. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
  553. package/dist/modules/tool-manuals/tool-manuals.service.js +415 -92
  554. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
  555. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
  556. package/dist/modules/tool-manuals/tool-manuals.tools.js +78 -6
  557. package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
  558. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  559. package/dist/modules/workflow/agent-tools/workflow.tools.js +88 -54
  560. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  561. package/dist/modules/workflow/event-bus.d.ts +10 -4
  562. package/dist/modules/workflow/event-bus.d.ts.map +1 -1
  563. package/dist/modules/workflow/event-bus.js +14 -11
  564. package/dist/modules/workflow/event-bus.js.map +1 -1
  565. package/dist/modules/workflow/events.routes.d.ts +17 -2
  566. package/dist/modules/workflow/events.routes.d.ts.map +1 -1
  567. package/dist/modules/workflow/events.routes.js +31 -12
  568. package/dist/modules/workflow/events.routes.js.map +1 -1
  569. package/dist/modules/workflow/file-lock.service.d.ts +22 -4
  570. package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
  571. package/dist/modules/workflow/file-lock.service.js +27 -4
  572. package/dist/modules/workflow/file-lock.service.js.map +1 -1
  573. package/dist/modules/workflow/git/change-request-link.d.ts +20 -0
  574. package/dist/modules/workflow/git/change-request-link.d.ts.map +1 -0
  575. package/dist/modules/workflow/git/change-request-link.js +34 -0
  576. package/dist/modules/workflow/git/change-request-link.js.map +1 -0
  577. package/dist/modules/workflow/git/git-version.d.ts.map +1 -1
  578. package/dist/modules/workflow/git/git-version.js +3 -1
  579. package/dist/modules/workflow/git/git-version.js.map +1 -1
  580. package/dist/modules/workflow/git/git.service.d.ts +303 -6
  581. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  582. package/dist/modules/workflow/git/git.service.js +753 -170
  583. package/dist/modules/workflow/git/git.service.js.map +1 -1
  584. package/dist/modules/workflow/git/node-git-runner.d.ts +36 -0
  585. package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -0
  586. package/dist/modules/workflow/git/node-git-runner.js +273 -0
  587. package/dist/modules/workflow/git/node-git-runner.js.map +1 -0
  588. package/dist/modules/workflow/git/pull-request.service.d.ts +57 -2
  589. package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
  590. package/dist/modules/workflow/git/pull-request.service.js +165 -25
  591. package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
  592. package/dist/modules/workflow/pending-commits.service.d.ts +11 -0
  593. package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
  594. package/dist/modules/workflow/pending-commits.service.js +24 -4
  595. package/dist/modules/workflow/pending-commits.service.js.map +1 -1
  596. package/dist/modules/workflow/pending-commits.worker.d.ts +15 -8
  597. package/dist/modules/workflow/pending-commits.worker.d.ts.map +1 -1
  598. package/dist/modules/workflow/pending-commits.worker.js +107 -58
  599. package/dist/modules/workflow/pending-commits.worker.js.map +1 -1
  600. package/dist/modules/workflow/recovery-bot.d.ts.map +1 -1
  601. package/dist/modules/workflow/recovery-bot.js +3 -1
  602. package/dist/modules/workflow/recovery-bot.js.map +1 -1
  603. package/dist/modules/workflow/review-workflow/approval-lock.d.ts +60 -0
  604. package/dist/modules/workflow/review-workflow/approval-lock.d.ts.map +1 -0
  605. package/dist/modules/workflow/review-workflow/approval-lock.js +116 -0
  606. package/dist/modules/workflow/review-workflow/approval-lock.js.map +1 -0
  607. package/dist/modules/workflow/review-workflow/review-workflow.interface.d.ts +54 -7
  608. package/dist/modules/workflow/review-workflow/review-workflow.interface.d.ts.map +1 -1
  609. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts +64 -0
  610. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
  611. package/dist/modules/workflow/review-workflow/review-workflow.service.js +269 -90
  612. package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
  613. package/dist/modules/workflow/sanitize-error.d.ts +5 -2
  614. package/dist/modules/workflow/sanitize-error.d.ts.map +1 -1
  615. package/dist/modules/workflow/sanitize-error.js +8 -4
  616. package/dist/modules/workflow/sanitize-error.js.map +1 -1
  617. package/dist/modules/workflow/workflow.routes.d.ts +2 -0
  618. package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
  619. package/dist/modules/workflow/workflow.routes.js +259 -29
  620. package/dist/modules/workflow/workflow.routes.js.map +1 -1
  621. package/dist/modules/workflow/workflow.service.d.ts +217 -14
  622. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  623. package/dist/modules/workflow/workflow.service.js +1142 -109
  624. package/dist/modules/workflow/workflow.service.js.map +1 -1
  625. package/dist/modules/workspace/empty-dirs.d.ts +15 -0
  626. package/dist/modules/workspace/empty-dirs.d.ts.map +1 -0
  627. package/dist/modules/workspace/empty-dirs.js +90 -0
  628. package/dist/modules/workspace/empty-dirs.js.map +1 -0
  629. package/dist/modules/workspace/file-readers/content-mode.d.ts +50 -0
  630. package/dist/modules/workspace/file-readers/content-mode.d.ts.map +1 -0
  631. package/dist/modules/workspace/file-readers/content-mode.js +55 -0
  632. package/dist/modules/workspace/file-readers/content-mode.js.map +1 -0
  633. package/dist/modules/workspace/file-readers/doc-extract.service.d.ts +4 -1
  634. package/dist/modules/workspace/file-readers/doc-extract.service.d.ts.map +1 -1
  635. package/dist/modules/workspace/file-readers/doc-extract.service.js +4 -1
  636. package/dist/modules/workspace/file-readers/doc-extract.service.js.map +1 -1
  637. package/dist/modules/workspace/file-readers/doc-extract.types.d.ts +5 -2
  638. package/dist/modules/workspace/file-readers/doc-extract.types.d.ts.map +1 -1
  639. package/dist/modules/workspace/file-readers/doc-extract.types.js +7 -4
  640. package/dist/modules/workspace/file-readers/doc-extract.types.js.map +1 -1
  641. package/dist/modules/workspace/file-readers/document-reader.d.ts +2 -0
  642. package/dist/modules/workspace/file-readers/document-reader.d.ts.map +1 -1
  643. package/dist/modules/workspace/file-readers/document-reader.js +5 -0
  644. package/dist/modules/workspace/file-readers/document-reader.js.map +1 -1
  645. package/dist/modules/workspace/file-readers/extract-docx.d.ts +6 -0
  646. package/dist/modules/workspace/file-readers/extract-docx.d.ts.map +1 -1
  647. package/dist/modules/workspace/file-readers/extract-docx.js +6 -0
  648. package/dist/modules/workspace/file-readers/extract-docx.js.map +1 -1
  649. package/dist/modules/workspace/file-readers/file-reader.d.ts +24 -5
  650. package/dist/modules/workspace/file-readers/file-reader.d.ts.map +1 -1
  651. package/dist/modules/workspace/file-readers/file-reader.js +11 -6
  652. package/dist/modules/workspace/file-readers/file-reader.js.map +1 -1
  653. package/dist/modules/workspace/file-readers/file-reader.registry.d.ts.map +1 -1
  654. package/dist/modules/workspace/file-readers/file-reader.registry.js +6 -1
  655. package/dist/modules/workspace/file-readers/file-reader.registry.js.map +1 -1
  656. package/dist/modules/workspace/file-readers/image-reader.d.ts +7 -5
  657. package/dist/modules/workspace/file-readers/image-reader.d.ts.map +1 -1
  658. package/dist/modules/workspace/file-readers/image-reader.js +9 -5
  659. package/dist/modules/workspace/file-readers/image-reader.js.map +1 -1
  660. package/dist/modules/workspace/file-readers/ooxml-text.d.ts +3 -0
  661. package/dist/modules/workspace/file-readers/ooxml-text.d.ts.map +1 -1
  662. package/dist/modules/workspace/file-readers/ooxml-text.js +39 -2
  663. package/dist/modules/workspace/file-readers/ooxml-text.js.map +1 -1
  664. package/dist/modules/workspace/file-readers/text-reader.d.ts +29 -1
  665. package/dist/modules/workspace/file-readers/text-reader.d.ts.map +1 -1
  666. package/dist/modules/workspace/file-readers/text-reader.js +57 -3
  667. package/dist/modules/workspace/file-readers/text-reader.js.map +1 -1
  668. package/dist/modules/workspace/git-internals.middleware.d.ts +28 -0
  669. package/dist/modules/workspace/git-internals.middleware.d.ts.map +1 -0
  670. package/dist/modules/workspace/git-internals.middleware.js +93 -0
  671. package/dist/modules/workspace/git-internals.middleware.js.map +1 -0
  672. package/dist/modules/workspace/not-found.d.ts +80 -0
  673. package/dist/modules/workspace/not-found.d.ts.map +1 -0
  674. package/dist/modules/workspace/not-found.js +112 -0
  675. package/dist/modules/workspace/not-found.js.map +1 -0
  676. package/dist/modules/workspace/session-ontology.gate.d.ts +1 -1
  677. package/dist/modules/workspace/session-ontology.gate.d.ts.map +1 -1
  678. package/dist/modules/workspace/session-ontology.gate.js +1 -1
  679. package/dist/modules/workspace/session-ontology.gate.js.map +1 -1
  680. package/dist/modules/workspace/startup/beside-checkout.d.ts +42 -0
  681. package/dist/modules/workspace/startup/beside-checkout.d.ts.map +1 -0
  682. package/dist/modules/workspace/startup/beside-checkout.js +110 -0
  683. package/dist/modules/workspace/startup/beside-checkout.js.map +1 -0
  684. package/dist/modules/workspace/startup/kb-git.d.ts +7 -12
  685. package/dist/modules/workspace/startup/kb-git.d.ts.map +1 -1
  686. package/dist/modules/workspace/startup/kb-git.js +34 -35
  687. package/dist/modules/workspace/startup/kb-git.js.map +1 -1
  688. package/dist/modules/workspace/startup/kb-startup-runner.d.ts +95 -0
  689. package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
  690. package/dist/modules/workspace/startup/kb-startup-runner.js +257 -55
  691. package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
  692. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts +45 -0
  693. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts.map +1 -1
  694. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js +417 -385
  695. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js.map +1 -1
  696. package/dist/modules/workspace/startup/steps/personal-spaces.step.d.ts +48 -0
  697. package/dist/modules/workspace/startup/steps/personal-spaces.step.d.ts.map +1 -0
  698. package/dist/modules/workspace/startup/steps/personal-spaces.step.js +183 -0
  699. package/dist/modules/workspace/startup/steps/personal-spaces.step.js.map +1 -0
  700. package/dist/modules/workspace/startup/steps/plugin-display-names.step.d.ts +51 -0
  701. package/dist/modules/workspace/startup/steps/plugin-display-names.step.d.ts.map +1 -0
  702. package/dist/modules/workspace/startup/steps/plugin-display-names.step.js +158 -0
  703. package/dist/modules/workspace/startup/steps/plugin-display-names.step.js.map +1 -0
  704. package/dist/modules/workspace/startup/steps/plugin-layout.d.ts +64 -0
  705. package/dist/modules/workspace/startup/steps/plugin-layout.d.ts.map +1 -0
  706. package/dist/modules/workspace/startup/steps/plugin-layout.js +97 -0
  707. package/dist/modules/workspace/startup/steps/plugin-layout.js.map +1 -0
  708. package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts +41 -0
  709. package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts.map +1 -0
  710. package/dist/modules/workspace/startup/steps/plugin-manifests.step.js +85 -0
  711. package/dist/modules/workspace/startup/steps/plugin-manifests.step.js.map +1 -0
  712. package/dist/modules/workspace/startup/steps/roles-yaml.step.d.ts +3 -1
  713. package/dist/modules/workspace/startup/steps/roles-yaml.step.d.ts.map +1 -1
  714. package/dist/modules/workspace/startup/steps/roles-yaml.step.js +4 -12
  715. package/dist/modules/workspace/startup/steps/roles-yaml.step.js.map +1 -1
  716. package/dist/modules/workspace/startup/steps/seed-tree.d.ts +6 -1
  717. package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
  718. package/dist/modules/workspace/startup/steps/seed-tree.js +174 -54
  719. package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
  720. package/dist/modules/workspace/startup/steps/template-files.step.d.ts +96 -24
  721. package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
  722. package/dist/modules/workspace/startup/steps/template-files.step.js +521 -126
  723. package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
  724. package/dist/modules/workspace/startup/steps/template-source.d.ts +94 -0
  725. package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -0
  726. package/dist/modules/workspace/startup/steps/template-source.js +160 -0
  727. package/dist/modules/workspace/startup/steps/template-source.js.map +1 -0
  728. package/dist/modules/workspace/workspace.routes.d.ts +14 -2
  729. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  730. package/dist/modules/workspace/workspace.routes.js +657 -246
  731. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  732. package/dist/modules/workspace/workspace.service.d.ts +323 -12
  733. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  734. package/dist/modules/workspace/workspace.service.js +1006 -257
  735. package/dist/modules/workspace/workspace.service.js.map +1 -1
  736. package/dist/modules/workspace/workspace.tools.d.ts +42 -1
  737. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  738. package/dist/modules/workspace/workspace.tools.js +1590 -146
  739. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  740. package/dist/modules/workspace/write-denial.d.ts +76 -0
  741. package/dist/modules/workspace/write-denial.d.ts.map +1 -0
  742. package/dist/modules/workspace/write-denial.js +138 -0
  743. package/dist/modules/workspace/write-denial.js.map +1 -0
  744. package/dist/shared/canonical-file-identity.d.ts +64 -0
  745. package/dist/shared/canonical-file-identity.d.ts.map +1 -0
  746. package/dist/shared/canonical-file-identity.js +92 -0
  747. package/dist/shared/canonical-file-identity.js.map +1 -0
  748. package/dist/shared/domain-errors.d.ts +128 -0
  749. package/dist/shared/domain-errors.d.ts.map +1 -1
  750. package/dist/shared/domain-errors.js +166 -0
  751. package/dist/shared/domain-errors.js.map +1 -1
  752. package/dist/shared/email-identity.d.ts +32 -0
  753. package/dist/shared/email-identity.d.ts.map +1 -0
  754. package/dist/shared/email-identity.js +37 -0
  755. package/dist/shared/email-identity.js.map +1 -0
  756. package/dist/shared/fs-errors.d.ts +8 -0
  757. package/dist/shared/fs-errors.d.ts.map +1 -0
  758. package/dist/shared/fs-errors.js +11 -0
  759. package/dist/shared/fs-errors.js.map +1 -0
  760. package/dist/shared/fs-walk.d.ts +20 -6
  761. package/dist/shared/fs-walk.d.ts.map +1 -1
  762. package/dist/shared/fs-walk.js +35 -27
  763. package/dist/shared/fs-walk.js.map +1 -1
  764. package/dist/shared/fs.contract.d.ts +206 -0
  765. package/dist/shared/fs.contract.d.ts.map +1 -0
  766. package/dist/shared/fs.contract.js +79 -0
  767. package/dist/shared/fs.contract.js.map +1 -0
  768. package/dist/shared/git-failure.d.ts +80 -0
  769. package/dist/shared/git-failure.d.ts.map +1 -0
  770. package/dist/shared/git-failure.js +139 -0
  771. package/dist/shared/git-failure.js.map +1 -0
  772. package/dist/shared/git-internals.d.ts +17 -0
  773. package/dist/shared/git-internals.d.ts.map +1 -0
  774. package/dist/shared/git-internals.js +123 -0
  775. package/dist/shared/git-internals.js.map +1 -0
  776. package/dist/shared/git.contract.d.ts +157 -0
  777. package/dist/shared/git.contract.d.ts.map +1 -0
  778. package/dist/shared/git.contract.js +103 -0
  779. package/dist/shared/git.contract.js.map +1 -0
  780. package/dist/shared/http-errors.d.ts +33 -0
  781. package/dist/shared/http-errors.d.ts.map +1 -0
  782. package/dist/shared/http-errors.js +35 -0
  783. package/dist/shared/http-errors.js.map +1 -0
  784. package/dist/shared/kb-walk.d.ts +52 -0
  785. package/dist/shared/kb-walk.d.ts.map +1 -0
  786. package/dist/shared/kb-walk.js +76 -0
  787. package/dist/shared/kb-walk.js.map +1 -0
  788. package/dist/shared/logger.contract.d.ts +63 -0
  789. package/dist/shared/logger.contract.d.ts.map +1 -0
  790. package/dist/shared/logger.contract.js +126 -0
  791. package/dist/shared/logger.contract.js.map +1 -0
  792. package/dist/shared/logging.d.ts +31 -0
  793. package/dist/shared/logging.d.ts.map +1 -0
  794. package/dist/shared/logging.js +92 -0
  795. package/dist/shared/logging.js.map +1 -0
  796. package/dist/shared/path-containment.d.ts +21 -0
  797. package/dist/shared/path-containment.d.ts.map +1 -0
  798. package/dist/shared/path-containment.js +34 -0
  799. package/dist/shared/path-containment.js.map +1 -0
  800. package/dist/shared/path-order.d.ts +18 -0
  801. package/dist/shared/path-order.d.ts.map +1 -0
  802. package/dist/shared/path-order.js +35 -0
  803. package/dist/shared/path-order.js.map +1 -0
  804. package/dist/shared/pending-proposals.d.ts +71 -0
  805. package/dist/shared/pending-proposals.d.ts.map +1 -0
  806. package/dist/shared/pending-proposals.js +98 -0
  807. package/dist/shared/pending-proposals.js.map +1 -0
  808. package/dist/shared/printable.d.ts +22 -0
  809. package/dist/shared/printable.d.ts.map +1 -0
  810. package/dist/shared/printable.js +65 -0
  811. package/dist/shared/printable.js.map +1 -0
  812. package/dist/shared/redact-secret.d.ts +30 -0
  813. package/dist/shared/redact-secret.d.ts.map +1 -0
  814. package/dist/shared/redact-secret.js +114 -0
  815. package/dist/shared/redact-secret.js.map +1 -0
  816. package/dist/shared/rename-no-replace.d.ts +119 -0
  817. package/dist/shared/rename-no-replace.d.ts.map +1 -0
  818. package/dist/shared/rename-no-replace.js +323 -0
  819. package/dist/shared/rename-no-replace.js.map +1 -0
  820. package/dist/shared/ssrf.d.ts.map +1 -1
  821. package/dist/shared/ssrf.js +49 -18
  822. package/dist/shared/ssrf.js.map +1 -1
  823. package/dist/shared/ttl-cache.d.ts +28 -1
  824. package/dist/shared/ttl-cache.d.ts.map +1 -1
  825. package/dist/shared/ttl-cache.js +33 -1
  826. package/dist/shared/ttl-cache.js.map +1 -1
  827. package/dist/version.d.ts +10 -6
  828. package/dist/version.d.ts.map +1 -1
  829. package/dist/version.js +10 -6
  830. package/dist/version.js.map +1 -1
  831. package/kb-template/.bevelignore +4 -3
  832. package/kb-template/AGENTS.md +364 -54
  833. package/kb-template/KnowledgeBase/How to get started.md +1 -1
  834. package/kb-template/Skills/.gitkeep +0 -0
  835. package/kb-template/access.md +5 -3
  836. package/kb-template/mcp-description.md +27 -0
  837. package/migrations/0005_github_facade.sql +25 -0
  838. package/migrations/0006_api_tokens_revoked_by.sql +1 -0
  839. package/migrations/0007_github_facade_registered.sql +1 -0
  840. package/migrations/0008_change_request_apply_failure.sql +4 -0
  841. package/migrations/0009_change_request_apply_failure_kind.sql +13 -0
  842. package/migrations/0010_plugin_join_requests.sql +15 -0
  843. package/migrations/0011_plugin_join_request_claim.sql +11 -0
  844. package/migrations/meta/0005_snapshot.json +1717 -0
  845. package/migrations/meta/0006_snapshot.json +1723 -0
  846. package/migrations/meta/0007_snapshot.json +1729 -0
  847. package/migrations/meta/0008_snapshot.json +1753 -0
  848. package/migrations/meta/0009_snapshot.json +1759 -0
  849. package/migrations/meta/0010_snapshot.json +1872 -0
  850. package/migrations/meta/0011_snapshot.json +1884 -0
  851. package/migrations/meta/_journal.json +49 -0
  852. package/package.json +8 -7
  853. package/src/__tests__/core-config.domain.test.ts +67 -2
  854. package/src/__tests__/kb-layout-config.test.ts +295 -0
  855. package/src/__tests__/open-change-gate.ts +15 -0
  856. package/src/core/__tests__/catalog-cache-invalidation.test.ts +226 -0
  857. package/src/core/__tests__/catalog-revision.test.ts +190 -0
  858. package/src/core/__tests__/lifecycle.test.ts +369 -0
  859. package/src/core/__tests__/public-config.test.ts +30 -0
  860. package/src/core/__tests__/readiness.test.ts +109 -0
  861. package/src/core/catalog-cache-invalidation.ts +111 -0
  862. package/src/core/catalog-revision.ts +110 -0
  863. package/src/core/create-core-server.ts +358 -63
  864. package/src/core/create-core-services.ts +449 -107
  865. package/src/core/lifecycle.ts +312 -0
  866. package/src/core/public-config.ts +86 -0
  867. package/src/core/readiness.ts +123 -0
  868. package/src/core-config.ts +70 -4
  869. package/src/index.ts +15 -0
  870. package/src/modules/access/__tests__/access-control.admin-root-floor.test.ts +362 -0
  871. package/src/modules/access/__tests__/access-control.atref-batch.test.ts +2 -1
  872. package/src/modules/access/__tests__/access-control.atref-cache.test.ts +46 -22
  873. package/src/modules/access/__tests__/access-control.deny-dependents.test.ts +215 -0
  874. package/src/modules/access/__tests__/access-control.download-read.test.ts +268 -0
  875. package/src/modules/access/__tests__/access-control.everyone-read.test.ts +145 -0
  876. package/src/modules/access/__tests__/access-control.group-read.test.ts +163 -0
  877. package/src/modules/access/__tests__/access-control.invalidate-race.test.ts +88 -0
  878. package/src/modules/access/__tests__/access-control.platform-restore.test.ts +152 -0
  879. package/src/modules/access/__tests__/access-control.prospective.test.ts +189 -0
  880. package/src/modules/access/__tests__/access-control.read-batch.test.ts +2 -1
  881. package/src/modules/access/__tests__/access-control.service.test.ts +142 -81
  882. package/src/modules/access/__tests__/access-groups.test.ts +47 -14
  883. package/src/modules/access/__tests__/access-md-format.test.ts +2 -1
  884. package/src/modules/access/__tests__/access-mutation.service.test.ts +52 -4
  885. package/src/modules/access/__tests__/access-own-read-grant.test.ts +2 -0
  886. package/src/modules/access/__tests__/access-personal-plugin.test.ts +153 -0
  887. package/src/modules/access/__tests__/access-plugin-principals.test.ts +385 -0
  888. package/src/modules/access/__tests__/access-restrict-here.test.ts +450 -0
  889. package/src/modules/access/__tests__/access.routes.batch.test.ts +139 -0
  890. package/src/modules/access/__tests__/access.routes.folder-governs.test.ts +394 -0
  891. package/src/modules/access/__tests__/access.routes.group-grant.test.ts +6 -2
  892. package/src/modules/access/__tests__/access.routes.overrides.test.ts +3 -2
  893. package/src/modules/access/__tests__/access.routes.proposal-branch.test.ts +234 -0
  894. package/src/modules/access/__tests__/access.routes.prospective.test.ts +216 -0
  895. package/src/modules/access/__tests__/access.routes.revoke.test.ts +7 -2
  896. package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +360 -0
  897. package/src/modules/access/__tests__/change-read-gate.test.ts +272 -0
  898. package/src/modules/access/__tests__/creator-access.test.ts +81 -83
  899. package/src/modules/access/__tests__/grant-sources.test.ts +3 -2
  900. package/src/modules/access/__tests__/groups-admin.service.test.ts +14 -5
  901. package/src/modules/access/__tests__/roles-admin.security.test.ts +196 -0
  902. package/src/modules/access/__tests__/roles-admin.service.test.ts +127 -2
  903. package/src/modules/access/__tests__/roles-capabilities.test.ts +5 -4
  904. package/src/modules/access/__tests__/roles.routes.test.ts +5 -2
  905. package/src/modules/access/__tests__/user-access-removal.service.test.ts +402 -0
  906. package/src/modules/access/__tests__/users-db-double.ts +63 -0
  907. package/src/modules/access/access-control.interface.ts +269 -18
  908. package/src/modules/access/access-control.service.ts +943 -226
  909. package/src/modules/access/access-mutation.service.ts +182 -13
  910. package/src/modules/access/access-view.ts +316 -0
  911. package/src/modules/access/access.routes.ts +385 -105
  912. package/src/modules/access/admin-locked-commit.ts +12 -14
  913. package/src/modules/access/admin-route-helpers.ts +4 -4
  914. package/src/modules/access/change-read-gate.ts +148 -0
  915. package/src/modules/access/creator-access.ts +89 -124
  916. package/src/modules/access/directory-sync-bot.ts +4 -1
  917. package/src/modules/access/groups-admin.service.ts +3 -3
  918. package/src/modules/access/reference-scan.ts +5 -5
  919. package/src/modules/access/roles-admin.service.ts +94 -15
  920. package/src/modules/access/synced-groups-committer.ts +10 -15
  921. package/src/modules/access/synced-groups-writer.ts +3 -12
  922. package/src/modules/access/user-access-removal.service.ts +711 -0
  923. package/src/modules/access-model/__tests__/access-grammar.test.ts +18 -0
  924. package/src/modules/access-model/__tests__/access-splice.test.ts +63 -1
  925. package/src/modules/access-model/__tests__/frontmatter-fences.test.ts +71 -0
  926. package/src/modules/access-model/__tests__/plugin-token-canonical.test.ts +40 -0
  927. package/src/modules/access-model/__tests__/roles-yaml-guard.test.ts +131 -0
  928. package/src/modules/access-model/access-errors.ts +56 -15
  929. package/src/modules/access-model/access-grammar.ts +198 -49
  930. package/src/modules/access-model/access-splice.ts +18 -18
  931. package/src/modules/access-model/access-template.ts +44 -0
  932. package/src/modules/access-model/change-gate.ts +80 -0
  933. package/src/modules/access-model/creator.ts +18 -21
  934. package/src/modules/access-model/frontmatter-lines.ts +98 -0
  935. package/src/modules/access-model/group-files.ts +4 -0
  936. package/src/modules/access-model/plugin-principals.ts +130 -0
  937. package/src/modules/access-model/roles-yaml-guard.ts +182 -4
  938. package/src/modules/admin/admin-access.service.ts +6 -2
  939. package/src/modules/agent-instructions/__tests__/agent-instructions.route.test.ts +100 -0
  940. package/src/modules/agent-instructions/__tests__/compose.test.ts +256 -0
  941. package/src/modules/agent-instructions/__tests__/read-preamble.test.ts +135 -0
  942. package/src/modules/agent-instructions/agent-instructions.routes.ts +41 -0
  943. package/src/modules/agent-instructions/compose.ts +271 -0
  944. package/src/modules/agent-instructions/index.ts +14 -0
  945. package/src/modules/agent-instructions/read-preamble.ts +88 -0
  946. package/src/modules/auth/__tests__/account-erasure.approval-gate.test.ts +209 -0
  947. package/src/modules/auth/__tests__/account.routes.test.ts +178 -2
  948. package/src/modules/auth/__tests__/auth.middleware.test.ts +78 -0
  949. package/src/modules/auth/__tests__/auth.service.test.ts +338 -5
  950. package/src/modules/auth/__tests__/oidc-auth-provider.test.ts +352 -12
  951. package/src/modules/auth/__tests__/onboarding-done.route.test.ts +3 -1
  952. package/src/modules/auth/account-erasure.service.ts +117 -10
  953. package/src/modules/auth/account.routes.ts +115 -14
  954. package/src/modules/auth/auth.routes.ts +20 -7
  955. package/src/modules/auth/auth.service.ts +187 -28
  956. package/src/modules/auth/oidc-auth-provider.ts +120 -22
  957. package/src/modules/code-mode/__tests__/code-mode.tool.test.ts +109 -1
  958. package/src/modules/code-mode/code-mode.tool.ts +13 -2
  959. package/src/modules/connection-probe/__tests__/connection-probe.service.test.ts +78 -0
  960. package/src/modules/connection-probe/connection-probe.service.ts +59 -7
  961. package/src/modules/database/__tests__/advisory-lease.test.ts +152 -0
  962. package/src/modules/database/__tests__/advisory-lock.test.ts +147 -0
  963. package/src/modules/database/advisory-lock.ts +346 -0
  964. package/src/modules/database/connection.ts +9 -1
  965. package/src/modules/database/core-schema.ts +177 -0
  966. package/src/modules/database/migrate.ts +27 -6
  967. package/src/modules/declared-variables/declared-variables.routes.ts +6 -3
  968. package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +3 -0
  969. package/src/modules/diff/__tests__/diff.service.test.ts +3 -0
  970. package/src/modules/diff/diff.routes.ts +2 -4
  971. package/src/modules/diff/diff.service.ts +75 -79
  972. package/src/modules/kb-fs/__tests__/locking-filesystem.test.ts +472 -9
  973. package/src/modules/kb-fs/__tests__/node-fs.test.ts +409 -0
  974. package/src/modules/kb-fs/__tests__/repo-path.test.ts +210 -1
  975. package/src/modules/{workspace → kb-fs}/bevel-ignore.ts +22 -15
  976. package/src/modules/kb-fs/file-change-notifier.ts +4 -1
  977. package/src/modules/kb-fs/git-guarded-filesystem.ts +123 -0
  978. package/src/modules/kb-fs/locking-filesystem.ts +399 -109
  979. package/src/modules/kb-fs/node-fs.ts +165 -0
  980. package/src/modules/kb-fs/read-only-filesystem.ts +18 -9
  981. package/src/modules/kb-fs/repo-path.ts +213 -3
  982. package/src/modules/kb-sync/__tests__/kb-sync.routes.test.ts +297 -0
  983. package/src/modules/kb-sync/__tests__/kb-sync.service.test.ts +295 -0
  984. package/src/modules/kb-sync/__tests__/sync-auth.test.ts +118 -0
  985. package/src/modules/kb-sync/__tests__/sync-payload.test.ts +148 -0
  986. package/src/modules/kb-sync/index.ts +19 -0
  987. package/src/modules/kb-sync/kb-sync.interface.ts +79 -0
  988. package/src/modules/kb-sync/kb-sync.routes.ts +200 -0
  989. package/src/modules/kb-sync/kb-sync.service.ts +204 -0
  990. package/src/modules/kb-sync/sync-auth.ts +118 -0
  991. package/src/modules/kb-sync/sync-payload.ts +143 -0
  992. package/src/modules/marketplace/__tests__/github-facade.test.ts +575 -0
  993. package/src/modules/marketplace/__tests__/marketplace-git.test.ts +180 -0
  994. package/src/modules/marketplace/__tests__/marketplace-repo.head.test.ts +47 -0
  995. package/src/modules/marketplace/git-http.routes.ts +196 -0
  996. package/src/modules/marketplace/github-facade/github-facade-admin.routes.ts +110 -0
  997. package/src/modules/marketplace/github-facade/github-facade-codes.store.ts +145 -0
  998. package/src/modules/marketplace/github-facade/github-facade-credentials.service.ts +263 -0
  999. package/src/modules/marketplace/github-facade/github-facade.routes.ts +294 -0
  1000. package/src/modules/marketplace/github-facade/github-facade.service.ts +282 -0
  1001. package/src/modules/marketplace/github-facade/index.ts +26 -0
  1002. package/src/modules/marketplace/index.ts +3 -0
  1003. package/src/modules/marketplace/marketplace-repo.service.ts +352 -0
  1004. package/src/modules/mcp/__tests__/downstream-pool.test.ts +278 -0
  1005. package/src/modules/mcp/__tests__/downstream-token-refresh.test.ts +178 -0
  1006. package/src/modules/mcp/__tests__/fake-downstream-mcp-server.ts +156 -0
  1007. package/src/modules/mcp/__tests__/first-call-probe.cli-args.test.ts +178 -0
  1008. package/src/modules/mcp/__tests__/first-call-probe.test.ts +414 -0
  1009. package/src/modules/mcp/__tests__/manual-failure-memo.test.ts +98 -6
  1010. package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +8 -5
  1011. package/src/modules/mcp/__tests__/mcp-routes-harness.ts +1 -3
  1012. package/src/modules/mcp/__tests__/mcp.e2e.test.ts +1055 -59
  1013. package/src/modules/mcp/__tests__/mcp.routes.stateless.test.ts +182 -0
  1014. package/src/modules/mcp/__tests__/mcp.service.test.ts +274 -6
  1015. package/src/modules/mcp/__tests__/surface-log-throttle.test.ts +169 -0
  1016. package/src/modules/mcp/downstream-pool.ts +256 -0
  1017. package/src/modules/mcp/downstream-token-refresh.ts +170 -0
  1018. package/src/modules/mcp/first-call-probe.cli-args.ts +159 -0
  1019. package/src/modules/mcp/first-call-probe.cli.ts +60 -0
  1020. package/src/modules/mcp/first-call-probe.ts +418 -0
  1021. package/src/modules/mcp/manual-failure-memo.ts +81 -23
  1022. package/src/modules/mcp/mcp-auth.middleware.ts +25 -16
  1023. package/src/modules/mcp/mcp.routes.ts +376 -482
  1024. package/src/modules/mcp/mcp.service.ts +846 -176
  1025. package/src/modules/mcp/oauth/bevel-oauth-provider.ts +8 -2
  1026. package/src/modules/mcp/oauth/oauth-consent.routes.ts +28 -6
  1027. package/src/modules/mcp/oauth/oauth-state.ts +15 -3
  1028. package/src/modules/mcp/surface-log-throttle.ts +120 -0
  1029. package/src/modules/plugins/__tests__/bundle-dialect.e2e.test.ts +166 -0
  1030. package/src/modules/plugins/__tests__/bundle-dialect.test.ts +165 -0
  1031. package/src/modules/plugins/__tests__/compile-marketplace.test.ts +423 -0
  1032. package/src/modules/plugins/__tests__/fake-join-request-store.ts +189 -0
  1033. package/src/modules/plugins/__tests__/join-request-jobs.service.test.ts +608 -0
  1034. package/src/modules/plugins/__tests__/plugin-creation-display-name.test.ts +241 -0
  1035. package/src/modules/plugins/__tests__/plugin-index.service.test.ts +201 -16
  1036. package/src/modules/plugins/__tests__/plugin-links.service.test.ts +284 -0
  1037. package/src/modules/plugins/__tests__/plugin-names.test.ts +77 -0
  1038. package/src/modules/plugins/__tests__/plugin-provision.service.test.ts +330 -20
  1039. package/src/modules/plugins/__tests__/plugin-rename.service.test.ts +456 -0
  1040. package/src/modules/plugins/__tests__/plugins.routes.test.ts +441 -43
  1041. package/src/modules/plugins/__tests__/plugins.tools.test.ts +131 -0
  1042. package/src/modules/plugins/__tests__/teams.routes.test.ts +248 -0
  1043. package/src/modules/plugins/compile/compile-marketplace.ts +500 -0
  1044. package/src/modules/plugins/compile/marketplace-compiler.service.ts +151 -0
  1045. package/src/modules/plugins/discovery/__tests__/kb-plugin-source.test.ts +365 -0
  1046. package/src/modules/plugins/discovery/bundle-dialect/bundle.source.ts +161 -0
  1047. package/src/modules/plugins/discovery/bundle-dialect/registry.ts +250 -0
  1048. package/src/modules/plugins/discovery/kb-plugin-source.ts +117 -0
  1049. package/src/modules/plugins/discovery/native.source.ts +140 -0
  1050. package/src/modules/plugins/discovery/plugin-source.ts +113 -0
  1051. package/src/modules/plugins/index.ts +25 -2
  1052. package/src/modules/plugins/join-request-jobs.service.ts +675 -0
  1053. package/src/modules/plugins/join-request-records.store.ts +353 -0
  1054. package/src/modules/plugins/join-requests.service.ts +7 -4
  1055. package/src/modules/plugins/plugin-links.service.ts +350 -0
  1056. package/src/modules/plugins/plugin-links.ts +187 -0
  1057. package/src/modules/plugins/plugin-provision.service.ts +356 -78
  1058. package/src/modules/plugins/plugin-rename.service.ts +310 -0
  1059. package/src/modules/plugins/plugins.contract.ts +79 -4
  1060. package/src/modules/plugins/plugins.routes.ts +320 -123
  1061. package/src/modules/plugins/plugins.service.ts +184 -57
  1062. package/src/modules/plugins/plugins.tools.ts +88 -0
  1063. package/src/modules/plugins/teams.routes.ts +129 -0
  1064. package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +359 -15
  1065. package/src/modules/secrets-vault/__tests__/db-secrets-vault.oauth.test.ts +248 -0
  1066. package/src/modules/secrets-vault/__tests__/namespace-secrets.test.ts +202 -0
  1067. package/src/modules/secrets-vault/db-secrets-vault.service.ts +217 -35
  1068. package/src/modules/secrets-vault/index.ts +1 -0
  1069. package/src/modules/secrets-vault/mcp-oauth-discovery.service.ts +6 -3
  1070. package/src/modules/secrets-vault/secrets-variable-loader.ts +4 -4
  1071. package/src/modules/secrets-vault/secrets-vault.contract.ts +93 -0
  1072. package/src/modules/secrets-vault/secrets-vault.routes.ts +99 -38
  1073. package/src/modules/settings/__tests__/connection-check.test.ts +233 -0
  1074. package/src/modules/settings/__tests__/deployment-settings.service.test.ts +240 -1
  1075. package/src/modules/settings/__tests__/git-root-folders.test.ts +247 -0
  1076. package/src/modules/settings/__tests__/oidc-check.test.ts +185 -0
  1077. package/src/modules/settings/__tests__/setup.routes.boot-failure.test.ts +119 -0
  1078. package/src/modules/settings/__tests__/setup.routes.layout-phase.test.ts +170 -0
  1079. package/src/modules/settings/__tests__/setup.routes.oidc.test.ts +555 -0
  1080. package/src/modules/settings/__tests__/setup.routes.sync-status.test.ts +77 -0
  1081. package/src/modules/settings/__tests__/setup.routes.test.ts +667 -16
  1082. package/src/modules/settings/connection-check.ts +351 -0
  1083. package/src/modules/settings/deployment-settings.service.ts +478 -39
  1084. package/src/modules/settings/git-root-folders.ts +171 -0
  1085. package/src/modules/settings/oidc-check.ts +229 -0
  1086. package/src/modules/settings/setup.routes.ts +480 -110
  1087. package/src/modules/skills/__tests__/allowed-tools-check.test.ts +224 -0
  1088. package/src/modules/skills/__tests__/allowed-tools-warn.tools.test.ts +210 -0
  1089. package/src/modules/skills/__tests__/pending-skills.service.test.ts +3 -3
  1090. package/src/modules/skills/__tests__/skill-access-requests.routes.test.ts +128 -0
  1091. package/src/modules/skills/__tests__/skills.routes.warnings.test.ts +91 -0
  1092. package/src/modules/skills/__tests__/skills.service.test.ts +308 -2
  1093. package/src/modules/skills/allowed-tools-check.ts +352 -0
  1094. package/src/modules/skills/index.ts +5 -0
  1095. package/src/modules/skills/pending-skills.service.ts +26 -85
  1096. package/src/modules/skills/skill-access-requests.routes.ts +203 -0
  1097. package/src/modules/skills/skills.contract.ts +67 -3
  1098. package/src/modules/skills/skills.routes.ts +75 -4
  1099. package/src/modules/skills/skills.service.ts +258 -66
  1100. package/src/modules/skills/skills.tools.ts +43 -5
  1101. package/src/modules/tool-auth/__tests__/connection-key-rejection.test.ts +192 -0
  1102. package/src/modules/tool-auth/__tests__/connection-keys-admin.routes.test.ts +116 -0
  1103. package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +124 -0
  1104. package/src/modules/tool-auth/connection-key-rejection.ts +25 -0
  1105. package/src/modules/tool-auth/connection-keys-admin.routes.ts +76 -0
  1106. package/src/modules/tool-auth/external-api-key.interface.ts +73 -1
  1107. package/src/modules/tool-auth/external-api-key.service.ts +95 -29
  1108. package/src/modules/tool-auth/internal-token.service.ts +5 -2
  1109. package/src/modules/tool-auth/key-or-session.middleware.ts +45 -0
  1110. package/src/modules/tool-auth/tool-auth.middleware.ts +16 -7
  1111. package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +228 -0
  1112. package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +33 -4
  1113. package/src/modules/tool-helpers/tool-context.ts +46 -7
  1114. package/src/modules/tool-helpers/tool-handler.ts +23 -5
  1115. package/src/modules/tool-helpers/tool.contract.ts +5 -0
  1116. package/src/modules/tool-manuals/__tests__/mcp-json-discovery.test.ts +24 -1
  1117. package/src/modules/tool-manuals/__tests__/mcp-server-edit.service.test.ts +2 -1
  1118. package/src/modules/tool-manuals/__tests__/pending-tools.service.test.ts +411 -0
  1119. package/src/modules/tool-manuals/__tests__/tool-delete.route.test.ts +133 -0
  1120. package/src/modules/tool-manuals/__tests__/tool-delete.service.test.ts +469 -0
  1121. package/src/modules/tool-manuals/__tests__/tool-manuals.archive.route.test.ts +21 -2
  1122. package/src/modules/tool-manuals/__tests__/tool-manuals.cli.test.ts +11 -4
  1123. package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +6 -1
  1124. package/src/modules/tool-manuals/__tests__/tool-manuals.invalid.routes.test.ts +254 -0
  1125. package/src/modules/tool-manuals/__tests__/tool-manuals.invalid.test.ts +577 -0
  1126. package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +6 -1
  1127. package/src/modules/tool-manuals/__tests__/tool-manuals.pending.route.test.ts +102 -0
  1128. package/src/modules/tool-manuals/__tests__/tool-manuals.restart.test.ts +285 -0
  1129. package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +178 -2
  1130. package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +114 -2
  1131. package/src/modules/tool-manuals/index.ts +3 -0
  1132. package/src/modules/tool-manuals/mcp-json-discovery.ts +164 -95
  1133. package/src/modules/tool-manuals/mcp-server-edit.service.ts +11 -14
  1134. package/src/modules/tool-manuals/pending-tools.service.ts +179 -0
  1135. package/src/modules/tool-manuals/tool-delete.service.ts +401 -0
  1136. package/src/modules/tool-manuals/tool-manuals.contract.ts +165 -0
  1137. package/src/modules/tool-manuals/tool-manuals.routes.ts +138 -54
  1138. package/src/modules/tool-manuals/tool-manuals.service.ts +440 -104
  1139. package/src/modules/tool-manuals/tool-manuals.tools.ts +81 -6
  1140. package/src/modules/workflow/__tests__/apply-failure.test.ts +1038 -0
  1141. package/src/modules/workflow/__tests__/event-bus.test.ts +61 -9
  1142. package/src/modules/workflow/__tests__/fake-file-lock-db.ts +199 -0
  1143. package/src/modules/workflow/__tests__/file-lock.service.path-identity.test.ts +237 -0
  1144. package/src/modules/workflow/__tests__/format-affected-owners.test.ts +18 -0
  1145. package/src/modules/workflow/__tests__/merge-announces-tree.test.ts +220 -0
  1146. package/src/modules/workflow/__tests__/pending-commits.worker.concurrency.test.ts +187 -0
  1147. package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +3 -1
  1148. package/src/modules/workflow/__tests__/sanitize-error.test.ts +10 -0
  1149. package/src/modules/workflow/__tests__/workflow.routes.folder-proposals.test.ts +128 -0
  1150. package/src/modules/workflow/__tests__/workflow.routes.fork-point-file.test.ts +149 -0
  1151. package/src/modules/workflow/__tests__/workflow.routes.lock-path.test.ts +305 -0
  1152. package/src/modules/workflow/__tests__/workflow.service.branch-in-use.test.ts +2 -0
  1153. package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +3 -0
  1154. package/src/modules/workflow/__tests__/workflow.service.deleted-branch-sweep.test.ts +2 -0
  1155. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +296 -27
  1156. package/src/modules/workflow/__tests__/workflow.service.folder-proposals.test.ts +564 -0
  1157. package/src/modules/workflow/__tests__/workflow.service.platform-restore.test.ts +135 -0
  1158. package/src/modules/workflow/__tests__/workflow.service.read-gate.test.ts +172 -0
  1159. package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +133 -2
  1160. package/src/modules/workflow/__tests__/workflow.service.sync.test.ts +442 -0
  1161. package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +281 -0
  1162. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +158 -7
  1163. package/src/modules/workflow/agent-tools/workflow.tools.ts +93 -64
  1164. package/src/modules/workflow/event-bus.ts +26 -28
  1165. package/src/modules/workflow/events.routes.ts +56 -21
  1166. package/src/modules/workflow/file-lock.service.ts +27 -4
  1167. package/src/modules/workflow/git/__tests__/change-request-link.test.ts +43 -0
  1168. package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +1 -0
  1169. package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +238 -1
  1170. package/src/modules/workflow/git/__tests__/git.service.forkPoint.test.ts +245 -0
  1171. package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +35 -0
  1172. package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +149 -0
  1173. package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +3 -3
  1174. package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +47 -4
  1175. package/src/modules/workflow/git/__tests__/git.service.revertPathsAndPush.test.ts +177 -0
  1176. package/src/modules/workflow/git/__tests__/git.service.syncFromRemote.test.ts +253 -0
  1177. package/src/modules/workflow/git/__tests__/node-git-runner.test.ts +114 -0
  1178. package/src/modules/workflow/git/__tests__/pull-request.service.getPrDetail.test.ts +69 -2
  1179. package/src/modules/workflow/git/__tests__/pull-request.service.list-fetch.test.ts +121 -0
  1180. package/src/modules/workflow/git/__tests__/pull-request.service.placeholder.test.ts +79 -0
  1181. package/src/modules/workflow/git/__tests__/pull-request.service.test.ts +1 -1
  1182. package/src/modules/workflow/git/__tests__/pull-request.service.viewer-can-cancel.test.ts +1 -1
  1183. package/src/modules/workflow/git/__tests__/pull-request.service.viewer-can-update.test.ts +111 -0
  1184. package/src/modules/workflow/git/change-request-link.ts +35 -0
  1185. package/src/modules/workflow/git/git-version.ts +5 -2
  1186. package/src/modules/workflow/git/git.service.ts +922 -199
  1187. package/src/modules/workflow/git/node-git-runner.ts +315 -0
  1188. package/src/modules/workflow/git/pull-request.service.ts +188 -27
  1189. package/src/modules/workflow/pending-commits.service.ts +26 -7
  1190. package/src/modules/workflow/pending-commits.worker.ts +114 -69
  1191. package/src/modules/workflow/recovery-bot.ts +4 -1
  1192. package/src/modules/workflow/review-workflow/__tests__/approval-states.test.ts +180 -1
  1193. package/src/modules/workflow/review-workflow/__tests__/cancel-pr.test.ts +1 -1
  1194. package/src/modules/workflow/review-workflow/__tests__/carry-approvals-forward.test.ts +520 -0
  1195. package/src/modules/workflow/review-workflow/__tests__/erase-approver.test.ts +84 -0
  1196. package/src/modules/workflow/review-workflow/__tests__/merge-gate.test.ts +89 -77
  1197. package/src/modules/workflow/review-workflow/approval-lock.ts +122 -0
  1198. package/src/modules/workflow/review-workflow/review-workflow.interface.ts +59 -7
  1199. package/src/modules/workflow/review-workflow/review-workflow.service.ts +309 -105
  1200. package/src/modules/workflow/sanitize-error.ts +9 -4
  1201. package/src/modules/workflow/workflow.routes.ts +273 -29
  1202. package/src/modules/workflow/workflow.service.ts +1341 -174
  1203. package/src/modules/workspace/__tests__/empty-dirs.test.ts +44 -0
  1204. package/src/modules/workspace/__tests__/file-stat-access.test.ts +301 -0
  1205. package/src/modules/workspace/__tests__/git-internals.security.test.ts +792 -0
  1206. package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +464 -0
  1207. package/src/modules/workspace/__tests__/workspace.routes.branch-errors.test.ts +139 -0
  1208. package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +189 -37
  1209. package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +51 -11
  1210. package/src/modules/workspace/__tests__/workspace.routes.download-implies-read.test.ts +161 -0
  1211. package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +109 -10
  1212. package/src/modules/workspace/__tests__/workspace.routes.file-writes.test.ts +624 -0
  1213. package/src/modules/workspace/__tests__/workspace.routes.folders.test.ts +409 -0
  1214. package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +327 -0
  1215. package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +31 -13
  1216. package/src/modules/workspace/__tests__/workspace.service.ensure-remotes-fetched.test.ts +109 -0
  1217. package/src/modules/workspace/__tests__/workspace.service.list-cloned.test.ts +94 -0
  1218. package/src/modules/workspace/__tests__/workspace.service.missing-branch.test.ts +28 -0
  1219. package/src/modules/workspace/__tests__/workspace.service.move-never-overwrites.test.ts +218 -0
  1220. package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +98 -13
  1221. package/src/modules/workspace/__tests__/workspace.service.test.ts +811 -42
  1222. package/src/modules/workspace/__tests__/workspace.service.unknown-branch.test.ts +197 -0
  1223. package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +128 -0
  1224. package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +212 -0
  1225. package/src/modules/workspace/__tests__/workspace.tools.test.ts +2632 -110
  1226. package/src/modules/workspace/__tests__/write-denial.test.ts +75 -0
  1227. package/src/modules/workspace/empty-dirs.ts +79 -0
  1228. package/src/modules/workspace/file-readers/README.md +32 -0
  1229. package/src/modules/workspace/file-readers/__tests__/doc-extract.test.ts +59 -2
  1230. package/src/modules/workspace/file-readers/__tests__/file-reader.registry.test.ts +133 -4
  1231. package/src/modules/workspace/file-readers/__tests__/fixtures/soft-break.docx +0 -0
  1232. package/src/modules/workspace/file-readers/__tests__/fixtures/tab.docx +0 -0
  1233. package/src/modules/workspace/file-readers/content-mode.ts +87 -0
  1234. package/src/modules/workspace/file-readers/doc-extract.service.ts +4 -1
  1235. package/src/modules/workspace/file-readers/doc-extract.types.ts +8 -4
  1236. package/src/modules/workspace/file-readers/document-reader.ts +6 -0
  1237. package/src/modules/workspace/file-readers/extract-docx.ts +6 -0
  1238. package/src/modules/workspace/file-readers/file-reader.registry.ts +9 -1
  1239. package/src/modules/workspace/file-readers/file-reader.ts +27 -6
  1240. package/src/modules/workspace/file-readers/image-reader.ts +10 -5
  1241. package/src/modules/workspace/file-readers/ooxml-text.ts +38 -2
  1242. package/src/modules/workspace/file-readers/text-reader.ts +61 -4
  1243. package/src/modules/workspace/git-internals.middleware.ts +86 -0
  1244. package/src/modules/workspace/not-found.ts +119 -0
  1245. package/src/modules/workspace/session-ontology.gate.ts +1 -1
  1246. package/src/modules/workspace/startup/__tests__/beside-checkout.test.ts +181 -0
  1247. package/src/modules/workspace/startup/__tests__/kb-startup-runner.degraded.test.ts +361 -0
  1248. package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +53 -16
  1249. package/src/modules/workspace/startup/beside-checkout.ts +112 -0
  1250. package/src/modules/workspace/startup/kb-git.ts +43 -36
  1251. package/src/modules/workspace/startup/kb-startup-runner.ts +303 -63
  1252. package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +1405 -48
  1253. package/src/modules/workspace/startup/steps/groups-to-plugins.step.ts +460 -417
  1254. package/src/modules/workspace/startup/steps/personal-spaces.step.ts +191 -0
  1255. package/src/modules/workspace/startup/steps/plugin-display-names.step.ts +169 -0
  1256. package/src/modules/workspace/startup/steps/plugin-layout.ts +110 -0
  1257. package/src/modules/workspace/startup/steps/plugin-manifests.step.ts +90 -0
  1258. package/src/modules/workspace/startup/steps/roles-yaml.step.ts +6 -12
  1259. package/src/modules/workspace/startup/steps/seed-tree.ts +177 -54
  1260. package/src/modules/workspace/startup/steps/template-files.step.ts +581 -126
  1261. package/src/modules/workspace/startup/steps/template-source.ts +168 -0
  1262. package/src/modules/workspace/workspace.routes.ts +691 -269
  1263. package/src/modules/workspace/workspace.service.ts +1071 -292
  1264. package/src/modules/workspace/workspace.tools.ts +1787 -180
  1265. package/src/modules/workspace/write-denial.ts +189 -0
  1266. package/src/shared/__tests__/canonical-file-identity.test.ts +154 -0
  1267. package/src/shared/__tests__/email-identity.test.ts +35 -0
  1268. package/src/shared/__tests__/filename.test.ts +0 -0
  1269. package/src/shared/__tests__/frontmatter-id.test.ts +5 -0
  1270. package/src/shared/__tests__/git-failure.test.ts +198 -0
  1271. package/src/shared/__tests__/git-internals.test.ts +115 -0
  1272. package/src/shared/__tests__/http-errors.test.ts +42 -0
  1273. package/src/shared/__tests__/logging.test.ts +185 -0
  1274. package/src/shared/__tests__/path-containment.test.ts +60 -0
  1275. package/src/shared/__tests__/path-order.test.ts +24 -0
  1276. package/src/shared/__tests__/pending-proposals.readAt.test.ts +102 -0
  1277. package/src/shared/__tests__/printable.test.ts +64 -0
  1278. package/src/shared/__tests__/redact-secret.test.ts +122 -0
  1279. package/src/shared/__tests__/rename-no-replace.test.ts +466 -0
  1280. package/src/shared/__tests__/ssrf.test.ts +20 -0
  1281. package/src/shared/__tests__/ttl-cache.test.ts +55 -0
  1282. package/src/shared/canonical-file-identity.ts +92 -0
  1283. package/src/shared/domain-errors.ts +178 -0
  1284. package/src/shared/email-identity.ts +38 -0
  1285. package/src/shared/fs.contract.ts +225 -0
  1286. package/src/shared/git-failure.ts +196 -0
  1287. package/src/shared/git-internals.ts +124 -0
  1288. package/src/shared/git.contract.ts +170 -0
  1289. package/src/shared/http-errors.ts +36 -0
  1290. package/src/shared/logger.contract.ts +141 -0
  1291. package/src/shared/logging.ts +96 -0
  1292. package/src/shared/path-containment.ts +34 -0
  1293. package/src/shared/path-order.ts +33 -0
  1294. package/src/shared/pending-proposals.ts +161 -0
  1295. package/src/shared/printable.ts +68 -0
  1296. package/src/shared/redact-secret.ts +118 -0
  1297. package/src/shared/rename-no-replace.ts +386 -0
  1298. package/src/shared/ssrf.ts +44 -16
  1299. package/src/shared/ttl-cache.ts +33 -1
  1300. package/src/version.ts +10 -6
  1301. package/src/modules/diff/diff-paths.ts +0 -9
  1302. package/src/modules/mcp/__tests__/mcp-session-store.test.ts +0 -151
  1303. package/src/modules/mcp/__tests__/mcp.routes.session.test.ts +0 -226
  1304. package/src/modules/mcp/mcp-session-store.ts +0 -162
  1305. package/src/shared/__tests__/fs-walk.test.ts +0 -42
  1306. package/src/shared/fs-walk.ts +0 -30
  1307. package/src/shared/hash-email.ts +0 -14
@@ -1,4 +1,8 @@
1
1
  import path from 'node:path';
2
+ import { createHash } from 'node:crypto';
3
+ import { logger } from '../../shared/logging.js';
4
+
5
+ const log = logger('tool-manuals');
2
6
  import fs from 'node:fs/promises';
3
7
  import { parse as parseYaml } from 'yaml';
4
8
  import '@utcp/http'; // side effect: register the 'http' call-template type (http + inline sub-manuals)
@@ -15,17 +19,18 @@ import {
15
19
  import {
16
20
  DEFAULT_BRANCH,
17
21
  PLUGINS_DIR,
18
- PLUGIN_MANIFEST_FILE,
19
- PLUGIN_MCP_FILE,
20
22
  } from '@bevel-software/platform-shared';
21
23
  import { descriptorsFromMcpJson } from './mcp-json-discovery.js';
24
+ import type { PluginSource } from '../plugins/discovery/plugin-source.js';
22
25
  import type { WorkspaceService } from '../workspace/workspace.service.js';
23
26
  import { workspaceIdForBranch } from '../../shared/workspace-id.js';
24
27
  import type { IAccessControl } from '../access/access-control.interface.js';
25
28
  import { assertSafeFetchUrl } from '../../shared/ssrf.js';
29
+ import { redactSecret } from '../../shared/redact-secret.js';
30
+ import { printable } from '../../shared/printable.js';
26
31
  import { RESERVED_VARIABLE_NAMES, findReservedVariableRef } from '../../shared/variable-refs.js';
27
32
  import { extractFrontmatter, resolveDeclaredId, isValidId, dedupeById } from '../../shared/frontmatter-id.js';
28
- import { walkFiles } from '../../shared/fs-walk.js';
33
+ import type { ITreeWalker } from '../../shared/fs.contract.js';
29
34
  import { TtlCache } from '../../shared/ttl-cache.js';
30
35
  import {
31
36
  utcpNamespacePrefix,
@@ -35,11 +40,14 @@ import {
35
40
  } from '../../shared/utcp-namespace.js';
36
41
  import {
37
42
  EXTERNAL_KB_MANUAL_NAME,
43
+ MAX_CAPABILITIES,
38
44
  type IToolManualService,
39
45
  type ToolManualDescriptor,
40
46
  type ToolManualDescriptorBase,
41
47
  type ToolManualSummary,
42
48
  type ToolManualDetail,
49
+ type InvalidToolManual,
50
+ type AccessibleCatalog,
43
51
  type ToolCapability,
44
52
  type UtcpManualDict,
45
53
  type ToolManualPreview,
@@ -53,13 +61,6 @@ import {
53
61
 
54
62
  const CACHE_TTL_MS = 60_000;
55
63
 
56
- /**
57
- * How many embedded tools a manual may advertise on the tool page. A `.tool` is
58
- * author-written, so its `tools` array is unbounded input; the page renders one
59
- * bullet per entry, and a thousand of them is a broken page, not a useful one.
60
- */
61
- const MAX_CAPABILITIES = 100;
62
-
63
64
  /**
64
65
  * UTCP namespaces a user `.tool` may NOT claim: they belong to built-in manuals
65
66
  * whose loopback creds are pre-seeded on the agent's code-mode client (the
@@ -84,18 +85,112 @@ const RESERVED_TOOL_NAMESPACES = [INTERNAL_MANUAL_NAME, EXTERNAL_KB_MANUAL_NAME]
84
85
  * every boundary that classifies references.
85
86
  */
86
87
 
87
- /** Throw if any string in the `.tool` document references a reserved variable. */
88
- function assertNoReservedVariableRefs(doc: unknown, name: string): void {
88
+ /**
89
+ * Throw if any string in the `.tool` document references a reserved variable.
90
+ *
91
+ * `ref` is named because it is OURS — one of `RESERVED_VARIABLE_NAMES`, matched
92
+ * from a fixed list rather than copied out of the file. That is the line every
93
+ * refusal here holds: see {@link describeManualFault}.
94
+ */
95
+ function assertNoReservedVariableRefs(doc: unknown): void {
89
96
  const ref = findReservedVariableRef(doc);
90
97
  if (ref !== null) {
91
98
  throw new Error(
92
- `\`.tool\` "${name}" references the reserved variable "${ref}" — ` +
99
+ `this \`.tool\` references the reserved variable "${ref}" — ` +
93
100
  'API_URL and CONNECTION_KEY (bare or namespaced, e.g. `<namespace>_CONNECTION_KEY`) ' +
94
101
  'are seeded by the platform for its own manuals and may not appear anywhere in a `.tool`.',
95
102
  );
96
103
  }
97
104
  }
98
105
 
106
+ /**
107
+ * How much of a validation message may reach a listing. Long enough for every
108
+ * sentence the normalizer writes; short enough that a message which interpolated
109
+ * a chunk of the file (`unknown \`.tool\` type: <whatever was written there>`)
110
+ * cannot smuggle a pasted credential out one character at a time.
111
+ */
112
+ const MAX_REASON_LENGTH = 300;
113
+
114
+ /**
115
+ * Why one `.tool` was refused, in a form safe to hand an agent, a browser and a
116
+ * log — the `reason` of an {@link InvalidToolManual}.
117
+ *
118
+ * This is the LAST of two defences, not the only one. The first is upstream and
119
+ * structural, and it is the one that carries the guarantee:
120
+ *
121
+ * A REASON REPEATS NOTHING THE FILE SAID.
122
+ *
123
+ * Every refusal this module writes locates the fault — a field name we chose
124
+ * (`` `id` ``, `` `healthCheck.url` ``), an ordinal (`` `variables[2].scope` ``,
125
+ * `` `headers` entry 3 of 4 ``) — and states the rule. It never interpolates
126
+ * what was written there, and that includes text which passed a check: a name
127
+ * matching `[A-Za-z0-9_]+` is a legal identifier, not a string we may repeat,
128
+ * and a token spelled with underscores matches it. The only author-derived
129
+ * strings named anywhere are ones matched against a FIXED list of ours (a
130
+ * reserved variable, a reserved namespace), where saying which one was hit
131
+ * teaches nothing the platform did not already publish.
132
+ *
133
+ * It has to be that way round — no scrub can recognise an arbitrary
134
+ * author-chosen string as a credential, so a message that interpolates one
135
+ * cannot be made safe after the fact. What remains for this function is the
136
+ * text the process does NOT author: the YAML parser's, which quotes the file at
137
+ * its fault.
138
+ *
139
+ * Two things happen here, and both are about NOT echoing the file back.
140
+ *
141
+ * 1. A `YAMLParseError`'s `message` ends with a SOURCE SNIPPET: the offending
142
+ * lines, verbatim, under a caret. A `.tool` is content an author may have
143
+ * pasted a literal token into (`Authorization: Bearer <a real key>`), and
144
+ * the line that fails to parse is as likely to be that one as any other.
145
+ * So only the message's first line survives — the parser's own prose — and
146
+ * the location is re-stated from `linePos`, which is numbers, not text.
147
+ * 2. Everything is then run through `redactSecret` and capped. The normalizer's
148
+ * own messages quote a url on an SSRF refusal, and a url can carry
149
+ * `user:pass@host` or a presigned query; that is precisely what the shared
150
+ * scrub takes out, and reusing it is what keeps one definition of "this must
151
+ * not reach a log" for the whole backend.
152
+ *
153
+ * What remains of the parser's prose still interpolates the odd token (`Missing
154
+ * , between flow map items`, `Unexpected , in flow collection`) — a structural
155
+ * character or a token type, never a value line. That is the point of the cut:
156
+ * the fault is described, the file is not quoted.
157
+ */
158
+ export function describeManualFault(err: unknown): string {
159
+ const raw = err instanceof Error ? err.message : String(err);
160
+ // `linePos` is the `yaml` package's own location, on the error object — the
161
+ // authority for WHERE, so the snippet never has to be read to find out.
162
+ const pos = (err as { linePos?: [{ line: number; col: number }, ...unknown[]] } | null)?.linePos?.[0];
163
+ // The prose, snippet dropped. `yaml` appends ` at line N, column M:` to it as
164
+ // the snippet's header; drop that too, since the location is restated below
165
+ // in a form that does not depend on the parser's phrasing.
166
+ const prose = raw.split('\n')[0].replace(/ at line \d+, column \d+:?$/, '').trim();
167
+ const located = pos ? `${prose} (line ${pos.line}, column ${pos.col})` : prose;
168
+ const scrubbed = redactSecret(located);
169
+ return scrubbed.length > MAX_REASON_LENGTH ? `${scrubbed.slice(0, MAX_REASON_LENGTH - 1)}…` : scrubbed;
170
+ }
171
+
172
+ /**
173
+ * One scan of the manuals on disk: what parsed, and what did not.
174
+ *
175
+ * The two travel TOGETHER, through the cache and out to every surface, because
176
+ * they are two halves of one answer. A caller handed only the manuals cannot
177
+ * tell a catalog of three tools from a catalog of four with one broken — which
178
+ * is exactly the confusion a silently-skipped file creates.
179
+ */
180
+ interface ScanResult {
181
+ manuals: ToolManualDescriptor[];
182
+ invalid: InvalidToolManual[];
183
+ }
184
+
185
+ /**
186
+ * The empty answer — a workspace that isn't there yet, or a caller who may read
187
+ * nothing. A FUNCTION, not a shared constant: the arrays in a scan result are
188
+ * handed to decoration passes and to the cache, and a single frozen-by-
189
+ * convention instance is one push away from every empty scan in the process
190
+ * inheriting another's contents.
191
+ */
192
+ const emptyScan = (): ScanResult => ({ manuals: [], invalid: [] });
193
+
99
194
  const manualSerializer = new UtcpManualSerializer();
100
195
  const callTemplateSerializer = new CallTemplateSerializer();
101
196
  // `findRequiredVariables` is a pure walk — one shared instance is fine.
@@ -142,13 +237,38 @@ export type McpAuthDiscoveryResult =
142
237
  * must never break because a `.tool` can't be read.
143
238
  */
144
239
  export class ToolManualService implements IToolManualService {
145
- private readonly cache: TtlCache<ToolManualDescriptor[]>;
240
+ private readonly cache: TtlCache<ScanResult>;
146
241
  private mcpAuthDiscovery?: McpAuthDiscoveryPort;
242
+ /**
243
+ * The refused set as it was last written to the log, so the warnings are
244
+ * logged ONCE PER CHANGE rather than once per scan. A broken `.tool` sits
245
+ * there until someone fixes it, and the catalog is re-scanned every minute on
246
+ * every surface — repeating the same three lines forever buries the scan that
247
+ * actually changed something. `null` until the first scan, so the first state
248
+ * is always reported.
249
+ */
250
+ private loggedInvalid: string | null = null;
251
+ /**
252
+ * The scan currently running, shared by everyone who asks while it runs.
253
+ *
254
+ * The TTL cache only holds a value once the scan RETURNS, so without this
255
+ * every caller arriving during the walk starts its own — and a listing that
256
+ * wants both halves of the catalog is exactly such a pair, as is a page that
257
+ * fires two requests. Sharing the promise makes one cold listing one disk
258
+ * walk, one MCP-discovery pass, and ONE snapshot for every reader of it.
259
+ * Cleared by `invalidate()` as well as on settle, so a caller arriving after
260
+ * a merge never inherits a scan that started on the tree it replaced — the
261
+ * same rule `TtlCache`'s generation token enforces for the cached value.
262
+ */
263
+ private inFlightScan: Promise<ScanResult> | null = null;
147
264
 
148
265
  constructor(
149
266
  private readonly workspaceService: WorkspaceService,
150
267
  private readonly accessControl: IAccessControl,
151
268
  private readonly kbDirName: string,
269
+ private readonly disk: ITreeWalker,
270
+ /** Where plugins (and their MCP servers) come from — the one discovery every catalog shares. */
271
+ private readonly source: PluginSource,
152
272
  now: () => number = Date.now,
153
273
  ) {
154
274
  this.cache = new TtlCache(CACHE_TTL_MS, now);
@@ -166,14 +286,24 @@ export class ToolManualService implements IToolManualService {
166
286
 
167
287
  invalidate(): void {
168
288
  this.cache.invalidate();
289
+ this.inFlightScan = null;
169
290
  }
170
291
 
171
292
  async listAccessible(userEmail: string): Promise<ToolManualSummary[]> {
172
293
  return (await this.accessibleManuals(userEmail)).map(toSummary);
173
294
  }
174
295
 
296
+ async listAccessibleCatalog(userEmail: string): Promise<AccessibleCatalog> {
297
+ const { manuals, invalid } = await this.accessibleScan(userEmail);
298
+ return { tools: manuals.map(toSummary), invalid };
299
+ }
300
+
175
301
  async listAllSummaries(): Promise<ToolManualSummary[]> {
176
- return (await this.scan()).map(toSummary);
302
+ return (await this.scan()).manuals.map(toSummary);
303
+ }
304
+
305
+ async catalogFingerprints(userEmail: string): Promise<string[]> {
306
+ return (await this.accessibleManuals(userEmail)).map(manualFingerprint);
177
307
  }
178
308
 
179
309
  async getDetail(userEmail: string, slug: string): Promise<ToolManualDetail | null> {
@@ -195,6 +325,41 @@ export class ToolManualService implements IToolManualService {
195
325
  return manuals.filter((m) => m.remote === false).map((m) => ({ slug: m.slug, name: m.name, path: m.path }));
196
326
  }
197
327
 
328
+ async listDeclaredOnlyOnBranch(
329
+ userEmail: string,
330
+ branch: string,
331
+ ): Promise<{ name: string; path: string; type: ToolManualType }[]> {
332
+ if (!branch || branch === DEFAULT_BRANCH) return [];
333
+ // Only a draft this process already holds a clone of — the one the caller
334
+ // wrote the declaration on. `scanDisk` would otherwise BOOTSTRAP any branch
335
+ // name a caller sends, before the read gate below has had a say: a clone
336
+ // and a fetch per guessed, private or nonexistent branch. A declaration on
337
+ // a branch nobody has checked out here is nothing this answer can report.
338
+ if (!(await this.workspaceService.hasBootstrappedWorkspace(workspaceIdForBranch(branch)))) return [];
339
+ // Names and paths only — `scanDisk` never probes a server, so asking about
340
+ // a draft costs no network and registers no OAuth client for a declaration
341
+ // that may never be merged.
342
+ const onBranch = (await this.scanDisk(branch)).manuals;
343
+ if (onBranch.length === 0) return [];
344
+ // Compared by NAMESPACE, the catalog's own identity (see the dedupe in
345
+ // `scanDisk`): a draft entry whose namespace the default branch already
346
+ // serves is an edit of a live tool, not a tool missing from the catalog.
347
+ const released = new Set((await this.scan()).manuals.map((m) => utcpNamespacePrefix(m.name)));
348
+ const pending = onBranch.filter((m) => !released.has(utcpNamespacePrefix(m.name)));
349
+ if (pending.length === 0) return [];
350
+ // Read-gated on the BRANCH's workspace, where the declaration lives — the
351
+ // same default-deny rule as the catalog, so this can't reveal a draft file
352
+ // the caller could not open with `read_file`.
353
+ const allowed = await this.accessControl.canReadBatch(
354
+ workspaceIdForBranch(branch),
355
+ userEmail,
356
+ pending.map((m) => m.path),
357
+ );
358
+ return pending
359
+ .filter((m) => allowed.get(m.path) === true)
360
+ .map((m) => ({ name: m.name, path: m.path, type: m.type }));
361
+ }
362
+
198
363
  async userScopedKeysForManual(
199
364
  manualName: string,
200
365
  ): Promise<
@@ -205,7 +370,7 @@ export class ToolManualService implements IToolManualService {
205
370
  // manual name doubled), so a readiness check reads the exact rows `resolve`
206
371
  // would. `oauth` lets the pre-check treat a not-yet-authorized sign-in as
207
372
  // still-missing.
208
- const manual = (await this.scan()).find((m) => m.name === manualName);
373
+ const manual = (await this.scan()).manuals.find((m) => m.name === manualName);
209
374
  return (manual?.variables ?? [])
210
375
  .filter((v) => v.scope === 'user')
211
376
  .map((v) => ({
@@ -226,7 +391,7 @@ export class ToolManualService implements IToolManualService {
226
391
  // the LONGEST prefix so a manual `a` can't shadow `a_b` when both exist. (A
227
392
  // plain first-underscore split would mis-parse a snake_case manual name.)
228
393
  let best: { manual: ToolManualDescriptor; varName: string; len: number } | null = null;
229
- for (const m of await this.scan()) {
394
+ for (const m of (await this.scan()).manuals) {
230
395
  const prefix = utcpNamespacePrefix(m.name);
231
396
  if (effectiveKey.startsWith(prefix) && (!best || prefix.length > best.len)) {
232
397
  best = { manual: m, varName: effectiveKey.slice(prefix.length), len: prefix.length };
@@ -264,9 +429,7 @@ export class ToolManualService implements IToolManualService {
264
429
  try {
265
430
  callTemplate = callTemplateSerializer.validateDict(this.buildCallTemplateDict(m));
266
431
  } catch (err) {
267
- console.warn(
268
- `[tool-manuals] no valid call template for "${m.path}": ${err instanceof Error ? err.message : String(err)}`,
269
- );
432
+ log.warn(`no valid call template for "${m.path}": ${err instanceof Error ? err.message : String(err)}`);
270
433
  }
271
434
  }
272
435
  return { name: m.name, type: m.type, remote: m.remote, healthCheck: m.healthCheck, callTemplate };
@@ -284,16 +447,14 @@ export class ToolManualService implements IToolManualService {
284
447
  } catch (err) {
285
448
  // A `.tool` that produces an invalid call-template is dropped here — at
286
449
  // the producing boundary — so the served list is always valid.
287
- console.warn(
288
- `[tool-manuals] skipping "${m.path}": ${err instanceof Error ? err.message : String(err)}`,
289
- );
450
+ log.warn(`skipping "${m.path}": ${err instanceof Error ? err.message : String(err)}`);
290
451
  }
291
452
  }
292
453
  return out;
293
454
  }
294
455
 
295
456
  async resolveInlineManual(userEmail: string, slug: string): Promise<UtcpManualDict | null> {
296
- const found = (await this.scan()).find((m) => m.slug === slug);
457
+ const found = (await this.scan()).manuals.find((m) => m.slug === slug);
297
458
  if (!found || found.type !== 'inline') return null;
298
459
  const wsId = workspaceIdForBranch(DEFAULT_BRANCH);
299
460
  if (!(await this.accessControl.canRead(wsId, userEmail, found.path))) return null;
@@ -409,29 +570,83 @@ export class ToolManualService implements IToolManualService {
409
570
  }
410
571
 
411
572
  private async accessibleManuals(userEmail: string): Promise<ToolManualDescriptor[]> {
412
- const manuals = await this.scan();
413
- if (manuals.length === 0) return [];
573
+ return (await this.accessibleScan(userEmail)).manuals;
574
+ }
575
+
576
+ /**
577
+ * The scan cut to what this caller may read — manuals AND refusals, through
578
+ * ONE `canReadBatch`. Both halves are paths in the same workspace judged by
579
+ * the same rule, and splitting them into two calls would pay a second
580
+ * round-trip to ask the same question.
581
+ */
582
+ private async accessibleScan(userEmail: string): Promise<ScanResult> {
583
+ const { manuals, invalid } = await this.scan();
584
+ if (manuals.length === 0 && invalid.length === 0) return emptyScan();
414
585
  const wsId = workspaceIdForBranch(DEFAULT_BRANCH);
415
- const allowed = await this.accessControl.canReadBatch(
416
- wsId,
417
- userEmail,
418
- manuals.map((m) => m.path),
419
- );
420
- // Fail closed: keep a manual only on an explicit `true` verdict (a missing
586
+ const allowed = await this.accessControl.canReadBatch(wsId, userEmail, [
587
+ ...new Set([...manuals.map((m) => m.path), ...invalid.map((i) => i.path)]),
588
+ ]);
589
+ // Fail closed: keep an entry only on an explicit `true` verdict (a missing
421
590
  // entry is treated as denied, matching the KB's default-deny read model).
422
- return manuals.filter((m) => allowed.get(m.path) === true);
591
+ // A REFUSED file is gated the same way a listed one is: its path is a fact
592
+ // about the knowledge base, and "there is a broken tool at this path" is
593
+ // not something to tell someone who may not read that path.
594
+ return {
595
+ manuals: manuals.filter((m) => allowed.get(m.path) === true),
596
+ invalid: invalid.filter((i) => allowed.get(i.path) === true),
597
+ };
423
598
  }
424
599
 
425
- private async scan(): Promise<ToolManualDescriptor[]> {
600
+ private async scan(): Promise<ScanResult> {
426
601
  const cached = this.cache.get();
427
602
  if (cached) return cached;
428
- const manuals = await this.scanDisk();
603
+ // See `inFlightScan`: the cache is populated only when the walk finishes,
604
+ // so between the miss above and that moment, callers share this promise
605
+ // instead of each starting a walk of their own.
606
+ if (this.inFlightScan) return this.inFlightScan;
607
+ const started = this.runScan().finally(() => {
608
+ // Only if it is still OURS: an `invalidate()` during the scan already
609
+ // cleared the field (and may have installed a newer scan), and this
610
+ // settle must not undo that.
611
+ if (this.inFlightScan === started) this.inFlightScan = null;
612
+ });
613
+ this.inFlightScan = started;
614
+ return started;
615
+ }
616
+
617
+ private async runScan(): Promise<ScanResult> {
618
+ // See `TtlCache.begin`: taken before the read so an `invalidate()` that
619
+ // lands mid-scan discards this result instead of being overwritten by it.
620
+ const token = this.cache.begin();
621
+ const { manuals, invalid } = await this.scanDisk();
429
622
  await this.decorateMcpOAuth(manuals);
430
623
  // AFTER the oauth decoration, so an injected `${MCP_OAUTH}` header ref is
431
624
  // already declared and isn't re-surfaced as a bare admin key.
432
625
  for (const m of manuals) this.surfaceReferencedVariables(m);
433
- this.cache.set(manuals);
434
- return manuals;
626
+ const result = { manuals, invalid };
627
+ this.cache.set(result, token);
628
+ return result;
629
+ }
630
+
631
+ /**
632
+ * Say what the scan refused — once per CHANGE, not once per scan. Every
633
+ * surface re-scans on its own TTL, so a file that stays broken would
634
+ * otherwise repeat these lines in the log forever and drown the scan where
635
+ * something actually moved. A fixed file is worth a line too: the set going
636
+ * empty is the recovery, said out loud.
637
+ */
638
+ private logInvalidOnChange(invalid: InvalidToolManual[]): void {
639
+ const signature = JSON.stringify(invalid);
640
+ if (signature === this.loggedInvalid) return;
641
+ const first = this.loggedInvalid === null;
642
+ this.loggedInvalid = signature;
643
+ // Both halves are author-written — a KB filename and a parser's words about
644
+ // a KB file — so both go through `printable`: a newline in either would
645
+ // otherwise forge a second log line, and an escape sequence would paint the
646
+ // operator's terminal.
647
+ // (`printable` quotes what it escapes, so the path keeps its quotes here.)
648
+ for (const i of invalid) log.warn(`skipping ${printable(i.path)}: ${printable(i.reason)}`);
649
+ if (invalid.length === 0 && !first) log.info('every `.tool` in the catalog parses again.');
435
650
  }
436
651
 
437
652
  /**
@@ -570,9 +785,7 @@ export class ToolManualService implements IToolManualService {
570
785
  ];
571
786
  } catch (err) {
572
787
  // Discovery must never break the catalog — the tool just stays bare.
573
- console.warn(
574
- `[tool-manuals] mcp auth discovery failed for "${m.path}": ${err instanceof Error ? err.message : String(err)}`,
575
- );
788
+ log.warn(`mcp auth discovery failed for "${m.path}": ${err instanceof Error ? err.message : String(err)}`);
576
789
  }
577
790
  }),
578
791
  ]);
@@ -628,24 +841,37 @@ export class ToolManualService implements IToolManualService {
628
841
  } catch (err) {
629
842
  // Never break the catalog — the sign-in just isn't ready yet.
630
843
  const msg = err instanceof Error ? err.message : String(err);
631
- console.warn(`[tool-manuals] sign-in endpoint discovery failed for "${m.path}": ${msg}`);
844
+ log.warn(`sign-in endpoint discovery failed for "${m.path}": ${msg}`);
632
845
  m.setup = { kind: 'oauth-manual', reason: `sign-in endpoint discovery failed: ${msg}` };
633
846
  }
634
847
  }
635
848
 
636
- private async scanDisk(): Promise<ToolManualDescriptor[]> {
849
+ /**
850
+ * Parse every declaration on `branch`'s workspace — the default branch for
851
+ * the catalog, a draft for `listDeclaredOnlyOnBranch`. Pure disk: no
852
+ * discovery, no access filter; callers add what their surface needs.
853
+ *
854
+ * ONE FILE'S FAULT IS ONE FILE'S FAULT. Every per-manual step below is
855
+ * contained — read, parse, validate, and the namespace dedup — so the answer
856
+ * is always "here is every manual that parses, and here is what the rest got
857
+ * wrong". There is no path through this loop on which a single bad `.tool`
858
+ * costs the catalog a manual that is fine, and nothing is remembered between
859
+ * calls: a refusal lives only in the scan it came from, so a fixed file is a
860
+ * valid manual on the very next scan.
861
+ */
862
+ private async scanDisk(branch: string = DEFAULT_BRANCH): Promise<ScanResult> {
637
863
  let wsId: string;
638
864
  try {
639
- wsId = (await this.workspaceService.getOrCreateForBranch(DEFAULT_BRANCH)).id;
865
+ wsId = (await this.workspaceService.getOrCreateForBranch(branch)).id;
640
866
  } catch {
641
- return [];
867
+ return emptyScan();
642
868
  }
643
869
  const kbRoot = path.join(await this.workspaceService.getWorkspacePath(wsId), this.kbDirName);
644
870
 
645
871
  // A `.tool` sits under `Plugins/`, beside the skills that use it.
646
872
  const files: { abs: string; rel: string }[] = [];
647
873
  const root = path.join(kbRoot, PLUGINS_DIR);
648
- for (const rel of await walkFiles(root, (n) => n.toLowerCase().endsWith('.tool'))) {
874
+ for (const rel of await this.disk.walkFiles(root, (n) => n.toLowerCase().endsWith('.tool'))) {
649
875
  files.push({ abs: path.join(root, rel), rel: `${PLUGINS_DIR}/${rel}` });
650
876
  }
651
877
 
@@ -654,46 +880,63 @@ export class ToolManualService implements IToolManualService {
654
880
  // shape. Listed BEFORE the `.tool` files: on a name collision (a legacy
655
881
  // mcp `.tool` the migration has not converted yet), the shared dedup keeps
656
882
  // the first occurrence, and the authoritative source must be the one kept.
883
+ // The plugins (and their mcp.json text) come from the configured source, so
884
+ // a dialect that expands servers from a registry lands here unchanged.
657
885
  const parsed: ToolManualDescriptor[] = [];
658
- let pluginFolders: string[] = [];
659
- try {
660
- pluginFolders = (await fs.readdir(root, { withFileTypes: true }))
661
- .filter((e) => e.isDirectory() && !e.name.startsWith('.'))
662
- .map((e) => e.name)
663
- .sort();
664
- } catch {
665
- /* no Plugins/ root — nothing to scan */
666
- }
667
- for (const folder of pluginFolders) {
668
- let mcpJson: string;
669
- try {
670
- mcpJson = await fs.readFile(path.join(root, folder, PLUGIN_MCP_FILE), 'utf-8');
671
- } catch {
672
- continue; // no mcp.json is the common case, not an error
886
+ const discovered = await this.source.discover(kbRoot);
887
+ for (const plugin of discovered.plugins) {
888
+ if (plugin.mcpJsonText === null) continue; // no servers is the common case, not an error
889
+ // One stamp for every server the file declares: the two texts together
890
+ // are the whole source of these descriptors, so any edit to either
891
+ // (a URL, a header, an added or dropped server, a `local: true` flip)
892
+ // moves every server's digest — which is correct, if slightly generous.
893
+ const from = sourceDigest(plugin.mcpJsonText + '\u0000' + (plugin.manifestText ?? ''));
894
+ for (const d of descriptorsFromMcpJson(plugin.relFolder, plugin.mcpJsonText, plugin.manifestText)) {
895
+ d.sourceRevision = from;
896
+ parsed.push(d);
673
897
  }
674
- const pluginJson = await fs
675
- .readFile(path.join(root, folder, PLUGIN_MANIFEST_FILE), 'utf-8')
676
- .catch(() => null);
677
- parsed.push(...descriptorsFromMcpJson(folder, mcpJson, pluginJson));
678
898
  }
679
899
 
900
+ const invalid: InvalidToolManual[] = [];
680
901
  for (const f of files) {
681
902
  let content: string;
682
903
  try {
683
904
  content = await fs.readFile(f.abs, 'utf-8');
684
- } catch {
905
+ } catch (err) {
906
+ // Not a malformed manual — a file the walk saw and the read could not
907
+ // open (deleted under us, a permission fault). Reported like one anyway:
908
+ // to the person looking for their tool, "it isn't here" needs a reason
909
+ // whichever step lost it.
910
+ //
911
+ // The CODE, not the message: an fs error quotes the absolute path it
912
+ // tried, which is this server's disk layout rather than anything about
913
+ // the knowledge base, and this string is handed to agents and browsers.
914
+ const code = (err as NodeJS.ErrnoException | null)?.code;
915
+ invalid.push({
916
+ path: f.rel,
917
+ reason: `the file could not be read${code ? ` (${code})` : ''} — it may have just been moved or deleted.`,
918
+ });
685
919
  continue;
686
920
  }
687
921
  let descriptor: ToolManualDescriptor;
688
922
  try {
689
923
  descriptor = normalizeToolManual(baseName(f.rel), f.rel, content);
690
- } catch {
691
- // A malformed `.tool` is skipped rather than breaking the catalog.
924
+ } catch (err) {
925
+ // A malformed `.tool` is skipped rather than breaking the catalog —
926
+ // and NAMED, rather than vanishing. Skipping in silence is the same
927
+ // outage from where the author stands: the tool is gone from every
928
+ // listing, with nothing anywhere saying which file or why.
929
+ invalid.push({ path: f.rel, reason: describeManualFault(err) });
692
930
  continue;
693
931
  }
694
932
  // The route slug IS the id (unique after dedup below, snake_case → URL-safe),
695
933
  // so the URL a user sees matches the tool's declared identity.
696
934
  descriptor.slug = descriptor.name;
935
+ // Stamped from the BYTES, here, before `decorateMcpOAuth` and
936
+ // `surfaceReferencedVariables` mutate the descriptor: those two derive
937
+ // from the network and from the file respectively, and a digest taken
938
+ // afterwards would move whenever an OAuth probe happened to fail.
939
+ descriptor.sourceRevision = sourceDigest(content);
697
940
  parsed.push(descriptor);
698
941
  }
699
942
  // The manual name (= its id) is the UTCP variable namespace secrets bind to, so
@@ -709,18 +952,70 @@ export class ToolManualService implements IToolManualService {
709
952
  // cannot contain a hyphen, but an mcp.json server name can, so the pair is
710
953
  // reachable — and the consequence is that two manuals share one set of
711
954
  // vault keys, with either able to resolve the other's secrets.
712
- return dedupeById(parsed, (m) => utcpNamespacePrefix(m.name), (m, ns) =>
713
- console.warn(
714
- `[tool-manuals] skipping "${m.path}": manual "${m.name}" resolves to the secret-variable ` +
715
- `namespace "${ns}", which another manual already uses. Names differing only in \`-\` vs \`_\` ` +
716
- 'share one namespace — rename one of them.',
717
- ),
955
+ const manuals = dedupeById(parsed, (m) => utcpNamespacePrefix(m.name), (m) =>
956
+ // A collision drops a manual from every surface just as surely as a parse
957
+ // error does, so it is reported the same way rather than only reaching a
958
+ // log that nobody browsing the catalog can see.
959
+ invalid.push({
960
+ path: m.path,
961
+ // Neither the manual's name nor the namespace it resolved to is
962
+ // repeated: both are the author's text put through a transform, and a
963
+ // reason carries none of it (see `describeManualFault`). `path` says
964
+ // which file, and the rule says what to look for in it.
965
+ reason:
966
+ 'this manual resolves to a secret-variable namespace another manual already uses. ' +
967
+ 'Names differing only in `-` vs `_` share one namespace — rename one of them.',
968
+ }),
718
969
  );
970
+ // Sorted so the refused set is a stable VALUE: the change-detecting log
971
+ // below compares one scan against the last, and two orderings of the same
972
+ // three faults are not a change worth repeating.
973
+ invalid.sort((a, b) => a.path.localeCompare(b.path));
974
+ // Only the CATALOG's scan talks. `listDeclaredOnlyOnBranch` re-scans a
975
+ // draft workspace, and a draft's half-written `.tool` is not news about the
976
+ // served catalog — it would also flap the log every time an agent saves.
977
+ if (branch === DEFAULT_BRANCH) this.logInvalidOnChange(invalid);
978
+ return { manuals, invalid };
719
979
  }
720
980
  }
721
981
 
722
982
  // --- helpers ------------------------------------------------------------------
723
983
 
984
+ /**
985
+ * A short digest of the text a descriptor was parsed from. Truncated because
986
+ * this is only ever compared for equality, and 128 bits of it is far past what
987
+ * a per-workspace catalog could collide in.
988
+ */
989
+ function sourceDigest(text: string): string {
990
+ return createHash('sha256').update(text).digest('hex').slice(0, 32);
991
+ }
992
+
993
+ /**
994
+ * One manual's line in the catalog fingerprint: what makes it the tool it is,
995
+ * plus the digest of the file it came from.
996
+ *
997
+ * The named fields rather than the whole descriptor, deliberately: `setup` and
998
+ * `variables` carry OAuth auto-discovery results, which are re-probed on every
999
+ * scan and can differ between two scans of an unchanged file — hashing them
1000
+ * would report a catalog change that no commit made. `sourceRevision` is what
1001
+ * covers everything else the file says, so nothing is lost by leaving the
1002
+ * decorated fields out.
1003
+ */
1004
+ function manualFingerprint(m: ToolManualDescriptor): string {
1005
+ return [
1006
+ m.slug,
1007
+ m.name,
1008
+ m.path,
1009
+ m.type,
1010
+ m.remote === false ? 'local' : 'remote',
1011
+ m.description ?? '',
1012
+ m.sourceRevision ?? '',
1013
+ // NUL-joined, like the skill lines this sits beside: no field can contain
1014
+ // one, so two different manuals can never render the same line by having
1015
+ // a separator inside one of their own fields.
1016
+ ].join('\u0000');
1017
+ }
1018
+
724
1019
  /**
725
1020
  * The one descriptor → summary projection, shared by every list surface
726
1021
  * (`listAccessible`, `listAllSummaries`, and the summary half of `getDetail`).
@@ -762,7 +1057,15 @@ function capabilitiesOf(m: ToolManualDescriptor): ToolCapability[] {
762
1057
  return out;
763
1058
  }
764
1059
 
765
- function baseName(rel: string): string {
1060
+ /**
1061
+ * A `.tool` file's PROVISIONAL slug — its filename without the extension, which
1062
+ * is what `normalizeToolManual` falls back to when the frontmatter names
1063
+ * nothing. It is not the served id: `scanDisk` overwrites `slug` with the
1064
+ * resolved manual `name` just below. Exported for the pending-tool surface,
1065
+ * which parses a `.tool` read at a change request's branch and must feed the
1066
+ * parser the same provisional value — and then resolve the slug the same way.
1067
+ */
1068
+ export function baseName(rel: string): string {
766
1069
  const base = rel.slice(rel.lastIndexOf('/') + 1);
767
1070
  return base.replace(/\.tool$/i, '');
768
1071
  }
@@ -824,7 +1127,12 @@ export function normalizeToolManual(
824
1127
  let name: string;
825
1128
  if (explicitId) {
826
1129
  if (!isValidId(explicitId)) {
827
- throw new Error(`tool id "${explicitId}" must be lowercase snake_case (letters, digits, underscores)`);
1130
+ // The rejected id is NOT quoted back — see `describeManualFault`: this
1131
+ // message becomes an `invalid[].reason` on an agent transcript, a browser
1132
+ // and a log, and `id` is a field an author can paste anything into,
1133
+ // including the token they meant for a header. The field name plus the
1134
+ // rule is what the author needs; the value is in front of them.
1135
+ throw new Error('tool `id` must be lowercase snake_case (letters, digits, underscores)');
828
1136
  }
829
1137
  name = explicitId;
830
1138
  } else {
@@ -836,14 +1144,15 @@ export function normalizeToolManual(
836
1144
  // code-mode client (internal token, connector creds, KB bearer).
837
1145
  if (RESERVED_TOOL_NAMESPACES.includes(name.toLowerCase())) {
838
1146
  throw new Error(
839
- `tool namespace "${name}" is reserved for a built-in manual — choose a different \`id\`/\`name\` ` +
840
- "(a `.tool` sharing a built-in namespace could read that manual's seeded credentials).",
1147
+ 'the tool namespace this file resolves to is reserved for a built-in manual — ' +
1148
+ "choose a different `id`/`name` (a `.tool` sharing a built-in namespace could read " +
1149
+ "that manual's seeded credentials).",
841
1150
  );
842
1151
  }
843
1152
 
844
1153
  // Any `.tool` content — url, headers, inline tool templates, notes — may not
845
1154
  // reference the platform-seeded variables.
846
- assertNoReservedVariableRefs(obj, name);
1155
+ assertNoReservedVariableRefs(obj);
847
1156
 
848
1157
  // The non-stdio constituent of the union, by name: `.tool` parsing can
849
1158
  // never produce a spawn spec, and the stdio side pins `remote: false`,
@@ -878,7 +1187,7 @@ export function normalizeToolManual(
878
1187
  if (containsCliCallTemplate(obj)) {
879
1188
  if (obj.remote === true) {
880
1189
  throw new Error(
881
- `\`.tool\` "${name}" declares \`remote: true\` but contains a \`cli\` call template — ` +
1190
+ 'this `.tool` declares `remote: true` but contains a `cli` call template — ' +
882
1191
  'shell tools execute only in a local runtime (drop `remote: true`, or the `cli` template).',
883
1192
  );
884
1193
  }
@@ -913,7 +1222,7 @@ export function normalizeToolManual(
913
1222
  // Local-only (`remote: false`) `.tool`s are never fetched server-side, so
914
1223
  // are exempt.
915
1224
  if (descriptor.remote !== false) {
916
- assertSafeManualFetchUrl(url, `\`.tool\` "${name}" url`);
1225
+ assertSafeManualFetchUrl(url, '`url`');
917
1226
  }
918
1227
  if (obj.headers && typeof obj.headers === 'object' && !Array.isArray(obj.headers)) {
919
1228
  descriptor.headers = obj.headers as Record<string, string>;
@@ -939,7 +1248,7 @@ export function normalizeToolManual(
939
1248
  type !== 'inline' && obj.headers && typeof obj.headers === 'object' && !Array.isArray(obj.headers)
940
1249
  ? (obj.headers as Record<string, string>)
941
1250
  : undefined;
942
- const healthCheck = normalizeHealthCheck(obj.healthCheck, name, descriptor.remote, declaredHeaders);
1251
+ const healthCheck = normalizeHealthCheck(obj.healthCheck, descriptor.remote, declaredHeaders);
943
1252
  if (healthCheck) descriptor.healthCheck = healthCheck;
944
1253
 
945
1254
  return descriptor;
@@ -1005,7 +1314,6 @@ function assertSafeManualFetchUrl(url: string, label: string): void {
1005
1314
  */
1006
1315
  function normalizeHealthCheck(
1007
1316
  raw: unknown,
1008
- manualName: string,
1009
1317
  remote: boolean | undefined,
1010
1318
  manualHeaders: Record<string, string> | undefined,
1011
1319
  ): ToolHealthCheck | undefined {
@@ -1015,7 +1323,7 @@ function normalizeHealthCheck(
1015
1323
  const url = typeof e.url === 'string' ? e.url.trim() : '';
1016
1324
  if (!url) throw new Error('`healthCheck` must have a `url`');
1017
1325
  if (remote !== false) {
1018
- assertSafeManualFetchUrl(url, `\`.tool\` "${manualName}" healthCheck.url`);
1326
+ assertSafeManualFetchUrl(url, '`healthCheck.url`');
1019
1327
  }
1020
1328
  const check: ToolHealthCheck = { url };
1021
1329
  if (e.method !== undefined) {
@@ -1048,9 +1356,18 @@ function normalizeHealthCheck(
1048
1356
  * what it is: a mistake in the `.tool` file.
1049
1357
  */
1050
1358
  function assertStringHeaders(headers: Record<string, unknown>, label: string): Record<string, string> {
1051
- for (const [k, v] of Object.entries(headers)) {
1359
+ // Located by POSITION, not by its key. A header name is text the author
1360
+ // wrote, and a refusal reason carries none of that — see
1361
+ // {@link describeManualFault}. The `.tool` has a handful of headers and the
1362
+ // reader is looking at the file, so an ordinal finds the line as surely as
1363
+ // the name would.
1364
+ const entries = Object.entries(headers);
1365
+ for (const [i, [, v]] of entries.entries()) {
1052
1366
  if (typeof v !== 'string') {
1053
- throw new Error(`\`${label}.${k}\` must be a string (quote it if it looks like a number)`);
1367
+ throw new Error(
1368
+ `\`${label}\` entry ${i + 1} of ${entries.length} must have a string value ` +
1369
+ '(quote it if it looks like a number)',
1370
+ );
1054
1371
  }
1055
1372
  }
1056
1373
  return headers as Record<string, string>;
@@ -1066,31 +1383,41 @@ function normalizeVariables(raw: unknown): ToolVariable[] {
1066
1383
  if (raw === undefined || raw === null) return [];
1067
1384
  if (!Array.isArray(raw)) throw new Error('`variables` must be an array');
1068
1385
  const seen = new Set<string>();
1069
- return raw.map((entry) => {
1386
+ return raw.map((entry, i) => {
1070
1387
  if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
1071
- throw new Error('each `variables` entry must be an object');
1388
+ throw new Error(`\`variables[${i}]\` must be an object`);
1072
1389
  }
1073
1390
  const e = entry as Record<string, unknown>;
1074
1391
  const name = typeof e.name === 'string' ? e.name.trim() : '';
1392
+ // EVERY refusal in this block is located by `variables[i]`, never by the
1393
+ // name the entry declared — passing `[A-Za-z0-9_]+` makes a string a legal
1394
+ // identifier, not a string this process may repeat. A token spelled with
1395
+ // underscores passes that test, and the field an author mis-pastes a token
1396
+ // into is not one we get to choose. See {@link describeManualFault}.
1397
+ const at = `\`variables[${i}]`;
1075
1398
  if (!/^[A-Za-z0-9_]+$/.test(name)) {
1076
- throw new Error(`variable name "${name}" must match [A-Za-z0-9_]+`);
1399
+ throw new Error(`${at}.name\` must match [A-Za-z0-9_]+`);
1077
1400
  }
1078
1401
  if (RESERVED_VARIABLE_NAMES.includes(name)) {
1079
- throw new Error(`variable name "${name}" is reserved for platform seeding and may not be declared by a \`.tool\``);
1402
+ // `name` is one of OURS here — matched against a fixed list — so saying
1403
+ // which reserved name was taken repeats nothing the file taught us.
1404
+ throw new Error(
1405
+ `${at}.name\` is "${name}", which is reserved for platform seeding and may not be declared by a \`.tool\``,
1406
+ );
1080
1407
  }
1081
- if (seen.has(name)) throw new Error(`duplicate variable "${name}"`);
1408
+ if (seen.has(name)) throw new Error(`${at}.name\` duplicates an earlier entry's`);
1082
1409
  seen.add(name);
1083
1410
  const rawScope = typeof e.scope === 'string' ? e.scope.toLowerCase().trim() : '';
1084
1411
  if (rawScope && rawScope !== 'admin' && rawScope !== 'user') {
1085
- throw new Error(`variable "${name}" has invalid scope "${e.scope}" (expected admin|user)`);
1412
+ throw new Error(`${at}.scope\` is invalid (expected admin|user)`);
1086
1413
  }
1087
1414
  const scope: ToolVariableScope = rawScope === 'user' ? 'user' : 'admin';
1088
1415
  const label = typeof e.label === 'string' && e.label.trim() ? e.label.trim() : undefined;
1089
- const oauth = normalizeVariableOAuth(name, e.oauth);
1416
+ const oauth = normalizeVariableOAuth(at, e.oauth);
1090
1417
  // OAuth is inherently per-caller — each user signs in for their own token. An
1091
1418
  // admin-shared OAuth token would leak one user's token to all callers.
1092
1419
  if (oauth && scope !== 'user') {
1093
- throw new Error(`variable "${name}" with oauth must be scope:user`);
1420
+ throw new Error(`${at}\` has \`oauth\`, so its \`scope\` must be \`user\``);
1094
1421
  }
1095
1422
  return {
1096
1423
  name,
@@ -1118,54 +1445,60 @@ function isProbeableMcpServer(m: ToolManualDescriptor): boolean {
1118
1445
  * `.tool` author can't aim a sign-in/token exchange at an internal host. Both
1119
1446
  * URLs are REQUIRED here: a `.tool` (http/inline) has no server whose OAuth
1120
1447
  * metadata could fill them in — that convenience belongs to mcp.json servers.
1448
+ *
1449
+ * `at` is the entry's position — `` `variables[2] `` with its opening backtick,
1450
+ * each message closing it after the field — rather than the variable's name.
1451
+ * Same rule as everywhere else a refusal is written: the reason locates the
1452
+ * fault in the file without repeating anything the file said. See
1453
+ * {@link describeManualFault}.
1121
1454
  */
1122
- function normalizeVariableOAuth(name: string, raw: unknown): ToolVariableOAuth | undefined {
1455
+ function normalizeVariableOAuth(at: string, raw: unknown): ToolVariableOAuth | undefined {
1123
1456
  if (raw === undefined || raw === null) return undefined;
1124
1457
  if (typeof raw !== 'object' || Array.isArray(raw)) {
1125
- throw new Error(`variable "${name}" oauth must be an object`);
1458
+ throw new Error(`${at}.oauth\` must be an object`);
1126
1459
  }
1127
1460
  const o = raw as Record<string, unknown>;
1128
1461
  // Confidential OAuth material is provisioned only through the protected
1129
1462
  // client-secret route; reject it here so a plaintext `.tool` can't smuggle one in.
1130
1463
  for (const forbidden of ['clientSecret', 'client_secret', 'secret']) {
1131
1464
  if (o[forbidden] !== undefined) {
1132
- throw new Error(`variable "${name}" oauth.${forbidden} must be set through the protected client-secret route`);
1465
+ throw new Error(`${at}.oauth.${forbidden}\` must be set through the protected client-secret route`);
1133
1466
  }
1134
1467
  }
1135
1468
  const safeUrl = (v: unknown, field: string): string => {
1136
1469
  const s = typeof v === 'string' ? v.trim() : '';
1137
1470
  try {
1138
- assertSafeFetchUrl(s, { requireHttps: true, label: `${name} oauth.${field}` });
1471
+ assertSafeFetchUrl(s, { requireHttps: true, label: `${at}.oauth.${field}\`` });
1139
1472
  } catch (err) {
1140
- throw new Error(err instanceof Error ? err.message : `variable "${name}" oauth.${field} invalid`);
1473
+ throw new Error(err instanceof Error ? err.message : `${at}.oauth.${field}\` is invalid`);
1141
1474
  }
1142
1475
  return s;
1143
1476
  };
1144
1477
  const authorizationUrl = safeUrl(o.authorizationUrl, 'authorizationUrl');
1145
1478
  const tokenUrl = safeUrl(o.tokenUrl, 'tokenUrl');
1146
1479
  const clientId = typeof o.clientId === 'string' && o.clientId.trim() ? o.clientId.trim() : '';
1147
- if (!clientId) throw new Error(`variable "${name}" oauth.clientId is required`);
1480
+ if (!clientId) throw new Error(`${at}.oauth.clientId\` is required`);
1148
1481
  let scopes: string[] | undefined;
1149
1482
  if (o.scopes !== undefined) {
1150
1483
  if (!Array.isArray(o.scopes) || !o.scopes.every((s) => typeof s === 'string')) {
1151
- throw new Error(`variable "${name}" oauth.scopes must be string[]`);
1484
+ throw new Error(`${at}.oauth.scopes\` must be string[]`);
1152
1485
  }
1153
1486
  scopes = o.scopes as string[];
1154
1487
  }
1155
1488
  let authParams: Record<string, string> | undefined;
1156
1489
  if (o.authParams !== undefined) {
1157
1490
  if (typeof o.authParams !== 'object' || Array.isArray(o.authParams)) {
1158
- throw new Error(`variable "${name}" oauth.authParams must be an object of string values`);
1491
+ throw new Error(`${at}.oauth.authParams\` must be an object of string values`);
1159
1492
  }
1160
1493
  const entries = Object.entries(o.authParams as Record<string, unknown>);
1161
1494
  if (!entries.every(([, v]) => typeof v === 'string')) {
1162
- throw new Error(`variable "${name}" oauth.authParams values must be strings`);
1495
+ throw new Error(`${at}.oauth.authParams\` values must be strings`);
1163
1496
  }
1164
1497
  authParams = Object.fromEntries(entries) as Record<string, string>;
1165
1498
  }
1166
1499
  // PKCE is on unless the file says `false`; only the opt-out is ever stored.
1167
1500
  if (o.pkce !== undefined && typeof o.pkce !== 'boolean') {
1168
- throw new Error(`variable "${name}" oauth.pkce must be a boolean`);
1501
+ throw new Error(`${at}.oauth.pkce\` must be a boolean`);
1169
1502
  }
1170
1503
  // Never fetched (it rides as a request param), but it names the remote
1171
1504
  // server — same https/SSRF bar as the endpoints.
@@ -1196,5 +1529,8 @@ function normalizeType(raw: unknown): ToolManualType {
1196
1529
  if (t === 'http') return 'http';
1197
1530
  if (t === 'mcp') return 'mcp';
1198
1531
  if (t === 'inline' || t === 'text' || t === '') return 'inline';
1199
- throw new Error(`unknown \`.tool\` type: ${raw}`);
1532
+ // The written value is not echoed (see the `id` refusal above): the accepted
1533
+ // set says more than the rejected value does, and a `type:` line is one
1534
+ // mis-paste away from holding a credential like any other.
1535
+ throw new Error('unknown `.tool` `type` (expected `http`, `mcp`, `inline`, or absent)');
1200
1536
  }