@bevel-software/platform-core-backend 0.20.0 → 0.22.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 +55 -107
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +41 -4
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +183 -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-requests.contract.d.ts +75 -0
- package/dist/modules/access/access-requests.contract.d.ts.map +1 -0
- package/dist/modules/access/access-requests.contract.js +20 -0
- package/dist/modules/access/access-requests.contract.js.map +1 -0
- package/dist/modules/access/access-requests.routes.d.ts +35 -0
- package/dist/modules/access/access-requests.routes.d.ts.map +1 -0
- package/dist/modules/access/access-requests.routes.js +237 -0
- package/dist/modules/access/access-requests.routes.js.map +1 -0
- package/dist/modules/access/access-requests.service.d.ts +123 -0
- package/dist/modules/access/access-requests.service.d.ts.map +1 -0
- package/dist/modules/access/access-requests.service.js +337 -0
- package/dist/modules/access/access-requests.service.js.map +1 -0
- 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/access-model/access-grammar.d.ts +12 -0
- package/dist/modules/access-model/access-grammar.d.ts.map +1 -1
- package/dist/modules/access-model/access-grammar.js +24 -0
- package/dist/modules/access-model/access-grammar.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/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 +45 -2
- package/dist/modules/auth/auth.service.d.ts.map +1 -1
- package/dist/modules/auth/auth.service.js +44 -3
- 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/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/github-app/github-app.client.d.ts +101 -0
- package/dist/modules/github-app/github-app.client.d.ts.map +1 -0
- package/dist/modules/github-app/github-app.client.js +222 -0
- package/dist/modules/github-app/github-app.client.js.map +1 -0
- package/dist/modules/github-app/github-app.connection.d.ts +102 -0
- package/dist/modules/github-app/github-app.connection.d.ts.map +1 -0
- package/dist/modules/github-app/github-app.connection.js +185 -0
- package/dist/modules/github-app/github-app.connection.js.map +1 -0
- package/dist/modules/github-app/github-app.routes.d.ts +59 -0
- package/dist/modules/github-app/github-app.routes.d.ts.map +1 -0
- package/dist/modules/github-app/github-app.routes.js +323 -0
- package/dist/modules/github-app/github-app.routes.js.map +1 -0
- package/dist/modules/github-app/index.d.ts +4 -0
- package/dist/modules/github-app/index.d.ts.map +1 -0
- package/dist/modules/github-app/index.js +4 -0
- package/dist/modules/github-app/index.js.map +1 -0
- 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/remote-url.d.ts +22 -0
- package/dist/modules/kb-fs/remote-url.d.ts.map +1 -0
- package/dist/modules/kb-fs/remote-url.js +35 -0
- package/dist/modules/kb-fs/remote-url.js.map +1 -0
- package/dist/modules/mcp/mcp.service.d.ts +7 -0
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +4 -4
- package/dist/modules/mcp/mcp.service.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-proposals.d.ts +17 -5
- package/dist/modules/plugins/join-proposals.d.ts.map +1 -1
- package/dist/modules/plugins/join-proposals.js +76 -22
- package/dist/modules/plugins/join-proposals.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 +113 -18
- package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
- package/dist/modules/plugins/join-requests.service.js +178 -33
- 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 +48 -17
- 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 +34 -9
- package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
- package/dist/modules/settings/deployment-settings.service.js +113 -26
- package/dist/modules/settings/deployment-settings.service.js.map +1 -1
- package/dist/modules/settings/managed-repository.d.ts +43 -0
- package/dist/modules/settings/managed-repository.d.ts.map +1 -0
- package/dist/modules/settings/managed-repository.js +60 -0
- package/dist/modules/settings/managed-repository.js.map +1 -0
- package/dist/modules/settings/repository-source.d.ts +128 -0
- package/dist/modules/settings/repository-source.d.ts.map +1 -0
- package/dist/modules/settings/repository-source.js +150 -0
- package/dist/modules/settings/repository-source.js.map +1 -0
- package/dist/modules/settings/setup.routes.d.ts +34 -4
- package/dist/modules/settings/setup.routes.d.ts.map +1 -1
- package/dist/modules/settings/setup.routes.js +198 -18
- 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 +8 -9
- package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -1
- package/dist/modules/skills/skill-access-requests.routes.js +26 -65
- 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-helpers/tool-context.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool-context.js +15 -0
- package/dist/modules/tool-helpers/tool-context.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 +47 -11
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +14 -6
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +40 -18
- 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 +40 -5
- package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
- package/dist/modules/workflow/git/pull-request.service.d.ts +45 -0
- package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/pull-request.service.js +99 -0
- package/dist/modules/workflow/git/pull-request.service.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.routes.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.routes.js +3 -1
- package/dist/modules/workflow/workflow.routes.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts +42 -10
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +181 -71
- 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 +70 -7
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.js +183 -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 +18 -12
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +49 -29
- 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 +48 -20
- 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/domain-errors.d.ts +39 -0
- package/dist/shared/domain-errors.d.ts.map +1 -1
- package/dist/shared/domain-errors.js +55 -0
- package/dist/shared/domain-errors.js.map +1 -1
- package/dist/shared/git.contract.d.ts +62 -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 +6 -6
- package/package.json +3 -3
- 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 +64 -107
- package/src/core/create-core-services.ts +238 -96
- 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-requests.recut.test.ts +134 -0
- package/src/modules/access/__tests__/access-requests.routes.test.ts +610 -0
- 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-requests.contract.ts +93 -0
- package/src/modules/access/access-requests.routes.ts +286 -0
- package/src/modules/access/access-requests.service.ts +420 -0
- 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/access-model/access-grammar.ts +22 -0
- 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/auth/__tests__/account.routes.test.ts +15 -0
- package/src/modules/auth/__tests__/auth.service.test.ts +98 -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 +61 -2
- 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/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/github-app/__tests__/github-app.test.ts +848 -0
- package/src/modules/github-app/github-app.client.ts +268 -0
- package/src/modules/github-app/github-app.connection.ts +204 -0
- package/src/modules/github-app/github-app.routes.ts +359 -0
- package/src/modules/github-app/index.ts +19 -0
- 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/__tests__/remote-url.test.ts +38 -0
- 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/remote-url.ts +35 -0
- package/src/modules/marketplace/__tests__/marketplace-repo.head.test.ts +2 -1
- package/src/modules/mcp/mcp.service.ts +11 -4
- 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-proposals.test.ts +100 -19
- package/src/modules/plugins/__tests__/join-request-jobs.service.test.ts +2 -1
- package/src/modules/plugins/__tests__/join-requests.service.test.ts +28 -11
- package/src/modules/plugins/__tests__/join-requests.settlement.test.ts +371 -0
- 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 +12 -3
- 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-proposals.ts +87 -19
- package/src/modules/plugins/join-request-jobs.service.ts +8 -7
- package/src/modules/plugins/join-requests.service.ts +203 -43
- 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 +48 -17
- 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 +24 -11
- package/src/modules/settings/__tests__/git-root-folders.test.ts +2 -1
- package/src/modules/settings/__tests__/repository-source.test.ts +191 -0
- package/src/modules/settings/__tests__/setup.routes.boot-failure.test.ts +2 -1
- package/src/modules/settings/__tests__/setup.routes.git-mode.test.ts +353 -0
- package/src/modules/settings/__tests__/setup.routes.github-app.test.ts +282 -0
- package/src/modules/settings/__tests__/setup.routes.layout-phase.test.ts +7 -4
- package/src/modules/settings/__tests__/setup.routes.managed-phase.test.ts +233 -0
- 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 +130 -23
- package/src/modules/settings/managed-repository.ts +68 -0
- package/src/modules/settings/repository-source.ts +197 -0
- package/src/modules/settings/setup.routes.ts +233 -19
- 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 +7 -2
- 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 +29 -79
- package/src/modules/skills/skills.routes.ts +4 -3
- package/src/modules/skills/skills.service.ts +13 -9
- 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-helpers/tool-context.ts +15 -0
- 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 +11 -2
- 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 +187 -35
- 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 +148 -41
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +143 -2
- package/src/modules/workflow/agent-tools/workflow.tools.ts +60 -12
- 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 +130 -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/__tests__/pull-request.service.getPrDetail.test.ts +145 -2
- package/src/modules/workflow/git/__tests__/pull-request.service.viewer-can-delete.test.ts +166 -0
- package/src/modules/workflow/git/git.service.ts +49 -17
- package/src/modules/workflow/git/node-git-runner.ts +43 -4
- package/src/modules/workflow/git/pull-request.service.ts +119 -0
- 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.routes.ts +3 -1
- package/src/modules/workflow/workflow.service.ts +201 -76
- package/src/modules/workspace/__tests__/file-stat-access.test.ts +3 -2
- package/src/modules/workspace/__tests__/git-internals.security.test.ts +10 -9
- 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 +45 -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 +237 -10
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +44 -11
- 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 +240 -21
- package/src/modules/workspace/startup/kb-git.ts +15 -22
- package/src/modules/workspace/startup/kb-startup-runner.ts +198 -45
- 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 +47 -28
- package/src/modules/workspace/workspace.tools.ts +56 -20
- package/src/modules/workspace/write-denial.ts +7 -5
- package/src/shared/__tests__/kb-layout.plugin.test.ts +19 -16
- package/src/shared/domain-errors.ts +58 -0
- package/src/shared/git.contract.ts +80 -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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
+
import { testKbContext } from '../../../__tests__/kb-context.js';
|
|
2
3
|
import { execFile } from 'node:child_process';
|
|
3
4
|
import { promisify } from 'node:util';
|
|
4
5
|
import fs from 'node:fs/promises';
|
|
@@ -63,7 +64,7 @@ describe('WorkspaceService — a branch origin does not have', () => {
|
|
|
63
64
|
const deleteOnHost = (branch: string): Promise<void> => runGit(upstream, ['branch', '-D', branch]);
|
|
64
65
|
|
|
65
66
|
const service = (repoUrl = upstream): WorkspaceService =>
|
|
66
|
-
new WorkspaceService(workspacesRoot, repoUrl,
|
|
67
|
+
new WorkspaceService(workspacesRoot, repoUrl, testKbContext(), new NodeFs());
|
|
67
68
|
|
|
68
69
|
it('a name nothing has ever cloned or listed is a 404 that names only the branch', async () => {
|
|
69
70
|
const svc = service();
|
|
@@ -76,6 +77,49 @@ describe('WorkspaceService — a branch origin does not have', () => {
|
|
|
76
77
|
});
|
|
77
78
|
});
|
|
78
79
|
|
|
80
|
+
/**
|
|
81
|
+
* The second defect on this ticket. A bootstrap that fails to clone used to
|
|
82
|
+
* leave its workspace directory behind, and a directory named after a branch
|
|
83
|
+
* is one of the ways the platform remembers having KNOWN a branch. So the
|
|
84
|
+
* first attempt at a typo answered 404 and then quietly created the evidence
|
|
85
|
+
* that turned every later attempt into 410 — the reader was told a branch
|
|
86
|
+
* they had invented "no longer exists on the remote".
|
|
87
|
+
*/
|
|
88
|
+
it('leaves nothing on disk when the clone fails, so a second attempt is still a 404', async () => {
|
|
89
|
+
const svc = service();
|
|
90
|
+
|
|
91
|
+
await expect(svc.getOrCreateForBranch('nobody/never-made-this')).rejects.toMatchObject({
|
|
92
|
+
name: 'BranchNotFoundError',
|
|
93
|
+
status: 404,
|
|
94
|
+
});
|
|
95
|
+
// The failed bootstrap rolled back completely — not the clone directory,
|
|
96
|
+
// not the workspace shell around it.
|
|
97
|
+
expect(await fs.readdir(workspacesRoot)).toEqual([]);
|
|
98
|
+
|
|
99
|
+
// The same name again, on the same instance that has now already failed on
|
|
100
|
+
// it once. Nothing about the first failure may change this answer.
|
|
101
|
+
await expect(svc.getOrCreateForBranch('nobody/never-made-this')).rejects.toMatchObject({
|
|
102
|
+
name: 'BranchNotFoundError',
|
|
103
|
+
status: 404,
|
|
104
|
+
message: 'There is no branch named nobody/never-made-this.',
|
|
105
|
+
payload: { kind: 'branch-not-found', branch: 'nobody/never-made-this' },
|
|
106
|
+
});
|
|
107
|
+
expect(await fs.readdir(workspacesRoot)).toEqual([]);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('does not count a bare directory with no clone in it as a branch it knew', async () => {
|
|
111
|
+
// A shell left by an older process (one that crashed mid-bootstrap, or that
|
|
112
|
+
// predates the rollback above). The "have I heard of this branch" probe asks
|
|
113
|
+
// for a COMPLETED clone, so a directory with no `.git` under it is absence:
|
|
114
|
+
// the honest 404 survives whatever is lying around the workspaces root.
|
|
115
|
+
await fs.mkdir(path.join(workspacesRoot, workspaceIdForBranch('nobody/never-made-this')), { recursive: true });
|
|
116
|
+
|
|
117
|
+
await expect(service().getOrCreateForBranch('nobody/never-made-this')).rejects.toMatchObject({
|
|
118
|
+
name: 'BranchNotFoundError',
|
|
119
|
+
status: 404,
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
79
123
|
it('a name a listing showed us, and origin no longer has, stays a 410', async () => {
|
|
80
124
|
const svc = service();
|
|
81
125
|
// What the branch selector saw while the draft still existed.
|
|
@@ -2,7 +2,8 @@ import express from 'express';
|
|
|
2
2
|
import { afterEach, describe, expect, it } from 'vitest';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
|
-
import { DEFAULT_KB_LAYOUT
|
|
5
|
+
import { DEFAULT_KB_LAYOUT } from '@bevel-software/platform-shared';
|
|
6
|
+
import { testKbContext } from '../../../__tests__/kb-context.js';
|
|
6
7
|
import { ToolRegistry } from '../../tool-registry/tool-registry.js';
|
|
7
8
|
import { createToolHandlerFactory } from '../../tool-helpers/tool-handler.js';
|
|
8
9
|
import type { ToolAuth } from '../../tool-auth/tool-auth.middleware.js';
|
|
@@ -24,6 +25,8 @@ import { registerWorkspaceTools } from '../workspace.tools.js';
|
|
|
24
25
|
* for it.
|
|
25
26
|
*/
|
|
26
27
|
const KB_DIR = 'knowledge-base';
|
|
28
|
+
/** The context the tools read; a case applies a deployment's own names to it. */
|
|
29
|
+
const kb = testKbContext({ kbDirName: KB_DIR });
|
|
27
30
|
|
|
28
31
|
/** Every workspace tool's description, keyed by name, under the layout in effect. */
|
|
29
32
|
async function descriptions(registry: ToolRegistry = new ToolRegistry()): Promise<Map<string, string>> {
|
|
@@ -37,11 +40,11 @@ async function descriptions(registry: ToolRegistry = new ToolRegistry()): Promis
|
|
|
37
40
|
new SpillStore(join(tmpdir(), 'bevel-test-spills')),
|
|
38
41
|
new DocExtractService(join(tmpdir(), 'bevel-test-doc-extract')),
|
|
39
42
|
{} as unknown as IAccessControl,
|
|
40
|
-
|
|
43
|
+
kb,
|
|
41
44
|
{
|
|
42
45
|
service: {} as never,
|
|
43
46
|
enabled: false,
|
|
44
|
-
|
|
47
|
+
kb,
|
|
45
48
|
recoveryBotEmail: 'recovery-bot@bevel.local',
|
|
46
49
|
hooks: new WorkflowHooks(),
|
|
47
50
|
},
|
|
@@ -57,7 +60,7 @@ async function listed(registry: ToolRegistry): Promise<Map<string, string>> {
|
|
|
57
60
|
return new Map(tools.map((t) => [t.name, t.description ?? '']));
|
|
58
61
|
}
|
|
59
62
|
|
|
60
|
-
afterEach(() =>
|
|
63
|
+
afterEach(() => kb.applyLayout({ ...DEFAULT_KB_LAYOUT }));
|
|
61
64
|
|
|
62
65
|
describe('the conventions note every workspace tool carries', () => {
|
|
63
66
|
it('names AGENTS.md, and CLAUDE.md beside it, under the default name', async () => {
|
|
@@ -71,7 +74,7 @@ describe('the conventions note every workspace tool carries', () => {
|
|
|
71
74
|
});
|
|
72
75
|
|
|
73
76
|
it('names the configured file first and the organisation\'s own AGENTS.md second', async () => {
|
|
74
|
-
|
|
77
|
+
kb.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
75
78
|
const byName = await descriptions();
|
|
76
79
|
const note = byName.get('grep') ?? '';
|
|
77
80
|
expect(note).toContain('read `HEXIS.md` at the KB root, then `AGENTS.md` if it also exists');
|
|
@@ -83,7 +86,7 @@ describe('the conventions note every workspace tool carries', () => {
|
|
|
83
86
|
});
|
|
84
87
|
|
|
85
88
|
it('describes the platform files under the configured name, and no longer under AGENTS.md', async () => {
|
|
86
|
-
|
|
89
|
+
kb.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
87
90
|
const byName = await descriptions();
|
|
88
91
|
const stat = byName.get('file_stat') ?? '';
|
|
89
92
|
expect(stat).toContain('`access.md`, `roles.yaml`, `.bevelignore`, `HEXIS.md`');
|
|
@@ -117,7 +120,7 @@ describe('the conventions note every workspace tool carries', () => {
|
|
|
117
120
|
const atMount = await descriptions(registry);
|
|
118
121
|
expect(atMount.get('grep')).toContain('read `AGENTS.md` at the KB root');
|
|
119
122
|
|
|
120
|
-
|
|
123
|
+
kb.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
121
124
|
|
|
122
125
|
const now = await listed(registry);
|
|
123
126
|
expect(now.get('grep')).toContain('read `HEXIS.md` at the KB root, then `AGENTS.md` if it also exists');
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import type { Server as HttpServer } from 'node:http';
|
|
2
2
|
import { execFile } from 'node:child_process';
|
|
3
|
-
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { mkdir, mkdtemp, readdir, rm, writeFile } from 'node:fs/promises';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import { promisify } from 'node:util';
|
|
7
7
|
import express from 'express';
|
|
8
8
|
import { afterEach, describe, expect, it } from 'vitest';
|
|
9
|
+
import '@utcp/http'; // registers the http CallTemplate serializer + protocol
|
|
10
|
+
import { UtcpManualSerializer } from '@utcp/sdk';
|
|
11
|
+
import { HttpCallTemplateSerializer } from '@utcp/http';
|
|
12
|
+
import { CodeModeUtcpClient } from '../../code-mode/index.js';
|
|
13
|
+
import { testKbContext } from '../../../__tests__/kb-context.js';
|
|
9
14
|
import { NodeFs } from '../../kb-fs/node-fs.js';
|
|
10
15
|
import { ToolRegistry } from '../../tool-registry/tool-registry.js';
|
|
11
16
|
import { createToolHandlerFactory } from '../../tool-helpers/tool-handler.js';
|
|
@@ -85,7 +90,12 @@ describe('workspace tools — a branch that cannot be opened', () => {
|
|
|
85
90
|
* real tool-context resolver — so a tool call clones (or fails to clone)
|
|
86
91
|
* exactly as it does in production.
|
|
87
92
|
*/
|
|
88
|
-
|
|
93
|
+
/** The tool defs the mounted registry serves, kept for the sweep below. */
|
|
94
|
+
let internalTools: { name: string; inputs: unknown }[] = [];
|
|
95
|
+
|
|
96
|
+
async function start(
|
|
97
|
+
opts: { repoUrl?: 'origin' | 'unreachable'; scope?: 'read' | 'write'; source?: 'internal' | 'external' } = {},
|
|
98
|
+
): Promise<string> {
|
|
89
99
|
root = await mkdtemp(join(tmpdir(), 'ws-tools-branch-'));
|
|
90
100
|
spillRoot = await mkdtemp(join(tmpdir(), 'ws-tools-spill-'));
|
|
91
101
|
docCacheDir = await mkdtemp(join(tmpdir(), 'ws-tools-doc-'));
|
|
@@ -109,7 +119,7 @@ describe('workspace tools — a branch that cannot be opened', () => {
|
|
|
109
119
|
workspaces = new WorkspaceService(
|
|
110
120
|
workspacesRoot,
|
|
111
121
|
opts.repoUrl === 'unreachable' ? join(root, 'no-such-repo.git') : upstream,
|
|
112
|
-
KB_DIR,
|
|
122
|
+
testKbContext({ kbDirName: KB_DIR }),
|
|
113
123
|
new NodeFs(),
|
|
114
124
|
);
|
|
115
125
|
|
|
@@ -127,22 +137,44 @@ describe('workspace tools — a branch that cannot be opened', () => {
|
|
|
127
137
|
const app = express();
|
|
128
138
|
app.use(express.json());
|
|
129
139
|
const router = express.Router();
|
|
140
|
+
const registry = new ToolRegistry();
|
|
141
|
+
// The internal discovery endpoint, exactly as `manual.routes` serves it —
|
|
142
|
+
// what a real `CodeModeUtcpClient` reads to learn the tools it can call
|
|
143
|
+
// from inside a chain. Served here so the chain test below drives the SAME
|
|
144
|
+
// routes as every direct call in this file.
|
|
145
|
+
router.get('/agent/internal/utcp', async (_req, res) => {
|
|
146
|
+
res.json(
|
|
147
|
+
new UtcpManualSerializer().validateDict({
|
|
148
|
+
utcp_version: '1.1.0',
|
|
149
|
+
manual_version: '1.0.0',
|
|
150
|
+
tools: await registry.listInternal(),
|
|
151
|
+
}),
|
|
152
|
+
);
|
|
153
|
+
});
|
|
130
154
|
registerWorkspaceTools(
|
|
131
|
-
|
|
155
|
+
registry,
|
|
132
156
|
router,
|
|
133
157
|
(req: express.Request, _res: express.Response, next: express.NextFunction) => {
|
|
134
|
-
req.toolAuth = {
|
|
158
|
+
req.toolAuth = {
|
|
159
|
+
// The sweep below asks for `internal` + `write`, which is what reaches
|
|
160
|
+
// the internal-only tools and gets past the write-scope refusal that
|
|
161
|
+
// sits in FRONT of every handler. Everything else in this file stays
|
|
162
|
+
// on the external read surface the bug was reported from.
|
|
163
|
+
source: opts.source ?? 'external',
|
|
164
|
+
userId: 'u',
|
|
165
|
+
scope: opts.scope ?? 'read',
|
|
166
|
+
} as ToolAuth;
|
|
135
167
|
next();
|
|
136
168
|
},
|
|
137
169
|
createToolHandlerFactory(resolve),
|
|
138
170
|
new SpillStore(spillRoot),
|
|
139
171
|
new DocExtractService(docCacheDir),
|
|
140
172
|
allowAll,
|
|
141
|
-
KB_DIR,
|
|
173
|
+
testKbContext({ kbDirName: KB_DIR }),
|
|
142
174
|
{
|
|
143
175
|
service: {} as never,
|
|
144
176
|
enabled: false,
|
|
145
|
-
kbDirName: KB_DIR,
|
|
177
|
+
kb: testKbContext({ kbDirName: KB_DIR }),
|
|
146
178
|
recoveryBotEmail: 'recovery-bot@bevel.local',
|
|
147
179
|
hooks: new WorkflowHooks(),
|
|
148
180
|
},
|
|
@@ -150,21 +182,34 @@ describe('workspace tools — a branch that cannot be opened', () => {
|
|
|
150
182
|
{} as never,
|
|
151
183
|
);
|
|
152
184
|
app.use('/api', router);
|
|
185
|
+
internalTools = (await registry.listInternal()) as unknown as { name: string; inputs: unknown }[];
|
|
153
186
|
httpServer = await new Promise<HttpServer>((r) => {
|
|
154
187
|
const s = app.listen(0, () => r(s));
|
|
155
188
|
});
|
|
156
189
|
return `http://127.0.0.1:${(httpServer.address() as { port: number }).port}`;
|
|
157
190
|
}
|
|
158
191
|
|
|
159
|
-
|
|
160
|
-
|
|
192
|
+
/** Call a tool with an arbitrary body — including one that omits `branch`. */
|
|
193
|
+
const callTool = async (
|
|
194
|
+
base: string,
|
|
195
|
+
tool: string,
|
|
196
|
+
body: unknown,
|
|
197
|
+
): Promise<{ status: number; body: Record<string, unknown> }> => {
|
|
198
|
+
const res = await fetch(`${base}/api/agent/tools/${tool}`, {
|
|
161
199
|
method: 'POST',
|
|
162
200
|
headers: { 'content-type': 'application/json', authorization: 'Bearer x' },
|
|
163
|
-
body: JSON.stringify(
|
|
201
|
+
body: JSON.stringify(body),
|
|
164
202
|
});
|
|
165
203
|
return { status: res.status, body: (await res.json()) as Record<string, unknown> };
|
|
166
204
|
};
|
|
167
205
|
|
|
206
|
+
const listFiles = async (base: string, branch: string): Promise<{ status: number; body: Record<string, unknown> }> =>
|
|
207
|
+
callTool(base, 'list_files', { branch, path: '' });
|
|
208
|
+
|
|
209
|
+
/** Every entry currently under the workspaces root. */
|
|
210
|
+
const workspaceDirs = async (): Promise<string[]> =>
|
|
211
|
+
(await readdir(join(root, 'workspaces'))).sort();
|
|
212
|
+
|
|
168
213
|
const deleteOnHost = (branch: string): Promise<void> =>
|
|
169
214
|
runGit(join(root, 'upstream.git'), ['branch', '-D', branch]);
|
|
170
215
|
|
|
@@ -181,6 +226,188 @@ describe('workspace tools — a branch that cannot be opened', () => {
|
|
|
181
226
|
});
|
|
182
227
|
});
|
|
183
228
|
|
|
229
|
+
/**
|
|
230
|
+
* The reported bug, from the outside: every tool call made without a
|
|
231
|
+
* `branch` answered `Branch "undefined" no longer exists on the remote.` —
|
|
232
|
+
* the missing input was carried all the way down, turned into a workspace
|
|
233
|
+
* directory named `undefined`, and the failed clone of that "branch" was
|
|
234
|
+
* then explained as a branch that had been deleted.
|
|
235
|
+
*
|
|
236
|
+
* The input is refused BY NAME instead, at the boundary, before any of that
|
|
237
|
+
* can happen. `list_files` stands in for every knowledge-base tool here
|
|
238
|
+
* because they share the one choke point (`getFilesystem`) — the refusal is
|
|
239
|
+
* the context resolver's, not this tool's.
|
|
240
|
+
*/
|
|
241
|
+
describe('a call that names no branch', () => {
|
|
242
|
+
// Every shape of "the caller sent no branch". The literals are in here
|
|
243
|
+
// because a client that interpolates a variable it never set sends the
|
|
244
|
+
// STRING "undefined" — indistinguishable, in intent, from omitting it, and
|
|
245
|
+
// the one value that must never reach a clone.
|
|
246
|
+
const absent: Array<[label: string, body: Record<string, unknown>]> = [
|
|
247
|
+
['the field is missing entirely', { path: '' }],
|
|
248
|
+
['the field is empty', { branch: '', path: '' }],
|
|
249
|
+
['the field is null', { branch: null, path: '' }],
|
|
250
|
+
['the field is a number', { branch: 42, path: '' }],
|
|
251
|
+
['the field is an object', { branch: { name: 'main' }, path: '' }],
|
|
252
|
+
['the field is an array', { branch: ['main'], path: '' }],
|
|
253
|
+
['the field is the literal "undefined"', { branch: 'undefined', path: '' }],
|
|
254
|
+
['the field is the literal "null"', { branch: 'null', path: '' }],
|
|
255
|
+
];
|
|
256
|
+
|
|
257
|
+
for (const [label, body] of absent) {
|
|
258
|
+
it(`400s branch-required when ${label}`, async () => {
|
|
259
|
+
const base = await start();
|
|
260
|
+
|
|
261
|
+
const res = await callTool(base, 'list_files', body);
|
|
262
|
+
|
|
263
|
+
expect(res.status).toBe(400);
|
|
264
|
+
expect(res.body).toEqual({
|
|
265
|
+
kind: 'branch-required',
|
|
266
|
+
error: '`branch` is required: pass the branch (draft) you are working on.',
|
|
267
|
+
});
|
|
268
|
+
// The refusal is the whole story: nothing was created and nothing was
|
|
269
|
+
// cloned. An empty workspaces root is the strongest form of that
|
|
270
|
+
// claim — there is no directory named for any branch, least of all one
|
|
271
|
+
// named `undefined`.
|
|
272
|
+
expect(await workspaceDirs()).toEqual([]);
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
it('never writes `undefined` or `null` as a branch name into the answer', async () => {
|
|
277
|
+
const base = await start();
|
|
278
|
+
|
|
279
|
+
const res = await callTool(base, 'list_files', { path: '' });
|
|
280
|
+
|
|
281
|
+
// AC3, checked against the whole response rather than one field: the
|
|
282
|
+
// message names the INPUT and what to pass, never a stringified value of
|
|
283
|
+
// what was missing. `Branch "undefined" no longer exists` is exactly the
|
|
284
|
+
// sentence this must never produce again.
|
|
285
|
+
const serialized = JSON.stringify(res.body);
|
|
286
|
+
expect(serialized).not.toContain('undefined');
|
|
287
|
+
expect(serialized).not.toContain('null');
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* `call_tool_chain` is the other way every one of these tools gets called,
|
|
292
|
+
* and it is where the bug was reported from just as often. It is not a
|
|
293
|
+
* second implementation to guard: the chain's UTCP http transport POSTs to
|
|
294
|
+
* the SAME `/agent/tools/...` route this file has been calling directly, so
|
|
295
|
+
* the one refusal covers both. This test is what proves that claim rather
|
|
296
|
+
* than assuming it — with a real `CodeModeUtcpClient` reading a real
|
|
297
|
+
* manual and running real JavaScript.
|
|
298
|
+
*/
|
|
299
|
+
it('400s branch-required from inside call_tool_chain, and creates no workspace', async () => {
|
|
300
|
+
const base = await start();
|
|
301
|
+
const client = await CodeModeUtcpClient.create(process.cwd(), {
|
|
302
|
+
variables: { bevel_API_URL: base, bevel_CONNECTION_KEY: 'internal-token' },
|
|
303
|
+
} as never);
|
|
304
|
+
await client.registerManual(
|
|
305
|
+
new HttpCallTemplateSerializer().validateDict({
|
|
306
|
+
name: 'bevel',
|
|
307
|
+
call_template_type: 'http',
|
|
308
|
+
http_method: 'GET',
|
|
309
|
+
url: '${API_URL}/api/agent/internal/utcp',
|
|
310
|
+
content_type: 'application/json',
|
|
311
|
+
headers: { Authorization: 'Bearer ${CONNECTION_KEY}' },
|
|
312
|
+
}),
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
// The exact call from the specification: a chain that names the path and
|
|
316
|
+
// forgets the branch. The tool THROWS inside the chain, so the failure is
|
|
317
|
+
// caught and its message returned — the runtime's own contract for
|
|
318
|
+
// surfacing a tool error to the model.
|
|
319
|
+
const { result } = await client.callToolChain(
|
|
320
|
+
`try { return { ok: bevel.list_files({ body: { path: 'knowledge-base' } }) }; }
|
|
321
|
+
catch (err) { return { failed: err.message }; }`,
|
|
322
|
+
30_000,
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
// The tool did not run.
|
|
326
|
+
expect(result.ok).toBeUndefined();
|
|
327
|
+
// The message the chain hands the model carries the whole refusal: the
|
|
328
|
+
// status, the sentence, and the `kind` the direct caller switches on.
|
|
329
|
+
// (The status and payload are IN the message rather than on the thrown
|
|
330
|
+
// object — the sandboxed error exposes no own properties — which is why
|
|
331
|
+
// this asserts on the text the model actually reads.)
|
|
332
|
+
expect(result.failed).toContain('HTTP 400');
|
|
333
|
+
expect(result.failed).toContain('`branch` is required: pass the branch (draft) you are working on.');
|
|
334
|
+
expect(result.failed).toContain('"kind":"branch-required"');
|
|
335
|
+
// Not the sentence the bug produced — and no invented branch name in it.
|
|
336
|
+
expect(result.failed).not.toContain('no longer exists');
|
|
337
|
+
expect(result.failed).not.toContain('undefined');
|
|
338
|
+
// And the chain path refuses just as early: nothing was cloned.
|
|
339
|
+
expect(await workspaceDirs()).toEqual([]);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* AC1 says "any knowledge-base tool", so this asserts it of EVERY tool the
|
|
344
|
+
* module mounts rather than of the one this file otherwise drives. The list
|
|
345
|
+
* comes from the registry, so a tool added later is swept in automatically
|
|
346
|
+
* and cannot quietly reintroduce the bug on its own route. The guard runs
|
|
347
|
+
* ahead of every other check, which is what lets one empty body stand in
|
|
348
|
+
* for a valid call to each of them.
|
|
349
|
+
*/
|
|
350
|
+
it('400s branch-required on every mounted tool that declares `branch`', async () => {
|
|
351
|
+
const base = await start({ source: 'internal', scope: 'write' });
|
|
352
|
+
const declaresBranch = internalTools
|
|
353
|
+
.filter((t) => {
|
|
354
|
+
const body = (t.inputs as { properties?: { body?: { required?: string[] } } }).properties?.body;
|
|
355
|
+
return (body?.required ?? []).includes('branch');
|
|
356
|
+
})
|
|
357
|
+
.map((t) => t.name);
|
|
358
|
+
|
|
359
|
+
// The whole branch-taking surface, not a sample of it.
|
|
360
|
+
expect(declaresBranch.length).toBeGreaterThan(10);
|
|
361
|
+
|
|
362
|
+
for (const tool of declaresBranch) {
|
|
363
|
+
const res = await callTool(base, tool, {});
|
|
364
|
+
expect(res.status, `${tool} must 400 on a branch-less call`).toBe(400);
|
|
365
|
+
expect(res.body.kind, `${tool} must answer kind branch-required`).toBe('branch-required');
|
|
366
|
+
// No tool's refusal may name the value it did not get.
|
|
367
|
+
expect(JSON.stringify(res.body), `${tool} must not echo an absent value`).not.toContain('undefined');
|
|
368
|
+
}
|
|
369
|
+
expect(await workspaceDirs()).toEqual([]);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
it('still serves the same tool once a branch is named', async () => {
|
|
373
|
+
const base = await start();
|
|
374
|
+
// The guard refuses an absent input, not the tool: the same call with a
|
|
375
|
+
// real branch works, so the refusal cannot be a tool that simply broke.
|
|
376
|
+
expect((await callTool(base, 'list_files', { path: '' })).status).toBe(400);
|
|
377
|
+
|
|
378
|
+
const { status, body } = await listFiles(base, 'alice/draft');
|
|
379
|
+
|
|
380
|
+
expect(status).toBe(200);
|
|
381
|
+
expect((body.entries as { name: string }[]).map((e) => e.name)).toContain(KB_DIR);
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* The second half of the bug: a bootstrap that failed to clone used to leave
|
|
387
|
+
* a directory behind, and a directory named after a branch is how the
|
|
388
|
+
* platform remembers having known one. The first attempt's leftovers turned
|
|
389
|
+
* the second attempt's honest "no such branch" into "it was deleted".
|
|
390
|
+
*/
|
|
391
|
+
it('answers 404 again on a second attempt at a name that never existed', async () => {
|
|
392
|
+
const base = await start();
|
|
393
|
+
|
|
394
|
+
const first = await listFiles(base, 'nobody/never-made-this');
|
|
395
|
+
expect(first.status).toBe(404);
|
|
396
|
+
// Nothing survived the failed clone — not the repo directory, not the
|
|
397
|
+
// workspace shell around it. This is what keeps the next attempt honest.
|
|
398
|
+
expect(await workspaceDirs()).toEqual([]);
|
|
399
|
+
|
|
400
|
+
const second = await listFiles(base, 'nobody/never-made-this');
|
|
401
|
+
|
|
402
|
+
expect(second.status).toBe(404);
|
|
403
|
+
expect(second.body).toEqual({
|
|
404
|
+
kind: 'branch-not-found',
|
|
405
|
+
branch: 'nobody/never-made-this',
|
|
406
|
+
error: 'There is no branch named nobody/never-made-this.',
|
|
407
|
+
});
|
|
408
|
+
expect(await workspaceDirs()).toEqual([]);
|
|
409
|
+
});
|
|
410
|
+
|
|
184
411
|
it('410s a branch a listing showed us and origin no longer has', async () => {
|
|
185
412
|
const base = await start();
|
|
186
413
|
workspaces!.noteBranchesListed(['target-company-state', 'alice/draft']);
|
|
@@ -7,6 +7,7 @@ import { promisify } from 'node:util';
|
|
|
7
7
|
import AdmZip from 'adm-zip';
|
|
8
8
|
import express from 'express';
|
|
9
9
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
10
|
+
import { testKbContext } from '../../../__tests__/kb-context.js';
|
|
10
11
|
import { LocalFilesystem } from '@mastra/core/workspace';
|
|
11
12
|
import { ToolRegistry } from '../../tool-registry/tool-registry.js';
|
|
12
13
|
import { createToolHandlerFactory } from '../../tool-helpers/tool-handler.js';
|
|
@@ -218,10 +219,10 @@ async function start(
|
|
|
218
219
|
const app = express();
|
|
219
220
|
app.use(express.json());
|
|
220
221
|
const router = express.Router();
|
|
221
|
-
registerWorkspaceTools(registry, router, fakeAuth, toolHandler, new SpillStore(join(tmpdir(), 'bevel-test-spills')), new DocExtractService(docCacheDir), access, KB_DIR, {
|
|
222
|
+
registerWorkspaceTools(registry, router, fakeAuth, toolHandler, new SpillStore(join(tmpdir(), 'bevel-test-spills')), new DocExtractService(docCacheDir), access, testKbContext({ kbDirName: KB_DIR }), {
|
|
222
223
|
service: {} as never,
|
|
223
224
|
enabled: false, // these tests predate and don't exercise the ontology boundary
|
|
224
|
-
kbDirName: KB_DIR,
|
|
225
|
+
kb: testKbContext({ kbDirName: KB_DIR }),
|
|
225
226
|
recoveryBotEmail: 'recovery-bot@bevel.local',
|
|
226
227
|
hooks: new WorkflowHooks(),
|
|
227
228
|
}, writePolicy, {} as never /* sessionSink — start_session not exercised here */);
|
|
@@ -232,9 +233,24 @@ async function start(
|
|
|
232
233
|
return `http://127.0.0.1:${(httpServer.address() as { port: number }).port}`;
|
|
233
234
|
}
|
|
234
235
|
|
|
235
|
-
|
|
236
|
+
/** POST a body EXACTLY as given — for the tests about a malformed call. */
|
|
237
|
+
const postRaw = (url: string, body: unknown = {}) =>
|
|
236
238
|
fetch(url, { method: 'POST', headers: { 'content-type': 'application/json', authorization: 'Bearer x' }, body: JSON.stringify(body) });
|
|
237
239
|
|
|
240
|
+
/**
|
|
241
|
+
* POST a well-formed call. Every KB tool requires `branch` — a call that names
|
|
242
|
+
* none is refused at the mount with 400 `branch-required` — so this names one
|
|
243
|
+
* unless the test already did. A test ABOUT the missing input uses `postRaw`,
|
|
244
|
+
* so the thing under test is never papered over by the helper.
|
|
245
|
+
*/
|
|
246
|
+
const post = (url: string, body: unknown = {}) =>
|
|
247
|
+
postRaw(
|
|
248
|
+
url,
|
|
249
|
+
body !== null && typeof body === 'object' && !Array.isArray(body) && !('branch' in body)
|
|
250
|
+
? { branch: 'main', ...body }
|
|
251
|
+
: body,
|
|
252
|
+
);
|
|
253
|
+
|
|
238
254
|
beforeEach(() => {
|
|
239
255
|
/* fresh per test via start() */
|
|
240
256
|
});
|
|
@@ -455,7 +471,8 @@ describe('workspace file primitives', () => {
|
|
|
455
471
|
// named "undefined" — it fails closed with a clear 4xx naming the missing
|
|
456
472
|
// branch context, BEFORE any workspace resolve.
|
|
457
473
|
expect(focusedBranch).toBeUndefined();
|
|
458
|
-
|
|
474
|
+
// `postRaw`: the absent field IS the test here, so the body goes as written.
|
|
475
|
+
const res = await postRaw(`${base}/api/agent/tools/execute_command`, { command: 'echo should-not-run' });
|
|
459
476
|
expect(res.status).toBe(400);
|
|
460
477
|
expect((await res.json()).error).toMatch(/branch/i);
|
|
461
478
|
// The guard runs before `getOrCreateForBranch`, so no workspace (least of all
|
|
@@ -470,7 +487,7 @@ describe('workspace file primitives', () => {
|
|
|
470
487
|
// against that branch's workspace and returns output end to end (AC2) —
|
|
471
488
|
// rather than failing closed the way a context-less external call does.
|
|
472
489
|
focusedBranch = 'main';
|
|
473
|
-
const res = (await (await
|
|
490
|
+
const res = (await (await postRaw(`${base}/api/agent/tools/execute_command`, { command: 'echo hello-exec' })).json()) as { stdout: string; exitCode: number };
|
|
474
491
|
expect(res.exitCode).toBe(0);
|
|
475
492
|
expect(res.stdout).toContain('hello-exec');
|
|
476
493
|
// Resolved against the focused branch — never an "undefined" workspace.
|
|
@@ -554,6 +571,20 @@ describe('workspace file primitives', () => {
|
|
|
554
571
|
expect(workspacePathCalls).toEqual([]);
|
|
555
572
|
});
|
|
556
573
|
|
|
574
|
+
it('answers a branch-less call with the same kind every other KB tool uses', async () => {
|
|
575
|
+
const base = await start();
|
|
576
|
+
// The MESSAGE here is this tool's own — only `execute_command` has a
|
|
577
|
+
// focused-branch fallback to explain. The DISCRIMINATOR is shared, so a
|
|
578
|
+
// client switches on one kind across the whole surface instead of matching
|
|
579
|
+
// prose per tool.
|
|
580
|
+
for (const body of [{ command: 'x' }, { branch: '', command: 'x' }, { branch: 'undefined', command: 'x' }]) {
|
|
581
|
+
const res = await postRaw(`${base}/api/agent/tools/execute_command`, body);
|
|
582
|
+
expect(res.status).toBe(400);
|
|
583
|
+
expect((await res.json()).kind).toBe('branch-required');
|
|
584
|
+
}
|
|
585
|
+
expect(workspacePathCalls).toEqual([]);
|
|
586
|
+
});
|
|
587
|
+
|
|
557
588
|
it('execute_command validates the branch BEFORE the write-policy gate', async () => {
|
|
558
589
|
const base = await start();
|
|
559
590
|
// A routine-restricted session is refused by `assertUnrestricted` with 403.
|
|
@@ -1831,8 +1862,8 @@ describe('start_session', () => {
|
|
|
1831
1862
|
const router = express.Router();
|
|
1832
1863
|
registerWorkspaceTools(
|
|
1833
1864
|
registry, router, auth, toolHandler,
|
|
1834
|
-
new SpillStore(join(tmpdir(), 'bevel-test-spills')), new DocExtractService(join(tmpdir(), 'bevel-test-doc-extract')), allowAll, KB_DIR,
|
|
1835
|
-
{ service: {} as never, enabled: false, kbDirName: KB_DIR, recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
|
|
1865
|
+
new SpillStore(join(tmpdir(), 'bevel-test-spills')), new DocExtractService(join(tmpdir(), 'bevel-test-doc-extract')), allowAll, testKbContext({ kbDirName: KB_DIR }),
|
|
1866
|
+
{ service: {} as never, enabled: false, kb: testKbContext({ kbDirName: KB_DIR }), recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
|
|
1836
1867
|
new RoutineWritePolicyService(),
|
|
1837
1868
|
sink ?? fakeSessionSink,
|
|
1838
1869
|
);
|
|
@@ -1956,8 +1987,8 @@ describe('start_session', () => {
|
|
|
1956
1987
|
const noopAuth: express.RequestHandler = (_req, _res, next) => next();
|
|
1957
1988
|
registerWorkspaceTools(
|
|
1958
1989
|
registry, router, noopAuth, (() => () => {}) as never,
|
|
1959
|
-
new SpillStore(join(tmpdir(), 'bevel-test-spills')), new DocExtractService(join(tmpdir(), 'bevel-test-doc-extract')), allowAll, KB_DIR,
|
|
1960
|
-
{ service: {} as never, enabled: false, kbDirName: KB_DIR, recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
|
|
1990
|
+
new SpillStore(join(tmpdir(), 'bevel-test-spills')), new DocExtractService(join(tmpdir(), 'bevel-test-doc-extract')), allowAll, testKbContext({ kbDirName: KB_DIR }),
|
|
1991
|
+
{ service: {} as never, enabled: false, kb: testKbContext({ kbDirName: KB_DIR }), recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
|
|
1961
1992
|
new RoutineWritePolicyService(),
|
|
1962
1993
|
{} as never,
|
|
1963
1994
|
);
|
|
@@ -1998,8 +2029,8 @@ describe('branch is a required parameter in the tool contract', () => {
|
|
|
1998
2029
|
new SpillStore(join(tmpdir(), 'bevel-test-spills')),
|
|
1999
2030
|
new DocExtractService(join(tmpdir(), 'bevel-test-doc-extract')),
|
|
2000
2031
|
allowAll,
|
|
2001
|
-
KB_DIR,
|
|
2002
|
-
{ service: {} as never, enabled: false, kbDirName: KB_DIR, recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
|
|
2032
|
+
testKbContext({ kbDirName: KB_DIR }),
|
|
2033
|
+
{ service: {} as never, enabled: false, kb: testKbContext({ kbDirName: KB_DIR }), recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
|
|
2003
2034
|
new RoutineWritePolicyService(),
|
|
2004
2035
|
{} as never,
|
|
2005
2036
|
);
|
|
@@ -2265,6 +2296,8 @@ describe('the tools place an unprefixed path inside the repository', () => {
|
|
|
2265
2296
|
describe('folders never vanish', () => {
|
|
2266
2297
|
const KB = (p: string) => `${KB_DIR}/${p}`;
|
|
2267
2298
|
const tool = async (base: string, name: string, body: Record<string, unknown>) => {
|
|
2299
|
+
// `post` names the branch every KB tool requires; these tests are about
|
|
2300
|
+
// folders, not about the branch input.
|
|
2268
2301
|
const res = await post(`${base}/api/agent/tools/${name}`, body);
|
|
2269
2302
|
return { status: res.status, body: (await res.json()) as Record<string, unknown> };
|
|
2270
2303
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { testKbContext } from '../../../__tests__/kb-context.js';
|
|
2
3
|
import { writeDenial } from '../write-denial.js';
|
|
3
4
|
import { AccessDeniedError } from '../../access-model/access-errors.js';
|
|
4
5
|
import type { ChangeReadVerdict, IChangeReadGate } from '../../access-model/change-gate.js';
|
|
@@ -34,7 +35,7 @@ describe('writeDenial asks the read gate about the refused path as the refuser s
|
|
|
34
35
|
eligibleUsers: [],
|
|
35
36
|
targetKind: 'dir',
|
|
36
37
|
});
|
|
37
|
-
const out = await writeDenial(err, INPUT, noAccess, KB, gate);
|
|
38
|
+
const out = await writeDenial(err, INPUT, noAccess, testKbContext({ kbDirName: KB }), gate);
|
|
38
39
|
expect(judge).toHaveBeenCalledWith(
|
|
39
40
|
'target-company-state',
|
|
40
41
|
'alice@example.com',
|
|
@@ -48,7 +49,7 @@ describe('writeDenial asks the read gate about the refused path as the refuser s
|
|
|
48
49
|
it('a refusal that says nothing about its kind is judged as a file', async () => {
|
|
49
50
|
const { gate, judge } = gateThat({ allowed: false, unreadable: 'KnowledgeBase' });
|
|
50
51
|
const err = new AccessDeniedError({ path: `${KB}/KnowledgeBase/loose.md`, eligibleRoles: [], eligibleUsers: [] });
|
|
51
|
-
const out = await writeDenial(err, INPUT, noAccess, KB, gate);
|
|
52
|
+
const out = await writeDenial(err, INPUT, noAccess, testKbContext({ kbDirName: KB }), gate);
|
|
52
53
|
expect(judge).toHaveBeenCalledWith(expect.any(String), 'alice@example.com', `${KB}/KnowledgeBase/loose.md`, 'file');
|
|
53
54
|
expect(out.details).toMatchObject({
|
|
54
55
|
kind: 'write-denied',
|
|
@@ -60,7 +61,7 @@ describe('writeDenial asks the read gate about the refused path as the refuser s
|
|
|
60
61
|
it('without a gate the read verdict alone decides, as before', async () => {
|
|
61
62
|
const accessControl = { canRead: vi.fn(async () => true) } as unknown as IAccessControl;
|
|
62
63
|
const err = new AccessDeniedError({ path: `${KB}/KnowledgeBase/Sales/deal.md`, eligibleRoles: [], eligibleUsers: [] });
|
|
63
|
-
const out = await writeDenial(err, INPUT, accessControl, KB);
|
|
64
|
+
const out = await writeDenial(err, INPUT, accessControl, testKbContext({ kbDirName: KB }));
|
|
64
65
|
expect(accessControl.canRead).toHaveBeenCalledWith('target-company-state', 'alice@example.com', 'KnowledgeBase/Sales/deal.md');
|
|
65
66
|
expect(out.details).toMatchObject({ kind: 'write-denied', canPropose: true });
|
|
66
67
|
});
|
|
@@ -68,7 +69,7 @@ describe('writeDenial asks the read gate about the refused path as the refuser s
|
|
|
68
69
|
it('a gate that cannot answer refuses to offer the route', async () => {
|
|
69
70
|
const gate: IChangeReadGate = { judge: vi.fn(async () => { throw new Error('git down'); }), assertMayChange: vi.fn() };
|
|
70
71
|
const err = new AccessDeniedError({ path: `${KB}/KnowledgeBase/Sales/deal.md`, eligibleRoles: [], eligibleUsers: [] });
|
|
71
|
-
const out = await writeDenial(err, INPUT, noAccess, KB, gate);
|
|
72
|
+
const out = await writeDenial(err, INPUT, noAccess, testKbContext({ kbDirName: KB }), gate);
|
|
72
73
|
expect(out.details).toMatchObject({ canPropose: false });
|
|
73
74
|
expect(out.details?.cannotProposeReason).toContain('could not be determined');
|
|
74
75
|
});
|