@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.
- package/agent-guide/access-control.md +146 -289
- package/agent-guide/conventions.md +23 -25
- package/agent-guide/directory-structure.md +72 -120
- package/agent-guide/drafts-and-change-requests.md +92 -0
- package/agent-guide/for-git-users.md +47 -0
- package/agent-guide/glossary.md +36 -0
- package/agent-guide/how-agents-find-things.md +49 -0
- package/agent-guide/html-views.md +239 -8
- package/agent-guide/new-knowledge-base.md +9 -8
- package/agent-guide/skills.md +67 -42
- package/agent-guide/start-here.md +65 -0
- package/agent-guide/tool-manuals.md +133 -155
- package/agent-guide/tools.md +67 -0
- package/agent-guide/where-a-new-file-goes.md +45 -28
- 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 +15 -8
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +22 -5
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +44 -16
- 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 +39 -9
- package/dist/modules/access/access-control.interface.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +15 -3
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +239 -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 +58 -33
- 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/index.d.ts +1 -1
- package/dist/modules/access/index.d.ts.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.d.ts +47 -7
- package/dist/modules/agent-guide/agent-guide.d.ts.map +1 -1
- package/dist/modules/agent-guide/agent-guide.js +103 -13
- package/dist/modules/agent-guide/agent-guide.js.map +1 -1
- package/dist/modules/agent-guide/agent-guide.tools.d.ts +6 -2
- package/dist/modules/agent-guide/agent-guide.tools.d.ts.map +1 -1
- package/dist/modules/agent-guide/agent-guide.tools.js +46 -22
- package/dist/modules/agent-guide/agent-guide.tools.js.map +1 -1
- package/dist/modules/agent-guide/guide-budget.d.ts +48 -0
- package/dist/modules/agent-guide/guide-budget.d.ts.map +1 -0
- package/dist/modules/agent-guide/guide-budget.js +67 -0
- package/dist/modules/agent-guide/guide-budget.js.map +1 -0
- package/dist/modules/agent-guide/index.d.ts +2 -1
- package/dist/modules/agent-guide/index.d.ts.map +1 -1
- package/dist/modules/agent-guide/index.js +2 -1
- package/dist/modules/agent-guide/index.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 +7 -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 +26 -9
- 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/code-mode/code-mode.tool.js +2 -2
- package/dist/modules/code-mode/code-mode.tool.js.map +1 -1
- package/dist/modules/connection-probe/connection-probe.service.d.ts +0 -12
- package/dist/modules/connection-probe/connection-probe.service.d.ts.map +1 -1
- package/dist/modules/connection-probe/connection-probe.service.js +1 -38
- package/dist/modules/connection-probe/connection-probe.service.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 +74 -48
- 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/db-secrets-vault.service.d.ts +11 -1
- package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts.map +1 -1
- package/dist/modules/secrets-vault/db-secrets-vault.service.js +159 -24
- package/dist/modules/secrets-vault/db-secrets-vault.service.js.map +1 -1
- package/dist/modules/secrets-vault/index.d.ts +1 -1
- package/dist/modules/secrets-vault/index.d.ts.map +1 -1
- package/dist/modules/secrets-vault/index.js +1 -1
- package/dist/modules/secrets-vault/index.js.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.contract.d.ts +53 -11
- package/dist/modules/secrets-vault/secrets-vault.contract.d.ts.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.contract.js +27 -0
- package/dist/modules/secrets-vault/secrets-vault.contract.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 +100 -42
- package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
- package/dist/modules/settings/oidc-check.d.ts.map +1 -1
- package/dist/modules/settings/oidc-check.js +5 -17
- package/dist/modules/settings/oidc-check.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 +25 -13
- 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-def.js +1 -1
- package/dist/modules/tool-helpers/tool-def.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/mcp-json-discovery.d.ts +7 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.d.ts.map +1 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.js +69 -38
- package/dist/modules/tool-manuals/mcp-json-discovery.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +46 -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 +24 -13
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +138 -59
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +8 -2
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +56 -20
- 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 +36 -27
- 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/agent-access.gate.d.ts +1 -1
- package/dist/modules/workspace/agent-access.gate.d.ts.map +1 -1
- package/dist/modules/workspace/agent-access.gate.js +1 -1
- package/dist/modules/workspace/agent-access.gate.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 +3 -2
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +531 -137
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/shared/oauth-token-error.d.ts +23 -0
- package/dist/shared/oauth-token-error.d.ts.map +1 -0
- package/dist/shared/oauth-token-error.js +47 -0
- package/dist/shared/oauth-token-error.js.map +1 -0
- 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/dist/shared/read-capped.d.ts +19 -0
- package/dist/shared/read-capped.d.ts.map +1 -0
- package/dist/shared/read-capped.js +45 -0
- package/dist/shared/read-capped.js.map +1 -0
- 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 +4 -3
- package/src/__tests__/hexis-catalog.ts +144 -0
- package/src/__tests__/pg-scratch.test.ts +69 -0
- package/src/__tests__/pg-scratch.ts +31 -0
- package/src/__tests__/real-disk.ts +21 -0
- package/src/__tests__/slow-ripgrep.ts +65 -0
- package/src/__tests__/tokens.ts +19 -0
- package/src/__tests__/tool-manuals.ts +32 -0
- package/src/__tests__/tool-wiring.ts +25 -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/__tests__/oauth-sign-in-real-file.test.ts +179 -0
- package/src/core/catalog-revision.ts +24 -2
- package/src/core/core-ports.ts +42 -0
- package/src/core/create-core-server.ts +14 -1
- package/src/core/create-core-services.ts +62 -15
- 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 +52 -10
- 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__/holder-changes.test.ts +127 -0
- 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 +43 -10
- package/src/modules/access/access-control.service.ts +250 -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 +66 -37
- 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/index.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 +110 -25
- package/src/modules/agent-guide/__tests__/agent-guide.tools.test.ts +38 -11
- package/src/modules/agent-guide/__tests__/guide-budget.test.ts +95 -0
- package/src/modules/agent-guide/__tests__/guide-eval.test.ts +182 -0
- package/src/modules/agent-guide/__tests__/guide-matches-code.test.ts +263 -0
- package/src/modules/agent-guide/__tests__/tool-surface.json +514 -0
- package/src/modules/agent-guide/__tests__/tool-surface.test.ts +75 -0
- package/src/modules/agent-guide/agent-guide.tools.ts +51 -22
- package/src/modules/agent-guide/agent-guide.ts +120 -13
- package/src/modules/agent-guide/guide-budget.ts +73 -0
- package/src/modules/agent-guide/index.ts +12 -0
- package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +5 -4
- package/src/modules/agent-instructions/compose.ts +7 -1
- package/src/modules/agent-instructions/shared-file-rules.ts +27 -9
- 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/code-mode/code-mode.tool.ts +2 -2
- package/src/modules/connection-probe/__tests__/connection-probe.service.test.ts +5 -24
- package/src/modules/connection-probe/connection-probe.service.ts +1 -34
- 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 +112 -52
- 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/__tests__/db-secrets-vault.oauth.test.ts +430 -3
- package/src/modules/secrets-vault/__tests__/oauth-live-declaration.route.test.ts +218 -0
- package/src/modules/secrets-vault/__tests__/oauth-return-to.route.test.ts +39 -6
- package/src/modules/secrets-vault/db-secrets-vault.service.ts +170 -27
- package/src/modules/secrets-vault/index.ts +1 -1
- package/src/modules/secrets-vault/secrets-vault.contract.ts +61 -11
- package/src/modules/secrets-vault/secrets-vault.routes.ts +114 -42
- package/src/modules/settings/oidc-check.ts +5 -18
- 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 +45 -14
- 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__/agent-roles-write.test.ts +19 -11
- package/src/modules/tool-helpers/__tests__/can-write.tools.test.ts +3 -1
- package/src/modules/tool-helpers/__tests__/route-tool-schemas.catalog.test.ts +38 -0
- package/src/modules/tool-helpers/tool-context.ts +10 -0
- package/src/modules/tool-helpers/tool-def.ts +1 -1
- 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.mcp-oauth.test.ts +197 -11
- package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +42 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +99 -8
- package/src/modules/tool-manuals/index.ts +6 -2
- package/src/modules/tool-manuals/mcp-json-discovery.ts +73 -34
- package/src/modules/tool-manuals/tool-manuals.contract.ts +40 -6
- package/src/modules/tool-manuals/tool-manuals.routes.ts +40 -3
- package/src/modules/tool-manuals/tool-manuals.service.ts +169 -61
- package/src/modules/tool-manuals/tool-manuals.tools.ts +81 -25
- package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +6 -113
- 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 +36 -27
- 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 +10 -12
- package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +22 -10
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +549 -162
- package/src/modules/workspace/agent-access.gate.ts +1 -1
- 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 +574 -176
- package/src/shared/__tests__/read-capped.test.ts +68 -0
- package/src/shared/oauth-token-error.ts +46 -0
- package/src/shared/path-order.ts +37 -8
- package/src/shared/read-capped.ts +40 -0
- 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/agent-guide/finding-things.md +0 -7
- package/agent-guide/introduction.md +0 -27
- 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 ')) {
|
|
@@ -4,21 +4,27 @@ import os from 'node:os';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import express from 'express';
|
|
6
6
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
7
|
-
import { ToolRegistry } from '../../tool-registry/
|
|
8
|
-
import {
|
|
9
|
-
|
|
7
|
+
import { ToolRegistry } from '../../tool-registry/index.js';
|
|
8
|
+
import {
|
|
9
|
+
InternalTokenService,
|
|
10
|
+
RoutineWritePolicyService,
|
|
11
|
+
WorkflowHooks,
|
|
12
|
+
createToolAuthMiddleware,
|
|
13
|
+
loadActiveGroups,
|
|
14
|
+
registerWorkspaceTools,
|
|
15
|
+
} from '../../../__tests__/tool-wiring.js';
|
|
10
16
|
import { createToolContextResolver } from '../tool-context.js';
|
|
11
17
|
import { createToolHandlerFactory } from '../tool-handler.js';
|
|
12
|
-
import {
|
|
13
|
-
import { RoutineWritePolicyService } from '../../workspace/routine-write-policy.js';
|
|
14
|
-
import { WorkflowHooks } from '../../workflow/workflow-hooks.js';
|
|
15
|
-
import { ToolDescriptionNotes } from '../../workspace/agent-access.gate.js';
|
|
16
|
-
import { SpillStore } from '../../workspace/spill-store.js';
|
|
17
|
-
import { DocExtractService, WorkerDocumentExtractor } from '../../workspace/index.js';
|
|
18
|
-
import { NEW_ROLE_GUIDANCE } from '../../access-model/roles-yaml-guard.js';
|
|
19
|
-
import { loadActiveGroups } from '../../access/access-control.service.js';
|
|
18
|
+
import { DocExtractService, SpillStore, ToolDescriptionNotes, WorkerDocumentExtractor } from '../../workspace/index.js';
|
|
20
19
|
import { testKbContext } from '../../../__tests__/kb-context.js';
|
|
21
20
|
|
|
21
|
+
/**
|
|
22
|
+
* The sentence a refused role creation carries to the agent, as the agent
|
|
23
|
+
* guide states it too: asserted as the words a person reads, not as the
|
|
24
|
+
* module's constant, so a reworded refusal is a visible change here.
|
|
25
|
+
*/
|
|
26
|
+
const NEW_ROLE_GUIDANCE = 'add people to existing roles, and use a GROUP for a task- or team-scoped set of people';
|
|
27
|
+
|
|
22
28
|
/**
|
|
23
29
|
* The agent's file tools over the production context resolver and a real
|
|
24
30
|
* workspace on disk: a roles.yaml write that creates a role is refused with a
|
|
@@ -71,6 +77,8 @@ async function start(): Promise<string> {
|
|
|
71
77
|
canReadBatch: async (_w: string, _u: string, paths: string[]) => new Map(paths.map((p) => [p, true])),
|
|
72
78
|
// The `after` half of a move's or copy's preview — allowing everything, like the gates above.
|
|
73
79
|
previewAccessAfterRelocation: async () => ({ read: true, write: true, download: true, owner: true }),
|
|
80
|
+
// Who else loses or gains access in a move: nobody, here.
|
|
81
|
+
prospectiveHolderChanges: async () => ({ lose: [], gain: [] }),
|
|
74
82
|
} as never;
|
|
75
83
|
registerWorkspaceTools(registry, router, toolAuth, createToolHandlerFactory(resolve), new SpillStore(path.join(os.tmpdir(), 'bevel-test-spills')), new DocExtractService(docCache, new WorkerDocumentExtractor()), allowAll, testKbContext({ kbDirName: KB }), {
|
|
76
84
|
// No hook registered: the agent-access gate refuses nothing here.
|
|
@@ -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
|
/**
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { compileCheck, exampleArguments } from '@bevel-software/platform-mcp-core';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { hexisCatalog } from '../../../__tests__/hexis-catalog.js';
|
|
4
|
+
import { routeToolSchemas } from '../route-tool-schemas.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Every tool a route mounts declares two schemas: the one a client sees
|
|
8
|
+
* (`inputs`, with the platform tools' arguments under `body`) and the FLAT one
|
|
9
|
+
* the route itself checks a call against. The `Call:` line at the top of each
|
|
10
|
+
* description is generated from the first; the route refuses by the second.
|
|
11
|
+
* The two must agree, or a call written from the example is refused one
|
|
12
|
+
* layer in, with nothing in the description to say why.
|
|
13
|
+
*
|
|
14
|
+
* Held here, over the whole catalog Hexis registers, because the flat schema
|
|
15
|
+
* is this module's: `routeToolSchemas` is how a mounted route finds its own,
|
|
16
|
+
* and no other module reads it.
|
|
17
|
+
*/
|
|
18
|
+
describe('the flat schema a route checks against accepts the call its own example shows', () => {
|
|
19
|
+
it('for every tool Hexis mounts on a route', async () => {
|
|
20
|
+
const { internal } = await hexisCatalog();
|
|
21
|
+
const mounted = internal.filter((tool) => routeToolSchemas(tool.name) !== undefined);
|
|
22
|
+
// The catalog is the real one: the family every scenario names is in it.
|
|
23
|
+
for (const name of ['read_file', 'write_file', 'list_files', 'grep', 'move_file']) {
|
|
24
|
+
expect(mounted.some((t) => t.name === name), name).toBe(true);
|
|
25
|
+
}
|
|
26
|
+
expect(mounted.length).toBeGreaterThan(12);
|
|
27
|
+
for (const tool of mounted) {
|
|
28
|
+
// The client's schema is the flat one in its envelope (`bodyEnvelope`),
|
|
29
|
+
// so the client's example and the route's check meet on the flat schema:
|
|
30
|
+
// an example written from it must pass the check made from it.
|
|
31
|
+
const flat = routeToolSchemas(tool.name)!.flat;
|
|
32
|
+
const check = compileCheck(flat);
|
|
33
|
+
expect(check.checkable, `${tool.name} (flat): ${check.checkable ? '' : check.reason}`).toBe(true);
|
|
34
|
+
if (!check.checkable) throw new Error(check.reason);
|
|
35
|
+
expect(check.check(exampleArguments(flat)), `${tool.name} (flat)`).toEqual([]);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -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
|
|
@@ -16,7 +16,7 @@ const toolSerializer = new ToolSerializer();
|
|
|
16
16
|
export const BRANCH_INPUT: JsonSchema = {
|
|
17
17
|
type: 'string',
|
|
18
18
|
minLength: 1,
|
|
19
|
-
description: 'The branch
|
|
19
|
+
description: 'The branch to work on: the default branch (`get_agent_guide` names it) or your draft.',
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -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
|
+
});
|