@bevel-software/platform-core-backend 0.19.0 → 0.21.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/dist/core/catalog-cache-invalidation.d.ts +7 -2
- package/dist/core/catalog-cache-invalidation.d.ts.map +1 -1
- package/dist/core/catalog-cache-invalidation.js +8 -9
- package/dist/core/catalog-cache-invalidation.js.map +1 -1
- package/dist/core/core-ports.d.ts +19 -0
- package/dist/core/core-ports.d.ts.map +1 -1
- package/dist/core/core-ports.js.map +1 -1
- package/dist/core/create-core-server.d.ts +2 -0
- package/dist/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +45 -105
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +33 -5
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +146 -82
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core/lifecycle.d.ts +74 -28
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +157 -20
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/core/public-config.d.ts +5 -1
- package/dist/core/public-config.d.ts.map +1 -1
- package/dist/core/public-config.js +7 -5
- package/dist/core/public-config.js.map +1 -1
- package/dist/core-config.d.ts +95 -1
- package/dist/core-config.d.ts.map +1 -1
- package/dist/core-config.js +24 -8
- package/dist/core-config.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +18 -1
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +19 -8
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/access.routes.d.ts +2 -1
- package/dist/modules/access/access.routes.d.ts.map +1 -1
- package/dist/modules/access/access.routes.js +10 -10
- package/dist/modules/access/access.routes.js.map +1 -1
- package/dist/modules/access/change-read-gate.d.ts +6 -3
- package/dist/modules/access/change-read-gate.d.ts.map +1 -1
- package/dist/modules/access/change-read-gate.js +9 -6
- package/dist/modules/access/change-read-gate.js.map +1 -1
- package/dist/modules/access/creator-access.d.ts +4 -2
- package/dist/modules/access/creator-access.d.ts.map +1 -1
- package/dist/modules/access/creator-access.js +7 -4
- package/dist/modules/access/creator-access.js.map +1 -1
- package/dist/modules/agent-instructions/read-preamble.d.ts +2 -1
- package/dist/modules/agent-instructions/read-preamble.d.ts.map +1 -1
- package/dist/modules/agent-instructions/read-preamble.js +6 -9
- package/dist/modules/agent-instructions/read-preamble.js.map +1 -1
- package/dist/modules/audit/agent-audit.service.d.ts +54 -0
- package/dist/modules/audit/agent-audit.service.d.ts.map +1 -0
- package/dist/modules/audit/agent-audit.service.js +290 -0
- package/dist/modules/audit/agent-audit.service.js.map +1 -0
- package/dist/modules/audit/agent-rest-audit.middleware.d.ts +40 -0
- package/dist/modules/audit/agent-rest-audit.middleware.d.ts.map +1 -0
- package/dist/modules/audit/agent-rest-audit.middleware.js +75 -0
- package/dist/modules/audit/agent-rest-audit.middleware.js.map +1 -0
- package/dist/modules/audit/audit.contract.d.ts +145 -0
- package/dist/modules/audit/audit.contract.d.ts.map +1 -0
- package/dist/modules/audit/audit.contract.js +35 -0
- package/dist/modules/audit/audit.contract.js.map +1 -0
- package/dist/modules/audit/audit.routes.d.ts +21 -0
- package/dist/modules/audit/audit.routes.d.ts.map +1 -0
- package/dist/modules/audit/audit.routes.js +157 -0
- package/dist/modules/audit/audit.routes.js.map +1 -0
- package/dist/modules/audit/event-classifier.d.ts +52 -0
- package/dist/modules/audit/event-classifier.d.ts.map +1 -0
- package/dist/modules/audit/event-classifier.js +123 -0
- package/dist/modules/audit/event-classifier.js.map +1 -0
- package/dist/modules/audit/index.d.ts +7 -0
- package/dist/modules/audit/index.d.ts.map +1 -0
- package/dist/modules/audit/index.js +7 -0
- package/dist/modules/audit/index.js.map +1 -0
- package/dist/modules/audit/request-audit.d.ts +57 -0
- package/dist/modules/audit/request-audit.d.ts.map +1 -0
- package/dist/modules/audit/request-audit.js +117 -0
- package/dist/modules/audit/request-audit.js.map +1 -0
- package/dist/modules/auth/account-admission.d.ts +40 -0
- package/dist/modules/auth/account-admission.d.ts.map +1 -0
- package/dist/modules/auth/account-admission.js +17 -0
- package/dist/modules/auth/account-admission.js.map +1 -0
- package/dist/modules/auth/account.routes.d.ts.map +1 -1
- package/dist/modules/auth/account.routes.js +4 -1
- package/dist/modules/auth/account.routes.js.map +1 -1
- package/dist/modules/auth/auth.service.d.ts +19 -1
- package/dist/modules/auth/auth.service.d.ts.map +1 -1
- package/dist/modules/auth/auth.service.js +33 -1
- package/dist/modules/auth/auth.service.js.map +1 -1
- package/dist/modules/auth/oidc-auth-provider.d.ts.map +1 -1
- package/dist/modules/auth/oidc-auth-provider.js +9 -0
- package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
- package/dist/modules/connection-probe/connection-probe.service.d.ts +13 -1
- package/dist/modules/connection-probe/connection-probe.service.d.ts.map +1 -1
- package/dist/modules/connection-probe/connection-probe.service.js +10 -2
- package/dist/modules/connection-probe/connection-probe.service.js.map +1 -1
- package/dist/modules/database/advisory-lock.d.ts +17 -0
- package/dist/modules/database/advisory-lock.d.ts.map +1 -1
- package/dist/modules/database/advisory-lock.js +24 -3
- package/dist/modules/database/advisory-lock.js.map +1 -1
- package/dist/modules/database/connection.d.ts +67 -2
- package/dist/modules/database/connection.d.ts.map +1 -1
- package/dist/modules/database/connection.js +118 -12
- package/dist/modules/database/connection.js.map +1 -1
- package/dist/modules/database/core-schema.d.ts +414 -0
- package/dist/modules/database/core-schema.d.ts.map +1 -1
- package/dist/modules/database/core-schema.js +99 -0
- package/dist/modules/database/core-schema.js.map +1 -1
- package/dist/modules/database/migrate.d.ts +1 -1
- package/dist/modules/database/migrate.d.ts.map +1 -1
- package/dist/modules/database/migrate.js +27 -3
- package/dist/modules/database/migrate.js.map +1 -1
- package/dist/modules/diff/diff.service.d.ts.map +1 -1
- package/dist/modules/diff/diff.service.js +6 -1
- package/dist/modules/diff/diff.service.js.map +1 -1
- package/dist/modules/kb-fs/branch-name.d.ts +0 -1
- package/dist/modules/kb-fs/branch-name.d.ts.map +1 -1
- package/dist/modules/kb-fs/branch-name.js +3 -3
- package/dist/modules/kb-fs/branch-name.js.map +1 -1
- package/dist/modules/kb-fs/clone-config.d.ts +9 -8
- package/dist/modules/kb-fs/clone-config.d.ts.map +1 -1
- package/dist/modules/kb-fs/clone-config.js +14 -12
- package/dist/modules/kb-fs/clone-config.js.map +1 -1
- package/dist/modules/kb-fs/git-guarded-filesystem.d.ts +9 -1
- package/dist/modules/kb-fs/git-guarded-filesystem.d.ts.map +1 -1
- package/dist/modules/kb-fs/git-guarded-filesystem.js +16 -3
- package/dist/modules/kb-fs/git-guarded-filesystem.js.map +1 -1
- package/dist/modules/mcp/mcp-auth.middleware.d.ts +1 -0
- package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
- package/dist/modules/mcp/mcp-auth.middleware.js +32 -0
- package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
- package/dist/modules/mcp/mcp.routes.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.routes.js +8 -1
- package/dist/modules/mcp/mcp.routes.js.map +1 -1
- package/dist/modules/mcp/mcp.service.d.ts +16 -1
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +52 -9
- package/dist/modules/mcp/mcp.service.js.map +1 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +59 -0
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js +180 -8
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
- package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts +4 -4
- package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts.map +1 -1
- package/dist/modules/plugins/compile/marketplace-compiler.service.js +7 -10
- package/dist/modules/plugins/compile/marketplace-compiler.service.js.map +1 -1
- package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts +4 -1
- package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts.map +1 -1
- package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js +5 -3
- package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js.map +1 -1
- package/dist/modules/plugins/discovery/kb-plugin-source.d.ts +6 -1
- package/dist/modules/plugins/discovery/kb-plugin-source.d.ts.map +1 -1
- package/dist/modules/plugins/discovery/kb-plugin-source.js +14 -9
- package/dist/modules/plugins/discovery/kb-plugin-source.js.map +1 -1
- package/dist/modules/plugins/discovery/native.source.d.ts +4 -1
- package/dist/modules/plugins/discovery/native.source.d.ts.map +1 -1
- package/dist/modules/plugins/discovery/native.source.js +4 -2
- package/dist/modules/plugins/discovery/native.source.js.map +1 -1
- package/dist/modules/plugins/index.d.ts +1 -1
- package/dist/modules/plugins/index.d.ts.map +1 -1
- package/dist/modules/plugins/index.js +1 -1
- package/dist/modules/plugins/index.js.map +1 -1
- package/dist/modules/plugins/join-request-jobs.service.d.ts +3 -1
- package/dist/modules/plugins/join-request-jobs.service.d.ts.map +1 -1
- package/dist/modules/plugins/join-request-jobs.service.js +6 -6
- package/dist/modules/plugins/join-request-jobs.service.js.map +1 -1
- package/dist/modules/plugins/join-requests.service.d.ts +3 -1
- package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
- package/dist/modules/plugins/join-requests.service.js +9 -8
- package/dist/modules/plugins/join-requests.service.js.map +1 -1
- package/dist/modules/plugins/plugin-links.d.ts +65 -10
- package/dist/modules/plugins/plugin-links.d.ts.map +1 -1
- package/dist/modules/plugins/plugin-links.js +136 -31
- package/dist/modules/plugins/plugin-links.js.map +1 -1
- package/dist/modules/plugins/plugin-links.service.d.ts +107 -5
- package/dist/modules/plugins/plugin-links.service.d.ts.map +1 -1
- package/dist/modules/plugins/plugin-links.service.js +151 -21
- package/dist/modules/plugins/plugin-links.service.js.map +1 -1
- package/dist/modules/plugins/plugin-provision.service.d.ts +10 -3
- package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
- package/dist/modules/plugins/plugin-provision.service.js +33 -26
- package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
- package/dist/modules/plugins/plugin-rename.service.d.ts +4 -2
- package/dist/modules/plugins/plugin-rename.service.d.ts.map +1 -1
- package/dist/modules/plugins/plugin-rename.service.js +10 -12
- package/dist/modules/plugins/plugin-rename.service.js.map +1 -1
- package/dist/modules/plugins/plugins.routes.d.ts +3 -0
- package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.routes.js +45 -15
- package/dist/modules/plugins/plugins.routes.js.map +1 -1
- package/dist/modules/plugins/plugins.service.d.ts +4 -4
- package/dist/modules/plugins/plugins.service.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.service.js +7 -10
- package/dist/modules/plugins/plugins.service.js.map +1 -1
- package/dist/modules/plugins/teams.routes.d.ts +4 -1
- package/dist/modules/plugins/teams.routes.d.ts.map +1 -1
- package/dist/modules/plugins/teams.routes.js +11 -9
- package/dist/modules/plugins/teams.routes.js.map +1 -1
- package/dist/modules/secrets-vault/index.d.ts +1 -1
- package/dist/modules/secrets-vault/index.d.ts.map +1 -1
- package/dist/modules/secrets-vault/index.js +1 -1
- package/dist/modules/secrets-vault/index.js.map +1 -1
- package/dist/modules/secrets-vault/secrets-variable-loader.d.ts +29 -11
- package/dist/modules/secrets-vault/secrets-variable-loader.d.ts.map +1 -1
- package/dist/modules/secrets-vault/secrets-variable-loader.js +46 -21
- package/dist/modules/secrets-vault/secrets-variable-loader.js.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +3 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.js +4 -6
- package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
- package/dist/modules/settings/deployment-settings.service.d.ts +22 -10
- package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
- package/dist/modules/settings/deployment-settings.service.js +52 -28
- package/dist/modules/settings/deployment-settings.service.js.map +1 -1
- package/dist/modules/settings/setup.routes.d.ts +9 -2
- package/dist/modules/settings/setup.routes.d.ts.map +1 -1
- package/dist/modules/settings/setup.routes.js +20 -14
- package/dist/modules/settings/setup.routes.js.map +1 -1
- package/dist/modules/skills/allowed-tools-check.d.ts +4 -3
- package/dist/modules/skills/allowed-tools-check.d.ts.map +1 -1
- package/dist/modules/skills/allowed-tools-check.js +8 -8
- package/dist/modules/skills/allowed-tools-check.js.map +1 -1
- package/dist/modules/skills/pending-skills.service.d.ts +3 -1
- package/dist/modules/skills/pending-skills.service.d.ts.map +1 -1
- package/dist/modules/skills/pending-skills.service.js +9 -6
- package/dist/modules/skills/pending-skills.service.js.map +1 -1
- package/dist/modules/skills/skill-access-requests.routes.d.ts +2 -1
- package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -1
- package/dist/modules/skills/skill-access-requests.routes.js +6 -6
- package/dist/modules/skills/skill-access-requests.routes.js.map +1 -1
- package/dist/modules/skills/skills.routes.d.ts +4 -1
- package/dist/modules/skills/skills.routes.d.ts.map +1 -1
- package/dist/modules/skills/skills.routes.js +4 -4
- package/dist/modules/skills/skills.routes.js.map +1 -1
- package/dist/modules/skills/skills.service.d.ts +4 -2
- package/dist/modules/skills/skills.service.d.ts.map +1 -1
- package/dist/modules/skills/skills.service.js +13 -11
- package/dist/modules/skills/skills.service.js.map +1 -1
- package/dist/modules/tool-auth/external-api-key.interface.d.ts +21 -5
- package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -1
- package/dist/modules/tool-auth/external-api-key.interface.js.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.d.ts +1 -0
- package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.js +22 -9
- package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
- package/dist/modules/tool-auth/internal-token.service.d.ts +10 -0
- package/dist/modules/tool-auth/internal-token.service.d.ts.map +1 -1
- package/dist/modules/tool-auth/internal-token.service.js +1 -0
- package/dist/modules/tool-auth/internal-token.service.js.map +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts +8 -0
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.js +9 -1
- package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.d.ts +2 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.d.ts.map +1 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.js +6 -5
- package/dist/modules/tool-manuals/mcp-json-discovery.js.map +1 -1
- package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts +4 -2
- package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/mcp-server-edit.service.js +12 -10
- package/dist/modules/tool-manuals/mcp-server-edit.service.js.map +1 -1
- package/dist/modules/tool-manuals/pending-tools.service.d.ts +3 -1
- package/dist/modules/tool-manuals/pending-tools.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/pending-tools.service.js +19 -16
- package/dist/modules/tool-manuals/pending-tools.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-delete.service.d.ts +4 -2
- package/dist/modules/tool-manuals/tool-delete.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-delete.service.js +14 -12
- package/dist/modules/tool-manuals/tool-delete.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +3 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.js +7 -7
- package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts +4 -2
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +15 -12
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +3 -0
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +4 -6
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +3 -2
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.js +9 -9
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +11 -5
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +23 -14
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/git/node-git-runner.d.ts +26 -2
- package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -1
- package/dist/modules/workflow/git/node-git-runner.js +35 -5
- package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.js +9 -4
- package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
- package/dist/modules/workflow/session-ontology.service.d.ts +6 -1
- package/dist/modules/workflow/session-ontology.service.d.ts.map +1 -1
- package/dist/modules/workflow/session-ontology.service.js +6 -2
- package/dist/modules/workflow/session-ontology.service.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts +8 -3
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +33 -23
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/session-ontology.gate.d.ts +3 -1
- package/dist/modules/workspace/session-ontology.gate.d.ts.map +1 -1
- package/dist/modules/workspace/session-ontology.gate.js +3 -3
- package/dist/modules/workspace/session-ontology.gate.js.map +1 -1
- package/dist/modules/workspace/startup/kb-git.d.ts +4 -3
- package/dist/modules/workspace/startup/kb-git.d.ts.map +1 -1
- package/dist/modules/workspace/startup/kb-git.js +15 -13
- package/dist/modules/workspace/startup/kb-git.js.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts +5 -8
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.js +35 -38
- package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
- package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts +7 -1
- package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js +23 -16
- package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/personal-spaces.step.d.ts +7 -1
- package/dist/modules/workspace/startup/steps/personal-spaces.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/personal-spaces.step.js +12 -5
- package/dist/modules/workspace/startup/steps/personal-spaces.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/plugin-display-names.step.d.ts +7 -1
- package/dist/modules/workspace/startup/steps/plugin-display-names.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/plugin-display-names.step.js +12 -5
- package/dist/modules/workspace/startup/steps/plugin-display-names.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts +7 -1
- package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/plugin-manifests.step.js +12 -5
- package/dist/modules/workspace/startup/steps/plugin-manifests.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts +4 -1
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.js +14 -11
- package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts +17 -3
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-files.step.js +36 -30
- package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.d.ts +6 -1
- package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.js +10 -6
- package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
- package/dist/modules/workspace/workspace.routes.d.ts +2 -1
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.routes.js +8 -7
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +26 -12
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +41 -28
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts +2 -1
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +69 -31
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/modules/workspace/write-denial.d.ts +3 -2
- package/dist/modules/workspace/write-denial.d.ts.map +1 -1
- package/dist/modules/workspace/write-denial.js +6 -5
- package/dist/modules/workspace/write-denial.js.map +1 -1
- package/dist/shared/git-internals.d.ts +7 -1
- package/dist/shared/git-internals.d.ts.map +1 -1
- package/dist/shared/git-internals.js +67 -9
- package/dist/shared/git-internals.js.map +1 -1
- package/dist/shared/git.contract.d.ts +52 -7
- package/dist/shared/git.contract.d.ts.map +1 -1
- package/dist/shared/git.contract.js +30 -8
- package/dist/shared/git.contract.js.map +1 -1
- package/dist/shared/kb-context.d.ts +76 -0
- package/dist/shared/kb-context.d.ts.map +1 -0
- package/dist/shared/kb-context.js +108 -0
- package/dist/shared/kb-context.js.map +1 -0
- package/dist/shared/kb-layout.d.ts +3 -2
- package/dist/shared/kb-layout.d.ts.map +1 -1
- package/dist/shared/kb-layout.js +4 -3
- package/dist/shared/kb-layout.js.map +1 -1
- package/dist/shared/kb-layout.test.js +35 -27
- package/dist/shared/kb-layout.test.js.map +1 -1
- package/dist/shared/pending-proposals.d.ts +4 -1
- package/dist/shared/pending-proposals.d.ts.map +1 -1
- package/dist/shared/pending-proposals.js +3 -4
- package/dist/shared/pending-proposals.js.map +1 -1
- package/dist/shared/redact-secret.d.ts +5 -5
- package/dist/shared/redact-secret.js +5 -5
- package/dist/tenancy/index.d.ts +13 -0
- package/dist/tenancy/index.d.ts.map +1 -0
- package/dist/tenancy/index.js +13 -0
- package/dist/tenancy/index.js.map +1 -0
- package/dist/tenancy/static-tenant-source.d.ts +98 -0
- package/dist/tenancy/static-tenant-source.d.ts.map +1 -0
- package/dist/tenancy/static-tenant-source.js +220 -0
- package/dist/tenancy/static-tenant-source.js.map +1 -0
- package/dist/tenancy/tenant-host.d.ts +80 -0
- package/dist/tenancy/tenant-host.d.ts.map +1 -0
- package/dist/tenancy/tenant-host.js +217 -0
- package/dist/tenancy/tenant-host.js.map +1 -0
- package/dist/tenancy/tenant-runtime.d.ts +91 -0
- package/dist/tenancy/tenant-runtime.d.ts.map +1 -0
- package/dist/tenancy/tenant-runtime.js +174 -0
- package/dist/tenancy/tenant-runtime.js.map +1 -0
- package/dist/tenancy/tenant-secrets.d.ts +24 -0
- package/dist/tenancy/tenant-secrets.d.ts.map +1 -0
- package/dist/tenancy/tenant-secrets.js +30 -0
- package/dist/tenancy/tenant-secrets.js.map +1 -0
- package/dist/tenancy/tenant-source.contract.d.ts +45 -0
- package/dist/tenancy/tenant-source.contract.d.ts.map +1 -0
- package/dist/tenancy/tenant-source.contract.js +21 -0
- package/dist/tenancy/tenant-source.contract.js.map +1 -0
- package/migrations/0000_core_init.sql +14 -14
- package/migrations/0003_deployment_settings.sql +1 -1
- package/migrations/0005_github_facade.sql +1 -1
- package/migrations/0012_agent_audit.sql +41 -0
- package/migrations/0013_agent_identity_and_key_soft_delete.sql +29 -0
- package/migrations/meta/0012_snapshot.json +2247 -0
- package/migrations/meta/0013_snapshot.json +2259 -0
- package/migrations/meta/_journal.json +14 -0
- package/package.json +4 -4
- package/src/__tests__/branch-model.test.ts +7 -6
- package/src/__tests__/kb-context.ts +30 -0
- package/src/__tests__/kb-layout-config.test.ts +35 -30
- package/src/core/__tests__/catalog-cache-invalidation.test.ts +2 -1
- package/src/core/__tests__/lifecycle.test.ts +78 -1
- package/src/core/__tests__/public-config.test.ts +5 -1
- package/src/core/catalog-cache-invalidation.ts +16 -11
- package/src/core/core-ports.ts +19 -0
- package/src/core/create-core-server.ts +55 -106
- package/src/core/create-core-services.ts +193 -95
- package/src/core/lifecycle.ts +214 -29
- package/src/core/public-config.ts +8 -5
- package/src/core-config.ts +107 -8
- package/src/index.ts +25 -2
- package/src/modules/access/__tests__/access-control.admin-root-floor.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.batch.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.folder-governs.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.group-grant.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.overrides.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.proposal-branch.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.prospective.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.revoke.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +2 -1
- package/src/modules/access/__tests__/change-read-gate.test.ts +13 -11
- package/src/modules/access/__tests__/creator-access.test.ts +3 -2
- package/src/modules/access/__tests__/roles.routes.test.ts +2 -1
- package/src/modules/access/access-control.service.ts +20 -6
- package/src/modules/access/access.routes.ts +10 -13
- package/src/modules/access/change-read-gate.ts +10 -4
- package/src/modules/access/creator-access.ts +7 -2
- package/src/modules/agent-instructions/__tests__/read-preamble.test.ts +13 -12
- package/src/modules/agent-instructions/read-preamble.ts +10 -12
- package/src/modules/audit/__tests__/agent-audit.service.test.ts +370 -0
- package/src/modules/audit/__tests__/agent-rest-audit.middleware.test.ts +113 -0
- package/src/modules/audit/__tests__/audit.routes.test.ts +201 -0
- package/src/modules/audit/__tests__/event-classifier.test.ts +121 -0
- package/src/modules/audit/agent-audit.service.ts +316 -0
- package/src/modules/audit/agent-rest-audit.middleware.ts +83 -0
- package/src/modules/audit/audit.contract.ts +164 -0
- package/src/modules/audit/audit.routes.ts +168 -0
- package/src/modules/audit/event-classifier.ts +155 -0
- package/src/modules/audit/index.ts +14 -0
- package/src/modules/audit/request-audit.ts +141 -0
- package/src/modules/auth/__tests__/account.routes.test.ts +15 -0
- package/src/modules/auth/__tests__/auth.service.test.ts +60 -0
- package/src/modules/auth/account-admission.ts +44 -0
- package/src/modules/auth/account.routes.ts +4 -1
- package/src/modules/auth/auth.service.ts +33 -1
- package/src/modules/auth/oidc-auth-provider.ts +9 -0
- package/src/modules/connection-probe/connection-probe.service.ts +7 -1
- package/src/modules/database/__tests__/advisory-lock.test.ts +23 -1
- package/src/modules/database/__tests__/connection.test.ts +98 -0
- package/src/modules/database/__tests__/migrations-unqualified.test.ts +32 -0
- package/src/modules/database/advisory-lock.ts +28 -4
- package/src/modules/database/connection.ts +143 -13
- package/src/modules/database/core-schema.ts +104 -0
- package/src/modules/database/migrate.ts +48 -14
- package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +2 -1
- package/src/modules/diff/__tests__/diff.service.test.ts +2 -1
- package/src/modules/diff/diff.service.ts +6 -1
- package/src/modules/kb-fs/__tests__/branch-name.test.ts +6 -6
- package/src/modules/kb-fs/__tests__/clone-config.test.ts +24 -20
- package/src/modules/kb-fs/branch-name.ts +3 -3
- package/src/modules/kb-fs/clone-config.ts +15 -12
- package/src/modules/kb-fs/git-guarded-filesystem.ts +16 -3
- package/src/modules/marketplace/__tests__/marketplace-repo.head.test.ts +2 -1
- package/src/modules/mcp/__tests__/bevel-oauth-provider.test.ts +183 -13
- package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +60 -2
- package/src/modules/mcp/__tests__/mcp.routes.local-token.test.ts +24 -4
- package/src/modules/mcp/__tests__/mcp.routes.stateless.test.ts +1 -1
- package/src/modules/mcp/__tests__/mcp.service.test.ts +120 -3
- package/src/modules/mcp/mcp-auth.middleware.ts +31 -0
- package/src/modules/mcp/mcp.routes.ts +11 -1
- package/src/modules/mcp/mcp.service.ts +73 -8
- package/src/modules/mcp/oauth/bevel-oauth-provider.ts +184 -6
- package/src/modules/plugins/__tests__/bundle-dialect.e2e.test.ts +12 -11
- package/src/modules/plugins/__tests__/bundle-dialect.test.ts +2 -1
- package/src/modules/plugins/__tests__/compile-marketplace.test.ts +6 -4
- package/src/modules/plugins/__tests__/join-request-jobs.service.test.ts +2 -1
- package/src/modules/plugins/__tests__/join-requests.service.test.ts +2 -1
- package/src/modules/plugins/__tests__/plugin-creation-display-name.test.ts +4 -3
- package/src/modules/plugins/__tests__/plugin-index.service.test.ts +6 -4
- package/src/modules/plugins/__tests__/plugin-links.service.test.ts +220 -5
- package/src/modules/plugins/__tests__/plugin-provision.service.test.ts +3 -1
- package/src/modules/plugins/__tests__/plugin-rename.service.test.ts +7 -6
- package/src/modules/plugins/__tests__/plugins.routes.test.ts +11 -2
- package/src/modules/plugins/__tests__/teams.routes.test.ts +2 -1
- package/src/modules/plugins/compile/marketplace-compiler.service.ts +7 -9
- package/src/modules/plugins/discovery/__tests__/kb-plugin-source.test.ts +20 -16
- package/src/modules/plugins/discovery/bundle-dialect/bundle.source.ts +9 -2
- package/src/modules/plugins/discovery/kb-plugin-source.ts +15 -8
- package/src/modules/plugins/discovery/native.source.ts +4 -1
- package/src/modules/plugins/index.ts +1 -1
- package/src/modules/plugins/join-request-jobs.service.ts +8 -7
- package/src/modules/plugins/join-requests.service.ts +7 -7
- package/src/modules/plugins/plugin-links.service.ts +192 -19
- package/src/modules/plugins/plugin-links.ts +147 -27
- package/src/modules/plugins/plugin-provision.service.ts +54 -27
- package/src/modules/plugins/plugin-rename.service.ts +10 -10
- package/src/modules/plugins/plugins.routes.ts +45 -15
- package/src/modules/plugins/plugins.service.ts +7 -11
- package/src/modules/plugins/teams.routes.ts +16 -8
- package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +7 -0
- package/src/modules/secrets-vault/__tests__/secrets-variable-loader.test.ts +40 -0
- package/src/modules/secrets-vault/__tests__/tool-owner-gate.route.test.ts +2 -0
- package/src/modules/secrets-vault/index.ts +2 -0
- package/src/modules/secrets-vault/secrets-variable-loader.ts +51 -21
- package/src/modules/secrets-vault/secrets-vault.routes.ts +7 -6
- package/src/modules/settings/__tests__/deployment-settings.service.test.ts +59 -11
- package/src/modules/settings/__tests__/git-root-folders.test.ts +2 -1
- package/src/modules/settings/__tests__/setup.routes.boot-failure.test.ts +2 -1
- package/src/modules/settings/__tests__/setup.routes.layout-phase.test.ts +7 -4
- package/src/modules/settings/__tests__/setup.routes.oidc.test.ts +2 -0
- package/src/modules/settings/__tests__/setup.routes.sync-status.test.ts +2 -0
- package/src/modules/settings/__tests__/setup.routes.test.ts +33 -52
- package/src/modules/settings/deployment-settings.service.ts +68 -28
- package/src/modules/settings/setup.routes.ts +26 -16
- package/src/modules/skills/__tests__/allowed-tools-check.test.ts +11 -10
- package/src/modules/skills/__tests__/allowed-tools-warn.tools.test.ts +4 -3
- package/src/modules/skills/__tests__/pending-skills.service.test.ts +3 -1
- package/src/modules/skills/__tests__/skill-access-requests.routes.test.ts +2 -1
- package/src/modules/skills/__tests__/skills.routes.warnings.test.ts +2 -1
- package/src/modules/skills/__tests__/skills.service.test.ts +3 -2
- package/src/modules/skills/allowed-tools-check.ts +7 -6
- package/src/modules/skills/pending-skills.service.ts +9 -8
- package/src/modules/skills/skill-access-requests.routes.ts +7 -7
- package/src/modules/skills/skills.routes.ts +4 -3
- package/src/modules/skills/skills.service.ts +13 -9
- package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +29 -8
- package/src/modules/tool-auth/__tests__/internal-token.service.test.ts +6 -0
- package/src/modules/tool-auth/external-api-key.interface.ts +22 -5
- package/src/modules/tool-auth/external-api-key.service.ts +25 -8
- package/src/modules/tool-auth/internal-token.service.ts +11 -0
- package/src/modules/tool-auth/tool-auth.middleware.ts +17 -1
- package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +3 -2
- package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +3 -2
- package/src/modules/tool-manuals/__tests__/mcp-json-discovery.test.ts +17 -12
- package/src/modules/tool-manuals/__tests__/mcp-server-edit.service.test.ts +2 -1
- package/src/modules/tool-manuals/__tests__/pending-tools.service.test.ts +4 -1
- package/src/modules/tool-manuals/__tests__/tool-delete.service.test.ts +2 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.archive.route.test.ts +2 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.cli.test.ts +5 -4
- package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +2 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.invalid.routes.test.ts +4 -2
- package/src/modules/tool-manuals/__tests__/tool-manuals.invalid.test.ts +13 -5
- package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +2 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.restart.test.ts +9 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +3 -2
- package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +2 -0
- package/src/modules/tool-manuals/mcp-json-discovery.ts +6 -4
- package/src/modules/tool-manuals/mcp-server-edit.service.ts +13 -11
- package/src/modules/tool-manuals/pending-tools.service.ts +19 -16
- package/src/modules/tool-manuals/tool-delete.service.ts +13 -10
- package/src/modules/tool-manuals/tool-manuals.routes.ts +10 -8
- package/src/modules/tool-manuals/tool-manuals.service.ts +15 -13
- package/src/modules/tool-manuals/tool-manuals.tools.ts +7 -6
- package/src/modules/workflow/__tests__/apply-failure.test.ts +2 -1
- package/src/modules/workflow/__tests__/merge-announces-tree.test.ts +14 -26
- package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +2 -1
- package/src/modules/workflow/__tests__/session-ontology.service.test.ts +3 -2
- package/src/modules/workflow/__tests__/workflow.routes.lock-path.test.ts +2 -1
- package/src/modules/workflow/__tests__/workflow.service.branch-in-use.test.ts +3 -10
- package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +2 -1
- package/src/modules/workflow/__tests__/workflow.service.deleted-branch-sweep.test.ts +3 -10
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +28 -27
- package/src/modules/workflow/__tests__/workflow.service.folder-proposals.test.ts +2 -1
- package/src/modules/workflow/__tests__/workflow.service.platform-restore.test.ts +2 -1
- package/src/modules/workflow/__tests__/workflow.service.read-gate.test.ts +3 -2
- package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +2 -1
- package/src/modules/workflow/__tests__/workflow.service.sync.test.ts +5 -4
- package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +2 -1
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +2 -1
- package/src/modules/workflow/agent-tools/workflow.tools.ts +11 -9
- package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +5 -4
- package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +12 -11
- package/src/modules/workflow/git/__tests__/git.service.commitChanges.test.ts +9 -8
- package/src/modules/workflow/git/__tests__/git.service.commitFile.strayPath.test.ts +8 -7
- package/src/modules/workflow/git/__tests__/git.service.commitFile.test.ts +6 -5
- package/src/modules/workflow/git/__tests__/git.service.createBranch.test.ts +3 -2
- package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +3 -2
- package/src/modules/workflow/git/__tests__/git.service.diffFileAtCommit.test.ts +7 -6
- package/src/modules/workflow/git/__tests__/git.service.diffFileBetweenBranches.test.ts +16 -15
- package/src/modules/workflow/git/__tests__/git.service.fileContentsAtCommit.test.ts +3 -2
- package/src/modules/workflow/git/__tests__/git.service.forkPoint.test.ts +2 -1
- package/src/modules/workflow/git/__tests__/git.service.history-guards.test.ts +2 -1
- package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +10 -9
- package/src/modules/workflow/git/__tests__/git.service.listTrackedFiles.test.ts +2 -1
- package/src/modules/workflow/git/__tests__/git.service.logForFile.test.ts +6 -5
- package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +9 -8
- package/src/modules/workflow/git/__tests__/git.service.pendingChanges.test.ts +2 -1
- package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +4 -3
- package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +9 -8
- package/src/modules/workflow/git/__tests__/git.service.readFileAtRef.test.ts +2 -1
- package/src/modules/workflow/git/__tests__/git.service.revertPathsAndPush.test.ts +2 -1
- package/src/modules/workflow/git/__tests__/git.service.status.test.ts +4 -3
- package/src/modules/workflow/git/__tests__/git.service.syncFromRemote.test.ts +8 -7
- package/src/modules/workflow/git/__tests__/node-git-runner.test.ts +41 -3
- package/src/modules/workflow/git/git.service.ts +24 -13
- package/src/modules/workflow/git/node-git-runner.ts +37 -4
- package/src/modules/workflow/review-workflow/review-workflow.service.ts +9 -6
- package/src/modules/workflow/session-ontology.service.ts +7 -2
- package/src/modules/workflow/workflow.service.ts +31 -24
- package/src/modules/workspace/__tests__/file-stat-access.test.ts +3 -2
- package/src/modules/workspace/__tests__/git-internals.security.test.ts +144 -52
- package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +4 -2
- package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +3 -2
- package/src/modules/workspace/__tests__/workspace.routes.branch-errors.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.routes.download-implies-read.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.routes.file-writes.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.routes.folders.test.ts +5 -4
- package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.ensure-remotes-fetched.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.service.list-cloned.test.ts +6 -5
- package/src/modules/workspace/__tests__/workspace.service.move-never-overwrites.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.test.ts +84 -50
- package/src/modules/workspace/__tests__/workspace.service.unknown-branch.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +10 -7
- package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +4 -3
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +9 -8
- package/src/modules/workspace/__tests__/write-denial.test.ts +5 -4
- package/src/modules/workspace/session-ontology.gate.ts +6 -4
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.degraded.test.ts +6 -2
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +29 -21
- package/src/modules/workspace/startup/kb-git.ts +15 -22
- package/src/modules/workspace/startup/kb-startup-runner.ts +40 -46
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +104 -98
- package/src/modules/workspace/startup/steps/groups-to-plugins.step.ts +24 -16
- package/src/modules/workspace/startup/steps/personal-spaces.step.ts +14 -5
- package/src/modules/workspace/startup/steps/plugin-display-names.step.ts +13 -5
- package/src/modules/workspace/startup/steps/plugin-manifests.step.ts +14 -5
- package/src/modules/workspace/startup/steps/seed-tree.ts +11 -9
- package/src/modules/workspace/startup/steps/template-files.step.ts +43 -34
- package/src/modules/workspace/startup/steps/template-source.ts +8 -5
- package/src/modules/workspace/workspace.routes.ts +8 -7
- package/src/modules/workspace/workspace.service.ts +39 -27
- package/src/modules/workspace/workspace.tools.ts +68 -31
- package/src/modules/workspace/write-denial.ts +7 -5
- package/src/shared/__tests__/git-internals.test.ts +41 -0
- package/src/shared/__tests__/kb-layout.plugin.test.ts +19 -16
- package/src/shared/git-internals.ts +61 -6
- package/src/shared/git.contract.ts +70 -8
- package/src/shared/kb-context.ts +130 -0
- package/src/shared/kb-layout.test.ts +37 -27
- package/src/shared/kb-layout.ts +4 -3
- package/src/shared/pending-proposals.ts +7 -4
- package/src/shared/redact-secret.ts +5 -5
- package/src/tenancy/__tests__/static-tenant-source.test.ts +177 -0
- package/src/tenancy/__tests__/tenant-host.test.ts +372 -0
- package/src/tenancy/__tests__/tenant-runtime.test.ts +221 -0
- package/src/tenancy/__tests__/tenant-secrets.test.ts +35 -0
- package/src/tenancy/index.ts +35 -0
- package/src/tenancy/static-tenant-source.ts +296 -0
- package/src/tenancy/tenant-host.ts +261 -0
- package/src/tenancy/tenant-runtime.ts +208 -0
- package/src/tenancy/tenant-secrets.ts +41 -0
- package/src/tenancy/tenant-source.contract.ts +59 -0
- package/dist/modules/access/access-errors.d.ts +0 -34
- package/dist/modules/access/access-errors.d.ts.map +0 -1
- package/dist/modules/access/access-errors.js +0 -40
- package/dist/modules/access/access-errors.js.map +0 -1
- package/dist/modules/access/access-splice.d.ts +0 -140
- package/dist/modules/access/access-splice.d.ts.map +0 -1
- package/dist/modules/access/access-splice.js +0 -389
- package/dist/modules/access/access-splice.js.map +0 -1
- package/dist/modules/access/group-files.d.ts +0 -83
- package/dist/modules/access/group-files.d.ts.map +0 -1
- package/dist/modules/access/group-files.js +0 -167
- package/dist/modules/access/group-files.js.map +0 -1
- package/dist/modules/access/kb-read-filter.d.ts +0 -41
- package/dist/modules/access/kb-read-filter.d.ts.map +0 -1
- package/dist/modules/access/kb-read-filter.js +0 -60
- package/dist/modules/access/kb-read-filter.js.map +0 -1
- package/dist/modules/access/render-roles-yaml.d.ts +0 -22
- package/dist/modules/access/render-roles-yaml.d.ts.map +0 -1
- package/dist/modules/access/render-roles-yaml.js +0 -56
- package/dist/modules/access/render-roles-yaml.js.map +0 -1
- package/dist/modules/access/roles-yaml-guard.d.ts +0 -56
- package/dist/modules/access/roles-yaml-guard.d.ts.map +0 -1
- package/dist/modules/access/roles-yaml-guard.js +0 -79
- package/dist/modules/access/roles-yaml-guard.js.map +0 -1
- package/dist/modules/diff/diff-paths.d.ts +0 -2
- package/dist/modules/diff/diff-paths.d.ts.map +0 -1
- package/dist/modules/diff/diff-paths.js +0 -9
- package/dist/modules/diff/diff-paths.js.map +0 -1
- package/dist/modules/groups/group-provision.service.d.ts +0 -130
- package/dist/modules/groups/group-provision.service.d.ts.map +0 -1
- package/dist/modules/groups/group-provision.service.js +0 -288
- package/dist/modules/groups/group-provision.service.js.map +0 -1
- package/dist/modules/groups/groups.contract.d.ts +0 -106
- package/dist/modules/groups/groups.contract.d.ts.map +0 -1
- package/dist/modules/groups/groups.contract.js +0 -36
- package/dist/modules/groups/groups.contract.js.map +0 -1
- package/dist/modules/groups/groups.routes.d.ts +0 -42
- package/dist/modules/groups/groups.routes.d.ts.map +0 -1
- package/dist/modules/groups/groups.routes.js +0 -379
- package/dist/modules/groups/groups.routes.js.map +0 -1
- package/dist/modules/groups/groups.service.d.ts +0 -60
- package/dist/modules/groups/groups.service.d.ts.map +0 -1
- package/dist/modules/groups/groups.service.js +0 -172
- package/dist/modules/groups/groups.service.js.map +0 -1
- package/dist/modules/groups/index.d.ts +0 -7
- package/dist/modules/groups/index.d.ts.map +0 -1
- package/dist/modules/groups/index.js +0 -6
- package/dist/modules/groups/index.js.map +0 -1
- package/dist/modules/groups/join-proposals.d.ts +0 -53
- package/dist/modules/groups/join-proposals.d.ts.map +0 -1
- package/dist/modules/groups/join-proposals.js +0 -67
- package/dist/modules/groups/join-proposals.js.map +0 -1
- package/dist/modules/groups/join-requests.service.d.ts +0 -81
- package/dist/modules/groups/join-requests.service.d.ts.map +0 -1
- package/dist/modules/groups/join-requests.service.js +0 -135
- package/dist/modules/groups/join-requests.service.js.map +0 -1
- package/dist/modules/mcp/mcp-session-store.d.ts +0 -74
- package/dist/modules/mcp/mcp-session-store.d.ts.map +0 -1
- package/dist/modules/mcp/mcp-session-store.js +0 -131
- package/dist/modules/mcp/mcp-session-store.js.map +0 -1
- package/dist/modules/workflow/file-change-notifier.d.ts +0 -38
- package/dist/modules/workflow/file-change-notifier.d.ts.map +0 -1
- package/dist/modules/workflow/file-change-notifier.js +0 -22
- package/dist/modules/workflow/file-change-notifier.js.map +0 -1
- package/dist/modules/workflow/git/branch-name.d.ts +0 -10
- package/dist/modules/workflow/git/branch-name.d.ts.map +0 -1
- package/dist/modules/workflow/git/branch-name.js +0 -76
- package/dist/modules/workflow/git/branch-name.js.map +0 -1
- package/dist/modules/workflow/git/clone-config.d.ts +0 -61
- package/dist/modules/workflow/git/clone-config.d.ts.map +0 -1
- package/dist/modules/workflow/git/clone-config.js +0 -69
- package/dist/modules/workflow/git/clone-config.js.map +0 -1
- package/dist/modules/workflow/git/mutex.d.ts +0 -11
- package/dist/modules/workflow/git/mutex.d.ts.map +0 -1
- package/dist/modules/workflow/git/mutex.js +0 -23
- package/dist/modules/workflow/git/mutex.js.map +0 -1
- package/dist/modules/workflow/locking-filesystem.d.ts +0 -137
- package/dist/modules/workflow/locking-filesystem.d.ts.map +0 -1
- package/dist/modules/workflow/locking-filesystem.js +0 -553
- package/dist/modules/workflow/locking-filesystem.js.map +0 -1
- package/dist/modules/workflow/read-only-filesystem.d.ts +0 -24
- package/dist/modules/workflow/read-only-filesystem.d.ts.map +0 -1
- package/dist/modules/workflow/read-only-filesystem.js +0 -39
- package/dist/modules/workflow/read-only-filesystem.js.map +0 -1
- package/dist/modules/workflow/workflow.errors.d.ts +0 -197
- package/dist/modules/workflow/workflow.errors.d.ts.map +0 -1
- package/dist/modules/workflow/workflow.errors.js +0 -298
- package/dist/modules/workflow/workflow.errors.js.map +0 -1
- package/dist/modules/workspace/bevel-ignore.d.ts +0 -30
- package/dist/modules/workspace/bevel-ignore.d.ts.map +0 -1
- package/dist/modules/workspace/bevel-ignore.js +0 -61
- package/dist/modules/workspace/bevel-ignore.js.map +0 -1
- package/dist/modules/workspace/kb-seed.interface.d.ts +0 -36
- package/dist/modules/workspace/kb-seed.interface.d.ts.map +0 -1
- package/dist/modules/workspace/kb-seed.interface.js +0 -2
- package/dist/modules/workspace/kb-seed.interface.js.map +0 -1
- package/dist/modules/workspace/kb-seed.service.d.ts +0 -125
- package/dist/modules/workspace/kb-seed.service.d.ts.map +0 -1
- package/dist/modules/workspace/kb-seed.service.js +0 -535
- package/dist/modules/workspace/kb-seed.service.js.map +0 -1
- package/dist/modules/workspace/plugins-migration.d.ts +0 -50
- package/dist/modules/workspace/plugins-migration.d.ts.map +0 -1
- package/dist/modules/workspace/plugins-migration.js +0 -379
- package/dist/modules/workspace/plugins-migration.js.map +0 -1
- package/dist/shared/fs-errors.d.ts +0 -8
- package/dist/shared/fs-errors.d.ts.map +0 -1
- package/dist/shared/fs-errors.js +0 -11
- package/dist/shared/fs-errors.js.map +0 -1
- package/dist/shared/fs-walk.d.ts +0 -23
- package/dist/shared/fs-walk.d.ts.map +0 -1
- package/dist/shared/fs-walk.js +0 -42
- package/dist/shared/fs-walk.js.map +0 -1
- package/dist/shared/hash-email.d.ts +0 -11
- package/dist/shared/hash-email.d.ts.map +0 -1
- package/dist/shared/hash-email.js +0 -14
- package/dist/shared/hash-email.js.map +0 -1
- package/dist/shared/kb-walk.d.ts +0 -52
- package/dist/shared/kb-walk.d.ts.map +0 -1
- package/dist/shared/kb-walk.js +0 -76
- package/dist/shared/kb-walk.js.map +0 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { logger } from '../../shared/logging.js';
|
|
3
|
+
import type { IAdminAccessService } from '../admin/admin.interface.js';
|
|
4
|
+
import { TokenNotFoundError } from '../tool-auth/external-api-key.errors.js';
|
|
5
|
+
import type { IExternalApiKeyService } from '../tool-auth/external-api-key.interface.js';
|
|
6
|
+
import {
|
|
7
|
+
AuditPrincipalNotFoundError,
|
|
8
|
+
InvalidCursorError,
|
|
9
|
+
isUuid,
|
|
10
|
+
type AuditPrincipalRef,
|
|
11
|
+
type IAgentAuditService,
|
|
12
|
+
} from './audit.contract.js';
|
|
13
|
+
import { MAX_EVENT_PAGE } from './agent-audit.service.js';
|
|
14
|
+
import '../auth/auth.middleware.js'; // Express Request augmentation (req.userId / req.userEmail)
|
|
15
|
+
|
|
16
|
+
const log = logger('audit');
|
|
17
|
+
|
|
18
|
+
const DEFAULT_EVENT_PAGE = 50;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The Audit log's routes, JWT-only (mounted behind the session middleware):
|
|
22
|
+
*
|
|
23
|
+
* GET /api/audit/principals?scope=me|all — agents + keys, with owners and event counts
|
|
24
|
+
* GET /api/audit/principals/:kind/:id/events — one principal's events, newest first, cursor-paged
|
|
25
|
+
* DELETE /api/audit/agents/:id — revoke an agent (owner or admin)
|
|
26
|
+
* DELETE /api/audit/keys/:id — revoke a key (owner or admin)
|
|
27
|
+
*
|
|
28
|
+
* Everyone may read and revoke their OWN rows; `scope=all` and anyone else's
|
|
29
|
+
* rows are admins' (per request, through {@link IAdminAccessService}). Both
|
|
30
|
+
* revokes are recorded as the owner's or an admin's doing, so the owner's
|
|
31
|
+
* page can say which. Keys keep their existing per-user and admin routes;
|
|
32
|
+
* the one here exists so the page has a single client for both kinds.
|
|
33
|
+
*/
|
|
34
|
+
export function createAuditRoutes(
|
|
35
|
+
audit: IAgentAuditService,
|
|
36
|
+
keys: Pick<IExternalApiKeyService, 'revoke' | 'revokeAny'>,
|
|
37
|
+
adminAccess: IAdminAccessService,
|
|
38
|
+
): express.Router {
|
|
39
|
+
const router = express.Router();
|
|
40
|
+
|
|
41
|
+
const isAdmin = (req: express.Request) => adminAccess.isAdmin(req.userEmail);
|
|
42
|
+
|
|
43
|
+
/** The principal named by the URL, or null when it names none (a malformed id is a not-found, not a 500). */
|
|
44
|
+
const principalOf = (req: express.Request): AuditPrincipalRef | null => {
|
|
45
|
+
const kind = String(req.params.kind);
|
|
46
|
+
const id = String(req.params.id);
|
|
47
|
+
if ((kind !== 'key' && kind !== 'agent') || !isUuid(id)) return null;
|
|
48
|
+
return { kind, id };
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** Whether the caller may read or revoke `principal`: its owner, or an admin. Null when there is no such principal. */
|
|
52
|
+
const mayAct = async (req: express.Request, principal: AuditPrincipalRef): Promise<boolean | null> => {
|
|
53
|
+
const owner = await audit.ownerOf(principal);
|
|
54
|
+
if (owner === null) return null;
|
|
55
|
+
if (owner === req.userId) return true;
|
|
56
|
+
return isAdmin(req);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
router.get('/audit/principals', async (req, res) => {
|
|
60
|
+
try {
|
|
61
|
+
const all = req.query.scope === 'all';
|
|
62
|
+
if (all && !(await isAdmin(req))) {
|
|
63
|
+
res.status(403).json({ error: 'Admins only' });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const principals = await audit.listPrincipals(all ? 'all' : { userId: req.userId! });
|
|
67
|
+
res.json({ principals });
|
|
68
|
+
} catch (err) {
|
|
69
|
+
log.error('list principals failed:', { err });
|
|
70
|
+
res.status(500).json({ error: 'Failed to load the audit log' });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
router.get('/audit/principals/:kind/:id/events', async (req, res) => {
|
|
75
|
+
const principal = principalOf(req);
|
|
76
|
+
if (!principal) {
|
|
77
|
+
res.status(404).json({ error: 'No such agent or key' });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const allowed = await mayAct(req, principal);
|
|
82
|
+
if (allowed === null) {
|
|
83
|
+
res.status(404).json({ error: 'No such agent or key' });
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (!allowed) {
|
|
87
|
+
res.status(403).json({ error: 'Not yours' });
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const rawLimit = Number(req.query.limit);
|
|
91
|
+
const limit = Number.isFinite(rawLimit) && rawLimit > 0 ? Math.min(rawLimit, MAX_EVENT_PAGE) : DEFAULT_EVENT_PAGE;
|
|
92
|
+
const before = typeof req.query.before === 'string' && req.query.before ? req.query.before : undefined;
|
|
93
|
+
res.json(await audit.listEvents(principal, { before, limit }));
|
|
94
|
+
} catch (err) {
|
|
95
|
+
if (err instanceof InvalidCursorError) {
|
|
96
|
+
res.status(400).json({ error: 'Invalid cursor — reload the events from the start' });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
log.error('list events failed:', { err });
|
|
100
|
+
res.status(500).json({ error: 'Failed to load events' });
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
router.delete('/audit/agents/:id', async (req, res) => {
|
|
105
|
+
const id = String(req.params.id);
|
|
106
|
+
if (!isUuid(id)) {
|
|
107
|
+
res.status(404).json({ error: 'No such agent' });
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
// Own connection: the owner's revoke, recorded as theirs — an admin
|
|
112
|
+
// cutting off their OWN agent disconnected it, and the row must not
|
|
113
|
+
// tell them an admin took it. Anyone else's: only an admin may, and it
|
|
114
|
+
// is recorded as an admin's so the owner is told. Same order as keys.
|
|
115
|
+
const owner = await audit.ownerOf({ kind: 'agent', id });
|
|
116
|
+
if (owner === req.userId) {
|
|
117
|
+
await audit.revokeConnection(id, 'owner', req.userId!);
|
|
118
|
+
} else if (await isAdmin(req)) {
|
|
119
|
+
await audit.revokeConnection(id, 'admin');
|
|
120
|
+
log.info('revoke audit:', { action: 'admin-revoke-agent', actorUserId: req.userId, connectionId: id });
|
|
121
|
+
} else {
|
|
122
|
+
res.status(owner === null ? 404 : 403).json({ error: owner === null ? 'No such agent' : 'Not yours' });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
res.json({ status: 'revoked' });
|
|
126
|
+
} catch (err) {
|
|
127
|
+
if (err instanceof AuditPrincipalNotFoundError) {
|
|
128
|
+
res.status(404).json({ error: err.message });
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
log.error('revoke agent failed:', { err });
|
|
132
|
+
res.status(500).json({ error: 'Failed to revoke this agent' });
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
router.delete('/audit/keys/:id', async (req, res) => {
|
|
137
|
+
const id = String(req.params.id);
|
|
138
|
+
if (!isUuid(id)) {
|
|
139
|
+
res.status(404).json({ error: 'Token not found' });
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
const admin = await isAdmin(req);
|
|
144
|
+
// Own key: the owner's revoke (recorded as theirs). Anyone else's: only
|
|
145
|
+
// an admin may, and it is recorded as an admin's so the owner is told.
|
|
146
|
+
const owner = await audit.ownerOf({ kind: 'key', id });
|
|
147
|
+
if (owner === req.userId) {
|
|
148
|
+
await keys.revoke(id, req.userId!);
|
|
149
|
+
} else if (admin) {
|
|
150
|
+
await keys.revokeAny(id);
|
|
151
|
+
log.info('revoke audit:', { action: 'admin-revoke-key', actorUserId: req.userId, tokenId: id });
|
|
152
|
+
} else {
|
|
153
|
+
res.status(owner === null ? 404 : 403).json({ error: owner === null ? 'Token not found' : 'Not yours' });
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
res.json({ status: 'revoked' });
|
|
157
|
+
} catch (err) {
|
|
158
|
+
if (err instanceof TokenNotFoundError) {
|
|
159
|
+
res.status(404).json({ error: err.message });
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
log.error('revoke key failed:', { err });
|
|
163
|
+
res.status(500).json({ error: 'Failed to revoke this key' });
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
return router;
|
|
168
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { AgentEventKind } from './audit.contract.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pure classification of one UTCP tool call into what the Audit log records:
|
|
5
|
+
* a hexis capability, a manual's tool, or a skill read. No I/O — the one
|
|
6
|
+
* catalog it may need (the skill folders) is handed in by the caller, which
|
|
7
|
+
* asks {@link skillReadPath} first whether that catalog is worth fetching.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** What a call is logged as: the kind, the manual (or skill folder), and the bare name. */
|
|
11
|
+
export interface ClassifiedCall {
|
|
12
|
+
kind: AgentEventKind;
|
|
13
|
+
manual: string | null;
|
|
14
|
+
name: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** A skill as the classifier needs it: its name and its repo-relative folder. */
|
|
18
|
+
export interface SkillFolder {
|
|
19
|
+
name: string;
|
|
20
|
+
path: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ClassifierContext {
|
|
24
|
+
/** The registered name of the platform's own manual (`KNOWLEDGE_BASE`). */
|
|
25
|
+
kbManualName: string;
|
|
26
|
+
/** Registered (rewritten) manual name → catalog name, for pooled MCP manuals. */
|
|
27
|
+
catalogNames: ReadonlyMap<string, string>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The platform tools whose `path` argument may point INTO a skill folder — a
|
|
32
|
+
* read of `Plugins/Sales/rfi/SKILL.md` or of a file bundled beside it is the
|
|
33
|
+
* agent reading that skill, and is logged as such rather than as a file read.
|
|
34
|
+
*/
|
|
35
|
+
const SKILL_FOLDER_READ_TOOLS: ReadonlySet<string> = new Set(['read_file', 'grep', 'list_files']);
|
|
36
|
+
|
|
37
|
+
/** The platform tool that loads a skill by name. */
|
|
38
|
+
const GET_SKILL = 'get_skill';
|
|
39
|
+
|
|
40
|
+
/** `<manual>.<tool>` → its two halves; a bare name has no manual. */
|
|
41
|
+
export function splitUtcpName(utcpName: string): { manual: string; tool: string } {
|
|
42
|
+
const dot = utcpName.indexOf('.');
|
|
43
|
+
return dot < 0
|
|
44
|
+
? { manual: '', tool: utcpName }
|
|
45
|
+
: { manual: utcpName.slice(0, dot), tool: utcpName.slice(dot + 1) };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The `path` a platform tool was called with, wherever the caller put it.
|
|
50
|
+
* Bevel-hosted http tools take their arguments inside a `body` envelope
|
|
51
|
+
* (`{ body: { path } }`); a caller that flattened it (`{ path }`) is read too.
|
|
52
|
+
*/
|
|
53
|
+
function pathArgument(args: Record<string, unknown>): string | null {
|
|
54
|
+
const body = args.body;
|
|
55
|
+
const inner = body && typeof body === 'object' ? (body as Record<string, unknown>).path : undefined;
|
|
56
|
+
const candidate = typeof inner === 'string' ? inner : args.path;
|
|
57
|
+
return typeof candidate === 'string' && candidate.length > 0 ? candidate : null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** The `name` a `get_skill` call asked for, from the envelope or flattened. */
|
|
61
|
+
function skillNameArgument(args: Record<string, unknown>): string | null {
|
|
62
|
+
const body = args.body;
|
|
63
|
+
const inner = body && typeof body === 'object' ? (body as Record<string, unknown>).name : undefined;
|
|
64
|
+
const candidate = typeof inner === 'string' ? inner : args.name;
|
|
65
|
+
return typeof candidate === 'string' && candidate.length > 0 ? candidate : null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* When a platform read names a path, the path — the signal that the caller
|
|
70
|
+
* should fetch the skill catalog before classifying (a folder match turns
|
|
71
|
+
* the read into a skill event). Null for every other call, so the catalog is
|
|
72
|
+
* never fetched for a `notion.search` or a `write_file`.
|
|
73
|
+
*/
|
|
74
|
+
export function skillReadPath(utcpName: string, args: Record<string, unknown>, kbManualName: string): string | null {
|
|
75
|
+
const { manual, tool } = splitUtcpName(utcpName);
|
|
76
|
+
if (manual !== kbManualName) return null;
|
|
77
|
+
if (tool === GET_SKILL) return skillNameArgument(args) === null ? null : '';
|
|
78
|
+
if (!SKILL_FOLDER_READ_TOOLS.has(tool)) return null;
|
|
79
|
+
return pathArgument(args);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The path as segments, resolved: forward slashes, `.` dropped, `..` taken
|
|
84
|
+
* back a segment, no empty segments — so two spellings of one place compare
|
|
85
|
+
* equal, and a path that climbs OUT of a folder is never matched to it. A
|
|
86
|
+
* path that climbs above its own start has no place at all and resolves to
|
|
87
|
+
* the empty string, which matches nothing. (The file tools refuse `..`
|
|
88
|
+
* outright; the log must still not credit a refused read to a skill.)
|
|
89
|
+
*/
|
|
90
|
+
function normalizePath(p: string): string {
|
|
91
|
+
const out: string[] = [];
|
|
92
|
+
for (const segment of p.replace(/\\/g, '/').split('/')) {
|
|
93
|
+
if (segment === '' || segment === '.') continue;
|
|
94
|
+
if (segment === '..') {
|
|
95
|
+
if (out.length === 0) return '';
|
|
96
|
+
out.pop();
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
out.push(segment);
|
|
100
|
+
}
|
|
101
|
+
return out.join('/');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* The skill whose folder contains `path`, if any. Matched on a segment
|
|
106
|
+
* boundary anywhere in the path — a caller may spell the path from the
|
|
107
|
+
* repository root (`Plugins/Sales/rfi/SKILL.md`) or from one level above it
|
|
108
|
+
* (`knowledge-base/Plugins/Sales/rfi/SKILL.md`), and both are that skill.
|
|
109
|
+
* The longest folder wins, so a skill nested under another's folder is not
|
|
110
|
+
* mistaken for its parent.
|
|
111
|
+
*/
|
|
112
|
+
export function skillContaining(path: string, skills: readonly SkillFolder[]): SkillFolder | null {
|
|
113
|
+
const normalized = normalizePath(path);
|
|
114
|
+
if (!normalized) return null;
|
|
115
|
+
const haystack = `/${normalized}/`;
|
|
116
|
+
let best: SkillFolder | null = null;
|
|
117
|
+
for (const skill of skills) {
|
|
118
|
+
const folder = normalizePath(skill.path);
|
|
119
|
+
if (!folder) continue;
|
|
120
|
+
if (haystack.includes(`/${folder}/`) && (!best || folder.length > normalizePath(best.path).length)) {
|
|
121
|
+
best = skill;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return best;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Classify one call. `skills` is the catalog when {@link skillReadPath} asked
|
|
129
|
+
* for it and the caller could fetch it; null otherwise (the read is then
|
|
130
|
+
* logged as the capability it is, which is the honest fallback).
|
|
131
|
+
*/
|
|
132
|
+
export function classifyToolCall(
|
|
133
|
+
utcpName: string,
|
|
134
|
+
args: Record<string, unknown>,
|
|
135
|
+
ctx: ClassifierContext,
|
|
136
|
+
skills: readonly SkillFolder[] | null,
|
|
137
|
+
): ClassifiedCall {
|
|
138
|
+
const { manual, tool } = splitUtcpName(utcpName);
|
|
139
|
+
// A meta-tool (`call_tool_chain`, `list_tools`, …) has no manual: the platform's own.
|
|
140
|
+
if (manual === '' || manual === ctx.kbManualName) {
|
|
141
|
+
if (tool === GET_SKILL) {
|
|
142
|
+
const name = skillNameArgument(args);
|
|
143
|
+
if (name) {
|
|
144
|
+
const folder = skills?.find((s) => s.name === name)?.path ?? null;
|
|
145
|
+
return { kind: 'skill', manual: folder, name };
|
|
146
|
+
}
|
|
147
|
+
} else if (SKILL_FOLDER_READ_TOOLS.has(tool) && skills) {
|
|
148
|
+
const path = pathArgument(args);
|
|
149
|
+
const skill = path ? skillContaining(path, skills) : null;
|
|
150
|
+
if (skill) return { kind: 'skill', manual: skill.path, name: skill.name };
|
|
151
|
+
}
|
|
152
|
+
return { kind: 'capability', manual: null, name: tool };
|
|
153
|
+
}
|
|
154
|
+
return { kind: 'tool', manual: ctx.catalogNames.get(manual) ?? manual, name: tool };
|
|
155
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from './audit.contract.js';
|
|
2
|
+
export { AgentAuditService, MAX_EVENT_PAGE, retentionDaysFrom } from './agent-audit.service.js';
|
|
3
|
+
export { createAgentRestAuditMiddleware } from './agent-rest-audit.middleware.js';
|
|
4
|
+
export { createAuditRoutes } from './audit.routes.js';
|
|
5
|
+
export { RequestAudit } from './request-audit.js';
|
|
6
|
+
export {
|
|
7
|
+
classifyToolCall,
|
|
8
|
+
skillContaining,
|
|
9
|
+
skillReadPath,
|
|
10
|
+
splitUtcpName,
|
|
11
|
+
type ClassifiedCall,
|
|
12
|
+
type ClassifierContext,
|
|
13
|
+
type SkillFolder,
|
|
14
|
+
} from './event-classifier.js';
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { CodeModeUtcpClient } from '@utcp/code-mode';
|
|
2
|
+
import { logger } from '../../shared/logging.js';
|
|
3
|
+
import type { AgentEventOutcome, AuditPrincipalRef, IAgentEventRecorder } from './audit.contract.js';
|
|
4
|
+
import {
|
|
5
|
+
classifyToolCall,
|
|
6
|
+
skillReadPath,
|
|
7
|
+
type ClassifiedCall,
|
|
8
|
+
type ClassifierContext,
|
|
9
|
+
type SkillFolder,
|
|
10
|
+
} from './event-classifier.js';
|
|
11
|
+
|
|
12
|
+
const log = logger('audit');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The Audit log's view of ONE MCP request: who is calling (the user and the
|
|
16
|
+
* key or agent connection the request arrived through), and how to name what
|
|
17
|
+
* they call. The MCP proxy creates one per request that has a principal and
|
|
18
|
+
* routes every call through it; a request with none (a browser JWT, an
|
|
19
|
+
* internal token minted before connections existed) gets no instance and
|
|
20
|
+
* records nothing.
|
|
21
|
+
*
|
|
22
|
+
* Holds nothing that outlives the request. The skill catalog it may need to
|
|
23
|
+
* tell a skill read from a file read is fetched at most once, and only when
|
|
24
|
+
* a platform read names a path.
|
|
25
|
+
*/
|
|
26
|
+
export class RequestAudit {
|
|
27
|
+
private skills: Promise<readonly SkillFolder[] | null> | undefined;
|
|
28
|
+
|
|
29
|
+
constructor(
|
|
30
|
+
private readonly recorder: IAgentEventRecorder,
|
|
31
|
+
private readonly userId: string,
|
|
32
|
+
private readonly principal: AuditPrincipalRef,
|
|
33
|
+
private readonly ctx: {
|
|
34
|
+
kbManualName: string;
|
|
35
|
+
/** Read at classification time — the surface (and its catalog names) is built lazily. */
|
|
36
|
+
catalogNames: () => ReadonlyMap<string, string>;
|
|
37
|
+
/** The caller's skill catalog, for telling a skill read from a file read. */
|
|
38
|
+
loadSkills: () => Promise<readonly SkillFolder[]>;
|
|
39
|
+
},
|
|
40
|
+
) {}
|
|
41
|
+
|
|
42
|
+
/** Record one already-classified call. Never throws. */
|
|
43
|
+
emit(call: ClassifiedCall, outcome: AgentEventOutcome, durationMs: number | null): void {
|
|
44
|
+
try {
|
|
45
|
+
this.recorder.record({
|
|
46
|
+
userId: this.userId,
|
|
47
|
+
principal: this.principal,
|
|
48
|
+
kind: call.kind,
|
|
49
|
+
manual: call.manual,
|
|
50
|
+
name: call.name,
|
|
51
|
+
outcome,
|
|
52
|
+
durationMs,
|
|
53
|
+
});
|
|
54
|
+
} catch (err) {
|
|
55
|
+
log.warn('recording an agent event failed:', { err });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** What a UTCP call is logged as — fetching the skill catalog first when the call might be a skill read. */
|
|
60
|
+
async classify(utcpName: string, args: Record<string, unknown>): Promise<ClassifiedCall> {
|
|
61
|
+
const ctx: ClassifierContext = { kbManualName: this.ctx.kbManualName, catalogNames: this.ctx.catalogNames() };
|
|
62
|
+
const wantsSkills = skillReadPath(utcpName, args, ctx.kbManualName) !== null;
|
|
63
|
+
const skills = wantsSkills ? await this.skillCatalog() : null;
|
|
64
|
+
return classifyToolCall(utcpName, args, ctx, skills);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Run a UTCP call and record it: `error` when it throws or `isError` says
|
|
69
|
+
* the result is one, `ok` otherwise. The result (or the throw) reaches the
|
|
70
|
+
* caller unchanged — recording is a side effect, never a filter.
|
|
71
|
+
*
|
|
72
|
+
* The call starts FIRST and is classified alongside: naming a read may cost
|
|
73
|
+
* a loopback fetch of the skill catalog, and that is the log's business,
|
|
74
|
+
* not the tool's — a tool result never waits on its own bookkeeping.
|
|
75
|
+
*/
|
|
76
|
+
async call<T>(
|
|
77
|
+
utcpName: string,
|
|
78
|
+
args: Record<string, unknown>,
|
|
79
|
+
run: () => Promise<T>,
|
|
80
|
+
isError: (result: T) => boolean,
|
|
81
|
+
): Promise<T> {
|
|
82
|
+
const started = performance.now();
|
|
83
|
+
const classified = this.classify(utcpName, args);
|
|
84
|
+
try {
|
|
85
|
+
const result = await run();
|
|
86
|
+
const duration = elapsed(started);
|
|
87
|
+
this.emit(await classified, isError(result) ? 'error' : 'ok', duration);
|
|
88
|
+
return result;
|
|
89
|
+
} catch (err) {
|
|
90
|
+
const duration = elapsed(started);
|
|
91
|
+
this.emit(await classified, 'error', duration);
|
|
92
|
+
throw err;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** A call refused before it ran, because the caller's sign-in for its manual is missing. */
|
|
97
|
+
async denied(utcpName: string, args: Record<string, unknown>): Promise<void> {
|
|
98
|
+
this.emit(await this.classify(utcpName, args), 'denied', null);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Record every tool call made from INSIDE `call_tool_chain`: the chain
|
|
103
|
+
* bridges each in-isolate tool function to `client.callTool`, so wrapping
|
|
104
|
+
* that one entry point catches them all. Installed after the downstream
|
|
105
|
+
* routing wrapper so the timing covers the pool lease and any retry too.
|
|
106
|
+
* The direct MCP path (`callToolStreaming`) is deliberately NOT wrapped —
|
|
107
|
+
* the proxy's tool handler records those itself, with the result's
|
|
108
|
+
* `isError` in hand.
|
|
109
|
+
*/
|
|
110
|
+
instrumentChainCalls(client: CodeModeUtcpClient): void {
|
|
111
|
+
const callTool = client.callTool.bind(client);
|
|
112
|
+
client.callTool = (toolName: string, toolArgs: Record<string, unknown>) =>
|
|
113
|
+
this.call(toolName, toolArgs, () => callTool(toolName, toolArgs), isErrorShaped);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private skillCatalog(): Promise<readonly SkillFolder[] | null> {
|
|
117
|
+
// A failed fetch is remembered as "no catalog" for the rest of the
|
|
118
|
+
// request: the read is then logged as a capability, and one hiccup does
|
|
119
|
+
// not cost a loopback round-trip per subsequent call.
|
|
120
|
+
this.skills ??= this.ctx.loadSkills().catch((err) => {
|
|
121
|
+
log.warn('skill catalog unavailable for audit classification:', { err });
|
|
122
|
+
return null;
|
|
123
|
+
});
|
|
124
|
+
return this.skills;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function elapsed(started: number): number {
|
|
129
|
+
return Math.max(0, Math.round(performance.now() - started));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* A chain-internal result that is the tool saying it failed. A downstream
|
|
134
|
+
* MCP server answers a failed call with `{ isError: true, content }` as a
|
|
135
|
+
* VALUE (the UTCP mcp protocol hands it through rather than throwing), and
|
|
136
|
+
* the direct path records that as an error — so must the chain path, or the
|
|
137
|
+
* same failure would read `ok` inside a chain and `error` outside one.
|
|
138
|
+
*/
|
|
139
|
+
function isErrorShaped(result: unknown): boolean {
|
|
140
|
+
return typeof result === 'object' && result !== null && (result as { isError?: unknown }).isError === true;
|
|
141
|
+
}
|
|
@@ -3,6 +3,7 @@ import express from 'express';
|
|
|
3
3
|
import type { Server } from 'node:http';
|
|
4
4
|
import { createAccountRoutes } from '../account.routes.js';
|
|
5
5
|
import { AuthService } from '../auth.service.js';
|
|
6
|
+
import { AccountAdmissionRefusedError } from '../account-admission.js';
|
|
6
7
|
import { hashPassword } from '../password-hash.js';
|
|
7
8
|
import type { Database } from '../../database/connection.js';
|
|
8
9
|
import type { IAdminAccessService } from '../../admin/admin.interface.js';
|
|
@@ -145,6 +146,20 @@ describe('account routes — admin gate', () => {
|
|
|
145
146
|
expect(accountErasure.eraseUser).toHaveBeenLastCalledWith('u2');
|
|
146
147
|
});
|
|
147
148
|
|
|
149
|
+
it('an account the admission port refuses → 403 carrying the port\'s own words', async () => {
|
|
150
|
+
const base = await listen(makeApp({ admin: true }));
|
|
151
|
+
vi.mocked(authService.createAccount).mockRejectedValueOnce(
|
|
152
|
+
new AccountAdmissionRefusedError('No seat left on this plan'),
|
|
153
|
+
);
|
|
154
|
+
const refused = await fetch(`${base}/api/admin/accounts`, {
|
|
155
|
+
method: 'POST',
|
|
156
|
+
headers: { 'Content-Type': 'application/json' },
|
|
157
|
+
body: JSON.stringify({ email: 'b@example.com', password: 'long-enough-pw' }),
|
|
158
|
+
});
|
|
159
|
+
expect(refused.status).toBe(403);
|
|
160
|
+
expect(((await refused.json()) as { error: string }).error).toBe('No seat left on this plan');
|
|
161
|
+
});
|
|
162
|
+
|
|
148
163
|
it('erasure failure → 500 with a generic body (no internal error text)', async () => {
|
|
149
164
|
const base = await listen(makeApp({ admin: true }));
|
|
150
165
|
vi.mocked(accountErasure.eraseUser).mockRejectedValueOnce(
|
|
@@ -2,6 +2,7 @@ import { describe, expect, it, vi } from 'vitest';
|
|
|
2
2
|
import type { Database } from '../../database/connection.js';
|
|
3
3
|
import type { CoreConfig } from '../../../core-config.js';
|
|
4
4
|
import { AuthService } from '../auth.service.js';
|
|
5
|
+
import { AccountAdmissionRefusedError, type IAccountAdmission } from '../account-admission.js';
|
|
5
6
|
import { hashPassword, verifyPassword } from '../password-hash.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -605,3 +606,62 @@ describe('AuthService — the SSO domain allow-list', () => {
|
|
|
605
606
|
expect(out.user.email).toBe('root@gmail.com');
|
|
606
607
|
});
|
|
607
608
|
});
|
|
609
|
+
|
|
610
|
+
describe('AuthService — the account admission port', () => {
|
|
611
|
+
const refusing: IAccountAdmission = {
|
|
612
|
+
canProvision: async () => ({ ok: false, message: 'No seat left on this plan' }),
|
|
613
|
+
};
|
|
614
|
+
const asked: Array<[string, string]> = [];
|
|
615
|
+
const recording: IAccountAdmission = {
|
|
616
|
+
canProvision: async (email, reason) => {
|
|
617
|
+
asked.push([email, reason]);
|
|
618
|
+
return { ok: true };
|
|
619
|
+
},
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
it('refuses a first SSO sign-in the port turns down, and inserts nothing', async () => {
|
|
623
|
+
// The lookup for an existing row answers empty: this is a new address (once per attempt).
|
|
624
|
+
const { db } = makeFakeDb([[], []]);
|
|
625
|
+
const svc = new AuthService(db, makeConfig(), refusing);
|
|
626
|
+
await expect(svc.loginWithSso('new@example.com', 'New')).rejects.toBeInstanceOf(AccountAdmissionRefusedError);
|
|
627
|
+
await expect(svc.loginWithSso('new@example.com', 'New')).rejects.toThrow('No seat left on this plan');
|
|
628
|
+
expect(vi.mocked(db.insert)).not.toHaveBeenCalled();
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
it('refuses an admin creating an account the port turns down, before any hash is stored', async () => {
|
|
632
|
+
const { db } = makeFakeDb([[]]);
|
|
633
|
+
const svc = new AuthService(db, makeConfig(), refusing);
|
|
634
|
+
await expect(svc.createAccount('new@example.com', 'New', 'a-long-enough-password')).rejects.toThrow(
|
|
635
|
+
'No seat left on this plan',
|
|
636
|
+
);
|
|
637
|
+
expect(vi.mocked(db.insert)).not.toHaveBeenCalled();
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
it('never asks about an address that already has an account, so a refusal cannot lock anyone out', async () => {
|
|
641
|
+
asked.length = 0;
|
|
642
|
+
const { db } = makeFakeDb([[{ id: ROW.id }], [ROW]]);
|
|
643
|
+
const svc = new AuthService(db, makeConfig(), refusing);
|
|
644
|
+
const { user } = await svc.loginWithSso('alice@example.com', 'Alice');
|
|
645
|
+
expect(user.email).toBe('alice@example.com');
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
it('names the path a new account arrives by, and admits when the port says so', async () => {
|
|
649
|
+
asked.length = 0;
|
|
650
|
+
const { db } = makeFakeDb([[], [ROW], [], [ROW]]);
|
|
651
|
+
const svc = new AuthService(db, makeConfig(), recording);
|
|
652
|
+
await svc.loginWithSso('alice@example.com', 'Alice');
|
|
653
|
+
await svc.createAccount('alice@example.com', 'Alice', 'a-long-enough-password');
|
|
654
|
+
expect(asked).toEqual([
|
|
655
|
+
['alice@example.com', 'sso'],
|
|
656
|
+
['alice@example.com', 'admin-create'],
|
|
657
|
+
]);
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
it('admits everyone by default, without a lookup', async () => {
|
|
661
|
+
const { db } = makeFakeDb([[ROW]]);
|
|
662
|
+
const svc = new AuthService(db, makeConfig());
|
|
663
|
+
const { user } = await svc.loginWithSso('alice@example.com', 'Alice');
|
|
664
|
+
expect(user.email).toBe('alice@example.com');
|
|
665
|
+
expect(vi.mocked(db.select)).not.toHaveBeenCalled();
|
|
666
|
+
});
|
|
667
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a NEW account may be provisioned on this deployment, asked before
|
|
3
|
+
* the row is inserted. The one seam a host that sells seats needs: core
|
|
4
|
+
* admits everyone, and a cloud overlay answers from its plan without
|
|
5
|
+
* forking any sign-in path.
|
|
6
|
+
*
|
|
7
|
+
* Asked only for an address with no account yet. An existing user's sign-in
|
|
8
|
+
* is never a provisioning, so a refusal can never lock out someone who is
|
|
9
|
+
* already in.
|
|
10
|
+
*/
|
|
11
|
+
export type AccountProvisionReason =
|
|
12
|
+
/** A first sign-in through single sign-on, which provisions on its own. */
|
|
13
|
+
| 'sso'
|
|
14
|
+
/** An admin creating an account from the app. */
|
|
15
|
+
| 'admin-create'
|
|
16
|
+
/** The deployment owner's first password sign-in, which creates their row. */
|
|
17
|
+
| 'bootstrap'
|
|
18
|
+
/** A verified identity from an embedding surface that needs a row without a session. */
|
|
19
|
+
| 'embed';
|
|
20
|
+
|
|
21
|
+
export type AccountAdmissionVerdict = { ok: true } | { ok: false; message: string };
|
|
22
|
+
|
|
23
|
+
export interface IAccountAdmission {
|
|
24
|
+
canProvision(email: string, reason: AccountProvisionReason): Promise<AccountAdmissionVerdict>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Core's default: every account is admitted. */
|
|
28
|
+
export const admitEveryone: IAccountAdmission = {
|
|
29
|
+
canProvision: async () => ({ ok: true }),
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The port said no. Carries the port's own words, which the routes surface
|
|
34
|
+
* to the person or admin who asked, and a 403: the identity was fine, the
|
|
35
|
+
* deployment has no place for it.
|
|
36
|
+
*/
|
|
37
|
+
export class AccountAdmissionRefusedError extends Error {
|
|
38
|
+
readonly status = 403;
|
|
39
|
+
|
|
40
|
+
constructor(message: string) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.name = 'AccountAdmissionRefusedError';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -6,6 +6,7 @@ import { printable } from '../../shared/printable.js';
|
|
|
6
6
|
const log = logger('accounts');
|
|
7
7
|
import type { AuthUser } from '@bevel-software/platform-shared';
|
|
8
8
|
import type { AuthService } from './auth.service.js';
|
|
9
|
+
import { AccountAdmissionRefusedError } from './account-admission.js';
|
|
9
10
|
import { erasedAccountId, type IAccountErasureService } from './account-erasure.service.js';
|
|
10
11
|
import type { IAdminAccessService } from '../admin/admin.interface.js';
|
|
11
12
|
import type { UserAccessRemovalService } from '../access/user-access-removal.service.js';
|
|
@@ -64,7 +65,9 @@ export function createAccountRoutes(
|
|
|
64
65
|
res.status(201).json(user);
|
|
65
66
|
} catch (error) {
|
|
66
67
|
const msg = error instanceof Error ? error.message : 'Unknown error';
|
|
67
|
-
|
|
68
|
+
// The deployment has no place for the account (a seat limit, say): the
|
|
69
|
+
// port's own words, as a refusal rather than a malformed request.
|
|
70
|
+
res.status(error instanceof AccountAdmissionRefusedError ? 403 : 400).json({ error: msg });
|
|
68
71
|
}
|
|
69
72
|
});
|
|
70
73
|
|