@bevel-software/platform-core-backend 0.33.0 → 0.35.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 (602) hide show
  1. package/agent-guide/access-control.md +146 -289
  2. package/agent-guide/conventions.md +23 -25
  3. package/agent-guide/directory-structure.md +72 -120
  4. package/agent-guide/drafts-and-change-requests.md +92 -0
  5. package/agent-guide/for-git-users.md +47 -0
  6. package/agent-guide/glossary.md +36 -0
  7. package/agent-guide/how-agents-find-things.md +49 -0
  8. package/agent-guide/html-views.md +239 -8
  9. package/agent-guide/new-knowledge-base.md +9 -8
  10. package/agent-guide/skills.md +67 -42
  11. package/agent-guide/start-here.md +65 -0
  12. package/agent-guide/tool-manuals.md +133 -155
  13. package/agent-guide/tools.md +67 -0
  14. package/agent-guide/where-a-new-file-goes.md +45 -28
  15. package/dist/core/catalog-revision.d.ts +12 -1
  16. package/dist/core/catalog-revision.d.ts.map +1 -1
  17. package/dist/core/catalog-revision.js +23 -3
  18. package/dist/core/catalog-revision.js.map +1 -1
  19. package/dist/core/core-ports.d.ts +41 -0
  20. package/dist/core/core-ports.d.ts.map +1 -1
  21. package/dist/core/core-ports.js.map +1 -1
  22. package/dist/core/create-core-server.d.ts.map +1 -1
  23. package/dist/core/create-core-server.js +15 -8
  24. package/dist/core/create-core-server.js.map +1 -1
  25. package/dist/core/create-core-services.d.ts +22 -5
  26. package/dist/core/create-core-services.d.ts.map +1 -1
  27. package/dist/core/create-core-services.js +44 -16
  28. package/dist/core/create-core-services.js.map +1 -1
  29. package/dist/core/lifecycle.d.ts +16 -0
  30. package/dist/core/lifecycle.d.ts.map +1 -1
  31. package/dist/core/lifecycle.js +12 -2
  32. package/dist/core/lifecycle.js.map +1 -1
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js.map +1 -1
  36. package/dist/modules/access/access-control.interface.d.ts +39 -9
  37. package/dist/modules/access/access-control.interface.d.ts.map +1 -1
  38. package/dist/modules/access/access-control.service.d.ts +15 -3
  39. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  40. package/dist/modules/access/access-control.service.js +239 -75
  41. package/dist/modules/access/access-control.service.js.map +1 -1
  42. package/dist/modules/access/access-mutation.service.d.ts +22 -24
  43. package/dist/modules/access/access-mutation.service.d.ts.map +1 -1
  44. package/dist/modules/access/access-mutation.service.js +48 -51
  45. package/dist/modules/access/access-mutation.service.js.map +1 -1
  46. package/dist/modules/access/access-view.d.ts.map +1 -1
  47. package/dist/modules/access/access-view.js +12 -11
  48. package/dist/modules/access/access-view.js.map +1 -1
  49. package/dist/modules/access/access.routes.d.ts +3 -0
  50. package/dist/modules/access/access.routes.d.ts.map +1 -1
  51. package/dist/modules/access/access.routes.js +58 -33
  52. package/dist/modules/access/access.routes.js.map +1 -1
  53. package/dist/modules/access/groups-admin.routes.d.ts.map +1 -1
  54. package/dist/modules/access/groups-admin.routes.js +4 -2
  55. package/dist/modules/access/groups-admin.routes.js.map +1 -1
  56. package/dist/modules/access/groups-admin.service.d.ts +44 -13
  57. package/dist/modules/access/groups-admin.service.d.ts.map +1 -1
  58. package/dist/modules/access/groups-admin.service.js +80 -38
  59. package/dist/modules/access/groups-admin.service.js.map +1 -1
  60. package/dist/modules/access/groups-edit.d.ts +1 -1
  61. package/dist/modules/access/groups-edit.d.ts.map +1 -1
  62. package/dist/modules/access/groups-edit.js +1 -1
  63. package/dist/modules/access/groups-edit.js.map +1 -1
  64. package/dist/modules/access/index.d.ts +1 -1
  65. package/dist/modules/access/index.d.ts.map +1 -1
  66. package/dist/modules/access/reference-scan.d.ts +116 -24
  67. package/dist/modules/access/reference-scan.d.ts.map +1 -1
  68. package/dist/modules/access/reference-scan.js +305 -44
  69. package/dist/modules/access/reference-scan.js.map +1 -1
  70. package/dist/modules/access/roles-admin.service.d.ts +17 -8
  71. package/dist/modules/access/roles-admin.service.d.ts.map +1 -1
  72. package/dist/modules/access/roles-admin.service.js +32 -23
  73. package/dist/modules/access/roles-admin.service.js.map +1 -1
  74. package/dist/modules/access-model/access-grammar.d.ts +35 -10
  75. package/dist/modules/access-model/access-grammar.d.ts.map +1 -1
  76. package/dist/modules/access-model/access-grammar.js +60 -20
  77. package/dist/modules/access-model/access-grammar.js.map +1 -1
  78. package/dist/modules/access-model/access-splice.d.ts +22 -18
  79. package/dist/modules/access-model/access-splice.d.ts.map +1 -1
  80. package/dist/modules/access-model/access-splice.js +20 -14
  81. package/dist/modules/access-model/access-splice.js.map +1 -1
  82. package/dist/modules/access-model/group-files.d.ts +1 -0
  83. package/dist/modules/access-model/group-files.d.ts.map +1 -1
  84. package/dist/modules/access-model/group-files.js +5 -1
  85. package/dist/modules/access-model/group-files.js.map +1 -1
  86. package/dist/modules/agent-guide/agent-guide.d.ts +47 -7
  87. package/dist/modules/agent-guide/agent-guide.d.ts.map +1 -1
  88. package/dist/modules/agent-guide/agent-guide.js +103 -13
  89. package/dist/modules/agent-guide/agent-guide.js.map +1 -1
  90. package/dist/modules/agent-guide/agent-guide.tools.d.ts +6 -2
  91. package/dist/modules/agent-guide/agent-guide.tools.d.ts.map +1 -1
  92. package/dist/modules/agent-guide/agent-guide.tools.js +46 -22
  93. package/dist/modules/agent-guide/agent-guide.tools.js.map +1 -1
  94. package/dist/modules/agent-guide/guide-budget.d.ts +48 -0
  95. package/dist/modules/agent-guide/guide-budget.d.ts.map +1 -0
  96. package/dist/modules/agent-guide/guide-budget.js +67 -0
  97. package/dist/modules/agent-guide/guide-budget.js.map +1 -0
  98. package/dist/modules/agent-guide/index.d.ts +2 -1
  99. package/dist/modules/agent-guide/index.d.ts.map +1 -1
  100. package/dist/modules/agent-guide/index.js +2 -1
  101. package/dist/modules/agent-guide/index.js.map +1 -1
  102. package/dist/modules/agent-instructions/compose.d.ts +3 -1
  103. package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
  104. package/dist/modules/agent-instructions/compose.js +7 -1
  105. package/dist/modules/agent-instructions/compose.js.map +1 -1
  106. package/dist/modules/agent-instructions/shared-file-rules.d.ts +5 -1
  107. package/dist/modules/agent-instructions/shared-file-rules.d.ts.map +1 -1
  108. package/dist/modules/agent-instructions/shared-file-rules.js +26 -9
  109. package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -1
  110. package/dist/modules/agent-scope/agent-scope.contract.d.ts +67 -0
  111. package/dist/modules/agent-scope/agent-scope.contract.d.ts.map +1 -0
  112. package/dist/modules/agent-scope/agent-scope.contract.js +27 -0
  113. package/dist/modules/agent-scope/agent-scope.contract.js.map +1 -0
  114. package/dist/modules/agent-scope/connection-scope.d.ts +111 -0
  115. package/dist/modules/agent-scope/connection-scope.d.ts.map +1 -0
  116. package/dist/modules/agent-scope/connection-scope.js +165 -0
  117. package/dist/modules/agent-scope/connection-scope.js.map +1 -0
  118. package/dist/modules/agent-scope/index.d.ts +3 -0
  119. package/dist/modules/agent-scope/index.d.ts.map +1 -0
  120. package/dist/modules/agent-scope/index.js +3 -0
  121. package/dist/modules/agent-scope/index.js.map +1 -0
  122. package/dist/modules/audit/agent-audit.service.d.ts.map +1 -1
  123. package/dist/modules/audit/agent-audit.service.js +2 -0
  124. package/dist/modules/audit/agent-audit.service.js.map +1 -1
  125. package/dist/modules/audit/audit.contract.d.ts +6 -0
  126. package/dist/modules/audit/audit.contract.d.ts.map +1 -1
  127. package/dist/modules/audit/audit.contract.js.map +1 -1
  128. package/dist/modules/auth/account-admission.d.ts +12 -0
  129. package/dist/modules/auth/account-admission.d.ts.map +1 -1
  130. package/dist/modules/auth/account-admission.js +15 -0
  131. package/dist/modules/auth/account-admission.js.map +1 -1
  132. package/dist/modules/auth/auth.middleware.d.ts +27 -1
  133. package/dist/modules/auth/auth.middleware.d.ts.map +1 -1
  134. package/dist/modules/auth/auth.middleware.js +42 -4
  135. package/dist/modules/auth/auth.middleware.js.map +1 -1
  136. package/dist/modules/auth/auth.routes.d.ts +13 -9
  137. package/dist/modules/auth/auth.routes.d.ts.map +1 -1
  138. package/dist/modules/auth/auth.routes.js +35 -29
  139. package/dist/modules/auth/auth.routes.js.map +1 -1
  140. package/dist/modules/auth/auth.service.d.ts +55 -6
  141. package/dist/modules/auth/auth.service.d.ts.map +1 -1
  142. package/dist/modules/auth/auth.service.js +128 -34
  143. package/dist/modules/auth/auth.service.js.map +1 -1
  144. package/dist/modules/auth/index.d.ts +1 -1
  145. package/dist/modules/auth/index.d.ts.map +1 -1
  146. package/dist/modules/auth/index.js +1 -1
  147. package/dist/modules/auth/index.js.map +1 -1
  148. package/dist/modules/auth/oidc-auth-provider.d.ts.map +1 -1
  149. package/dist/modules/auth/oidc-auth-provider.js +2 -9
  150. package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
  151. package/dist/modules/code-mode/code-mode.tool.js +2 -2
  152. package/dist/modules/code-mode/code-mode.tool.js.map +1 -1
  153. package/dist/modules/connection-probe/connection-probe.service.d.ts +0 -12
  154. package/dist/modules/connection-probe/connection-probe.service.d.ts.map +1 -1
  155. package/dist/modules/connection-probe/connection-probe.service.js +1 -38
  156. package/dist/modules/connection-probe/connection-probe.service.js.map +1 -1
  157. package/dist/modules/database/core-schema.d.ts +68 -0
  158. package/dist/modules/database/core-schema.d.ts.map +1 -1
  159. package/dist/modules/database/core-schema.js +33 -0
  160. package/dist/modules/database/core-schema.js.map +1 -1
  161. package/dist/modules/declared-variables/declared-variables.routes.d.ts +8 -1
  162. package/dist/modules/declared-variables/declared-variables.routes.d.ts.map +1 -1
  163. package/dist/modules/declared-variables/declared-variables.routes.js +13 -2
  164. package/dist/modules/declared-variables/declared-variables.routes.js.map +1 -1
  165. package/dist/modules/embed/embed.tools.d.ts.map +1 -1
  166. package/dist/modules/embed/embed.tools.js +5 -0
  167. package/dist/modules/embed/embed.tools.js.map +1 -1
  168. package/dist/modules/kb-fs/index.d.ts +2 -0
  169. package/dist/modules/kb-fs/index.d.ts.map +1 -1
  170. package/dist/modules/kb-fs/index.js +1 -0
  171. package/dist/modules/kb-fs/index.js.map +1 -1
  172. package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
  173. package/dist/modules/kb-fs/locking-filesystem.js +7 -1
  174. package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
  175. package/dist/modules/kb-fs/repo-path.d.ts +26 -6
  176. package/dist/modules/kb-fs/repo-path.d.ts.map +1 -1
  177. package/dist/modules/kb-fs/repo-path.js +22 -7
  178. package/dist/modules/kb-fs/repo-path.js.map +1 -1
  179. package/dist/modules/kb-fs/tmp-ref.d.ts +36 -0
  180. package/dist/modules/kb-fs/tmp-ref.d.ts.map +1 -0
  181. package/dist/modules/kb-fs/tmp-ref.js +76 -0
  182. package/dist/modules/kb-fs/tmp-ref.js.map +1 -0
  183. package/dist/modules/mcp/mcp-auth.middleware.d.ts +7 -0
  184. package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
  185. package/dist/modules/mcp/mcp-auth.middleware.js +14 -1
  186. package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
  187. package/dist/modules/mcp/mcp.routes.d.ts +7 -1
  188. package/dist/modules/mcp/mcp.routes.d.ts.map +1 -1
  189. package/dist/modules/mcp/mcp.routes.js +39 -4
  190. package/dist/modules/mcp/mcp.routes.js.map +1 -1
  191. package/dist/modules/mcp/mcp.service.d.ts +11 -0
  192. package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
  193. package/dist/modules/mcp/mcp.service.js +74 -48
  194. package/dist/modules/mcp/mcp.service.js.map +1 -1
  195. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +24 -1
  196. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
  197. package/dist/modules/mcp/oauth/bevel-oauth-provider.js +45 -10
  198. package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
  199. package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts +9 -0
  200. package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts.map +1 -1
  201. package/dist/modules/mcp/oauth/oauth-consent.routes.js +34 -1
  202. package/dist/modules/mcp/oauth/oauth-consent.routes.js.map +1 -1
  203. package/dist/modules/plugins/index.d.ts +1 -1
  204. package/dist/modules/plugins/index.d.ts.map +1 -1
  205. package/dist/modules/plugins/index.js.map +1 -1
  206. package/dist/modules/plugins/plugin-links.d.ts +18 -2
  207. package/dist/modules/plugins/plugin-links.d.ts.map +1 -1
  208. package/dist/modules/plugins/plugin-links.js.map +1 -1
  209. package/dist/modules/plugins/plugins.routes.d.ts +5 -1
  210. package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
  211. package/dist/modules/plugins/plugins.routes.js +32 -5
  212. package/dist/modules/plugins/plugins.routes.js.map +1 -1
  213. package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts +11 -1
  214. package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts.map +1 -1
  215. package/dist/modules/secrets-vault/db-secrets-vault.service.js +159 -24
  216. package/dist/modules/secrets-vault/db-secrets-vault.service.js.map +1 -1
  217. package/dist/modules/secrets-vault/index.d.ts +1 -1
  218. package/dist/modules/secrets-vault/index.d.ts.map +1 -1
  219. package/dist/modules/secrets-vault/index.js +1 -1
  220. package/dist/modules/secrets-vault/index.js.map +1 -1
  221. package/dist/modules/secrets-vault/secrets-vault.contract.d.ts +53 -11
  222. package/dist/modules/secrets-vault/secrets-vault.contract.d.ts.map +1 -1
  223. package/dist/modules/secrets-vault/secrets-vault.contract.js +27 -0
  224. package/dist/modules/secrets-vault/secrets-vault.contract.js.map +1 -1
  225. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +9 -0
  226. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
  227. package/dist/modules/secrets-vault/secrets-vault.routes.js +100 -42
  228. package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
  229. package/dist/modules/settings/oidc-check.d.ts.map +1 -1
  230. package/dist/modules/settings/oidc-check.js +5 -17
  231. package/dist/modules/settings/oidc-check.js.map +1 -1
  232. package/dist/modules/skills/index.d.ts +3 -3
  233. package/dist/modules/skills/index.d.ts.map +1 -1
  234. package/dist/modules/skills/index.js +0 -2
  235. package/dist/modules/skills/index.js.map +1 -1
  236. package/dist/modules/skills/skills.contract.d.ts +16 -0
  237. package/dist/modules/skills/skills.contract.d.ts.map +1 -1
  238. package/dist/modules/skills/skills.service.d.ts.map +1 -1
  239. package/dist/modules/skills/skills.service.js +6 -1
  240. package/dist/modules/skills/skills.service.js.map +1 -1
  241. package/dist/modules/skills/skills.tools.d.ts.map +1 -1
  242. package/dist/modules/skills/skills.tools.js +25 -13
  243. package/dist/modules/skills/skills.tools.js.map +1 -1
  244. package/dist/modules/tool-auth/external-api-key.interface.d.ts +11 -0
  245. package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -1
  246. package/dist/modules/tool-auth/external-api-key.interface.js.map +1 -1
  247. package/dist/modules/tool-auth/external-api-key.service.d.ts +1 -0
  248. package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
  249. package/dist/modules/tool-auth/external-api-key.service.js +4 -1
  250. package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
  251. package/dist/modules/tool-auth/index.d.ts +1 -1
  252. package/dist/modules/tool-auth/index.d.ts.map +1 -1
  253. package/dist/modules/tool-auth/internal-token.service.d.ts +9 -0
  254. package/dist/modules/tool-auth/internal-token.service.d.ts.map +1 -1
  255. package/dist/modules/tool-auth/internal-token.service.js +1 -0
  256. package/dist/modules/tool-auth/internal-token.service.js.map +1 -1
  257. package/dist/modules/tool-auth/tool-auth.middleware.d.ts +27 -3
  258. package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
  259. package/dist/modules/tool-auth/tool-auth.middleware.js +32 -6
  260. package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
  261. package/dist/modules/tool-helpers/tool-context.d.ts +7 -0
  262. package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -1
  263. package/dist/modules/tool-helpers/tool-context.js +3 -0
  264. package/dist/modules/tool-helpers/tool-context.js.map +1 -1
  265. package/dist/modules/tool-helpers/tool-def.js +1 -1
  266. package/dist/modules/tool-helpers/tool-def.js.map +1 -1
  267. package/dist/modules/tool-helpers/tool-handler.d.ts +15 -0
  268. package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -1
  269. package/dist/modules/tool-helpers/tool-handler.js +19 -0
  270. package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
  271. package/dist/modules/tool-helpers/tool.contract.d.ts +10 -0
  272. package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
  273. package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
  274. package/dist/modules/tool-helpers/validate-token.d.ts +3 -1
  275. package/dist/modules/tool-helpers/validate-token.d.ts.map +1 -1
  276. package/dist/modules/tool-helpers/validate-token.js +1 -1
  277. package/dist/modules/tool-helpers/validate-token.js.map +1 -1
  278. package/dist/modules/tool-manuals/index.d.ts +3 -3
  279. package/dist/modules/tool-manuals/index.d.ts.map +1 -1
  280. package/dist/modules/tool-manuals/index.js +0 -2
  281. package/dist/modules/tool-manuals/index.js.map +1 -1
  282. package/dist/modules/tool-manuals/mcp-json-discovery.d.ts +7 -1
  283. package/dist/modules/tool-manuals/mcp-json-discovery.d.ts.map +1 -1
  284. package/dist/modules/tool-manuals/mcp-json-discovery.js +69 -38
  285. package/dist/modules/tool-manuals/mcp-json-discovery.js.map +1 -1
  286. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +46 -6
  287. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
  288. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +7 -1
  289. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
  290. package/dist/modules/tool-manuals/tool-manuals.routes.js +41 -4
  291. package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
  292. package/dist/modules/tool-manuals/tool-manuals.service.d.ts +24 -13
  293. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
  294. package/dist/modules/tool-manuals/tool-manuals.service.js +138 -59
  295. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
  296. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +8 -2
  297. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
  298. package/dist/modules/tool-manuals/tool-manuals.tools.js +56 -20
  299. package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
  300. package/dist/modules/tool-registry/manual.routes.d.ts +8 -1
  301. package/dist/modules/tool-registry/manual.routes.d.ts.map +1 -1
  302. package/dist/modules/tool-registry/manual.routes.js +27 -7
  303. package/dist/modules/tool-registry/manual.routes.js.map +1 -1
  304. package/dist/modules/tool-registry/tool.contract.d.ts +7 -0
  305. package/dist/modules/tool-registry/tool.contract.d.ts.map +1 -1
  306. package/dist/modules/tool-registry/tool.contract.js.map +1 -1
  307. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  308. package/dist/modules/workflow/agent-tools/workflow.tools.js +36 -27
  309. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  310. package/dist/modules/workflow/git/git.service.d.ts +2 -2
  311. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  312. package/dist/modules/workflow/git/git.service.js +20 -35
  313. package/dist/modules/workflow/git/git.service.js.map +1 -1
  314. package/dist/modules/workflow/workflow.service.d.ts +2 -1
  315. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  316. package/dist/modules/workflow/workflow.service.js +3 -0
  317. package/dist/modules/workflow/workflow.service.js.map +1 -1
  318. package/dist/modules/workspace/agent-access.gate.d.ts +1 -1
  319. package/dist/modules/workspace/agent-access.gate.d.ts.map +1 -1
  320. package/dist/modules/workspace/agent-access.gate.js +1 -1
  321. package/dist/modules/workspace/agent-access.gate.js.map +1 -1
  322. package/dist/modules/workspace/file-readers/doc-extract.service.d.ts +28 -4
  323. package/dist/modules/workspace/file-readers/doc-extract.service.d.ts.map +1 -1
  324. package/dist/modules/workspace/file-readers/doc-extract.service.js +61 -40
  325. package/dist/modules/workspace/file-readers/doc-extract.service.js.map +1 -1
  326. package/dist/modules/workspace/index.d.ts +8 -0
  327. package/dist/modules/workspace/index.d.ts.map +1 -1
  328. package/dist/modules/workspace/index.js +8 -0
  329. package/dist/modules/workspace/index.js.map +1 -1
  330. package/dist/modules/workspace/nul-scan.d.ts +19 -0
  331. package/dist/modules/workspace/nul-scan.d.ts.map +1 -0
  332. package/dist/modules/workspace/nul-scan.js +55 -0
  333. package/dist/modules/workspace/nul-scan.js.map +1 -0
  334. package/dist/modules/workspace/pattern-matcher.contract.d.ts +110 -27
  335. package/dist/modules/workspace/pattern-matcher.contract.d.ts.map +1 -1
  336. package/dist/modules/workspace/pattern-matcher.contract.js +30 -13
  337. package/dist/modules/workspace/pattern-matcher.contract.js.map +1 -1
  338. package/dist/modules/workspace/ripgrep-search.d.ts +54 -0
  339. package/dist/modules/workspace/ripgrep-search.d.ts.map +1 -0
  340. package/dist/modules/workspace/ripgrep-search.js +657 -0
  341. package/dist/modules/workspace/ripgrep-search.js.map +1 -0
  342. package/dist/modules/workspace/ripgrep-version.d.ts +15 -0
  343. package/dist/modules/workspace/ripgrep-version.d.ts.map +1 -0
  344. package/dist/modules/workspace/ripgrep-version.js +31 -0
  345. package/dist/modules/workspace/ripgrep-version.js.map +1 -0
  346. package/dist/modules/workspace/startup/beside-checkout.d.ts +8 -5
  347. package/dist/modules/workspace/startup/beside-checkout.d.ts.map +1 -1
  348. package/dist/modules/workspace/startup/beside-checkout.js +14 -5
  349. package/dist/modules/workspace/startup/beside-checkout.js.map +1 -1
  350. package/dist/modules/workspace/worker-pool.d.ts +3 -4
  351. package/dist/modules/workspace/worker-pool.d.ts.map +1 -1
  352. package/dist/modules/workspace/worker-pool.js.map +1 -1
  353. package/dist/modules/workspace/workspace-tmp.d.ts +146 -0
  354. package/dist/modules/workspace/workspace-tmp.d.ts.map +1 -0
  355. package/dist/modules/workspace/workspace-tmp.js +435 -0
  356. package/dist/modules/workspace/workspace-tmp.js.map +1 -0
  357. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  358. package/dist/modules/workspace/workspace.routes.js +5 -26
  359. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  360. package/dist/modules/workspace/workspace.service.d.ts +47 -6
  361. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  362. package/dist/modules/workspace/workspace.service.js +86 -6
  363. package/dist/modules/workspace/workspace.service.js.map +1 -1
  364. package/dist/modules/workspace/workspace.tools.d.ts +3 -2
  365. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  366. package/dist/modules/workspace/workspace.tools.js +531 -137
  367. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  368. package/dist/shared/oauth-token-error.d.ts +23 -0
  369. package/dist/shared/oauth-token-error.d.ts.map +1 -0
  370. package/dist/shared/oauth-token-error.js +47 -0
  371. package/dist/shared/oauth-token-error.js.map +1 -0
  372. package/dist/shared/path-order.d.ts +28 -8
  373. package/dist/shared/path-order.d.ts.map +1 -1
  374. package/dist/shared/path-order.js +37 -8
  375. package/dist/shared/path-order.js.map +1 -1
  376. package/dist/shared/read-capped.d.ts +19 -0
  377. package/dist/shared/read-capped.d.ts.map +1 -0
  378. package/dist/shared/read-capped.js +45 -0
  379. package/dist/shared/read-capped.js.map +1 -0
  380. package/migrations/0022_session_version.sql +6 -0
  381. package/migrations/0023_agent_path.sql +3 -0
  382. package/migrations/meta/0022_snapshot.json +2360 -0
  383. package/migrations/meta/0023_snapshot.json +2378 -0
  384. package/migrations/meta/_journal.json +14 -0
  385. package/package.json +4 -3
  386. package/src/__tests__/hexis-catalog.ts +144 -0
  387. package/src/__tests__/pg-scratch.test.ts +69 -0
  388. package/src/__tests__/pg-scratch.ts +31 -0
  389. package/src/__tests__/real-disk.ts +21 -0
  390. package/src/__tests__/slow-ripgrep.ts +65 -0
  391. package/src/__tests__/tokens.ts +19 -0
  392. package/src/__tests__/tool-manuals.ts +32 -0
  393. package/src/__tests__/tool-wiring.ts +25 -0
  394. package/src/core/__tests__/boot-without-ripgrep.test.ts +34 -0
  395. package/src/core/__tests__/catalog-revision.test.ts +89 -0
  396. package/src/core/__tests__/damaged-document.tools.test.ts +2 -2
  397. package/src/core/__tests__/gated-boot.test.ts +8 -1
  398. package/src/core/__tests__/lifecycle.test.ts +46 -13
  399. package/src/core/__tests__/oauth-sign-in-real-file.test.ts +179 -0
  400. package/src/core/catalog-revision.ts +24 -2
  401. package/src/core/core-ports.ts +42 -0
  402. package/src/core/create-core-server.ts +14 -1
  403. package/src/core/create-core-services.ts +62 -15
  404. package/src/core/lifecycle.ts +26 -2
  405. package/src/index.ts +1 -1
  406. package/src/modules/access/__tests__/access-control.admin-root-floor.test.ts +12 -0
  407. package/src/modules/access/__tests__/access-control.colliding-name-cases.test.ts +113 -0
  408. package/src/modules/access/__tests__/access-control.frontmatter-head.test.ts +117 -0
  409. package/src/modules/access/__tests__/access-control.group-named-admin.test.ts +122 -0
  410. package/src/modules/access/__tests__/access-control.preview-relocation.test.ts +50 -0
  411. package/src/modules/access/__tests__/access-declarations.test.ts +19 -0
  412. package/src/modules/access/__tests__/access-groups.test.ts +55 -22
  413. package/src/modules/access/__tests__/access-mutation.service.test.ts +85 -59
  414. package/src/modules/access/__tests__/access-restrict-here.test.ts +7 -5
  415. package/src/modules/access/__tests__/access.routes.admins.test.ts +1 -0
  416. package/src/modules/access/__tests__/access.routes.batch.test.ts +2 -0
  417. package/src/modules/access/__tests__/access.routes.folder-governs.test.ts +2 -0
  418. package/src/modules/access/__tests__/access.routes.group-grant.test.ts +50 -14
  419. package/src/modules/access/__tests__/access.routes.overrides.test.ts +2 -1
  420. package/src/modules/access/__tests__/access.routes.proposal-branch.test.ts +1 -0
  421. package/src/modules/access/__tests__/access.routes.prospective.test.ts +52 -10
  422. package/src/modules/access/__tests__/access.routes.revoke.test.ts +18 -13
  423. package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +2 -0
  424. package/src/modules/access/__tests__/grant-sources.test.ts +20 -15
  425. package/src/modules/access/__tests__/groups-admin.routes.test.ts +61 -0
  426. package/src/modules/access/__tests__/groups-admin.service.test.ts +211 -18
  427. package/src/modules/access/__tests__/holder-changes.test.ts +127 -0
  428. package/src/modules/access/__tests__/reference-scan.test.ts +366 -14
  429. package/src/modules/access/__tests__/roles-admin.security.test.ts +1 -1
  430. package/src/modules/access/__tests__/roles-admin.service.test.ts +43 -22
  431. package/src/modules/access/__tests__/roles-capabilities.test.ts +6 -2
  432. package/src/modules/access/__tests__/roles.routes.test.ts +1 -1
  433. package/src/modules/access/access-control.interface.ts +43 -10
  434. package/src/modules/access/access-control.service.ts +250 -72
  435. package/src/modules/access/access-mutation.service.ts +48 -53
  436. package/src/modules/access/access-view.ts +12 -10
  437. package/src/modules/access/access.routes.ts +66 -37
  438. package/src/modules/access/groups-admin.routes.ts +4 -2
  439. package/src/modules/access/groups-admin.service.ts +114 -44
  440. package/src/modules/access/groups-edit.ts +1 -1
  441. package/src/modules/access/index.ts +1 -1
  442. package/src/modules/access/reference-scan.ts +319 -46
  443. package/src/modules/access/roles-admin.service.ts +43 -26
  444. package/src/modules/access/synced-groups-writer.ts +1 -1
  445. package/src/modules/access-model/__tests__/access-grammar.test.ts +38 -1
  446. package/src/modules/access-model/__tests__/access-splice.test.ts +50 -8
  447. package/src/modules/access-model/access-grammar.ts +65 -20
  448. package/src/modules/access-model/access-splice.ts +31 -23
  449. package/src/modules/access-model/group-files.ts +5 -0
  450. package/src/modules/agent-guide/__tests__/agent-guide.test.ts +110 -25
  451. package/src/modules/agent-guide/__tests__/agent-guide.tools.test.ts +38 -11
  452. package/src/modules/agent-guide/__tests__/guide-budget.test.ts +95 -0
  453. package/src/modules/agent-guide/__tests__/guide-eval.test.ts +182 -0
  454. package/src/modules/agent-guide/__tests__/guide-matches-code.test.ts +263 -0
  455. package/src/modules/agent-guide/__tests__/tool-surface.json +514 -0
  456. package/src/modules/agent-guide/__tests__/tool-surface.test.ts +75 -0
  457. package/src/modules/agent-guide/agent-guide.tools.ts +51 -22
  458. package/src/modules/agent-guide/agent-guide.ts +120 -13
  459. package/src/modules/agent-guide/guide-budget.ts +73 -0
  460. package/src/modules/agent-guide/index.ts +12 -0
  461. package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +5 -4
  462. package/src/modules/agent-instructions/compose.ts +7 -1
  463. package/src/modules/agent-instructions/shared-file-rules.ts +27 -9
  464. package/src/modules/agent-scope/__tests__/agent-surfaces.connect-as.test.ts +421 -0
  465. package/src/modules/agent-scope/__tests__/connection-scope.test.ts +46 -0
  466. package/src/modules/agent-scope/__tests__/in-memory-kb.ts +148 -0
  467. package/src/modules/agent-scope/agent-scope.contract.ts +83 -0
  468. package/src/modules/agent-scope/connection-scope.ts +199 -0
  469. package/src/modules/agent-scope/index.ts +15 -0
  470. package/src/modules/audit/agent-audit.service.ts +2 -0
  471. package/src/modules/audit/audit.contract.ts +6 -0
  472. package/src/modules/auth/__tests__/auth.middleware.test.ts +30 -2
  473. package/src/modules/auth/__tests__/auth.routes.test.ts +71 -5
  474. package/src/modules/auth/__tests__/auth.service.test.ts +90 -9
  475. package/src/modules/auth/__tests__/password-change-sessions.pg.test.ts +269 -0
  476. package/src/modules/auth/account-admission.ts +19 -0
  477. package/src/modules/auth/auth.middleware.ts +45 -4
  478. package/src/modules/auth/auth.routes.ts +46 -29
  479. package/src/modules/auth/auth.service.ts +135 -34
  480. package/src/modules/auth/index.ts +2 -0
  481. package/src/modules/auth/oidc-auth-provider.ts +2 -9
  482. package/src/modules/code-mode/code-mode.tool.ts +2 -2
  483. package/src/modules/connection-probe/__tests__/connection-probe.service.test.ts +5 -24
  484. package/src/modules/connection-probe/connection-probe.service.ts +1 -34
  485. package/src/modules/database/__tests__/session-version-migration.pg.test.ts +133 -0
  486. package/src/modules/database/core-schema.ts +33 -0
  487. package/src/modules/declared-variables/__tests__/declared-variables.route.test.ts +44 -1
  488. package/src/modules/declared-variables/declared-variables.routes.ts +12 -1
  489. package/src/modules/embed/__tests__/embed.tools.test.ts +12 -0
  490. package/src/modules/embed/embed.tools.ts +5 -0
  491. package/src/modules/kb-fs/__tests__/locking-filesystem.test.ts +25 -0
  492. package/src/modules/kb-fs/__tests__/repo-path.test.ts +53 -8
  493. package/src/modules/kb-fs/index.ts +2 -0
  494. package/src/modules/kb-fs/locking-filesystem.ts +7 -1
  495. package/src/modules/kb-fs/repo-path.ts +33 -7
  496. package/src/modules/kb-fs/tmp-ref.ts +81 -0
  497. package/src/modules/mcp/__tests__/connect-as.pg.test.ts +137 -0
  498. package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +29 -5
  499. package/src/modules/mcp/__tests__/mcp-routes-harness.ts +8 -0
  500. package/src/modules/mcp/__tests__/mcp.connect-as.test.ts +195 -0
  501. package/src/modules/mcp/__tests__/mcp.routes.connect-as.test.ts +192 -0
  502. package/src/modules/mcp/__tests__/oauth-consent.connect-as.test.ts +146 -0
  503. package/src/modules/mcp/mcp-auth.middleware.ts +19 -2
  504. package/src/modules/mcp/mcp.routes.ts +39 -3
  505. package/src/modules/mcp/mcp.service.ts +112 -52
  506. package/src/modules/mcp/oauth/bevel-oauth-provider.ts +46 -8
  507. package/src/modules/mcp/oauth/oauth-consent.routes.ts +41 -1
  508. package/src/modules/plugins/__tests__/plugins.tools.test.ts +38 -2
  509. package/src/modules/plugins/index.ts +1 -1
  510. package/src/modules/plugins/plugin-links.ts +19 -2
  511. package/src/modules/plugins/plugins.routes.ts +35 -4
  512. package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +113 -0
  513. package/src/modules/secrets-vault/__tests__/db-secrets-vault.oauth.test.ts +430 -3
  514. package/src/modules/secrets-vault/__tests__/oauth-live-declaration.route.test.ts +218 -0
  515. package/src/modules/secrets-vault/__tests__/oauth-return-to.route.test.ts +39 -6
  516. package/src/modules/secrets-vault/db-secrets-vault.service.ts +170 -27
  517. package/src/modules/secrets-vault/index.ts +1 -1
  518. package/src/modules/secrets-vault/secrets-vault.contract.ts +61 -11
  519. package/src/modules/secrets-vault/secrets-vault.routes.ts +114 -42
  520. package/src/modules/settings/oidc-check.ts +5 -18
  521. package/src/modules/skills/__tests__/skills.service.test.ts +34 -0
  522. package/src/modules/skills/index.ts +7 -2
  523. package/src/modules/skills/skills.contract.ts +17 -0
  524. package/src/modules/skills/skills.service.ts +5 -1
  525. package/src/modules/skills/skills.tools.ts +45 -14
  526. package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +4 -0
  527. package/src/modules/tool-auth/external-api-key.interface.ts +11 -1
  528. package/src/modules/tool-auth/external-api-key.service.ts +5 -2
  529. package/src/modules/tool-auth/index.ts +1 -1
  530. package/src/modules/tool-auth/internal-token.service.ts +10 -0
  531. package/src/modules/tool-auth/tool-auth.middleware.ts +45 -3
  532. package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +19 -11
  533. package/src/modules/tool-helpers/__tests__/can-write.tools.test.ts +3 -1
  534. package/src/modules/tool-helpers/__tests__/route-tool-schemas.catalog.test.ts +38 -0
  535. package/src/modules/tool-helpers/tool-context.ts +10 -0
  536. package/src/modules/tool-helpers/tool-def.ts +1 -1
  537. package/src/modules/tool-helpers/tool-handler.ts +34 -0
  538. package/src/modules/tool-helpers/tool.contract.ts +10 -0
  539. package/src/modules/tool-helpers/validate-token.ts +4 -2
  540. package/src/modules/tool-manuals/__tests__/tool-manuals.archive.route.test.ts +80 -4
  541. package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +197 -11
  542. package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +42 -0
  543. package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +99 -8
  544. package/src/modules/tool-manuals/index.ts +6 -2
  545. package/src/modules/tool-manuals/mcp-json-discovery.ts +73 -34
  546. package/src/modules/tool-manuals/tool-manuals.contract.ts +40 -6
  547. package/src/modules/tool-manuals/tool-manuals.routes.ts +40 -3
  548. package/src/modules/tool-manuals/tool-manuals.service.ts +169 -61
  549. package/src/modules/tool-manuals/tool-manuals.tools.ts +81 -25
  550. package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +6 -113
  551. package/src/modules/tool-registry/manual.routes.ts +26 -5
  552. package/src/modules/tool-registry/tool.contract.ts +7 -0
  553. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +1 -1
  554. package/src/modules/workflow/__tests__/workflow.service.sync.test.ts +1 -1
  555. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +54 -3
  556. package/src/modules/workflow/agent-tools/workflow.tools.ts +36 -27
  557. package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +130 -3
  558. package/src/modules/workflow/git/git.service.ts +29 -48
  559. package/src/modules/workflow/workflow.service.ts +5 -0
  560. package/src/modules/workspace/__tests__/git-internals.security.test.ts +2 -2
  561. package/src/modules/workspace/__tests__/holds-nul.test.ts +66 -0
  562. package/src/modules/workspace/__tests__/rest-tool-arguments.test.ts +3 -3
  563. package/src/modules/workspace/__tests__/ripgrep-search.test.ts +570 -0
  564. package/src/modules/workspace/__tests__/ripgrep-version.test.ts +29 -0
  565. package/src/modules/workspace/__tests__/workspace-tmp.tools.test.ts +928 -0
  566. package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +17 -37
  567. package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +20 -8
  568. package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +10 -12
  569. package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +22 -10
  570. package/src/modules/workspace/__tests__/workspace.tools.test.ts +549 -162
  571. package/src/modules/workspace/agent-access.gate.ts +1 -1
  572. package/src/modules/workspace/file-readers/__tests__/doc-extract.service.test.ts +10 -0
  573. package/src/modules/workspace/file-readers/doc-extract.service.ts +71 -38
  574. package/src/modules/workspace/index.ts +20 -0
  575. package/src/modules/workspace/nul-scan.ts +50 -0
  576. package/src/modules/workspace/pattern-matcher.contract.ts +123 -32
  577. package/src/modules/workspace/ripgrep-search.ts +715 -0
  578. package/src/modules/workspace/ripgrep-version.ts +35 -0
  579. package/src/modules/workspace/startup/__tests__/beside-checkout.test.ts +11 -0
  580. package/src/modules/workspace/startup/beside-checkout.ts +13 -5
  581. package/src/modules/workspace/worker-pool.ts +3 -4
  582. package/src/modules/workspace/workspace-tmp.ts +457 -0
  583. package/src/modules/workspace/workspace.routes.ts +6 -27
  584. package/src/modules/workspace/workspace.service.ts +92 -15
  585. package/src/modules/workspace/workspace.tools.ts +574 -176
  586. package/src/shared/__tests__/read-capped.test.ts +68 -0
  587. package/src/shared/oauth-token-error.ts +46 -0
  588. package/src/shared/path-order.ts +37 -8
  589. package/src/shared/read-capped.ts +40 -0
  590. package/starter-packs/engineering/Plugins/engineering-starter/access.md +1 -1
  591. package/starter-packs/general/Plugins/general-starter/access.md +1 -1
  592. package/starter-packs/operations/Plugins/operations-starter/access.md +1 -1
  593. package/starter-packs/sales/Plugins/sales-starter/access.md +1 -1
  594. package/starter-packs/support/Plugins/support-starter/access.md +1 -1
  595. package/agent-guide/finding-things.md +0 -7
  596. package/agent-guide/introduction.md +0 -27
  597. package/dist/modules/workspace/bounded-matcher.d.ts +0 -73
  598. package/dist/modules/workspace/bounded-matcher.d.ts.map +0 -1
  599. package/dist/modules/workspace/bounded-matcher.js +0 -200
  600. package/dist/modules/workspace/bounded-matcher.js.map +0 -1
  601. package/src/modules/workspace/__tests__/bounded-matcher.test.ts +0 -213
  602. package/src/modules/workspace/bounded-matcher.ts +0 -271
@@ -199,10 +199,16 @@ export class BevelOAuthProvider implements OAuthServerProvider {
199
199
  * Called by the Finish endpoint once an authenticated user completes the
200
200
  * /connect step: bind a one-time code to (user, client, redirect_uri, PKCE
201
201
  * challenge) and hand back the client redirect the browser should follow.
202
+ *
203
+ * @param agentPath The "Connect as" choice — an agent configuration the consent
204
+ * route has already checked the person may choose — or null for
205
+ * Everything. Carried on the code to the exchange, which records it on
206
+ * the agent connection.
202
207
  */
203
208
  async issueAuthCode(
204
209
  userId: string,
205
210
  st: McpAuthRequestState,
211
+ agentPath: string | null = null,
206
212
  ): Promise<{ redirectTo: string }> {
207
213
  // A state without a PKCE challenge is a Claude-link request, which the
208
214
  // marketplace bridge finishes; it must never reach the SDK's code store.
@@ -217,6 +223,7 @@ export class BevelOAuthProvider implements OAuthServerProvider {
217
223
  scope: st.sc ?? null,
218
224
  resource: st.rs ?? null,
219
225
  expiresAt: new Date(Date.now() + CODE_TTL_MS),
226
+ ...(agentPath ? { agentPath } : {}),
220
227
  });
221
228
  const redirect = new URL(st.r);
222
229
  redirect.searchParams.set('code', code);
@@ -269,7 +276,7 @@ export class BevelOAuthProvider implements OAuthServerProvider {
269
276
  if (redirectUri && redirectUri !== row.redirectUri) {
270
277
  throw new InvalidGrantError('redirect_uri does not match the authorization request');
271
278
  }
272
- return this.mintTokens(row.userId, row.clientId, row.scope, row.resource);
279
+ return this.mintTokens(row.userId, row.clientId, row.scope, row.resource, undefined, undefined, row.agentPath ?? null);
273
280
  }
274
281
 
275
282
  async exchangeRefreshToken(
@@ -463,6 +470,7 @@ export class BevelOAuthProvider implements OAuthServerProvider {
463
470
  id: oauthTokens.id,
464
471
  clientId: oauthTokens.clientId,
465
472
  connectionId: oauthTokens.connectionId,
473
+ agentPath: agentConnections.agentPath,
466
474
  scope: oauthTokens.scope,
467
475
  resource: oauthTokens.resource,
468
476
  expiresAt: oauthTokens.expiresAt,
@@ -507,6 +515,10 @@ export class BevelOAuthProvider implements OAuthServerProvider {
507
515
  // Null on a token minted before connections existed; the auth
508
516
  // middleware then binds no agent and the call goes unrecorded.
509
517
  connectionId: row.connectionId,
518
+ // The connection's "Connect as" choice, read off the row on every
519
+ // verification, so a re-consent with another choice reaches the
520
+ // agent's very next request. Null is Everything.
521
+ agentPath: row.agentPath ?? null,
510
522
  },
511
523
  };
512
524
  }
@@ -575,6 +587,9 @@ export class BevelOAuthProvider implements OAuthServerProvider {
575
587
  * first mint, which finds or makes the live connection for (user, client).
576
588
  * @param tx The transaction the insert belongs to, when the mint must land
577
589
  * with the statement that consumed the token it replaces (a refresh).
590
+ * @param agentPath The consent's "Connect as" choice, recorded on the
591
+ * connection the pair is bound to (null: Everything). Only a first mint —
592
+ * a consent — passes it; a refresh leaves the connection's choice alone.
578
593
  * The prune is then the caller's, before the transaction opens: a
579
594
  * best-effort statement that fails inside a transaction would abort the
580
595
  * mint it is meant to spare, and one on the pool from inside it would
@@ -587,6 +602,7 @@ export class BevelOAuthProvider implements OAuthServerProvider {
587
602
  resource: string | null,
588
603
  connectionId?: string,
589
604
  tx?: Tx,
605
+ agentPath?: string | null,
590
606
  ): Promise<OAuthTokens> {
591
607
  const accessToken = this.deps.tokenPrefix + randomBytes(TOKEN_BYTES).toString('base64url');
592
608
  const refreshToken = this.refreshPrefix + randomBytes(TOKEN_BYTES).toString('base64url');
@@ -594,7 +610,7 @@ export class BevelOAuthProvider implements OAuthServerProvider {
594
610
  // A mint of its own (a sign-in) prunes here; a refresh pruned before its
595
611
  // transaction opened.
596
612
  if (!tx) await this.pruneTokenTables(now);
597
- const boundTo = connectionId ?? (await this.ensureConnection(userId, clientId));
613
+ const boundTo = connectionId ?? (await this.ensureConnection(userId, clientId, agentPath));
598
614
  const sink: Tx | Database = tx ?? this.deps.db;
599
615
  await sink.insert(oauthTokens).values({
600
616
  accessTokenHash: hashToken(accessToken),
@@ -665,12 +681,23 @@ export class BevelOAuthProvider implements OAuthServerProvider {
665
681
  * revoke. A read, not a write: the use is stamped separately, throttled.
666
682
  */
667
683
  async isConnectionLive(connectionId: string): Promise<boolean> {
684
+ return (await this.liveConnectionChoice(connectionId)) !== null;
685
+ }
686
+
687
+ /**
688
+ * A live agent connection's current "Connect as" choice (`agentPath` null
689
+ * = Everything), or null when the connection is gone or revoked. Read on
690
+ * every request through the local server's exchanged grant: that token is
691
+ * stateless and outlives a re-consent, so the choice it was minted with is
692
+ * not the one it is served as — the row's is.
693
+ */
694
+ async liveConnectionChoice(connectionId: string): Promise<{ agentPath: string | null } | null> {
668
695
  const [row] = await this.deps.db
669
- .select({ id: agentConnections.id })
696
+ .select({ agentPath: agentConnections.agentPath })
670
697
  .from(agentConnections)
671
698
  .where(and(eq(agentConnections.id, connectionId), isNull(agentConnections.revokedAt)))
672
699
  .limit(1);
673
- return row !== undefined;
700
+ return row ? { agentPath: row.agentPath ?? null } : null;
674
701
  }
675
702
 
676
703
  /**
@@ -737,8 +764,13 @@ export class BevelOAuthProvider implements OAuthServerProvider {
737
764
  * the other's `ON CONFLICT DO NOTHING` returns no row, and it re-reads the
738
765
  * winner's. The client's display name is snapshotted from its registration
739
766
  * at that moment.
767
+ *
768
+ * `agentPath` is a consent's "Connect as" choice: written on the row made,
769
+ * and on the live row found — the person's latest consent is what the agent
770
+ * connects as. `undefined` (a refresh of a token from before connections
771
+ * existed) leaves a found row's choice as it is.
740
772
  */
741
- private async ensureConnection(userId: string, clientId: string): Promise<string> {
773
+ private async ensureConnection(userId: string, clientId: string, agentPath?: string | null): Promise<string> {
742
774
  const [client] = await this.deps.db
743
775
  .select({ clientName: oauthClients.clientName })
744
776
  .from(oauthClients)
@@ -758,11 +790,17 @@ export class BevelOAuthProvider implements OAuthServerProvider {
758
790
  ),
759
791
  )
760
792
  .limit(1);
793
+ const choose = async (id: string): Promise<string> => {
794
+ if (agentPath !== undefined) {
795
+ await this.deps.db.update(agentConnections).set({ agentPath }).where(eq(agentConnections.id, id));
796
+ }
797
+ return id;
798
+ };
761
799
  const [existing] = await live();
762
- if (existing) return existing.id;
800
+ if (existing) return choose(existing.id);
763
801
  const [inserted] = await this.deps.db
764
802
  .insert(agentConnections)
765
- .values({ userId, clientId, clientName, agentKey })
803
+ .values({ userId, clientId, clientName, agentKey, ...(agentPath ? { agentPath } : {}) })
766
804
  .onConflictDoNothing({
767
805
  target: [agentConnections.userId, agentConnections.agentKey],
768
806
  where: sql`${agentConnections.revokedAt} is null`,
@@ -771,7 +809,7 @@ export class BevelOAuthProvider implements OAuthServerProvider {
771
809
  if (inserted) return inserted.id;
772
810
  const [winner] = await live();
773
811
  if (!winner) throw new Error('agent connection vanished between insert and re-read');
774
- return winner.id;
812
+ return choose(winner.id);
775
813
  }
776
814
  }
777
815
 
@@ -4,6 +4,7 @@ import { logger } from '../../../shared/logging.js';
4
4
  const log = logger('mcp-oauth');
5
5
  import type { BevelOAuthProvider } from './bevel-oauth-provider.js';
6
6
  import { verifyAuthRequest, type McpAuthRequestState } from './oauth-state.js';
7
+ import type { IAgentScopeResolver } from '../../agent-scope/index.js';
7
8
  import '../../auth/index.js'; // Express Request augmentation (req.userId / req.userEmail)
8
9
 
9
10
  export interface OAuthConsentRoutesDeps {
@@ -21,8 +22,17 @@ export interface OAuthConsentRoutesDeps {
21
22
  clientNameFor(st: McpAuthRequestState): string;
22
23
  completeConsent(userId: string, st: McpAuthRequestState): Promise<{ redirectTo: string }>;
23
24
  };
25
+ /**
26
+ * The "Connect as" choices: the agent configurations the person may connect an
27
+ * MCP client as, offered below Everything. Absent, the consent offers
28
+ * Everything alone and Finish refuses any other choice.
29
+ */
30
+ agents?: Pick<IAgentScopeResolver, 'listChoices' | 'choosable'>;
24
31
  }
25
32
 
33
+ /** The refusal of a choice that is not one of the person's — one answer for missing and unreadable. */
34
+ export const NOT_AN_AGENT_CHOICE = 'That agent is not one you can connect as. Choose Everything or one of the agents listed.';
35
+
26
36
  /**
27
37
  * The authenticated tail of the MCP OAuth flow. `/authorize` (SDK-owned)
28
38
  * validated the client's request, packed it into a signed state, and sent the
@@ -49,10 +59,25 @@ export function createOAuthConsentRoutes(deps: OAuthConsentRoutesDeps): express.
49
59
  return;
50
60
  }
51
61
  const client = await deps.provider.clientsStore.getClient(st.c);
62
+ // Everything is not in the list: it is the choice every consent has, and
63
+ // the one the page selects. A failure to read the agents costs the choice
64
+ // of an agent, never the consent itself — but it is SAID
65
+ // (`agentsUnavailable`), so the page does not pass an empty list off as
66
+ // "you have no agents" and approve Everything unasked.
67
+ let agentsUnavailable = false;
68
+ const agents = deps.agents && req.userEmail
69
+ ? await deps.agents.listChoices(req.userEmail).catch((err: unknown) => {
70
+ log.warn('listing the agents to connect as failed:', { detail: err instanceof Error ? err.message : String(err) });
71
+ agentsUnavailable = true;
72
+ return [];
73
+ })
74
+ : [];
52
75
  res.json({
53
76
  clientName: client?.client_name ?? null,
54
77
  scope: st.sc ?? null,
55
78
  resource: st.rs ?? null,
79
+ agents,
80
+ ...(agentsUnavailable ? { agentsUnavailable: true } : {}),
56
81
  });
57
82
  });
58
83
 
@@ -65,10 +90,25 @@ export function createOAuthConsentRoutes(deps: OAuthConsentRoutesDeps): express.
65
90
  const st = raw ? verifyAuthRequest(deps.stateSecret, raw) : null;
66
91
  if (!st) return void res.status(400).json({ error: 'Invalid or expired authorization request. Restart the connection from your agent.' });
67
92
  if (st.gh && !deps.facade) return void res.status(400).json({ error: NO_FACADE });
93
+ // "Connect as": absent, null or empty is Everything. Anything else must be
94
+ // an agent the person may choose right now — checked here, at the only
95
+ // place a choice is made, so the token exchange records it as given.
96
+ const asked: unknown = (req.body ?? {}).agentPath;
97
+ if (asked !== undefined && asked !== null && typeof asked !== 'string') {
98
+ return void res.status(400).json({ error: NOT_AN_AGENT_CHOICE });
99
+ }
100
+ const choosing = typeof asked === 'string' && asked.trim() !== '';
101
+ // An account linked through the GitHub facade has no agent connection to
102
+ // record a choice on.
103
+ if (choosing && (st.gh || !deps.agents || !req.userEmail)) {
104
+ return void res.status(400).json({ error: NOT_AN_AGENT_CHOICE });
105
+ }
68
106
  try {
107
+ const agentPath = choosing && deps.agents && req.userEmail ? await deps.agents.choosable(req.userEmail, asked as string) : null;
108
+ if (choosing && agentPath === null) return void res.status(400).json({ error: NOT_AN_AGENT_CHOICE });
69
109
  const { redirectTo } = st.gh && deps.facade
70
110
  ? await deps.facade.completeConsent(userId, st)
71
- : await deps.provider.issueAuthCode(userId, st);
111
+ : await deps.provider.issueAuthCode(userId, st, agentPath);
72
112
  res.json({ redirectTo });
73
113
  } catch (err) {
74
114
  // Message only — the raw error object can carry sensitive context
@@ -13,6 +13,8 @@ import { GUIDE_FIRST_SENTENCE } from '../../tool-registry/guide-first.js';
13
13
  import { registerPluginsTools, CREATE_PLUGIN, myPluginDef, myPluginDescription } from '../plugins.tools.js';
14
14
  import { createPluginCreationRoutes } from '../plugins.routes.js';
15
15
  import { PluginProvisionError } from '../plugin-provision.service.js';
16
+ import type { IAgentScopeResolver } from '../../agent-scope/index.js';
17
+ import { agentFile, agentScopeOver, inMemoryKb } from '../../agent-scope/__tests__/in-memory-kb.js';
16
18
 
17
19
  /**
18
20
  * The plugin tools are DESCRIPTIONS of the app's own creation endpoints.
@@ -200,7 +202,12 @@ describe('the creation endpoints behind the key-or-session gate', () => {
200
202
 
201
203
  const externalApiKeyService = {
202
204
  looksLikeExternalApiKey: (t: string) => typeof t === 'string' && t.startsWith('bevel_'),
203
- verifyAndLoadToken: async (t: string) => (t === 'bevel_alice' ? { user: ALICE, tokenId: 'tok-a' } : null),
205
+ verifyAndLoadToken: async (t: string) =>
206
+ t === 'bevel_alice'
207
+ ? { user: ALICE, tokenId: 'tok-a' }
208
+ : t === 'bevel_alice_agent'
209
+ ? { user: ALICE, tokenId: 'tok-b', agentPath: 'Agents/plugin-maker.agent' }
210
+ : null,
204
211
  } as never;
205
212
  const authService = {
206
213
  getUserById: async (id: string) => (id === ALICE.id ? ALICE : null),
@@ -211,7 +218,7 @@ describe('the creation endpoints behind the key-or-session gate', () => {
211
218
  },
212
219
  } as never;
213
220
 
214
- async function start(): Promise<string> {
221
+ async function start(agentScope?: Pick<IAgentScopeResolver, 'resolve'>): Promise<string> {
215
222
  const internalToken = new InternalTokenService({ secret: 'test-secret' });
216
223
  const app = express();
217
224
  app.use(express.json());
@@ -224,6 +231,7 @@ describe('the creation endpoints behind the key-or-session gate', () => {
224
231
  }),
225
232
  createPluginCreationRoutes({ ensurePersonalPlugin, createPlugin } as never, async (req) =>
226
233
  req.userId ? ((await (authService as { getUserById(id: string): Promise<unknown> }).getUserById(req.userId)) as never) : null,
234
+ agentScope,
227
235
  ),
228
236
  );
229
237
  httpServer = await new Promise<HttpServer>((r) => {
@@ -302,4 +310,32 @@ describe('the creation endpoints behind the key-or-session gate', () => {
302
310
  );
303
311
  expect(createPlugin).not.toHaveBeenCalled();
304
312
  });
313
+
314
+ it("refuses a connection made as an .agent that does not list the tool, by name, before anything is provisioned", async () => {
315
+ // The agent lists `my_plugin` only. These routes are not hosted by
316
+ // `toolHandler`, so they make its connection-scope check themselves.
317
+ const kb = inMemoryKb(
318
+ { 'Agents/plugin-maker.agent': agentFile('name: Plugin maker\nplatformTools: [my_plugin]') },
319
+ { reader: ALICE.email },
320
+ );
321
+ const base = await start(agentScopeOver(kb));
322
+ const refused = await post(base, '/api/plugins', { name: 'GTM' }, 'bevel_alice_agent');
323
+ expect(refused.status).toBe(403);
324
+ expect(await refused.json()).toEqual({
325
+ error: expect.stringContaining('The tool "create_plugin" is not available to this connection'),
326
+ code: 'not_available_to_connection',
327
+ });
328
+ expect(createPlugin).not.toHaveBeenCalled();
329
+
330
+ // The tool it lists is served; a key made as Everything and a session are untouched.
331
+ expect((await post(base, '/api/plugins/personal', {}, 'bevel_alice_agent')).status).toBe(200);
332
+ expect((await post(base, '/api/plugins', { name: 'Ops' }, 'bevel_alice')).status).toBe(201);
333
+ expect((await post(base, '/api/plugins', { name: 'Fin' }, 'session-alice')).status).toBe(201);
334
+ });
335
+
336
+ it('a narrowed connection with no scope resolver wired loads nothing, never Everything', async () => {
337
+ const base = await start();
338
+ expect((await post(base, '/api/plugins/personal', {}, 'bevel_alice_agent')).status).toBe(403);
339
+ expect(ensurePersonalPlugin).not.toHaveBeenCalled();
340
+ });
305
341
  });
@@ -19,7 +19,7 @@ export {
19
19
  type JoinRequestStatus,
20
20
  type JoinRequestStore,
21
21
  } from './join-request-records.store.js';
22
- export { PluginLinkIndex, type LinkMembership, type PluginLinks } from './plugin-links.js';
22
+ export { PluginLinkIndex, type IPluginLinkIndex, type LinkMembership, type PluginLinks } from './plugin-links.js';
23
23
  export { PluginLinksService, PluginLinkError } from './plugin-links.service.js';
24
24
  export { PluginRenameService, PluginRenameError, renamePluginPrincipalInText } from './plugin-rename.service.js';
25
25
  export { compileMarketplace, type VirtualTree, type CompileInput, type MarketplaceOptions } from './compile/compile-marketplace.js';
@@ -58,10 +58,27 @@ export const LINK_GRANT_VERBS = ['read', 'write'] as const;
58
58
  export interface LinkMembership {
59
59
  /** skill path → every plugin that holds it, inline or by link. */
60
60
  bySkill: Map<string, PluginMembership[]>;
61
- /** plugin folder → its links. Every plugin folder appears, linked or not. */
61
+ /**
62
+ * plugin identity (`PluginLinks.name`) → its links. Every plugin appears,
63
+ * linked or not. A name and a folder may differ, so a repository path is
64
+ * read from the value's `folder`, never from the key.
65
+ */
62
66
  byPlugin: Map<string, PluginLinks>;
63
67
  }
64
68
 
69
+ /**
70
+ * What a reader of the link index asks it — the contract a consumer outside
71
+ * this module (a distribution's agent-scope resolver, through
72
+ * `CorePorts.agentScope`) is written against. Dropping the cache is the
73
+ * index owner's affair, not a reader's, so it is not here.
74
+ */
75
+ export interface IPluginLinkIndex {
76
+ /** Every plugin's links and every skill's memberships, from the released catalog. */
77
+ membership(): Promise<LinkMembership>;
78
+ /** The memberships of one skill (empty when it is in no plugin). */
79
+ pluginsOf(skillPath: string): Promise<PluginMembership[]>;
80
+ }
81
+
65
82
  /**
66
83
  * The link index: which shared skills each plugin links, and — the other way
67
84
  * round — which plugins each skill belongs to, whether by sitting inside the
@@ -88,7 +105,7 @@ export interface LinkMembership {
88
105
  * subscriber that drops the plugin index, so a link committed on the default
89
106
  * branch shows within one round-trip.
90
107
  */
91
- export class PluginLinkIndex {
108
+ export class PluginLinkIndex implements IPluginLinkIndex {
92
109
  private readonly cache: TtlCache<LinkMembership>;
93
110
 
94
111
  constructor(
@@ -17,6 +17,8 @@ import { pluginFolderBelowRoot } from './plugins.service.js';
17
17
  import type { KbContext } from '../../shared/kb-context.js';
18
18
  import { PluginProvisionError, type PluginProvisionService } from './plugin-provision.service.js';
19
19
  import { argumentsRefusal } from '../tool-helpers/index.js';
20
+ import { resolveConnectionScope, type IAgentScopeResolver } from '../agent-scope/index.js';
21
+ import '../tool-auth/index.js'; // Express Request.toolAuth augmentation
20
22
  import { PluginLinkError, type PluginLinksService } from './plugin-links.service.js';
21
23
  import { PluginRenameError, type PluginRenameService } from './plugin-rename.service.js';
22
24
  import type { JoinRequestsService } from './join-requests.service.js';
@@ -83,6 +85,29 @@ function refuseMismatchedArguments(req: express.Request, res: express.Response):
83
85
  return true;
84
86
  }
85
87
 
88
+ /**
89
+ * Answer the connection-scope refusal when the caller's connection was made
90
+ * as an agent configuration that does not list `toolName`; `true` when it answered.
91
+ * These routes ARE the `create_plugin` and `my_plugin` tools but are not
92
+ * hosted by `toolHandler`, so they ask the one policy it asks —
93
+ * `ConnectionScope.platformToolRefusal` — and answer what it answers. A
94
+ * session, or a key made as Everything, carries no `agentPath` and is never
95
+ * refused.
96
+ */
97
+ async function refuseOutsideConnectionScope(
98
+ req: express.Request,
99
+ res: express.Response,
100
+ user: AuthUser,
101
+ toolName: string,
102
+ agentScope: Pick<IAgentScopeResolver, 'resolve'> | undefined,
103
+ ): Promise<boolean> {
104
+ const scope = await resolveConnectionScope(agentScope, user.email, req.toolAuth?.agentPath);
105
+ const refusal = scope.platformToolRefusal(toolName);
106
+ if (!refusal) return false;
107
+ res.status(403).json(refusal);
108
+ return true;
109
+ }
110
+
86
111
  /**
87
112
  * The two doors through which plugin folders come to exist — ONE
88
113
  * implementation each, for the app and for agents alike:
@@ -106,6 +131,8 @@ function refuseMismatchedArguments(req: express.Request, res: express.Response):
106
131
  export function createPluginCreationRoutes(
107
132
  provision: Pick<PluginProvisionService, 'createPlugin' | 'ensurePersonalPlugin'>,
108
133
  resolveUser: (req: express.Request) => Promise<AuthUser | null>,
134
+ /** Resolves a connection's agent choice to its scope; absent, a narrowed connection loads nothing. */
135
+ agentScope?: Pick<IAgentScopeResolver, 'resolve'>,
109
136
  ): express.Router {
110
137
  const router = express.Router();
111
138
 
@@ -117,8 +144,10 @@ export function createPluginCreationRoutes(
117
144
  }
118
145
  // These two routes ARE the `create_plugin` and `my_plugin` tools, so an
119
146
  // agent's call is checked against what those tools declare, exactly as a
120
- // route-hosted tool's is in `toolHandler`: a call that does not match is
121
- // refused before anything is provisioned.
147
+ // route-hosted tool's is in `toolHandler`: a call that does not match, or
148
+ // a connection whose agent does not list the tool, is refused before
149
+ // anything is provisioned.
150
+ if (await refuseOutsideConnectionScope(req, res, user, 'create_plugin', agentScope)) return;
122
151
  if (refuseMismatchedArguments(req, res)) return;
123
152
  // `req.body` is undefined when no JSON body was sent at all — that is a
124
153
  // 400, not a destructuring crash.
@@ -155,8 +184,10 @@ export function createPluginCreationRoutes(
155
184
  }
156
185
  // These two routes ARE the `create_plugin` and `my_plugin` tools, so an
157
186
  // agent's call is checked against what those tools declare, exactly as a
158
- // route-hosted tool's is in `toolHandler`: a call that does not match is
159
- // refused before anything is provisioned.
187
+ // route-hosted tool's is in `toolHandler`: a call that does not match, or
188
+ // a connection whose agent does not list the tool, is refused before
189
+ // anything is provisioned.
190
+ if (await refuseOutsideConnectionScope(req, res, user, 'my_plugin', agentScope)) return;
160
191
  if (refuseMismatchedArguments(req, res)) return;
161
192
  try {
162
193
  res.json(await provision.ensurePersonalPlugin(user));
@@ -3,6 +3,7 @@ import express from 'express';
3
3
  import { afterEach, describe, expect, it } from 'vitest';
4
4
  import { createSecretsVaultRoutes } from '../secrets-vault.routes.js';
5
5
  import { testKbContext } from '../../../__tests__/kb-context.js';
6
+ import { ConnectionScope } from '../../agent-scope/index.js';
6
7
 
7
8
  /**
8
9
  * The aggregated `/connect/pending` surface: everything standing between the
@@ -336,6 +337,118 @@ describe('GET /api/connect/pending — readability', () => {
336
337
  });
337
338
  });
338
339
 
340
+ describe('GET /api/connect/pending — narrowed to the agent the connection is made as', () => {
341
+ /**
342
+ * The consent step's "Connect as" choice: a connection made as an `.agent`
343
+ * file loads only the connectors the file lists, so the page that asks for
344
+ * sign-ins and keys lists only those. Two readable tools, one of which the
345
+ * agent loads; the agent is answered by a stub resolver over the REAL
346
+ * `ConnectionScope`, the one answer every agent surface asks.
347
+ */
348
+ const AGENT = { path: 'Agents/ops.agent', name: 'ops' };
349
+ const resolver = {
350
+ resolve: async (_email: string | undefined, agentPath: string | null | undefined) => {
351
+ if (!agentPath) return ConnectionScope.everything();
352
+ if (agentPath === AGENT.path) {
353
+ return ConnectionScope.narrowed(AGENT, { skills: [], connectors: ['Tools/weather.tool'], platformTools: null }, 'fp');
354
+ }
355
+ return ConnectionScope.gone(agentPath);
356
+ },
357
+ };
358
+ const twoTools = {
359
+ listAccessible: async () => [
360
+ {
361
+ slug: 'weather',
362
+ name: 'weather',
363
+ path: 'Tools/weather.tool',
364
+ type: 'http' as const,
365
+ variables: [{ name: 'API_KEY', scope: 'user' as const, label: null }],
366
+ },
367
+ {
368
+ slug: 'notion',
369
+ name: 'notion',
370
+ path: 'Tools/notion.tool',
371
+ type: 'mcp' as const,
372
+ variables: [
373
+ {
374
+ name: 'MCP_OAUTH',
375
+ scope: 'user' as const,
376
+ label: 'notion sign-in',
377
+ oauth: { authorizationUrl: 'https://a.example/auth', tokenUrl: 'https://a.example/token', clientId: 'cid' },
378
+ },
379
+ ],
380
+ },
381
+ ],
382
+ } as unknown as Parameters<typeof createSecretsVaultRoutes>[0]['toolManualService'];
383
+ const vault = {
384
+ statusFor: async (_u: string, keys: string[]) =>
385
+ keys.map((key) => ({
386
+ key,
387
+ adminConfigured: key === 'notion_MCP_OAUTH',
388
+ adminKind: key === 'notion_MCP_OAUTH' ? ('oauth' as const) : null,
389
+ userConfigured: false,
390
+ userKind: null,
391
+ })),
392
+ // A sign-in registered directly on the Secrets page: nobody's connector.
393
+ list: async () => [
394
+ { id: 's-own', key: 'MY_TOKEN', kind: 'oauth' as const, label: 'Mine', authorized: false, createdAt: new Date(), updatedAt: new Date() },
395
+ ],
396
+ } as unknown as Parameters<typeof createSecretsVaultRoutes>[0]['secretsVault'];
397
+
398
+ async function pendingAs(agent: string | null, withResolver = true) {
399
+ const app = express();
400
+ app.use(express.json());
401
+ app.use((req, _res, next) => {
402
+ req.userId = 'u1';
403
+ req.userEmail = 'a@x.com';
404
+ next();
405
+ });
406
+ app.use(
407
+ '/api',
408
+ createSecretsVaultRoutes({
409
+ kb: testKbContext(),
410
+ secretsVault: vault,
411
+ toolManualService: twoTools,
412
+ accessControl,
413
+ ...(withResolver ? { agents: resolver } : {}),
414
+ connectionProbe: {
415
+ probe: async () => ({ status: 'unverifiable' as const, detail: null, checkedAt: new Date() }),
416
+ },
417
+ stateSecret: 'test-secret',
418
+ publicBackendUrl: 'http://localhost:3000',
419
+ publicFrontendUrl: 'http://localhost:5173',
420
+ }),
421
+ );
422
+ httpServer = await new Promise<HttpServer>((resolve) => {
423
+ const s = app.listen(0, () => resolve(s));
424
+ });
425
+ const port = (httpServer.address() as { port: number }).port;
426
+ const query = agent === null ? '' : `?agent=${encodeURIComponent(agent)}`;
427
+ const res = await fetch(`http://127.0.0.1:${port}/api/connect/pending${query}`);
428
+ expect(res.status).toBe(200);
429
+ const body = (await res.json()) as PendingBody & { toolOAuth: { slug: string }[] };
430
+ return { tools: body.tools.map((t) => t.slug), signIns: body.toolOAuth.map((o) => o.slug), standalone: body.oauth.map((o) => o.id) };
431
+ }
432
+
433
+ it('lists everything without a choice, as before', async () => {
434
+ expect(await pendingAs(null)).toEqual({ tools: ['weather'], signIns: ['notion'], standalone: ['s-own'] });
435
+ });
436
+
437
+ it('lists only the connectors the agent loads, and no standalone sign-in', async () => {
438
+ expect(await pendingAs(AGENT.path)).toEqual({ tools: ['weather'], signIns: [], standalone: [] });
439
+ });
440
+
441
+ it('lists nothing for an agent the person cannot use: a narrowing that cannot be read is never Everything', async () => {
442
+ expect(await pendingAs('Agents/gone.agent')).toEqual({ tools: [], signIns: [], standalone: [] });
443
+ // …and the same with no resolver wired at all.
444
+ expect(await pendingAs(AGENT.path, false)).toEqual({ tools: [], signIns: [], standalone: [] });
445
+ });
446
+
447
+ it('reads an empty or blank choice as Everything', async () => {
448
+ expect(await pendingAs(' ')).toEqual({ tools: ['weather'], signIns: ['notion'], standalone: ['s-own'] });
449
+ });
450
+ });
451
+
339
452
  describe('GET /api/connect/pending — OAuth scope coverage', () => {
340
453
  // A tool with an OAuth-backed var that now requires two scopes.
341
454
  const oauthTool = {