@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
@@ -10,6 +10,7 @@ import {
10
10
  scopesCovered,
11
11
  missingScopes,
12
12
  configuredAs,
13
+ type DeclaredOAuthProvider,
13
14
  type ISecretsVaultService,
14
15
  } from './secrets-vault.contract.js';
15
16
  import type { IToolManualService, ToolManualSummary, ToolVariable } from '../tool-manuals/index.js';
@@ -17,10 +18,19 @@ import type { IConnectionProbeService } from '../connection-probe/index.js';
17
18
  import { utcpNamespacedKey } from '../../shared/utcp-namespace.js';
18
19
  import type { IAccessControl } from '../access/index.js';
19
20
  import type { KbContext } from '../../shared/kb-context.js';
21
+ import { resolveConnectionScope, type IAgentScopeResolver } from '../agent-scope/index.js';
20
22
  import '../auth/index.js'; // Express Request augmentation (req.userId / req.userEmail)
21
23
 
22
24
  export interface SecretsVaultRoutesDeps {
23
25
  secretsVault: ISecretsVaultService;
26
+ /**
27
+ * Resolves what a connection made as an agent configuration loads, so the connect
28
+ * page can list only the tools the chosen agent would reach (`?agent=`).
29
+ * Optional: a construction without one answers such a request as a
30
+ * connection that loads nothing — a narrowing that cannot be read is never
31
+ * read as Everything.
32
+ */
33
+ agents?: Pick<IAgentScopeResolver, 'resolve'>;
24
34
  /** The released branch's clone — where the `.tool` files the access verdicts are read from live. */
25
35
  kb: Pick<KbContext, 'defaultWorkspaceId'>;
26
36
  /** Source of `.tool` manuals + their declared variable scopes (default-branch catalog). */
@@ -44,6 +54,38 @@ function redirectUriFor(publicBackendUrl: string): string {
44
54
  return `${publicBackendUrl}/api/secrets/oauth/callback`;
45
55
  }
46
56
 
57
+ /**
58
+ * What of a declared sign-in is its provider configuration — ONE reading, for
59
+ * the client-secret save (which stores it as a record) and the sign-in start
60
+ * (which runs from it). `null` while the declaration has no endpoints: it named
61
+ * only its client id and the server's metadata could not complete it.
62
+ */
63
+ function declaredProvider(variable: ToolVariable): DeclaredOAuthProvider | null {
64
+ const oauth = variable.oauth;
65
+ if (!oauth?.authorizationUrl || !oauth.tokenUrl) return null;
66
+ return {
67
+ authorizationUrl: oauth.authorizationUrl,
68
+ tokenUrl: oauth.tokenUrl,
69
+ clientId: oauth.clientId,
70
+ scopes: oauth.scopes,
71
+ // Static authorize params (e.g. Google's `access_type=offline`) so the
72
+ // provider returns a refresh token.
73
+ authParams: oauth.authParams,
74
+ // PKCE unless the declaration opted out; the resource indicator when the
75
+ // server (or the declaration) names one.
76
+ pkce: oauth.pkce !== false,
77
+ resource: oauth.resource,
78
+ };
79
+ }
80
+
81
+ /** Why a declared sign-in has no endpoints — the discovery's own reason when it gave one. */
82
+ function endpointsUnknown(manual: ToolManualSummary): string {
83
+ const why = manual.setup?.reason;
84
+ return why
85
+ ? `The sign-in endpoints for this server aren't known yet: ${why}.`
86
+ : "The sign-in endpoints for this server aren't known yet — declare `authorizationUrl` and `tokenUrl` on the sign-in variable.";
87
+ }
88
+
47
89
  /**
48
90
  * Is this a SAME-ORIGIN path we're willing to bounce the browser back to after a
49
91
  * sign-in? The callback builds `${publicFrontendUrl}${dest}#…`, so anything that
@@ -267,12 +309,21 @@ export function createSecretsVaultRoutes(deps: SecretsVaultRoutesDeps): express.
267
309
  // that is already set is nobody's outstanding work, so it is dropped. What is
268
310
  // not relaxed is readability: the listing is still built from `listAccessible`,
269
311
  // so a tool the caller may not read is named here in no state at all.
312
+ //
313
+ // `?agent=<path>` — the consent step's "Connect as" choice — narrows the
314
+ // listing to what a connection made as that agent configuration would load, by the
315
+ // ONE answer every agent surface asks (`ConnectionScope.allowsConnector`,
316
+ // applied after the read gate exactly as the tool listing applies it). A
317
+ // sign-in the connection will never reach is not on a page about what the
318
+ // connection needs. Absent, the listing is Everything's, as it always was.
270
319
  router.get('/connect/pending', async (req, res) => {
271
320
  const userId = req.userId;
272
321
  const email = req.userEmail;
273
322
  if (!userId || !email) return void res.status(401).json({ error: 'Not authenticated' });
274
323
  try {
275
- const manuals = await toolManualService.listAccessible(email);
324
+ const agentPath = typeof req.query.agent === 'string' && req.query.agent.trim() !== '' ? req.query.agent : null;
325
+ const scope = await resolveConnectionScope(deps.agents, email, agentPath);
326
+ const manuals = (await toolManualService.listAccessible(email)).filter((m) => scope.allowsConnector(m.path));
276
327
  // BOTH tiers now — the workspace values are reported as well, so their
277
328
  // stored state has to be asked for.
278
329
  const allKeys = manuals.flatMap((m) => (m.variables ?? []).map((v) => varKey(m.name, v.name)));
@@ -371,9 +422,11 @@ export function createSecretsVaultRoutes(deps: SecretsVaultRoutesDeps): express.
371
422
  // Secrets page. A TOOL sign-in provisions a per-user row in the same
372
423
  // table (keyed `<manual>_<VAR>`), so exclude every tool-var key here or
373
424
  // an authorized tool sign-in would render twice — once as a toolOAuth
374
- // row and again as a "standalone" one.
425
+ // row and again as a "standalone" one. They belong to no connector, so
426
+ // a connection narrowed to an agent's connectors has nothing to do with
427
+ // them: listed for Everything only.
375
428
  const toolOAuthKeys = new Set(toolOAuth.map((o) => o.key));
376
- const secrets = await secretsVault.list(userId);
429
+ const secrets = scope.isEverything() ? await secretsVault.list(userId) : [];
377
430
  const oauth = secrets
378
431
  .filter((s) => s.kind === 'oauth' && !toolOAuthKeys.has(s.key))
379
432
  .map((s) => ({ id: s.id, key: s.key, label: s.label, authorized: s.authorized ?? false }));
@@ -441,8 +494,8 @@ export function createSecretsVaultRoutes(deps: SecretsVaultRoutesDeps): express.
441
494
 
442
495
  // Set the confidential client secret for a tool's OAuth-backed variable — the
443
496
  // ONLY place the secret is provided. Requires WRITE on the `.tool`. The provider
444
- // config comes from the variable's own `oauth` declaration (stored WITH the
445
- // secret so a later `.tool` edit can't redirect it).
497
+ // config of the variable's own `oauth` declaration is stored with the secret as
498
+ // a record of the save; a sign-in start reads the declaration afresh.
446
499
  router.put('/secrets/tools/:slug/vars/:var/oauth/admin', async (req, res) => {
447
500
  const userId = req.userId;
448
501
  const email = req.userEmail;
@@ -456,38 +509,17 @@ export function createSecretsVaultRoutes(deps: SecretsVaultRoutesDeps): express.
456
509
  if (!(await accessControl.canWrite(defaultWs(), email, found.manual.path))) {
457
510
  return void res.status(403).json({ error: 'You need write access to this tool to set its client secret.' });
458
511
  }
459
- const { authorizationUrl, tokenUrl } = found.variable.oauth;
460
512
  // A declaration that names only its client id is completed from the
461
- // server's OAuth metadata at scan time. When that didn't happen, pinning
462
- // the secret to a provider with no endpoints would leave every sign-in
463
- // failing later with a far less specific error than the catalog's own.
464
- if (!authorizationUrl || !tokenUrl) {
465
- const why = found.manual.setup?.reason;
466
- return void res.status(422).json({
467
- error: why
468
- ? `The sign-in endpoints for this server aren't known yet: ${why}.`
469
- : "The sign-in endpoints for this server aren't known yet — declare `authorizationUrl` and `tokenUrl` on the sign-in variable.",
470
- });
471
- }
513
+ // server's OAuth metadata. When that didn't happen, storing the secret
514
+ // with a provider that has no endpoints would leave every sign-in failing
515
+ // later with a far less specific error than the catalog's own.
516
+ const provider = declaredProvider(found.variable);
517
+ if (!provider) return void res.status(422).json({ error: endpointsUnknown(found.manual) });
472
518
  const clientSecret = (req.body ?? {}).clientSecret;
473
519
  await secretsVault.putSharedOAuthClientSecret({
474
520
  key: varKey(found.manual.name, found.variable.name),
475
521
  clientSecret,
476
- provider: {
477
- authorizationUrl,
478
- tokenUrl,
479
- clientId: found.variable.oauth.clientId,
480
- scopes: found.variable.oauth.scopes,
481
- // Static authorize params (e.g. Google's `access_type=offline`) so the
482
- // provider returns a refresh token — stored with the secret so a later
483
- // `.tool` edit can't redirect the flow.
484
- authParams: found.variable.oauth.authParams,
485
- // PKCE unless the declaration opted out; the resource indicator when
486
- // the server (or the declaration) names one. Both pinned here for the
487
- // same reason as the rest: the flow runs from the stored row.
488
- pkce: found.variable.oauth.pkce !== false,
489
- resource: found.variable.oauth.resource,
490
- },
522
+ provider,
491
523
  });
492
524
  res.status(201).json({ ok: true });
493
525
  } catch (err) {
@@ -505,12 +537,37 @@ export function createSecretsVaultRoutes(deps: SecretsVaultRoutesDeps): express.
505
537
  const email = req.userEmail;
506
538
  if (!userId || !email) return void res.status(401).json({ error: 'Not authenticated' });
507
539
  try {
508
- const found = await findManualVar(email, req.params.slug, req.params.var);
509
- if (!found) return void res.status(404).json({ error: 'Tool or variable not found' });
510
- if (!found.variable.oauth) {
511
- return void res.status(422).json({ error: 'This variable is not an OAuth sign-in.' });
540
+ // Two sources, one per kind of sign-in. A DECLARED one follows its tool
541
+ // file as it reads now — never the catalog's scan, which can be a refresh
542
+ // behind the file, and never the copy the client-secret save stored. A
543
+ // client the platform registered itself (oauth-auto) is described by no
544
+ // file: the catalog's discovery surfaced it, and its stored row is the
545
+ // only description of it there is.
546
+ const [live, catalog] = await Promise.all([
547
+ toolManualService.liveDeclaration(email, req.params.slug, req.params.var),
548
+ findManualVar(email, req.params.slug, req.params.var),
549
+ ]);
550
+ // The file is there but its declaration is refused as it reads now (an
551
+ // http:// or private endpoint, say): the parser's reason is the answer,
552
+ // and neither a catalog still holding the earlier version nor the stored
553
+ // row stands in for it. Nothing is sent anywhere.
554
+ if (live?.refused) return void res.status(422).json({ error: live.refused });
555
+ const manual = live?.manual ?? catalog?.manual;
556
+ if (!manual || (!live?.variable && !catalog)) {
557
+ return void res.status(404).json({ error: 'Tool or variable not found' });
512
558
  }
513
- const key = varKey(found.manual.name, found.variable.name);
559
+ const key = varKey(manual.name, req.params.var);
560
+ const declared = live?.variable?.oauth ? live.variable : null;
561
+ const registered =
562
+ !declared && catalog?.manual.setup?.kind === 'oauth-auto' && catalog.variable.oauth ? catalog.variable : null;
563
+ const signIn = declared ?? registered;
564
+ // No sign-in in the file and none the platform registered: whatever the
565
+ // shared row still holds is not used.
566
+ if (!signIn?.oauth) {
567
+ throw new SecretOAuthError("This tool's owner hasn't finished setting this up");
568
+ }
569
+ const provider = declared ? declaredProvider(declared) : undefined;
570
+ if (provider === null) return void res.status(422).json({ error: endpointsUnknown(manual) });
514
571
  // Provision the caller's oauth row (from the owner-set secret) FIRST — its id
515
572
  // is what the un-authed callback keys on. Pass an empty state placeholder; we
516
573
  // sign the real state below with the returned id and swap it into the URL, so
@@ -520,10 +577,10 @@ export function createSecretsVaultRoutes(deps: SecretsVaultRoutesDeps): express.
520
577
  key,
521
578
  redirectUri: redirectUriFor(deps.publicBackendUrl),
522
579
  state: '',
523
- // Request the permissions the tool file declares RIGHT NOW (not the frozen
524
- // copy on the owner-set row), so adding a scope to the `.tool` takes effect
525
- // on the next sign-in. The secret/clientId/addresses stay owner-pinned.
526
- scopes: found.variable.oauth.scopes,
580
+ // Request the permissions the tool file declares RIGHT NOW, so adding a
581
+ // scope takes effect on the next sign-in.
582
+ scopes: signIn.oauth.scopes,
583
+ provider,
527
584
  });
528
585
  // The return path is signed INTO the state (HMAC-SHA256) rather than kept
529
586
  // in a query param or a cookie: the callback arrives un-authenticated from
@@ -637,7 +694,22 @@ export function createSecretsVaultPublicRoutes(deps: SecretsVaultRoutesDeps): ex
637
694
  back(`authorized=${encodeURIComponent(state.i)}`, dest);
638
695
  } catch (err) {
639
696
  log.error('oauth callback failed:', { err });
640
- back(`error=${encodeURIComponent('Authorization failed. Check the provider configuration and try again.')}`, dest);
697
+ // A provider's REFUSAL (the vault's error carrying the provider's HTTP
698
+ // status) names the provider's error code and Hexis's own sentence for
699
+ // it — the one thing the person on the Connect page (or the agent they
700
+ // paste it to) can act on: a client the provider does not accept, a
701
+ // refused authorization code. Nothing of the provider's text is in it.
702
+ // Every other failure stays the generic line: a transport error quotes
703
+ // what fetch said, which is not a provider's word.
704
+ const refusal = err instanceof SecretOAuthError && err.providerStatus !== undefined ? err.message : null;
705
+ back(
706
+ `error=${encodeURIComponent(
707
+ refusal
708
+ ? `Authorization failed. ${refusal}`
709
+ : 'Authorization failed. Check the provider configuration and try again.',
710
+ )}`,
711
+ dest,
712
+ );
641
713
  }
642
714
  });
643
715
 
@@ -1,4 +1,5 @@
1
1
  import { randomBytes } from 'node:crypto';
2
+ import { isStandardTokenErrorCode } from '../../shared/oauth-token-error.js';
2
3
 
3
4
  /** The single sign-on configuration a deployment would sign people in with. */
4
5
  export interface OidcConfiguration {
@@ -55,21 +56,6 @@ const REQUEST_TIMEOUT_MS = 10_000;
55
56
  */
56
57
  const CODE_REJECTIONS: readonly string[] = ['invalid_grant'];
57
58
 
58
- /**
59
- * The other error codes RFC 6749 §5.2 (and OIDC Core §3.1.2.6) define — the
60
- * only ones echoed back in an "unverified" message. Anything else in `error`
61
- * is text of the provider's choosing, and could be the secret reflected back.
62
- */
63
- const ECHOED_ERRORS: readonly string[] = [
64
- 'invalid_request',
65
- 'unauthorized_client',
66
- 'unsupported_grant_type',
67
- 'invalid_scope',
68
- 'access_denied',
69
- 'server_error',
70
- 'temporarily_unavailable',
71
- ];
72
-
73
59
  /** The issuer as the provider appends `/.well-known/...` to it: no trailing slash. */
74
60
  export function normalizeIssuerUrl(issuerUrl: string): string {
75
61
  return issuerUrl.trim().replace(/\/+$/, '');
@@ -219,9 +205,10 @@ export async function checkOidcConfiguration(
219
205
  };
220
206
  }
221
207
  if (CODE_REJECTIONS.includes(errorCode)) return { outcome: 'verified' };
222
- // Only a standard error code is echoed — anything else could be text of the
223
- // provider's choosing, the secret included.
224
- const code = ECHOED_ERRORS.includes(errorCode) ? ` (${errorCode})` : ` (HTTP ${status})`;
208
+ // Only a standard error code is echoed (the one list the vault reads a
209
+ // refusal by too) — anything else could be text of the provider's choosing,
210
+ // the secret included.
211
+ const code = isStandardTokenErrorCode(errorCode) ? ` (${errorCode})` : ` (HTTP ${status})`;
225
212
  return {
226
213
  outcome: 'unverified',
227
214
  error: `The application ID and secret could not be verified — the provider gave an answer that does not say whether they are right${code}.`,
@@ -280,6 +280,40 @@ describe('SkillService', () => {
280
280
  expect(await svc(denyRfi).getSkill('user@x.eu', 'rfi')).toEqual({ ok: false, error: 'forbidden' });
281
281
  });
282
282
 
283
+ /**
284
+ * A connection made as an `.agent` file narrows the skills (`within`) —
285
+ * AFTER the person's read gate, so it can take a skill away and never give
286
+ * one: a skill its lists name that the person may not read stays out.
287
+ */
288
+ describe('narrowed to a connection’s skills', () => {
289
+ const denyGuidelines = {
290
+ canRead: async () => true,
291
+ canReadBatch: async (_w: string, _e: string, paths: string[]) =>
292
+ new Map(paths.map((p) => [p, !p.startsWith('Plugins/Development/')])),
293
+ } as unknown as IAccessControl;
294
+ const everyPluginSkill = (folder: string) => folder.startsWith('Plugins/');
295
+
296
+ test('lists only what is both readable and within, and loads nothing else', async () => {
297
+ const list = await svc(denyGuidelines).listSkills('user@x.eu', { within: everyPluginSkill });
298
+ expect(list.map((s) => s.name)).toEqual(['rfi']);
299
+ expect(await svc().listSkills('user@x.eu', { within: (p) => p === 'Plugins/Development/coding-guidelines' })).toEqual([
300
+ expect.objectContaining({ name: 'coding-guidelines' }),
301
+ ]);
302
+ });
303
+
304
+ test('getSkill outside it is not there for the connection; inside it, the read gate still answers', async () => {
305
+ expect(await svc().getSkill('user@x.eu', 'rfi', undefined, { within: () => false })).toEqual({
306
+ ok: false,
307
+ error: 'not_found',
308
+ });
309
+ const inside = await svc().getSkill('user@x.eu', 'rfi', undefined, { within: everyPluginSkill });
310
+ expect(inside.ok).toBe(true);
311
+ expect(
312
+ await svc(denyGuidelines).getSkill('user@x.eu', 'coding-guidelines', undefined, { within: everyPluginSkill }),
313
+ ).toEqual({ ok: false, error: 'forbidden' });
314
+ });
315
+ });
316
+
283
317
  /**
284
318
  * The listing and the loader must never disagree about the same skill at the
285
319
  * same instant.
@@ -1,5 +1,8 @@
1
- export { SkillService } from './skills.service.js';
2
- export { PendingSkillsService } from './pending-skills.service.js';
1
+ // The services are types here: the composition root constructs them from
2
+ // their files, so a module that imports this entry for a helper or a type
3
+ // does not load the implementations.
4
+ export type { SkillService } from './skills.service.js';
5
+ export type { PendingSkillsService } from './pending-skills.service.js';
3
6
  export { registerSkillsTools } from './skills.tools.js';
4
7
  export { createSkillsRoutes } from './skills.routes.js';
5
8
  export { AllowedToolsChecker } from './allowed-tools-check.js';
@@ -14,7 +17,9 @@ export type {
14
17
  PendingSkill,
15
18
  GetSkillResult,
16
19
  GetSkillOptions,
20
+ ListSkillsOptions,
17
21
  SkillHistorySource,
22
+ SkillScope,
18
23
  } from './skills.contract.js';
19
24
  // Reached by other modules; exported here so they stop importing the files.
20
25
  export type { PluginMembership } from './skills.contract.js';
@@ -119,8 +119,19 @@ export interface ListSkillsOptions {
119
119
  * carries `unmerged: true` and this branch name: nobody approved it.
120
120
  */
121
121
  branch?: string;
122
+ /** Narrow the listing to a connection's skills — see {@link SkillScope}. */
123
+ within?: SkillScope;
122
124
  }
123
125
 
126
+ /**
127
+ * A connection's narrowing of the skills: whether the skill in `skillFolder`
128
+ * (repo-relative) is one the connection loads. Applied AFTER the caller's read
129
+ * gate, so it can only take skills away. The agent surfaces pass the
130
+ * connection scope's `allowsSkill` (`modules/agent-scope`); absent is every
131
+ * skill the caller may read.
132
+ */
133
+ export type SkillScope = (skillFolder: string) => boolean;
134
+
124
135
  /** What `getSkill` may be asked beyond a name and a file. */
125
136
  export interface GetSkillOptions {
126
137
  /**
@@ -152,6 +163,12 @@ export interface GetSkillOptions {
152
163
  * combination has exactly one sensible meaning.
153
164
  */
154
165
  branch?: string;
166
+ /**
167
+ * Narrow to a connection's skills — see {@link SkillScope}. A skill outside
168
+ * it answers `not_found`, as a name nobody used does: to this connection it
169
+ * is not there.
170
+ */
171
+ within?: SkillScope;
155
172
  }
156
173
 
157
174
  /**
@@ -108,7 +108,9 @@ export class SkillService implements ISkillService {
108
108
 
109
109
  async listSkills(userEmail?: string, options: ListSkillsOptions = {}): Promise<SkillSummary[]> {
110
110
  const { catalog, branch } = await this.catalogFor(options.branch);
111
- const visible = userEmail ? await this.readableSkills(catalog, userEmail) : catalog.skills;
111
+ const readable = userEmail ? await this.readableSkills(catalog, userEmail) : catalog.skills;
112
+ const within = options.within;
113
+ const visible = within ? readable.filter((s) => within(s.summary.path)) : readable;
112
114
  if (branch === undefined) return visible.map((s) => s.summary);
113
115
  // Marking reads both copies of a folder, so it happens only here, on a
114
116
  // branch read that asked for it — the released catalog every other surface
@@ -135,6 +137,8 @@ export class SkillService implements ISkillService {
135
137
  // A skill the branch deleted is not a skill as far as this answer goes:
136
138
  // the same `not_found` a name nobody ever used gets.
137
139
  if (!found) return { ok: false, error: 'not_found' };
140
+ // Outside the connection's skills: not there, for this connection.
141
+ if (options.within && !options.within(found.summary.path)) return { ok: false, error: 'not_found' };
138
142
 
139
143
  // Through `readable`, not a bare `canRead`: the two gates must never
140
144
  // disagree. `canRead` reads a file's own frontmatter rules off disk on
@@ -4,7 +4,7 @@ import type { IToolRegistry, JsonSchema, UtcpTool } from '../tool-registry/index
4
4
  import { TOOL_DESCRIPTION_CAP, GUIDE_FIRST_SENTENCE } from '../tool-registry/index.js';
5
5
  import { ToolError, type ToolContext, toolDef, bodyEnvelope, declareRouteTool, CAN_WRITE_CLAUSE, defaultBranchWriteVerdicts, type DefaultBranchWriteDeps } from '../tool-helpers/index.js';
6
6
  import type { ToolHandlerFactory } from '../tool-helpers/index.js';
7
- import type { ISkillService } from './skills.contract.js';
7
+ import type { ISkillService, SkillScope } from './skills.contract.js';
8
8
  import { EXTERNAL_KB_MANUAL_NAME } from '../tool-manuals/index.js';
9
9
  import type { IAllowedToolsChecker } from './allowed-tools-check.js';
10
10
 
@@ -33,7 +33,7 @@ const LIST_SKILLS_INPUTS = {
33
33
  const GET_SKILL_INPUTS = {
34
34
  type: 'object' as const,
35
35
  properties: {
36
- name: { type: 'string' as const, minLength: 1, description: 'Skill name (its folder name, e.g. `rfi`).' },
36
+ name: { type: 'string' as const, minLength: 1, description: 'Skill name, as `list_skills` gives it (its `id`, else its `name`, else its folder name; e.g. `rfi`).' },
37
37
  file: {
38
38
  type: 'string' as const,
39
39
  description:
@@ -130,9 +130,13 @@ export function registerSkillsTools(
130
130
  return { paths: committed.includes(skillMdOf(loaded)) ? committed : [skillMdOf(loaded), ...loaded.files], at };
131
131
  };
132
132
 
133
- registry.registerExternalTool((ctx) => buildListSkillsDef(skillService, ctx.userEmail));
133
+ registry.registerExternalTool((ctx) =>
134
+ buildListSkillsDef(skillService, ctx.userEmail, ctx.connectionScope?.skillFilter()),
135
+ );
134
136
  registry.registerInternalTool((ctx) => buildListSkillsDef(skillService, ctx.userEmail));
135
- registry.registerExternalTool((ctx) => buildGetSkillDef(skillService, ctx.userEmail));
137
+ registry.registerExternalTool((ctx) =>
138
+ buildGetSkillDef(skillService, ctx.userEmail, ctx.connectionScope?.skillFilter()),
139
+ );
136
140
  registry.registerInternalTool((ctx) => buildGetSkillDef(skillService, ctx.userEmail));
137
141
  // Both defs are built per catalog listing (their descriptions name the skills
138
142
  // THIS caller may read), so declare the arguments here as well: a direct REST
@@ -140,17 +144,24 @@ export function registerSkillsTools(
140
144
  declareRouteTool('list_skills', LIST_SKILLS_INPUTS);
141
145
  declareRouteTool('get_skill', GET_SKILL_INPUTS);
142
146
 
147
+ // Both skill routes are also how prompts are read (`discovery`): a
148
+ // connection made as an agent configuration that names skills has them as
149
+ // prompts even when its `platformTools` does not offer these two tools.
143
150
  router.post(
144
151
  '/agent/tools/list_skills',
145
152
  toolAuth,
146
153
  toolHandler(async (args, ctx: ToolContext) => {
147
- const skills = await skillService.listSkills(ctx.user.email, { branch: branchArg(args) });
154
+ const within = ctx.connectionScope?.skillFilter();
155
+ const skills = await skillService.listSkills(ctx.user.email, {
156
+ branch: branchArg(args),
157
+ ...(within ? { within } : {}),
158
+ });
148
159
  // Judged on each skill's SKILL.md, by the default branch's rules — a
149
160
  // skill only on a draft is judged where it would land. Each verdict goes
150
161
  // onto a COPY: the summaries may be the catalog shared across users.
151
162
  const verdicts = await verdictsFor(ctx, skills.map(skillMdOf));
152
163
  return { skills: skills.map((s) => ({ ...s, canWrite: verdicts.get(skillMdOf(s)) === true })) };
153
- }),
164
+ }, { discovery: true }),
154
165
  );
155
166
 
156
167
  router.post(
@@ -174,7 +185,12 @@ export function registerSkillsTools(
174
185
  400,
175
186
  );
176
187
  }
177
- const result = await skillService.getSkill(ctx.user.email, name, file, { version, branch });
188
+ const within = ctx.connectionScope?.skillFilter();
189
+ const result = await skillService.getSkill(ctx.user.email, name, file, {
190
+ version,
191
+ branch,
192
+ ...(within ? { within } : {}),
193
+ });
178
194
  if (!result.ok) return result;
179
195
  if (result.kind === 'file') {
180
196
  const verdicts = await verdictsFor(ctx, [result.file.path]);
@@ -193,7 +209,7 @@ export function registerSkillsTools(
193
209
  };
194
210
  if (!allowedTools) return { ...result, skill };
195
211
  return { ...result, skill, warnings: await allowedTools.check(ctx.user.email, result.skill.allowedTools) };
196
- }),
212
+ }, { discovery: true }),
197
213
  );
198
214
  }
199
215
 
@@ -223,8 +239,13 @@ function branchArg(args: Record<string, unknown>): string | undefined {
223
239
  * the tool's fixed text leaves under {@link TOOL_DESCRIPTION_CAP} once the
224
240
  * guide-first sentence the registry puts in front is counted.
225
241
  */
226
- async function availableSkillsLine(skillService: ISkillService, userEmail: string | undefined, budget: number): Promise<string> {
227
- const skills = await skillService.listSkills(userEmail);
242
+ async function availableSkillsLine(
243
+ skillService: ISkillService,
244
+ userEmail: string | undefined,
245
+ budget: number,
246
+ within?: SkillScope,
247
+ ): Promise<string> {
248
+ const skills = await skillService.listSkills(userEmail, within ? { within } : {});
228
249
  if (skills.length === 0) return 'No skills are currently available.';
229
250
  const names = skills.map((s) => `\`${s.name}\``);
230
251
  const rest = (shown: number): string =>
@@ -276,12 +297,17 @@ const LIST_SKILLS_DESCRIPTION =
276
297
  'Each skill carries `canWrite`: whether you may change its SKILL.md directly on the default branch. ' +
277
298
  `${CAN_WRITE_CLAUSE} `;
278
299
 
279
- async function buildListSkillsDef(skillService: ISkillService, userEmail?: string): Promise<UtcpTool> {
300
+ async function buildListSkillsDef(skillService: ISkillService, userEmail?: string, within?: SkillScope): Promise<UtcpTool> {
280
301
  return toolDef({
281
302
  name: 'list_skills',
282
303
  description:
283
304
  LIST_SKILLS_DESCRIPTION +
284
- (await availableSkillsLine(skillService, userEmail, skillsLineBudget('list_skills', LIST_SKILLS_INPUTS, LIST_SKILLS_DESCRIPTION))),
305
+ (await availableSkillsLine(
306
+ skillService,
307
+ userEmail,
308
+ skillsLineBudget('list_skills', LIST_SKILLS_INPUTS, LIST_SKILLS_DESCRIPTION),
309
+ within,
310
+ )),
285
311
  path: '/api/agent/tools/list_skills',
286
312
  inputs: LIST_SKILLS_INPUTS,
287
313
  outputs: {
@@ -334,12 +360,17 @@ const GET_SKILL_DESCRIPTION =
334
360
  'The skill (or `file`) carries `canWrite`: whether you may change all of it directly on the default branch. ' +
335
361
  `${CAN_WRITE_CLAUSE} `;
336
362
 
337
- async function buildGetSkillDef(skillService: ISkillService, userEmail?: string): Promise<UtcpTool> {
363
+ async function buildGetSkillDef(skillService: ISkillService, userEmail?: string, within?: SkillScope): Promise<UtcpTool> {
338
364
  return toolDef({
339
365
  name: 'get_skill',
340
366
  description:
341
367
  GET_SKILL_DESCRIPTION +
342
- (await availableSkillsLine(skillService, userEmail, skillsLineBudget('get_skill', GET_SKILL_INPUTS, GET_SKILL_DESCRIPTION))),
368
+ (await availableSkillsLine(
369
+ skillService,
370
+ userEmail,
371
+ skillsLineBudget('get_skill', GET_SKILL_INPUTS, GET_SKILL_DESCRIPTION),
372
+ within,
373
+ )),
343
374
  path: '/api/agent/tools/get_skill',
344
375
  inputs: GET_SKILL_INPUTS,
345
376
  outputs: {
@@ -150,6 +150,7 @@ describe('ExternalApiKeyService', () => {
150
150
  revokedAt: null,
151
151
  revokedBy: null,
152
152
  deletedAt: null,
153
+ agentPath: null,
153
154
  });
154
155
  });
155
156
 
@@ -370,6 +371,7 @@ describe('ExternalApiKeyService', () => {
370
371
  revokedAt: null,
371
372
  revokedBy: null,
372
373
  deletedAt: null,
374
+ agentPath: null,
373
375
  });
374
376
  expect(summaries[1].revokedAt).toBe(rows[1].revokedAt!.getTime());
375
377
  // sanity-check that ordering was requested (we can't introspect the
@@ -401,6 +403,7 @@ describe('ExternalApiKeyService', () => {
401
403
  revokedAt: null,
402
404
  revokedBy: null,
403
405
  deletedAt: null,
406
+ agentPath: null,
404
407
  user: { id: 'u-alice', email: 'alice@example.com', name: 'Alice' },
405
408
  },
406
409
  {
@@ -412,6 +415,7 @@ describe('ExternalApiKeyService', () => {
412
415
  revokedAt: bobKey.revokedAt!.getTime(),
413
416
  revokedBy: null,
414
417
  deletedAt: null,
418
+ agentPath: null,
415
419
  user: { id: 'u-bob', email: 'bob@example.com', name: 'Bob' },
416
420
  },
417
421
  ]);
@@ -43,6 +43,11 @@ export interface ExternalApiKeySummary {
43
43
  * its row stays so the Audit log's events keep their principal.
44
44
  */
45
45
  deletedAt: number | null;
46
+ /**
47
+ * The agent configuration the key connects as (a repo-relative knowledge-base
48
+ * path), or null for Everything — chosen when the key was minted.
49
+ */
50
+ agentPath: string | null;
46
51
  }
47
52
 
48
53
  /** Who revoked a key: its owner, or an admin acting across the deployment. */
@@ -97,6 +102,11 @@ export interface KeyKindSpec {
97
102
  */
98
103
  export interface MintOptions {
99
104
  kind?: string;
105
+ /**
106
+ * The agent configuration the key connects as, already checked to be one the
107
+ * owner may choose (`IAgentScopeResolver.choosable`). Absent: Everything.
108
+ */
109
+ agentPath?: string;
100
110
  }
101
111
 
102
112
  /**
@@ -138,7 +148,7 @@ export interface IExternalApiKeyService {
138
148
  */
139
149
  verifyAndLoadToken(
140
150
  plaintext: string,
141
- ): Promise<{ tokenId: string; user: AuthUser } | null>;
151
+ ): Promise<{ tokenId: string; user: AuthUser; agentPath?: string | null } | null>;
142
152
 
143
153
  /**
144
154
  * For a key {@link verifyAndLoadToken} refused: whether it is a live key
@@ -89,7 +89,7 @@ export class ExternalApiKeyService implements IExternalApiKeyService {
89
89
 
90
90
  const [row] = await this.db
91
91
  .insert(externalApiKeys)
92
- .values({ userId, tokenHash, label: trimmed, kind })
92
+ .values({ userId, tokenHash, label: trimmed, kind, ...(options.agentPath ? { agentPath: options.agentPath } : {}) })
93
93
  .returning();
94
94
 
95
95
  return {
@@ -118,7 +118,7 @@ export class ExternalApiKeyService implements IExternalApiKeyService {
118
118
 
119
119
  async verifyAndLoadToken(
120
120
  plaintext: string,
121
- ): Promise<{ tokenId: string; user: AuthUser } | null> {
121
+ ): Promise<{ tokenId: string; user: AuthUser; agentPath: string | null } | null> {
122
122
  if (!this.looksLikeExternalApiKey(plaintext)) {
123
123
  return null;
124
124
  }
@@ -135,6 +135,7 @@ export class ExternalApiKeyService implements IExternalApiKeyService {
135
135
  tokenId: externalApiKeys.id,
136
136
  label: externalApiKeys.label,
137
137
  lastUsedAt: externalApiKeys.lastUsedAt,
138
+ agentPath: externalApiKeys.agentPath,
138
139
  userId: users.id,
139
140
  email: users.email,
140
141
  name: users.name,
@@ -176,6 +177,7 @@ export class ExternalApiKeyService implements IExternalApiKeyService {
176
177
 
177
178
  return {
178
179
  tokenId: row.tokenId,
180
+ agentPath: row.agentPath,
179
181
  user: {
180
182
  id: row.userId,
181
183
  email: row.email,
@@ -353,5 +355,6 @@ function toSummary(row: typeof externalApiKeys.$inferSelect): ExternalApiKeySumm
353
355
  revokedAt: row.revokedAt ? row.revokedAt.getTime() : null,
354
356
  revokedBy: (row.revokedBy as RevokedBy | null) ?? null,
355
357
  deletedAt: row.deletedAt ? row.deletedAt.getTime() : null,
358
+ agentPath: row.agentPath ?? null,
356
359
  };
357
360
  }
@@ -10,5 +10,5 @@ import './external-api-key.interface.js';
10
10
  export type { InternalTokenService } from './internal-token.service.js';
11
11
  export type { ILlmUsageMeter } from './llm-usage-meter.js';
12
12
  export { createTokenVerifier, requireExternalSource, requireInternalSource } from './tool-auth.middleware.js';
13
- export type { ToolAuth } from './tool-auth.middleware.js';
13
+ export type { ConnectionChoices, ToolAuth } from './tool-auth.middleware.js';
14
14
  import './tool-auth.middleware.js';