@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,213 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { execFile } from 'node:child_process';
|
|
3
|
+
import { promisify } from 'node:util';
|
|
4
|
+
import fs from 'node:fs/promises';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import os from 'node:os';
|
|
7
|
+
import { KbSeedService } from '../kb-seed.service.js';
|
|
8
|
+
import { defaultKbTemplateDir } from '../../../assets.js';
|
|
9
|
+
|
|
10
|
+
const execFileAsync = promisify(execFile);
|
|
11
|
+
|
|
12
|
+
/** The real seed template shipped inside this package (see assets.ts). */
|
|
13
|
+
const TEMPLATE_DIR = defaultKbTemplateDir();
|
|
14
|
+
|
|
15
|
+
const PROTECTED = ['current-company-state', 'target-company-state'];
|
|
16
|
+
const DEFAULT_BRANCH = 'current-company-state';
|
|
17
|
+
const ADMINS = ['alice@example.com', 'bob@example.com'];
|
|
18
|
+
|
|
19
|
+
async function git(cwd: string, args: string[]): Promise<string> {
|
|
20
|
+
const { stdout } = await execFileAsync('git', args, {
|
|
21
|
+
cwd,
|
|
22
|
+
env: {
|
|
23
|
+
...process.env,
|
|
24
|
+
GIT_AUTHOR_NAME: 'Test', GIT_AUTHOR_EMAIL: 't@x.com',
|
|
25
|
+
GIT_COMMITTER_NAME: 'Test', GIT_COMMITTER_EMAIL: 't@x.com',
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
return stdout.toString();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function makeSeeder(upstream: string, admins: readonly string[] = ADMINS): KbSeedService {
|
|
32
|
+
return new KbSeedService(upstream, TEMPLATE_DIR, PROTECTED, DEFAULT_BRANCH, admins);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Clone a branch of the upstream into a fresh checkout for inspection. */
|
|
36
|
+
async function checkout(root: string, upstream: string, branch: string): Promise<string> {
|
|
37
|
+
const dir = path.join(root, `checkout-${branch}-${Math.random().toString(36).slice(2)}`);
|
|
38
|
+
await git(root, ['clone', '-b', branch, upstream, dir]);
|
|
39
|
+
return dir;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function exists(p: string): Promise<boolean> {
|
|
43
|
+
try {
|
|
44
|
+
await fs.access(p);
|
|
45
|
+
return true;
|
|
46
|
+
} catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function headCommitCount(root: string, upstream: string, branch: string): Promise<number> {
|
|
52
|
+
const dir = await checkout(root, upstream, branch);
|
|
53
|
+
const out = await git(dir, ['rev-list', '--count', 'HEAD']);
|
|
54
|
+
return Number(out.trim());
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
describe('KbSeedService', () => {
|
|
58
|
+
let root: string;
|
|
59
|
+
|
|
60
|
+
beforeEach(async () => {
|
|
61
|
+
root = await fs.mkdtemp(path.join(os.tmpdir(), 'kb-seed-test-'));
|
|
62
|
+
});
|
|
63
|
+
afterEach(async () => {
|
|
64
|
+
await fs.rm(root, { recursive: true, force: true }).catch(() => {});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
/** A bare, branch-less "empty" remote. */
|
|
68
|
+
async function emptyUpstream(): Promise<string> {
|
|
69
|
+
const upstream = path.join(root, 'upstream.git');
|
|
70
|
+
await git(root, ['init', '--bare', upstream]);
|
|
71
|
+
return upstream;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** A bare remote pre-seeded on `branches`, each with `files` written at the root. */
|
|
75
|
+
async function seededUpstream(
|
|
76
|
+
branches: string[],
|
|
77
|
+
files: Record<string, string>,
|
|
78
|
+
): Promise<string> {
|
|
79
|
+
const upstream = path.join(root, 'upstream.git');
|
|
80
|
+
await git(root, ['init', '--bare', upstream]);
|
|
81
|
+
const seed = path.join(root, '.seed');
|
|
82
|
+
await fs.mkdir(seed);
|
|
83
|
+
await git(seed, ['init', '-b', branches[0]]);
|
|
84
|
+
await git(seed, ['remote', 'add', 'origin', upstream]);
|
|
85
|
+
for (const [name, content] of Object.entries(files)) {
|
|
86
|
+
const abs = path.join(seed, name);
|
|
87
|
+
await fs.mkdir(path.dirname(abs), { recursive: true });
|
|
88
|
+
await fs.writeFile(abs, content, 'utf8');
|
|
89
|
+
}
|
|
90
|
+
await git(seed, ['add', '-A']);
|
|
91
|
+
await git(seed, ['commit', '-m', 'pre-seed']);
|
|
92
|
+
for (const b of branches.slice(1)) await git(seed, ['branch', b]);
|
|
93
|
+
await git(seed, ['push', 'origin', ...branches]);
|
|
94
|
+
return upstream;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
describe('empty remote → full seed', () => {
|
|
98
|
+
it('seeds every protected branch with base scaffolding + generated roles.yaml', async () => {
|
|
99
|
+
const upstream = await emptyUpstream();
|
|
100
|
+
await makeSeeder(upstream).ensureRemoteSeeded();
|
|
101
|
+
|
|
102
|
+
for (const branch of PROTECTED) {
|
|
103
|
+
const dir = await checkout(root, upstream, branch);
|
|
104
|
+
expect(await exists(path.join(dir, 'access.md'))).toBe(true);
|
|
105
|
+
expect(await exists(path.join(dir, 'CLAUDE.md'))).toBe(true);
|
|
106
|
+
expect(await exists(path.join(dir, '.bevelignore'))).toBe(true);
|
|
107
|
+
expect(await exists(path.join(dir, '.gitignore'))).toBe(true);
|
|
108
|
+
// The well-known KB roots are seeded (kept present via their .gitkeep).
|
|
109
|
+
expect(await exists(path.join(dir, 'KnowledgeBase/.gitkeep'))).toBe(true);
|
|
110
|
+
expect(await exists(path.join(dir, 'Skills/.gitkeep'))).toBe(true);
|
|
111
|
+
|
|
112
|
+
const roles = await fs.readFile(path.join(dir, 'roles.yaml'), 'utf8');
|
|
113
|
+
for (const email of ADMINS) expect(roles).toContain(email);
|
|
114
|
+
// The template's illustrative placeholder must NOT leak into the seed.
|
|
115
|
+
expect(roles).not.toContain('admin@example.com');
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('throws when no admin emails are configured', async () => {
|
|
120
|
+
const upstream = await emptyUpstream();
|
|
121
|
+
await expect(makeSeeder(upstream, []).ensureRemoteSeeded()).rejects.toThrow(
|
|
122
|
+
/SEED_ADMIN_EMAILS/,
|
|
123
|
+
);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe('existing remote → conservative top-up', () => {
|
|
128
|
+
it('creates a missing protected branch off an existing one', async () => {
|
|
129
|
+
// Only current-company-state exists; target-company-state is missing.
|
|
130
|
+
const upstream = await seededUpstream([DEFAULT_BRANCH], {
|
|
131
|
+
'roles.yaml': 'roles:\n Admin:\n - keep@example.com\n',
|
|
132
|
+
'access.md': 'existing',
|
|
133
|
+
'CLAUDE.md': 'existing',
|
|
134
|
+
'.bevelignore': 'x',
|
|
135
|
+
'.gitignore': 'x',
|
|
136
|
+
'KnowledgeBase/Real/Knowledge/.gitkeep': '',
|
|
137
|
+
'Skills/.gitkeep': '',
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
await makeSeeder(upstream).ensureRemoteSeeded();
|
|
141
|
+
|
|
142
|
+
const heads = await git(root, ['ls-remote', '--heads', upstream]);
|
|
143
|
+
expect(heads).toContain('refs/heads/target-company-state');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('topUpWorkspace adds only missing scaffolding and never overwrites existing files', async () => {
|
|
147
|
+
const upstream = await seededUpstream(PROTECTED, {
|
|
148
|
+
// roles.yaml + access.md already exist with custom content — must survive.
|
|
149
|
+
'roles.yaml': 'roles:\n Admin:\n - keep@example.com\n',
|
|
150
|
+
'access.md': 'CUSTOM ACCESS RULES',
|
|
151
|
+
// CLAUDE.md / .bevelignore / .gitignore are absent → should be added.
|
|
152
|
+
'KnowledgeBase/Real/Knowledge/.gitkeep': '',
|
|
153
|
+
'Skills/.gitkeep': '',
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Simulate the app loading the branch: a fresh clone, then top-up on it.
|
|
157
|
+
const repoDir = await checkout(root, upstream, DEFAULT_BRANCH);
|
|
158
|
+
await makeSeeder(upstream).topUpWorkspace(repoDir, DEFAULT_BRANCH);
|
|
159
|
+
|
|
160
|
+
// Verify the pushed remote state via an independent clone.
|
|
161
|
+
const dir = await checkout(root, upstream, DEFAULT_BRANCH);
|
|
162
|
+
// Existing files preserved verbatim.
|
|
163
|
+
expect(await fs.readFile(path.join(dir, 'access.md'), 'utf8')).toBe('CUSTOM ACCESS RULES');
|
|
164
|
+
expect(await fs.readFile(path.join(dir, 'roles.yaml'), 'utf8')).toContain('keep@example.com');
|
|
165
|
+
// Missing scaffolding added.
|
|
166
|
+
expect(await exists(path.join(dir, 'CLAUDE.md'))).toBe(true);
|
|
167
|
+
expect(await exists(path.join(dir, '.bevelignore'))).toBe(true);
|
|
168
|
+
// Sample content is NOT restored — the real KnowledgeBase already had content,
|
|
169
|
+
// so no placeholder .gitkeep is dropped into it, and no ExampleOntology appears.
|
|
170
|
+
expect(await exists(path.join(dir, 'KnowledgeBase/.gitkeep'))).toBe(false);
|
|
171
|
+
expect(await exists(path.join(dir, 'KnowledgeBase/ExampleOntology'))).toBe(false);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('topUpWorkspace is idempotent — a second load makes no new commit', async () => {
|
|
175
|
+
const upstream = await seededUpstream(PROTECTED, {
|
|
176
|
+
'roles.yaml': 'roles:\n Admin:\n - keep@example.com\n',
|
|
177
|
+
'KnowledgeBase/Real/Knowledge/.gitkeep': '',
|
|
178
|
+
'Skills/.gitkeep': '',
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const first = await checkout(root, upstream, DEFAULT_BRANCH);
|
|
182
|
+
await makeSeeder(upstream).topUpWorkspace(first, DEFAULT_BRANCH);
|
|
183
|
+
const after1 = await headCommitCount(root, upstream, DEFAULT_BRANCH);
|
|
184
|
+
|
|
185
|
+
// A later reload: fresh clone reflects the pushed scaffolding, so top-up
|
|
186
|
+
// finds nothing missing and makes no new commit.
|
|
187
|
+
const second = await checkout(root, upstream, DEFAULT_BRANCH);
|
|
188
|
+
await makeSeeder(upstream).topUpWorkspace(second, DEFAULT_BRANCH);
|
|
189
|
+
const after2 = await headCommitCount(root, upstream, DEFAULT_BRANCH);
|
|
190
|
+
|
|
191
|
+
expect(after2).toBe(after1);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('topUpWorkspace fills scaffolding on a non-protected feature branch too', async () => {
|
|
195
|
+
const upstream = await seededUpstream(PROTECTED, {
|
|
196
|
+
'roles.yaml': 'roles:\n Admin:\n - keep@example.com\n',
|
|
197
|
+
'KnowledgeBase/Real/Knowledge/.gitkeep': '',
|
|
198
|
+
'Skills/.gitkeep': '',
|
|
199
|
+
});
|
|
200
|
+
// Branch a feature off the default and load it.
|
|
201
|
+
const seed = await checkout(root, upstream, DEFAULT_BRANCH);
|
|
202
|
+
await git(seed, ['checkout', '-b', 'alice/feature']);
|
|
203
|
+
await git(seed, ['push', 'origin', 'alice/feature']);
|
|
204
|
+
|
|
205
|
+
const repoDir = await checkout(root, upstream, 'alice/feature');
|
|
206
|
+
await makeSeeder(upstream).topUpWorkspace(repoDir, 'alice/feature');
|
|
207
|
+
|
|
208
|
+
const dir = await checkout(root, upstream, 'alice/feature');
|
|
209
|
+
expect(await exists(path.join(dir, 'CLAUDE.md'))).toBe(true);
|
|
210
|
+
expect(await exists(path.join(dir, 'access.md'))).toBe(true);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { RoutineWritePolicyService } from '../routine-write-policy.js';
|
|
3
|
+
import { ToolError } from '../../tool-helpers/tool.contract.js';
|
|
4
|
+
|
|
5
|
+
const SID = 'watchlistcheck-gtm-run-1';
|
|
6
|
+
|
|
7
|
+
describe('RoutineWritePolicyService', () => {
|
|
8
|
+
it('allows any write when the session has no restriction', () => {
|
|
9
|
+
const policy = new RoutineWritePolicyService();
|
|
10
|
+
expect(() => policy.assertPathWritable(SID, 'knowledge-base/KnowledgeBase/Product/Knowledge/Foo.md')).not.toThrow();
|
|
11
|
+
expect(() => policy.assertUnrestricted(SID)).not.toThrow();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('allows only the restricted extensions and blocks everything else with a 403', () => {
|
|
15
|
+
const policy = new RoutineWritePolicyService();
|
|
16
|
+
policy.restrictToExtensions(SID, ['.html', '.htm']);
|
|
17
|
+
|
|
18
|
+
// Dashboard writes pass (case-insensitive).
|
|
19
|
+
expect(() => policy.assertPathWritable(SID, 'knowledge-base/KnowledgeBase/GTM/Dashboard.html')).not.toThrow();
|
|
20
|
+
expect(() => policy.assertPathWritable(SID, 'knowledge-base/KnowledgeBase/GTM/Dashboard.HTM')).not.toThrow();
|
|
21
|
+
|
|
22
|
+
// Graph nodes and any other path are refused.
|
|
23
|
+
for (const blocked of [
|
|
24
|
+
'knowledge-base/KnowledgeBase/Product/Knowledge/sc-b2g-no-self-billing.md',
|
|
25
|
+
'knowledge-base/CLAUDE.md',
|
|
26
|
+
'knowledge-base/KnowledgeBase/GTM/notes.txt',
|
|
27
|
+
'knowledge-base/KnowledgeBase/GTM', // a directory (mkdir) — no extension
|
|
28
|
+
]) {
|
|
29
|
+
const err = getThrown(() => policy.assertPathWritable(SID, blocked));
|
|
30
|
+
expect(err).toBeInstanceOf(ToolError);
|
|
31
|
+
expect((err as ToolError).status).toBe(403);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('never restricts a caller with no session id', () => {
|
|
36
|
+
const policy = new RoutineWritePolicyService();
|
|
37
|
+
policy.restrictToExtensions(SID, ['.html']);
|
|
38
|
+
// A different (or absent) session id is unaffected by SID's restriction.
|
|
39
|
+
expect(() => policy.assertPathWritable(undefined, 'anything.md')).not.toThrow();
|
|
40
|
+
expect(() => policy.assertPathWritable('other-session', 'anything.md')).not.toThrow();
|
|
41
|
+
expect(() => policy.assertUnrestricted(undefined)).not.toThrow();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('blocks the pathless shell tool for a restricted session', () => {
|
|
45
|
+
const policy = new RoutineWritePolicyService();
|
|
46
|
+
policy.restrictToExtensions(SID, ['.html']);
|
|
47
|
+
const err = getThrown(() => policy.assertUnrestricted(SID));
|
|
48
|
+
expect(err).toBeInstanceOf(ToolError);
|
|
49
|
+
expect((err as ToolError).status).toBe(403);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('clear() lifts the restriction', () => {
|
|
53
|
+
const policy = new RoutineWritePolicyService();
|
|
54
|
+
policy.restrictToExtensions(SID, ['.html']);
|
|
55
|
+
policy.clear(SID);
|
|
56
|
+
expect(() => policy.assertPathWritable(SID, 'foo.md')).not.toThrow();
|
|
57
|
+
expect(() => policy.assertUnrestricted(SID)).not.toThrow();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
function getThrown(fn: () => void): unknown {
|
|
62
|
+
try {
|
|
63
|
+
fn();
|
|
64
|
+
} catch (e) {
|
|
65
|
+
return e;
|
|
66
|
+
}
|
|
67
|
+
throw new Error('expected the function to throw, but it did not');
|
|
68
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
recordOntologyRead,
|
|
5
|
+
assertOntologyWriteAllowed,
|
|
6
|
+
assertShellAllowedWithinOntology,
|
|
7
|
+
MissingSessionError,
|
|
8
|
+
type SessionOntologyGate,
|
|
9
|
+
} from '../session-ontology.gate.js';
|
|
10
|
+
import type { ToolContext } from '../../tool-helpers/tool.contract.js';
|
|
11
|
+
import type { ISessionOntologyService, OperationDecision } from '../../workflow/session-ontology.service.js';
|
|
12
|
+
import { WorkflowHooks } from '../../workflow/workflow-hooks.js';
|
|
13
|
+
import { ontologyOf } from '../../../shared/kb-layout.js';
|
|
14
|
+
|
|
15
|
+
const KB = 'knowledge-base';
|
|
16
|
+
const P_FILE = 'KnowledgeBase/Product/Knowledge/Foo.md';
|
|
17
|
+
const PL_FILE = 'KnowledgeBase/Platform/Knowledge/Bar.md';
|
|
18
|
+
const NEUTRAL = 'access.md';
|
|
19
|
+
const RECOVERY_EMAIL = 'recovery-bot@bevel.local';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* In-memory stand-in for the touched-set service — applies the real
|
|
23
|
+
* reads-record / writes-block-once-multi rule against a per-session set, so the
|
|
24
|
+
* gate's interaction with it is exercised end to end without a DB.
|
|
25
|
+
*/
|
|
26
|
+
function makeFakeService(): ISessionOntologyService {
|
|
27
|
+
const touched = new Map<string, Set<string>>();
|
|
28
|
+
const setFor = (s: string) => touched.get(s) ?? new Set<string>();
|
|
29
|
+
return {
|
|
30
|
+
async checkOperation(sessionId, wsPath, isWrite): Promise<OperationDecision> {
|
|
31
|
+
const ont = ontologyOf(wsPath, KB);
|
|
32
|
+
const set = setFor(sessionId);
|
|
33
|
+
if (ont === null) return { allow: true, touched: [...set].sort() };
|
|
34
|
+
if (isWrite) {
|
|
35
|
+
const spanned = new Set(set).add(ont);
|
|
36
|
+
if (spanned.size > 1) {
|
|
37
|
+
return {
|
|
38
|
+
allow: false,
|
|
39
|
+
reason: set.size >= 2 ? 'multi-ontology' : 'different-ontology',
|
|
40
|
+
touched: [...set].sort(),
|
|
41
|
+
attempted: ont,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
set.add(ont);
|
|
46
|
+
touched.set(sessionId, set);
|
|
47
|
+
return { allow: true, touched: [...set].sort() };
|
|
48
|
+
},
|
|
49
|
+
checkOntology: async () => ({ allow: true, touched: [] }),
|
|
50
|
+
getTouched: async (s) => [...setFor(s)].sort(),
|
|
51
|
+
delete: async (s) => { touched.delete(s); },
|
|
52
|
+
sweepOlderThan: async () => 0,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Build a gate wired the way the CORE composition wires it: the fake
|
|
58
|
+
* touched-set service plus an EMPTY hooks registry. Core registers no
|
|
59
|
+
* `preWrite` hook, so the gate only TRACKS touches and never blocks — the
|
|
60
|
+
* blocking assertions (the ontology-block hook the enterprise composition
|
|
61
|
+
* root registers) live with that hook in the enterprise repo.
|
|
62
|
+
*/
|
|
63
|
+
function makeGate(): SessionOntologyGate {
|
|
64
|
+
const service = makeFakeService();
|
|
65
|
+
const hooks = new WorkflowHooks();
|
|
66
|
+
return { service, enabled: true, kbDirName: KB, recoveryBotEmail: RECOVERY_EMAIL, hooks };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function ctx(overrides: Partial<ToolContext> = {}): ToolContext {
|
|
70
|
+
return {
|
|
71
|
+
user: { id: 'u1', email: 'dev@bevel.local', name: 'Dev' },
|
|
72
|
+
scope: 'write',
|
|
73
|
+
source: 'internal',
|
|
74
|
+
sessionId: 's1',
|
|
75
|
+
abortSignal: new AbortController().signal,
|
|
76
|
+
workspaceService: {} as never,
|
|
77
|
+
workflowService: {} as never,
|
|
78
|
+
events: {} as never,
|
|
79
|
+
getFilesystem: async () => ({} as never),
|
|
80
|
+
...overrides,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
describe('recordOntologyRead', () => {
|
|
85
|
+
let gate: SessionOntologyGate;
|
|
86
|
+
|
|
87
|
+
beforeEach(() => {
|
|
88
|
+
gate = makeGate();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('does nothing when the flag is disabled', async () => {
|
|
92
|
+
gate.enabled = false;
|
|
93
|
+
await expect(recordOntologyRead(gate, ctx(), P_FILE)).resolves.toBeUndefined();
|
|
94
|
+
expect(await gate.service.getTouched('s1')).toEqual([]);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('skips neutral paths (no record)', async () => {
|
|
98
|
+
await expect(recordOntologyRead(gate, ctx(), NEUTRAL)).resolves.toBeUndefined();
|
|
99
|
+
expect(await gate.service.getTouched('s1')).toEqual([]);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('skips non-agent (browser session) callers', async () => {
|
|
103
|
+
await expect(
|
|
104
|
+
recordOntologyRead(gate, ctx({ source: 'session', sessionId: undefined }), P_FILE),
|
|
105
|
+
).resolves.toBeUndefined();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('skips the recovery bot by identity', async () => {
|
|
109
|
+
await expect(
|
|
110
|
+
recordOntologyRead(
|
|
111
|
+
gate,
|
|
112
|
+
ctx({ user: { id: 'bot', email: 'Recovery-Bot@Bevel.Local', name: 'bot' }, sessionId: undefined }),
|
|
113
|
+
PL_FILE,
|
|
114
|
+
),
|
|
115
|
+
).resolves.toBeUndefined();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('fails closed when an agent read of a named path has no session id', async () => {
|
|
119
|
+
await expect(recordOntologyRead(gate, ctx({ sessionId: undefined }), P_FILE)).rejects.toBeInstanceOf(
|
|
120
|
+
MissingSessionError,
|
|
121
|
+
);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('allows a neutral read without a session id', async () => {
|
|
125
|
+
await expect(recordOntologyRead(gate, ctx({ sessionId: undefined }), NEUTRAL)).resolves.toBeUndefined();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('records a read and allows it', async () => {
|
|
129
|
+
await recordOntologyRead(gate, ctx(), P_FILE);
|
|
130
|
+
expect(await gate.service.getTouched('s1')).toEqual(['KnowledgeBase/Product']);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('allows reads across ontologies (recording both)', async () => {
|
|
134
|
+
await recordOntologyRead(gate, ctx(), P_FILE);
|
|
135
|
+
await expect(recordOntologyRead(gate, ctx(), PL_FILE)).resolves.toBeUndefined();
|
|
136
|
+
expect(await gate.service.getTouched('s1')).toEqual(['KnowledgeBase/Platform', 'KnowledgeBase/Product']);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('never blocks — a read into a second ontology still passes (delete_file relies on this)', async () => {
|
|
140
|
+
await recordOntologyRead(gate, ctx(), P_FILE);
|
|
141
|
+
// A delete_file in a different ontology records its touch but never throws.
|
|
142
|
+
await expect(recordOntologyRead(gate, ctx(), PL_FILE)).resolves.toBeUndefined();
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
describe('assertOntologyWriteAllowed', () => {
|
|
147
|
+
let gate: SessionOntologyGate;
|
|
148
|
+
|
|
149
|
+
beforeEach(() => {
|
|
150
|
+
gate = makeGate();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('does nothing when the flag is disabled', async () => {
|
|
154
|
+
gate.enabled = false;
|
|
155
|
+
// Even a cross-ontology write must pass when disabled.
|
|
156
|
+
await recordOntologyRead(gate, ctx(), P_FILE);
|
|
157
|
+
await expect(assertOntologyWriteAllowed(gate, ctx(), PL_FILE)).resolves.toBeUndefined();
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('skips neutral paths (no record, no block)', async () => {
|
|
161
|
+
await expect(assertOntologyWriteAllowed(gate, ctx(), NEUTRAL)).resolves.toBeUndefined();
|
|
162
|
+
expect(await gate.service.getTouched('s1')).toEqual([]);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('fails closed when an agent write of a named path has no session id', async () => {
|
|
166
|
+
await expect(assertOntologyWriteAllowed(gate, ctx({ sessionId: undefined }), P_FILE)).rejects.toBeInstanceOf(
|
|
167
|
+
MissingSessionError,
|
|
168
|
+
);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('allows a write confined to the one touched ontology', async () => {
|
|
172
|
+
await recordOntologyRead(gate, ctx(), P_FILE);
|
|
173
|
+
await expect(assertOntologyWriteAllowed(gate, ctx(), P_FILE)).resolves.toBeUndefined();
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// NOTE (core split): the "blocks a write to a different ontology" and
|
|
177
|
+
// "blocks ALL writes once the session has read across two ontologies" cases
|
|
178
|
+
// moved with the ontology-block hook (`registerOntologyBlockHook`) to the
|
|
179
|
+
// enterprise repo — core registers no preWrite hook, so a core-only
|
|
180
|
+
// deployment TRACKS but never blocks. The tests below pin exactly that.
|
|
181
|
+
|
|
182
|
+
it('core: allows a write to a different ontology (tracking only, no block hook)', async () => {
|
|
183
|
+
await recordOntologyRead(gate, ctx(), P_FILE);
|
|
184
|
+
await expect(assertOntologyWriteAllowed(gate, ctx(), PL_FILE)).resolves.toBeUndefined();
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('core: still allows writes after reading across two ontologies (no block hook)', async () => {
|
|
188
|
+
await recordOntologyRead(gate, ctx(), P_FILE);
|
|
189
|
+
await recordOntologyRead(gate, ctx(), PL_FILE);
|
|
190
|
+
await expect(assertOntologyWriteAllowed(gate, ctx(), P_FILE)).resolves.toBeUndefined();
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
describe('assertShellAllowedWithinOntology (shell / no-path tools)', () => {
|
|
195
|
+
let gate: SessionOntologyGate;
|
|
196
|
+
|
|
197
|
+
beforeEach(() => {
|
|
198
|
+
gate = makeGate();
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('allows a fresh session (nothing touched)', async () => {
|
|
202
|
+
await expect(assertShellAllowedWithinOntology(gate, ctx())).resolves.toBeUndefined();
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('allows a session confined to a single ontology', async () => {
|
|
206
|
+
await recordOntologyRead(gate, ctx(), P_FILE);
|
|
207
|
+
await expect(assertShellAllowedWithinOntology(gate, ctx())).resolves.toBeUndefined();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// NOTE (core split): the "blocks once the session has crossed into two
|
|
211
|
+
// ontologies" case moved with the enterprise ontology-block hook. Core
|
|
212
|
+
// registers no preWrite hook, so shell is never refused here.
|
|
213
|
+
it('core: allows shell even after crossing into two ontologies (no block hook)', async () => {
|
|
214
|
+
await recordOntologyRead(gate, ctx(), P_FILE);
|
|
215
|
+
await recordOntologyRead(gate, ctx(), PL_FILE);
|
|
216
|
+
await expect(assertShellAllowedWithinOntology(gate, ctx())).resolves.toBeUndefined();
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('does nothing when the flag is disabled', async () => {
|
|
220
|
+
gate.enabled = false;
|
|
221
|
+
await gate.service.checkOperation('s1', P_FILE, false);
|
|
222
|
+
await gate.service.checkOperation('s1', PL_FILE, false);
|
|
223
|
+
await expect(assertShellAllowedWithinOntology(gate, ctx())).resolves.toBeUndefined();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('exempts the recovery bot', async () => {
|
|
227
|
+
await gate.service.checkOperation('s1', P_FILE, false);
|
|
228
|
+
await gate.service.checkOperation('s1', PL_FILE, false);
|
|
229
|
+
await expect(
|
|
230
|
+
assertShellAllowedWithinOntology(gate, ctx({ user: { id: 'bot', email: RECOVERY_EMAIL, name: 'bot' } })),
|
|
231
|
+
).resolves.toBeUndefined();
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('allows when there is no session id (nothing to evaluate)', async () => {
|
|
235
|
+
await expect(assertShellAllowedWithinOntology(gate, ctx({ sessionId: undefined }))).resolves.toBeUndefined();
|
|
236
|
+
});
|
|
237
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
5
|
+
import { SpillStore } from '../spill-store.js';
|
|
6
|
+
|
|
7
|
+
describe('SpillStore', () => {
|
|
8
|
+
let root: string;
|
|
9
|
+
let store: SpillStore;
|
|
10
|
+
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
root = await mkdtemp(join(tmpdir(), 'spill-test-'));
|
|
13
|
+
store = new SpillStore(root);
|
|
14
|
+
});
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
await rm(root, { recursive: true, force: true });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('round-trips content under a recognisable spill ref', async () => {
|
|
20
|
+
const { ref, bytes } = await store.write('hello world');
|
|
21
|
+
expect(store.isSpillRef(ref)).toBe(true);
|
|
22
|
+
expect(ref.startsWith('__tool_chain_spill__/')).toBe(true);
|
|
23
|
+
expect(bytes).toBe('hello world'.length);
|
|
24
|
+
expect(await store.read(ref)).toBe('hello world');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('slices by offset/limit (byte range, read off disk)', async () => {
|
|
28
|
+
const { ref } = await store.write('0123456789');
|
|
29
|
+
expect(await store.read(ref, 3)).toBe('3456789');
|
|
30
|
+
expect(await store.read(ref, 2, 4)).toBe('2345');
|
|
31
|
+
expect(await store.read(ref, 0, 0)).toBe('');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('does not treat a normal workspace path as a spill ref', () => {
|
|
35
|
+
expect(store.isSpillRef('docs/readme.md')).toBe(false);
|
|
36
|
+
expect(store.isSpillRef('knowledge-base/CLAUDE.md')).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('rejects a ref whose id tries to escape the store', async () => {
|
|
40
|
+
await expect(store.read('__tool_chain_spill__/../secret')).rejects.toThrow(/invalid spill ref/i);
|
|
41
|
+
await expect(store.read('__tool_chain_spill__/a/b.json')).rejects.toThrow(/invalid spill ref/i);
|
|
42
|
+
});
|
|
43
|
+
});
|