@bevel-software/platform-core-backend 0.33.0 → 0.34.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.
- package/agent-guide/access-control.md +19 -8
- package/agent-guide/html-views.md +231 -5
- package/agent-guide/tool-manuals.md +1 -1
- package/dist/core/catalog-revision.d.ts +12 -1
- package/dist/core/catalog-revision.d.ts.map +1 -1
- package/dist/core/catalog-revision.js +23 -3
- package/dist/core/catalog-revision.js.map +1 -1
- package/dist/core/core-ports.d.ts +41 -0
- package/dist/core/core-ports.d.ts.map +1 -1
- package/dist/core/core-ports.js.map +1 -1
- package/dist/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +14 -7
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +16 -5
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +37 -12
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core/lifecycle.d.ts +16 -0
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +12 -2
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modules/access/access-control.interface.d.ts +17 -9
- package/dist/modules/access/access-control.interface.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +12 -2
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +164 -75
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/access-mutation.service.d.ts +22 -24
- package/dist/modules/access/access-mutation.service.d.ts.map +1 -1
- package/dist/modules/access/access-mutation.service.js +48 -51
- package/dist/modules/access/access-mutation.service.js.map +1 -1
- package/dist/modules/access/access-view.d.ts.map +1 -1
- package/dist/modules/access/access-view.js +12 -11
- package/dist/modules/access/access-view.js.map +1 -1
- package/dist/modules/access/access.routes.d.ts +3 -0
- package/dist/modules/access/access.routes.d.ts.map +1 -1
- package/dist/modules/access/access.routes.js +35 -29
- package/dist/modules/access/access.routes.js.map +1 -1
- package/dist/modules/access/groups-admin.routes.d.ts.map +1 -1
- package/dist/modules/access/groups-admin.routes.js +4 -2
- package/dist/modules/access/groups-admin.routes.js.map +1 -1
- package/dist/modules/access/groups-admin.service.d.ts +44 -13
- package/dist/modules/access/groups-admin.service.d.ts.map +1 -1
- package/dist/modules/access/groups-admin.service.js +80 -38
- package/dist/modules/access/groups-admin.service.js.map +1 -1
- package/dist/modules/access/groups-edit.d.ts +1 -1
- package/dist/modules/access/groups-edit.d.ts.map +1 -1
- package/dist/modules/access/groups-edit.js +1 -1
- package/dist/modules/access/groups-edit.js.map +1 -1
- package/dist/modules/access/reference-scan.d.ts +116 -24
- package/dist/modules/access/reference-scan.d.ts.map +1 -1
- package/dist/modules/access/reference-scan.js +305 -44
- package/dist/modules/access/reference-scan.js.map +1 -1
- package/dist/modules/access/roles-admin.service.d.ts +17 -8
- package/dist/modules/access/roles-admin.service.d.ts.map +1 -1
- package/dist/modules/access/roles-admin.service.js +32 -23
- package/dist/modules/access/roles-admin.service.js.map +1 -1
- package/dist/modules/access-model/access-grammar.d.ts +35 -10
- package/dist/modules/access-model/access-grammar.d.ts.map +1 -1
- package/dist/modules/access-model/access-grammar.js +60 -20
- package/dist/modules/access-model/access-grammar.js.map +1 -1
- package/dist/modules/access-model/access-splice.d.ts +22 -18
- package/dist/modules/access-model/access-splice.d.ts.map +1 -1
- package/dist/modules/access-model/access-splice.js +20 -14
- package/dist/modules/access-model/access-splice.js.map +1 -1
- package/dist/modules/access-model/group-files.d.ts +1 -0
- package/dist/modules/access-model/group-files.d.ts.map +1 -1
- package/dist/modules/access-model/group-files.js +5 -1
- package/dist/modules/access-model/group-files.js.map +1 -1
- package/dist/modules/agent-guide/agent-guide.tools.d.ts.map +1 -1
- package/dist/modules/agent-guide/agent-guide.tools.js +13 -3
- package/dist/modules/agent-guide/agent-guide.tools.js.map +1 -1
- package/dist/modules/agent-instructions/compose.d.ts +3 -1
- package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
- package/dist/modules/agent-instructions/compose.js +3 -1
- package/dist/modules/agent-instructions/compose.js.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.d.ts +5 -1
- package/dist/modules/agent-instructions/shared-file-rules.d.ts.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.js +16 -1
- package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -1
- package/dist/modules/agent-scope/agent-scope.contract.d.ts +67 -0
- package/dist/modules/agent-scope/agent-scope.contract.d.ts.map +1 -0
- package/dist/modules/agent-scope/agent-scope.contract.js +27 -0
- package/dist/modules/agent-scope/agent-scope.contract.js.map +1 -0
- package/dist/modules/agent-scope/connection-scope.d.ts +111 -0
- package/dist/modules/agent-scope/connection-scope.d.ts.map +1 -0
- package/dist/modules/agent-scope/connection-scope.js +165 -0
- package/dist/modules/agent-scope/connection-scope.js.map +1 -0
- package/dist/modules/agent-scope/index.d.ts +3 -0
- package/dist/modules/agent-scope/index.d.ts.map +1 -0
- package/dist/modules/agent-scope/index.js +3 -0
- package/dist/modules/agent-scope/index.js.map +1 -0
- package/dist/modules/audit/agent-audit.service.d.ts.map +1 -1
- package/dist/modules/audit/agent-audit.service.js +2 -0
- package/dist/modules/audit/agent-audit.service.js.map +1 -1
- package/dist/modules/audit/audit.contract.d.ts +6 -0
- package/dist/modules/audit/audit.contract.d.ts.map +1 -1
- package/dist/modules/audit/audit.contract.js.map +1 -1
- package/dist/modules/auth/account-admission.d.ts +12 -0
- package/dist/modules/auth/account-admission.d.ts.map +1 -1
- package/dist/modules/auth/account-admission.js +15 -0
- package/dist/modules/auth/account-admission.js.map +1 -1
- package/dist/modules/auth/auth.middleware.d.ts +27 -1
- package/dist/modules/auth/auth.middleware.d.ts.map +1 -1
- package/dist/modules/auth/auth.middleware.js +42 -4
- package/dist/modules/auth/auth.middleware.js.map +1 -1
- package/dist/modules/auth/auth.routes.d.ts +13 -9
- package/dist/modules/auth/auth.routes.d.ts.map +1 -1
- package/dist/modules/auth/auth.routes.js +35 -29
- package/dist/modules/auth/auth.routes.js.map +1 -1
- package/dist/modules/auth/auth.service.d.ts +55 -6
- package/dist/modules/auth/auth.service.d.ts.map +1 -1
- package/dist/modules/auth/auth.service.js +128 -34
- package/dist/modules/auth/auth.service.js.map +1 -1
- package/dist/modules/auth/index.d.ts +1 -1
- package/dist/modules/auth/index.d.ts.map +1 -1
- package/dist/modules/auth/index.js +1 -1
- package/dist/modules/auth/index.js.map +1 -1
- package/dist/modules/auth/oidc-auth-provider.d.ts.map +1 -1
- package/dist/modules/auth/oidc-auth-provider.js +2 -9
- package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
- package/dist/modules/database/core-schema.d.ts +68 -0
- package/dist/modules/database/core-schema.d.ts.map +1 -1
- package/dist/modules/database/core-schema.js +33 -0
- package/dist/modules/database/core-schema.js.map +1 -1
- package/dist/modules/declared-variables/declared-variables.routes.d.ts +8 -1
- package/dist/modules/declared-variables/declared-variables.routes.d.ts.map +1 -1
- package/dist/modules/declared-variables/declared-variables.routes.js +13 -2
- package/dist/modules/declared-variables/declared-variables.routes.js.map +1 -1
- package/dist/modules/embed/embed.tools.d.ts.map +1 -1
- package/dist/modules/embed/embed.tools.js +5 -0
- package/dist/modules/embed/embed.tools.js.map +1 -1
- package/dist/modules/kb-fs/index.d.ts +2 -0
- package/dist/modules/kb-fs/index.d.ts.map +1 -1
- package/dist/modules/kb-fs/index.js +1 -0
- package/dist/modules/kb-fs/index.js.map +1 -1
- package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
- package/dist/modules/kb-fs/locking-filesystem.js +7 -1
- package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
- package/dist/modules/kb-fs/repo-path.d.ts +26 -6
- package/dist/modules/kb-fs/repo-path.d.ts.map +1 -1
- package/dist/modules/kb-fs/repo-path.js +22 -7
- package/dist/modules/kb-fs/repo-path.js.map +1 -1
- package/dist/modules/kb-fs/tmp-ref.d.ts +36 -0
- package/dist/modules/kb-fs/tmp-ref.d.ts.map +1 -0
- package/dist/modules/kb-fs/tmp-ref.js +76 -0
- package/dist/modules/kb-fs/tmp-ref.js.map +1 -0
- package/dist/modules/mcp/mcp-auth.middleware.d.ts +7 -0
- package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
- package/dist/modules/mcp/mcp-auth.middleware.js +14 -1
- package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
- package/dist/modules/mcp/mcp.routes.d.ts +7 -1
- package/dist/modules/mcp/mcp.routes.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.routes.js +39 -4
- package/dist/modules/mcp/mcp.routes.js.map +1 -1
- package/dist/modules/mcp/mcp.service.d.ts +11 -0
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +68 -13
- package/dist/modules/mcp/mcp.service.js.map +1 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +24 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js +45 -10
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
- package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts +9 -0
- package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts.map +1 -1
- package/dist/modules/mcp/oauth/oauth-consent.routes.js +34 -1
- package/dist/modules/mcp/oauth/oauth-consent.routes.js.map +1 -1
- package/dist/modules/plugins/index.d.ts +1 -1
- package/dist/modules/plugins/index.d.ts.map +1 -1
- package/dist/modules/plugins/index.js.map +1 -1
- package/dist/modules/plugins/plugin-links.d.ts +18 -2
- package/dist/modules/plugins/plugin-links.d.ts.map +1 -1
- package/dist/modules/plugins/plugin-links.js.map +1 -1
- package/dist/modules/plugins/plugins.routes.d.ts +5 -1
- package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.routes.js +32 -5
- package/dist/modules/plugins/plugins.routes.js.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +9 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.js +15 -3
- package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
- package/dist/modules/skills/index.d.ts +3 -3
- package/dist/modules/skills/index.d.ts.map +1 -1
- package/dist/modules/skills/index.js +0 -2
- package/dist/modules/skills/index.js.map +1 -1
- package/dist/modules/skills/skills.contract.d.ts +16 -0
- package/dist/modules/skills/skills.contract.d.ts.map +1 -1
- package/dist/modules/skills/skills.service.d.ts.map +1 -1
- package/dist/modules/skills/skills.service.js +6 -1
- package/dist/modules/skills/skills.service.js.map +1 -1
- package/dist/modules/skills/skills.tools.d.ts.map +1 -1
- package/dist/modules/skills/skills.tools.js +24 -12
- package/dist/modules/skills/skills.tools.js.map +1 -1
- package/dist/modules/tool-auth/external-api-key.interface.d.ts +11 -0
- package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -1
- package/dist/modules/tool-auth/external-api-key.interface.js.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.d.ts +1 -0
- package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.js +4 -1
- package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
- package/dist/modules/tool-auth/index.d.ts +1 -1
- package/dist/modules/tool-auth/index.d.ts.map +1 -1
- package/dist/modules/tool-auth/internal-token.service.d.ts +9 -0
- package/dist/modules/tool-auth/internal-token.service.d.ts.map +1 -1
- package/dist/modules/tool-auth/internal-token.service.js +1 -0
- package/dist/modules/tool-auth/internal-token.service.js.map +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts +27 -3
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.js +32 -6
- package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
- package/dist/modules/tool-helpers/tool-context.d.ts +7 -0
- package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool-context.js +3 -0
- package/dist/modules/tool-helpers/tool-context.js.map +1 -1
- package/dist/modules/tool-helpers/tool-handler.d.ts +15 -0
- package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool-handler.js +19 -0
- package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
- package/dist/modules/tool-helpers/tool.contract.d.ts +10 -0
- package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
- package/dist/modules/tool-helpers/validate-token.d.ts +3 -1
- package/dist/modules/tool-helpers/validate-token.d.ts.map +1 -1
- package/dist/modules/tool-helpers/validate-token.js +1 -1
- package/dist/modules/tool-helpers/validate-token.js.map +1 -1
- package/dist/modules/tool-manuals/index.d.ts +3 -3
- package/dist/modules/tool-manuals/index.d.ts.map +1 -1
- package/dist/modules/tool-manuals/index.js +0 -2
- package/dist/modules/tool-manuals/index.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +19 -6
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +7 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.js +41 -4
- package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts +13 -6
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +23 -15
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +25 -10
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/tool-registry/manual.routes.d.ts +8 -1
- package/dist/modules/tool-registry/manual.routes.d.ts.map +1 -1
- package/dist/modules/tool-registry/manual.routes.js +27 -7
- package/dist/modules/tool-registry/manual.routes.js.map +1 -1
- package/dist/modules/tool-registry/tool.contract.d.ts +7 -0
- package/dist/modules/tool-registry/tool.contract.d.ts.map +1 -1
- package/dist/modules/tool-registry/tool.contract.js.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.js +14 -9
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +2 -2
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +20 -35
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts +2 -1
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +3 -0
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/file-readers/doc-extract.service.d.ts +28 -4
- package/dist/modules/workspace/file-readers/doc-extract.service.d.ts.map +1 -1
- package/dist/modules/workspace/file-readers/doc-extract.service.js +61 -40
- package/dist/modules/workspace/file-readers/doc-extract.service.js.map +1 -1
- package/dist/modules/workspace/index.d.ts +8 -0
- package/dist/modules/workspace/index.d.ts.map +1 -1
- package/dist/modules/workspace/index.js +8 -0
- package/dist/modules/workspace/index.js.map +1 -1
- package/dist/modules/workspace/nul-scan.d.ts +19 -0
- package/dist/modules/workspace/nul-scan.d.ts.map +1 -0
- package/dist/modules/workspace/nul-scan.js +55 -0
- package/dist/modules/workspace/nul-scan.js.map +1 -0
- package/dist/modules/workspace/pattern-matcher.contract.d.ts +110 -27
- package/dist/modules/workspace/pattern-matcher.contract.d.ts.map +1 -1
- package/dist/modules/workspace/pattern-matcher.contract.js +30 -13
- package/dist/modules/workspace/pattern-matcher.contract.js.map +1 -1
- package/dist/modules/workspace/ripgrep-search.d.ts +54 -0
- package/dist/modules/workspace/ripgrep-search.d.ts.map +1 -0
- package/dist/modules/workspace/ripgrep-search.js +657 -0
- package/dist/modules/workspace/ripgrep-search.js.map +1 -0
- package/dist/modules/workspace/ripgrep-version.d.ts +15 -0
- package/dist/modules/workspace/ripgrep-version.d.ts.map +1 -0
- package/dist/modules/workspace/ripgrep-version.js +31 -0
- package/dist/modules/workspace/ripgrep-version.js.map +1 -0
- package/dist/modules/workspace/startup/beside-checkout.d.ts +8 -5
- package/dist/modules/workspace/startup/beside-checkout.d.ts.map +1 -1
- package/dist/modules/workspace/startup/beside-checkout.js +14 -5
- package/dist/modules/workspace/startup/beside-checkout.js.map +1 -1
- package/dist/modules/workspace/worker-pool.d.ts +3 -4
- package/dist/modules/workspace/worker-pool.d.ts.map +1 -1
- package/dist/modules/workspace/worker-pool.js.map +1 -1
- package/dist/modules/workspace/workspace-tmp.d.ts +146 -0
- package/dist/modules/workspace/workspace-tmp.d.ts.map +1 -0
- package/dist/modules/workspace/workspace-tmp.js +435 -0
- package/dist/modules/workspace/workspace-tmp.js.map +1 -0
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.routes.js +5 -26
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +47 -6
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +86 -6
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +460 -116
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/shared/path-order.d.ts +28 -8
- package/dist/shared/path-order.d.ts.map +1 -1
- package/dist/shared/path-order.js +37 -8
- package/dist/shared/path-order.js.map +1 -1
- package/migrations/0022_session_version.sql +6 -0
- package/migrations/0023_agent_path.sql +3 -0
- package/migrations/meta/0022_snapshot.json +2360 -0
- package/migrations/meta/0023_snapshot.json +2378 -0
- package/migrations/meta/_journal.json +14 -0
- package/package.json +3 -3
- package/src/__tests__/pg-scratch.test.ts +69 -0
- package/src/__tests__/pg-scratch.ts +31 -0
- package/src/__tests__/slow-ripgrep.ts +65 -0
- package/src/core/__tests__/boot-without-ripgrep.test.ts +34 -0
- package/src/core/__tests__/catalog-revision.test.ts +89 -0
- package/src/core/__tests__/damaged-document.tools.test.ts +2 -2
- package/src/core/__tests__/gated-boot.test.ts +8 -1
- package/src/core/__tests__/lifecycle.test.ts +46 -13
- package/src/core/catalog-revision.ts +24 -2
- package/src/core/core-ports.ts +42 -0
- package/src/core/create-core-server.ts +13 -0
- package/src/core/create-core-services.ts +49 -12
- package/src/core/lifecycle.ts +26 -2
- package/src/index.ts +1 -1
- package/src/modules/access/__tests__/access-control.admin-root-floor.test.ts +12 -0
- package/src/modules/access/__tests__/access-control.colliding-name-cases.test.ts +113 -0
- package/src/modules/access/__tests__/access-control.frontmatter-head.test.ts +117 -0
- package/src/modules/access/__tests__/access-control.group-named-admin.test.ts +122 -0
- package/src/modules/access/__tests__/access-control.preview-relocation.test.ts +50 -0
- package/src/modules/access/__tests__/access-declarations.test.ts +19 -0
- package/src/modules/access/__tests__/access-groups.test.ts +55 -22
- package/src/modules/access/__tests__/access-mutation.service.test.ts +85 -59
- package/src/modules/access/__tests__/access-restrict-here.test.ts +7 -5
- package/src/modules/access/__tests__/access.routes.admins.test.ts +1 -0
- package/src/modules/access/__tests__/access.routes.batch.test.ts +2 -0
- package/src/modules/access/__tests__/access.routes.folder-governs.test.ts +2 -0
- package/src/modules/access/__tests__/access.routes.group-grant.test.ts +50 -14
- package/src/modules/access/__tests__/access.routes.overrides.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.proposal-branch.test.ts +1 -0
- package/src/modules/access/__tests__/access.routes.prospective.test.ts +2 -0
- package/src/modules/access/__tests__/access.routes.revoke.test.ts +18 -13
- package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +2 -0
- package/src/modules/access/__tests__/grant-sources.test.ts +20 -15
- package/src/modules/access/__tests__/groups-admin.routes.test.ts +61 -0
- package/src/modules/access/__tests__/groups-admin.service.test.ts +211 -18
- package/src/modules/access/__tests__/reference-scan.test.ts +366 -14
- package/src/modules/access/__tests__/roles-admin.security.test.ts +1 -1
- package/src/modules/access/__tests__/roles-admin.service.test.ts +43 -22
- package/src/modules/access/__tests__/roles-capabilities.test.ts +6 -2
- package/src/modules/access/__tests__/roles.routes.test.ts +1 -1
- package/src/modules/access/access-control.interface.ts +17 -10
- package/src/modules/access/access-control.service.ts +158 -72
- package/src/modules/access/access-mutation.service.ts +48 -53
- package/src/modules/access/access-view.ts +12 -10
- package/src/modules/access/access.routes.ts +43 -33
- package/src/modules/access/groups-admin.routes.ts +4 -2
- package/src/modules/access/groups-admin.service.ts +114 -44
- package/src/modules/access/groups-edit.ts +1 -1
- package/src/modules/access/reference-scan.ts +319 -46
- package/src/modules/access/roles-admin.service.ts +43 -26
- package/src/modules/access/synced-groups-writer.ts +1 -1
- package/src/modules/access-model/__tests__/access-grammar.test.ts +38 -1
- package/src/modules/access-model/__tests__/access-splice.test.ts +50 -8
- package/src/modules/access-model/access-grammar.ts +65 -20
- package/src/modules/access-model/access-splice.ts +31 -23
- package/src/modules/access-model/group-files.ts +5 -0
- package/src/modules/agent-guide/__tests__/agent-guide.test.ts +31 -0
- package/src/modules/agent-guide/agent-guide.tools.ts +13 -2
- package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +1 -0
- package/src/modules/agent-instructions/compose.ts +3 -1
- package/src/modules/agent-instructions/shared-file-rules.ts +17 -1
- package/src/modules/agent-scope/__tests__/agent-surfaces.connect-as.test.ts +421 -0
- package/src/modules/agent-scope/__tests__/connection-scope.test.ts +46 -0
- package/src/modules/agent-scope/__tests__/in-memory-kb.ts +148 -0
- package/src/modules/agent-scope/agent-scope.contract.ts +83 -0
- package/src/modules/agent-scope/connection-scope.ts +199 -0
- package/src/modules/agent-scope/index.ts +15 -0
- package/src/modules/audit/agent-audit.service.ts +2 -0
- package/src/modules/audit/audit.contract.ts +6 -0
- package/src/modules/auth/__tests__/auth.middleware.test.ts +30 -2
- package/src/modules/auth/__tests__/auth.routes.test.ts +71 -5
- package/src/modules/auth/__tests__/auth.service.test.ts +90 -9
- package/src/modules/auth/__tests__/password-change-sessions.pg.test.ts +269 -0
- package/src/modules/auth/account-admission.ts +19 -0
- package/src/modules/auth/auth.middleware.ts +45 -4
- package/src/modules/auth/auth.routes.ts +46 -29
- package/src/modules/auth/auth.service.ts +135 -34
- package/src/modules/auth/index.ts +2 -0
- package/src/modules/auth/oidc-auth-provider.ts +2 -9
- package/src/modules/database/__tests__/session-version-migration.pg.test.ts +133 -0
- package/src/modules/database/core-schema.ts +33 -0
- package/src/modules/declared-variables/__tests__/declared-variables.route.test.ts +44 -1
- package/src/modules/declared-variables/declared-variables.routes.ts +12 -1
- package/src/modules/embed/__tests__/embed.tools.test.ts +12 -0
- package/src/modules/embed/embed.tools.ts +5 -0
- package/src/modules/kb-fs/__tests__/locking-filesystem.test.ts +25 -0
- package/src/modules/kb-fs/__tests__/repo-path.test.ts +53 -8
- package/src/modules/kb-fs/index.ts +2 -0
- package/src/modules/kb-fs/locking-filesystem.ts +7 -1
- package/src/modules/kb-fs/repo-path.ts +33 -7
- package/src/modules/kb-fs/tmp-ref.ts +81 -0
- package/src/modules/mcp/__tests__/connect-as.pg.test.ts +137 -0
- package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +29 -5
- package/src/modules/mcp/__tests__/mcp-routes-harness.ts +8 -0
- package/src/modules/mcp/__tests__/mcp.connect-as.test.ts +195 -0
- package/src/modules/mcp/__tests__/mcp.routes.connect-as.test.ts +192 -0
- package/src/modules/mcp/__tests__/oauth-consent.connect-as.test.ts +146 -0
- package/src/modules/mcp/mcp-auth.middleware.ts +19 -2
- package/src/modules/mcp/mcp.routes.ts +39 -3
- package/src/modules/mcp/mcp.service.ts +107 -17
- package/src/modules/mcp/oauth/bevel-oauth-provider.ts +46 -8
- package/src/modules/mcp/oauth/oauth-consent.routes.ts +41 -1
- package/src/modules/plugins/__tests__/plugins.tools.test.ts +38 -2
- package/src/modules/plugins/index.ts +1 -1
- package/src/modules/plugins/plugin-links.ts +19 -2
- package/src/modules/plugins/plugins.routes.ts +35 -4
- package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +113 -0
- package/src/modules/secrets-vault/secrets-vault.routes.ts +23 -3
- package/src/modules/skills/__tests__/skills.service.test.ts +34 -0
- package/src/modules/skills/index.ts +7 -2
- package/src/modules/skills/skills.contract.ts +17 -0
- package/src/modules/skills/skills.service.ts +5 -1
- package/src/modules/skills/skills.tools.ts +44 -13
- package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +4 -0
- package/src/modules/tool-auth/external-api-key.interface.ts +11 -1
- package/src/modules/tool-auth/external-api-key.service.ts +5 -2
- package/src/modules/tool-auth/index.ts +1 -1
- package/src/modules/tool-auth/internal-token.service.ts +10 -0
- package/src/modules/tool-auth/tool-auth.middleware.ts +45 -3
- package/src/modules/tool-helpers/__tests__/can-write.tools.test.ts +3 -1
- package/src/modules/tool-helpers/tool-context.ts +10 -0
- package/src/modules/tool-helpers/tool-handler.ts +34 -0
- package/src/modules/tool-helpers/tool.contract.ts +10 -0
- package/src/modules/tool-helpers/validate-token.ts +4 -2
- package/src/modules/tool-manuals/__tests__/tool-manuals.archive.route.test.ts +80 -4
- package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +42 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +3 -3
- package/src/modules/tool-manuals/index.ts +6 -2
- package/src/modules/tool-manuals/tool-manuals.contract.ts +18 -6
- package/src/modules/tool-manuals/tool-manuals.routes.ts +40 -3
- package/src/modules/tool-manuals/tool-manuals.service.ts +31 -15
- package/src/modules/tool-manuals/tool-manuals.tools.ts +28 -11
- package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +2 -2
- package/src/modules/tool-registry/manual.routes.ts +26 -5
- package/src/modules/tool-registry/tool.contract.ts +7 -0
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +1 -1
- package/src/modules/workflow/__tests__/workflow.service.sync.test.ts +1 -1
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +54 -3
- package/src/modules/workflow/agent-tools/workflow.tools.ts +14 -9
- package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +130 -3
- package/src/modules/workflow/git/git.service.ts +29 -48
- package/src/modules/workflow/workflow.service.ts +5 -0
- package/src/modules/workspace/__tests__/git-internals.security.test.ts +2 -2
- package/src/modules/workspace/__tests__/holds-nul.test.ts +66 -0
- package/src/modules/workspace/__tests__/rest-tool-arguments.test.ts +3 -3
- package/src/modules/workspace/__tests__/ripgrep-search.test.ts +570 -0
- package/src/modules/workspace/__tests__/ripgrep-version.test.ts +29 -0
- package/src/modules/workspace/__tests__/workspace-tmp.tools.test.ts +928 -0
- package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +17 -37
- package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +20 -8
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +22 -10
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +393 -113
- package/src/modules/workspace/file-readers/__tests__/doc-extract.service.test.ts +10 -0
- package/src/modules/workspace/file-readers/doc-extract.service.ts +71 -38
- package/src/modules/workspace/index.ts +20 -0
- package/src/modules/workspace/nul-scan.ts +50 -0
- package/src/modules/workspace/pattern-matcher.contract.ts +123 -32
- package/src/modules/workspace/ripgrep-search.ts +715 -0
- package/src/modules/workspace/ripgrep-version.ts +35 -0
- package/src/modules/workspace/startup/__tests__/beside-checkout.test.ts +11 -0
- package/src/modules/workspace/startup/beside-checkout.ts +13 -5
- package/src/modules/workspace/worker-pool.ts +3 -4
- package/src/modules/workspace/workspace-tmp.ts +457 -0
- package/src/modules/workspace/workspace.routes.ts +6 -27
- package/src/modules/workspace/workspace.service.ts +92 -15
- package/src/modules/workspace/workspace.tools.ts +500 -155
- package/src/shared/path-order.ts +37 -8
- package/starter-packs/engineering/Plugins/engineering-starter/access.md +1 -1
- package/starter-packs/general/Plugins/general-starter/access.md +1 -1
- package/starter-packs/operations/Plugins/operations-starter/access.md +1 -1
- package/starter-packs/sales/Plugins/sales-starter/access.md +1 -1
- package/starter-packs/support/Plugins/support-starter/access.md +1 -1
- package/dist/modules/workspace/bounded-matcher.d.ts +0 -73
- package/dist/modules/workspace/bounded-matcher.d.ts.map +0 -1
- package/dist/modules/workspace/bounded-matcher.js +0 -200
- package/dist/modules/workspace/bounded-matcher.js.map +0 -1
- package/src/modules/workspace/__tests__/bounded-matcher.test.ts +0 -213
- package/src/modules/workspace/bounded-matcher.ts +0 -271
|
@@ -47,6 +47,15 @@ export interface InternalTokenClaim {
|
|
|
47
47
|
* internal token.
|
|
48
48
|
*/
|
|
49
49
|
connectionId?: string;
|
|
50
|
+
/**
|
|
51
|
+
* The agent configuration the external caller's connection was made as (a
|
|
52
|
+
* repo-relative knowledge-base path), copied at mint from the verified
|
|
53
|
+
* grant or connection — the hosted proxy's loopback token and the local
|
|
54
|
+
* server's exchanged grant both carry it, so every agent surface narrows
|
|
55
|
+
* their calls to that agent's scope (`modules/agent-scope`). Absent is
|
|
56
|
+
* Everything. Carried, never decided, like `connectionId`.
|
|
57
|
+
*/
|
|
58
|
+
agentPath?: string;
|
|
50
59
|
}
|
|
51
60
|
|
|
52
61
|
interface SignedPayload extends InternalTokenClaim {
|
|
@@ -148,6 +157,7 @@ export class InternalTokenService {
|
|
|
148
157
|
...(typeof payload.focusedBranch === 'string' ? { focusedBranch: payload.focusedBranch } : {}),
|
|
149
158
|
...(payload.externalProxy === true ? { externalProxy: true } : {}),
|
|
150
159
|
...(typeof payload.connectionId === 'string' ? { connectionId: payload.connectionId } : {}),
|
|
160
|
+
...(typeof payload.agentPath === 'string' && payload.agentPath ? { agentPath: payload.agentPath } : {}),
|
|
151
161
|
};
|
|
152
162
|
}
|
|
153
163
|
|
|
@@ -47,6 +47,13 @@ export interface ToolAuth {
|
|
|
47
47
|
* recorder attributes a direct tool call to.
|
|
48
48
|
*/
|
|
49
49
|
connectionId?: string;
|
|
50
|
+
/**
|
|
51
|
+
* The agent configuration an EXTERNAL caller's connection was made as — a
|
|
52
|
+
* connection key's `api_tokens.agent_path`, or the one an `externalProxy`
|
|
53
|
+
* token carries for an agent connection. Absent is Everything. Every agent
|
|
54
|
+
* surface resolves it to the connection's scope (`modules/agent-scope`).
|
|
55
|
+
*/
|
|
56
|
+
agentPath?: string;
|
|
50
57
|
/** Always `'write'` now (the middleware sets it for both internal + external — neither credential carries scope). The read path is dormant until consumer agents are removed. */
|
|
51
58
|
scope: 'read' | 'write';
|
|
52
59
|
}
|
|
@@ -114,6 +121,14 @@ export type VerifyResult =
|
|
|
114
121
|
| { ok: true; auth: ToolAuth }
|
|
115
122
|
| { ok: false; status: number; message: string; challenge?: string };
|
|
116
123
|
|
|
124
|
+
/**
|
|
125
|
+
* A live agent connection's current "Connect as" choice, or null when it is
|
|
126
|
+
* gone or revoked — what `BevelOAuthProvider.liveConnectionChoice` answers.
|
|
127
|
+
*/
|
|
128
|
+
export interface ConnectionChoices {
|
|
129
|
+
liveConnectionChoice(connectionId: string): Promise<{ agentPath: string | null } | null>;
|
|
130
|
+
}
|
|
131
|
+
|
|
117
132
|
/**
|
|
118
133
|
* The framework-agnostic verify core: bearer token (the value AFTER `Bearer `) →
|
|
119
134
|
* normalized `ToolAuth`, accepting EITHER a `bevel_…` connection key (external —
|
|
@@ -135,6 +150,14 @@ export function createTokenVerifier(
|
|
|
135
150
|
* it; absent, internal tokens are judged on their signature alone.
|
|
136
151
|
*/
|
|
137
152
|
accounts?: Pick<AuthService, 'isActive'>,
|
|
153
|
+
/**
|
|
154
|
+
* Where an `externalProxy` token that names an agent connection reads the
|
|
155
|
+
* connection's CURRENT choice: the token outlives a re-consent, so the
|
|
156
|
+
* agent it was minted with may no longer be the one chosen. A
|
|
157
|
+
* connection no longer live (revoked, deleted) refuses the token. Absent,
|
|
158
|
+
* the token's own choice stands.
|
|
159
|
+
*/
|
|
160
|
+
connections?: ConnectionChoices,
|
|
138
161
|
): (token: string | undefined) => Promise<VerifyResult> {
|
|
139
162
|
const missing = { ok: false as const, status: 401, message: 'A connection key or internal token is required' };
|
|
140
163
|
return async (token) => {
|
|
@@ -152,6 +175,13 @@ export function createTokenVerifier(
|
|
|
152
175
|
if (accounts && !(await accounts.isActive(claim.userId))) {
|
|
153
176
|
return { ok: false, status: 401, message: ACCOUNT_DEACTIVATED_MESSAGE };
|
|
154
177
|
}
|
|
178
|
+
let agentPath = claim.agentPath;
|
|
179
|
+
if (claim.externalProxy && claim.connectionId && connections) {
|
|
180
|
+
const live = await connections.liveConnectionChoice(claim.connectionId);
|
|
181
|
+
// A revoked connection's token is dead here too, as it is at the MCP endpoint.
|
|
182
|
+
if (!live) return { ok: false, status: 401, message: 'Access for this agent was revoked' };
|
|
183
|
+
agentPath = live.agentPath ?? undefined;
|
|
184
|
+
}
|
|
155
185
|
return claim.externalProxy
|
|
156
186
|
? {
|
|
157
187
|
ok: true,
|
|
@@ -159,6 +189,7 @@ export function createTokenVerifier(
|
|
|
159
189
|
source: 'external',
|
|
160
190
|
userId: claim.userId,
|
|
161
191
|
...(claim.connectionId ? { connectionId: claim.connectionId } : {}),
|
|
192
|
+
...(agentPath ? { agentPath } : {}),
|
|
162
193
|
scope: 'write',
|
|
163
194
|
},
|
|
164
195
|
}
|
|
@@ -169,7 +200,16 @@ export function createTokenVerifier(
|
|
|
169
200
|
if (externalApiKeyService.looksLikeExternalApiKey(token)) {
|
|
170
201
|
const resolved = await externalApiKeyService.verifyAndLoadToken(token);
|
|
171
202
|
if (resolved) {
|
|
172
|
-
return {
|
|
203
|
+
return {
|
|
204
|
+
ok: true,
|
|
205
|
+
auth: {
|
|
206
|
+
source: 'external',
|
|
207
|
+
userId: resolved.user.id,
|
|
208
|
+
tokenId: resolved.tokenId,
|
|
209
|
+
...(resolved.agentPath ? { agentPath: resolved.agentPath } : {}),
|
|
210
|
+
scope: 'write',
|
|
211
|
+
},
|
|
212
|
+
};
|
|
173
213
|
}
|
|
174
214
|
// A live key of a switched-off account is told so, not sent to mint another.
|
|
175
215
|
if (await externalApiKeyService.isKeyOfSwitchedOffAccount?.(token)) {
|
|
@@ -192,8 +232,9 @@ export function createToolAuthMiddleware(
|
|
|
192
232
|
externalApiKeyService: IExternalApiKeyService,
|
|
193
233
|
internalTokenService: InternalTokenService,
|
|
194
234
|
accounts?: Pick<AuthService, 'isActive'>,
|
|
235
|
+
connections?: ConnectionChoices,
|
|
195
236
|
): RequestHandler {
|
|
196
|
-
const verify = createTokenVerifier(externalApiKeyService, internalTokenService, accounts);
|
|
237
|
+
const verify = createTokenVerifier(externalApiKeyService, internalTokenService, accounts, connections);
|
|
197
238
|
return async (req: Request, res: Response, next: NextFunction) => {
|
|
198
239
|
const header = req.headers.authorization;
|
|
199
240
|
if (!header || !header.toLowerCase().startsWith('bearer ')) {
|
|
@@ -233,8 +274,9 @@ export function createManualAuthMiddleware(
|
|
|
233
274
|
externalApiKeyService: IExternalApiKeyService,
|
|
234
275
|
internalTokenService: InternalTokenService,
|
|
235
276
|
authService: Pick<AuthService, 'isActive' | 'resolveSession'>,
|
|
277
|
+
connections?: ConnectionChoices,
|
|
236
278
|
): RequestHandler {
|
|
237
|
-
const verify = createTokenVerifier(externalApiKeyService, internalTokenService, authService);
|
|
279
|
+
const verify = createTokenVerifier(externalApiKeyService, internalTokenService, authService, connections);
|
|
238
280
|
return async (req: Request, res: Response, next: NextFunction) => {
|
|
239
281
|
const header = req.headers.authorization;
|
|
240
282
|
if (!header || !header.toLowerCase().startsWith('bearer ')) {
|
|
@@ -24,7 +24,9 @@ import { NodeFs } from '../../kb-fs/node-fs.js';
|
|
|
24
24
|
import { workspaceIdForBranch } from '../../../shared/workspace-id.js';
|
|
25
25
|
import { BranchNotFoundError } from '../../../shared/domain-errors.js';
|
|
26
26
|
import type { WorkspaceService } from '../../workspace/workspace.service.js';
|
|
27
|
-
import {
|
|
27
|
+
import { registerSkillsTools } from '../../skills/index.js';
|
|
28
|
+
// The service itself, from its file: the module entry offers it as a type only.
|
|
29
|
+
import { SkillService } from '../../skills/skills.service.js';
|
|
28
30
|
import { defaultBranchWriteVerdicts } from '../index.js';
|
|
29
31
|
|
|
30
32
|
/**
|
|
@@ -17,6 +17,7 @@ import type { WorkflowEventBus } from '../workflow/index.js';
|
|
|
17
17
|
import type { AuthService } from '../auth/index.js';
|
|
18
18
|
import { ToolError, type ToolContext } from './tool.contract.js';
|
|
19
19
|
import type { ToolAuth } from '../tool-auth/index.js';
|
|
20
|
+
import { resolveConnectionScope, type IAgentScopeResolver } from '../agent-scope/index.js';
|
|
20
21
|
|
|
21
22
|
export interface ToolContextDeps {
|
|
22
23
|
authService: AuthService;
|
|
@@ -40,6 +41,12 @@ export interface ToolContextDeps {
|
|
|
40
41
|
loadActiveGroups?: (
|
|
41
42
|
read: (filename: string) => Promise<string | null>,
|
|
42
43
|
) => Promise<{ groups: GroupsIndex; sourceFile: string; health: { ok: boolean } }>;
|
|
44
|
+
/**
|
|
45
|
+
* Resolves the scope of a connection made as an agent configuration. Every
|
|
46
|
+
* deployment passes it. Absent, a credential that names an agent loads
|
|
47
|
+
* nothing — a narrowing that cannot be read is never read as Everything.
|
|
48
|
+
*/
|
|
49
|
+
agentScope?: Pick<IAgentScopeResolver, 'resolve'>;
|
|
43
50
|
}
|
|
44
51
|
|
|
45
52
|
/** A file's text, or null when it does not exist. Any other failure throws. */
|
|
@@ -149,9 +156,12 @@ export function createToolContextResolver(deps: ToolContextDeps): ResolveToolCon
|
|
|
149
156
|
return fs;
|
|
150
157
|
};
|
|
151
158
|
|
|
159
|
+
const connectionScope = await resolveConnectionScope(deps.agentScope, user.email, auth.agentPath);
|
|
160
|
+
|
|
152
161
|
return {
|
|
153
162
|
user,
|
|
154
163
|
scope: auth.scope,
|
|
164
|
+
connectionScope,
|
|
155
165
|
source: auth.source,
|
|
156
166
|
tokenId: auth.tokenId,
|
|
157
167
|
// For `internal` callers the signed token claim is the ONLY trustworthy
|
|
@@ -13,6 +13,8 @@ import { branchHandlingFor, type BranchHandling } from './tool-def.js';
|
|
|
13
13
|
import { domainErrorBody } from '../../shared/http-errors.js';
|
|
14
14
|
import type { ResolveToolContext } from './tool-context.js';
|
|
15
15
|
import { argumentsRefusal } from './route-argument-check.js';
|
|
16
|
+
import { routeToolName, routeToolSchemasForRequest } from './route-tool-schemas.js';
|
|
17
|
+
import { ConnectionScope, NOT_AVAILABLE_TO_CONNECTION } from '../agent-scope/index.js';
|
|
16
18
|
import { alwaysWritable, READ_ONLY_CODE, refuseWriteTool, type IWriteAccess } from '../write-access/index.js';
|
|
17
19
|
import '../tool-auth/index.js'; // Express Request.toolAuth augmentation
|
|
18
20
|
|
|
@@ -40,6 +42,19 @@ export interface ToolHandlerOptions {
|
|
|
40
42
|
* being refused).
|
|
41
43
|
*/
|
|
42
44
|
branch?: BranchHandling;
|
|
45
|
+
/**
|
|
46
|
+
* The route is ALSO a discovery read of the connection's surface, which
|
|
47
|
+
* both MCP servers make whatever tools the connection is offered:
|
|
48
|
+
* `list_skills` and `get_skill` are how `prompts/list` and `prompts/get`
|
|
49
|
+
* are built, and `list_local_tools` is how the local server learns which
|
|
50
|
+
* connectors it must materialize. A connection's `platformTools` decides
|
|
51
|
+
* which tools its agent is OFFERED — the MCP listing and `tools/call`
|
|
52
|
+
* refuse the rest by name — not what its surface holds, so such a route is
|
|
53
|
+
* not refused for want of a `platformTools` entry. Its answer is still
|
|
54
|
+
* narrowed to the connection's skills or connectors by the handler, and a
|
|
55
|
+
* connection that loads nothing is refused it like any other route.
|
|
56
|
+
*/
|
|
57
|
+
discovery?: boolean;
|
|
43
58
|
}
|
|
44
59
|
|
|
45
60
|
/**
|
|
@@ -255,6 +270,23 @@ export function createToolHandlerFactory(
|
|
|
255
270
|
? withoutBranch(args)
|
|
256
271
|
: args;
|
|
257
272
|
const ctx = await resolve(auth, abort.signal, sessionId);
|
|
273
|
+
// The connection's scope, before the tool runs, for every caller of a
|
|
274
|
+
// hosted platform tool — MCP, a chain, the local server, a script with
|
|
275
|
+
// a key. A connection made as an agent configuration that does not
|
|
276
|
+
// list this tool is refused it by name: the ONE policy,
|
|
277
|
+
// `ConnectionScope.platformToolRefusal`, which the platform-tool routes
|
|
278
|
+
// this handler does not host (the plugin-creation routes) ask as well.
|
|
279
|
+
const toolName = routeToolSchemasForRequest(req.originalUrl)?.name ?? routeToolName(req.originalUrl);
|
|
280
|
+
const scope =
|
|
281
|
+
ctx.connectionScope ?? (auth.agentPath ? ConnectionScope.gone(auth.agentPath) : ConnectionScope.everything());
|
|
282
|
+
// The handler narrows by the scope decided here, so a context built
|
|
283
|
+
// without one cannot read as Everything inside the tool either.
|
|
284
|
+
ctx.connectionScope = scope;
|
|
285
|
+
const refusal = scope.platformToolRefusal(toolName, { discovery: opts.discovery === true });
|
|
286
|
+
if (refusal) {
|
|
287
|
+
res.status(403).json(refusal);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
258
290
|
if (resolved) ctx.branch = resolved.branch;
|
|
259
291
|
let out = await handler(toolArgs, ctx);
|
|
260
292
|
// A defaulted call's answer says which branch it ran on, so a caller
|
|
@@ -315,3 +347,5 @@ function withoutBranch(args: Record<string, unknown>): Record<string, unknown> {
|
|
|
315
347
|
}
|
|
316
348
|
|
|
317
349
|
export type ToolHandlerFactory = ReturnType<typeof createToolHandlerFactory>;
|
|
350
|
+
|
|
351
|
+
export { NOT_AVAILABLE_TO_CONNECTION };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AuthUser, IWorkflowService } from '@bevel-software/platform-shared';
|
|
2
|
+
import type { ConnectionScope } from '../agent-scope/index.js';
|
|
2
3
|
import type { LocalFilesystem } from '@mastra/core/workspace';
|
|
3
4
|
import type { WorkspaceService } from '../workspace/index.js';
|
|
4
5
|
import type { WorkflowEventBus } from '../workflow/index.js';
|
|
@@ -58,6 +59,15 @@ export interface ToolContext {
|
|
|
58
59
|
* tool that takes no branch.
|
|
59
60
|
*/
|
|
60
61
|
branch?: string;
|
|
62
|
+
/**
|
|
63
|
+
* What the caller's connection may load (`modules/agent-scope`): resolved
|
|
64
|
+
* once per call from the agent configuration its credential connects as. The
|
|
65
|
+
* tool handler refuses a platform tool outside it before the tool runs; the
|
|
66
|
+
* tools that list skills and connectors narrow by it. Absent is Everything
|
|
67
|
+
* — and a context built without it for a credential that names an agent is
|
|
68
|
+
* refused every tool by the handler, never served Everything.
|
|
69
|
+
*/
|
|
70
|
+
connectionScope?: ConnectionScope;
|
|
61
71
|
abortSignal: AbortSignal;
|
|
62
72
|
workspaceService: WorkspaceService;
|
|
63
73
|
workflowService: IWorkflowService;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IExternalApiKeyService, InternalTokenService } from '../tool-auth/index.js';
|
|
1
|
+
import type { IExternalApiKeyService, InternalTokenService, ConnectionChoices } from '../tool-auth/index.js';
|
|
2
2
|
import { createTokenVerifier } from '../tool-auth/index.js';
|
|
3
3
|
import { createToolContextResolver, type ToolContextDeps } from './tool-context.js';
|
|
4
4
|
import { ToolError, type ToolContext } from './tool.contract.js';
|
|
@@ -6,6 +6,8 @@ import { ToolError, type ToolContext } from './tool.contract.js';
|
|
|
6
6
|
export interface ToolValidatorDeps extends ToolContextDeps {
|
|
7
7
|
externalApiKeyService: IExternalApiKeyService;
|
|
8
8
|
internalTokenService: InternalTokenService;
|
|
9
|
+
/** Where an agent connection's current "Connect as" choice is read (see `createTokenVerifier`). */
|
|
10
|
+
connections?: ConnectionChoices;
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
/**
|
|
@@ -34,7 +36,7 @@ export type ValidateToken = (
|
|
|
34
36
|
) => Promise<ToolContext>;
|
|
35
37
|
|
|
36
38
|
export function createToolValidator(deps: ToolValidatorDeps): ValidateToken {
|
|
37
|
-
const verify = createTokenVerifier(deps.externalApiKeyService, deps.internalTokenService, deps.authService);
|
|
39
|
+
const verify = createTokenVerifier(deps.externalApiKeyService, deps.internalTokenService, deps.authService, deps.connections);
|
|
38
40
|
const resolve = createToolContextResolver(deps);
|
|
39
41
|
return async (token, signal) => {
|
|
40
42
|
let result;
|
|
@@ -12,6 +12,7 @@ import type { WorkspaceService } from '../../workspace/workspace.service.js';
|
|
|
12
12
|
import type { IAccessControl } from '../../access/access-control.interface.js';
|
|
13
13
|
import type { IToolManualService } from '../tool-manuals.contract.js';
|
|
14
14
|
import { testKbContext } from '../../../__tests__/kb-context.js';
|
|
15
|
+
import { ConnectionScope, type IAgentScopeResolver } from '../../agent-scope/index.js';
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* `GET /agent/plugins/:folder/archive` — error taxonomy of the plugin-folder
|
|
@@ -27,10 +28,20 @@ let httpServer: HttpServer | undefined;
|
|
|
27
28
|
let root: string;
|
|
28
29
|
let wsDir: string;
|
|
29
30
|
|
|
30
|
-
async function baseUrl(
|
|
31
|
+
async function baseUrl(
|
|
32
|
+
pluginIndex?: { catalog(): Promise<{ name: string; folders: string[] }[]> },
|
|
33
|
+
/** The connection's `.agent` choice; absent is Everything. */
|
|
34
|
+
connection?: {
|
|
35
|
+
agentPath: string;
|
|
36
|
+
agentScope?: Pick<IAgentScopeResolver, 'resolve'>;
|
|
37
|
+
/** Whether the person may read the plugin's files; default yes. */
|
|
38
|
+
readable?: boolean;
|
|
39
|
+
},
|
|
40
|
+
toolManualService: IToolManualService = {} as unknown as IToolManualService,
|
|
41
|
+
): Promise<string> {
|
|
31
42
|
const app = express();
|
|
32
43
|
const manualAuth: express.RequestHandler = (req, _res, next) => {
|
|
33
|
-
req.toolAuth = { userId: 'u-1' } as never;
|
|
44
|
+
req.toolAuth = { userId: 'u-1', ...(connection ? { agentPath: connection.agentPath } : {}) } as never;
|
|
34
45
|
next();
|
|
35
46
|
};
|
|
36
47
|
const workspaceService = {
|
|
@@ -39,16 +50,17 @@ async function baseUrl(pluginIndex?: { catalog(): Promise<{ name: string; folder
|
|
|
39
50
|
} as unknown as WorkspaceService;
|
|
40
51
|
const accessControl = {
|
|
41
52
|
canReadBatch: vi.fn(async (_ws: string, _email: string, rels: string[]) => {
|
|
42
|
-
return new Map(rels.map((r) => [r, true]));
|
|
53
|
+
return new Map(rels.map((r) => [r, connection?.readable ?? true]));
|
|
43
54
|
}),
|
|
44
55
|
} as unknown as IAccessControl;
|
|
45
56
|
app.use(
|
|
46
57
|
'/api',
|
|
47
58
|
createToolManualsAgentRoutes(
|
|
48
|
-
|
|
59
|
+
toolManualService,
|
|
49
60
|
manualAuth,
|
|
50
61
|
async () => 'ali@example.com',
|
|
51
62
|
{ workspaceService, accessControl, kb: testKbContext({ kbDirName: KB }), disk: new NodeFs(), pluginIndex: pluginIndex as never },
|
|
63
|
+
connection?.agentScope,
|
|
52
64
|
),
|
|
53
65
|
);
|
|
54
66
|
httpServer = await new Promise<HttpServer>((resolve) => {
|
|
@@ -71,7 +83,53 @@ afterEach(async () => {
|
|
|
71
83
|
await fs.rm(root, { recursive: true, force: true });
|
|
72
84
|
});
|
|
73
85
|
|
|
86
|
+
const OPS = { path: 'Agents/ops.agent', name: 'Ops' };
|
|
87
|
+
/** A resolver that narrows every connection to `connectors`. */
|
|
88
|
+
function loading(connectors: string[]): Pick<IAgentScopeResolver, 'resolve'> {
|
|
89
|
+
return { resolve: async () => ConnectionScope.narrowed(OPS, { skills: [], connectors, platformTools: null }, 'fp') };
|
|
90
|
+
}
|
|
91
|
+
|
|
74
92
|
describe('GET /agent/plugins/:folder/archive', () => {
|
|
93
|
+
it("a connection made as an .agent file archives only a plugin defining a connector the file loads", async () => {
|
|
94
|
+
const pluginDir = path.join(wsDir, KB, 'Plugins', 'GTM');
|
|
95
|
+
await fs.mkdir(pluginDir, { recursive: true });
|
|
96
|
+
await fs.writeFile(path.join(pluginDir, 'mcp.json'), '{"mcpServers":{}}', 'utf-8');
|
|
97
|
+
const archive = async (connectors: string[] | null) => {
|
|
98
|
+
const base = await baseUrl(undefined, {
|
|
99
|
+
agentPath: OPS.path,
|
|
100
|
+
...(connectors ? { agentScope: loading(connectors) } : {}),
|
|
101
|
+
});
|
|
102
|
+
const res = await fetch(`${base}/api/agent/plugins/GTM/archive`);
|
|
103
|
+
await new Promise<void>((r) => httpServer!.close(() => r()));
|
|
104
|
+
httpServer = undefined;
|
|
105
|
+
return res;
|
|
106
|
+
};
|
|
107
|
+
// The plugin's own definition file, the plugin folder, a folder above it.
|
|
108
|
+
expect((await archive(['Plugins/GTM/mcp.json'])).status).toBe(200);
|
|
109
|
+
expect((await archive(['Plugins/GTM'])).status).toBe(200);
|
|
110
|
+
expect((await archive(['Plugins'])).status).toBe(200);
|
|
111
|
+
// A connector elsewhere: refused by name, before anything is read.
|
|
112
|
+
const refused = await archive(['Plugins/Other']);
|
|
113
|
+
expect(refused.status).toBe(403);
|
|
114
|
+
const body = (await refused.json()) as { error: string; code: string };
|
|
115
|
+
expect(body.code).toBe('not_available_to_connection');
|
|
116
|
+
expect(body.error).toContain('The plugin "GTM" is not available to this connection.');
|
|
117
|
+
// A narrowed connection with no resolver wired loads nothing.
|
|
118
|
+
expect((await archive(null)).status).toBe(403);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('an out-of-scope plugin folder the person cannot read answers the 404 an absent one does', async () => {
|
|
122
|
+
const pluginDir = path.join(wsDir, KB, 'Plugins', 'Private');
|
|
123
|
+
await fs.mkdir(pluginDir, { recursive: true });
|
|
124
|
+
await fs.writeFile(path.join(pluginDir, 'mcp.json'), '{"mcpServers":{}}', 'utf-8');
|
|
125
|
+
const base = await baseUrl(undefined, { agentPath: OPS.path, agentScope: loading(['Plugins/Other']), readable: false });
|
|
126
|
+
const existing = await fetch(`${base}/api/agent/plugins/Private/archive`);
|
|
127
|
+
const absent = await fetch(`${base}/api/agent/plugins/Nowhere/archive`);
|
|
128
|
+
expect(existing.status).toBe(404);
|
|
129
|
+
expect(await existing.json()).toEqual(await absent.json());
|
|
130
|
+
expect(absent.status).toBe(404);
|
|
131
|
+
});
|
|
132
|
+
|
|
75
133
|
it('zips a readable plugin folder', async () => {
|
|
76
134
|
const pluginDir = path.join(wsDir, KB, 'Plugins', 'GTM');
|
|
77
135
|
await fs.mkdir(pluginDir, { recursive: true });
|
|
@@ -119,3 +177,21 @@ describe('GET /agent/plugins/:folder/archive', () => {
|
|
|
119
177
|
expect(await res.json()).toEqual({ error: 'Failed to archive plugin' });
|
|
120
178
|
});
|
|
121
179
|
});
|
|
180
|
+
|
|
181
|
+
describe('GET /tools/:slug/manual', () => {
|
|
182
|
+
it("narrows an inline manual read to the connectors the connection's .agent file loads", async () => {
|
|
183
|
+
const resolveInlineManual = vi.fn(async () => ({ utcp_version: '1.1.0', manual_version: '1.0.0', tools: [] }));
|
|
184
|
+
const service = { resolveInlineManual } as unknown as IToolManualService;
|
|
185
|
+
// Everything asks exactly what it asked before: no narrowing at all.
|
|
186
|
+
let base = await baseUrl(undefined, undefined, service);
|
|
187
|
+
expect((await fetch(`${base}/api/tools/weather/manual`)).status).toBe(200);
|
|
188
|
+
expect(resolveInlineManual).toHaveBeenLastCalledWith('ali@example.com', 'weather', undefined);
|
|
189
|
+
await new Promise<void>((r) => httpServer!.close(() => r()));
|
|
190
|
+
|
|
191
|
+
base = await baseUrl(undefined, { agentPath: OPS.path, agentScope: loading(['Plugins/GTM']) }, service);
|
|
192
|
+
expect((await fetch(`${base}/api/tools/weather/manual`)).status).toBe(200);
|
|
193
|
+
const within = (resolveInlineManual.mock.calls.at(-1) as unknown[])[2] as { within: (p: string) => boolean };
|
|
194
|
+
expect(within.within('Plugins/GTM/weather.tool')).toBe(true);
|
|
195
|
+
expect(within.within('Plugins/Other/weather.tool')).toBe(false);
|
|
196
|
+
});
|
|
197
|
+
});
|
|
@@ -183,6 +183,15 @@ describe('ToolManualService', () => {
|
|
|
183
183
|
expect(manual).toBeNull();
|
|
184
184
|
});
|
|
185
185
|
|
|
186
|
+
test("does not resolve a readable inline manual outside a connection's connectors", async () => {
|
|
187
|
+
// The narrowing applies after the read gate, on the manual's own path.
|
|
188
|
+
const paths: string[] = [];
|
|
189
|
+
const within = (p: string) => (paths.push(p), false);
|
|
190
|
+
expect(await svc().resolveInlineManual('user@x.eu', 'weather', { within })).toBeNull();
|
|
191
|
+
expect(paths).toEqual([expect.stringMatching(/weather\.tool$/)]);
|
|
192
|
+
expect(await svc().resolveInlineManual('user@x.eu', 'weather', { within: () => true })).not.toBeNull();
|
|
193
|
+
});
|
|
194
|
+
|
|
186
195
|
test('resolves an inline tool that calls Google as a service account, and surfaces the key variable', async () => {
|
|
187
196
|
// The auth block is what makes the call; the key it names has to reach the
|
|
188
197
|
// secrets UI as a shared variable or nobody can store it.
|
|
@@ -486,6 +495,30 @@ describe('ToolManualService', () => {
|
|
|
486
495
|
});
|
|
487
496
|
});
|
|
488
497
|
|
|
498
|
+
/**
|
|
499
|
+
* A connection made as an `.agent` file narrows the catalog (`within`) —
|
|
500
|
+
* AFTER the read gate, on every read an agent surface makes, so it can take
|
|
501
|
+
* a manual away and never give one.
|
|
502
|
+
*/
|
|
503
|
+
describe('narrowed to a connection’s connectors', () => {
|
|
504
|
+
const onlyBilling = (p: string) => p === 'Plugins/billing.tool';
|
|
505
|
+
const everything = () => true;
|
|
506
|
+
|
|
507
|
+
test('every agent-facing read answers only what is both readable and within', async () => {
|
|
508
|
+
const s = svc();
|
|
509
|
+
expect((await s.toManualCallTemplates('user@x.eu', { within: onlyBilling })).map((t) => t.name)).toEqual(['billing']);
|
|
510
|
+
expect((await s.listAccessibleCatalog('user@x.eu', onlyBilling)).tools.map((t) => t.name)).toEqual(['billing']);
|
|
511
|
+
expect(await s.catalogFingerprints('user@x.eu', onlyBilling)).toHaveLength(1);
|
|
512
|
+
expect(await s.listLocalOnly('user@x.eu', () => false)).toEqual([]);
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
test('an entry naming a manual the person may not read loads nothing for it', async () => {
|
|
516
|
+
const s = svc(denyBilling);
|
|
517
|
+
expect(await s.toManualCallTemplates('user@x.eu', { within: onlyBilling })).toEqual([]);
|
|
518
|
+
expect((await s.toManualCallTemplates('user@x.eu', { within: everything })).map((t) => t.name)).toEqual(['weather']);
|
|
519
|
+
});
|
|
520
|
+
});
|
|
521
|
+
|
|
489
522
|
test('skips a `.tool` with a malformed `variables` entry (never silently mis-scoped)', async () => {
|
|
490
523
|
root = await mkdtemp(join(tmpdir(), 'toolsvbad-'));
|
|
491
524
|
const tools = join(root, wsId, KB_DIR, 'Plugins');
|
|
@@ -920,6 +953,15 @@ describe('ToolManualService.listDeclaredOnlyOnBranch', () => {
|
|
|
920
953
|
]);
|
|
921
954
|
});
|
|
922
955
|
|
|
956
|
+
test("narrowed to a connection's connectors, after the read gate", async () => {
|
|
957
|
+
await writeMcpJson(draftWs, 'Ops', ['pager']);
|
|
958
|
+
expect(await svc().listDeclaredOnlyOnBranch('user@example.com', DRAFT, (p) => p.startsWith('Plugins/Ops/'))).toEqual([
|
|
959
|
+
{ name: 'pager', path: 'Plugins/Ops/mcp.json', type: 'mcp' },
|
|
960
|
+
]);
|
|
961
|
+
// Naming an unreadable declaration does not let it through.
|
|
962
|
+
expect(await svc().listDeclaredOnlyOnBranch('user@example.com', DRAFT, (p) => p.startsWith('Plugins/Secret Plugin/'))).toEqual([]);
|
|
963
|
+
});
|
|
964
|
+
|
|
923
965
|
test('is empty for the default branch itself and for a branch without a workspace', async () => {
|
|
924
966
|
expect(await svc().listDeclaredOnlyOnBranch('user@example.com', DEFAULT_BRANCH)).toEqual([]);
|
|
925
967
|
expect(await svc().listDeclaredOnlyOnBranch('user@example.com', 'user/gone')).toEqual([]);
|
|
@@ -273,7 +273,7 @@ describe('list_tool_setup — a declaration that lives on a draft says so', () =
|
|
|
273
273
|
note?: string;
|
|
274
274
|
};
|
|
275
275
|
// Resolved for the caller, on the branch they named.
|
|
276
|
-
expect(toolManualService.listDeclaredOnlyOnBranch).toHaveBeenCalledWith(ALICE.email, 'alice/add-crm');
|
|
276
|
+
expect(toolManualService.listDeclaredOnlyOnBranch).toHaveBeenCalledWith(ALICE.email, 'alice/add-crm', undefined);
|
|
277
277
|
// The released catalog is unchanged — the draft's server is not in it...
|
|
278
278
|
expect(body.tools.map((t) => t.slug)).not.toContain('crm');
|
|
279
279
|
// ...and the agent is told where it is and what makes it live.
|
|
@@ -294,7 +294,7 @@ describe('list_tool_setup — a declaration that lives on a draft says so', () =
|
|
|
294
294
|
const res = await callSetup(base, agentToken);
|
|
295
295
|
expect(res.status).toBe(200);
|
|
296
296
|
const body = (await res.json()) as { onBranchOnly: { name: string; branch: string }[]; note?: string };
|
|
297
|
-
expect(toolManualService.listDeclaredOnlyOnBranch).toHaveBeenCalledWith(ALICE.email, 'alice/add-crm');
|
|
297
|
+
expect(toolManualService.listDeclaredOnlyOnBranch).toHaveBeenCalledWith(ALICE.email, 'alice/add-crm', undefined);
|
|
298
298
|
expect(body.onBranchOnly).toEqual([
|
|
299
299
|
{ name: 'crm', path: 'Plugins/Sales/mcp.json', type: 'mcp', branch: 'alice/add-crm' },
|
|
300
300
|
]);
|
|
@@ -311,7 +311,7 @@ describe('list_tool_setup — a declaration that lives on a draft says so', () =
|
|
|
311
311
|
onBranchOnly: { name: string }[];
|
|
312
312
|
};
|
|
313
313
|
expect(toolManualService.listDeclaredOnlyOnBranch).toHaveBeenCalledTimes(1);
|
|
314
|
-
expect(toolManualService.listDeclaredOnlyOnBranch).toHaveBeenCalledWith(ALICE.email, 'alice/add-crm');
|
|
314
|
+
expect(toolManualService.listDeclaredOnlyOnBranch).toHaveBeenCalledWith(ALICE.email, 'alice/add-crm', undefined);
|
|
315
315
|
expect(body.onBranchOnly.map((p) => p.name)).toEqual(['crm']);
|
|
316
316
|
});
|
|
317
317
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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 { ToolManualService } from './tool-manuals.service.js';
|
|
5
|
+
export type { PendingToolsService } from './pending-tools.service.js';
|
|
3
6
|
export { registerToolManualsTools } from './tool-manuals.tools.js';
|
|
4
7
|
export {
|
|
5
8
|
createToolManualsAgentRoutes,
|
|
@@ -7,6 +10,7 @@ export {
|
|
|
7
10
|
} from './tool-manuals.routes.js';
|
|
8
11
|
export {
|
|
9
12
|
EXTERNAL_KB_MANUAL_NAME,
|
|
13
|
+
type ConnectorScope,
|
|
10
14
|
type IPendingToolService,
|
|
11
15
|
type IToolManualService,
|
|
12
16
|
type PendingTool,
|
|
@@ -356,6 +356,16 @@ export interface ToolManualDetail extends Omit<ToolManualSummary, 'description'>
|
|
|
356
356
|
hiddenTools: HiddenTool[];
|
|
357
357
|
}
|
|
358
358
|
|
|
359
|
+
/**
|
|
360
|
+
* A connection's narrowing of the catalog: whether the connector defined at
|
|
361
|
+
* `definitionPath` (a `.tool` file, or the MCP server definition a server
|
|
362
|
+
* entry came from) is one the connection loads. Applied AFTER the caller's
|
|
363
|
+
* read gate, so it can only take manuals away. The agent surfaces pass the
|
|
364
|
+
* connection scope's `allowsConnector` (`modules/agent-scope`); absent is the
|
|
365
|
+
* whole readable catalog.
|
|
366
|
+
*/
|
|
367
|
+
export type ConnectorScope = (definitionPath: string) => boolean;
|
|
368
|
+
|
|
359
369
|
export interface IToolManualService {
|
|
360
370
|
/** The `.tool` manuals the user can read, as summaries. */
|
|
361
371
|
listAccessible(userEmail: string): Promise<ToolManualSummary[]>;
|
|
@@ -377,7 +387,7 @@ export interface IToolManualService {
|
|
|
377
387
|
* unparseable by definition, so the verdict comes from its folder's
|
|
378
388
|
* `access.md` chain — default-deny, as everywhere else.
|
|
379
389
|
*/
|
|
380
|
-
listAccessibleCatalog(userEmail: string): Promise<AccessibleCatalog>;
|
|
390
|
+
listAccessibleCatalog(userEmail: string, within?: ConnectorScope): Promise<AccessibleCatalog>;
|
|
381
391
|
/**
|
|
382
392
|
* One readable `.tool` by slug, with its description + capabilities, for the
|
|
383
393
|
* browser tool page. `null` when no such slug exists OR the caller can't read
|
|
@@ -406,7 +416,7 @@ export interface IToolManualService {
|
|
|
406
416
|
* manual's embedded tools breaks without touching anything a summary shows.
|
|
407
417
|
* Opaque to callers: only equality is ever asked of these lines.
|
|
408
418
|
*/
|
|
409
|
-
catalogFingerprints(userEmail: string): Promise<string[]>;
|
|
419
|
+
catalogFingerprints(userEmail: string, within?: ConnectorScope): Promise<string[]>;
|
|
410
420
|
/**
|
|
411
421
|
* Every manual in the catalog, UNFILTERED by access — the mirror of
|
|
412
422
|
* `skillService.listSkills(undefined)`. For caller-INDEPENDENT counting only
|
|
@@ -422,7 +432,7 @@ export interface IToolManualService {
|
|
|
422
432
|
* NOT include the KB manual (the route prepends that). With `{ remoteOnly: true }`
|
|
423
433
|
* (the remote MCP proxy), LOCAL-ONLY manuals (`remote: false`) are excluded.
|
|
424
434
|
*/
|
|
425
|
-
toManualCallTemplates(userEmail: string, opts?: { remoteOnly?: boolean }): Promise<CallTemplate[]>;
|
|
435
|
+
toManualCallTemplates(userEmail: string, opts?: { remoteOnly?: boolean; within?: ConnectorScope }): Promise<CallTemplate[]>;
|
|
426
436
|
/**
|
|
427
437
|
* The caller's accessible LOCAL-ONLY (`remote: false`) manuals.
|
|
428
438
|
*
|
|
@@ -430,21 +440,23 @@ export interface IToolManualService {
|
|
|
430
440
|
* both: `name` is the UTCP namespace its `${VAR}` refs are keyed by, and
|
|
431
441
|
* `slug` is what addresses the manual on the variable-resolution route.
|
|
432
442
|
*/
|
|
433
|
-
listLocalOnly(userEmail: string): Promise<{ slug: string; name: string; path: string }[]>;
|
|
443
|
+
listLocalOnly(userEmail: string, within?: ConnectorScope): Promise<{ slug: string; name: string; path: string }[]>;
|
|
434
444
|
/**
|
|
435
445
|
* Tools declared on `branch` whose namespace the default-branch catalog does
|
|
436
446
|
* not serve yet, filtered to what the caller can read there. The catalog is
|
|
437
447
|
* built from the default branch only, so a server an agent declares on its
|
|
438
448
|
* draft is invisible to every tool surface until the draft is merged — this
|
|
439
449
|
* is how the agent is told where its declaration lives. `[]` for the default
|
|
440
|
-
* branch itself, or a branch with no workspace.
|
|
450
|
+
* branch itself, or a branch with no workspace. `within` narrows the answer
|
|
451
|
+
* to a connection's connectors, after the read gate, as the catalog's does.
|
|
441
452
|
*/
|
|
442
453
|
listDeclaredOnlyOnBranch(
|
|
443
454
|
userEmail: string,
|
|
444
455
|
branch: string,
|
|
456
|
+
within?: ConnectorScope,
|
|
445
457
|
): Promise<{ name: string; path: string; type: ToolManualType }[]>;
|
|
446
458
|
/** The embedded UTCP manual for an inline `.tool` (served at `/api/tools/:slug/manual`). */
|
|
447
|
-
resolveInlineManual(userEmail: string, slug: string): Promise<UtcpManualDict | null>;
|
|
459
|
+
resolveInlineManual(userEmail: string, slug: string, opts?: { within?: ConnectorScope }): Promise<UtcpManualDict | null>;
|
|
448
460
|
/** Validate a draft `.tool` file's content for the renderer preview. */
|
|
449
461
|
preview(content: string): Promise<ToolManualPreview>;
|
|
450
462
|
/**
|