@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,164 @@
|
|
|
1
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
import { and, desc, eq, isNotNull, isNull } from 'drizzle-orm';
|
|
3
|
+
import { externalApiKeys, users } from '../database/schema.js';
|
|
4
|
+
import { InvalidTokenLabelError, TokenNotFoundError, TokenStillActiveError, } from './external-api-key.errors.js';
|
|
5
|
+
// Plaintext format: `<tenant>_<43 base64url chars>`. 32 random bytes encoded
|
|
6
|
+
// base64url is 43 chars and gives 256 bits of entropy — overkill against
|
|
7
|
+
// brute force, cheap to copy. The tenant prefix (default `bevel_`) lets the
|
|
8
|
+
// auth middleware route key-vs-JWT requests without parsing both shapes.
|
|
9
|
+
const TOKEN_BYTES = 32;
|
|
10
|
+
const MAX_LABEL_LEN = 200;
|
|
11
|
+
export class ExternalApiKeyService {
|
|
12
|
+
db;
|
|
13
|
+
keyPrefix;
|
|
14
|
+
/**
|
|
15
|
+
* @param keyPrefix Tenant-derived plaintext prefix (e.g. `bevel_`) — injected
|
|
16
|
+
* from {@link AppConfig.externalApiKeyPrefix} so a deploy can brand its keys.
|
|
17
|
+
*/
|
|
18
|
+
constructor(db, keyPrefix) {
|
|
19
|
+
this.db = db;
|
|
20
|
+
this.keyPrefix = keyPrefix;
|
|
21
|
+
}
|
|
22
|
+
/** True if a bearer string carries this tenant's external-API-key prefix. */
|
|
23
|
+
looksLikeExternalApiKey(token) {
|
|
24
|
+
return typeof token === 'string' && token.startsWith(this.keyPrefix);
|
|
25
|
+
}
|
|
26
|
+
async mint(userId, label) {
|
|
27
|
+
const trimmed = (label ?? '').trim();
|
|
28
|
+
if (trimmed.length === 0) {
|
|
29
|
+
throw new InvalidTokenLabelError('Label cannot be empty');
|
|
30
|
+
}
|
|
31
|
+
if (trimmed.length > MAX_LABEL_LEN) {
|
|
32
|
+
throw new InvalidTokenLabelError(`Label cannot exceed ${MAX_LABEL_LEN} characters`);
|
|
33
|
+
}
|
|
34
|
+
const plaintext = this.keyPrefix + randomBytes(TOKEN_BYTES).toString('base64url');
|
|
35
|
+
const tokenHash = hashToken(plaintext);
|
|
36
|
+
const [row] = await this.db
|
|
37
|
+
.insert(externalApiKeys)
|
|
38
|
+
.values({ userId, tokenHash, label: trimmed })
|
|
39
|
+
.returning();
|
|
40
|
+
return {
|
|
41
|
+
plaintext,
|
|
42
|
+
summary: toSummary(row),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async verifyAndLoadUser(plaintext) {
|
|
46
|
+
const resolved = await this.verifyAndLoadToken(plaintext);
|
|
47
|
+
return resolved ? resolved.user : null;
|
|
48
|
+
}
|
|
49
|
+
async verifyAndLoadToken(plaintext) {
|
|
50
|
+
if (!this.looksLikeExternalApiKey(plaintext)) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
const tokenHash = hashToken(plaintext);
|
|
54
|
+
// Join users so a single round-trip resolves both "token is valid" and
|
|
55
|
+
// "load the user it belongs to". The unique index on token_hash makes
|
|
56
|
+
// this a point-lookup. `isNull(revokedAt)` is what enforces revocation
|
|
57
|
+
// — the row remains for audit.
|
|
58
|
+
const [row] = await this.db
|
|
59
|
+
.select({
|
|
60
|
+
tokenId: externalApiKeys.id,
|
|
61
|
+
userId: users.id,
|
|
62
|
+
email: users.email,
|
|
63
|
+
name: users.name,
|
|
64
|
+
avatarUrl: users.avatarUrl,
|
|
65
|
+
})
|
|
66
|
+
.from(externalApiKeys)
|
|
67
|
+
.innerJoin(users, eq(externalApiKeys.userId, users.id))
|
|
68
|
+
.where(and(eq(externalApiKeys.tokenHash, tokenHash), isNull(externalApiKeys.revokedAt)))
|
|
69
|
+
.limit(1);
|
|
70
|
+
if (!row)
|
|
71
|
+
return null;
|
|
72
|
+
// Fire-and-forget so verification latency is bounded by the SELECT, not
|
|
73
|
+
// the UPDATE. A failed touch is logged but never blocks the caller —
|
|
74
|
+
// the worst case is a slightly stale `last_used_at`, which is fine for
|
|
75
|
+
// a "when was this key last used" audit view.
|
|
76
|
+
this.touchLastUsed(row.tokenId).catch((err) => {
|
|
77
|
+
console.warn('[external-api-key] touchLastUsed failed:', err);
|
|
78
|
+
});
|
|
79
|
+
return {
|
|
80
|
+
tokenId: row.tokenId,
|
|
81
|
+
user: {
|
|
82
|
+
id: row.userId,
|
|
83
|
+
email: row.email,
|
|
84
|
+
name: row.name,
|
|
85
|
+
avatarUrl: row.avatarUrl ?? undefined,
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
async listForUser(userId) {
|
|
90
|
+
const rows = await this.db
|
|
91
|
+
.select()
|
|
92
|
+
.from(externalApiKeys)
|
|
93
|
+
.where(eq(externalApiKeys.userId, userId))
|
|
94
|
+
.orderBy(desc(externalApiKeys.createdAt));
|
|
95
|
+
return rows.map(toSummary);
|
|
96
|
+
}
|
|
97
|
+
async revoke(id, userId) {
|
|
98
|
+
// Scope the WHERE by userId so a user can never revoke another user's
|
|
99
|
+
// token even if they learn the id. Idempotent on already-revoked rows
|
|
100
|
+
// because we only set `revokedAt` when it's currently null — re-revoking
|
|
101
|
+
// returns 0 rows changed but no error.
|
|
102
|
+
const result = await this.db
|
|
103
|
+
.update(externalApiKeys)
|
|
104
|
+
.set({ revokedAt: new Date() })
|
|
105
|
+
.where(and(eq(externalApiKeys.id, id), eq(externalApiKeys.userId, userId), isNull(externalApiKeys.revokedAt)))
|
|
106
|
+
.returning({ id: externalApiKeys.id });
|
|
107
|
+
if (result.length === 0) {
|
|
108
|
+
// Distinguish "doesn't exist / not yours" from "already revoked".
|
|
109
|
+
// The latter must stay idempotent (return success); only the former
|
|
110
|
+
// throws.
|
|
111
|
+
const [existing] = await this.db
|
|
112
|
+
.select({ id: externalApiKeys.id })
|
|
113
|
+
.from(externalApiKeys)
|
|
114
|
+
.where(and(eq(externalApiKeys.id, id), eq(externalApiKeys.userId, userId)))
|
|
115
|
+
.limit(1);
|
|
116
|
+
if (!existing) {
|
|
117
|
+
throw new TokenNotFoundError();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async remove(id, userId) {
|
|
122
|
+
// Only revoked rows may be hard-deleted — deleting an active key would
|
|
123
|
+
// silently cut off a live agent. Scope by userId so a user can only
|
|
124
|
+
// delete their own tokens. Validate first (so we can return a precise
|
|
125
|
+
// not-found vs still-active error), then delete inside a transaction.
|
|
126
|
+
const [existing] = await this.db
|
|
127
|
+
.select({ revokedAt: externalApiKeys.revokedAt })
|
|
128
|
+
.from(externalApiKeys)
|
|
129
|
+
.where(and(eq(externalApiKeys.id, id), eq(externalApiKeys.userId, userId)))
|
|
130
|
+
.limit(1);
|
|
131
|
+
if (!existing) {
|
|
132
|
+
throw new TokenNotFoundError();
|
|
133
|
+
}
|
|
134
|
+
if (existing.revokedAt === null) {
|
|
135
|
+
// Exists and is yours, but wasn't revoked — refuse rather than delete.
|
|
136
|
+
throw new TokenStillActiveError();
|
|
137
|
+
}
|
|
138
|
+
// Dependents (e.g. the enterprise LLM-usage metering rows) hang off this
|
|
139
|
+
// row via ON DELETE CASCADE foreign keys, so a bare delete takes any audit
|
|
140
|
+
// trail with it — this service doesn't have to know those tables exist.
|
|
141
|
+
await this.db
|
|
142
|
+
.delete(externalApiKeys)
|
|
143
|
+
.where(and(eq(externalApiKeys.id, id), eq(externalApiKeys.userId, userId), isNotNull(externalApiKeys.revokedAt)));
|
|
144
|
+
}
|
|
145
|
+
async touchLastUsed(tokenId) {
|
|
146
|
+
await this.db
|
|
147
|
+
.update(externalApiKeys)
|
|
148
|
+
.set({ lastUsedAt: new Date() })
|
|
149
|
+
.where(eq(externalApiKeys.id, tokenId));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function hashToken(plaintext) {
|
|
153
|
+
return createHash('sha256').update(plaintext).digest('hex');
|
|
154
|
+
}
|
|
155
|
+
function toSummary(row) {
|
|
156
|
+
return {
|
|
157
|
+
id: row.id,
|
|
158
|
+
label: row.label,
|
|
159
|
+
createdAt: row.createdAt.getTime(),
|
|
160
|
+
lastUsedAt: row.lastUsedAt ? row.lastUsedAt.getTime() : null,
|
|
161
|
+
revokedAt: row.revokedAt ? row.revokedAt.getTime() : null,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=external-api-key.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external-api-key.service.js","sourceRoot":"","sources":["../../../src/modules/tool-auth/external-api-key.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an internal token authorizes: a user identity, nothing more. Minted when
|
|
3
|
+
* an agent's code-mode client is built and seeded into that client's UTCP config.
|
|
4
|
+
* Deliberately identity-only — the SAME shape a `bevel_…` connection key resolves
|
|
5
|
+
* to: the workspace is chosen per call from the tool's `branch` argument, and the
|
|
6
|
+
* scope is always write (the middleware sets it, exactly as for connection keys).
|
|
7
|
+
*/
|
|
8
|
+
export interface InternalTokenClaim {
|
|
9
|
+
userId: string;
|
|
10
|
+
/**
|
|
11
|
+
* The agent run / conversation id (the Mastra thread id) this token is scoped
|
|
12
|
+
* to, when minted per-run. Surfaced as `ToolContext.sessionId` so the
|
|
13
|
+
* ontology-session boundary can scope to one run for the in-process agent
|
|
14
|
+
* (the external/MCP path carries `sessionId` on the tool body instead).
|
|
15
|
+
* Absent for identity-only tokens.
|
|
16
|
+
*/
|
|
17
|
+
sessionId?: string;
|
|
18
|
+
/**
|
|
19
|
+
* True when this token is the LOOPBACK identity of an external caller — the
|
|
20
|
+
* MCP proxy mints one per OAuth/JWT MCP session (which has no `bevel_…`
|
|
21
|
+
* connection key to pass through). The verifier resolves such tokens to
|
|
22
|
+
* `source: 'external'`: the caller IS an external agent, and must be treated
|
|
23
|
+
* like one everywhere — admitted to external-only surfaces (`start_session`,
|
|
24
|
+
* `ask`), refused from internal-only ones (`execute_command`, …), and
|
|
25
|
+
* expected to carry `sessionId` on the tool body, not in the token.
|
|
26
|
+
*/
|
|
27
|
+
externalProxy?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Mints + verifies stateless HMAC internal tokens. No DB: the token is
|
|
31
|
+
* self-contained `(claim, exp)` signed with a process secret, so it is
|
|
32
|
+
* multi-replica safe for verification within a deploy and costs nothing to
|
|
33
|
+
* issue. Tokens carry only `userId` and are short-lived; the agent factory
|
|
34
|
+
* mints one per code-mode client (per user).
|
|
35
|
+
*
|
|
36
|
+
* Distinct from connection keys (`bevel_…`, long-lived, user-wide): internal
|
|
37
|
+
* tokens are the least-privilege credential for the in-process loopback surface
|
|
38
|
+
* and are rejected by the external endpoints, and vice-versa.
|
|
39
|
+
*/
|
|
40
|
+
export declare class InternalTokenService {
|
|
41
|
+
private readonly secret;
|
|
42
|
+
private readonly ttlMs;
|
|
43
|
+
private readonly now;
|
|
44
|
+
private readonly prefix;
|
|
45
|
+
constructor(opts?: {
|
|
46
|
+
secret?: string;
|
|
47
|
+
ttlMs?: number;
|
|
48
|
+
now?: () => number;
|
|
49
|
+
prefix?: string;
|
|
50
|
+
});
|
|
51
|
+
/** Token lifetime in ms — so callers caching a minted token can refresh it before expiry. */
|
|
52
|
+
get tokenTtlMs(): number;
|
|
53
|
+
/** @param ttlMs Override the default lifetime — e.g. the MCP proxy mints
|
|
54
|
+
* session-loopback tokens that must outlive its 4h session idle TTL. */
|
|
55
|
+
mint(claim: InternalTokenClaim, ttlMs?: number): string;
|
|
56
|
+
/** Returns the claim for a valid, unexpired token; null otherwise. */
|
|
57
|
+
verify(token: string): InternalTokenClaim | null;
|
|
58
|
+
/** True if the bearer string looks like an internal token (vs an external API key). */
|
|
59
|
+
looksLikeInternalToken(token: string): boolean;
|
|
60
|
+
private sign;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=internal-token.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal-token.service.d.ts","sourceRoot":"","sources":["../../../src/modules/tool-auth/internal-token.service.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAaD;;;;;;;;;;GAUG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAG9B,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO;IAarF,6FAA6F;IAC7F,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;8EAC0E;IAC1E,IAAI,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;IAOvD,sEAAsE;IACtE,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI;IA2BhD,uFAAuF;IACvF,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAI9C,OAAO,CAAC,IAAI;CAGb"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { createHmac, randomBytes, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
const DEFAULT_PREFIX = 'bevel-int_';
|
|
3
|
+
function b64url(buf) {
|
|
4
|
+
return buf.toString('base64url');
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Mints + verifies stateless HMAC internal tokens. No DB: the token is
|
|
8
|
+
* self-contained `(claim, exp)` signed with a process secret, so it is
|
|
9
|
+
* multi-replica safe for verification within a deploy and costs nothing to
|
|
10
|
+
* issue. Tokens carry only `userId` and are short-lived; the agent factory
|
|
11
|
+
* mints one per code-mode client (per user).
|
|
12
|
+
*
|
|
13
|
+
* Distinct from connection keys (`bevel_…`, long-lived, user-wide): internal
|
|
14
|
+
* tokens are the least-privilege credential for the in-process loopback surface
|
|
15
|
+
* and are rejected by the external endpoints, and vice-versa.
|
|
16
|
+
*/
|
|
17
|
+
export class InternalTokenService {
|
|
18
|
+
secret;
|
|
19
|
+
ttlMs;
|
|
20
|
+
now;
|
|
21
|
+
prefix;
|
|
22
|
+
constructor(opts = {}) {
|
|
23
|
+
// A per-boot random secret is fine: tokens are minted per turn-ish and
|
|
24
|
+
// re-minted after a restart. A caller may inject a stable secret (tests, or
|
|
25
|
+
// a future multi-replica deploy) instead.
|
|
26
|
+
this.secret = opts.secret ? Buffer.from(opts.secret, 'utf8') : randomBytes(32);
|
|
27
|
+
this.ttlMs = opts.ttlMs ?? 60 * 60 * 1000; // 1h
|
|
28
|
+
this.now = opts.now ?? Date.now;
|
|
29
|
+
// Tenant-derived prefix (default `bevel-int_`), injected from
|
|
30
|
+
// AppConfig.internalTokenPrefix so internal tokens brand with the deploy's tenant.
|
|
31
|
+
this.prefix = opts.prefix ?? DEFAULT_PREFIX;
|
|
32
|
+
}
|
|
33
|
+
/** Token lifetime in ms — so callers caching a minted token can refresh it before expiry. */
|
|
34
|
+
get tokenTtlMs() {
|
|
35
|
+
return this.ttlMs;
|
|
36
|
+
}
|
|
37
|
+
/** @param ttlMs Override the default lifetime — e.g. the MCP proxy mints
|
|
38
|
+
* session-loopback tokens that must outlive its 4h session idle TTL. */
|
|
39
|
+
mint(claim, ttlMs) {
|
|
40
|
+
const payload = { ...claim, exp: this.now() + (ttlMs ?? this.ttlMs) };
|
|
41
|
+
const body = b64url(Buffer.from(JSON.stringify(payload), 'utf8'));
|
|
42
|
+
const sig = b64url(this.sign(body));
|
|
43
|
+
return `${this.prefix}${body}.${sig}`;
|
|
44
|
+
}
|
|
45
|
+
/** Returns the claim for a valid, unexpired token; null otherwise. */
|
|
46
|
+
verify(token) {
|
|
47
|
+
if (!this.looksLikeInternalToken(token))
|
|
48
|
+
return null;
|
|
49
|
+
const rest = token.slice(this.prefix.length);
|
|
50
|
+
const dot = rest.indexOf('.');
|
|
51
|
+
if (dot < 0)
|
|
52
|
+
return null;
|
|
53
|
+
const body = rest.slice(0, dot);
|
|
54
|
+
const sig = rest.slice(dot + 1);
|
|
55
|
+
const expected = b64url(this.sign(body));
|
|
56
|
+
if (sig.length !== expected.length)
|
|
57
|
+
return null;
|
|
58
|
+
if (!timingSafeEqual(Buffer.from(sig), Buffer.from(expected)))
|
|
59
|
+
return null;
|
|
60
|
+
let payload;
|
|
61
|
+
try {
|
|
62
|
+
payload = JSON.parse(Buffer.from(body, 'base64url').toString('utf8'));
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
if (typeof payload.exp !== 'number' || payload.exp < this.now())
|
|
68
|
+
return null;
|
|
69
|
+
if (typeof payload.userId !== 'string')
|
|
70
|
+
return null;
|
|
71
|
+
return {
|
|
72
|
+
userId: payload.userId,
|
|
73
|
+
...(typeof payload.sessionId === 'string' ? { sessionId: payload.sessionId } : {}),
|
|
74
|
+
...(payload.externalProxy === true ? { externalProxy: true } : {}),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** True if the bearer string looks like an internal token (vs an external API key). */
|
|
78
|
+
looksLikeInternalToken(token) {
|
|
79
|
+
return token.startsWith(this.prefix);
|
|
80
|
+
}
|
|
81
|
+
sign(body) {
|
|
82
|
+
return createHmac('sha256', this.secret).update(body).digest();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=internal-token.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal-token.service.js","sourceRoot":"","sources":["../../../src/modules/tool-auth/internal-token.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metering view over connection-key LLM usage, consumed by the connection-key
|
|
3
|
+
* management routes (mcp) to show each key's spend against the daily budget.
|
|
4
|
+
* The enterprise LLM proxy's `LlmUsageService` satisfies this structurally; a
|
|
5
|
+
* core-only deployment (no LLM proxy, nothing to meter) passes
|
|
6
|
+
* {@link unmeteredLlmUsage}.
|
|
7
|
+
*/
|
|
8
|
+
export interface ILlmUsageMeter {
|
|
9
|
+
/** Daily per-key token cap shown in the UI, or null when unmetered. */
|
|
10
|
+
readonly dailyCap: number | null;
|
|
11
|
+
/** Today's usage per key id, as `{ [tokenId]: tokens }` — missing keys mean 0. */
|
|
12
|
+
usageForTokens(tokenIds: string[]): Promise<Record<string, number>>;
|
|
13
|
+
}
|
|
14
|
+
/** Core default: no proxy, no metering — every key reads as unused/uncapped. */
|
|
15
|
+
export declare const unmeteredLlmUsage: ILlmUsageMeter;
|
|
16
|
+
//# sourceMappingURL=llm-usage-meter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-usage-meter.d.ts","sourceRoot":"","sources":["../../../src/modules/tool-auth/llm-usage-meter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,kFAAkF;IAClF,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrE;AAED,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,EAAE,cAG/B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-usage-meter.js","sourceRoot":"","sources":["../../../src/modules/tool-auth/llm-usage-meter.ts"],"names":[],"mappings":"AAcA,gFAAgF;AAChF,MAAM,CAAC,MAAM,iBAAiB,GAAmB;IAC/C,QAAQ,EAAE,IAAI;IACd,cAAc,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;CACjC,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { RequestHandler } from 'express';
|
|
2
|
+
import type { IExternalApiKeyService } from './external-api-key.interface.js';
|
|
3
|
+
import type { AuthService } from '../auth/auth.service.js';
|
|
4
|
+
import { InternalTokenService } from './internal-token.service.js';
|
|
5
|
+
/**
|
|
6
|
+
* What the `toolAuth` middleware resolves a bearer to, before the per-call
|
|
7
|
+
* `ToolContext` is built. Internal and external are now the SAME shape — a user
|
|
8
|
+
* identity at write scope — resolving through one path; `source` only records
|
|
9
|
+
* which credential authenticated (so internal-only routes can be gated):
|
|
10
|
+
* - `external`: a `bevel_…` connection key → user.
|
|
11
|
+
* - `internal`: an identity-only HMAC token minted for an agent's code-mode client.
|
|
12
|
+
* - `session`: a browser JWT — admitted ONLY on the read-only manual endpoint
|
|
13
|
+
* (`createManualAuthMiddleware`), never on a tool-execution route, so it can
|
|
14
|
+
* browse the catalog but cannot invoke tools.
|
|
15
|
+
* The workspace is chosen per call from the tool's `branch` argument (downstream
|
|
16
|
+
* ACL / protected-branch checks gate writes).
|
|
17
|
+
*/
|
|
18
|
+
export interface ToolAuth {
|
|
19
|
+
source: 'internal' | 'external' | 'session';
|
|
20
|
+
userId: string;
|
|
21
|
+
tokenId?: string;
|
|
22
|
+
/** The agent run id carried by a per-run internal token (in-process agent). The external path supplies `sessionId` on the tool body instead. */
|
|
23
|
+
sessionId?: string;
|
|
24
|
+
/** Always `'write'` now (the middleware sets it for both internal + external — neither credential carries scope). The read path is dormant until consumer agents are removed. */
|
|
25
|
+
scope: 'read' | 'write';
|
|
26
|
+
}
|
|
27
|
+
declare global {
|
|
28
|
+
namespace Express {
|
|
29
|
+
interface Request {
|
|
30
|
+
toolAuth?: ToolAuth;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Gate that admits ONLY in-process callers (those bearing an internal HMAC
|
|
36
|
+
* token). Mount it AFTER `toolAuth` on every internal-only surface — the
|
|
37
|
+
* internal tool catalog and the routes of tools registered with
|
|
38
|
+
* `registerInternalTool` but NOT `registerExternalTool` (e.g. `execute_command`,
|
|
39
|
+
* `switch_branch`, the `sharepoint_*` reads). `toolAuth` alone is not enough:
|
|
40
|
+
* an external connection key authenticates successfully, so without this gate it
|
|
41
|
+
* could invoke an internal-only route directly by guessing its name. The route
|
|
42
|
+
* MUST stay mounted (our own agent reaches it over the same loopback HTTP), so
|
|
43
|
+
* the restriction has to be enforced here at request time, not by hiding the
|
|
44
|
+
* route. 403 (authenticated, but not authorized for this surface).
|
|
45
|
+
*/
|
|
46
|
+
export declare const requireInternalSource: RequestHandler;
|
|
47
|
+
/**
|
|
48
|
+
* Mirror of `requireInternalSource` for surfaces that must admit ONLY external
|
|
49
|
+
* callers. `start_session` mints a fresh chat thread as the caller's
|
|
50
|
+
* ontology-session id; an internal (in-process agent) token already carries
|
|
51
|
+
* its run's `sessionId`, so letting it mint a new thread mid-run would
|
|
52
|
+
* silently reset the one-ontology-per-conversation boundary.
|
|
53
|
+
*
|
|
54
|
+
* "External" is decided by the VERIFIER, not by which credential shape
|
|
55
|
+
* authenticated: a `bevel_…` connection key resolves external, and so does an
|
|
56
|
+
* `externalProxy` internal token — the loopback identity the MCP proxy mints
|
|
57
|
+
* for an OAuth/JWT MCP session, whose caller IS an external agent. (Gating on
|
|
58
|
+
* the raw credential shape used to 403 those sessions here, deadlocking them:
|
|
59
|
+
* they couldn't mint a sessionId, and every session-gated tool demands one.)
|
|
60
|
+
* Mount AFTER `toolAuth`. 403 (authenticated, but not authorized).
|
|
61
|
+
*/
|
|
62
|
+
export declare const requireExternalSource: RequestHandler;
|
|
63
|
+
/** Outcome of verifying a bearer token — either a normalized identity or a status+message to surface. */
|
|
64
|
+
export type VerifyResult = {
|
|
65
|
+
ok: true;
|
|
66
|
+
auth: ToolAuth;
|
|
67
|
+
} | {
|
|
68
|
+
ok: false;
|
|
69
|
+
status: number;
|
|
70
|
+
message: string;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* The framework-agnostic verify core: bearer token (the value AFTER `Bearer `) →
|
|
74
|
+
* normalized `ToolAuth`, accepting EITHER a `bevel_…` connection key (external —
|
|
75
|
+
* pipeline-agent, MCP) OR an internal HMAC token (our own agent's loopback). A
|
|
76
|
+
* bare JWT / unknown scheme is refused. Throws only if the connection-key store
|
|
77
|
+
* itself errors (backend down); the caller maps that to 500. This is the shared
|
|
78
|
+
* primitive both `createToolAuthMiddleware` (our Express hosting) and
|
|
79
|
+
* `validateToken` (the tool-author SDK) are built on, so there is ONE auth path.
|
|
80
|
+
*/
|
|
81
|
+
export declare function createTokenVerifier(externalApiKeyService: IExternalApiKeyService, internalTokenService: InternalTokenService): (token: string | undefined) => Promise<VerifyResult>;
|
|
82
|
+
/**
|
|
83
|
+
* The one auth gate every tool endpoint applies — a THIN Express adapter over
|
|
84
|
+
* `createTokenVerifier`: parse the bearer header, run the shared verify core,
|
|
85
|
+
* normalize the result to `req.toolAuth` (or the matching status). All auth logic
|
|
86
|
+
* lives in the verifier; this only does header parsing + HTTP mapping.
|
|
87
|
+
*/
|
|
88
|
+
export declare function createToolAuthMiddleware(externalApiKeyService: IExternalApiKeyService, internalTokenService: InternalTokenService): RequestHandler;
|
|
89
|
+
/**
|
|
90
|
+
* Auth gate for the READ-ONLY discovery manuals (`GET /agent/utcp` +
|
|
91
|
+
* `/agent/internal/utcp`) ONLY. Superset of `createToolAuthMiddleware`: it
|
|
92
|
+
* accepts a `bevel_…` connection key, an internal token, OR a browser JWT —
|
|
93
|
+
* the last resolving to `source: 'session'`. This is what lets a logged-in user
|
|
94
|
+
* browse the catalog with their existing session (the manual is just a spec, no
|
|
95
|
+
* secrets, and may become per-user — hence one user-aware endpoint rather than a
|
|
96
|
+
* parallel route). It is deliberately NOT used on tool-execution routes, so a
|
|
97
|
+
* JWT can read the manual but can never invoke a tool. The internal manual stays
|
|
98
|
+
* `requireInternalSource`-gated downstream, so a session/key is 403'd there.
|
|
99
|
+
*/
|
|
100
|
+
export declare function createManualAuthMiddleware(externalApiKeyService: IExternalApiKeyService, internalTokenService: InternalTokenService, authService: AuthService): RequestHandler;
|
|
101
|
+
//# sourceMappingURL=tool-auth.middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-auth.middleware.d.ts","sourceRoot":"","sources":["../../../src/modules/tool-auth/tool-auth.middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmC,cAAc,EAAE,MAAM,SAAS,CAAC;AAC/E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gJAAgJ;IAChJ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iLAAiL;IACjL,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CACzB;AAED,OAAO,CAAC,MAAM,CAAC;IAEb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,QAAQ,CAAC,EAAE,QAAQ,CAAC;SACrB;KACF;CACF;AAID;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,EAAE,cAMnC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,qBAAqB,EAAE,cAMnC,CAAC;AAEF,yGAAyG;AACzG,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC5B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,qBAAqB,EAAE,sBAAsB,EAC7C,oBAAoB,EAAE,oBAAoB,GACzC,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAC,YAAY,CAAC,CA6BtD;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,qBAAqB,EAAE,sBAAsB,EAC7C,oBAAoB,EAAE,oBAAoB,GACzC,cAAc,CAwBhB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACxC,qBAAqB,EAAE,sBAAsB,EAC7C,oBAAoB,EAAE,oBAAoB,EAC1C,WAAW,EAAE,WAAW,GACvB,cAAc,CAuChB"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
const WWW_AUTH = 'Bearer realm="bevel-tools"';
|
|
2
|
+
/**
|
|
3
|
+
* Gate that admits ONLY in-process callers (those bearing an internal HMAC
|
|
4
|
+
* token). Mount it AFTER `toolAuth` on every internal-only surface — the
|
|
5
|
+
* internal tool catalog and the routes of tools registered with
|
|
6
|
+
* `registerInternalTool` but NOT `registerExternalTool` (e.g. `execute_command`,
|
|
7
|
+
* `switch_branch`, the `sharepoint_*` reads). `toolAuth` alone is not enough:
|
|
8
|
+
* an external connection key authenticates successfully, so without this gate it
|
|
9
|
+
* could invoke an internal-only route directly by guessing its name. The route
|
|
10
|
+
* MUST stay mounted (our own agent reaches it over the same loopback HTTP), so
|
|
11
|
+
* the restriction has to be enforced here at request time, not by hiding the
|
|
12
|
+
* route. 403 (authenticated, but not authorized for this surface).
|
|
13
|
+
*/
|
|
14
|
+
export const requireInternalSource = (req, res, next) => {
|
|
15
|
+
if (req.toolAuth?.source !== 'internal') {
|
|
16
|
+
res.status(403).json({ error: 'This tool is internal-only.' });
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
next();
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Mirror of `requireInternalSource` for surfaces that must admit ONLY external
|
|
23
|
+
* callers. `start_session` mints a fresh chat thread as the caller's
|
|
24
|
+
* ontology-session id; an internal (in-process agent) token already carries
|
|
25
|
+
* its run's `sessionId`, so letting it mint a new thread mid-run would
|
|
26
|
+
* silently reset the one-ontology-per-conversation boundary.
|
|
27
|
+
*
|
|
28
|
+
* "External" is decided by the VERIFIER, not by which credential shape
|
|
29
|
+
* authenticated: a `bevel_…` connection key resolves external, and so does an
|
|
30
|
+
* `externalProxy` internal token — the loopback identity the MCP proxy mints
|
|
31
|
+
* for an OAuth/JWT MCP session, whose caller IS an external agent. (Gating on
|
|
32
|
+
* the raw credential shape used to 403 those sessions here, deadlocking them:
|
|
33
|
+
* they couldn't mint a sessionId, and every session-gated tool demands one.)
|
|
34
|
+
* Mount AFTER `toolAuth`. 403 (authenticated, but not authorized).
|
|
35
|
+
*/
|
|
36
|
+
export const requireExternalSource = (req, res, next) => {
|
|
37
|
+
if (req.toolAuth?.source !== 'external') {
|
|
38
|
+
res.status(403).json({ error: 'This tool is external-only.' });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
next();
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* The framework-agnostic verify core: bearer token (the value AFTER `Bearer `) →
|
|
45
|
+
* normalized `ToolAuth`, accepting EITHER a `bevel_…` connection key (external —
|
|
46
|
+
* pipeline-agent, MCP) OR an internal HMAC token (our own agent's loopback). A
|
|
47
|
+
* bare JWT / unknown scheme is refused. Throws only if the connection-key store
|
|
48
|
+
* itself errors (backend down); the caller maps that to 500. This is the shared
|
|
49
|
+
* primitive both `createToolAuthMiddleware` (our Express hosting) and
|
|
50
|
+
* `validateToken` (the tool-author SDK) are built on, so there is ONE auth path.
|
|
51
|
+
*/
|
|
52
|
+
export function createTokenVerifier(externalApiKeyService, internalTokenService) {
|
|
53
|
+
const missing = { ok: false, status: 401, message: 'A connection key or internal token is required' };
|
|
54
|
+
return async (token) => {
|
|
55
|
+
if (!token)
|
|
56
|
+
return missing;
|
|
57
|
+
// Internal token → in-process loopback caller. Usually our own agent
|
|
58
|
+
// (source 'internal'), EXCEPT the `externalProxy` tokens the MCP proxy
|
|
59
|
+
// mints as the loopback identity of an OAuth/JWT MCP session — that
|
|
60
|
+
// caller is an external agent and resolves as one, so external-only
|
|
61
|
+
// surfaces admit it and internal-only surfaces refuse it, exactly like a
|
|
62
|
+
// connection key (it just has no tokenId to meter on).
|
|
63
|
+
if (internalTokenService.looksLikeInternalToken(token)) {
|
|
64
|
+
const claim = internalTokenService.verify(token);
|
|
65
|
+
if (!claim)
|
|
66
|
+
return { ok: false, status: 401, message: 'Invalid or expired internal token' };
|
|
67
|
+
return claim.externalProxy
|
|
68
|
+
? { ok: true, auth: { source: 'external', userId: claim.userId, scope: 'write' } }
|
|
69
|
+
: { ok: true, auth: { source: 'internal', userId: claim.userId, sessionId: claim.sessionId, scope: 'write' } };
|
|
70
|
+
}
|
|
71
|
+
// External API key → external caller. (verifyAndLoadToken may throw → propagates → caller maps to 500.)
|
|
72
|
+
if (externalApiKeyService.looksLikeExternalApiKey(token)) {
|
|
73
|
+
const resolved = await externalApiKeyService.verifyAndLoadToken(token);
|
|
74
|
+
return resolved
|
|
75
|
+
? { ok: true, auth: { source: 'external', userId: resolved.user.id, tokenId: resolved.tokenId, scope: 'write' } }
|
|
76
|
+
: { ok: false, status: 401, message: 'Invalid or revoked connection key' };
|
|
77
|
+
}
|
|
78
|
+
return missing;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The one auth gate every tool endpoint applies — a THIN Express adapter over
|
|
83
|
+
* `createTokenVerifier`: parse the bearer header, run the shared verify core,
|
|
84
|
+
* normalize the result to `req.toolAuth` (or the matching status). All auth logic
|
|
85
|
+
* lives in the verifier; this only does header parsing + HTTP mapping.
|
|
86
|
+
*/
|
|
87
|
+
export function createToolAuthMiddleware(externalApiKeyService, internalTokenService) {
|
|
88
|
+
const verify = createTokenVerifier(externalApiKeyService, internalTokenService);
|
|
89
|
+
return async (req, res, next) => {
|
|
90
|
+
const header = req.headers.authorization;
|
|
91
|
+
if (!header || !header.toLowerCase().startsWith('bearer ')) {
|
|
92
|
+
res.setHeader('WWW-Authenticate', WWW_AUTH);
|
|
93
|
+
res.status(401).json({ error: 'Missing or invalid Authorization header' });
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const token = header.slice(header.indexOf(' ') + 1).trim();
|
|
97
|
+
try {
|
|
98
|
+
const result = await verify(token);
|
|
99
|
+
if (!result.ok) {
|
|
100
|
+
if (result.status === 401)
|
|
101
|
+
res.setHeader('WWW-Authenticate', WWW_AUTH);
|
|
102
|
+
res.status(result.status).json({ error: result.message });
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
req.toolAuth = result.auth;
|
|
106
|
+
next();
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
console.error('[tools] connection-key verification failed:', err);
|
|
110
|
+
res.status(500).json({ error: 'Authentication backend unavailable' });
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Auth gate for the READ-ONLY discovery manuals (`GET /agent/utcp` +
|
|
116
|
+
* `/agent/internal/utcp`) ONLY. Superset of `createToolAuthMiddleware`: it
|
|
117
|
+
* accepts a `bevel_…` connection key, an internal token, OR a browser JWT —
|
|
118
|
+
* the last resolving to `source: 'session'`. This is what lets a logged-in user
|
|
119
|
+
* browse the catalog with their existing session (the manual is just a spec, no
|
|
120
|
+
* secrets, and may become per-user — hence one user-aware endpoint rather than a
|
|
121
|
+
* parallel route). It is deliberately NOT used on tool-execution routes, so a
|
|
122
|
+
* JWT can read the manual but can never invoke a tool. The internal manual stays
|
|
123
|
+
* `requireInternalSource`-gated downstream, so a session/key is 403'd there.
|
|
124
|
+
*/
|
|
125
|
+
export function createManualAuthMiddleware(externalApiKeyService, internalTokenService, authService) {
|
|
126
|
+
const verify = createTokenVerifier(externalApiKeyService, internalTokenService);
|
|
127
|
+
return async (req, res, next) => {
|
|
128
|
+
const header = req.headers.authorization;
|
|
129
|
+
if (!header || !header.toLowerCase().startsWith('bearer ')) {
|
|
130
|
+
res.setHeader('WWW-Authenticate', WWW_AUTH);
|
|
131
|
+
res.status(401).json({ error: 'Missing or invalid Authorization header' });
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const token = header.slice(header.indexOf(' ') + 1).trim();
|
|
135
|
+
// An external API key / internal token goes through the shared verify core.
|
|
136
|
+
if (internalTokenService.looksLikeInternalToken(token) || externalApiKeyService.looksLikeExternalApiKey(token)) {
|
|
137
|
+
try {
|
|
138
|
+
const result = await verify(token);
|
|
139
|
+
if (!result.ok) {
|
|
140
|
+
if (result.status === 401)
|
|
141
|
+
res.setHeader('WWW-Authenticate', WWW_AUTH);
|
|
142
|
+
res.status(result.status).json({ error: result.message });
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
req.toolAuth = result.auth;
|
|
146
|
+
next();
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
console.error('[tools] connection-key verification failed:', err);
|
|
150
|
+
res.status(500).json({ error: 'Authentication backend unavailable' });
|
|
151
|
+
}
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
// Otherwise treat the bearer as a browser session JWT.
|
|
155
|
+
try {
|
|
156
|
+
const { userId } = authService.verifyToken(token);
|
|
157
|
+
req.toolAuth = { source: 'session', userId, scope: 'write' };
|
|
158
|
+
next();
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
res.setHeader('WWW-Authenticate', WWW_AUTH);
|
|
162
|
+
res.status(401).json({ error: 'Invalid or expired token' });
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=tool-auth.middleware.js.map
|