@bevel-software/platform-core-backend 0.1.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/LICENSE +202 -0
- package/dist/assets.d.ts +5 -0
- package/dist/assets.d.ts.map +1 -0
- package/dist/assets.js +23 -0
- package/dist/assets.js.map +1 -0
- package/dist/core/core-ports.d.ts +83 -0
- package/dist/core/core-ports.d.ts.map +1 -0
- package/dist/core/core-ports.js +12 -0
- package/dist/core/core-ports.js.map +1 -0
- package/dist/core/create-core-server.d.ts +62 -0
- package/dist/core/create-core-server.d.ts.map +1 -0
- package/dist/core/create-core-server.js +204 -0
- package/dist/core/create-core-server.js.map +1 -0
- package/dist/core/create-core-services.d.ts +95 -0
- package/dist/core/create-core-services.d.ts.map +1 -0
- package/dist/core/create-core-services.js +352 -0
- package/dist/core/create-core-services.js.map +1 -0
- package/dist/core-config.d.ts +119 -0
- package/dist/core-config.d.ts.map +1 -0
- package/dist/core-config.js +240 -0
- package/dist/core-config.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/access/access-control.interface.d.ts +348 -0
- package/dist/modules/access/access-control.interface.d.ts.map +1 -0
- package/dist/modules/access/access-control.interface.js +2 -0
- package/dist/modules/access/access-control.interface.js.map +1 -0
- package/dist/modules/access/access-control.service.d.ts +323 -0
- package/dist/modules/access/access-control.service.d.ts.map +1 -0
- package/dist/modules/access/access-control.service.js +1431 -0
- package/dist/modules/access/access-control.service.js.map +1 -0
- package/dist/modules/access/access-errors.d.ts +34 -0
- package/dist/modules/access/access-errors.d.ts.map +1 -0
- package/dist/modules/access/access-errors.js +40 -0
- package/dist/modules/access/access-errors.js.map +1 -0
- package/dist/modules/access/access-mutation.service.d.ts +176 -0
- package/dist/modules/access/access-mutation.service.d.ts.map +1 -0
- package/dist/modules/access/access-mutation.service.js +307 -0
- package/dist/modules/access/access-mutation.service.js.map +1 -0
- package/dist/modules/access/access-splice.d.ts +98 -0
- package/dist/modules/access/access-splice.d.ts.map +1 -0
- package/dist/modules/access/access-splice.js +346 -0
- package/dist/modules/access/access-splice.js.map +1 -0
- package/dist/modules/access/access.routes.d.ts +10 -0
- package/dist/modules/access/access.routes.d.ts.map +1 -0
- package/dist/modules/access/access.routes.js +757 -0
- package/dist/modules/access/access.routes.js.map +1 -0
- package/dist/modules/access/creator-access.d.ts +113 -0
- package/dist/modules/access/creator-access.d.ts.map +1 -0
- package/dist/modules/access/creator-access.js +212 -0
- package/dist/modules/access/creator-access.js.map +1 -0
- package/dist/modules/access/kb-read-filter.d.ts +41 -0
- package/dist/modules/access/kb-read-filter.d.ts.map +1 -0
- package/dist/modules/access/kb-read-filter.js +60 -0
- package/dist/modules/access/kb-read-filter.js.map +1 -0
- package/dist/modules/access/roles-admin.service.d.ts +240 -0
- package/dist/modules/access/roles-admin.service.d.ts.map +1 -0
- package/dist/modules/access/roles-admin.service.js +630 -0
- package/dist/modules/access/roles-admin.service.js.map +1 -0
- package/dist/modules/access/roles-edit.d.ts +91 -0
- package/dist/modules/access/roles-edit.d.ts.map +1 -0
- package/dist/modules/access/roles-edit.js +232 -0
- package/dist/modules/access/roles-edit.js.map +1 -0
- package/dist/modules/access/roles-yaml-guard.d.ts +56 -0
- package/dist/modules/access/roles-yaml-guard.d.ts.map +1 -0
- package/dist/modules/access/roles-yaml-guard.js +79 -0
- package/dist/modules/access/roles-yaml-guard.js.map +1 -0
- package/dist/modules/admin/admin-access.routes.d.ts +18 -0
- package/dist/modules/admin/admin-access.routes.d.ts.map +1 -0
- package/dist/modules/admin/admin-access.routes.js +26 -0
- package/dist/modules/admin/admin-access.routes.js.map +1 -0
- package/dist/modules/admin/admin-access.service.d.ts +24 -0
- package/dist/modules/admin/admin-access.service.d.ts.map +1 -0
- package/dist/modules/admin/admin-access.service.js +41 -0
- package/dist/modules/admin/admin-access.service.js.map +1 -0
- package/dist/modules/admin/admin.interface.d.ts +11 -0
- package/dist/modules/admin/admin.interface.d.ts.map +1 -0
- package/dist/modules/admin/admin.interface.js +2 -0
- package/dist/modules/admin/admin.interface.js.map +1 -0
- package/dist/modules/auth/account-erasure.service.d.ts +80 -0
- package/dist/modules/auth/account-erasure.service.d.ts.map +1 -0
- package/dist/modules/auth/account-erasure.service.js +91 -0
- package/dist/modules/auth/account-erasure.service.js.map +1 -0
- package/dist/modules/auth/auth.middleware.d.ts +23 -0
- package/dist/modules/auth/auth.middleware.d.ts.map +1 -0
- package/dist/modules/auth/auth.middleware.js +68 -0
- package/dist/modules/auth/auth.middleware.js.map +1 -0
- package/dist/modules/auth/auth.routes.d.ts +25 -0
- package/dist/modules/auth/auth.routes.d.ts.map +1 -0
- package/dist/modules/auth/auth.routes.js +72 -0
- package/dist/modules/auth/auth.routes.js.map +1 -0
- package/dist/modules/auth/auth.service.d.ts +76 -0
- package/dist/modules/auth/auth.service.d.ts.map +1 -0
- package/dist/modules/auth/auth.service.js +168 -0
- package/dist/modules/auth/auth.service.js.map +1 -0
- package/dist/modules/code-mode/code-mode-names.d.ts +16 -0
- package/dist/modules/code-mode/code-mode-names.d.ts.map +1 -0
- package/dist/modules/code-mode/code-mode-names.js +30 -0
- package/dist/modules/code-mode/code-mode-names.js.map +1 -0
- package/dist/modules/code-mode/code-mode.tool.d.ts +13 -0
- package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -0
- package/dist/modules/code-mode/code-mode.tool.js +112 -0
- package/dist/modules/code-mode/code-mode.tool.js.map +1 -0
- package/dist/modules/code-mode/index.d.ts +3 -0
- package/dist/modules/code-mode/index.d.ts.map +1 -0
- package/dist/modules/code-mode/index.js +3 -0
- package/dist/modules/code-mode/index.js.map +1 -0
- package/dist/modules/database/connection.d.ts +6 -0
- package/dist/modules/database/connection.d.ts.map +1 -0
- package/dist/modules/database/connection.js +12 -0
- package/dist/modules/database/connection.js.map +1 -0
- package/dist/modules/database/core-schema.d.ts +2273 -0
- package/dist/modules/database/core-schema.d.ts.map +1 -0
- package/dist/modules/database/core-schema.js +413 -0
- package/dist/modules/database/core-schema.js.map +1 -0
- package/dist/modules/database/migrate.d.ts +10 -0
- package/dist/modules/database/migrate.d.ts.map +1 -0
- package/dist/modules/database/migrate.js +40 -0
- package/dist/modules/database/migrate.js.map +1 -0
- package/dist/modules/database/schema.d.ts +12 -0
- package/dist/modules/database/schema.d.ts.map +1 -0
- package/dist/modules/database/schema.js +12 -0
- package/dist/modules/database/schema.js.map +1 -0
- package/dist/modules/diff/diff-paths.d.ts +2 -0
- package/dist/modules/diff/diff-paths.d.ts.map +1 -0
- package/dist/modules/diff/diff-paths.js +9 -0
- package/dist/modules/diff/diff-paths.js.map +1 -0
- package/dist/modules/diff/diff.config.d.ts +8 -0
- package/dist/modules/diff/diff.config.d.ts.map +1 -0
- package/dist/modules/diff/diff.config.js +13 -0
- package/dist/modules/diff/diff.config.js.map +1 -0
- package/dist/modules/diff/diff.interface.d.ts +73 -0
- package/dist/modules/diff/diff.interface.d.ts.map +1 -0
- package/dist/modules/diff/diff.interface.js +2 -0
- package/dist/modules/diff/diff.interface.js.map +1 -0
- package/dist/modules/diff/diff.routes.d.ts +35 -0
- package/dist/modules/diff/diff.routes.d.ts.map +1 -0
- package/dist/modules/diff/diff.routes.js +228 -0
- package/dist/modules/diff/diff.routes.js.map +1 -0
- package/dist/modules/diff/diff.service.d.ts +51 -0
- package/dist/modules/diff/diff.service.d.ts.map +1 -0
- package/dist/modules/diff/diff.service.js +489 -0
- package/dist/modules/diff/diff.service.js.map +1 -0
- package/dist/modules/diff/line-diff.d.ts +16 -0
- package/dist/modules/diff/line-diff.d.ts.map +1 -0
- package/dist/modules/diff/line-diff.js +67 -0
- package/dist/modules/diff/line-diff.js.map +1 -0
- package/dist/modules/mcp/mcp-auth.middleware.d.ts +27 -0
- package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -0
- package/dist/modules/mcp/mcp-auth.middleware.js +116 -0
- package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -0
- package/dist/modules/mcp/mcp-session-store.d.ts +74 -0
- package/dist/modules/mcp/mcp-session-store.d.ts.map +1 -0
- package/dist/modules/mcp/mcp-session-store.js +131 -0
- package/dist/modules/mcp/mcp-session-store.js.map +1 -0
- package/dist/modules/mcp/mcp.routes.d.ts +24 -0
- package/dist/modules/mcp/mcp.routes.d.ts.map +1 -0
- package/dist/modules/mcp/mcp.routes.js +229 -0
- package/dist/modules/mcp/mcp.routes.js.map +1 -0
- package/dist/modules/mcp/mcp.service.d.ts +198 -0
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -0
- package/dist/modules/mcp/mcp.service.js +840 -0
- package/dist/modules/mcp/mcp.service.js.map +1 -0
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +76 -0
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -0
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js +291 -0
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -0
- package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts +18 -0
- package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts.map +1 -0
- package/dist/modules/mcp/oauth/oauth-consent.routes.js +52 -0
- package/dist/modules/mcp/oauth/oauth-consent.routes.js.map +1 -0
- package/dist/modules/mcp/oauth/oauth-state.d.ts +32 -0
- package/dist/modules/mcp/oauth/oauth-state.d.ts.map +1 -0
- package/dist/modules/mcp/oauth/oauth-state.js +34 -0
- package/dist/modules/mcp/oauth/oauth-state.js.map +1 -0
- package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts +92 -0
- package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts.map +1 -0
- package/dist/modules/secrets-vault/db-secrets-vault.service.js +728 -0
- package/dist/modules/secrets-vault/db-secrets-vault.service.js.map +1 -0
- package/dist/modules/secrets-vault/index.d.ts +7 -0
- package/dist/modules/secrets-vault/index.d.ts.map +1 -0
- package/dist/modules/secrets-vault/index.js +6 -0
- package/dist/modules/secrets-vault/index.js.map +1 -0
- package/dist/modules/secrets-vault/mcp-oauth-discovery.service.d.ts +63 -0
- package/dist/modules/secrets-vault/mcp-oauth-discovery.service.d.ts.map +1 -0
- package/dist/modules/secrets-vault/mcp-oauth-discovery.service.js +269 -0
- package/dist/modules/secrets-vault/mcp-oauth-discovery.service.js.map +1 -0
- package/dist/modules/secrets-vault/secrets-variable-loader.d.ts +46 -0
- package/dist/modules/secrets-vault/secrets-variable-loader.d.ts.map +1 -0
- package/dist/modules/secrets-vault/secrets-variable-loader.js +87 -0
- package/dist/modules/secrets-vault/secrets-variable-loader.js.map +1 -0
- package/dist/modules/secrets-vault/secrets-vault.contract.d.ts +210 -0
- package/dist/modules/secrets-vault/secrets-vault.contract.d.ts.map +1 -0
- package/dist/modules/secrets-vault/secrets-vault.contract.js +90 -0
- package/dist/modules/secrets-vault/secrets-vault.contract.js.map +1 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +30 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.js +490 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -0
- package/dist/modules/skills/index.d.ts +5 -0
- package/dist/modules/skills/index.d.ts.map +1 -0
- package/dist/modules/skills/index.js +4 -0
- package/dist/modules/skills/index.js.map +1 -0
- package/dist/modules/skills/skills.contract.d.ts +58 -0
- package/dist/modules/skills/skills.contract.d.ts.map +1 -0
- package/dist/modules/skills/skills.contract.js +10 -0
- package/dist/modules/skills/skills.contract.js.map +1 -0
- package/dist/modules/skills/skills.routes.d.ts +15 -0
- package/dist/modules/skills/skills.routes.d.ts.map +1 -0
- package/dist/modules/skills/skills.routes.js +34 -0
- package/dist/modules/skills/skills.routes.js.map +1 -0
- package/dist/modules/skills/skills.service.d.ts +21 -0
- package/dist/modules/skills/skills.service.d.ts.map +1 -0
- package/dist/modules/skills/skills.service.js +202 -0
- package/dist/modules/skills/skills.service.js.map +1 -0
- package/dist/modules/skills/skills.tools.d.ts +15 -0
- package/dist/modules/skills/skills.tools.d.ts.map +1 -0
- package/dist/modules/skills/skills.tools.js +96 -0
- package/dist/modules/skills/skills.tools.js.map +1 -0
- package/dist/modules/tool-auth/external-api-key.errors.d.ts +14 -0
- package/dist/modules/tool-auth/external-api-key.errors.d.ts.map +1 -0
- package/dist/modules/tool-auth/external-api-key.errors.js +23 -0
- package/dist/modules/tool-auth/external-api-key.errors.js.map +1 -0
- package/dist/modules/tool-auth/external-api-key.interface.d.ts +90 -0
- package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -0
- package/dist/modules/tool-auth/external-api-key.interface.js +2 -0
- package/dist/modules/tool-auth/external-api-key.interface.js.map +1 -0
- package/dist/modules/tool-auth/external-api-key.service.d.ts +25 -0
- package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -0
- package/dist/modules/tool-auth/external-api-key.service.js +164 -0
- package/dist/modules/tool-auth/external-api-key.service.js.map +1 -0
- package/dist/modules/tool-auth/internal-token.service.d.ts +62 -0
- package/dist/modules/tool-auth/internal-token.service.d.ts.map +1 -0
- package/dist/modules/tool-auth/internal-token.service.js +85 -0
- package/dist/modules/tool-auth/internal-token.service.js.map +1 -0
- package/dist/modules/tool-auth/llm-usage-meter.d.ts +16 -0
- package/dist/modules/tool-auth/llm-usage-meter.d.ts.map +1 -0
- package/dist/modules/tool-auth/llm-usage-meter.js +6 -0
- package/dist/modules/tool-auth/llm-usage-meter.js.map +1 -0
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts +101 -0
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -0
- package/dist/modules/tool-auth/tool-auth.middleware.js +166 -0
- package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -0
- package/dist/modules/tool-helpers/index.d.ts +19 -0
- package/dist/modules/tool-helpers/index.d.ts.map +1 -0
- package/dist/modules/tool-helpers/index.js +18 -0
- package/dist/modules/tool-helpers/index.js.map +1 -0
- package/dist/modules/tool-helpers/tool-context.d.ts +35 -0
- package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -0
- package/dist/modules/tool-helpers/tool-context.js +66 -0
- package/dist/modules/tool-helpers/tool-context.js.map +1 -0
- package/dist/modules/tool-helpers/tool-def.d.ts +33 -0
- package/dist/modules/tool-helpers/tool-def.d.ts.map +1 -0
- package/dist/modules/tool-helpers/tool-def.js +57 -0
- package/dist/modules/tool-helpers/tool-def.js.map +1 -0
- package/dist/modules/tool-helpers/tool-handler.d.ts +19 -0
- package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -0
- package/dist/modules/tool-helpers/tool-handler.js +84 -0
- package/dist/modules/tool-helpers/tool-handler.js.map +1 -0
- package/dist/modules/tool-helpers/tool.contract.d.ts +64 -0
- package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -0
- package/dist/modules/tool-helpers/tool.contract.js +24 -0
- package/dist/modules/tool-helpers/tool.contract.js.map +1 -0
- package/dist/modules/tool-helpers/validate-token.d.ts +31 -0
- package/dist/modules/tool-helpers/validate-token.d.ts.map +1 -0
- package/dist/modules/tool-helpers/validate-token.js +20 -0
- package/dist/modules/tool-helpers/validate-token.js.map +1 -0
- package/dist/modules/tool-manuals/index.d.ts +5 -0
- package/dist/modules/tool-manuals/index.d.ts.map +1 -0
- package/dist/modules/tool-manuals/index.js +5 -0
- package/dist/modules/tool-manuals/index.js.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +182 -0
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.contract.js +19 -0
- package/dist/modules/tool-manuals/tool-manuals.contract.js.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +24 -0
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.routes.js +102 -0
- package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts +108 -0
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.service.js +710 -0
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +35 -0
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.tools.js +157 -0
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -0
- package/dist/modules/tool-registry/manual.routes.d.ts +6 -0
- package/dist/modules/tool-registry/manual.routes.d.ts.map +1 -0
- package/dist/modules/tool-registry/manual.routes.js +76 -0
- package/dist/modules/tool-registry/manual.routes.js.map +1 -0
- package/dist/modules/tool-registry/tool-registry.d.ts +23 -0
- package/dist/modules/tool-registry/tool-registry.d.ts.map +1 -0
- package/dist/modules/tool-registry/tool-registry.js +46 -0
- package/dist/modules/tool-registry/tool-registry.js.map +1 -0
- package/dist/modules/tool-registry/tool.contract.d.ts +48 -0
- package/dist/modules/tool-registry/tool.contract.d.ts.map +1 -0
- package/dist/modules/tool-registry/tool.contract.js +2 -0
- package/dist/modules/tool-registry/tool.contract.js.map +1 -0
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +14 -0
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -0
- package/dist/modules/workflow/agent-tools/workflow.tools.js +437 -0
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -0
- package/dist/modules/workflow/event-bus.d.ts +107 -0
- package/dist/modules/workflow/event-bus.d.ts.map +1 -0
- package/dist/modules/workflow/event-bus.js +224 -0
- package/dist/modules/workflow/event-bus.js.map +1 -0
- package/dist/modules/workflow/events.routes.d.ts +80 -0
- package/dist/modules/workflow/events.routes.d.ts.map +1 -0
- package/dist/modules/workflow/events.routes.js +216 -0
- package/dist/modules/workflow/events.routes.js.map +1 -0
- package/dist/modules/workflow/file-change-notifier.d.ts +38 -0
- package/dist/modules/workflow/file-change-notifier.d.ts.map +1 -0
- package/dist/modules/workflow/file-change-notifier.js +22 -0
- package/dist/modules/workflow/file-change-notifier.js.map +1 -0
- package/dist/modules/workflow/file-lock.service.d.ts +57 -0
- package/dist/modules/workflow/file-lock.service.d.ts.map +1 -0
- package/dist/modules/workflow/file-lock.service.js +202 -0
- package/dist/modules/workflow/file-lock.service.js.map +1 -0
- package/dist/modules/workflow/git/branch-name.d.ts +10 -0
- package/dist/modules/workflow/git/branch-name.d.ts.map +1 -0
- package/dist/modules/workflow/git/branch-name.js +76 -0
- package/dist/modules/workflow/git/branch-name.js.map +1 -0
- package/dist/modules/workflow/git/clone-config.d.ts +61 -0
- package/dist/modules/workflow/git/clone-config.d.ts.map +1 -0
- package/dist/modules/workflow/git/clone-config.js +69 -0
- package/dist/modules/workflow/git/clone-config.js.map +1 -0
- package/dist/modules/workflow/git/git-version.d.ts +34 -0
- package/dist/modules/workflow/git/git-version.d.ts.map +1 -0
- package/dist/modules/workflow/git/git-version.js +63 -0
- package/dist/modules/workflow/git/git-version.js.map +1 -0
- package/dist/modules/workflow/git/git.service.d.ts +427 -0
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -0
- package/dist/modules/workflow/git/git.service.js +1987 -0
- package/dist/modules/workflow/git/git.service.js.map +1 -0
- package/dist/modules/workflow/git/mutex.d.ts +11 -0
- package/dist/modules/workflow/git/mutex.d.ts.map +1 -0
- package/dist/modules/workflow/git/mutex.js +23 -0
- package/dist/modules/workflow/git/mutex.js.map +1 -0
- package/dist/modules/workflow/git/pull-request.service.d.ts +124 -0
- package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -0
- package/dist/modules/workflow/git/pull-request.service.js +328 -0
- package/dist/modules/workflow/git/pull-request.service.js.map +1 -0
- package/dist/modules/workflow/locking-filesystem.d.ts +133 -0
- package/dist/modules/workflow/locking-filesystem.d.ts.map +1 -0
- package/dist/modules/workflow/locking-filesystem.js +400 -0
- package/dist/modules/workflow/locking-filesystem.js.map +1 -0
- package/dist/modules/workflow/pending-commits.service.d.ts +221 -0
- package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -0
- package/dist/modules/workflow/pending-commits.service.js +364 -0
- package/dist/modules/workflow/pending-commits.service.js.map +1 -0
- package/dist/modules/workflow/pending-commits.worker.d.ts +148 -0
- package/dist/modules/workflow/pending-commits.worker.d.ts.map +1 -0
- package/dist/modules/workflow/pending-commits.worker.js +245 -0
- package/dist/modules/workflow/pending-commits.worker.js.map +1 -0
- package/dist/modules/workflow/read-only-filesystem.d.ts +24 -0
- package/dist/modules/workflow/read-only-filesystem.d.ts.map +1 -0
- package/dist/modules/workflow/read-only-filesystem.js +39 -0
- package/dist/modules/workflow/read-only-filesystem.js.map +1 -0
- package/dist/modules/workflow/recovery-bot.d.ts +31 -0
- package/dist/modules/workflow/recovery-bot.d.ts.map +1 -0
- package/dist/modules/workflow/recovery-bot.js +64 -0
- package/dist/modules/workflow/recovery-bot.js.map +1 -0
- package/dist/modules/workflow/review-workflow/review-workflow.interface.d.ts +137 -0
- package/dist/modules/workflow/review-workflow/review-workflow.interface.d.ts.map +1 -0
- package/dist/modules/workflow/review-workflow/review-workflow.interface.js +2 -0
- package/dist/modules/workflow/review-workflow/review-workflow.interface.js.map +1 -0
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts +26 -0
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -0
- package/dist/modules/workflow/review-workflow/review-workflow.service.js +636 -0
- package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -0
- package/dist/modules/workflow/sanitize-error.d.ts +29 -0
- package/dist/modules/workflow/sanitize-error.d.ts.map +1 -0
- package/dist/modules/workflow/sanitize-error.js +60 -0
- package/dist/modules/workflow/sanitize-error.js.map +1 -0
- package/dist/modules/workflow/session-ontology.policy.d.ts +52 -0
- package/dist/modules/workflow/session-ontology.policy.d.ts.map +1 -0
- package/dist/modules/workflow/session-ontology.policy.js +62 -0
- package/dist/modules/workflow/session-ontology.policy.js.map +1 -0
- package/dist/modules/workflow/session-ontology.service.d.ts +100 -0
- package/dist/modules/workflow/session-ontology.service.d.ts.map +1 -0
- package/dist/modules/workflow/session-ontology.service.js +143 -0
- package/dist/modules/workflow/session-ontology.service.js.map +1 -0
- package/dist/modules/workflow/workflow-hooks.d.ts +87 -0
- package/dist/modules/workflow/workflow-hooks.d.ts.map +1 -0
- package/dist/modules/workflow/workflow-hooks.js +35 -0
- package/dist/modules/workflow/workflow-hooks.js.map +1 -0
- package/dist/modules/workflow/workflow.errors.d.ts +171 -0
- package/dist/modules/workflow/workflow.errors.d.ts.map +1 -0
- package/dist/modules/workflow/workflow.errors.js +260 -0
- package/dist/modules/workflow/workflow.errors.js.map +1 -0
- package/dist/modules/workflow/workflow.routes.d.ts +26 -0
- package/dist/modules/workflow/workflow.routes.d.ts.map +1 -0
- package/dist/modules/workflow/workflow.routes.js +804 -0
- package/dist/modules/workflow/workflow.routes.js.map +1 -0
- package/dist/modules/workflow/workflow.service.d.ts +385 -0
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -0
- package/dist/modules/workflow/workflow.service.js +1155 -0
- package/dist/modules/workflow/workflow.service.js.map +1 -0
- package/dist/modules/workspace/bevel-ignore.d.ts +25 -0
- package/dist/modules/workspace/bevel-ignore.d.ts.map +1 -0
- package/dist/modules/workspace/bevel-ignore.js +57 -0
- package/dist/modules/workspace/bevel-ignore.js.map +1 -0
- package/dist/modules/workspace/kb-seed.interface.d.ts +36 -0
- package/dist/modules/workspace/kb-seed.interface.d.ts.map +1 -0
- package/dist/modules/workspace/kb-seed.interface.js +2 -0
- package/dist/modules/workspace/kb-seed.interface.js.map +1 -0
- package/dist/modules/workspace/kb-seed.service.d.ts +70 -0
- package/dist/modules/workspace/kb-seed.service.d.ts.map +1 -0
- package/dist/modules/workspace/kb-seed.service.js +325 -0
- package/dist/modules/workspace/kb-seed.service.js.map +1 -0
- package/dist/modules/workspace/routine-write-policy.d.ts +49 -0
- package/dist/modules/workspace/routine-write-policy.d.ts.map +1 -0
- package/dist/modules/workspace/routine-write-policy.js +46 -0
- package/dist/modules/workspace/routine-write-policy.js.map +1 -0
- package/dist/modules/workspace/session-ontology.gate.d.ts +112 -0
- package/dist/modules/workspace/session-ontology.gate.d.ts.map +1 -0
- package/dist/modules/workspace/session-ontology.gate.js +161 -0
- package/dist/modules/workspace/session-ontology.gate.js.map +1 -0
- package/dist/modules/workspace/session-sink.d.ts +25 -0
- package/dist/modules/workspace/session-sink.d.ts.map +1 -0
- package/dist/modules/workspace/session-sink.js +8 -0
- package/dist/modules/workspace/session-sink.js.map +1 -0
- package/dist/modules/workspace/spill-store.d.ts +24 -0
- package/dist/modules/workspace/spill-store.d.ts.map +1 -0
- package/dist/modules/workspace/spill-store.js +87 -0
- package/dist/modules/workspace/spill-store.js.map +1 -0
- package/dist/modules/workspace/workspace.routes.d.ts +25 -0
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -0
- package/dist/modules/workspace/workspace.routes.js +1046 -0
- package/dist/modules/workspace/workspace.routes.js.map +1 -0
- package/dist/modules/workspace/workspace.service.d.ts +339 -0
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -0
- package/dist/modules/workspace/workspace.service.js +1221 -0
- package/dist/modules/workspace/workspace.service.js.map +1 -0
- package/dist/modules/workspace/workspace.tools.d.ts +19 -0
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -0
- package/dist/modules/workspace/workspace.tools.js +767 -0
- package/dist/modules/workspace/workspace.tools.js.map +1 -0
- package/dist/shared/frontmatter-id.d.ts +35 -0
- package/dist/shared/frontmatter-id.d.ts.map +1 -0
- package/dist/shared/frontmatter-id.js +68 -0
- package/dist/shared/frontmatter-id.js.map +1 -0
- package/dist/shared/fs-walk.d.ts +9 -0
- package/dist/shared/fs-walk.d.ts.map +1 -0
- package/dist/shared/fs-walk.js +34 -0
- package/dist/shared/fs-walk.js.map +1 -0
- package/dist/shared/hash-email.d.ts +11 -0
- package/dist/shared/hash-email.d.ts.map +1 -0
- package/dist/shared/hash-email.js +14 -0
- package/dist/shared/hash-email.js.map +1 -0
- package/dist/shared/kb-layout.d.ts +38 -0
- package/dist/shared/kb-layout.d.ts.map +1 -0
- package/dist/shared/kb-layout.js +102 -0
- package/dist/shared/kb-layout.js.map +1 -0
- package/dist/shared/kb-layout.test.d.ts +2 -0
- package/dist/shared/kb-layout.test.d.ts.map +1 -0
- package/dist/shared/kb-layout.test.js +67 -0
- package/dist/shared/kb-layout.test.js.map +1 -0
- package/dist/shared/ssrf.d.ts +20 -0
- package/dist/shared/ssrf.d.ts.map +1 -0
- package/dist/shared/ssrf.js +89 -0
- package/dist/shared/ssrf.js.map +1 -0
- package/dist/shared/token-crypto.d.ts +16 -0
- package/dist/shared/token-crypto.d.ts.map +1 -0
- package/dist/shared/token-crypto.js +49 -0
- package/dist/shared/token-crypto.js.map +1 -0
- package/dist/shared/ttl-cache.d.ts +16 -0
- package/dist/shared/ttl-cache.d.ts.map +1 -0
- package/dist/shared/ttl-cache.js +27 -0
- package/dist/shared/ttl-cache.js.map +1 -0
- package/dist/shared/utcp-namespace.d.ts +46 -0
- package/dist/shared/utcp-namespace.d.ts.map +1 -0
- package/dist/shared/utcp-namespace.js +82 -0
- package/dist/shared/utcp-namespace.js.map +1 -0
- package/dist/version.d.ts +17 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +19 -0
- package/dist/version.js.map +1 -0
- package/kb-template/.bevelignore +21 -0
- package/kb-template/Agents/.gitkeep +0 -0
- package/kb-template/Agents/README.md +38 -0
- package/kb-template/CLAUDE.md +419 -0
- package/kb-template/Data/.gitkeep +0 -0
- package/kb-template/Data/README.md +39 -0
- package/kb-template/KnowledgeBase/.gitkeep +0 -0
- package/kb-template/KnowledgeBase/README.md +37 -0
- package/kb-template/Pipelines/.gitkeep +0 -0
- package/kb-template/Pipelines/README.md +38 -0
- package/kb-template/Skills/.gitkeep +0 -0
- package/kb-template/Skills/README.md +32 -0
- package/kb-template/Tools/.gitkeep +0 -0
- package/kb-template/Tools/README.md +42 -0
- package/kb-template/access.md +36 -0
- package/migrations/0000_core_init.sql +243 -0
- package/migrations/meta/0000_snapshot.json +1480 -0
- package/migrations/meta/_journal.json +13 -0
- package/package.json +80 -0
- package/src/assets.ts +25 -0
- package/src/core/core-ports.ts +91 -0
- package/src/core/create-core-server.ts +338 -0
- package/src/core/create-core-services.ts +501 -0
- package/src/core-config.ts +257 -0
- package/src/index.ts +69 -0
- package/src/modules/access/__tests__/access-control.atref-batch.test.ts +98 -0
- package/src/modules/access/__tests__/access-control.read-batch.test.ts +132 -0
- package/src/modules/access/__tests__/access-control.service.test.ts +1011 -0
- package/src/modules/access/__tests__/access-mutation.service.test.ts +439 -0
- package/src/modules/access/__tests__/access-splice.test.ts +247 -0
- package/src/modules/access/__tests__/access.routes.revoke.test.ts +407 -0
- package/src/modules/access/__tests__/creator-access.test.ts +217 -0
- package/src/modules/access/__tests__/grant-sources.test.ts +204 -0
- package/src/modules/access/__tests__/kb-read-filter.test.ts +70 -0
- package/src/modules/access/__tests__/roles-admin.service.test.ts +469 -0
- package/src/modules/access/__tests__/roles-edit.test.ts +138 -0
- package/src/modules/access/__tests__/roles-yaml-guard.test.ts +70 -0
- package/src/modules/access/__tests__/roles.routes.test.ts +234 -0
- package/src/modules/access/access-control.interface.ts +383 -0
- package/src/modules/access/access-control.service.ts +1794 -0
- package/src/modules/access/access-errors.ts +60 -0
- package/src/modules/access/access-mutation.service.ts +369 -0
- package/src/modules/access/access-splice.ts +413 -0
- package/src/modules/access/access.routes.ts +894 -0
- package/src/modules/access/creator-access.ts +270 -0
- package/src/modules/access/kb-read-filter.ts +76 -0
- package/src/modules/access/roles-admin.service.ts +741 -0
- package/src/modules/access/roles-edit.ts +248 -0
- package/src/modules/access/roles-yaml-guard.ts +89 -0
- package/src/modules/admin/admin-access.routes.ts +29 -0
- package/src/modules/admin/admin-access.service.ts +38 -0
- package/src/modules/admin/admin.interface.ts +10 -0
- package/src/modules/auth/account-erasure.service.ts +183 -0
- package/src/modules/auth/auth.middleware.ts +78 -0
- package/src/modules/auth/auth.routes.ts +97 -0
- package/src/modules/auth/auth.service.ts +199 -0
- package/src/modules/code-mode/code-mode-names.ts +38 -0
- package/src/modules/code-mode/code-mode.tool.ts +117 -0
- package/src/modules/code-mode/index.ts +6 -0
- package/src/modules/database/connection.ts +15 -0
- package/src/modules/database/core-schema.ts +431 -0
- package/src/modules/database/migrate.ts +43 -0
- package/src/modules/database/schema.ts +11 -0
- package/src/modules/diff/__tests__/diff.routes.read-gate.test.ts +87 -0
- package/src/modules/diff/__tests__/diff.routes.rejectPathsLocked.test.ts +150 -0
- package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +184 -0
- package/src/modules/diff/__tests__/diff.service.test.ts +202 -0
- package/src/modules/diff/diff-paths.ts +9 -0
- package/src/modules/diff/diff.config.ts +12 -0
- package/src/modules/diff/diff.interface.ts +78 -0
- package/src/modules/diff/diff.routes.ts +277 -0
- package/src/modules/diff/diff.service.ts +508 -0
- package/src/modules/diff/line-diff.ts +79 -0
- package/src/modules/mcp/__tests__/bevel-oauth-provider.test.ts +287 -0
- package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +249 -0
- package/src/modules/mcp/__tests__/mcp-proxy-helpers.test.ts +253 -0
- package/src/modules/mcp/__tests__/mcp-session-store.test.ts +151 -0
- package/src/modules/mcp/__tests__/mcp.e2e.test.ts +150 -0
- package/src/modules/mcp/__tests__/mcp.routes.delete.test.ts +92 -0
- package/src/modules/mcp/__tests__/mcp.service.test.ts +414 -0
- package/src/modules/mcp/mcp-auth.middleware.ts +126 -0
- package/src/modules/mcp/mcp-session-store.ts +162 -0
- package/src/modules/mcp/mcp.routes.ts +263 -0
- package/src/modules/mcp/mcp.service.ts +973 -0
- package/src/modules/mcp/oauth/bevel-oauth-provider.ts +401 -0
- package/src/modules/mcp/oauth/oauth-consent.routes.ts +60 -0
- package/src/modules/mcp/oauth/oauth-state.ts +61 -0
- package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +277 -0
- package/src/modules/secrets-vault/__tests__/db-secrets-vault.oauth.test.ts +206 -0
- package/src/modules/secrets-vault/__tests__/mcp-oauth-discovery.service.test.ts +178 -0
- package/src/modules/secrets-vault/__tests__/scopes-covered.test.ts +101 -0
- package/src/modules/secrets-vault/__tests__/secrets-variable-loader.test.ts +54 -0
- package/src/modules/secrets-vault/__tests__/tool-owner-gate.route.test.ts +143 -0
- package/src/modules/secrets-vault/db-secrets-vault.service.ts +792 -0
- package/src/modules/secrets-vault/index.ts +25 -0
- package/src/modules/secrets-vault/mcp-oauth-discovery.service.ts +289 -0
- package/src/modules/secrets-vault/secrets-variable-loader.ts +104 -0
- package/src/modules/secrets-vault/secrets-vault.contract.ts +270 -0
- package/src/modules/secrets-vault/secrets-vault.routes.ts +526 -0
- package/src/modules/skills/__tests__/skills.service.test.ts +176 -0
- package/src/modules/skills/index.ts +10 -0
- package/src/modules/skills/skills.contract.ts +54 -0
- package/src/modules/skills/skills.routes.ts +38 -0
- package/src/modules/skills/skills.service.ts +245 -0
- package/src/modules/skills/skills.tools.ts +121 -0
- package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +358 -0
- package/src/modules/tool-auth/__tests__/internal-token.service.test.ts +79 -0
- package/src/modules/tool-auth/__tests__/manual-auth.middleware.test.ts +88 -0
- package/src/modules/tool-auth/external-api-key.errors.ts +25 -0
- package/src/modules/tool-auth/external-api-key.interface.ts +99 -0
- package/src/modules/tool-auth/external-api-key.service.ts +209 -0
- package/src/modules/tool-auth/internal-token.service.ts +124 -0
- package/src/modules/tool-auth/llm-usage-meter.ts +19 -0
- package/src/modules/tool-auth/tool-auth.middleware.ts +220 -0
- package/src/modules/tool-helpers/__tests__/phase0-loopback-spike.test.ts +129 -0
- package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +95 -0
- package/src/modules/tool-helpers/__tests__/tools-surface.test.ts +146 -0
- package/src/modules/tool-helpers/__tests__/validate-token.test.ts +75 -0
- package/src/modules/tool-helpers/index.ts +18 -0
- package/src/modules/tool-helpers/tool-context.ts +98 -0
- package/src/modules/tool-helpers/tool-def.ts +73 -0
- package/src/modules/tool-helpers/tool-handler.ts +91 -0
- package/src/modules/tool-helpers/tool.contract.ts +85 -0
- package/src/modules/tool-helpers/validate-token.ts +50 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +200 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +499 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +156 -0
- package/src/modules/tool-manuals/index.ts +12 -0
- package/src/modules/tool-manuals/tool-manuals.contract.ts +183 -0
- package/src/modules/tool-manuals/tool-manuals.routes.ts +110 -0
- package/src/modules/tool-manuals/tool-manuals.service.ts +781 -0
- package/src/modules/tool-manuals/tool-manuals.tools.ts +202 -0
- package/src/modules/tool-registry/__tests__/tool-registry.test.ts +64 -0
- package/src/modules/tool-registry/manual.routes.ts +87 -0
- package/src/modules/tool-registry/tool-registry.ts +55 -0
- package/src/modules/tool-registry/tool.contract.ts +52 -0
- package/src/modules/workflow/__tests__/event-bus.test.ts +322 -0
- package/src/modules/workflow/__tests__/file-change-notifier.test.ts +51 -0
- package/src/modules/workflow/__tests__/format-affected-owners.test.ts +67 -0
- package/src/modules/workflow/__tests__/locking-filesystem.test.ts +445 -0
- package/src/modules/workflow/__tests__/pending-commits.canonical.test.ts +36 -0
- package/src/modules/workflow/__tests__/pending-commits.worker.test.ts +243 -0
- package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +308 -0
- package/src/modules/workflow/__tests__/sanitize-error.test.ts +67 -0
- package/src/modules/workflow/__tests__/session-ontology.policy.test.ts +62 -0
- package/src/modules/workflow/__tests__/session-ontology.service.test.ts +200 -0
- package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +232 -0
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +380 -0
- package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +340 -0
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +192 -0
- package/src/modules/workflow/agent-tools/workflow.tools.ts +502 -0
- package/src/modules/workflow/event-bus.ts +262 -0
- package/src/modules/workflow/events.routes.ts +266 -0
- package/src/modules/workflow/file-change-notifier.ts +54 -0
- package/src/modules/workflow/file-lock.service.ts +269 -0
- package/src/modules/workflow/git/__tests__/branch-name.test.ts +86 -0
- package/src/modules/workflow/git/__tests__/branchAuthor.test.ts +80 -0
- package/src/modules/workflow/git/__tests__/clone-config.test.ts +15 -0
- package/src/modules/workflow/git/__tests__/git-test-helpers.ts +47 -0
- package/src/modules/workflow/git/__tests__/git-version.failure.test.ts +24 -0
- package/src/modules/workflow/git/__tests__/git-version.test.ts +49 -0
- package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +389 -0
- package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +124 -0
- package/src/modules/workflow/git/__tests__/git.service.commitChanges.test.ts +105 -0
- package/src/modules/workflow/git/__tests__/git.service.commitFile.test.ts +211 -0
- package/src/modules/workflow/git/__tests__/git.service.createBranch.test.ts +154 -0
- package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +320 -0
- package/src/modules/workflow/git/__tests__/git.service.diffFileAtCommit.test.ts +202 -0
- package/src/modules/workflow/git/__tests__/git.service.diffFileBetweenBranches.test.ts +453 -0
- package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +198 -0
- package/src/modules/workflow/git/__tests__/git.service.listTrackedFiles.test.ts +125 -0
- package/src/modules/workflow/git/__tests__/git.service.logForFile.test.ts +219 -0
- package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +145 -0
- package/src/modules/workflow/git/__tests__/git.service.pendingChanges.test.ts +240 -0
- package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +272 -0
- package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +232 -0
- package/src/modules/workflow/git/__tests__/git.service.readFileAtRef.test.ts +101 -0
- package/src/modules/workflow/git/__tests__/git.service.status.test.ts +127 -0
- package/src/modules/workflow/git/__tests__/mutex.test.ts +78 -0
- package/src/modules/workflow/git/__tests__/pull-request.service.test.ts +225 -0
- package/src/modules/workflow/git/__tests__/pull-request.service.viewer-can-cancel.test.ts +101 -0
- package/src/modules/workflow/git/branch-name.ts +70 -0
- package/src/modules/workflow/git/clone-config.ts +71 -0
- package/src/modules/workflow/git/git-version.ts +70 -0
- package/src/modules/workflow/git/git.service.ts +2248 -0
- package/src/modules/workflow/git/mutex.ts +22 -0
- package/src/modules/workflow/git/pull-request.service.ts +447 -0
- package/src/modules/workflow/locking-filesystem.ts +489 -0
- package/src/modules/workflow/pending-commits.service.ts +444 -0
- package/src/modules/workflow/pending-commits.worker.ts +361 -0
- package/src/modules/workflow/read-only-filesystem.ts +54 -0
- package/src/modules/workflow/recovery-bot.ts +73 -0
- package/src/modules/workflow/review-workflow/__tests__/approval-states.test.ts +560 -0
- package/src/modules/workflow/review-workflow/__tests__/cancel-pr.test.ts +176 -0
- package/src/modules/workflow/review-workflow/__tests__/merge-gate.test.ts +258 -0
- package/src/modules/workflow/review-workflow/review-workflow.interface.ts +199 -0
- package/src/modules/workflow/review-workflow/review-workflow.service.ts +806 -0
- package/src/modules/workflow/sanitize-error.ts +62 -0
- package/src/modules/workflow/session-ontology.policy.ts +70 -0
- package/src/modules/workflow/session-ontology.service.ts +178 -0
- package/src/modules/workflow/workflow-hooks.ts +101 -0
- package/src/modules/workflow/workflow.errors.ts +285 -0
- package/src/modules/workflow/workflow.routes.ts +858 -0
- package/src/modules/workflow/workflow.service.ts +1555 -0
- package/src/modules/workspace/__tests__/kb-seed.service.test.ts +213 -0
- package/src/modules/workspace/__tests__/routine-write-policy.test.ts +68 -0
- package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +237 -0
- package/src/modules/workspace/__tests__/spill-store.test.ts +43 -0
- package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +233 -0
- package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +176 -0
- package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +303 -0
- package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +276 -0
- package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +120 -0
- package/src/modules/workspace/__tests__/workspace.service.test.ts +565 -0
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +504 -0
- package/src/modules/workspace/bevel-ignore.ts +62 -0
- package/src/modules/workspace/kb-seed.interface.ts +36 -0
- package/src/modules/workspace/kb-seed.service.ts +361 -0
- package/src/modules/workspace/routine-write-policy.ts +79 -0
- package/src/modules/workspace/session-ontology.gate.ts +189 -0
- package/src/modules/workspace/session-sink.ts +25 -0
- package/src/modules/workspace/spill-store.ts +87 -0
- package/src/modules/workspace/workspace.routes.ts +1114 -0
- package/src/modules/workspace/workspace.service.ts +1343 -0
- package/src/modules/workspace/workspace.tools.ts +885 -0
- package/src/shared/__tests__/frontmatter-id.test.ts +88 -0
- package/src/shared/__tests__/fs-walk.test.ts +42 -0
- package/src/shared/__tests__/ssrf.test.ts +53 -0
- package/src/shared/__tests__/utcp-namespace.test.ts +19 -0
- package/src/shared/frontmatter-id.ts +72 -0
- package/src/shared/fs-walk.ts +30 -0
- package/src/shared/hash-email.ts +14 -0
- package/src/shared/kb-layout.test.ts +88 -0
- package/src/shared/kb-layout.ts +101 -0
- package/src/shared/ssrf.ts +78 -0
- package/src/shared/token-crypto.ts +54 -0
- package/src/shared/ttl-cache.ts +27 -0
- package/src/shared/utcp-namespace.ts +88 -0
- package/src/version.ts +19 -0
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
import type { Server as HttpServer } from 'node:http';
|
|
2
|
+
import { execFile } from 'node:child_process';
|
|
3
|
+
import { mkdir, mkdtemp, rm } from 'node:fs/promises';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { promisify } from 'node:util';
|
|
7
|
+
import express from 'express';
|
|
8
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
9
|
+
import { LocalFilesystem } from '@mastra/core/workspace';
|
|
10
|
+
import { ToolRegistry } from '../../tool-registry/tool-registry.js';
|
|
11
|
+
import { createToolHandlerFactory } from '../../tool-helpers/tool-handler.js';
|
|
12
|
+
import type { ToolContext } from '../../tool-helpers/tool.contract.js';
|
|
13
|
+
import type { ToolAuth } from '../../tool-auth/tool-auth.middleware.js';
|
|
14
|
+
import { registerWorkspaceTools } from '../workspace.tools.js';
|
|
15
|
+
import { RoutineWritePolicyService } from '../routine-write-policy.js';
|
|
16
|
+
import { WorkflowHooks } from '../../workflow/workflow-hooks.js';
|
|
17
|
+
import { SpillStore } from '../spill-store.js';
|
|
18
|
+
import type { IAccessControl } from '../../access/access-control.interface.js';
|
|
19
|
+
|
|
20
|
+
const KB_DIR = 'knowledge-base';
|
|
21
|
+
|
|
22
|
+
/** Allow-all access control — the default for tests not exercising read gating. */
|
|
23
|
+
const allowAll = {
|
|
24
|
+
canRead: async () => true,
|
|
25
|
+
canReadBatch: async (_w: string, _u: string, paths: string[]) =>
|
|
26
|
+
new Map(paths.map((p) => [p, true])),
|
|
27
|
+
} as unknown as IAccessControl;
|
|
28
|
+
|
|
29
|
+
/** Access control that denies `canRead` for an explicit set of repo-relative paths. */
|
|
30
|
+
function denyReads(denied: Set<string>): IAccessControl {
|
|
31
|
+
return {
|
|
32
|
+
canRead: async (_w: string, _u: string, rel: string) => !denied.has(rel),
|
|
33
|
+
canReadBatch: async (_w: string, _u: string, paths: string[]) =>
|
|
34
|
+
new Map(paths.map((p) => [p, !denied.has(p)])),
|
|
35
|
+
} as unknown as IAccessControl;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* File primitives over a REAL LocalFilesystem on a temp dir — proves read_file /
|
|
40
|
+
* write_file / edit_file / list_files / grep / file_stat / execute_command
|
|
41
|
+
* actually work (the handlers re-expose the same filesystem methods Mastra
|
|
42
|
+
* uses). No locking pipeline (plain LocalFilesystem), so writes don't commit.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
let httpServer: HttpServer | undefined;
|
|
46
|
+
let tempDir = '';
|
|
47
|
+
let fs: LocalFilesystem;
|
|
48
|
+
/**
|
|
49
|
+
* Every branch / workspaceId `execute_command`'s handler resolves a workspace
|
|
50
|
+
* for. Resolving a workspace is what triggers the lazy per-branch CLONE in
|
|
51
|
+
* production, so asserting this never contains `"undefined"` proves the
|
|
52
|
+
* missing-branch guard short-circuits before any clone of a branch literally
|
|
53
|
+
* named "undefined" is attempted.
|
|
54
|
+
*/
|
|
55
|
+
let workspacePathCalls: string[] = [];
|
|
56
|
+
/** The policy instance the tools were mounted with, so a test can restrict a session. */
|
|
57
|
+
let writePolicy: RoutineWritePolicyService;
|
|
58
|
+
|
|
59
|
+
async function start(
|
|
60
|
+
scope: 'read' | 'write' = 'write',
|
|
61
|
+
access: IAccessControl = allowAll,
|
|
62
|
+
): Promise<string> {
|
|
63
|
+
tempDir = await mkdtemp(join(tmpdir(), 'ws-tools-'));
|
|
64
|
+
fs = new LocalFilesystem({ basePath: tempDir, contained: true });
|
|
65
|
+
await fs.writeFile('a.md', 'hello\nworld\n');
|
|
66
|
+
workspacePathCalls = [];
|
|
67
|
+
writePolicy = new RoutineWritePolicyService();
|
|
68
|
+
|
|
69
|
+
const registry = new ToolRegistry();
|
|
70
|
+
const resolve = async (auth: ToolAuth, signal: AbortSignal, sessionId?: string): Promise<ToolContext> => ({
|
|
71
|
+
user: { id: 'u', email: 'e@x', name: 'N' },
|
|
72
|
+
scope: auth.scope,
|
|
73
|
+
source: auth.source,
|
|
74
|
+
sessionId,
|
|
75
|
+
abortSignal: signal,
|
|
76
|
+
workspaceService: {
|
|
77
|
+
// Both entry points record, so the guard tests prove NEITHER resolves a
|
|
78
|
+
// workspace for an invalid branch.
|
|
79
|
+
getOrCreateForBranch: async (branch: string) => {
|
|
80
|
+
workspacePathCalls.push(branch);
|
|
81
|
+
return { id: encodeURIComponent(branch), name: branch, absolutePath: tempDir, createdAt: '', kbDirName: KB_DIR };
|
|
82
|
+
},
|
|
83
|
+
getWorkspacePath: async (id: string) => {
|
|
84
|
+
workspacePathCalls.push(id);
|
|
85
|
+
return tempDir;
|
|
86
|
+
},
|
|
87
|
+
} as never,
|
|
88
|
+
workflowService: {} as never,
|
|
89
|
+
events: {} as never,
|
|
90
|
+
getFilesystem: async () => fs,
|
|
91
|
+
});
|
|
92
|
+
const toolHandler = createToolHandlerFactory(resolve);
|
|
93
|
+
const fakeAuth = (req: express.Request, _res: express.Response, next: express.NextFunction) => {
|
|
94
|
+
req.toolAuth = { source: 'internal', userId: 'u', scope };
|
|
95
|
+
next();
|
|
96
|
+
};
|
|
97
|
+
const app = express();
|
|
98
|
+
app.use(express.json());
|
|
99
|
+
const router = express.Router();
|
|
100
|
+
registerWorkspaceTools(registry, router, fakeAuth, toolHandler, new SpillStore(join(tmpdir(), 'bevel-test-spills')), access, KB_DIR, {
|
|
101
|
+
service: {} as never,
|
|
102
|
+
enabled: false, // these tests predate and don't exercise the ontology boundary
|
|
103
|
+
kbDirName: KB_DIR,
|
|
104
|
+
recoveryBotEmail: 'recovery-bot@bevel.local',
|
|
105
|
+
hooks: new WorkflowHooks(),
|
|
106
|
+
}, writePolicy, {} as never /* sessionSink — start_session not exercised here */);
|
|
107
|
+
app.use('/api', router);
|
|
108
|
+
httpServer = await new Promise<HttpServer>((r) => {
|
|
109
|
+
const s = app.listen(0, () => r(s));
|
|
110
|
+
});
|
|
111
|
+
return `http://127.0.0.1:${(httpServer.address() as { port: number }).port}`;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const post = (url: string, body: unknown = {}) =>
|
|
115
|
+
fetch(url, { method: 'POST', headers: { 'content-type': 'application/json', authorization: 'Bearer x' }, body: JSON.stringify(body) });
|
|
116
|
+
|
|
117
|
+
beforeEach(() => {
|
|
118
|
+
/* fresh per test via start() */
|
|
119
|
+
});
|
|
120
|
+
afterEach(async () => {
|
|
121
|
+
if (httpServer) await new Promise<void>((r) => httpServer!.close(() => r()));
|
|
122
|
+
httpServer = undefined;
|
|
123
|
+
if (tempDir) {
|
|
124
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
125
|
+
tempDir = '';
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe('workspace file primitives', () => {
|
|
130
|
+
it('read_file returns the content', async () => {
|
|
131
|
+
const base = await start();
|
|
132
|
+
expect(await (await post(`${base}/api/agent/tools/read_file`, { path: 'a.md' })).json()).toEqual({ path: 'a.md', content: 'hello\nworld\n' });
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('write_file then read_file round-trips', async () => {
|
|
136
|
+
const base = await start();
|
|
137
|
+
await post(`${base}/api/agent/tools/write_file`, { path: 'b.md', content: 'fresh' });
|
|
138
|
+
expect(await (await post(`${base}/api/agent/tools/read_file`, { path: 'b.md' })).json()).toMatchObject({ content: 'fresh' });
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('edit_file replaces an exact unique string', async () => {
|
|
142
|
+
const base = await start();
|
|
143
|
+
const res = await post(`${base}/api/agent/tools/edit_file`, { path: 'a.md', old_string: 'world', new_string: 'earth' });
|
|
144
|
+
expect(await res.json()).toMatchObject({ path: 'a.md', replaced: 1 });
|
|
145
|
+
expect(await (await post(`${base}/api/agent/tools/read_file`, { path: 'a.md' })).json()).toMatchObject({ content: 'hello\nearth\n' });
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('edit_file 400s when old_string is missing', async () => {
|
|
149
|
+
const base = await start();
|
|
150
|
+
expect((await post(`${base}/api/agent/tools/edit_file`, { path: 'a.md', old_string: 'nope', new_string: 'x' })).status).toBe(400);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('list_files + file_stat', async () => {
|
|
154
|
+
const base = await start();
|
|
155
|
+
const list = (await (await post(`${base}/api/agent/tools/list_files`, {})).json()) as { entries: { name: string }[] };
|
|
156
|
+
expect(list.entries.map((e) => e.name)).toContain('a.md');
|
|
157
|
+
expect(await (await post(`${base}/api/agent/tools/file_stat`, { path: 'a.md' })).json()).toMatchObject({ type: 'file' });
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('grep finds a match with line number', async () => {
|
|
161
|
+
const base = await start();
|
|
162
|
+
const res = (await (await post(`${base}/api/agent/tools/grep`, { pattern: 'wor' })).json()) as { matches: { path: string; line: number }[] };
|
|
163
|
+
expect(res.matches).toContainEqual(expect.objectContaining({ path: 'a.md', line: 2 }));
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('execute_command runs in the workspace dir', async () => {
|
|
167
|
+
const base = await start();
|
|
168
|
+
const res = (await (await post(`${base}/api/agent/tools/execute_command`, { branch: 'main', command: 'echo hello-exec' })).json()) as { stdout: string; exitCode: number };
|
|
169
|
+
expect(res.stdout).toContain('hello-exec');
|
|
170
|
+
expect(res.exitCode).toBe(0);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('execute_command 400s when no branch is given (never clones "undefined")', async () => {
|
|
174
|
+
const base = await start();
|
|
175
|
+
// A missing branch must NOT resolve the workspace id to "undefined" and try
|
|
176
|
+
// to clone a branch literally named "undefined" — it must fail closed with a
|
|
177
|
+
// clear 4xx naming the missing branch context, BEFORE any workspace resolve.
|
|
178
|
+
const res = await post(`${base}/api/agent/tools/execute_command`, { command: 'echo should-not-run' });
|
|
179
|
+
expect(res.status).toBe(400);
|
|
180
|
+
expect((await res.json()).error).toMatch(/branch/i);
|
|
181
|
+
// The guard runs before `getWorkspacePath`, so no workspace (least of all the
|
|
182
|
+
// "undefined" one) is ever resolved — proving no clone is attempted.
|
|
183
|
+
expect(workspacePathCalls).toEqual([]);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Every branch value that must fail closed without resolving a workspace.
|
|
187
|
+
// `''` (like the missing field above) is refused a layer earlier by the input
|
|
188
|
+
// schema's `minLength: 1`; the rest satisfy the schema and reach the handler,
|
|
189
|
+
// so they exercise the guard itself. Both layers must produce the same 400.
|
|
190
|
+
// The malformed refs below are rejected by the shared `assertValidBranchName`,
|
|
191
|
+
// which replaced the hand-listed "undefined"/"null" reservations: those are
|
|
192
|
+
// legal git branch names, and the bug PR #285 fixed was an ABSENT `branch`
|
|
193
|
+
// (caught by the missing/non-string check above), not a caller that says
|
|
194
|
+
// "undefined" on purpose.
|
|
195
|
+
const invalidBranches: Array<[label: string, branch: string]> = [
|
|
196
|
+
['empty', ''],
|
|
197
|
+
['whitespace-only', ' '],
|
|
198
|
+
['whitespace-padded', ' main '],
|
|
199
|
+
['containing a space', 'alice/my draft'],
|
|
200
|
+
['containing ".."', 'alice/../../etc'],
|
|
201
|
+
['starting with "-"', '--upload-pack=touch'],
|
|
202
|
+
['containing "//"', 'alice//draft'],
|
|
203
|
+
['ending with "/"', 'alice/'],
|
|
204
|
+
['a segment starting with "."', 'alice/.hidden'],
|
|
205
|
+
['a segment ending with ".lock"', 'alice/draft.lock'],
|
|
206
|
+
['containing "@{"', 'alice/draft@{0}'],
|
|
207
|
+
['containing a shell metacharacter', 'alice/draft;rm -rf /'],
|
|
208
|
+
];
|
|
209
|
+
for (const [label, branch] of invalidBranches) {
|
|
210
|
+
it(`execute_command 400s when branch is ${label}`, async () => {
|
|
211
|
+
const base = await start();
|
|
212
|
+
const res = await post(`${base}/api/agent/tools/execute_command`, { branch, command: 'echo should-not-run' });
|
|
213
|
+
expect(res.status).toBe(400);
|
|
214
|
+
expect((await res.json()).error).toMatch(/branch/i);
|
|
215
|
+
// No workspace is resolved for the bad value — proving no clone is attempted.
|
|
216
|
+
expect(workspacePathCalls).toEqual([]);
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
it('execute_command accepts a branch git itself considers valid (no literal-name reservations)', async () => {
|
|
221
|
+
const base = await start();
|
|
222
|
+
// "undefined"/"null" used to be hand-reserved here. They're ordinary branch
|
|
223
|
+
// names as far as git is concerned, and the real PR #285 guard is the
|
|
224
|
+
// missing/non-string check — so the validator must let them through.
|
|
225
|
+
for (const branch of ['undefined', 'null']) {
|
|
226
|
+
const res = (await (await post(`${base}/api/agent/tools/execute_command`, { branch, command: 'echo ok' })).json()) as { stdout: string; exitCode: number };
|
|
227
|
+
expect(res.exitCode).toBe(0);
|
|
228
|
+
}
|
|
229
|
+
expect(workspacePathCalls).toEqual(['undefined', 'null']);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('execute_command validates the branch BEFORE the write-policy gate', async () => {
|
|
233
|
+
const base = await start();
|
|
234
|
+
// A routine-restricted session is refused by `assertUnrestricted` with 403.
|
|
235
|
+
// The branch guard must still run first, so a malformed call gets the 400
|
|
236
|
+
// that names the bad context instead of a 403 masking it.
|
|
237
|
+
writePolicy.restrictToExtensions('restricted-run', ['.html']);
|
|
238
|
+
const res = await post(`${base}/api/agent/tools/execute_command`, {
|
|
239
|
+
branch: 'alice/../../etc',
|
|
240
|
+
command: 'echo should-not-run',
|
|
241
|
+
sessionId: 'restricted-run',
|
|
242
|
+
});
|
|
243
|
+
expect(res.status).toBe(400);
|
|
244
|
+
expect((await res.json()).error).toMatch(/branch/i);
|
|
245
|
+
expect(workspacePathCalls).toEqual([]);
|
|
246
|
+
// …and the restriction really is live for that session (so the 400 above is
|
|
247
|
+
// the guard winning the race, not an inert policy).
|
|
248
|
+
const gated = await post(`${base}/api/agent/tools/execute_command`, {
|
|
249
|
+
branch: 'main',
|
|
250
|
+
command: 'echo should-not-run',
|
|
251
|
+
sessionId: 'restricted-run',
|
|
252
|
+
});
|
|
253
|
+
expect(gated.status).toBe(403);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it('execute_command bootstraps the workspace through getOrCreateForBranch', async () => {
|
|
257
|
+
const base = await start();
|
|
258
|
+
// Per-branch bootstrap is the service's job: the shell passes the branch
|
|
259
|
+
// itself rather than hand-encoding a workspace id.
|
|
260
|
+
await post(`${base}/api/agent/tools/execute_command`, { branch: 'alice/draft', command: 'echo hi' });
|
|
261
|
+
expect(workspacePathCalls).toEqual(['alice/draft']);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('execute_command runs plain git against the nested KB clone', async () => {
|
|
265
|
+
const base = await start();
|
|
266
|
+
// Production layout: the repo lives one level BELOW the shell's cwd, at
|
|
267
|
+
// <workspace>/<kbDirName>/.git. A bare `git …` (what the agent prompt
|
|
268
|
+
// teaches) must still target that clone instead of failing with
|
|
269
|
+
// "not a git repository".
|
|
270
|
+
const execFileAsync = promisify(execFile);
|
|
271
|
+
const repoDir = join(tempDir, KB_DIR);
|
|
272
|
+
await mkdir(repoDir, { recursive: true });
|
|
273
|
+
await execFileAsync('git', ['init'], { cwd: repoDir });
|
|
274
|
+
await execFileAsync(
|
|
275
|
+
'git',
|
|
276
|
+
['-c', 'user.email=t@test', '-c', 'user.name=t', 'commit', '--allow-empty', '-m', 'kb-seed'],
|
|
277
|
+
{ cwd: repoDir },
|
|
278
|
+
);
|
|
279
|
+
const res = (await (await post(`${base}/api/agent/tools/execute_command`, { branch: 'main', command: 'git log -1 --format=%s' })).json()) as { stdout: string; stderr: string; exitCode: number };
|
|
280
|
+
expect(res.exitCode).toBe(0);
|
|
281
|
+
expect(res.stdout.trim()).toBe('kb-seed');
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it('execute_command does not leak GIT_DIR into non-git commands', async () => {
|
|
285
|
+
const base = await start();
|
|
286
|
+
// The KB-clone GIT_DIR/GIT_WORK_TREE override is scoped to bare `git …`
|
|
287
|
+
// only; a non-git command (e.g. npm/pip that shells git internally) must
|
|
288
|
+
// NOT inherit it, or the nested git child would target the KB clone.
|
|
289
|
+
const res = (await (await post(`${base}/api/agent/tools/execute_command`, { branch: 'main', command: 'echo "GIT_DIR=[$GIT_DIR]"' })).json()) as { stdout: string; stderr: string; exitCode: number };
|
|
290
|
+
expect(res.exitCode).toBe(0);
|
|
291
|
+
expect(res.stdout.trim()).toBe('GIT_DIR=[]');
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it('execute_command does not leak GIT_DIR into a chained step after git', async () => {
|
|
295
|
+
const base = await start();
|
|
296
|
+
// Runs under `shell: true`, so a command that merely STARTS with git but
|
|
297
|
+
// chains another step must not export the KB git env to the whole shell —
|
|
298
|
+
// otherwise `git … && npm ci` would leak the KB repo context into the npm/pip
|
|
299
|
+
// git subprocess. `git --version` needs no repo, so exit stays 0.
|
|
300
|
+
const res = (await (await post(`${base}/api/agent/tools/execute_command`, { branch: 'main', command: 'git --version >/dev/null && echo "leak=[$GIT_DIR]"' })).json()) as { stdout: string; stderr: string; exitCode: number };
|
|
301
|
+
expect(res.exitCode).toBe(0);
|
|
302
|
+
expect(res.stdout.trim()).toBe('leak=[]');
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('read scope refuses write tools (403) but allows reads', async () => {
|
|
306
|
+
const base = await start('read');
|
|
307
|
+
expect((await post(`${base}/api/agent/tools/write_file`, { path: 'c.md', content: 'x' })).status).toBe(403);
|
|
308
|
+
expect((await post(`${base}/api/agent/tools/read_file`, { path: 'a.md' })).status).toBe(200);
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
describe('read-permission gating', () => {
|
|
313
|
+
// Seed two KB nodes; the access stub denies read on the "secret" one.
|
|
314
|
+
async function startGated(): Promise<string> {
|
|
315
|
+
const base = await start('write', denyReads(new Set([`Knowledge/Secret.md`])));
|
|
316
|
+
await fs.writeFile(`${KB_DIR}/Knowledge/Public.md`, 'public body\nneedle\n');
|
|
317
|
+
await fs.writeFile(`${KB_DIR}/Knowledge/Secret.md`, 'secret body\nneedle\n');
|
|
318
|
+
return base;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
it('read_file denies an unreadable KB node with 403', async () => {
|
|
322
|
+
const base = await startGated();
|
|
323
|
+
expect((await post(`${base}/api/agent/tools/read_file`, { path: `${KB_DIR}/Knowledge/Secret.md` })).status).toBe(403);
|
|
324
|
+
expect((await post(`${base}/api/agent/tools/read_file`, { path: `${KB_DIR}/Knowledge/Public.md` })).status).toBe(200);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('list_files hides unreadable KB nodes but keeps readable ones', async () => {
|
|
328
|
+
const base = await startGated();
|
|
329
|
+
const list = (await (await post(`${base}/api/agent/tools/list_files`, { path: `${KB_DIR}/Knowledge` })).json()) as {
|
|
330
|
+
entries: { name: string }[];
|
|
331
|
+
};
|
|
332
|
+
const names = list.entries.map((e) => e.name);
|
|
333
|
+
expect(names).toContain('Public.md');
|
|
334
|
+
expect(names).not.toContain('Secret.md');
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it('grep never returns a line from an unreadable KB node', async () => {
|
|
338
|
+
const base = await startGated();
|
|
339
|
+
const res = (await (await post(`${base}/api/agent/tools/grep`, { pattern: 'needle', path: KB_DIR })).json()) as {
|
|
340
|
+
matches: { path: string }[];
|
|
341
|
+
};
|
|
342
|
+
const paths = res.matches.map((m) => m.path);
|
|
343
|
+
expect(paths).toContain(`${KB_DIR}/Knowledge/Public.md`);
|
|
344
|
+
expect(paths).not.toContain(`${KB_DIR}/Knowledge/Secret.md`);
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it('non-KB workspace files are never gated', async () => {
|
|
348
|
+
// `a.md` lives at the workspace root, outside the KB dir → always readable.
|
|
349
|
+
const base = await start('read', denyReads(new Set(['a.md'])));
|
|
350
|
+
expect((await post(`${base}/api/agent/tools/read_file`, { path: 'a.md' })).status).toBe(200);
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* start_session must mint a REAL chat thread and return its id (not a bare
|
|
356
|
+
* random UUID), so the same id works for KB reads AND for `ask` (whose
|
|
357
|
+
* sessionId IS a chat thread). This is what unifies the ontology boundary
|
|
358
|
+
* across reads + ask — see workspace.tools.ts start_session comment.
|
|
359
|
+
*/
|
|
360
|
+
describe('start_session', () => {
|
|
361
|
+
// Minimal harness: own app + a fake ISessionSink that records createSession.
|
|
362
|
+
let server: HttpServer | undefined;
|
|
363
|
+
let created: Array<{ userId: string; startedAt: Date }> = [];
|
|
364
|
+
|
|
365
|
+
async function startSessionApp(source: 'external' | 'internal' = 'external'): Promise<string> {
|
|
366
|
+
created = [];
|
|
367
|
+
const registry = new ToolRegistry();
|
|
368
|
+
const resolve = async (auth: ToolAuth, signal: AbortSignal): Promise<ToolContext> => ({
|
|
369
|
+
user: { id: 'user-42', email: 'e@x', name: 'N' },
|
|
370
|
+
scope: auth.scope,
|
|
371
|
+
source: auth.source,
|
|
372
|
+
abortSignal: signal,
|
|
373
|
+
workspaceService: {} as never,
|
|
374
|
+
workflowService: {} as never,
|
|
375
|
+
events: {} as never,
|
|
376
|
+
getFilesystem: async () => ({}) as never,
|
|
377
|
+
});
|
|
378
|
+
const toolHandler = createToolHandlerFactory(resolve);
|
|
379
|
+
const auth = (req: express.Request, _res: express.Response, next: express.NextFunction) => {
|
|
380
|
+
req.toolAuth = { source, userId: 'user-42', scope: 'write' };
|
|
381
|
+
next();
|
|
382
|
+
};
|
|
383
|
+
// Fake ISessionSink: record the call, return a fixed session id.
|
|
384
|
+
const fakeSessionSink = {
|
|
385
|
+
createSession: async (userId: string, startedAt: Date) => {
|
|
386
|
+
created.push({ userId, startedAt });
|
|
387
|
+
return { sessionId: 'thread-xyz' };
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
const app = express();
|
|
392
|
+
app.use(express.json());
|
|
393
|
+
const router = express.Router();
|
|
394
|
+
registerWorkspaceTools(
|
|
395
|
+
registry, router, auth, toolHandler,
|
|
396
|
+
new SpillStore(join(tmpdir(), 'bevel-test-spills')), allowAll, KB_DIR,
|
|
397
|
+
{ service: {} as never, enabled: false, kbDirName: KB_DIR, recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
|
|
398
|
+
new RoutineWritePolicyService(),
|
|
399
|
+
fakeSessionSink,
|
|
400
|
+
);
|
|
401
|
+
app.use('/api', router);
|
|
402
|
+
server = await new Promise<HttpServer>((r) => {
|
|
403
|
+
const s = app.listen(0, () => r(s));
|
|
404
|
+
});
|
|
405
|
+
return `http://127.0.0.1:${(server.address() as { port: number }).port}`;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
afterEach(async () => {
|
|
409
|
+
if (server) await new Promise<void>((r) => server!.close(() => r()));
|
|
410
|
+
server = undefined;
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
it('returns the sink-minted id as sessionId', async () => {
|
|
414
|
+
const base = await startSessionApp();
|
|
415
|
+
const res = (await (await post(`${base}/api/agent/tools/start_session`)).json()) as { sessionId: string };
|
|
416
|
+
expect(res.sessionId).toBe('thread-xyz');
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
it('mints the session for the authenticated user', async () => {
|
|
420
|
+
const base = await startSessionApp();
|
|
421
|
+
await post(`${base}/api/agent/tools/start_session`);
|
|
422
|
+
expect(created).toHaveLength(1);
|
|
423
|
+
expect(created[0].userId).toBe('user-42');
|
|
424
|
+
expect(created[0].startedAt).toBeInstanceOf(Date);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it('rejects an internal-source caller (external-only) so an agent cannot mint a session mid-run', async () => {
|
|
428
|
+
// Note: an OAuth/JWT MCP session is NOT this case — its `externalProxy`
|
|
429
|
+
// loopback token resolves to source 'external' at the verifier (see
|
|
430
|
+
// tool-auth), so it is admitted here like any external agent.
|
|
431
|
+
const base = await startSessionApp('internal');
|
|
432
|
+
const res = await post(`${base}/api/agent/tools/start_session`);
|
|
433
|
+
expect(res.status).toBe(403);
|
|
434
|
+
expect(created).toHaveLength(0);
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Contract-level guarantee: `branch` is a REQUIRED input on every workspace tool
|
|
440
|
+
* def, on BOTH the internal and external manuals — one convention everywhere, so
|
|
441
|
+
* the caller always names the branch (there is no implied "current" workspace).
|
|
442
|
+
* This is what stops a call from ever resolving a `undefined` workspace at the
|
|
443
|
+
* schema layer, complementing the handler-level guard exercised above.
|
|
444
|
+
*/
|
|
445
|
+
describe('branch is a required parameter in the tool contract', () => {
|
|
446
|
+
/** Register the workspace tools into a fresh registry (no server needed). */
|
|
447
|
+
function buildRegistry(): ToolRegistry {
|
|
448
|
+
const registry = new ToolRegistry();
|
|
449
|
+
const router = express.Router();
|
|
450
|
+
const noopAuth: express.RequestHandler = (_req, _res, next) => next();
|
|
451
|
+
// The handler factory is only invoked to build routes; its output is never
|
|
452
|
+
// called in this test, so a no-op express handler suffices.
|
|
453
|
+
const toolHandler = (() => () => {}) as never;
|
|
454
|
+
registerWorkspaceTools(
|
|
455
|
+
registry,
|
|
456
|
+
router,
|
|
457
|
+
noopAuth,
|
|
458
|
+
toolHandler,
|
|
459
|
+
new SpillStore(join(tmpdir(), 'bevel-test-spills')),
|
|
460
|
+
allowAll,
|
|
461
|
+
KB_DIR,
|
|
462
|
+
{ service: {} as never, enabled: false, kbDirName: KB_DIR, recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
|
|
463
|
+
new RoutineWritePolicyService(),
|
|
464
|
+
{} as never,
|
|
465
|
+
);
|
|
466
|
+
return registry;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/** The flat input schema's `required` list (unwrapping `toolDef`'s `{ body }` envelope). */
|
|
470
|
+
function bodyRequired(tool: { inputs?: unknown } | undefined): string[] {
|
|
471
|
+
const inputs = tool?.inputs as { properties?: { body?: { required?: string[] } } } | undefined;
|
|
472
|
+
return inputs?.properties?.body?.required ?? [];
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
it('execute_command declares branch required on the INTERNAL manual', async () => {
|
|
476
|
+
const internal = await buildRegistry().listInternal();
|
|
477
|
+
const exec = internal.find((t) => t.name === 'execute_command');
|
|
478
|
+
expect(exec).toBeDefined();
|
|
479
|
+
expect(bodyRequired(exec)).toContain('branch');
|
|
480
|
+
expect(bodyRequired(exec)).toContain('command');
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
it('execute_command is internal-only — never advertised on the external manual', async () => {
|
|
484
|
+
const external = await buildRegistry().listExternal();
|
|
485
|
+
expect(external.find((t) => t.name === 'execute_command')).toBeUndefined();
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
it('every workspace file tool requires branch on BOTH manuals (one convention everywhere)', async () => {
|
|
489
|
+
const registry = buildRegistry();
|
|
490
|
+
const [internal, external] = await Promise.all([registry.listInternal(), registry.listExternal()]);
|
|
491
|
+
const fileTools = [
|
|
492
|
+
'read_file', 'write_file', 'write_files', 'edit_file', 'delete_file',
|
|
493
|
+
'mkdir', 'move_file', 'copy_file', 'list_files', 'file_stat', 'grep', 'unzip',
|
|
494
|
+
];
|
|
495
|
+
for (const name of fileTools) {
|
|
496
|
+
const int = internal.find((t) => t.name === name);
|
|
497
|
+
const ext = external.find((t) => t.name === name);
|
|
498
|
+
expect(int, `${name} should be on the internal manual`).toBeDefined();
|
|
499
|
+
expect(ext, `${name} should be on the external manual`).toBeDefined();
|
|
500
|
+
expect(bodyRequired(int), `${name} internal requires branch`).toContain('branch');
|
|
501
|
+
expect(bodyRequired(ext), `${name} external requires branch`).toContain('branch');
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import ignore, { type Ignore } from 'ignore';
|
|
4
|
+
|
|
5
|
+
const IGNORE_FILENAME = '.bevelignore';
|
|
6
|
+
|
|
7
|
+
/** One .bevelignore file's rules, scoped to the directory it lives in. */
|
|
8
|
+
interface IgnoreLayer {
|
|
9
|
+
/** Absolute path of the directory where the .bevelignore lives. */
|
|
10
|
+
readonly root: string;
|
|
11
|
+
readonly matcher: Ignore;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A hierarchical stack of `.bevelignore` rule sets.
|
|
16
|
+
*
|
|
17
|
+
* Each `.bevelignore` file applies to paths beneath the directory it lives in,
|
|
18
|
+
* using standard gitignore syntax (negations, `**`, directory-only patterns, anchoring).
|
|
19
|
+
* Deeper files combine with — and can override — rules from shallower files,
|
|
20
|
+
* mirroring how git layers `.gitignore` files.
|
|
21
|
+
*/
|
|
22
|
+
export class BevelIgnoreStack {
|
|
23
|
+
private constructor(private readonly layers: readonly IgnoreLayer[]) {}
|
|
24
|
+
|
|
25
|
+
static empty(): BevelIgnoreStack {
|
|
26
|
+
return new BevelIgnoreStack([]);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Return a new stack that additionally includes a `.bevelignore` from `dir`
|
|
31
|
+
* (if present). If no `.bevelignore` exists in `dir`, returns this stack unchanged.
|
|
32
|
+
*/
|
|
33
|
+
async extendedWith(dir: string): Promise<BevelIgnoreStack> {
|
|
34
|
+
const file = path.join(dir, IGNORE_FILENAME);
|
|
35
|
+
let contents: string;
|
|
36
|
+
try {
|
|
37
|
+
contents = await fs.readFile(file, 'utf-8');
|
|
38
|
+
} catch {
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
const matcher = ignore().add(contents);
|
|
42
|
+
return new BevelIgnoreStack([...this.layers, { root: dir, matcher }]);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Whether the given entry should be hidden from the file tree.
|
|
47
|
+
* @param absolutePath absolute path of the entry
|
|
48
|
+
* @param isDirectory needed because gitignore patterns ending in `/` match directories only
|
|
49
|
+
*/
|
|
50
|
+
isIgnored(absolutePath: string, isDirectory: boolean): boolean {
|
|
51
|
+
for (const layer of this.layers) {
|
|
52
|
+
const rel = path.relative(layer.root, absolutePath).replace(/\\/g, '/');
|
|
53
|
+
// Skip entries that aren't under this layer's root (shouldn't happen in normal
|
|
54
|
+
// recursion, but guards against absolute-path quirks on Windows).
|
|
55
|
+
if (!rel || rel.startsWith('..')) continue;
|
|
56
|
+
// Append trailing slash for directories so `foo/`-style rules match correctly.
|
|
57
|
+
const probe = isDirectory ? `${rel}/` : rel;
|
|
58
|
+
if (layer.matcher.ignores(probe)) return true;
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bootstraps the KB *remote* so the rest of the app's assumption — that the KB
|
|
3
|
+
* repo it clones already carries the protected branches and base scaffolding —
|
|
4
|
+
* holds even for a brand-new (or partially-populated) GitHub repo.
|
|
5
|
+
*
|
|
6
|
+
* The platform used to require the KB remote to have been forked from the
|
|
7
|
+
* standalone `knowledge-base-template` repo. That template now ships inside the
|
|
8
|
+
* platform (`kb-template/` at the repo root) and this service seeds from it.
|
|
9
|
+
*/
|
|
10
|
+
export interface IKbSeedService {
|
|
11
|
+
/**
|
|
12
|
+
* Ensure the KB remote can be cloned: seed a fully-empty repo, and make sure
|
|
13
|
+
* every protected branch exists as a ref (so `clone -b <branch>` succeeds).
|
|
14
|
+
* Idempotent and single-flight — safe to await before every clone; the real
|
|
15
|
+
* work runs at most once per process.
|
|
16
|
+
*
|
|
17
|
+
* - **Empty remote** → full seed: all template files (incl. the sample
|
|
18
|
+
* ontology) committed to every protected branch. Requires `SEED_ADMIN_EMAILS`
|
|
19
|
+
* (a repo with no Admin is unusable), otherwise throws.
|
|
20
|
+
* - **Existing remote** → create only the protected branches that don't exist
|
|
21
|
+
* yet, off an existing one. No file changes here — per-branch base files are
|
|
22
|
+
* filled in by {@link topUpWorkspace} when a branch is loaded.
|
|
23
|
+
*/
|
|
24
|
+
ensureRemoteSeeded(): Promise<void>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Fill in any missing base scaffolding on the freshly-cloned workspace of the
|
|
28
|
+
* branch a user just loaded, then commit + push it to that branch. Add-only —
|
|
29
|
+
* never overwrites existing files, and never restores the sample ontology.
|
|
30
|
+
* Best-effort: never throws, so a top-up hiccup can't block loading the branch.
|
|
31
|
+
*
|
|
32
|
+
* @param repoDir Absolute path to the checked-out KB clone for `branch`.
|
|
33
|
+
* @param branch The branch that clone is on (the push target).
|
|
34
|
+
*/
|
|
35
|
+
topUpWorkspace(repoDir: string, branch: string): Promise<void>;
|
|
36
|
+
}
|