@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
|
@@ -63,32 +63,38 @@ function parseDomainList(raw: string): string[] {
|
|
|
63
63
|
.filter((d) => d.length > 0);
|
|
64
64
|
}
|
|
65
65
|
import { SpillStore } from '../modules/workspace/spill-store.js';
|
|
66
|
+
import { TmpSweeper } from '../modules/workspace/workspace-tmp.js';
|
|
66
67
|
import { AgentUploadStore, assertUploadsRootOutsideWorkspaces } from '../modules/workspace/agent-upload.store.js';
|
|
67
68
|
import { AgentDownloadStore, type IAgentDownloadStore } from '../modules/workspace/agent-download.store.js';
|
|
68
69
|
import { createDownloadFetcherIdentifier } from '../modules/workspace/agent-download.routes.js';
|
|
69
|
-
import { WorkerPatternMatcher } from '../modules/workspace/bounded-matcher.js';
|
|
70
|
-
import type { IPatternMatcher } from '../modules/workspace/pattern-matcher.contract.js';
|
|
71
70
|
import type { Request } from 'express';
|
|
72
71
|
import {
|
|
72
|
+
assertRipgrep,
|
|
73
73
|
DocExtractService,
|
|
74
|
+
RipgrepPatternMatcher,
|
|
74
75
|
WorkerDocumentExtractor,
|
|
75
76
|
type IDocumentExtractor,
|
|
77
|
+
type IPatternMatcher,
|
|
76
78
|
} from '../modules/workspace/index.js';
|
|
77
79
|
import { UuidSessionSink, type ISessionSink } from '../modules/workspace/session-sink.js';
|
|
78
80
|
import { AuthService } from '../modules/auth/auth.service.js';
|
|
79
81
|
import { AccountHooks, type IAccountHooks } from '../modules/auth/account-hooks.js';
|
|
80
82
|
import { AccountErasureService } from '../modules/auth/account-erasure.service.js';
|
|
81
83
|
import { OidcAuthProvider, oidcSettingsFrom } from '../modules/auth/oidc-auth-provider.js';
|
|
82
|
-
import { createAuthMiddleware, readAuthCookie } from '../modules/auth/auth.middleware.js';
|
|
84
|
+
import { authCookieSecure, createAuthMiddleware, readAuthCookie } from '../modules/auth/auth.middleware.js';
|
|
83
85
|
import { AccessControlService, loadActiveGroups } from '../modules/access/access-control.service.js';
|
|
84
86
|
import { AccessMutationService } from '../modules/access/access-mutation.service.js';
|
|
85
87
|
import { CreatorAccessService } from '../modules/access/creator-access.js';
|
|
86
88
|
import { ChangeReadGate } from '../modules/access/change-read-gate.js';
|
|
87
89
|
import { GroupsAdminService } from '../modules/access/groups-admin.service.js';
|
|
88
90
|
import { UserAccessRemovalService } from '../modules/access/user-access-removal.service.js';
|
|
89
|
-
import { makeRolesYamlWriteValidator } from '../modules/access-model/
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
import { makeRolesYamlWriteValidator } from '../modules/access-model/index.js';
|
|
92
|
+
// The implementations, from their files: the module entries offer them as
|
|
93
|
+
// types only, so nothing that imports an entry loads a service.
|
|
94
|
+
import { SkillService } from '../modules/skills/skills.service.js';
|
|
95
|
+
import { PendingSkillsService } from '../modules/skills/pending-skills.service.js';
|
|
96
|
+
import { ToolManualService } from '../modules/tool-manuals/tool-manuals.service.js';
|
|
97
|
+
import { PendingToolsService } from '../modules/tool-manuals/pending-tools.service.js';
|
|
92
98
|
import { McpServerEditService } from '../modules/tool-manuals/mcp-server-edit.service.js';
|
|
93
99
|
import { ToolDeleteService } from '../modules/tool-manuals/tool-delete.service.js';
|
|
94
100
|
import {
|
|
@@ -105,6 +111,7 @@ import {
|
|
|
105
111
|
MarketplaceCompilerService,
|
|
106
112
|
KbPluginSource,
|
|
107
113
|
} from '../modules/plugins/index.js';
|
|
114
|
+
import { noAgentConfigurations, type IAgentScopeResolver } from '../modules/agent-scope/index.js';
|
|
108
115
|
import { MarketplaceRepoService } from '../modules/marketplace/index.js';
|
|
109
116
|
import {
|
|
110
117
|
GitHubFacadeCredentialsService,
|
|
@@ -164,6 +171,7 @@ import { AgentAuditService, retentionDaysFrom } from '../modules/audit/agent-aud
|
|
|
164
171
|
import { readAgentPreamble, type AgentPreambleReader } from '../modules/agent-instructions/index.js';
|
|
165
172
|
import {
|
|
166
173
|
agentGuideSections,
|
|
174
|
+
guideStartText,
|
|
167
175
|
joinGuideSections,
|
|
168
176
|
type AgentGuideReader,
|
|
169
177
|
type AgentGuideSectionsReader,
|
|
@@ -255,7 +263,9 @@ export interface CoreServices {
|
|
|
255
263
|
agentUploadStore: AgentUploadStore;
|
|
256
264
|
/** The bytes `request_file_download` captured, held until their one-time link is fetched or expires. */
|
|
257
265
|
agentDownloadStore: IAgentDownloadStore;
|
|
258
|
-
/**
|
|
266
|
+
/** Sweeps every workspace's `tmp/` folder of entries older than seven days, hourly; started and stopped with the graph. */
|
|
267
|
+
tmpSweeper: TmpSweeper;
|
|
268
|
+
/** Runs a caller's `grep` pattern in ripgrep under a budget; its running searches end when the graph stops. */
|
|
259
269
|
patternMatcher: IPatternMatcher;
|
|
260
270
|
/**
|
|
261
271
|
* Every user a download fetch identifies itself as, by its bearer and its
|
|
@@ -287,6 +297,12 @@ export interface CoreServices {
|
|
|
287
297
|
* `read_file` of the guide's name answer. See modules/agent-guide.
|
|
288
298
|
*/
|
|
289
299
|
agentGuide: AgentGuideReader;
|
|
300
|
+
/**
|
|
301
|
+
* The start of that guide and the list of its sections: what a `read_file`
|
|
302
|
+
* of the guide's name answers, the same as `get_agent_guide` with no
|
|
303
|
+
* `section`. See `guideStartText`.
|
|
304
|
+
*/
|
|
305
|
+
agentGuideStart: AgentGuideReader;
|
|
290
306
|
/** The same guide as its sections, each with its title — what `get_agent_guide` lists and serves one of. */
|
|
291
307
|
agentGuideSections: AgentGuideSectionsReader;
|
|
292
308
|
mcpServerEditService: McpServerEditService;
|
|
@@ -309,6 +325,12 @@ export interface CoreServices {
|
|
|
309
325
|
pluginJoinRequestJobs: PluginJoinRequestJobs;
|
|
310
326
|
/** Which plugins hold which skills (inline or linked) — see `PluginLinkIndex`. */
|
|
311
327
|
pluginLinkIndex: PluginLinkIndex;
|
|
328
|
+
/**
|
|
329
|
+
* Connecting as an agent configuration: the choices offered at consent and key
|
|
330
|
+
* mint, and the scope every agent surface narrows a connection to — see
|
|
331
|
+
* `modules/agent-scope`.
|
|
332
|
+
*/
|
|
333
|
+
agentScopeService: IAgentScopeResolver;
|
|
312
334
|
/** Link / unlink / repair shared skills into plugins. */
|
|
313
335
|
pluginLinksService: PluginLinksService;
|
|
314
336
|
pluginRenameService: PluginRenameService;
|
|
@@ -432,6 +454,9 @@ export async function createCoreServices(
|
|
|
432
454
|
// (see `git-version.ts`): every clone, fetch and refresh below depends on it,
|
|
433
455
|
// so an unsupported binary is better surfaced here than at the first merge.
|
|
434
456
|
await assertGitVersion();
|
|
457
|
+
// The same for ripgrep, which the grep tool searches with and has no
|
|
458
|
+
// fallback for (see `ripgrep-version.ts`).
|
|
459
|
+
await assertRipgrep();
|
|
435
460
|
// What tells this knowledge base's locks, migration ledger and secrets
|
|
436
461
|
// loader apart from another's in the same process and database. Empty for
|
|
437
462
|
// the default schema, so a single-tenant deployment keeps the lock ids and
|
|
@@ -767,6 +792,10 @@ export async function createCoreServices(
|
|
|
767
792
|
// Shared, workspace-independent store for oversized `call_tool_chain` results,
|
|
768
793
|
// read back via `read_file`. Sibling of `workspacesRoot`, never committed.
|
|
769
794
|
const spillStore = new SpillStore(config.spillRoot);
|
|
795
|
+
// What the chat, the SharePoint reader and tool chains stage in a
|
|
796
|
+
// workspace's `tmp/` folder lives seven days past its last change; the file
|
|
797
|
+
// tools read it through the `__tmp__/` ref meanwhile (see workspace-tmp.ts).
|
|
798
|
+
const tmpSweeper = new TmpSweeper((signal) => workspaceService.sweepTmp(undefined, undefined, signal));
|
|
770
799
|
// The upload route an agent lands files by, so their content never passes
|
|
771
800
|
// through the model. Bytes live BESIDE the workspaces root (never inside
|
|
772
801
|
// one) until the apply commits them or the token expires — checked here
|
|
@@ -795,7 +824,7 @@ export async function createCoreServices(
|
|
|
795
824
|
'captured download bytes wait there for their one-time links, so a root inside a workspace would let the ' +
|
|
796
825
|
'file tools read them. Point AGENT_UPLOADS_ROOT at a directory whose parent is outside WORKSPACES_ROOT.',
|
|
797
826
|
});
|
|
798
|
-
const patternMatcher = new
|
|
827
|
+
const patternMatcher = new RipgrepPatternMatcher();
|
|
799
828
|
const agentDownloadStore = new AgentDownloadStore({
|
|
800
829
|
root: agentDownloadsRoot,
|
|
801
830
|
publicBaseUrl: config.publicBackendUrl,
|
|
@@ -851,6 +880,17 @@ export async function createCoreServices(
|
|
|
851
880
|
// The link index resolves manifests against the released catalog, and the
|
|
852
881
|
// plugin index counts through it (inline + linked), so it comes first.
|
|
853
882
|
const pluginLinkIndex = new PluginLinkIndex(workspaceService, skillService, accessControl, kb, pluginSource);
|
|
883
|
+
// What "Connect as" offers and what a connection made as an agent loads:
|
|
884
|
+
// the distribution's resolver (`CorePorts.agentScope`), made HERE with the
|
|
885
|
+
// core services it reads through — its configurations behind the person's
|
|
886
|
+
// read gate, `plugins:` expanded through the link index above — or core's
|
|
887
|
+
// default, which offers no agent and loads nothing for a path it cannot
|
|
888
|
+
// read. Made once, before anything consults it: the tool-context resolver
|
|
889
|
+
// below captures it, as the routes the server mounts do, so there is one
|
|
890
|
+
// resolver in effect and no later assignment to miss. Core owns the
|
|
891
|
+
// mechanism and no configuration (see `modules/agent-scope`).
|
|
892
|
+
const agentScopeService: IAgentScopeResolver =
|
|
893
|
+
ports.agentScope?.({ workspaceService, accessControl, kb, disk, pluginLinkIndex }) ?? noAgentConfigurations();
|
|
854
894
|
const pluginIndexService = new PluginIndexService(
|
|
855
895
|
workspaceService,
|
|
856
896
|
accessControl,
|
|
@@ -1343,11 +1383,13 @@ export async function createCoreServices(
|
|
|
1343
1383
|
// serves the same composition to the local bridge and the frontend card.
|
|
1344
1384
|
const readPreamble: AgentPreambleReader = () => readAgentPreamble(workspaceService, kb, disk);
|
|
1345
1385
|
// The guide every agent is told to read first, composed when asked for —
|
|
1346
|
-
// the layout
|
|
1347
|
-
// without a restart, and the distribution's hook sees
|
|
1386
|
+
// the layout and the default branch are read per call, so a name the setup
|
|
1387
|
+
// save applies lands without a restart, and the distribution's hook sees
|
|
1388
|
+
// every composition.
|
|
1348
1389
|
const agentGuideSectionsReader: AgentGuideSectionsReader = () =>
|
|
1349
|
-
agentGuideSections(kb.layout, ports.agentGuide, { kbDirName });
|
|
1390
|
+
agentGuideSections(kb.layout, ports.agentGuide, { kbDirName, defaultBranch: kb.defaultBranch });
|
|
1350
1391
|
const agentGuide: AgentGuideReader = async () => joinGuideSections(await agentGuideSectionsReader());
|
|
1392
|
+
const agentGuideStart: AgentGuideReader = async () => guideStartText(await agentGuideSectionsReader());
|
|
1351
1393
|
// The Audit log. Records through the proxy below (every call an external
|
|
1352
1394
|
// agent makes), reads keys through the key service so their shape is
|
|
1353
1395
|
// defined once, and prunes past the retention setting — read per sweep, so
|
|
@@ -1487,6 +1529,7 @@ export async function createCoreServices(
|
|
|
1487
1529
|
kbDirName: kbDirName,
|
|
1488
1530
|
creatorAccess,
|
|
1489
1531
|
loadActiveGroups,
|
|
1532
|
+
agentScope: agentScopeService,
|
|
1490
1533
|
});
|
|
1491
1534
|
const writeAccess = ports.writeAccess ?? alwaysWritable;
|
|
1492
1535
|
// The branch every tool call runs on is resolved by the handler, before the
|
|
@@ -1496,8 +1539,8 @@ export async function createCoreServices(
|
|
|
1496
1539
|
defaultBranch: () => kb.defaultBranch,
|
|
1497
1540
|
isMissing: (branch) => workspaceService.isBranchMissing(branch),
|
|
1498
1541
|
});
|
|
1499
|
-
const toolAuthMiddleware = createToolAuthMiddleware(externalApiKeyService, internalTokenService, authService);
|
|
1500
|
-
const verifyToolToken = createTokenVerifier(externalApiKeyService, internalTokenService, authService);
|
|
1542
|
+
const toolAuthMiddleware = createToolAuthMiddleware(externalApiKeyService, internalTokenService, authService, mcpOAuthProvider);
|
|
1543
|
+
const verifyToolToken = createTokenVerifier(externalApiKeyService, internalTokenService, authService, mcpOAuthProvider);
|
|
1501
1544
|
// Every credential kind this server issues — connection keys, internal
|
|
1502
1545
|
// tokens and app sessions (bearer or cookie) — so a fetch carrying another
|
|
1503
1546
|
// user's identity of ANY kind is refused the link.
|
|
@@ -1508,7 +1551,7 @@ export async function createCoreServices(
|
|
|
1508
1551
|
// Read-only manual endpoints accept the above PLUS a browser JWT, so a
|
|
1509
1552
|
// logged-in user can browse the catalog with their session. Execution routes
|
|
1510
1553
|
// keep `toolAuthMiddleware` (no JWT), so a session can read but not invoke.
|
|
1511
|
-
const manualAuthMiddleware = createManualAuthMiddleware(externalApiKeyService, internalTokenService, authService);
|
|
1554
|
+
const manualAuthMiddleware = createManualAuthMiddleware(externalApiKeyService, internalTokenService, authService, mcpOAuthProvider);
|
|
1512
1555
|
|
|
1513
1556
|
// Recovery-bot identity: a synthetic `recovery-bot@bevel.local` user
|
|
1514
1557
|
// backing (a) the recovery agent's commit authorship and (b) the
|
|
@@ -1575,7 +1618,7 @@ export async function createCoreServices(
|
|
|
1575
1618
|
settings: () => oidcSettingsFrom(settings),
|
|
1576
1619
|
publicBackendUrl: config.publicBackendUrl,
|
|
1577
1620
|
publicFrontendUrl: config.publicFrontendUrl,
|
|
1578
|
-
cookieSecure: config.publicBackendUrl
|
|
1621
|
+
cookieSecure: authCookieSecure(config.publicBackendUrl),
|
|
1579
1622
|
// A real sign-in proves the values that sign-in used. Recorded against
|
|
1580
1623
|
// those — under their own key — so it says nothing about any saved
|
|
1581
1624
|
// since, and cannot overwrite what was recorded about them.
|
|
@@ -1619,6 +1662,7 @@ export async function createCoreServices(
|
|
|
1619
1662
|
workspaceService,
|
|
1620
1663
|
workflowService,
|
|
1621
1664
|
accessControl,
|
|
1665
|
+
disk,
|
|
1622
1666
|
kbDirName,
|
|
1623
1667
|
() => kb.defaultBranch,
|
|
1624
1668
|
eventBus,
|
|
@@ -1673,6 +1717,7 @@ export async function createCoreServices(
|
|
|
1673
1717
|
spillStore,
|
|
1674
1718
|
agentUploadStore,
|
|
1675
1719
|
agentDownloadStore,
|
|
1720
|
+
tmpSweeper,
|
|
1676
1721
|
patternMatcher,
|
|
1677
1722
|
agentDownloadFetcher,
|
|
1678
1723
|
documentExtractor,
|
|
@@ -1687,6 +1732,7 @@ export async function createCoreServices(
|
|
|
1687
1732
|
pendingToolsService,
|
|
1688
1733
|
readAgentPreamble: readPreamble,
|
|
1689
1734
|
agentGuide,
|
|
1735
|
+
agentGuideStart,
|
|
1690
1736
|
agentGuideSections: agentGuideSectionsReader,
|
|
1691
1737
|
pluginIndexService,
|
|
1692
1738
|
pluginProvisionService,
|
|
@@ -1694,6 +1740,7 @@ export async function createCoreServices(
|
|
|
1694
1740
|
joinRequestsService,
|
|
1695
1741
|
pluginJoinRequestJobs,
|
|
1696
1742
|
pluginLinkIndex,
|
|
1743
|
+
agentScopeService,
|
|
1697
1744
|
pluginLinksService,
|
|
1698
1745
|
pluginRenameService,
|
|
1699
1746
|
marketplaceCompiler,
|
package/src/core/lifecycle.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { noteBesideCheckout } from '../modules/workspace/startup/beside-checkout
|
|
|
6
6
|
import { unregisterBevelSecretsVariableLoader } from '../modules/secrets-vault/secrets-variable-loader.js';
|
|
7
7
|
import type { WorkflowService } from '../modules/workflow/workflow.service.js';
|
|
8
8
|
import type { PluginJoinRequestJobs } from '../modules/plugins/join-request-jobs.service.js';
|
|
9
|
+
import type { TmpSweeper } from '../modules/workspace/workspace-tmp.js';
|
|
9
10
|
import { printable } from '../shared/printable.js';
|
|
10
11
|
import { logger } from '../shared/logging.js';
|
|
11
12
|
|
|
@@ -293,6 +294,8 @@ export interface BootableCore {
|
|
|
293
294
|
kbStartupRunner: Pick<KbStartupRunner, 'runAll' | 'retryUntilMaintained'>;
|
|
294
295
|
workflowService: Pick<WorkflowService, 'closeChangeRequestsWithDeletedBranches' | 'tidyAfterSweep'>;
|
|
295
296
|
pluginJoinRequestJobs: Pick<PluginJoinRequestJobs, 'startSweeping'>;
|
|
297
|
+
/** The periodic sweep of every workspace's `tmp/` folder, started here and stopped by {@link stopCore}. */
|
|
298
|
+
tmpSweeper: Pick<TmpSweeper, 'startSweeping'>;
|
|
296
299
|
/**
|
|
297
300
|
* The startup phase's retry, when the boot survived an unreachable remote
|
|
298
301
|
* and is asking again on a timer; null otherwise. Set by {@link startCore},
|
|
@@ -336,6 +339,13 @@ export async function startCore<C extends BootableCore>(
|
|
|
336
339
|
});
|
|
337
340
|
}
|
|
338
341
|
|
|
342
|
+
// The seven-day sweep of every workspace's `tmp/` folder (see
|
|
343
|
+
// `workspace-tmp.ts`), now and hourly. Needs nothing the startup phase
|
|
344
|
+
// provides — it reads the workspaces root and nothing else — so it is not
|
|
345
|
+
// held behind it, and a remote that is down does not leave staged files to
|
|
346
|
+
// pile up. Stopped by `stopCore`.
|
|
347
|
+
core.tmpSweeper.startSweeping();
|
|
348
|
+
|
|
339
349
|
// The KB startup phase — AFTER the distribution's onBoot, because a FATAL
|
|
340
350
|
// template finding raised there must stop the boot before anything seeds
|
|
341
351
|
// from that template; the runner then brings every branch up to this build
|
|
@@ -448,6 +458,16 @@ export interface CoreStopDeps {
|
|
|
448
458
|
agentUploadStore?: { stopSweeping(): void; drainSweep(): Promise<void> };
|
|
449
459
|
/** The agent download store, whose sweep deletes captured bytes nobody fetched — stopped for the same reason. */
|
|
450
460
|
agentDownloadStore?: { stopSweeping(): void; drainSweep(): Promise<void> };
|
|
461
|
+
/**
|
|
462
|
+
* The sweep of the workspaces' `tmp/` folders: stopped with this graph, so
|
|
463
|
+
* an evicted tenant's graph leaves no timer behind, and its sweep in flight
|
|
464
|
+
* cancelled (it removes nothing more) and then awaited within the stop's
|
|
465
|
+
* deadline, so the next graph over the same root does not meet it still
|
|
466
|
+
* walking there — unless one filesystem call outlasts that deadline, after
|
|
467
|
+
* which the cancelled sweep still removes nothing. Optional: a caller that
|
|
468
|
+
* has not built one passes nothing.
|
|
469
|
+
*/
|
|
470
|
+
tmpSweeper?: { stopSweeping(): void; drainSweep(): Promise<void> };
|
|
451
471
|
/**
|
|
452
472
|
* The grep pattern matcher, whose worker threads are this graph's own: ended
|
|
453
473
|
* here so a graph a tenant host evicts leaves no worker behind. Optional: a
|
|
@@ -555,6 +575,7 @@ async function releaseCore(deps: CoreStopDeps, remaining: () => number, log: (m:
|
|
|
555
575
|
// running to stop deleting.
|
|
556
576
|
deps.agentUploadStore?.stopSweeping();
|
|
557
577
|
deps.agentDownloadStore?.stopSweeping();
|
|
578
|
+
deps.tmpSweeper?.stopSweeping();
|
|
558
579
|
// A startup phase still asking for an unreachable remote stops asking:
|
|
559
580
|
// synchronous, and nothing after it must be able to clone into a
|
|
560
581
|
// workspaces folder that is about to belong to nobody.
|
|
@@ -587,15 +608,18 @@ async function releaseCore(deps: CoreStopDeps, remaining: () => number, log: (m:
|
|
|
587
608
|
if (deps.agentDownloadStore) {
|
|
588
609
|
await bounded(deps.agentDownloadStore.drainSweep(), remaining(), 'finishing the download sweep', log);
|
|
589
610
|
}
|
|
611
|
+
if (deps.tmpSweeper) {
|
|
612
|
+
await bounded(deps.tmpSweeper.drainSweep(), remaining(), "finishing the workspaces' tmp sweep", log);
|
|
613
|
+
}
|
|
590
614
|
// The tidy-up in flight fetches and deletes branches through the pool and
|
|
591
615
|
// the default branch's checkout: awaited, so the next graph for this
|
|
592
616
|
// tenant cannot find a branch deletion still running under it.
|
|
593
617
|
if (deps.workflowService) {
|
|
594
618
|
await bounded(deps.workflowService.drainTidy(), remaining(), 'finishing the branch tidy-up', log);
|
|
595
619
|
}
|
|
596
|
-
// Its
|
|
620
|
+
// Its ripgrep runs end with the graph; a search still running is answered busy or stopped.
|
|
597
621
|
if (deps.patternMatcher) {
|
|
598
|
-
await bounded(deps.patternMatcher.close(), remaining(), 'ending the
|
|
622
|
+
await bounded(deps.patternMatcher.close(), remaining(), 'ending the running searches', log);
|
|
599
623
|
}
|
|
600
624
|
// Likewise: an extraction still running is answered busy, and nothing about its file is remembered.
|
|
601
625
|
if (deps.documentExtractor) {
|
package/src/index.ts
CHANGED
|
@@ -26,7 +26,7 @@ export {
|
|
|
26
26
|
type ServerExtensions,
|
|
27
27
|
type ToolSurfaceCtx,
|
|
28
28
|
} from './core/create-core-server.js';
|
|
29
|
-
export { noopRecoveryAgent, type CorePorts } from './core/core-ports.js';
|
|
29
|
+
export { noopRecoveryAgent, type AgentScopeCollaborators, type CorePorts } from './core/core-ports.js';
|
|
30
30
|
// Logging: the contract, the slot a shell installs its sink into, and the
|
|
31
31
|
// tagged-logger lookup every module logs through. See shared/logging.ts.
|
|
32
32
|
export { setLogger, logger, createConsoleLogger } from './shared/logging.js';
|
|
@@ -242,6 +242,17 @@ describe('Admin write floor at the repository root', () => {
|
|
|
242
242
|
expect(await fs.readFile(path.join(repo, 'access.md'), 'utf-8')).toContain('write:\n - Admin');
|
|
243
243
|
});
|
|
244
244
|
|
|
245
|
+
it('lets the root drop a GROUP named Admin — group/Admin is never the role', async () => {
|
|
246
|
+
await write(repo, 'access.md', '---\n---\nwrite:\n - Admin\n - group/Admin\n');
|
|
247
|
+
const group = { kind: 'role' as const, role: 'group/Admin' };
|
|
248
|
+
await expect(mutation.revoke(WS, 'folder', '', group, ADMIN, 'write')).resolves.toMatchObject({
|
|
249
|
+
changed: true,
|
|
250
|
+
});
|
|
251
|
+
const after = await fs.readFile(path.join(repo, 'access.md'), 'utf-8');
|
|
252
|
+
expect(after).not.toContain('group/Admin');
|
|
253
|
+
expect(after).toContain('write:\n - Admin'); // the role's line is untouched
|
|
254
|
+
});
|
|
255
|
+
|
|
245
256
|
it('refuses deny-here on a PERSON who is an admin at the root, with the reason, and writes nothing', async () => {
|
|
246
257
|
const before = await fs.readFile(path.join(repo, 'access.md'), 'utf-8');
|
|
247
258
|
for (const email of [ADMIN, OWNER]) {
|
|
@@ -310,6 +321,7 @@ describe('Admin write floor at the repository root', () => {
|
|
|
310
321
|
{ emit: () => {} } as unknown as WorkflowEventBus,
|
|
311
322
|
usersDbDouble(),
|
|
312
323
|
testKbContext({ kbDirName: KB }),
|
|
324
|
+
new NodeFs(),
|
|
313
325
|
),
|
|
314
326
|
);
|
|
315
327
|
server = await new Promise<Server>((resolve) => {
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The case table for a name shared by a role and a group (the moved property
|
|
3
|
+
* of decision #315, "a bare name means the role"). Before this change a bare
|
|
4
|
+
* name meant the GROUP when both existed; it now means the ROLE. Exactly the
|
|
5
|
+
* colliding bare spellings change meaning, in grants AND in denials (decided
|
|
6
|
+
* by Razvan on 2026-10-23: a bare denial means the role exactly as a bare
|
|
7
|
+
* grant does; a group denial is written `deny group/<Name>`):
|
|
8
|
+
*
|
|
9
|
+
* rule | role-only member | group-only member
|
|
10
|
+
* -----------------------|-----------------------|----------------------
|
|
11
|
+
* read: Reviewer | was denied → granted | was granted → denied
|
|
12
|
+
* deny Reviewer | was allowed → denied | was denied → allowed
|
|
13
|
+
* read: group/Reviewer | denied (unchanged) | granted (new token)
|
|
14
|
+
* deny group/Reviewer | allowed (unchanged) | denied (new token)
|
|
15
|
+
* read: role/Reviewer | granted (unchanged) | denied (unchanged)
|
|
16
|
+
* deny role/Reviewer | denied (unchanged) | allowed (unchanged)
|
|
17
|
+
*
|
|
18
|
+
* A bare denial never touches the same-named group, so `read: group/Reviewer`
|
|
19
|
+
* beside `deny Reviewer` lets the group in. A name held by only one kind
|
|
20
|
+
* resolves as before. Every file with a colliding bare entry is listed by
|
|
21
|
+
* the groups roster (`bareNameResolvesToRole`) so an Admin can rewrite it as
|
|
22
|
+
* `group/<Name>` or `role/<Name>`.
|
|
23
|
+
*/
|
|
24
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
25
|
+
import fs from 'node:fs/promises';
|
|
26
|
+
import path from 'node:path';
|
|
27
|
+
import os from 'node:os';
|
|
28
|
+
|
|
29
|
+
import { NodeFs } from '../../kb-fs/node-fs.js';
|
|
30
|
+
import type { WorkspaceService } from '../../workspace/index.js';
|
|
31
|
+
import { AccessControlService } from '../access-control.service.js';
|
|
32
|
+
|
|
33
|
+
const KB_DIR = 'knowledge-base';
|
|
34
|
+
const WS = 'ws-colliding-name';
|
|
35
|
+
|
|
36
|
+
const ADMIN = 'admin@x.io';
|
|
37
|
+
const ROLE_MEMBER = 'role-member@x.io';
|
|
38
|
+
const GROUP_MEMBER = 'group-member@x.io';
|
|
39
|
+
const DOC = 'Docs/Plan.md';
|
|
40
|
+
|
|
41
|
+
const ROOT_FILES: Record<string, string> = {
|
|
42
|
+
'roles.yaml': `roles:\n Admin:\n - ${ADMIN}\n Reviewer:\n - ${ROLE_MEMBER}\n`,
|
|
43
|
+
'groups.yaml': `groups:\n Reviewer:\n - ${GROUP_MEMBER}\n`,
|
|
44
|
+
'access.md': '---\nwrite:\n - Admin\n---\nwrite:\n - Admin\n',
|
|
45
|
+
[DOC]: '# Plan\n',
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
describe('a name shared by a role and a group: grant and deny case table', () => {
|
|
49
|
+
let root: string;
|
|
50
|
+
let repo: string;
|
|
51
|
+
let svc: AccessControlService;
|
|
52
|
+
|
|
53
|
+
beforeEach(async () => {
|
|
54
|
+
root = await fs.mkdtemp(path.join(os.tmpdir(), 'bevel-colliding-name-'));
|
|
55
|
+
const workspaceDir = path.join(root, WS);
|
|
56
|
+
repo = path.join(workspaceDir, KB_DIR);
|
|
57
|
+
for (const [rel, text] of Object.entries(ROOT_FILES)) {
|
|
58
|
+
await fs.mkdir(path.dirname(path.join(repo, rel)), { recursive: true });
|
|
59
|
+
await fs.writeFile(path.join(repo, rel), text);
|
|
60
|
+
}
|
|
61
|
+
const workspaceService = {
|
|
62
|
+
getWorkspacePath: async () => workspaceDir,
|
|
63
|
+
ensureRemotesFetched: async () => undefined,
|
|
64
|
+
} as unknown as WorkspaceService;
|
|
65
|
+
svc = new AccessControlService(workspaceService, KB_DIR, new NodeFs());
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
afterEach(async () => {
|
|
69
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
/** Who may read DOC when the Docs folder's read list is `entries`. */
|
|
73
|
+
async function readers(entries: string[]): Promise<{ role: boolean; group: boolean }> {
|
|
74
|
+
const body = `read:\n${entries.map((e) => ` - ${e}\n`).join('')}`;
|
|
75
|
+
await fs.writeFile(path.join(repo, 'Docs/access.md'), `---\nwrite:\n - Admin\n---\n${body}`);
|
|
76
|
+
svc.invalidate(WS);
|
|
77
|
+
return {
|
|
78
|
+
role: await svc.canRead(WS, ROLE_MEMBER, DOC),
|
|
79
|
+
group: await svc.canRead(WS, GROUP_MEMBER, DOC),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
it('a bare grant reaches the role only', async () => {
|
|
84
|
+
expect(await readers(['Reviewer'])).toEqual({ role: true, group: false });
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('a bare denial reaches the role only: the members of the same-named group are untouched', async () => {
|
|
88
|
+
expect(await readers(['everyone', 'deny Reviewer'])).toEqual({ role: false, group: true });
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('a group grant beside a bare denial lets the group in', async () => {
|
|
92
|
+
expect(await readers(['group/Reviewer', 'deny Reviewer'])).toEqual({ role: false, group: true });
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('group/<Name> grants and denies the group only', async () => {
|
|
96
|
+
expect(await readers(['group/Reviewer'])).toEqual({ role: false, group: true });
|
|
97
|
+
expect(await readers(['everyone', 'deny group/Reviewer'])).toEqual({ role: true, group: false });
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('role/<Name> grants and denies the role only', async () => {
|
|
101
|
+
expect(await readers(['role/Reviewer'])).toEqual({ role: true, group: false });
|
|
102
|
+
expect(await readers(['everyone', 'deny role/Reviewer'])).toEqual({ role: false, group: true });
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('a bare name held only by a group still means the group, in grants and denials', async () => {
|
|
106
|
+
await fs.writeFile(
|
|
107
|
+
path.join(repo, 'roles.yaml'),
|
|
108
|
+
`roles:\n Admin:\n - ${ADMIN}\n`,
|
|
109
|
+
);
|
|
110
|
+
expect(await readers(['Reviewer'])).toEqual({ role: false, group: true });
|
|
111
|
+
expect(await readers(['everyone', 'deny Reviewer'])).toEqual({ role: true, group: false });
|
|
112
|
+
});
|
|
113
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import { NodeFs } from '../../kb-fs/node-fs.js';
|
|
6
|
+
import type { WorkspaceService } from '../../workspace/workspace.service.js';
|
|
7
|
+
import { AccessControlService } from '../access-control.service.js';
|
|
8
|
+
|
|
9
|
+
const KB = 'knowledge-base';
|
|
10
|
+
const RULE = 'read:\n - deny everyone\n - Product Manager\n';
|
|
11
|
+
const ali = 'ali@bevel.software'; // no role
|
|
12
|
+
const felix = 'felix@example.com'; // Product Manager
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A file's own access rules live in its frontmatter, so the read checks read
|
|
16
|
+
* a file only as far as its frontmatter reaches — a line, for a file with
|
|
17
|
+
* none. That is what keeps a batch over a tree of large transcripts (grep's,
|
|
18
|
+
* the explorer's) from reading the whole tree, and these pin that the head
|
|
19
|
+
* answers exactly as the whole file would, fence rule and all.
|
|
20
|
+
*/
|
|
21
|
+
describe('AccessControlService — a file is read only as far as its frontmatter', () => {
|
|
22
|
+
let root: string;
|
|
23
|
+
let repo: string;
|
|
24
|
+
let svc: AccessControlService;
|
|
25
|
+
const workspaceId = 'ws-frontmatter-head';
|
|
26
|
+
|
|
27
|
+
beforeEach(async () => {
|
|
28
|
+
root = await fs.mkdtemp(path.join(os.tmpdir(), 'bevel-fm-head-'));
|
|
29
|
+
const workspaceDir = path.join(root, workspaceId);
|
|
30
|
+
repo = path.join(workspaceDir, KB);
|
|
31
|
+
await fs.mkdir(path.join(repo, 'Open'), { recursive: true });
|
|
32
|
+
await fs.writeFile(path.join(repo, 'roles.yaml'), 'roles:\n Admin:\n - razvan@bevel.software\n Product Manager:\n - felix@example.com\n');
|
|
33
|
+
await fs.writeFile(path.join(repo, 'Open', 'access.md'), '---\nread:\n - everyone\n---\n');
|
|
34
|
+
svc = new AccessControlService(
|
|
35
|
+
{ getWorkspacePath: async () => workspaceDir } as unknown as WorkspaceService,
|
|
36
|
+
KB,
|
|
37
|
+
new NodeFs(),
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
afterEach(async () => {
|
|
41
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const put = (name: string, content: string | Buffer) => fs.writeFile(path.join(repo, 'Open', name), content);
|
|
45
|
+
const verdicts = async (name: string) => {
|
|
46
|
+
const rel = `Open/${name}`;
|
|
47
|
+
const batch = await svc.canReadBatch(workspaceId, ali, [rel]);
|
|
48
|
+
const felixBatch = await svc.canReadBatch(workspaceId, felix, [rel]);
|
|
49
|
+
return {
|
|
50
|
+
ali: batch.get(rel),
|
|
51
|
+
felix: felixBatch.get(rel),
|
|
52
|
+
single: await svc.canRead(workspaceId, ali, rel),
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
it('honours the rules of a file far too large to read whole, at once', async () => {
|
|
57
|
+
await put('huge.md', `---\n${RULE}---\n`);
|
|
58
|
+
// 600 MB, sparse: more text than one string can hold, so a read of the
|
|
59
|
+
// whole file could not even be decoded, and its rule would be missed.
|
|
60
|
+
await fs.truncate(path.join(repo, 'Open', 'huge.md'), 600 * 1024 * 1024);
|
|
61
|
+
expect(await verdicts('huge.md')).toEqual({ ali: false, felix: true, single: false });
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('reads a frontmatter longer than any one read through to its closing fence', async () => {
|
|
65
|
+
await put('long-fm.md', `---\nsummary: "${'x'.repeat(200_000)}"\n${RULE}---\nbody\n`);
|
|
66
|
+
expect(await verdicts('long-fm.md')).toEqual({ ali: false, felix: true, single: false });
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('scans a frontmatter line far longer than one read once, not again with every read', async () => {
|
|
70
|
+
// A long line inside the frontmatter, then the rule; and a closing fence
|
|
71
|
+
// padded with 3 MB of spaces, which stays a fence however long it runs.
|
|
72
|
+
const longValue = (chars: number) =>
|
|
73
|
+
`---\nsummary: "${'x'.repeat(chars)}"\n${RULE}${' '.repeat(3_000_000)}---${' '.repeat(3_000_000)}\nbody\n`;
|
|
74
|
+
await put('long-value.md', longValue(32_000_000));
|
|
75
|
+
expect(await verdicts('long-value.md')).toEqual({ ali: false, felix: true, single: false });
|
|
76
|
+
// How the cost grows, not how long it takes on this machine: a line 16
|
|
77
|
+
// times longer costs about 16 times as much scanned once, and far more
|
|
78
|
+
// (about 60 times, measured) scanned again with every read. The slowest
|
|
79
|
+
// short check against the fastest long one, so noise only helps a scan
|
|
80
|
+
// that is linear pass.
|
|
81
|
+
const timed = async (name: string, chars: number): Promise<number> => {
|
|
82
|
+
await put(name, `---\nsummary: "${'x'.repeat(chars)}"\n${RULE}---\n`);
|
|
83
|
+
const started = performance.now();
|
|
84
|
+
await svc.canReadBatch(workspaceId, ali, [`Open/${name}`]);
|
|
85
|
+
return performance.now() - started;
|
|
86
|
+
};
|
|
87
|
+
const short: number[] = [];
|
|
88
|
+
const long: number[] = [];
|
|
89
|
+
for (let i = 0; i < 3; i++) {
|
|
90
|
+
short.push(await timed(`short-${i}.md`, 2_000_000));
|
|
91
|
+
long.push(await timed(`long-${i}.md`, 32_000_000));
|
|
92
|
+
}
|
|
93
|
+
expect(Math.min(...long) / Math.max(...short)).toBeLessThan(32);
|
|
94
|
+
}, 60_000);
|
|
95
|
+
|
|
96
|
+
it('applies the fence rule as the whole-file scan does: CRLF, a BOM, padding around the fence', async () => {
|
|
97
|
+
await put('crlf.md', `---\r\n${RULE.replace(/\n/g, '\r\n')}---\r\nbody\r\n`);
|
|
98
|
+
await put('bom.md', `\uFEFF---\n${RULE}---\n`);
|
|
99
|
+
await put('padded.md', `${' '.repeat(5_000)}--- \n${RULE} ---\n`);
|
|
100
|
+
for (const name of ['crlf.md', 'bom.md', 'padded.md']) {
|
|
101
|
+
expect(await verdicts(name), name).toEqual({ ali: false, felix: true, single: false });
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('finds no rules where the whole-file scan finds none', async () => {
|
|
106
|
+
// A fenced block that is not at the top is body, not frontmatter.
|
|
107
|
+
await put('later.md', `# title\n---\n${RULE}---\n`);
|
|
108
|
+
// An opening fence never closed is no frontmatter either.
|
|
109
|
+
await put('unclosed.md', `---\n${RULE}`);
|
|
110
|
+
// A first line that is long, and no fence, ends the read at once.
|
|
111
|
+
await put('long-line.md', `${'x'.repeat(3_000_000)}\n---\n${RULE}---\n`);
|
|
112
|
+
await put('empty.md', '');
|
|
113
|
+
for (const name of ['later.md', 'unclosed.md', 'long-line.md', 'empty.md']) {
|
|
114
|
+
expect(await verdicts(name), name).toEqual({ ali: true, felix: true, single: true });
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
});
|