@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,116 @@
|
|
|
1
|
+
import { InvalidTokenError } from '@modelcontextprotocol/sdk/server/auth/errors.js';
|
|
2
|
+
import '../tool-auth/external-api-key.interface.js'; // Express Request augmentation (req.externalApiKeyId)
|
|
3
|
+
/**
|
|
4
|
+
* Auth middleware for the MCP endpoint. Accepts any of:
|
|
5
|
+
*
|
|
6
|
+
* 1. A connection key (Bearer `bevel_…`) — minted from the settings UI,
|
|
7
|
+
* resolved via ExternalApiKeyService.
|
|
8
|
+
* 2. An MCP OAuth access token (Bearer `bevel-mcp_…`) — issued by our own
|
|
9
|
+
* authorization server after the /connect consent flow, resolved via
|
|
10
|
+
* BevelOAuthProvider.
|
|
11
|
+
* 3. A regular JWT — same shape the web app uses. Lets a logged-in user
|
|
12
|
+
* hit the MCP endpoint from their browser if we ever need it
|
|
13
|
+
* (e.g. an in-app debugger). Keeps the surface from forking.
|
|
14
|
+
*
|
|
15
|
+
* The middleware **must** run before the MCP transport handler — the
|
|
16
|
+
* transport pulls `req.userId` to populate the session row at `initialize`.
|
|
17
|
+
*
|
|
18
|
+
* Failures return 401 with a `WWW-Authenticate` challenge carrying
|
|
19
|
+
* `resource_metadata` (RFC 9728) so an OAuth-capable MCP client discovers our
|
|
20
|
+
* authorization server and starts the flow, while clients configured with a
|
|
21
|
+
* key simply prompt for it.
|
|
22
|
+
*/
|
|
23
|
+
export function createMcpAuthMiddleware(authService, externalApiKeyService, oauthProvider, resourceMetadataUrl) {
|
|
24
|
+
const wwwAuthenticate = `Bearer realm="bevel-mcp", resource_metadata="${resourceMetadataUrl}"`;
|
|
25
|
+
const unauthorized = (res, error) => {
|
|
26
|
+
res.setHeader('WWW-Authenticate', wwwAuthenticate);
|
|
27
|
+
res.status(401).json({ error });
|
|
28
|
+
};
|
|
29
|
+
return async (req, res, next) => {
|
|
30
|
+
const header = req.headers.authorization;
|
|
31
|
+
// RFC 7235 §2.1: auth scheme matching is case-insensitive ("bearer",
|
|
32
|
+
// "BEARER", "BeArEr" are all valid). Match on the lowercased prefix and
|
|
33
|
+
// then take the token as whatever follows the first whitespace, so the
|
|
34
|
+
// extraction stays correct regardless of the caller's casing.
|
|
35
|
+
if (!header || !header.toLowerCase().startsWith('bearer ')) {
|
|
36
|
+
unauthorized(res, 'Missing or invalid Authorization header');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const firstSpace = header.indexOf(' ');
|
|
40
|
+
const token = header.slice(firstSpace + 1).trim();
|
|
41
|
+
// Route on the tenant key prefixes so we never accidentally pass a JWT
|
|
42
|
+
// through hash lookup or an external API key through jsonwebtoken — both
|
|
43
|
+
// would 500 instead of cleanly 401-ing. Order matters only for clarity:
|
|
44
|
+
// the connection-key (`bevel_`), OAuth (`bevel-mcp_`), and JWT (`eyJ…`)
|
|
45
|
+
// shapes are mutually non-overlapping.
|
|
46
|
+
if (externalApiKeyService.looksLikeExternalApiKey(token)) {
|
|
47
|
+
try {
|
|
48
|
+
// Resolve the token *id* alongside the user so the tool handler can
|
|
49
|
+
// meter the internal model against this key's daily cap — the same
|
|
50
|
+
// per-key guardrail the LLM proxy enforces. OAuth and JWT callers
|
|
51
|
+
// have no connection key, so those paths below leave
|
|
52
|
+
// `externalApiKeyId` unset and are not metered.
|
|
53
|
+
const resolved = await externalApiKeyService.verifyAndLoadToken(token);
|
|
54
|
+
if (!resolved) {
|
|
55
|
+
unauthorized(res, 'Invalid or revoked connection key');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
req.userId = resolved.user.id;
|
|
59
|
+
req.userEmail = resolved.user.email;
|
|
60
|
+
req.externalApiKeyId = resolved.tokenId;
|
|
61
|
+
next();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
// A DB error during verification is a 500, not a 401 — the caller's
|
|
66
|
+
// credentials may be valid; we just can't check them right now.
|
|
67
|
+
console.error('[mcp-auth] connection-key verification failed:', err);
|
|
68
|
+
res.status(500).json({ error: 'Authentication backend unavailable' });
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// MCP OAuth access token — issued by our own authorization server. An
|
|
73
|
+
// invalid/expired/revoked token is a clean 401 (re-challenging with
|
|
74
|
+
// resource_metadata so the client can re-authorize); a DB failure is a
|
|
75
|
+
// 500, same split as the connection-key branch above.
|
|
76
|
+
if (oauthProvider.looksLikeAccessToken(token)) {
|
|
77
|
+
try {
|
|
78
|
+
const info = await oauthProvider.verifyAccessToken(token);
|
|
79
|
+
req.userId = String(info.extra?.userId ?? '');
|
|
80
|
+
req.userEmail = String(info.extra?.userEmail ?? '');
|
|
81
|
+
if (!req.userId) {
|
|
82
|
+
unauthorized(res, 'Invalid access token');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
if (err instanceof InvalidTokenError) {
|
|
88
|
+
unauthorized(res, 'Invalid, expired, or revoked access token');
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
console.error('[mcp-auth] OAuth token verification failed:', err);
|
|
92
|
+
res.status(500).json({ error: 'Authentication backend unavailable' });
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// Outside the try so a synchronous throw from a downstream handler isn't
|
|
97
|
+
// misclassified as a token-verification failure (and doesn't try to write
|
|
98
|
+
// a second response).
|
|
99
|
+
next();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// JWT path — same logic as `createAuthMiddleware` in modules/auth, kept
|
|
103
|
+
// duplicated rather than imported because that one writes its own 401
|
|
104
|
+
// body shape and we want the WWW-Authenticate header set.
|
|
105
|
+
try {
|
|
106
|
+
const { userId, email } = authService.verifyToken(token);
|
|
107
|
+
req.userId = userId;
|
|
108
|
+
req.userEmail = email;
|
|
109
|
+
next();
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
unauthorized(res, 'Invalid or expired token');
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=mcp-auth.middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-auth.middleware.js","sourceRoot":"","sources":["../../../src/modules/mcp/mcp-auth.middleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory mapping from MCP session id → { userId, tokenId }. Each entry
|
|
3
|
+
* represents one MCP client connection's worth of state: the Bevel user the
|
|
4
|
+
* Bearer token resolved to at `initialize`, and the connection-key id for
|
|
5
|
+
* metering. Conversation continuity is the caller's own (a continuity-aware
|
|
6
|
+
* tool like `ask` returns its `sessionId` in the result and the caller echoes
|
|
7
|
+
* it back); thread/workspace bookkeeping lives on the REST tool surface.
|
|
8
|
+
*
|
|
9
|
+
* Eviction is lazy: each `get` / `touch` sweeps idle entries before the
|
|
10
|
+
* lookup, and `put` enforces the size cap before insert. No background
|
|
11
|
+
* timer — keeps the store cheap to construct and avoids leaking a setInterval
|
|
12
|
+
* handle in tests.
|
|
13
|
+
*
|
|
14
|
+
* Single-replica only. If we add a second backend instance later, sessions
|
|
15
|
+
* need to be persisted (see docs/mcp-remote-access.md → "Out of scope"). The
|
|
16
|
+
* MCP protocol tolerates this — a 404 on an unknown session id is a defined
|
|
17
|
+
* response, and clients re-initialize.
|
|
18
|
+
*/
|
|
19
|
+
export interface McpSession {
|
|
20
|
+
sessionId: string;
|
|
21
|
+
userId: string;
|
|
22
|
+
/**
|
|
23
|
+
* The connection-key id this session authenticated with, or null when the
|
|
24
|
+
* session was opened with a browser JWT (no connection key). Captured at
|
|
25
|
+
* `initialize` so every `ask_bevel_agent` call in the session can be metered
|
|
26
|
+
* against that key's daily token cap.
|
|
27
|
+
*/
|
|
28
|
+
tokenId: string | null;
|
|
29
|
+
createdAt: number;
|
|
30
|
+
lastTouchedAt: number;
|
|
31
|
+
}
|
|
32
|
+
export interface McpSessionStoreOptions {
|
|
33
|
+
/** Drop sessions idle for longer than this. Default: 4 hours. */
|
|
34
|
+
idleTtlMs?: number;
|
|
35
|
+
/** Hard cap on simultaneous live sessions. Oldest-touched evicted first. */
|
|
36
|
+
maxSessions?: number;
|
|
37
|
+
/** Override `Date.now` — injected only by tests. */
|
|
38
|
+
now?: () => number;
|
|
39
|
+
}
|
|
40
|
+
export declare class McpSessionStore {
|
|
41
|
+
private readonly sessions;
|
|
42
|
+
private readonly idleTtlMs;
|
|
43
|
+
private readonly maxSessions;
|
|
44
|
+
private readonly now;
|
|
45
|
+
private readonly evictListeners;
|
|
46
|
+
constructor(opts?: McpSessionStoreOptions);
|
|
47
|
+
/**
|
|
48
|
+
* Subscribe to eviction events. Returns an unsubscribe function so callers
|
|
49
|
+
* can clean up in test teardown. The route layer uses this to drop the
|
|
50
|
+
* transport-state entry in its `active` map and close the underlying SDK
|
|
51
|
+
* transport when the store decides a session has aged out.
|
|
52
|
+
*/
|
|
53
|
+
onEvict(listener: (sessionId: string) => void): () => void;
|
|
54
|
+
/**
|
|
55
|
+
* Register a fresh MCP session. Caller supplies the id (generated by the
|
|
56
|
+
* SDK's transport). Evicts the oldest-touched session if the cap is hit
|
|
57
|
+
* — better than refusing the connection, since a wedged old session is
|
|
58
|
+
* the most likely cause of a full table.
|
|
59
|
+
*/
|
|
60
|
+
create(sessionId: string, userId: string, tokenId?: string | null): McpSession;
|
|
61
|
+
/**
|
|
62
|
+
* Look up a session and bump its `lastTouchedAt`. Returns null when the
|
|
63
|
+
* session is unknown or has aged out. Sweep runs first so an aged entry
|
|
64
|
+
* is collected, not silently revived.
|
|
65
|
+
*/
|
|
66
|
+
get(sessionId: string): McpSession | null;
|
|
67
|
+
delete(sessionId: string): void;
|
|
68
|
+
/** Visible size; useful for diagnostics. Does not sweep. */
|
|
69
|
+
size(): number;
|
|
70
|
+
private sweep;
|
|
71
|
+
private evictOldest;
|
|
72
|
+
private emitEviction;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=mcp-session-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-session-store.d.ts","sourceRoot":"","sources":["../../../src/modules/mcp/mcp-session-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAKD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAC1D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IASnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0C;gBAE7D,IAAI,GAAE,sBAA2B;IAM7C;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IAO1D;;;;;OAKG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,GAAG,IAAW,GAAG,UAAU;IAiBpF;;;;OAIG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAQzC,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAI/B,4DAA4D;IAC5D,IAAI,IAAI,MAAM;IAId,OAAO,CAAC,KAAK;IAUb,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,YAAY;CAYrB"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory mapping from MCP session id → { userId, tokenId }. Each entry
|
|
3
|
+
* represents one MCP client connection's worth of state: the Bevel user the
|
|
4
|
+
* Bearer token resolved to at `initialize`, and the connection-key id for
|
|
5
|
+
* metering. Conversation continuity is the caller's own (a continuity-aware
|
|
6
|
+
* tool like `ask` returns its `sessionId` in the result and the caller echoes
|
|
7
|
+
* it back); thread/workspace bookkeeping lives on the REST tool surface.
|
|
8
|
+
*
|
|
9
|
+
* Eviction is lazy: each `get` / `touch` sweeps idle entries before the
|
|
10
|
+
* lookup, and `put` enforces the size cap before insert. No background
|
|
11
|
+
* timer — keeps the store cheap to construct and avoids leaking a setInterval
|
|
12
|
+
* handle in tests.
|
|
13
|
+
*
|
|
14
|
+
* Single-replica only. If we add a second backend instance later, sessions
|
|
15
|
+
* need to be persisted (see docs/mcp-remote-access.md → "Out of scope"). The
|
|
16
|
+
* MCP protocol tolerates this — a 404 on an unknown session id is a defined
|
|
17
|
+
* response, and clients re-initialize.
|
|
18
|
+
*/
|
|
19
|
+
const DEFAULT_IDLE_TTL_MS = 4 * 60 * 60 * 1000;
|
|
20
|
+
const DEFAULT_MAX_SESSIONS = 5000;
|
|
21
|
+
export class McpSessionStore {
|
|
22
|
+
sessions = new Map();
|
|
23
|
+
idleTtlMs;
|
|
24
|
+
maxSessions;
|
|
25
|
+
now;
|
|
26
|
+
// Subscribers notified whenever a session is dropped by the store itself
|
|
27
|
+
// (idle TTL sweep or size-cap eviction). NOT fired by explicit `delete()` —
|
|
28
|
+
// the caller of `delete` already knows the session is gone, and the route
|
|
29
|
+
// layer uses `delete` *because* it's already cleaning up.
|
|
30
|
+
//
|
|
31
|
+
// Callbacks are invoked synchronously; long-running cleanup (e.g.
|
|
32
|
+
// `transport.close()`) should be fire-and-forget so a slow listener can't
|
|
33
|
+
// block the next eviction.
|
|
34
|
+
evictListeners = new Set();
|
|
35
|
+
constructor(opts = {}) {
|
|
36
|
+
this.idleTtlMs = opts.idleTtlMs ?? DEFAULT_IDLE_TTL_MS;
|
|
37
|
+
this.maxSessions = opts.maxSessions ?? DEFAULT_MAX_SESSIONS;
|
|
38
|
+
this.now = opts.now ?? Date.now;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Subscribe to eviction events. Returns an unsubscribe function so callers
|
|
42
|
+
* can clean up in test teardown. The route layer uses this to drop the
|
|
43
|
+
* transport-state entry in its `active` map and close the underlying SDK
|
|
44
|
+
* transport when the store decides a session has aged out.
|
|
45
|
+
*/
|
|
46
|
+
onEvict(listener) {
|
|
47
|
+
this.evictListeners.add(listener);
|
|
48
|
+
return () => {
|
|
49
|
+
this.evictListeners.delete(listener);
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Register a fresh MCP session. Caller supplies the id (generated by the
|
|
54
|
+
* SDK's transport). Evicts the oldest-touched session if the cap is hit
|
|
55
|
+
* — better than refusing the connection, since a wedged old session is
|
|
56
|
+
* the most likely cause of a full table.
|
|
57
|
+
*/
|
|
58
|
+
create(sessionId, userId, tokenId = null) {
|
|
59
|
+
this.sweep();
|
|
60
|
+
if (this.sessions.size >= this.maxSessions) {
|
|
61
|
+
this.evictOldest();
|
|
62
|
+
}
|
|
63
|
+
const now = this.now();
|
|
64
|
+
const session = {
|
|
65
|
+
sessionId,
|
|
66
|
+
userId,
|
|
67
|
+
tokenId,
|
|
68
|
+
createdAt: now,
|
|
69
|
+
lastTouchedAt: now,
|
|
70
|
+
};
|
|
71
|
+
this.sessions.set(sessionId, session);
|
|
72
|
+
return session;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Look up a session and bump its `lastTouchedAt`. Returns null when the
|
|
76
|
+
* session is unknown or has aged out. Sweep runs first so an aged entry
|
|
77
|
+
* is collected, not silently revived.
|
|
78
|
+
*/
|
|
79
|
+
get(sessionId) {
|
|
80
|
+
this.sweep();
|
|
81
|
+
const session = this.sessions.get(sessionId);
|
|
82
|
+
if (!session)
|
|
83
|
+
return null;
|
|
84
|
+
session.lastTouchedAt = this.now();
|
|
85
|
+
return session;
|
|
86
|
+
}
|
|
87
|
+
delete(sessionId) {
|
|
88
|
+
this.sessions.delete(sessionId);
|
|
89
|
+
}
|
|
90
|
+
/** Visible size; useful for diagnostics. Does not sweep. */
|
|
91
|
+
size() {
|
|
92
|
+
return this.sessions.size;
|
|
93
|
+
}
|
|
94
|
+
sweep() {
|
|
95
|
+
const cutoff = this.now() - this.idleTtlMs;
|
|
96
|
+
for (const [id, s] of this.sessions) {
|
|
97
|
+
if (s.lastTouchedAt < cutoff) {
|
|
98
|
+
this.sessions.delete(id);
|
|
99
|
+
this.emitEviction(id);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
evictOldest() {
|
|
104
|
+
let oldestId = null;
|
|
105
|
+
let oldestTouched = Infinity;
|
|
106
|
+
for (const [id, s] of this.sessions) {
|
|
107
|
+
if (s.lastTouchedAt < oldestTouched) {
|
|
108
|
+
oldestTouched = s.lastTouchedAt;
|
|
109
|
+
oldestId = id;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (oldestId) {
|
|
113
|
+
this.sessions.delete(oldestId);
|
|
114
|
+
this.emitEviction(oldestId);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
emitEviction(sessionId) {
|
|
118
|
+
for (const listener of this.evictListeners) {
|
|
119
|
+
try {
|
|
120
|
+
listener(sessionId);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
// A misbehaving listener must not stop the sweep from finishing —
|
|
124
|
+
// otherwise one bad subscriber would block the rest of the eviction
|
|
125
|
+
// pass and leak more sessions.
|
|
126
|
+
console.warn('[mcp-session-store] eviction listener threw:', err);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=mcp-session-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-session-store.js","sourceRoot":"","sources":["../../../src/modules/mcp/mcp-session-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import express, { type RequestHandler } from 'express';
|
|
2
|
+
import type { IExternalApiKeyService } from '../tool-auth/external-api-key.interface.js';
|
|
3
|
+
import type { McpService } from './mcp.service.js';
|
|
4
|
+
import type { ILlmUsageMeter } from '../tool-auth/llm-usage-meter.js';
|
|
5
|
+
import '../tool-auth/external-api-key.interface.js';
|
|
6
|
+
/**
|
|
7
|
+
* Routes for the remote MCP server + the connection-key management endpoints.
|
|
8
|
+
*
|
|
9
|
+
* Layout:
|
|
10
|
+
* POST /mcp — client→server MCP messages (initialize + tool calls)
|
|
11
|
+
* GET /mcp — server→client SSE channel (session-bound)
|
|
12
|
+
* DELETE /mcp — terminate a session
|
|
13
|
+
*
|
|
14
|
+
* GET /mcp/external-api-keys — list this user's connection keys
|
|
15
|
+
* POST /mcp/external-api-keys — mint a new key (returns plaintext ONCE)
|
|
16
|
+
* DELETE /mcp/external-api-keys/:id — revoke
|
|
17
|
+
*
|
|
18
|
+
* The `/mcp` endpoints accept either a connection key or a JWT (see
|
|
19
|
+
* McpAuthMiddleware). The `/mcp/external-api-keys/*` endpoints accept only the JWT —
|
|
20
|
+
* minting/revoking via a connection key would let a leaked key roll itself
|
|
21
|
+
* over and stay alive forever.
|
|
22
|
+
*/
|
|
23
|
+
export declare function createMcpRoutes(mcpService: McpService, externalApiKeyService: IExternalApiKeyService, mcpAuthMiddleware: RequestHandler, jwtAuthMiddleware: RequestHandler, llmUsageService: ILlmUsageMeter): express.Router;
|
|
24
|
+
//# sourceMappingURL=mcp.routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.routes.d.ts","sourceRoot":"","sources":["../../../src/modules/mcp/mcp.routes.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,EAAE,EAAgB,KAAK,cAAc,EAAE,MAAM,SAAS,CAAC;AASrE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AACzF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,4CAA4C,CAAC;AAepD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,UAAU,EACtB,qBAAqB,EAAE,sBAAsB,EAC7C,iBAAiB,EAAE,cAAc,EACjC,iBAAiB,EAAE,cAAc,EACjC,eAAe,EAAE,cAAc,GAC9B,OAAO,CAAC,MAAM,CAoNhB"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import { InvalidTokenLabelError, TokenNotFoundError, TokenStillActiveError, } from '../tool-auth/external-api-key.errors.js';
|
|
4
|
+
import '../tool-auth/external-api-key.interface.js'; // req.externalApiKeyId augmentation
|
|
5
|
+
/** Pull the raw bearer token off an already-authenticated request. */
|
|
6
|
+
function extractBearer(req) {
|
|
7
|
+
const header = req.headers.authorization ?? '';
|
|
8
|
+
const firstSpace = header.indexOf(' ');
|
|
9
|
+
return firstSpace >= 0 ? header.slice(firstSpace + 1).trim() : '';
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Routes for the remote MCP server + the connection-key management endpoints.
|
|
13
|
+
*
|
|
14
|
+
* Layout:
|
|
15
|
+
* POST /mcp — client→server MCP messages (initialize + tool calls)
|
|
16
|
+
* GET /mcp — server→client SSE channel (session-bound)
|
|
17
|
+
* DELETE /mcp — terminate a session
|
|
18
|
+
*
|
|
19
|
+
* GET /mcp/external-api-keys — list this user's connection keys
|
|
20
|
+
* POST /mcp/external-api-keys — mint a new key (returns plaintext ONCE)
|
|
21
|
+
* DELETE /mcp/external-api-keys/:id — revoke
|
|
22
|
+
*
|
|
23
|
+
* The `/mcp` endpoints accept either a connection key or a JWT (see
|
|
24
|
+
* McpAuthMiddleware). The `/mcp/external-api-keys/*` endpoints accept only the JWT —
|
|
25
|
+
* minting/revoking via a connection key would let a leaked key roll itself
|
|
26
|
+
* over and stay alive forever.
|
|
27
|
+
*/
|
|
28
|
+
export function createMcpRoutes(mcpService, externalApiKeyService, mcpAuthMiddleware, jwtAuthMiddleware, llmUsageService) {
|
|
29
|
+
const router = express.Router();
|
|
30
|
+
// Per-process map of live MCP sessions. In-memory mirror of McpSessionStore
|
|
31
|
+
// — McpSessionStore holds the *domain* state (userId, threadId, idle TTL),
|
|
32
|
+
// this map holds the *transport* state (the SDK objects we need to route
|
|
33
|
+
// a subsequent HTTP request to the correct session). Both are cleared on
|
|
34
|
+
// restart; clients re-initialize.
|
|
35
|
+
const active = new Map();
|
|
36
|
+
// When McpSessionStore drops a session on its own (idle-TTL sweep or
|
|
37
|
+
// size-cap eviction), the matching transport pair would otherwise leak
|
|
38
|
+
// here — `active.has(id)` would still return true and route requests to a
|
|
39
|
+
// McpServer whose backing domain state is gone. Subscribe to the store and
|
|
40
|
+
// tear down the transport so the resources free immediately and the next
|
|
41
|
+
// request with that id correctly 404s.
|
|
42
|
+
mcpService.onSessionEvicted((sessionId) => {
|
|
43
|
+
const entry = active.get(sessionId);
|
|
44
|
+
if (!entry)
|
|
45
|
+
return;
|
|
46
|
+
active.delete(sessionId);
|
|
47
|
+
// close() is async; fire-and-forget so a slow socket teardown can't
|
|
48
|
+
// block the store's eviction loop. transport.onclose still fires but
|
|
49
|
+
// its `active.delete` is now a no-op.
|
|
50
|
+
void entry.transport.close().catch((err) => {
|
|
51
|
+
console.warn('[mcp] transport close on eviction failed:', err);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
// ── MCP transport ──────────────────────────────────────────────────────
|
|
55
|
+
router.post('/mcp', mcpAuthMiddleware, async (req, res) => {
|
|
56
|
+
try {
|
|
57
|
+
const sessionIdHeader = req.headers['mcp-session-id'];
|
|
58
|
+
const body = req.body;
|
|
59
|
+
// Three valid request shapes on POST /mcp:
|
|
60
|
+
// 1. No session id + body is initialize → spin up a new transport.
|
|
61
|
+
// 2. Session id + matching active session → forward.
|
|
62
|
+
// 3. Anything else → 400 / 404.
|
|
63
|
+
if (sessionIdHeader && active.has(sessionIdHeader)) {
|
|
64
|
+
const session = active.get(sessionIdHeader);
|
|
65
|
+
// Defense in depth: the auth middleware bound a userId for this
|
|
66
|
+
// request; refuse if it doesn't match the session's owner. Stops
|
|
67
|
+
// a leaked session id from being used cross-user even if the
|
|
68
|
+
// attacker has their own valid connection key.
|
|
69
|
+
if (session.userId !== req.userId) {
|
|
70
|
+
res.status(403).json({ error: 'Session does not belong to this user' });
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
await session.transport.handleRequest(req, res, body);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (!sessionIdHeader && isInitializeRequest(body)) {
|
|
77
|
+
// The proxy authenticates its loopback calls with the SAME bearer the
|
|
78
|
+
// client used here, so it acts on the request exactly as the caller
|
|
79
|
+
// would. Captured at initialize and seeded into the session's UtcpClient.
|
|
80
|
+
const { transport, server } = await mcpService.createSession(req.userId,
|
|
81
|
+
// Connection-key id (set by mcpAuthMiddleware for `bevel_…` bearers;
|
|
82
|
+
// undefined for browser JWT) — kept for audit/diagnostics.
|
|
83
|
+
req.externalApiKeyId ?? null, extractBearer(req), (sessionId) => {
|
|
84
|
+
active.set(sessionId, { transport, server, userId: req.userId });
|
|
85
|
+
});
|
|
86
|
+
// Closing the transport (DELETE /mcp, or client disconnect during
|
|
87
|
+
// close) should drop both the active map and the McpSessionStore
|
|
88
|
+
// entry. McpService wired onsessionclosed → sessionStore.delete; we
|
|
89
|
+
// mirror it here.
|
|
90
|
+
transport.onclose = () => {
|
|
91
|
+
if (transport.sessionId)
|
|
92
|
+
active.delete(transport.sessionId);
|
|
93
|
+
};
|
|
94
|
+
await server.connect(transport);
|
|
95
|
+
await transport.handleRequest(req, res, body);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
res.status(400).json({
|
|
99
|
+
error: 'Bad request: missing session id, or session id does not match any active session.',
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
const msg = err instanceof Error ? err.message : 'Unknown error';
|
|
104
|
+
console.error('[mcp] POST /mcp failed:', msg);
|
|
105
|
+
if (!res.headersSent) {
|
|
106
|
+
res.status(500).json({ error: msg });
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
res.end();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
const sessionRequest = async (req, res) => {
|
|
114
|
+
const sessionIdHeader = req.headers['mcp-session-id'];
|
|
115
|
+
if (!sessionIdHeader || !active.has(sessionIdHeader)) {
|
|
116
|
+
res.status(404).json({ error: 'Unknown MCP session' });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const session = active.get(sessionIdHeader);
|
|
120
|
+
if (session.userId !== req.userId) {
|
|
121
|
+
res.status(403).json({ error: 'Session does not belong to this user' });
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
await session.transport.handleRequest(req, res);
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
const msg = err instanceof Error ? err.message : 'Unknown error';
|
|
129
|
+
console.error('[mcp] session request failed:', msg);
|
|
130
|
+
if (!res.headersSent)
|
|
131
|
+
res.status(500).json({ error: msg });
|
|
132
|
+
else
|
|
133
|
+
res.end();
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
// GET is the server→client SSE channel for session-scoped notifications.
|
|
137
|
+
router.get('/mcp', mcpAuthMiddleware, sessionRequest);
|
|
138
|
+
// DELETE terminates the session — SDK closes the transport, our
|
|
139
|
+
// onclose handler cleans up the active map, and McpService's
|
|
140
|
+
// onsessionclosed clears the McpSessionStore entry.
|
|
141
|
+
router.delete('/mcp', mcpAuthMiddleware, sessionRequest);
|
|
142
|
+
// ── Connection-key management (JWT-only) ───────────────────────────────
|
|
143
|
+
router.get('/mcp/external-api-keys', jwtAuthMiddleware, async (req, res) => {
|
|
144
|
+
try {
|
|
145
|
+
const tokens = await externalApiKeyService.listForUser(req.userId);
|
|
146
|
+
// Enrich each key with its LLM-proxy usage today + the daily cap, so the
|
|
147
|
+
// settings UI can show how much of the model budget the key has spent.
|
|
148
|
+
const usage = await llmUsageService.usageForTokens(tokens.map((t) => t.id));
|
|
149
|
+
res.json(tokens.map((t) => ({
|
|
150
|
+
...t,
|
|
151
|
+
llmUsage: {
|
|
152
|
+
usedTodayTokens: usage[t.id] ?? 0,
|
|
153
|
+
dailyTokenCap: llmUsageService.dailyCap,
|
|
154
|
+
},
|
|
155
|
+
})));
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
const msg = err instanceof Error ? err.message : 'Unknown error';
|
|
159
|
+
res.status(500).json({ error: msg });
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
router.post('/mcp/external-api-keys', jwtAuthMiddleware, async (req, res) => {
|
|
163
|
+
try {
|
|
164
|
+
// `express.json()` leaves req.body undefined when the client posts
|
|
165
|
+
// without `Content-Type: application/json` (or with another type
|
|
166
|
+
// entirely). Destructuring undefined throws a TypeError that the outer
|
|
167
|
+
// catch would 500 — guard with a clean 400 instead.
|
|
168
|
+
if (!req.body || typeof req.body !== 'object') {
|
|
169
|
+
res.status(400).json({ error: 'JSON body required' });
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const { label } = req.body;
|
|
173
|
+
if (!label) {
|
|
174
|
+
res.status(400).json({ error: 'label is required' });
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const minted = await externalApiKeyService.mint(req.userId, label);
|
|
178
|
+
// The plaintext field is the *only* read path for the raw key. The
|
|
179
|
+
// frontend must store it nowhere — it shows the dialog once and then
|
|
180
|
+
// discards. Subsequent fetches return only `summary`-shaped rows.
|
|
181
|
+
res.json(minted);
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
if (err instanceof InvalidTokenLabelError) {
|
|
185
|
+
res.status(400).json({ error: err.message });
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const msg = err instanceof Error ? err.message : 'Unknown error';
|
|
189
|
+
res.status(500).json({ error: msg });
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
router.delete('/mcp/external-api-keys/:id', jwtAuthMiddleware, async (req, res) => {
|
|
193
|
+
try {
|
|
194
|
+
await externalApiKeyService.revoke(String(req.params.id), req.userId);
|
|
195
|
+
res.json({ status: 'revoked' });
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
if (err instanceof TokenNotFoundError) {
|
|
199
|
+
res.status(404).json({ error: err.message });
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const msg = err instanceof Error ? err.message : 'Unknown error';
|
|
203
|
+
res.status(500).json({ error: msg });
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
// Hard-delete: permanently remove a *disconnected* key and its audit row.
|
|
207
|
+
// Separate path from revoke so the two lifecycle steps can't be conflated;
|
|
208
|
+
// the service refuses to delete a still-active key (409).
|
|
209
|
+
router.delete('/mcp/external-api-keys/:id/permanent', jwtAuthMiddleware, async (req, res) => {
|
|
210
|
+
try {
|
|
211
|
+
await externalApiKeyService.remove(String(req.params.id), req.userId);
|
|
212
|
+
res.json({ status: 'deleted' });
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
if (err instanceof TokenNotFoundError) {
|
|
216
|
+
res.status(404).json({ error: err.message });
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (err instanceof TokenStillActiveError) {
|
|
220
|
+
res.status(409).json({ error: err.message });
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const msg = err instanceof Error ? err.message : 'Unknown error';
|
|
224
|
+
res.status(500).json({ error: msg });
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
return router;
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=mcp.routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.routes.js","sourceRoot":"","sources":["../../../src/modules/mcp/mcp.routes.ts"],"names":[],"mappings":"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"}
|