@bevel-software/platform-core-backend 0.21.0 → 0.23.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/core-ports.d.ts +11 -1
- 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 +3 -3
- package/dist/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +62 -13
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +22 -3
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +158 -23
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core/lifecycle.d.ts +34 -1
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +89 -13
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/core-config.d.ts +0 -12
- package/dist/core-config.d.ts.map +1 -1
- package/dist/core-config.js +11 -13
- package/dist/core-config.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/modules/access/access-control.interface.d.ts +42 -12
- package/dist/modules/access/access-control.interface.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +67 -10
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +214 -35
- 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.map +1 -1
- package/dist/modules/access/access.routes.js +13 -15
- package/dist/modules/access/access.routes.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/auth/account-admission.d.ts +58 -7
- package/dist/modules/auth/account-admission.d.ts.map +1 -1
- package/dist/modules/auth/account-admission.js +44 -1
- package/dist/modules/auth/account-admission.js.map +1 -1
- package/dist/modules/auth/account.routes.d.ts +1 -1
- package/dist/modules/auth/account.routes.d.ts.map +1 -1
- package/dist/modules/auth/account.routes.js +61 -5
- package/dist/modules/auth/account.routes.js.map +1 -1
- package/dist/modules/auth/auth.middleware.d.ts +1 -1
- package/dist/modules/auth/auth.middleware.d.ts.map +1 -1
- package/dist/modules/auth/auth.middleware.js +18 -7
- package/dist/modules/auth/auth.middleware.js.map +1 -1
- package/dist/modules/auth/auth.routes.d.ts.map +1 -1
- package/dist/modules/auth/auth.routes.js +8 -0
- package/dist/modules/auth/auth.routes.js.map +1 -1
- package/dist/modules/auth/auth.service.d.ts +96 -3
- package/dist/modules/auth/auth.service.d.ts.map +1 -1
- package/dist/modules/auth/auth.service.js +187 -9
- 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 +7 -2
- package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
- package/dist/modules/database/core-schema.d.ts +41 -24
- package/dist/modules/database/core-schema.d.ts.map +1 -1
- package/dist/modules/database/core-schema.js +35 -27
- package/dist/modules/database/core-schema.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.map +1 -1
- package/dist/modules/kb-fs/branch-name.js +12 -2
- package/dist/modules/kb-fs/branch-name.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/kb-fs/repo-path.d.ts +11 -16
- package/dist/modules/kb-fs/repo-path.d.ts.map +1 -1
- package/dist/modules/kb-fs/repo-path.js +79 -0
- package/dist/modules/kb-fs/repo-path.js.map +1 -1
- package/dist/modules/kb-sync/kb-sync.routes.d.ts +2 -2
- package/dist/modules/kb-sync/kb-sync.routes.d.ts.map +1 -1
- package/dist/modules/kb-sync/kb-sync.routes.js +14 -3
- package/dist/modules/kb-sync/kb-sync.routes.js.map +1 -1
- package/dist/modules/kb-sync/sync-auth.d.ts +3 -1
- package/dist/modules/kb-sync/sync-auth.d.ts.map +1 -1
- package/dist/modules/kb-sync/sync-auth.js +1 -1
- package/dist/modules/kb-sync/sync-auth.js.map +1 -1
- package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
- package/dist/modules/mcp/mcp-auth.middleware.js +21 -6
- package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js +3 -2
- package/dist/modules/mcp/oauth/bevel-oauth-provider.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-requests.service.d.ts +111 -18
- package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
- package/dist/modules/plugins/join-requests.service.js +173 -29
- package/dist/modules/plugins/join-requests.service.js.map +1 -1
- package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.routes.js +3 -2
- package/dist/modules/plugins/plugins.routes.js.map +1 -1
- package/dist/modules/settings/deployment-settings.service.d.ts +22 -1
- package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
- package/dist/modules/settings/deployment-settings.service.js +101 -7
- 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 +78 -4
- package/dist/modules/settings/setup.routes.d.ts.map +1 -1
- package/dist/modules/settings/setup.routes.js +379 -17
- package/dist/modules/settings/setup.routes.js.map +1 -1
- package/dist/modules/skills/skill-access-requests.routes.d.ts +6 -8
- package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -1
- package/dist/modules/skills/skill-access-requests.routes.js +24 -63
- package/dist/modules/skills/skill-access-requests.routes.js.map +1 -1
- package/dist/modules/skills/skills.contract.d.ts +90 -18
- package/dist/modules/skills/skills.contract.d.ts.map +1 -1
- package/dist/modules/skills/skills.contract.js +4 -1
- package/dist/modules/skills/skills.contract.js.map +1 -1
- package/dist/modules/skills/skills.service.d.ts +98 -9
- package/dist/modules/skills/skills.service.d.ts.map +1 -1
- package/dist/modules/skills/skills.service.js +239 -37
- package/dist/modules/skills/skills.service.js.map +1 -1
- package/dist/modules/skills/skills.tools.d.ts +7 -0
- package/dist/modules/skills/skills.tools.d.ts.map +1 -1
- package/dist/modules/skills/skills.tools.js +71 -7
- package/dist/modules/skills/skills.tools.js.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.js +4 -2
- package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
- package/dist/modules/tool-auth/internal-token.service.d.ts +3 -3
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts +16 -7
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.js +34 -12
- package/dist/modules/tool-auth/tool-auth.middleware.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-helpers/tool-handler.d.ts +2 -1
- package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool-handler.js +25 -4
- package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
- package/dist/modules/tool-helpers/tool.contract.d.ts +3 -2
- package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
- package/dist/modules/tool-helpers/validate-token.js +1 -1
- package/dist/modules/tool-helpers/validate-token.js.map +1 -1
- package/dist/modules/workflow/agent-tools/change-request-summary.d.ts +98 -0
- package/dist/modules/workflow/agent-tools/change-request-summary.d.ts.map +1 -0
- package/dist/modules/workflow/agent-tools/change-request-summary.js +81 -0
- package/dist/modules/workflow/agent-tools/change-request-summary.js.map +1 -0
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.js +113 -37
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
- package/dist/modules/workflow/file-lock.service.d.ts +24 -0
- package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
- package/dist/modules/workflow/file-lock.service.js +30 -0
- package/dist/modules/workflow/file-lock.service.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +72 -1
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +170 -6
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -1
- package/dist/modules/workflow/git/node-git-runner.js +5 -0
- 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/pending-commits.service.d.ts +38 -0
- package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
- package/dist/modules/workflow/pending-commits.service.js +55 -0
- package/dist/modules/workflow/pending-commits.service.js.map +1 -1
- package/dist/modules/workflow/workflow-hooks.d.ts +54 -32
- package/dist/modules/workflow/workflow-hooks.d.ts.map +1 -1
- package/dist/modules/workflow/workflow-hooks.js +16 -1
- package/dist/modules/workflow/workflow-hooks.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 +94 -13
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +258 -51
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/agent-access.gate.d.ts +94 -0
- package/dist/modules/workspace/agent-access.gate.d.ts.map +1 -0
- package/dist/modules/workspace/agent-access.gate.js +123 -0
- package/dist/modules/workspace/agent-access.gate.js.map +1 -0
- package/dist/modules/workspace/routine-write-policy.d.ts +5 -6
- package/dist/modules/workspace/routine-write-policy.d.ts.map +1 -1
- package/dist/modules/workspace/routine-write-policy.js +5 -6
- package/dist/modules/workspace/routine-write-policy.js.map +1 -1
- package/dist/modules/workspace/session-sink.d.ts +5 -5
- package/dist/modules/workspace/set-aside-clone.d.ts +46 -0
- package/dist/modules/workspace/set-aside-clone.d.ts.map +1 -0
- package/dist/modules/workspace/set-aside-clone.js +92 -0
- package/dist/modules/workspace/set-aside-clone.js.map +1 -0
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts +117 -1
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.js +190 -1
- package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.routes.js +92 -3
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +115 -5
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +272 -26
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts +2 -2
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +337 -117
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/modules/write-access/write-access.d.ts +60 -0
- package/dist/modules/write-access/write-access.d.ts.map +1 -0
- package/dist/modules/write-access/write-access.js +129 -0
- package/dist/modules/write-access/write-access.js.map +1 -0
- package/dist/shared/domain-errors.d.ts +64 -0
- package/dist/shared/domain-errors.d.ts.map +1 -1
- package/dist/shared/domain-errors.js +83 -0
- package/dist/shared/domain-errors.js.map +1 -1
- package/dist/shared/git.contract.d.ts +30 -0
- package/dist/shared/git.contract.d.ts.map +1 -1
- package/dist/shared/git.contract.js +26 -0
- package/dist/shared/git.contract.js.map +1 -1
- package/dist/tenancy/static-tenant-source.d.ts +0 -1
- package/dist/tenancy/static-tenant-source.d.ts.map +1 -1
- package/dist/tenancy/static-tenant-source.js +0 -2
- package/dist/tenancy/static-tenant-source.js.map +1 -1
- package/migrations/0014_change_request_closed_reason.sql +1 -0
- package/migrations/0015_account_deactivation.sql +3 -0
- package/migrations/meta/0014_snapshot.json +2265 -0
- package/migrations/meta/0015_snapshot.json +2271 -0
- package/migrations/meta/_journal.json +14 -0
- package/package.json +3 -3
- package/src/__tests__/kb-layout-config.test.ts +0 -2
- package/src/__tests__/retired-settings.test.ts +96 -0
- package/src/core/__tests__/gated-boot.test.ts +132 -0
- package/src/core/__tests__/lifecycle.test.ts +170 -1
- package/src/core/__tests__/set-aside-root-is-one-place.test.ts +63 -0
- package/src/core/core-ports.ts +11 -1
- package/src/core/create-core-server.ts +69 -15
- package/src/core/create-core-services.ts +190 -27
- package/src/core/lifecycle.ts +98 -13
- package/src/core-config.ts +13 -14
- package/src/index.ts +12 -1
- package/src/modules/access/__tests__/access-control.preview-relocation.test.ts +385 -0
- package/src/modules/access/__tests__/access-control.prospective.test.ts +94 -18
- 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.prospective.test.ts +6 -7
- package/src/modules/access/access-control.interface.ts +43 -12
- package/src/modules/access/access-control.service.ts +234 -36
- 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 +13 -15
- package/src/modules/access-model/access-grammar.ts +22 -0
- package/src/modules/agent-instructions/__tests__/agent-instructions.route.test.ts +3 -1
- package/src/modules/auth/__tests__/account-deactivation.test.ts +252 -0
- package/src/modules/auth/__tests__/account.routes.test.ts +81 -3
- package/src/modules/auth/__tests__/auth.middleware.test.ts +45 -22
- package/src/modules/auth/__tests__/auth.service.test.ts +39 -1
- package/src/modules/auth/account-admission.ts +78 -9
- package/src/modules/auth/account.routes.ts +63 -7
- package/src/modules/auth/auth.middleware.ts +19 -8
- package/src/modules/auth/auth.routes.ts +8 -0
- package/src/modules/auth/auth.service.ts +207 -7
- package/src/modules/auth/oidc-auth-provider.ts +7 -2
- package/src/modules/database/core-schema.ts +35 -27
- 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 +10 -0
- package/src/modules/kb-fs/__tests__/remote-url.test.ts +38 -0
- package/src/modules/kb-fs/__tests__/repo-path.test.ts +123 -0
- package/src/modules/kb-fs/branch-name.ts +14 -1
- package/src/modules/kb-fs/remote-url.ts +35 -0
- package/src/modules/kb-fs/repo-path.ts +85 -0
- package/src/modules/kb-sync/__tests__/kb-sync.routes.test.ts +26 -1
- package/src/modules/kb-sync/kb-sync.routes.ts +14 -4
- package/src/modules/kb-sync/sync-auth.ts +2 -2
- package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +60 -3
- package/src/modules/mcp/__tests__/mcp.service.test.ts +68 -6
- package/src/modules/mcp/mcp-auth.middleware.ts +20 -6
- package/src/modules/mcp/oauth/bevel-oauth-provider.ts +3 -1
- package/src/modules/plugins/__tests__/join-proposals.test.ts +100 -19
- package/src/modules/plugins/__tests__/join-requests.service.test.ts +27 -11
- package/src/modules/plugins/__tests__/join-requests.settlement.test.ts +371 -0
- package/src/modules/plugins/__tests__/plugins.routes.test.ts +1 -1
- package/src/modules/plugins/__tests__/plugins.tools.test.ts +2 -1
- package/src/modules/plugins/join-proposals.ts +87 -19
- package/src/modules/plugins/join-requests.service.ts +199 -39
- package/src/modules/plugins/plugins.routes.ts +3 -2
- package/src/modules/settings/__tests__/deployment-settings.service.test.ts +16 -0
- package/src/modules/settings/__tests__/repository-source.test.ts +191 -0
- package/src/modules/settings/__tests__/setup.routes.git-mode.test.ts +386 -0
- package/src/modules/settings/__tests__/setup.routes.github-app.test.ts +299 -0
- package/src/modules/settings/__tests__/setup.routes.managed-phase.test.ts +236 -0
- package/src/modules/settings/__tests__/setup.routes.repository-change.test.ts +390 -0
- package/src/modules/settings/__tests__/setup.routes.test.ts +3 -0
- package/src/modules/settings/deployment-settings.service.ts +117 -6
- 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 +463 -15
- package/src/modules/skills/__tests__/allowed-tools-warn.tools.test.ts +2 -1
- package/src/modules/skills/__tests__/branch-skills.tools.test.ts +218 -0
- package/src/modules/skills/__tests__/skill-access-requests.routes.test.ts +5 -1
- package/src/modules/skills/__tests__/skills.service.test.ts +229 -5
- package/src/modules/skills/skill-access-requests.routes.ts +25 -75
- package/src/modules/skills/skills.contract.ts +91 -18
- package/src/modules/skills/skills.service.ts +278 -41
- package/src/modules/skills/skills.tools.ts +80 -8
- package/src/modules/tool-auth/__tests__/manual-auth.middleware.test.ts +14 -1
- package/src/modules/tool-auth/external-api-key.service.ts +4 -2
- package/src/modules/tool-auth/internal-token.service.ts +3 -3
- package/src/modules/tool-auth/tool-auth.middleware.ts +34 -11
- package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +5 -3
- package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +3 -3
- package/src/modules/tool-helpers/__tests__/validate-token.test.ts +11 -1
- package/src/modules/tool-helpers/tool-context.ts +15 -0
- package/src/modules/tool-helpers/tool-handler.ts +24 -4
- package/src/modules/tool-helpers/tool.contract.ts +3 -2
- package/src/modules/tool-helpers/validate-token.ts +1 -1
- package/src/modules/workflow/__tests__/apply-failure.test.ts +9 -1
- package/src/modules/workflow/__tests__/pending-commits.repository-replaced.test.ts +111 -0
- package/src/modules/workflow/__tests__/workflow.routes.history-read-gate.test.ts +25 -0
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +159 -8
- package/src/modules/workflow/__tests__/workflow.service.repository-replaced.test.ts +249 -0
- package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +146 -40
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +405 -7
- package/src/modules/workflow/agent-tools/change-request-summary.ts +182 -0
- package/src/modules/workflow/agent-tools/workflow.tools.ts +135 -38
- package/src/modules/workflow/file-lock.service.ts +31 -0
- package/src/modules/workflow/git/__tests__/git.service.fileBytesAtCommit.test.ts +260 -0
- package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +121 -0
- 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 +193 -4
- package/src/modules/workflow/git/node-git-runner.ts +6 -0
- package/src/modules/workflow/git/pull-request.service.ts +119 -0
- package/src/modules/workflow/pending-commits.service.ts +59 -1
- package/src/modules/workflow/workflow-hooks.ts +64 -26
- package/src/modules/workflow/workflow.routes.ts +3 -1
- package/src/modules/workflow/workflow.service.ts +290 -55
- package/src/modules/workspace/__tests__/agent-access.gate.test.ts +208 -0
- package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +384 -0
- package/src/modules/workspace/__tests__/file-stat-access.test.ts +2 -1
- package/src/modules/workspace/__tests__/git-internals.security.test.ts +2 -1
- package/src/modules/workspace/__tests__/set-aside-clone.test.ts +52 -0
- package/src/modules/workspace/__tests__/workspace.routes.at-ref.test.ts +305 -0
- package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +2 -0
- package/src/modules/workspace/__tests__/workspace.service.forget-clone-races.test.ts +147 -0
- package/src/modules/workspace/__tests__/workspace.service.replaced-repository.test.ts +326 -0
- package/src/modules/workspace/__tests__/workspace.service.test.ts +20 -9
- package/src/modules/workspace/__tests__/workspace.service.unknown-branch.test.ts +43 -0
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +2 -3
- package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +235 -10
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +720 -17
- package/src/modules/workspace/agent-access.gate.ts +164 -0
- package/src/modules/workspace/routine-write-policy.ts +5 -6
- package/src/modules/workspace/session-sink.ts +5 -5
- package/src/modules/workspace/set-aside-clone.ts +96 -0
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +297 -0
- package/src/modules/workspace/startup/kb-startup-runner.ts +242 -2
- package/src/modules/workspace/workspace.routes.ts +95 -3
- package/src/modules/workspace/workspace.service.ts +273 -25
- package/src/modules/workspace/workspace.tools.ts +373 -119
- package/src/modules/write-access/__tests__/write-access.test.ts +248 -0
- package/src/modules/write-access/write-access.ts +153 -0
- package/src/shared/domain-errors.ts +89 -0
- package/src/shared/git.contract.ts +37 -0
- package/src/tenancy/__tests__/static-tenant-source.test.ts +0 -1
- package/src/tenancy/static-tenant-source.ts +0 -3
- package/dist/modules/workflow/session-ontology.policy.d.ts +0 -52
- package/dist/modules/workflow/session-ontology.policy.d.ts.map +0 -1
- package/dist/modules/workflow/session-ontology.policy.js +0 -62
- package/dist/modules/workflow/session-ontology.policy.js.map +0 -1
- package/dist/modules/workflow/session-ontology.service.d.ts +0 -105
- package/dist/modules/workflow/session-ontology.service.d.ts.map +0 -1
- package/dist/modules/workflow/session-ontology.service.js +0 -147
- package/dist/modules/workflow/session-ontology.service.js.map +0 -1
- package/dist/modules/workspace/session-ontology.gate.d.ts +0 -114
- package/dist/modules/workspace/session-ontology.gate.d.ts.map +0 -1
- package/dist/modules/workspace/session-ontology.gate.js +0 -161
- package/dist/modules/workspace/session-ontology.gate.js.map +0 -1
- package/dist/shared/kb-layout.d.ts +0 -39
- package/dist/shared/kb-layout.d.ts.map +0 -1
- package/dist/shared/kb-layout.js +0 -103
- package/dist/shared/kb-layout.js.map +0 -1
- package/dist/shared/kb-layout.test.d.ts +0 -2
- package/dist/shared/kb-layout.test.d.ts.map +0 -1
- package/dist/shared/kb-layout.test.js +0 -75
- package/dist/shared/kb-layout.test.js.map +0 -1
- package/src/modules/workflow/__tests__/session-ontology.policy.test.ts +0 -62
- package/src/modules/workflow/__tests__/session-ontology.service.test.ts +0 -201
- package/src/modules/workflow/session-ontology.policy.ts +0 -70
- package/src/modules/workflow/session-ontology.service.ts +0 -183
- package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +0 -239
- package/src/modules/workspace/session-ontology.gate.ts +0 -191
- package/src/shared/kb-layout.test.ts +0 -98
- package/src/shared/kb-layout.ts +0 -102
|
@@ -10,6 +10,7 @@ import { createDiffRoutes } from '../modules/diff/diff.routes.js';
|
|
|
10
10
|
import { createWorkflowRoutes } from '../modules/workflow/workflow.routes.js';
|
|
11
11
|
import { createEventsRoutes } from '../modules/workflow/events.routes.js';
|
|
12
12
|
import { createAccessRoutes } from '../modules/access/access.routes.js';
|
|
13
|
+
import { createAccessRequestRoutes } from '../modules/access/access-requests.routes.js';
|
|
13
14
|
import { createMcpRoutes } from '../modules/mcp/mcp.routes.js';
|
|
14
15
|
import { createOAuthConsentRoutes } from '../modules/mcp/oauth/oauth-consent.routes.js';
|
|
15
16
|
import { mcpAuthRouter } from '@modelcontextprotocol/sdk/server/auth/router.js';
|
|
@@ -36,7 +37,7 @@ import {
|
|
|
36
37
|
registerPluginsTools,
|
|
37
38
|
} from '../modules/plugins/index.js';
|
|
38
39
|
import { keyOrSessionAuth } from '../modules/tool-auth/key-or-session.middleware.js';
|
|
39
|
-
import type
|
|
40
|
+
import { ToolDescriptionNotes, type AgentAccessGate } from '../modules/workspace/agent-access.gate.js';
|
|
40
41
|
import {
|
|
41
42
|
createSecretsVaultRoutes,
|
|
42
43
|
createSecretsVaultPublicRoutes,
|
|
@@ -50,7 +51,8 @@ import { createConnectionKeysAdminRoutes } from '../modules/tool-auth/connection
|
|
|
50
51
|
import { createAuditRoutes } from '../modules/audit/audit.routes.js';
|
|
51
52
|
import { createAgentRestAuditMiddleware } from '../modules/audit/agent-rest-audit.middleware.js';
|
|
52
53
|
import { EXTERNAL_KB_MANUAL_NAME } from '../modules/tool-manuals/tool-manuals.contract.js';
|
|
53
|
-
import { createSetupRoutes } from '../modules/settings/setup.routes.js';
|
|
54
|
+
import { createSetupRoutes, isComplete } from '../modules/settings/setup.routes.js';
|
|
55
|
+
import { createGitHubAppRoutes } from '../modules/github-app/index.js';
|
|
54
56
|
import { oidcRedirectUri } from '../modules/auth/oidc-auth-provider.js';
|
|
55
57
|
import { repositoryConnectionCheck } from '../modules/settings/connection-check.js';
|
|
56
58
|
import { rootFolderListerFor } from '../modules/settings/git-root-folders.js';
|
|
@@ -70,6 +72,7 @@ import { publicConfig } from './public-config.js';
|
|
|
70
72
|
import { createReadiness } from './readiness.js';
|
|
71
73
|
import { createAgentInstructionsRoutes } from '../modules/agent-instructions/index.js';
|
|
72
74
|
import type { CoreServices } from './create-core-services.js';
|
|
75
|
+
import { createWriteAccessRoutes, createWriteGateMiddleware } from '../modules/write-access/write-access.js';
|
|
73
76
|
|
|
74
77
|
type ExpressApp = ReturnType<typeof express>;
|
|
75
78
|
|
|
@@ -83,8 +86,8 @@ export interface ToolSurfaceCtx {
|
|
|
83
86
|
router: Router;
|
|
84
87
|
toolAuth: RequestHandler;
|
|
85
88
|
toolHandler: CoreServices['toolHandlerFactory'];
|
|
86
|
-
/** Shared
|
|
87
|
-
|
|
89
|
+
/** Shared agent-access gate config (file tools + graph tools). */
|
|
90
|
+
agentAccessGate: AgentAccessGate;
|
|
88
91
|
core: CoreServices;
|
|
89
92
|
}
|
|
90
93
|
|
|
@@ -198,6 +201,14 @@ export async function createCoreServer(
|
|
|
198
201
|
// is mounted again below, once the body is parsed and once the caller is
|
|
199
202
|
// known (see the two mounts under `/api/workspace/:id`).
|
|
200
203
|
app.use('/api/workspace/:id', createGitInternalsRouteGuard(core.workspaceService));
|
|
204
|
+
// The read-only gate, ahead of every route — core's, the tool surface's
|
|
205
|
+
// and an overlay's alike — so a read-only deployment refuses a change
|
|
206
|
+
// wherever it would enter. It lets through what signs people in, manages
|
|
207
|
+
// accounts and configures the deployment (see `ALWAYS_WRITABLE`); write
|
|
208
|
+
// tools are judged by the tool layer. A no-op unless a host fills
|
|
209
|
+
// `ports.writeAccess`. Ahead of the body parser too: a refused write is
|
|
210
|
+
// refused with its own 403, never parsed first (and answered 400 or 413).
|
|
211
|
+
app.use(createWriteGateMiddleware(core.writeAccess));
|
|
201
212
|
app.use((req, res, next) => {
|
|
202
213
|
if (jsonExemptPaths.has(req.path) || isSyncRawBodyPath(req.path)) return next();
|
|
203
214
|
return globalJson(req, res, next);
|
|
@@ -418,24 +429,23 @@ export async function createCoreServer(
|
|
|
418
429
|
},
|
|
419
430
|
}),
|
|
420
431
|
);
|
|
421
|
-
// Shared
|
|
422
|
-
//
|
|
423
|
-
//
|
|
424
|
-
//
|
|
425
|
-
//
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
enabled: core.config.ontologySessionBlock,
|
|
429
|
-
kb: core.kb,
|
|
432
|
+
// Shared agent-access gate config, consumed by every tool surface that
|
|
433
|
+
// touches the KB (file tools + graph tools). The gate decides nothing
|
|
434
|
+
// itself: it calls the read and write hooks a deployment registered on
|
|
435
|
+
// `workflowService.hooks`, and carries the notes that deployment wants
|
|
436
|
+
// agents to read about the gated tools. Core registers neither, so a
|
|
437
|
+
// core-only deployment refuses nothing and says nothing extra.
|
|
438
|
+
const agentAccessGate: AgentAccessGate = {
|
|
430
439
|
recoveryBotEmail: RECOVERY_BOT_EMAIL,
|
|
431
440
|
hooks: core.workflowService.hooks,
|
|
441
|
+
notes: new ToolDescriptionNotes(),
|
|
432
442
|
};
|
|
433
443
|
// A skill's `allowed-tools`, checked against what the caller can see — on
|
|
434
444
|
// every save surface (agent write tools, the app's PUT /file) and on
|
|
435
445
|
// `get_skill`. Warnings only; it never refuses a save.
|
|
436
446
|
const allowedToolsChecker = new AllowedToolsChecker(core.toolRegistry, core.toolManualService, core.kb);
|
|
437
447
|
registerWorkflowTools(core.toolRegistry, toolsRouter, ta, th, core.kb);
|
|
438
|
-
registerWorkspaceTools(core.toolRegistry, toolsRouter, ta, th, core.spillStore, core.docExtractService, core.accessControl, core.kb,
|
|
448
|
+
registerWorkspaceTools(core.toolRegistry, toolsRouter, ta, th, core.spillStore, core.docExtractService, core.accessControl, core.kb, agentAccessGate, core.routineWritePolicy, core.sessionSink, allowedToolsChecker, core.changeGate);
|
|
439
449
|
registerSkillsTools(core.toolRegistry, toolsRouter, ta, th, core.skillService, allowedToolsChecker);
|
|
440
450
|
// Definitions only: the endpoints they describe are the app's own plugin
|
|
441
451
|
// creation routes, mounted below behind the key-or-session gate.
|
|
@@ -453,7 +463,7 @@ export async function createCoreServer(
|
|
|
453
463
|
router: toolsRouter,
|
|
454
464
|
toolAuth: ta,
|
|
455
465
|
toolHandler: th,
|
|
456
|
-
|
|
466
|
+
agentAccessGate,
|
|
457
467
|
core,
|
|
458
468
|
});
|
|
459
469
|
toolsRouter.use(createManualRoutes(
|
|
@@ -544,6 +554,7 @@ export async function createCoreServer(
|
|
|
544
554
|
// request also gets the resolved form judged — a link in the repository that
|
|
545
555
|
// points into the git folder — before any read gate or lock.
|
|
546
556
|
app.use('/api/workspace/:id', core.authMiddleware, createGitInternalsRouteGuard(core.workspaceService));
|
|
557
|
+
app.use('/api', core.authMiddleware, createWriteAccessRoutes(core.writeAccess));
|
|
547
558
|
app.use('/api', core.authMiddleware, createWorkspaceRoutes(
|
|
548
559
|
core.workspaceService,
|
|
549
560
|
core.authService,
|
|
@@ -591,6 +602,18 @@ export async function createCoreServer(
|
|
|
591
602
|
core.kb,
|
|
592
603
|
[core.config.adminEmail],
|
|
593
604
|
));
|
|
605
|
+
// Asking for Can edit or Owner on an item from its Manage access dialog, and
|
|
606
|
+
// the editors' Accept / Decline. Mounted beside the access routes it shares
|
|
607
|
+
// its gate with: the request is refused by the same canWrite it would
|
|
608
|
+
// otherwise have to wait for.
|
|
609
|
+
app.use('/api', core.authMiddleware, createAccessRequestRoutes({
|
|
610
|
+
accessControl: core.accessControl,
|
|
611
|
+
workspaceService: core.workspaceService,
|
|
612
|
+
authService: core.authService,
|
|
613
|
+
workflow: core.workflowService,
|
|
614
|
+
lifecycle: core.joinRequestsService,
|
|
615
|
+
kb: core.kb,
|
|
616
|
+
}));
|
|
594
617
|
app.use(
|
|
595
618
|
'/api',
|
|
596
619
|
core.authMiddleware,
|
|
@@ -700,8 +723,39 @@ export async function createCoreServer(
|
|
|
700
723
|
repositoryConnectionCheck(core.gitRunner),
|
|
701
724
|
rootFolderListerFor(core.gitRunner),
|
|
702
725
|
oidcRedirectUri(core.config.publicBackendUrl),
|
|
726
|
+
// The two sign-in checks keep their defaults.
|
|
727
|
+
undefined,
|
|
728
|
+
undefined,
|
|
729
|
+
{
|
|
730
|
+
source: core.repositorySource,
|
|
731
|
+
ensureManaged: (branch) => core.managedRepository.ensure(core.gitRunner, branch),
|
|
732
|
+
githubApp: core.githubApp,
|
|
733
|
+
},
|
|
734
|
+
// What a move to another repository has to decide about, and what it
|
|
735
|
+
// runs under. Bound here rather than handed the whole workflow service:
|
|
736
|
+
// the setup routes ask two questions, hold the commit worker for the
|
|
737
|
+
// move, and know nothing else about a request or a commit.
|
|
738
|
+
{
|
|
739
|
+
countOpen: () => core.workflowService.countOpenChangeRequests(),
|
|
740
|
+
closeAsRepositoryReplaced: () => core.workflowService.closeOpenChangeRequestsAsRepositoryReplaced(),
|
|
741
|
+
whileCommitsHeld: (work) => core.whileCommitsHeld(work),
|
|
742
|
+
},
|
|
703
743
|
),
|
|
704
744
|
);
|
|
745
|
+
// Connecting a repository on GitHub through a GitHub App: the round trips
|
|
746
|
+
// to GitHub the setup screen starts, behind the same sign-in.
|
|
747
|
+
app.use(
|
|
748
|
+
'/api',
|
|
749
|
+
core.authMiddleware,
|
|
750
|
+
createGitHubAppRoutes({
|
|
751
|
+
settings: core.settings,
|
|
752
|
+
connection: core.githubApp,
|
|
753
|
+
adminAccess: core.adminAccess,
|
|
754
|
+
publicBackendUrl: core.config.publicBackendUrl,
|
|
755
|
+
publicFrontendUrl: core.config.publicFrontendUrl,
|
|
756
|
+
isComplete: () => isComplete(core.settings, core.kb, core.repositorySource),
|
|
757
|
+
}),
|
|
758
|
+
);
|
|
705
759
|
const toolPageUser = async (userId: string): Promise<AuthUser | undefined> => {
|
|
706
760
|
const u = await core.authService.getUserById(userId);
|
|
707
761
|
return u ? ({ id: u.id, email: u.email, name: u.name } as AuthUser) : undefined;
|
|
@@ -12,6 +12,7 @@ import { sql } from 'drizzle-orm';
|
|
|
12
12
|
import { DEFAULT_DB_SCHEMA, assertSearchPath } from '../modules/database/connection.js';
|
|
13
13
|
import { DEFAULT_SECRETS_SCOPE } from '../modules/secrets-vault/secrets-variable-loader.js';
|
|
14
14
|
import { KbContext } from '../shared/kb-context.js';
|
|
15
|
+
import { branchForWorkspaceId } from '../shared/workspace-id.js';
|
|
15
16
|
import { getDb, type Database } from '../modules/database/connection.js';
|
|
16
17
|
import { runCoreMigrations } from '../modules/database/migrate.js';
|
|
17
18
|
import { coreMigrationsDir } from '../assets.js';
|
|
@@ -30,9 +31,12 @@ import { KbSyncService } from '../modules/kb-sync/kb-sync.service.js';
|
|
|
30
31
|
import { NodeFs } from '../modules/kb-fs/node-fs.js';
|
|
31
32
|
import { assertKbDirNameFree } from '../modules/kb-fs/repo-path.js';
|
|
32
33
|
import type { IFsProbe, ITreeWalker } from '../shared/fs.contract.js';
|
|
33
|
-
import {
|
|
34
|
+
import type { IGitRunner } from '../shared/git.contract.js';
|
|
35
|
+
import { ManagedRepository, MANAGED_DEFAULT_BRANCH } from '../modules/settings/managed-repository.js';
|
|
36
|
+
import { RepositorySource } from '../modules/settings/repository-source.js';
|
|
37
|
+
import { GitHubAppConnection } from '../modules/github-app/index.js';
|
|
34
38
|
import { AdvisoryLease, AdvisoryLock } from '../modules/database/advisory-lock.js';
|
|
35
|
-
import { holdCommitWorkerLease, withStartupTask, type LeaseLoopHandle } from './lifecycle.js';
|
|
39
|
+
import { holdCommitWorkerLease, holdable, withStartupTask, type LeaseLoopHandle } from './lifecycle.js';
|
|
36
40
|
|
|
37
41
|
/** The hosted MCP endpoint at a deployment address, with any userinfo stripped. */
|
|
38
42
|
function mcpEndpointUrl(publicBackendUrl: string): string {
|
|
@@ -107,7 +111,6 @@ import { WorkflowEventBus } from '../modules/workflow/event-bus.js';
|
|
|
107
111
|
import { FileChangeNotifier } from '../modules/kb-fs/file-change-notifier.js';
|
|
108
112
|
import { WorkflowService } from '../modules/workflow/workflow.service.js';
|
|
109
113
|
import { WorkflowHooks } from '../modules/workflow/workflow-hooks.js';
|
|
110
|
-
import { SessionOntologyService } from '../modules/workflow/session-ontology.service.js';
|
|
111
114
|
import { PendingCommitsService } from '../modules/workflow/pending-commits.service.js';
|
|
112
115
|
import {
|
|
113
116
|
PendingCommitsWorker,
|
|
@@ -139,6 +142,7 @@ import { BevelOAuthProvider } from '../modules/mcp/oauth/bevel-oauth-provider.js
|
|
|
139
142
|
import { getOAuthProtectedResourceMetadataUrl } from '@modelcontextprotocol/sdk/server/auth/router.js';
|
|
140
143
|
import { ToolRegistry } from '../modules/tool-registry/tool-registry.js';
|
|
141
144
|
import { createToolContextResolver } from '../modules/tool-helpers/tool-context.js';
|
|
145
|
+
import { alwaysWritable, type IWriteAccess } from '../modules/write-access/write-access.js';
|
|
142
146
|
import { createToolHandlerFactory } from '../modules/tool-helpers/tool-handler.js';
|
|
143
147
|
import { TokenCrypto } from '../shared/token-crypto.js';
|
|
144
148
|
import { UpdateCheckService } from '../modules/update-check/update-check.service.js';
|
|
@@ -179,6 +183,12 @@ export interface CoreServices {
|
|
|
179
183
|
* lease to the replacement.
|
|
180
184
|
*/
|
|
181
185
|
commitWorker: LeaseLoopHandle;
|
|
186
|
+
/**
|
|
187
|
+
* Run something with no queued commit being written: the commit worker is
|
|
188
|
+
* stopped for its duration and started again afterwards, the lease kept.
|
|
189
|
+
* What a move to another repository runs the startup phase under.
|
|
190
|
+
*/
|
|
191
|
+
whileCommitsHeld<T>(work: () => Promise<T>): Promise<T>;
|
|
182
192
|
workspaceService: WorkspaceService;
|
|
183
193
|
/**
|
|
184
194
|
* The KB startup phase (see `startup/on-server-start.ts`): run at the
|
|
@@ -186,6 +196,15 @@ export interface CoreServices {
|
|
|
186
196
|
* first-time setup completion — and never again while the process serves.
|
|
187
197
|
*/
|
|
188
198
|
kbStartupRunner: KbStartupRunner;
|
|
199
|
+
/**
|
|
200
|
+
* Where the knowledge base's repository is and what git presents to it,
|
|
201
|
+
* whichever way the deployment was given one (see `RepositorySource`).
|
|
202
|
+
*/
|
|
203
|
+
repositorySource: RepositorySource;
|
|
204
|
+
/** The repository the deployment keeps for itself, when that is the way it chose. */
|
|
205
|
+
managedRepository: ManagedRepository;
|
|
206
|
+
/** The connection to GitHub through a GitHub App, when that is the way it chose. */
|
|
207
|
+
githubApp: GitHubAppConnection;
|
|
189
208
|
/**
|
|
190
209
|
* The startup phase's retry when the boot survived an unreachable remote
|
|
191
210
|
* — set by `startCore`, stopped by `stopCore` (see `core/lifecycle.ts`);
|
|
@@ -206,7 +225,6 @@ export interface CoreServices {
|
|
|
206
225
|
creatorAccess: CreatorAccessService;
|
|
207
226
|
/** Read-before-write, for the surfaces that ask ahead of the lock (see `access-model/change-gate.ts`). */
|
|
208
227
|
changeGate: ChangeReadGate;
|
|
209
|
-
sessionOntologyService: SessionOntologyService;
|
|
210
228
|
routineWritePolicy: RoutineWritePolicyService;
|
|
211
229
|
skillService: SkillService;
|
|
212
230
|
pendingSkillsService: PendingSkillsService;
|
|
@@ -315,6 +333,8 @@ export interface CoreServices {
|
|
|
315
333
|
toolAuthMiddleware: ReturnType<typeof createToolAuthMiddleware>;
|
|
316
334
|
manualAuthMiddleware: ReturnType<typeof createManualAuthMiddleware>;
|
|
317
335
|
toolHandlerFactory: ReturnType<typeof createToolHandlerFactory>;
|
|
336
|
+
/** Whether the deployment may be changed right now — `ports.writeAccess`, or always. */
|
|
337
|
+
writeAccess: IWriteAccess;
|
|
318
338
|
// ── Server-time seams (enterprise overwrites after construction) ────────
|
|
319
339
|
/** `start_session` backing — core default {@link UuidSessionSink}. */
|
|
320
340
|
sessionSink: ISessionSink;
|
|
@@ -434,21 +454,123 @@ export async function createCoreServices(
|
|
|
434
454
|
// settings catalogue knows `GIT_TOKEN` alone. Handed to the runner, which
|
|
435
455
|
// puts the token into each child's environment — never into this
|
|
436
456
|
// process's, which several knowledge bases may share.
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
457
|
+
//
|
|
458
|
+
// Both come from the repository source, which is the one place that knows
|
|
459
|
+
// a deployment can be given its repository in more than one way; what
|
|
460
|
+
// comes back is the address and the credential, as it always was.
|
|
461
|
+
const managedRepository = new ManagedRepository(path.join(config.backupsRoot, 'managed-repository'));
|
|
462
|
+
const githubApp = new GitHubAppConnection({
|
|
463
|
+
read: (key) => settings.resolve(key),
|
|
464
|
+
sourceOf: (key) => settings.sourceOf(key),
|
|
465
|
+
});
|
|
466
|
+
const repositorySource = new RepositorySource({
|
|
467
|
+
read: (key) => settings.resolve(key),
|
|
468
|
+
fallback: { username: config.gitUsername, token: config.gitToken },
|
|
469
|
+
managed: managedRepository,
|
|
470
|
+
githubApp,
|
|
471
|
+
});
|
|
472
|
+
const gitCredentialsInEffect = repositorySource.credentials;
|
|
441
473
|
// How git is run, for every module that runs it: one environment, one buffer
|
|
442
474
|
// ceiling, one error shape, and — the reason it exists — one deadline, so a
|
|
443
475
|
// git that never returns cannot hold a workspace (and with it the commit
|
|
444
476
|
// queue) open indefinitely. See `shared/git.contract.ts`.
|
|
445
477
|
const gitRunner = new NodeGitRunner(config.gitTimeoutMs, gitCredentialsInEffect);
|
|
478
|
+
// A deployment that keeps its own repository has it before anything asks
|
|
479
|
+
// for it: one that chose the mode through the environment never passes
|
|
480
|
+
// through the save that would have created it, and the startup phase's
|
|
481
|
+
// first question would be asked of a folder that is not there. Left to
|
|
482
|
+
// that phase to report if it cannot be made: its failures are classified
|
|
483
|
+
// and shown on the setup screen, where a throw here would take the screen
|
|
484
|
+
// down with the boot.
|
|
485
|
+
if (repositorySource.mode() === 'managed') {
|
|
486
|
+
await managedRepository
|
|
487
|
+
.ensure(gitRunner, settings.resolve('defaultBranch') || MANAGED_DEFAULT_BRANCH)
|
|
488
|
+
.catch((err: unknown) => logger('setup').error('the managed repository could not be created:', { err }));
|
|
489
|
+
}
|
|
490
|
+
// One reached through a GitHub App has a token in hand before anything
|
|
491
|
+
// reads it: a working copy's credential helper is stamped according to
|
|
492
|
+
// whether there is a token, by code that cannot wait for one. A failure is
|
|
493
|
+
// the startup phase's to report, for the same reason as above.
|
|
494
|
+
if (repositorySource.mode() === 'github-app') {
|
|
495
|
+
await githubApp.prepare().catch(() => undefined);
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Where a working copy of a replaced repository is kept, for BOTH the places
|
|
499
|
+
* that find one: the KB startup phase sweeping the workspaces root, and the
|
|
500
|
+
* workspace service refusing to adopt one on a branch open. One variable,
|
|
501
|
+
* passed to both, because they move the same clones for the same reason and
|
|
502
|
+
* an admin looking for their work must have one folder to look in — the two
|
|
503
|
+
* drifted apart once already, and the copy the workspace service set aside
|
|
504
|
+
* landed in the image's own filesystem and was gone at the next recreate.
|
|
505
|
+
*
|
|
506
|
+
* Under the backups root: a persistent volume of its own, and one nothing
|
|
507
|
+
* sweeps (see the runner's `reconcileClonesWithConfiguredRepository`).
|
|
508
|
+
*/
|
|
509
|
+
const replacedWorkingCopiesRoot = path.join(config.backupsRoot, 'replaced-working-copies');
|
|
510
|
+
/**
|
|
511
|
+
* What must leave with a working copy that is set aside, whoever sets it
|
|
512
|
+
* aside: the startup phase, or the workspace service on a branch open.
|
|
513
|
+
*
|
|
514
|
+
* Its queue: whatever still waits to be committed into that copy was
|
|
515
|
+
* written against the repository that was left, and the path it names is
|
|
516
|
+
* about to hold a fresh clone of another one. Held for a person, on every
|
|
517
|
+
* branch, never written and never deleted.
|
|
518
|
+
*
|
|
519
|
+
* And the locks on its branch: each is a claim on a file of the copy that
|
|
520
|
+
* is going. Left standing, a holder still connected keeps one alive with
|
|
521
|
+
* heartbeats, and the same path in the new repository refuses everybody
|
|
522
|
+
* else. Dropped without enqueueing anything, as when change requests are
|
|
523
|
+
* closed as "repository replaced".
|
|
524
|
+
*
|
|
525
|
+
* Throws when either cannot be done, and the caller then leaves the copy
|
|
526
|
+
* where it is. Reaches FORWARD to both services, like `gitService` below:
|
|
527
|
+
* it is only ever called long after this function has returned them.
|
|
528
|
+
*/
|
|
529
|
+
const releaseWorkOnSetAsideCopy = async (workspaceId: string): Promise<void> => {
|
|
530
|
+
const held = await pendingCommitsService.markNeedsAttentionInWorkspace(
|
|
531
|
+
workspaceId,
|
|
532
|
+
'The knowledge-base repository was replaced while this commit was still queued, so it was never ' +
|
|
533
|
+
'written. The bytes are kept here: the working copy it was meant for belongs to the previous repository.',
|
|
534
|
+
);
|
|
535
|
+
if (held > 0) {
|
|
536
|
+
logger('kb-startup').warn(
|
|
537
|
+
`${held} queued commit(s) for the working copy "${workspaceId}" need attention: the repository was ` +
|
|
538
|
+
'replaced before they landed, so they were not written to the new one.',
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
await fileLockService.releaseAllOnBranch(branchForWorkspaceId(workspaceId));
|
|
542
|
+
};
|
|
446
543
|
const workspaceService = new WorkspaceService(
|
|
447
544
|
config.workspacesRoot,
|
|
448
|
-
() =>
|
|
545
|
+
() => repositorySource.url(),
|
|
449
546
|
kb,
|
|
450
547
|
disk,
|
|
451
548
|
gitRunner,
|
|
549
|
+
replacedWorkingCopiesRoot,
|
|
550
|
+
// A branch opened onto a clone of another repository sets it aside on
|
|
551
|
+
// the spot, with nobody having stopped the commit worker for it. So it
|
|
552
|
+
// is held here, for the one move, and the copy's work leaves first and
|
|
553
|
+
// is looked for again once the copy has gone: a release that queued its
|
|
554
|
+
// bytes in between was writing to the copy that left.
|
|
555
|
+
//
|
|
556
|
+
// Only the first look may refuse the branch: the copy has not moved yet.
|
|
557
|
+
// The second runs after the move, so its failure is tried once more and
|
|
558
|
+
// then logged, as the startup phase logs the same step. Refusing then
|
|
559
|
+
// would report a move that did happen as one that did not.
|
|
560
|
+
(workspaceId, move) =>
|
|
561
|
+
leased.whileHeld(async () => {
|
|
562
|
+
await releaseWorkOnSetAsideCopy(workspaceId);
|
|
563
|
+
await move();
|
|
564
|
+
await releaseWorkOnSetAsideCopy(workspaceId)
|
|
565
|
+
.catch(() => releaseWorkOnSetAsideCopy(workspaceId))
|
|
566
|
+
.catch((err: unknown) => {
|
|
567
|
+
logger('workspace').error(
|
|
568
|
+
`the working copy "${workspaceId}" was set aside, but what was queued or locked on it meanwhile ` +
|
|
569
|
+
'could not be looked for again:',
|
|
570
|
+
{ err },
|
|
571
|
+
);
|
|
572
|
+
});
|
|
573
|
+
}),
|
|
452
574
|
);
|
|
453
575
|
// The KB startup phase: every seeding, scaffolding and migration concern,
|
|
454
576
|
// run through one runner at the deployment's quiet moments (boot + setup
|
|
@@ -484,8 +606,11 @@ export async function createCoreServices(
|
|
|
484
606
|
// Getters, not values: the remote and the branch model can arrive from the
|
|
485
607
|
// setup screen after this object exists, and the setup-completion run is
|
|
486
608
|
// the first thing that needs them.
|
|
487
|
-
kbRepoUrl: () =>
|
|
609
|
+
kbRepoUrl: () => repositorySource.url(),
|
|
488
610
|
workspacesRoot: config.workspacesRoot,
|
|
611
|
+
// The same folder the workspace service sets aside into — see
|
|
612
|
+
// `replacedWorkingCopiesRoot` above for why the two must agree.
|
|
613
|
+
setAsideRoot: replacedWorkingCopiesRoot,
|
|
489
614
|
kbDirName,
|
|
490
615
|
templateDir: config.kbTemplateDir,
|
|
491
616
|
defaultBranch: () => kb.defaultBranch,
|
|
@@ -496,6 +621,33 @@ export async function createCoreServices(
|
|
|
496
621
|
steps: kbStartupSteps,
|
|
497
622
|
buildSeedTree: buildSeedTree(disk, config.kbTemplateDir, extraDirs, [config.adminEmail], kb),
|
|
498
623
|
gitRunner,
|
|
624
|
+
// The work on a working copy that is about to be set aside leaves first:
|
|
625
|
+
// its queued commits and the locks on its branch (see
|
|
626
|
+
// `releaseWorkOnSetAsideCopy`). A failure here stops the phase before
|
|
627
|
+
// the copy moves: a replacement cloned over an untouched queue is how
|
|
628
|
+
// those bytes would land in the wrong repository.
|
|
629
|
+
beforeCloneSetAside: releaseWorkOnSetAsideCopy,
|
|
630
|
+
// And once it is set aside it must leave the workspace service's cache:
|
|
631
|
+
// on the SAVE that moves the deployment the process is already running,
|
|
632
|
+
// and a cached path to a directory that is gone is how the next reader
|
|
633
|
+
// gets an ENOENT instead of a fresh clone.
|
|
634
|
+
//
|
|
635
|
+
// Then the copy's work is looked for once more. A release that queued
|
|
636
|
+
// its bytes between the first look and the move was writing to the copy
|
|
637
|
+
// that has now gone; nothing can queue against it after this.
|
|
638
|
+
onCloneDiscarded: async (workspaceId) => {
|
|
639
|
+
workspaceService.forgetClone(workspaceId);
|
|
640
|
+
await releaseWorkOnSetAsideCopy(workspaceId);
|
|
641
|
+
},
|
|
642
|
+
// And the replacement it cloned in its place: a fresh clone holds every
|
|
643
|
+
// ref, so the git layer's per-workspace fetch record is told so. Without
|
|
644
|
+
// it that record still holds the FAILED fetch of the repository that was
|
|
645
|
+
// replaced, and a strict branch listing within its TTL refuses the new
|
|
646
|
+
// clone's refs as unproven. Reaches FORWARD to `gitService`, which is
|
|
647
|
+
// built further down: safe because the runner only ever calls this from
|
|
648
|
+
// `runAll`, which the server builder invokes long after this function has
|
|
649
|
+
// returned every service.
|
|
650
|
+
onCloneCreated: (workspaceId) => gitService.noteWorkspaceFetched(workspaceId),
|
|
499
651
|
});
|
|
500
652
|
// Shared, workspace-independent store for oversized `call_tool_chain` results,
|
|
501
653
|
// read back via `read_file`. Sibling of `workspacesRoot`, never committed.
|
|
@@ -527,14 +679,10 @@ export async function createCoreServices(
|
|
|
527
679
|
// except that new folder at a root (see `access-model/change-gate.ts`).
|
|
528
680
|
const changeGate = new ChangeReadGate(workspaceService, accessControl, kb, disk);
|
|
529
681
|
|
|
530
|
-
// Ontology-session boundary: records each agent run's touched ontologies and
|
|
531
|
-
// blocks writes once a run has crossed ontologies. Postgres-backed so the
|
|
532
|
-
// boundary survives a restart.
|
|
533
|
-
const sessionOntologyService = new SessionOntologyService(db, kb);
|
|
534
682
|
// Per-run write restriction (by file extension). Shared by the workspace tool
|
|
535
683
|
// surface (which enforces it) and the routine runner (which sets it for
|
|
536
|
-
// dashboard-only `watchlist_check` runs). In-memory: a restriction lives only
|
|
537
|
-
// one run
|
|
684
|
+
// dashboard-only `watchlist_check` runs). In-memory: a restriction lives only
|
|
685
|
+
// for one run.
|
|
538
686
|
const routineWritePolicy = new RoutineWritePolicyService();
|
|
539
687
|
// Skills: discovered from the default-branch workspace only (global catalog).
|
|
540
688
|
const skillService = new SkillService(workspaceService, accessControl, kb, disk);
|
|
@@ -585,11 +733,11 @@ export async function createCoreServices(
|
|
|
585
733
|
// against each other — a backup-reseed races a concurrent commit otherwise.
|
|
586
734
|
const workspaceMutex = new WorkspaceMutex();
|
|
587
735
|
// Workflow lifecycle hooks — the ONE registry this composition shares
|
|
588
|
-
// between GitService (advisory commit validation), the
|
|
589
|
-
//
|
|
590
|
-
// registers module-owned handlers on `workflowService.hooks` right
|
|
591
|
-
// this function returns. Core registers none: no commit-time
|
|
592
|
-
// (advisory anyway) and
|
|
736
|
+
// between GitService (advisory commit validation), the agent-access gate
|
|
737
|
+
// (the blocking agentRead / preWrite hooks), and the composition root,
|
|
738
|
+
// which registers module-owned handlers on `workflowService.hooks` right
|
|
739
|
+
// after this function returns. Core registers none: no commit-time
|
|
740
|
+
// validation (advisory anyway) and nothing that refuses an agent call.
|
|
593
741
|
const workflowHooks = new WorkflowHooks();
|
|
594
742
|
const gitService = new GitService(
|
|
595
743
|
workspaceService,
|
|
@@ -684,7 +832,7 @@ export async function createCoreServices(
|
|
|
684
832
|
eventBus,
|
|
685
833
|
fileChangeNotifier,
|
|
686
834
|
// Exposed as `workflowService.hooks` — the SAME instance GitService and
|
|
687
|
-
// the
|
|
835
|
+
// the agent-access gate consult, so a deployment's registrations against
|
|
688
836
|
// it reach every hook point.
|
|
689
837
|
workflowHooks,
|
|
690
838
|
);
|
|
@@ -693,7 +841,14 @@ export async function createCoreServices(
|
|
|
693
841
|
// (the request's branch vs the default branch), so it holds no state — it
|
|
694
842
|
// only needs to read files at refs and to close a request whose proposals
|
|
695
843
|
// have all landed.
|
|
696
|
-
const joinRequestsService = new JoinRequestsService(
|
|
844
|
+
const joinRequestsService = new JoinRequestsService(
|
|
845
|
+
workspaceService,
|
|
846
|
+
workflowService,
|
|
847
|
+
kb,
|
|
848
|
+
// Read-only: the one question a request asks of the resolver is whether
|
|
849
|
+
// the person it names already holds what it proposes.
|
|
850
|
+
accessControl,
|
|
851
|
+
);
|
|
697
852
|
// The OTHER half of a join request: the row the subscribe endpoint writes
|
|
698
853
|
// before it answers, and the branch/clone/commit/push/change-request work
|
|
699
854
|
// that runs against it afterwards. The row is what lets the click be
|
|
@@ -1080,8 +1235,9 @@ export async function createCoreServices(
|
|
|
1080
1235
|
creatorAccess,
|
|
1081
1236
|
loadActiveGroups,
|
|
1082
1237
|
});
|
|
1083
|
-
const
|
|
1084
|
-
const
|
|
1238
|
+
const writeAccess = ports.writeAccess ?? alwaysWritable;
|
|
1239
|
+
const toolHandlerFactory = createToolHandlerFactory(resolveToolContext, writeAccess);
|
|
1240
|
+
const toolAuthMiddleware = createToolAuthMiddleware(externalApiKeyService, internalTokenService, authService);
|
|
1085
1241
|
// Read-only manual endpoints accept the above PLUS a browser JWT, so a
|
|
1086
1242
|
// logged-in user can browse the catalog with their session. Execution routes
|
|
1087
1243
|
// keep `toolAuthMiddleware` (no JWT), so a session can read but not invoke.
|
|
@@ -1133,7 +1289,10 @@ export async function createCoreServices(
|
|
|
1133
1289
|
name: recoveryBot.name,
|
|
1134
1290
|
},
|
|
1135
1291
|
});
|
|
1136
|
-
|
|
1292
|
+
// Holdable: a move to another repository stops the worker for as long as
|
|
1293
|
+
// working copies are being set aside and cloned again, without giving up
|
|
1294
|
+
// the lease (see `holdable` in `core/lifecycle.ts`).
|
|
1295
|
+
const leased = holdable(withStartupTask(pendingCommitsWorker, reconcileQueue));
|
|
1137
1296
|
|
|
1138
1297
|
// SSO providers. The array REFERENCE is shared with the caller's port — an
|
|
1139
1298
|
// overlay pushes its own plugins into it after construction (they mount when
|
|
@@ -1229,6 +1388,7 @@ export async function createCoreServices(
|
|
|
1229
1388
|
db,
|
|
1230
1389
|
gitRunner,
|
|
1231
1390
|
commitWorker,
|
|
1391
|
+
whileCommitsHeld: (work) => leased.whileHeld(work),
|
|
1232
1392
|
startupRetry: null,
|
|
1233
1393
|
tenantKey,
|
|
1234
1394
|
secretsScope,
|
|
@@ -1237,6 +1397,9 @@ export async function createCoreServices(
|
|
|
1237
1397
|
toolDeleteService,
|
|
1238
1398
|
workspaceService,
|
|
1239
1399
|
kbStartupRunner,
|
|
1400
|
+
repositorySource,
|
|
1401
|
+
managedRepository,
|
|
1402
|
+
githubApp,
|
|
1240
1403
|
settings,
|
|
1241
1404
|
kb,
|
|
1242
1405
|
kbDirName,
|
|
@@ -1245,7 +1408,6 @@ export async function createCoreServices(
|
|
|
1245
1408
|
accessControl,
|
|
1246
1409
|
creatorAccess,
|
|
1247
1410
|
changeGate,
|
|
1248
|
-
sessionOntologyService,
|
|
1249
1411
|
routineWritePolicy,
|
|
1250
1412
|
skillService,
|
|
1251
1413
|
pendingSkillsService,
|
|
@@ -1296,6 +1458,7 @@ export async function createCoreServices(
|
|
|
1296
1458
|
toolAuthMiddleware,
|
|
1297
1459
|
manualAuthMiddleware,
|
|
1298
1460
|
toolHandlerFactory,
|
|
1461
|
+
writeAccess,
|
|
1299
1462
|
// Server-time seams — defaults here; the enterprise overlay overwrites
|
|
1300
1463
|
// (or, for the array, pushes into) these after construction.
|
|
1301
1464
|
sessionSink: ports.sessionSink ?? new UuidSessionSink(),
|