@bevel-software/platform-core-backend 0.22.0 → 0.24.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 +46 -13
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +12 -2
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +137 -24
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core/lifecycle.d.ts +46 -1
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +99 -13
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/core-config.d.ts +16 -12
- package/dist/core-config.d.ts.map +1 -1
- package/dist/core-config.js +28 -13
- package/dist/core-config.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -3
- 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.routes.d.ts.map +1 -1
- package/dist/modules/access/access.routes.js +17 -16
- package/dist/modules/access/access.routes.js.map +1 -1
- package/dist/modules/access/directory-sync-bot.d.ts.map +1 -1
- package/dist/modules/access/directory-sync-bot.js +7 -3
- package/dist/modules/access/directory-sync-bot.js.map +1 -1
- package/dist/modules/agent-instructions/agent-instructions.routes.d.ts +8 -1
- package/dist/modules/agent-instructions/agent-instructions.routes.d.ts.map +1 -1
- package/dist/modules/agent-instructions/agent-instructions.routes.js +8 -2
- package/dist/modules/agent-instructions/agent-instructions.routes.js.map +1 -1
- package/dist/modules/agent-instructions/compose.d.ts +38 -6
- package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
- package/dist/modules/agent-instructions/compose.js +39 -6
- package/dist/modules/agent-instructions/compose.js.map +1 -1
- package/dist/modules/agent-instructions/index.d.ts +2 -1
- package/dist/modules/agent-instructions/index.d.ts.map +1 -1
- package/dist/modules/agent-instructions/index.js +2 -1
- package/dist/modules/agent-instructions/index.js.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.d.ts +115 -0
- package/dist/modules/agent-instructions/shared-file-rules.d.ts.map +1 -0
- package/dist/modules/agent-instructions/shared-file-rules.js +272 -0
- package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -0
- package/dist/modules/audit/agent-audit.service.d.ts.map +1 -1
- package/dist/modules/audit/agent-audit.service.js +4 -2
- package/dist/modules/audit/agent-audit.service.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-erasure.service.d.ts.map +1 -1
- package/dist/modules/auth/account-erasure.service.js +57 -16
- package/dist/modules/auth/account-erasure.service.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 +70 -2
- package/dist/modules/auth/auth.service.d.ts.map +1 -1
- package/dist/modules/auth/auth.service.js +197 -18
- 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/code-mode/code-mode.tool.d.ts +20 -2
- package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -1
- package/dist/modules/code-mode/code-mode.tool.js +66 -35
- package/dist/modules/code-mode/code-mode.tool.js.map +1 -1
- package/dist/modules/database/connection.d.ts +16 -0
- package/dist/modules/database/connection.d.ts.map +1 -1
- package/dist/modules/database/connection.js +117 -0
- package/dist/modules/database/connection.js.map +1 -1
- package/dist/modules/database/core-schema.d.ts +337 -120
- package/dist/modules/database/core-schema.d.ts.map +1 -1
- package/dist/modules/database/core-schema.js +116 -58
- package/dist/modules/database/core-schema.js.map +1 -1
- package/dist/modules/database/migrate.d.ts +8 -0
- package/dist/modules/database/migrate.d.ts.map +1 -1
- package/dist/modules/database/migrate.js +271 -1
- package/dist/modules/database/migrate.js.map +1 -1
- 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/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/mcp.service.d.ts +8 -0
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +38 -8
- package/dist/modules/mcp/mcp.service.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-request-records.store.d.ts.map +1 -1
- package/dist/modules/plugins/join-request-records.store.js +7 -4
- package/dist/modules/plugins/join-request-records.store.js.map +1 -1
- package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
- package/dist/modules/settings/deployment-settings.service.js +8 -3
- package/dist/modules/settings/deployment-settings.service.js.map +1 -1
- package/dist/modules/settings/setup.routes.d.ts +52 -1
- package/dist/modules/settings/setup.routes.d.ts.map +1 -1
- package/dist/modules/settings/setup.routes.js +207 -19
- package/dist/modules/settings/setup.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 +12 -4
- 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-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/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +42 -31
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/tool-registry/description-length.d.ts +80 -0
- package/dist/modules/tool-registry/description-length.d.ts.map +1 -0
- package/dist/modules/tool-registry/description-length.js +108 -0
- package/dist/modules/tool-registry/description-length.js.map +1 -0
- 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 +75 -35
- 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 +94 -0
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +193 -3
- package/dist/modules/workflow/git/git.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 +60 -1
- package/dist/modules/workflow/pending-commits.service.js.map +1 -1
- package/dist/modules/workflow/recovery-bot.d.ts.map +1 -1
- package/dist/modules/workflow/recovery-bot.js +7 -3
- package/dist/modules/workflow/recovery-bot.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 +12 -3
- package/dist/modules/workflow/review-workflow/review-workflow.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.service.d.ts +60 -6
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +115 -5
- 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/agent-upload.routes.d.ts +77 -0
- package/dist/modules/workspace/agent-upload.routes.d.ts.map +1 -0
- package/dist/modules/workspace/agent-upload.routes.js +210 -0
- package/dist/modules/workspace/agent-upload.routes.js.map +1 -0
- package/dist/modules/workspace/agent-upload.store.d.ts +284 -0
- package/dist/modules/workspace/agent-upload.store.d.ts.map +1 -0
- package/dist/modules/workspace/agent-upload.store.js +553 -0
- package/dist/modules/workspace/agent-upload.store.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 +59 -9
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.js +65 -24
- package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.js +3 -3
- package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.d.ts +40 -0
- package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.js +46 -4
- package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
- package/dist/modules/workspace/upload-limits.d.ts +13 -0
- package/dist/modules/workspace/upload-limits.d.ts.map +1 -0
- package/dist/modules/workspace/upload-limits.js +13 -0
- package/dist/modules/workspace/upload-limits.js.map +1 -0
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.routes.js +93 -4
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +128 -5
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +316 -58
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts +13 -11
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +791 -198
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/modules/workspace/write-denial.d.ts +0 -6
- package/dist/modules/workspace/write-denial.d.ts.map +1 -1
- package/dist/modules/workspace/write-denial.js +0 -6
- package/dist/modules/workspace/write-denial.js.map +1 -1
- package/dist/modules/workspace/zip-entry-rules.d.ts +114 -0
- package/dist/modules/workspace/zip-entry-rules.d.ts.map +1 -0
- package/dist/modules/workspace/zip-entry-rules.js +154 -0
- package/dist/modules/workspace/zip-entry-rules.js.map +1 -0
- 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/column-crypto.d.ts +194 -0
- package/dist/shared/column-crypto.d.ts.map +1 -0
- package/dist/shared/column-crypto.js +144 -0
- package/dist/shared/column-crypto.js.map +1 -0
- package/dist/shared/domain-errors.d.ts +25 -0
- package/dist/shared/domain-errors.d.ts.map +1 -1
- package/dist/shared/domain-errors.js +28 -0
- package/dist/shared/domain-errors.js.map +1 -1
- package/dist/shared/git.contract.d.ts +20 -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/shared/token-crypto.d.ts.map +1 -1
- package/dist/shared/token-crypto.js +25 -1
- package/dist/shared/token-crypto.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 +1 -2
- package/dist/tenancy/static-tenant-source.js.map +1 -1
- package/dist/tenancy/tenant-secrets.d.ts +5 -1
- package/dist/tenancy/tenant-secrets.d.ts.map +1 -1
- package/dist/tenancy/tenant-secrets.js +4 -0
- package/dist/tenancy/tenant-secrets.js.map +1 -1
- package/kb-template/AGENTS.md +2 -0
- package/migrations/0014_change_request_closed_reason.sql +1 -0
- package/migrations/0015_account_deactivation.sql +3 -0
- package/migrations/0016_pii_encryption.sql +20 -0
- package/migrations/meta/0014_snapshot.json +2265 -0
- package/migrations/meta/0015_snapshot.json +2271 -0
- package/migrations/meta/0016_snapshot.json +2327 -0
- package/migrations/meta/_journal.json +21 -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 +241 -5
- 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 +52 -16
- package/src/core/create-core-services.ts +156 -24
- package/src/core/lifecycle.ts +117 -13
- package/src/core-config.ts +31 -14
- package/src/index.ts +30 -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.routes.prospective.test.ts +6 -7
- package/src/modules/access/__tests__/users-db-double.ts +21 -12
- 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.routes.ts +17 -16
- package/src/modules/access/directory-sync-bot.ts +7 -3
- package/src/modules/agent-instructions/__tests__/agent-instructions.route.test.ts +11 -5
- package/src/modules/agent-instructions/__tests__/compose.test.ts +19 -10
- package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +238 -0
- package/src/modules/agent-instructions/agent-instructions.routes.ts +12 -2
- package/src/modules/agent-instructions/compose.ts +50 -7
- package/src/modules/agent-instructions/index.ts +12 -0
- package/src/modules/agent-instructions/shared-file-rules.ts +314 -0
- package/src/modules/audit/agent-audit.service.ts +4 -2
- package/src/modules/auth/__tests__/account-deactivation.test.ts +253 -0
- package/src/modules/auth/__tests__/account-erasure.approval-gate.test.ts +6 -2
- package/src/modules/auth/__tests__/account.routes.test.ts +87 -6
- package/src/modules/auth/__tests__/auth.middleware.test.ts +45 -22
- package/src/modules/auth/__tests__/auth.service.test.ts +4 -2
- package/src/modules/auth/account-admission.ts +78 -9
- package/src/modules/auth/account-erasure.service.ts +69 -18
- 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 +206 -23
- package/src/modules/auth/oidc-auth-provider.ts +7 -2
- package/src/modules/code-mode/__tests__/chain-runtime.e2e.test.ts +335 -0
- package/src/modules/code-mode/__tests__/code-mode.tool.test.ts +46 -2
- package/src/modules/code-mode/code-mode.tool.ts +80 -34
- package/src/modules/database/__tests__/connection.test.ts +12 -0
- package/src/modules/database/__tests__/pii-backfill.pg.test.ts +561 -0
- package/src/modules/database/connection.ts +117 -0
- package/src/modules/database/core-schema.ts +116 -58
- package/src/modules/database/migrate.ts +353 -1
- package/src/modules/kb-fs/__tests__/branch-name.test.ts +10 -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/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.e2e.test.ts +4 -3
- package/src/modules/mcp/__tests__/mcp.service.test.ts +115 -13
- package/src/modules/mcp/mcp-auth.middleware.ts +20 -6
- package/src/modules/mcp/mcp.service.ts +46 -7
- package/src/modules/mcp/oauth/bevel-oauth-provider.ts +3 -1
- package/src/modules/plugins/__tests__/plugins.tools.test.ts +2 -1
- package/src/modules/plugins/join-request-records.store.ts +7 -4
- package/src/modules/settings/__tests__/deployment-settings.service.test.ts +16 -0
- package/src/modules/settings/__tests__/setup.routes.git-mode.test.ts +91 -58
- package/src/modules/settings/__tests__/setup.routes.github-app.test.ts +25 -8
- package/src/modules/settings/__tests__/setup.routes.managed-phase.test.ts +14 -11
- 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 +8 -3
- package/src/modules/settings/setup.routes.ts +263 -19
- 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__/skills.service.test.ts +229 -5
- 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 +12 -4
- 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-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/tool-manuals/tool-manuals.tools.ts +44 -31
- package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +378 -0
- package/src/modules/tool-registry/description-length.ts +111 -0
- 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.repository-replaced.test.ts +249 -0
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +264 -6
- package/src/modules/workflow/agent-tools/change-request-summary.ts +182 -0
- package/src/modules/workflow/agent-tools/workflow.tools.ts +86 -35
- 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.prFetchFailure.test.ts +170 -0
- package/src/modules/workflow/git/git.service.ts +215 -1
- package/src/modules/workflow/pending-commits.service.ts +64 -2
- package/src/modules/workflow/recovery-bot.ts +7 -3
- package/src/modules/workflow/review-workflow/__tests__/carry-approvals-forward.test.ts +4 -0
- package/src/modules/workflow/review-workflow/__tests__/erase-approver.test.ts +25 -3
- package/src/modules/workflow/review-workflow/review-workflow.service.ts +12 -3
- package/src/modules/workflow/workflow-hooks.ts +64 -26
- package/src/modules/workflow/workflow.service.ts +125 -5
- package/src/modules/workspace/__tests__/agent-access.gate.test.ts +208 -0
- package/src/modules/workspace/__tests__/agent-uploads.test.ts +1604 -0
- package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +394 -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.any-workspace-credentials.test.ts +156 -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 +402 -0
- package/src/modules/workspace/__tests__/workspace.service.test.ts +77 -9
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +41 -39
- package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +2 -3
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +766 -56
- package/src/modules/workspace/agent-access.gate.ts +164 -0
- package/src/modules/workspace/agent-upload.routes.ts +214 -0
- package/src/modules/workspace/agent-upload.store.ts +668 -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 +86 -0
- package/src/modules/workspace/startup/kb-startup-runner.ts +115 -34
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +9 -9
- package/src/modules/workspace/startup/steps/seed-tree.ts +3 -6
- package/src/modules/workspace/startup/steps/template-source.ts +53 -5
- package/src/modules/workspace/upload-limits.ts +12 -0
- package/src/modules/workspace/workspace.routes.ts +96 -5
- package/src/modules/workspace/workspace.service.ts +319 -61
- package/src/modules/workspace/workspace.tools.ts +894 -214
- package/src/modules/workspace/write-denial.ts +0 -8
- package/src/modules/workspace/zip-entry-rules.ts +173 -0
- 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/__tests__/column-crypto.test.ts +217 -0
- package/src/shared/column-crypto.ts +218 -0
- package/src/shared/domain-errors.ts +31 -0
- package/src/shared/git.contract.ts +27 -0
- package/src/shared/token-crypto.ts +28 -1
- package/src/tenancy/__tests__/static-tenant-source.test.ts +4 -1
- package/src/tenancy/static-tenant-source.ts +1 -3
- package/src/tenancy/tenant-secrets.ts +5 -1
- 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
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { setAsideRootFor } from '../../modules/workspace/set-aside-clone.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A working copy of a repository that is no longer the configured one is SET
|
|
9
|
+
* ASIDE rather than deleted, and two places do it: the KB startup phase,
|
|
10
|
+
* sweeping the whole workspaces root, and the workspace service, refusing to
|
|
11
|
+
* adopt one on a branch open. They must set aside into ONE directory.
|
|
12
|
+
*
|
|
13
|
+
* They did not. The composition root gave the phase a root under the backups
|
|
14
|
+
* volume and the workspace service nothing at all, so that one fell back to a
|
|
15
|
+
* sibling of the workspaces root — which in the shipped compose file is the
|
|
16
|
+
* container's own filesystem, not a volume. A copy the workspace service kept
|
|
17
|
+
* was therefore gone at the next ordinary recreate, after the setup screen had
|
|
18
|
+
* told the admin it was being kept and where to find it.
|
|
19
|
+
*
|
|
20
|
+
* Read off the source, like `migrations-unqualified.test.ts` reads the
|
|
21
|
+
* migrations: the wiring is a single call graph that cannot be built in a unit
|
|
22
|
+
* test (it wants a database, a git host and a disk), and the invariant is
|
|
23
|
+
* about the TEXT — that the folder is named once and that one name reaches
|
|
24
|
+
* both. A second literal is exactly how the two came apart.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const compositionRoot = path.resolve(
|
|
28
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
29
|
+
'../create-core-services.ts',
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
describe('the set-aside root the composition root wires', () => {
|
|
33
|
+
it('is named once, and handed to both the startup phase and the workspace service', async () => {
|
|
34
|
+
const source = await fs.readFile(compositionRoot, 'utf8');
|
|
35
|
+
|
|
36
|
+
// Named once. Two occurrences means two expressions, which is how a
|
|
37
|
+
// change to one of them silently stops applying to the other.
|
|
38
|
+
const literals = source.match(/'replaced-working-copies'/g) ?? [];
|
|
39
|
+
expect(literals).toHaveLength(1);
|
|
40
|
+
|
|
41
|
+
// And that one name is rooted at the backups volume, which the deployment
|
|
42
|
+
// mounts — not at the workspaces root's parent, which it does not.
|
|
43
|
+
expect(source).toMatch(
|
|
44
|
+
/const replacedWorkingCopiesRoot = path\.join\(config\.backupsRoot, 'replaced-working-copies'\)/,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// Both consumers read the one variable.
|
|
48
|
+
expect(source).toMatch(/new WorkspaceService\([\s\S]*?replacedWorkingCopiesRoot,[\s\S]*?\);/);
|
|
49
|
+
expect(source).toMatch(/setAsideRoot: replacedWorkingCopiesRoot,/);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('setAsideRootFor', () => {
|
|
54
|
+
it('uses the root it is given, whatever the workspaces root is', () => {
|
|
55
|
+
expect(setAsideRootFor('/app/apps/server/workspaces', '/app/apps/server/backups/replaced-working-copies')).toBe(
|
|
56
|
+
'/app/apps/server/backups/replaced-working-copies',
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('falls back beside the workspaces root — a place a container deployment must not rely on', () => {
|
|
61
|
+
expect(setAsideRootFor('/app/apps/server/workspaces')).toBe('/app/apps/server/replaced-working-copies');
|
|
62
|
+
});
|
|
63
|
+
});
|
package/src/core/core-ports.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { ILlmUsageMeter } from '../modules/tool-auth/llm-usage-meter.js';
|
|
|
7
7
|
import type { AuthProviderPlugin } from '../modules/auth/auth.routes.js';
|
|
8
8
|
import type { IErasureParticipant } from '../modules/auth/account-erasure.service.js';
|
|
9
9
|
import type { IAccountAdmission } from '../modules/auth/account-admission.js';
|
|
10
|
+
import type { IWriteAccess } from '../modules/write-access/write-access.js';
|
|
10
11
|
import type { OnServerStart } from '../modules/workspace/startup/on-server-start.js';
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -34,7 +35,7 @@ import type { OnServerStart } from '../modules/workspace/startup/on-server-start
|
|
|
34
35
|
* enterprise root overwrites the `CoreServices` fields (or pushes into the
|
|
35
36
|
* `authProviders` array) after construction, before the server is built.
|
|
36
37
|
*
|
|
37
|
-
* (Commit-time KB validation and the
|
|
38
|
+
* (Commit-time KB validation and the agent read/write hooks are NOT ports:
|
|
38
39
|
* they are workflow lifecycle HOOKS the enterprise root registers on
|
|
39
40
|
* `workflowService.hooks` after construction — see
|
|
40
41
|
* `modules/workflow/workflow-hooks.ts`.)
|
|
@@ -117,6 +118,15 @@ export interface CorePorts {
|
|
|
117
118
|
* admin who asked. See `modules/auth/account-admission.ts`.
|
|
118
119
|
*/
|
|
119
120
|
accountAdmission?: IAccountAdmission;
|
|
121
|
+
/**
|
|
122
|
+
* Whether the deployment may be changed right now. Asked before every
|
|
123
|
+
* mutating route (bar the ones that sign people in, manage accounts or
|
|
124
|
+
* configure the deployment) and every write tool. Core default: always.
|
|
125
|
+
* A host that sells seats answers no while more accounts are on than its
|
|
126
|
+
* plan allows, so the workspace is read-only until an admin fixes it. See
|
|
127
|
+
* `modules/write-access/write-access.ts`.
|
|
128
|
+
*/
|
|
129
|
+
writeAccess?: IWriteAccess;
|
|
120
130
|
}
|
|
121
131
|
|
|
122
132
|
/**
|
|
@@ -4,6 +4,10 @@ import path from 'node:path';
|
|
|
4
4
|
import type { Router, RequestHandler } from 'express';
|
|
5
5
|
import { createAuthRoutes } from '../modules/auth/auth.routes.js';
|
|
6
6
|
import { createWorkspaceRoutes } from '../modules/workspace/workspace.routes.js';
|
|
7
|
+
import {
|
|
8
|
+
createAgentUploadRoutes,
|
|
9
|
+
isAgentUploadRawBodyPath,
|
|
10
|
+
} from '../modules/workspace/agent-upload.routes.js';
|
|
7
11
|
import { createGitInternalsRouteGuard } from '../modules/workspace/git-internals.middleware.js';
|
|
8
12
|
import { startCore } from './lifecycle.js';
|
|
9
13
|
import { createDiffRoutes } from '../modules/diff/diff.routes.js';
|
|
@@ -37,7 +41,7 @@ import {
|
|
|
37
41
|
registerPluginsTools,
|
|
38
42
|
} from '../modules/plugins/index.js';
|
|
39
43
|
import { keyOrSessionAuth } from '../modules/tool-auth/key-or-session.middleware.js';
|
|
40
|
-
import type
|
|
44
|
+
import { ToolDescriptionNotes, type AgentAccessGate } from '../modules/workspace/agent-access.gate.js';
|
|
41
45
|
import {
|
|
42
46
|
createSecretsVaultRoutes,
|
|
43
47
|
createSecretsVaultPublicRoutes,
|
|
@@ -72,6 +76,7 @@ import { publicConfig } from './public-config.js';
|
|
|
72
76
|
import { createReadiness } from './readiness.js';
|
|
73
77
|
import { createAgentInstructionsRoutes } from '../modules/agent-instructions/index.js';
|
|
74
78
|
import type { CoreServices } from './create-core-services.js';
|
|
79
|
+
import { createWriteAccessRoutes, createWriteGateMiddleware } from '../modules/write-access/write-access.js';
|
|
75
80
|
|
|
76
81
|
type ExpressApp = ReturnType<typeof express>;
|
|
77
82
|
|
|
@@ -85,8 +90,8 @@ export interface ToolSurfaceCtx {
|
|
|
85
90
|
router: Router;
|
|
86
91
|
toolAuth: RequestHandler;
|
|
87
92
|
toolHandler: CoreServices['toolHandlerFactory'];
|
|
88
|
-
/** Shared
|
|
89
|
-
|
|
93
|
+
/** Shared agent-access gate config (file tools + graph tools). */
|
|
94
|
+
agentAccessGate: AgentAccessGate;
|
|
90
95
|
core: CoreServices;
|
|
91
96
|
}
|
|
92
97
|
|
|
@@ -200,8 +205,23 @@ export async function createCoreServer(
|
|
|
200
205
|
// is mounted again below, once the body is parsed and once the caller is
|
|
201
206
|
// known (see the two mounts under `/api/workspace/:id`).
|
|
202
207
|
app.use('/api/workspace/:id', createGitInternalsRouteGuard(core.workspaceService));
|
|
208
|
+
// The read-only gate, ahead of every route — core's, the tool surface's
|
|
209
|
+
// and an overlay's alike — so a read-only deployment refuses a change
|
|
210
|
+
// wherever it would enter. It lets through what signs people in, manages
|
|
211
|
+
// accounts and configures the deployment (see `ALWAYS_WRITABLE`); write
|
|
212
|
+
// tools are judged by the tool layer. A no-op unless a host fills
|
|
213
|
+
// `ports.writeAccess`. Ahead of the body parser too: a refused write is
|
|
214
|
+
// refused with its own 403, never parsed first (and answered 400 or 413).
|
|
215
|
+
app.use(createWriteGateMiddleware(core.writeAccess));
|
|
203
216
|
app.use((req, res, next) => {
|
|
204
|
-
|
|
217
|
+
// The agent upload route is exempt for the same reason `/api/sync` is:
|
|
218
|
+
// whoever needs the EXACT bytes has to see them before any parser can
|
|
219
|
+
// drain the stream. `curl --data-binary @file.zip` with a JSON
|
|
220
|
+
// content-type is a request an agent can make, and the parser would
|
|
221
|
+
// otherwise leave the handler nothing to store.
|
|
222
|
+
if (jsonExemptPaths.has(req.path) || isSyncRawBodyPath(req.path) || isAgentUploadRawBodyPath(req.path)) {
|
|
223
|
+
return next();
|
|
224
|
+
}
|
|
205
225
|
return globalJson(req, res, next);
|
|
206
226
|
});
|
|
207
227
|
|
|
@@ -420,24 +440,30 @@ export async function createCoreServer(
|
|
|
420
440
|
},
|
|
421
441
|
}),
|
|
422
442
|
);
|
|
423
|
-
// Shared
|
|
424
|
-
//
|
|
425
|
-
//
|
|
426
|
-
//
|
|
427
|
-
//
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
enabled: core.config.ontologySessionBlock,
|
|
431
|
-
kb: core.kb,
|
|
443
|
+
// Shared agent-access gate config, consumed by every tool surface that
|
|
444
|
+
// touches the KB (file tools + graph tools). The gate decides nothing
|
|
445
|
+
// itself: it calls the read and write hooks a deployment registered on
|
|
446
|
+
// `workflowService.hooks`, and carries the notes that deployment wants
|
|
447
|
+
// agents to read about the gated tools. Core registers neither, so a
|
|
448
|
+
// core-only deployment refuses nothing and says nothing extra.
|
|
449
|
+
const agentAccessGate: AgentAccessGate = {
|
|
432
450
|
recoveryBotEmail: RECOVERY_BOT_EMAIL,
|
|
433
451
|
hooks: core.workflowService.hooks,
|
|
452
|
+
notes: new ToolDescriptionNotes(),
|
|
434
453
|
};
|
|
435
454
|
// A skill's `allowed-tools`, checked against what the caller can see — on
|
|
436
455
|
// every save surface (agent write tools, the app's PUT /file) and on
|
|
437
456
|
// `get_skill`. Warnings only; it never refuses a save.
|
|
438
457
|
const allowedToolsChecker = new AllowedToolsChecker(core.toolRegistry, core.toolManualService, core.kb);
|
|
439
458
|
registerWorkflowTools(core.toolRegistry, toolsRouter, ta, th, core.kb);
|
|
440
|
-
registerWorkspaceTools(core.toolRegistry, toolsRouter, ta, th, core.spillStore, core.docExtractService, core.accessControl, core.kb,
|
|
459
|
+
registerWorkspaceTools(core.toolRegistry, toolsRouter, ta, th, core.spillStore, core.docExtractService, core.accessControl, core.kb, agentAccessGate, core.routineWritePolicy, core.sessionSink, allowedToolsChecker, core.changeGate, core.agentUploadStore);
|
|
460
|
+
// The agent upload route, on the same router as the tool endpoints so it
|
|
461
|
+
// mounts ahead of the JWT `/api` mounts below — but WITHOUT `toolAuth`: its
|
|
462
|
+
// whole credential is the single-use token in its path, which is the point
|
|
463
|
+
// (an agent's `curl` carries no session and no connection key). It resolves
|
|
464
|
+
// no workspace and writes into none; every access, platform-file and branch
|
|
465
|
+
// rule is applied later by `apply_file_upload`.
|
|
466
|
+
toolsRouter.use(createAgentUploadRoutes({ uploads: core.agentUploadStore }));
|
|
441
467
|
registerSkillsTools(core.toolRegistry, toolsRouter, ta, th, core.skillService, allowedToolsChecker);
|
|
442
468
|
// Definitions only: the endpoints they describe are the app's own plugin
|
|
443
469
|
// creation routes, mounted below behind the key-or-session gate.
|
|
@@ -455,7 +481,7 @@ export async function createCoreServer(
|
|
|
455
481
|
router: toolsRouter,
|
|
456
482
|
toolAuth: ta,
|
|
457
483
|
toolHandler: th,
|
|
458
|
-
|
|
484
|
+
agentAccessGate,
|
|
459
485
|
core,
|
|
460
486
|
});
|
|
461
487
|
toolsRouter.use(createManualRoutes(
|
|
@@ -481,7 +507,7 @@ export async function createCoreServer(
|
|
|
481
507
|
// What every connected agent is told at session start, as the hosted proxy
|
|
482
508
|
// composes it: read by the local `hexis-mcp` bridge at startup and by the
|
|
483
509
|
// External agent access card. Same `manualAuth`, same router, as `all-tools`.
|
|
484
|
-
toolsRouter.use(createAgentInstructionsRoutes(core.manualAuthMiddleware, core.readAgentPreamble));
|
|
510
|
+
toolsRouter.use(createAgentInstructionsRoutes(core.manualAuthMiddleware, core.readAgentPreamble, () => core.kb.layout));
|
|
485
511
|
// The fingerprint of the caller's released catalog. The local `hexis-mcp`
|
|
486
512
|
// server polls it to learn that a manual or a skill changed under a
|
|
487
513
|
// connection it cannot be pushed to; nothing else consults it. Same
|
|
@@ -546,6 +572,7 @@ export async function createCoreServer(
|
|
|
546
572
|
// request also gets the resolved form judged — a link in the repository that
|
|
547
573
|
// points into the git folder — before any read gate or lock.
|
|
548
574
|
app.use('/api/workspace/:id', core.authMiddleware, createGitInternalsRouteGuard(core.workspaceService));
|
|
575
|
+
app.use('/api', core.authMiddleware, createWriteAccessRoutes(core.writeAccess));
|
|
549
576
|
app.use('/api', core.authMiddleware, createWorkspaceRoutes(
|
|
550
577
|
core.workspaceService,
|
|
551
578
|
core.authService,
|
|
@@ -722,6 +749,15 @@ export async function createCoreServer(
|
|
|
722
749
|
ensureManaged: (branch) => core.managedRepository.ensure(core.gitRunner, branch),
|
|
723
750
|
githubApp: core.githubApp,
|
|
724
751
|
},
|
|
752
|
+
// What a move to another repository has to decide about, and what it
|
|
753
|
+
// runs under. Bound here rather than handed the whole workflow service:
|
|
754
|
+
// the setup routes ask two questions, hold the commit worker for the
|
|
755
|
+
// move, and know nothing else about a request or a commit.
|
|
756
|
+
{
|
|
757
|
+
countOpen: () => core.workflowService.countOpenChangeRequests(),
|
|
758
|
+
closeAsRepositoryReplaced: () => core.workflowService.closeOpenChangeRequestsAsRepositoryReplaced(),
|
|
759
|
+
whileCommitsHeld: (work) => core.whileCommitsHeld(work),
|
|
760
|
+
},
|
|
725
761
|
),
|
|
726
762
|
);
|
|
727
763
|
// Connecting a repository on GitHub through a GitHub App: the round trips
|
|
@@ -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';
|
|
@@ -35,7 +36,7 @@ import { ManagedRepository, MANAGED_DEFAULT_BRANCH } from '../modules/settings/m
|
|
|
35
36
|
import { RepositorySource } from '../modules/settings/repository-source.js';
|
|
36
37
|
import { GitHubAppConnection } from '../modules/github-app/index.js';
|
|
37
38
|
import { AdvisoryLease, AdvisoryLock } from '../modules/database/advisory-lock.js';
|
|
38
|
-
import { holdCommitWorkerLease, withStartupTask, type LeaseLoopHandle } from './lifecycle.js';
|
|
39
|
+
import { holdCommitWorkerLease, holdable, withStartupTask, type LeaseLoopHandle } from './lifecycle.js';
|
|
39
40
|
|
|
40
41
|
/** The hosted MCP endpoint at a deployment address, with any userinfo stripped. */
|
|
41
42
|
function mcpEndpointUrl(publicBackendUrl: string): string {
|
|
@@ -53,6 +54,7 @@ function parseDomainList(raw: string): string[] {
|
|
|
53
54
|
.filter((d) => d.length > 0);
|
|
54
55
|
}
|
|
55
56
|
import { SpillStore } from '../modules/workspace/spill-store.js';
|
|
57
|
+
import { AgentUploadStore, assertUploadsRootOutsideWorkspaces } from '../modules/workspace/agent-upload.store.js';
|
|
56
58
|
import { DocExtractService } from '../modules/workspace/file-readers/doc-extract.service.js';
|
|
57
59
|
import { UuidSessionSink, type ISessionSink } from '../modules/workspace/session-sink.js';
|
|
58
60
|
import { AuthService } from '../modules/auth/auth.service.js';
|
|
@@ -110,7 +112,6 @@ import { WorkflowEventBus } from '../modules/workflow/event-bus.js';
|
|
|
110
112
|
import { FileChangeNotifier } from '../modules/kb-fs/file-change-notifier.js';
|
|
111
113
|
import { WorkflowService } from '../modules/workflow/workflow.service.js';
|
|
112
114
|
import { WorkflowHooks } from '../modules/workflow/workflow-hooks.js';
|
|
113
|
-
import { SessionOntologyService } from '../modules/workflow/session-ontology.service.js';
|
|
114
115
|
import { PendingCommitsService } from '../modules/workflow/pending-commits.service.js';
|
|
115
116
|
import {
|
|
116
117
|
PendingCommitsWorker,
|
|
@@ -142,6 +143,7 @@ import { BevelOAuthProvider } from '../modules/mcp/oauth/bevel-oauth-provider.js
|
|
|
142
143
|
import { getOAuthProtectedResourceMetadataUrl } from '@modelcontextprotocol/sdk/server/auth/router.js';
|
|
143
144
|
import { ToolRegistry } from '../modules/tool-registry/tool-registry.js';
|
|
144
145
|
import { createToolContextResolver } from '../modules/tool-helpers/tool-context.js';
|
|
146
|
+
import { alwaysWritable, type IWriteAccess } from '../modules/write-access/write-access.js';
|
|
145
147
|
import { createToolHandlerFactory } from '../modules/tool-helpers/tool-handler.js';
|
|
146
148
|
import { TokenCrypto } from '../shared/token-crypto.js';
|
|
147
149
|
import { UpdateCheckService } from '../modules/update-check/update-check.service.js';
|
|
@@ -182,6 +184,12 @@ export interface CoreServices {
|
|
|
182
184
|
* lease to the replacement.
|
|
183
185
|
*/
|
|
184
186
|
commitWorker: LeaseLoopHandle;
|
|
187
|
+
/**
|
|
188
|
+
* Run something with no queued commit being written: the commit worker is
|
|
189
|
+
* stopped for its duration and started again afterwards, the lease kept.
|
|
190
|
+
* What a move to another repository runs the startup phase under.
|
|
191
|
+
*/
|
|
192
|
+
whileCommitsHeld<T>(work: () => Promise<T>): Promise<T>;
|
|
185
193
|
workspaceService: WorkspaceService;
|
|
186
194
|
/**
|
|
187
195
|
* The KB startup phase (see `startup/on-server-start.ts`): run at the
|
|
@@ -213,12 +221,13 @@ export interface CoreServices {
|
|
|
213
221
|
/** The scope this graph's vault is registered under with the UTCP variable loader. */
|
|
214
222
|
secretsScope: string;
|
|
215
223
|
spillStore: SpillStore;
|
|
224
|
+
/** The bytes an agent uploaded, held until `apply_file_upload` lands them or their token expires. */
|
|
225
|
+
agentUploadStore: AgentUploadStore;
|
|
216
226
|
docExtractService: DocExtractService;
|
|
217
227
|
accessControl: AccessControlService;
|
|
218
228
|
creatorAccess: CreatorAccessService;
|
|
219
229
|
/** Read-before-write, for the surfaces that ask ahead of the lock (see `access-model/change-gate.ts`). */
|
|
220
230
|
changeGate: ChangeReadGate;
|
|
221
|
-
sessionOntologyService: SessionOntologyService;
|
|
222
231
|
routineWritePolicy: RoutineWritePolicyService;
|
|
223
232
|
skillService: SkillService;
|
|
224
233
|
pendingSkillsService: PendingSkillsService;
|
|
@@ -327,6 +336,8 @@ export interface CoreServices {
|
|
|
327
336
|
toolAuthMiddleware: ReturnType<typeof createToolAuthMiddleware>;
|
|
328
337
|
manualAuthMiddleware: ReturnType<typeof createManualAuthMiddleware>;
|
|
329
338
|
toolHandlerFactory: ReturnType<typeof createToolHandlerFactory>;
|
|
339
|
+
/** Whether the deployment may be changed right now — `ports.writeAccess`, or always. */
|
|
340
|
+
writeAccess: IWriteAccess;
|
|
330
341
|
// ── Server-time seams (enterprise overwrites after construction) ────────
|
|
331
342
|
/** `start_session` backing — core default {@link UuidSessionSink}. */
|
|
332
343
|
sessionSink: ISessionSink;
|
|
@@ -349,7 +360,11 @@ export async function createCoreServices(
|
|
|
349
360
|
// the default schema, so a single-tenant deployment keeps the lock ids and
|
|
350
361
|
// the ledger it always had.
|
|
351
362
|
const tenantKey = config.dbSchema === DEFAULT_DB_SCHEMA ? '' : config.dbSchema;
|
|
352
|
-
|
|
363
|
+
// The handle holds this knowledge base's key for its personal-data columns:
|
|
364
|
+
// the same `SECRETS_ENC_KEY` that seals its stored credentials — its own
|
|
365
|
+
// derived one, for a tenant — so everything in the schema opens with one
|
|
366
|
+
// key and nothing in it opens with another tenant's.
|
|
367
|
+
const db = getDb(config.databaseUrl, { schema: config.dbSchema, piiKey: config.secretsEncKey });
|
|
353
368
|
// A schema of its own is created on first use, so a tenant's first
|
|
354
369
|
// activation needs nothing done by hand; `public` always exists. Then the
|
|
355
370
|
// server is asked whether the connections really search that schema: a
|
|
@@ -369,6 +384,10 @@ export async function createCoreServices(
|
|
|
369
384
|
// package runs its own squashed idempotent CORE history from the packaged
|
|
370
385
|
// `migrations/` folder, tracked in `__drizzle_migrations_core`. An
|
|
371
386
|
// enterprise overlay runs its own history AFTER this (see migrate.ts).
|
|
387
|
+
// `runCoreMigrations` also seals any pre-encryption plaintext PII rows and
|
|
388
|
+
// swaps the unique constraints onto the blind-index columns (see
|
|
389
|
+
// migrate.ts), under the same lock, before any service reads or writes a
|
|
390
|
+
// PII column.
|
|
372
391
|
await runCoreMigrations(db, coreMigrationsDir());
|
|
373
392
|
|
|
374
393
|
// Deployment settings come next, before ANY service is built: the KB remote
|
|
@@ -486,12 +505,83 @@ export async function createCoreServices(
|
|
|
486
505
|
if (repositorySource.mode() === 'github-app') {
|
|
487
506
|
await githubApp.prepare().catch(() => undefined);
|
|
488
507
|
}
|
|
508
|
+
/**
|
|
509
|
+
* Where a working copy of a replaced repository is kept, for BOTH the places
|
|
510
|
+
* that find one: the KB startup phase sweeping the workspaces root, and the
|
|
511
|
+
* workspace service refusing to adopt one on a branch open. One variable,
|
|
512
|
+
* passed to both, because they move the same clones for the same reason and
|
|
513
|
+
* an admin looking for their work must have one folder to look in — the two
|
|
514
|
+
* drifted apart once already, and the copy the workspace service set aside
|
|
515
|
+
* landed in the image's own filesystem and was gone at the next recreate.
|
|
516
|
+
*
|
|
517
|
+
* Under the backups root: a persistent volume of its own, and one nothing
|
|
518
|
+
* sweeps (see the runner's `reconcileClonesWithConfiguredRepository`).
|
|
519
|
+
*/
|
|
520
|
+
const replacedWorkingCopiesRoot = path.join(config.backupsRoot, 'replaced-working-copies');
|
|
521
|
+
/**
|
|
522
|
+
* What must leave with a working copy that is set aside, whoever sets it
|
|
523
|
+
* aside: the startup phase, or the workspace service on a branch open.
|
|
524
|
+
*
|
|
525
|
+
* Its queue: whatever still waits to be committed into that copy was
|
|
526
|
+
* written against the repository that was left, and the path it names is
|
|
527
|
+
* about to hold a fresh clone of another one. Held for a person, on every
|
|
528
|
+
* branch, never written and never deleted.
|
|
529
|
+
*
|
|
530
|
+
* And the locks on its branch: each is a claim on a file of the copy that
|
|
531
|
+
* is going. Left standing, a holder still connected keeps one alive with
|
|
532
|
+
* heartbeats, and the same path in the new repository refuses everybody
|
|
533
|
+
* else. Dropped without enqueueing anything, as when change requests are
|
|
534
|
+
* closed as "repository replaced".
|
|
535
|
+
*
|
|
536
|
+
* Throws when either cannot be done, and the caller then leaves the copy
|
|
537
|
+
* where it is. Reaches FORWARD to both services, like `gitService` below:
|
|
538
|
+
* it is only ever called long after this function has returned them.
|
|
539
|
+
*/
|
|
540
|
+
const releaseWorkOnSetAsideCopy = async (workspaceId: string): Promise<void> => {
|
|
541
|
+
const held = await pendingCommitsService.markNeedsAttentionInWorkspace(
|
|
542
|
+
workspaceId,
|
|
543
|
+
'The knowledge-base repository was replaced while this commit was still queued, so it was never ' +
|
|
544
|
+
'written. The bytes are kept here: the working copy it was meant for belongs to the previous repository.',
|
|
545
|
+
);
|
|
546
|
+
if (held > 0) {
|
|
547
|
+
logger('kb-startup').warn(
|
|
548
|
+
`${held} queued commit(s) for the working copy "${workspaceId}" need attention: the repository was ` +
|
|
549
|
+
'replaced before they landed, so they were not written to the new one.',
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
await fileLockService.releaseAllOnBranch(branchForWorkspaceId(workspaceId));
|
|
553
|
+
};
|
|
489
554
|
const workspaceService = new WorkspaceService(
|
|
490
555
|
config.workspacesRoot,
|
|
491
556
|
() => repositorySource.url(),
|
|
492
557
|
kb,
|
|
493
558
|
disk,
|
|
494
559
|
gitRunner,
|
|
560
|
+
replacedWorkingCopiesRoot,
|
|
561
|
+
// A branch opened onto a clone of another repository sets it aside on
|
|
562
|
+
// the spot, with nobody having stopped the commit worker for it. So it
|
|
563
|
+
// is held here, for the one move, and the copy's work leaves first and
|
|
564
|
+
// is looked for again once the copy has gone: a release that queued its
|
|
565
|
+
// bytes in between was writing to the copy that left.
|
|
566
|
+
//
|
|
567
|
+
// Only the first look may refuse the branch: the copy has not moved yet.
|
|
568
|
+
// The second runs after the move, so its failure is tried once more and
|
|
569
|
+
// then logged, as the startup phase logs the same step. Refusing then
|
|
570
|
+
// would report a move that did happen as one that did not.
|
|
571
|
+
(workspaceId, move) =>
|
|
572
|
+
leased.whileHeld(async () => {
|
|
573
|
+
await releaseWorkOnSetAsideCopy(workspaceId);
|
|
574
|
+
await move();
|
|
575
|
+
await releaseWorkOnSetAsideCopy(workspaceId)
|
|
576
|
+
.catch(() => releaseWorkOnSetAsideCopy(workspaceId))
|
|
577
|
+
.catch((err: unknown) => {
|
|
578
|
+
logger('workspace').error(
|
|
579
|
+
`the working copy "${workspaceId}" was set aside, but what was queued or locked on it meanwhile ` +
|
|
580
|
+
'could not be looked for again:',
|
|
581
|
+
{ err },
|
|
582
|
+
);
|
|
583
|
+
});
|
|
584
|
+
}),
|
|
495
585
|
);
|
|
496
586
|
// The KB startup phase: every seeding, scaffolding and migration concern,
|
|
497
587
|
// run through one runner at the deployment's quiet moments (boot + setup
|
|
@@ -529,10 +619,9 @@ export async function createCoreServices(
|
|
|
529
619
|
// the first thing that needs them.
|
|
530
620
|
kbRepoUrl: () => repositorySource.url(),
|
|
531
621
|
workspacesRoot: config.workspacesRoot,
|
|
532
|
-
//
|
|
533
|
-
//
|
|
534
|
-
|
|
535
|
-
setAsideRoot: path.join(config.backupsRoot, 'replaced-working-copies'),
|
|
622
|
+
// The same folder the workspace service sets aside into — see
|
|
623
|
+
// `replacedWorkingCopiesRoot` above for why the two must agree.
|
|
624
|
+
setAsideRoot: replacedWorkingCopiesRoot,
|
|
536
625
|
kbDirName,
|
|
537
626
|
templateDir: config.kbTemplateDir,
|
|
538
627
|
defaultBranch: () => kb.defaultBranch,
|
|
@@ -543,10 +632,48 @@ export async function createCoreServices(
|
|
|
543
632
|
steps: kbStartupSteps,
|
|
544
633
|
buildSeedTree: buildSeedTree(disk, config.kbTemplateDir, extraDirs, [config.adminEmail], kb),
|
|
545
634
|
gitRunner,
|
|
635
|
+
// The work on a working copy that is about to be set aside leaves first:
|
|
636
|
+
// its queued commits and the locks on its branch (see
|
|
637
|
+
// `releaseWorkOnSetAsideCopy`). A failure here stops the phase before
|
|
638
|
+
// the copy moves: a replacement cloned over an untouched queue is how
|
|
639
|
+
// those bytes would land in the wrong repository.
|
|
640
|
+
beforeCloneSetAside: releaseWorkOnSetAsideCopy,
|
|
641
|
+
// And once it is set aside it must leave the workspace service's cache:
|
|
642
|
+
// on the SAVE that moves the deployment the process is already running,
|
|
643
|
+
// and a cached path to a directory that is gone is how the next reader
|
|
644
|
+
// gets an ENOENT instead of a fresh clone.
|
|
645
|
+
//
|
|
646
|
+
// Then the copy's work is looked for once more. A release that queued
|
|
647
|
+
// its bytes between the first look and the move was writing to the copy
|
|
648
|
+
// that has now gone; nothing can queue against it after this.
|
|
649
|
+
onCloneDiscarded: async (workspaceId) => {
|
|
650
|
+
workspaceService.forgetClone(workspaceId);
|
|
651
|
+
await releaseWorkOnSetAsideCopy(workspaceId);
|
|
652
|
+
},
|
|
653
|
+
// And the replacement it cloned in its place: a fresh clone holds every
|
|
654
|
+
// ref, so the git layer's per-workspace fetch record is told so. Without
|
|
655
|
+
// it that record still holds the FAILED fetch of the repository that was
|
|
656
|
+
// replaced, and a strict branch listing within its TTL refuses the new
|
|
657
|
+
// clone's refs as unproven. Reaches FORWARD to `gitService`, which is
|
|
658
|
+
// built further down: safe because the runner only ever calls this from
|
|
659
|
+
// `runAll`, which the server builder invokes long after this function has
|
|
660
|
+
// returned every service.
|
|
661
|
+
onCloneCreated: (workspaceId) => gitService.noteWorkspaceFetched(workspaceId),
|
|
546
662
|
});
|
|
547
663
|
// Shared, workspace-independent store for oversized `call_tool_chain` results,
|
|
548
664
|
// read back via `read_file`. Sibling of `workspacesRoot`, never committed.
|
|
549
665
|
const spillStore = new SpillStore(config.spillRoot);
|
|
666
|
+
// The upload route an agent lands files by, so their content never passes
|
|
667
|
+
// through the model. Bytes live BESIDE the workspaces root (never inside
|
|
668
|
+
// one) until the apply commits them or the token expires — checked here
|
|
669
|
+
// rather than assumed, because a root configured inside a workspace would
|
|
670
|
+
// put bytes no gate has judged where the file tools read.
|
|
671
|
+
await assertUploadsRootOutsideWorkspaces(config.agentUploadsRoot, config.workspacesRoot);
|
|
672
|
+
const agentUploadStore = new AgentUploadStore({
|
|
673
|
+
root: config.agentUploadsRoot,
|
|
674
|
+
publicBaseUrl: config.publicBackendUrl,
|
|
675
|
+
tokenPrefix: config.uploadTokenPrefix,
|
|
676
|
+
});
|
|
550
677
|
// Office-document/PDF text extraction for `read_file`/`grep`, cached by
|
|
551
678
|
// content hash beside the workspaces root (see `DocExtractionCache`).
|
|
552
679
|
const docExtractService = new DocExtractService(config.docExtractCacheRoot);
|
|
@@ -574,14 +701,10 @@ export async function createCoreServices(
|
|
|
574
701
|
// except that new folder at a root (see `access-model/change-gate.ts`).
|
|
575
702
|
const changeGate = new ChangeReadGate(workspaceService, accessControl, kb, disk);
|
|
576
703
|
|
|
577
|
-
// Ontology-session boundary: records each agent run's touched ontologies and
|
|
578
|
-
// blocks writes once a run has crossed ontologies. Postgres-backed so the
|
|
579
|
-
// boundary survives a restart.
|
|
580
|
-
const sessionOntologyService = new SessionOntologyService(db, kb);
|
|
581
704
|
// Per-run write restriction (by file extension). Shared by the workspace tool
|
|
582
705
|
// surface (which enforces it) and the routine runner (which sets it for
|
|
583
|
-
// dashboard-only `watchlist_check` runs). In-memory: a restriction lives only
|
|
584
|
-
// one run
|
|
706
|
+
// dashboard-only `watchlist_check` runs). In-memory: a restriction lives only
|
|
707
|
+
// for one run.
|
|
585
708
|
const routineWritePolicy = new RoutineWritePolicyService();
|
|
586
709
|
// Skills: discovered from the default-branch workspace only (global catalog).
|
|
587
710
|
const skillService = new SkillService(workspaceService, accessControl, kb, disk);
|
|
@@ -632,11 +755,11 @@ export async function createCoreServices(
|
|
|
632
755
|
// against each other — a backup-reseed races a concurrent commit otherwise.
|
|
633
756
|
const workspaceMutex = new WorkspaceMutex();
|
|
634
757
|
// Workflow lifecycle hooks — the ONE registry this composition shares
|
|
635
|
-
// between GitService (advisory commit validation), the
|
|
636
|
-
//
|
|
637
|
-
// registers module-owned handlers on `workflowService.hooks` right
|
|
638
|
-
// this function returns. Core registers none: no commit-time
|
|
639
|
-
// (advisory anyway) and
|
|
758
|
+
// between GitService (advisory commit validation), the agent-access gate
|
|
759
|
+
// (the blocking agentRead / preWrite hooks), and the composition root,
|
|
760
|
+
// which registers module-owned handlers on `workflowService.hooks` right
|
|
761
|
+
// after this function returns. Core registers none: no commit-time
|
|
762
|
+
// validation (advisory anyway) and nothing that refuses an agent call.
|
|
640
763
|
const workflowHooks = new WorkflowHooks();
|
|
641
764
|
const gitService = new GitService(
|
|
642
765
|
workspaceService,
|
|
@@ -731,7 +854,7 @@ export async function createCoreServices(
|
|
|
731
854
|
eventBus,
|
|
732
855
|
fileChangeNotifier,
|
|
733
856
|
// Exposed as `workflowService.hooks` — the SAME instance GitService and
|
|
734
|
-
// the
|
|
857
|
+
// the agent-access gate consult, so a deployment's registrations against
|
|
735
858
|
// it reach every hook point.
|
|
736
859
|
workflowHooks,
|
|
737
860
|
);
|
|
@@ -1066,6 +1189,9 @@ export async function createCoreServices(
|
|
|
1066
1189
|
// For the needs-authorization setup link surfaced to external agents.
|
|
1067
1190
|
publicFrontendUrl: config.publicFrontendUrl,
|
|
1068
1191
|
readAgentPreamble: readPreamble,
|
|
1192
|
+
// The guide's name the shared file rules spell, read per request so a name
|
|
1193
|
+
// the setup save applies lands without a restart.
|
|
1194
|
+
kbLayout: () => kb.layout,
|
|
1069
1195
|
secretsScope,
|
|
1070
1196
|
},
|
|
1071
1197
|
// Pre-dispatch per-user credential check: the vault answers "has this caller
|
|
@@ -1134,8 +1260,9 @@ export async function createCoreServices(
|
|
|
1134
1260
|
creatorAccess,
|
|
1135
1261
|
loadActiveGroups,
|
|
1136
1262
|
});
|
|
1137
|
-
const
|
|
1138
|
-
const
|
|
1263
|
+
const writeAccess = ports.writeAccess ?? alwaysWritable;
|
|
1264
|
+
const toolHandlerFactory = createToolHandlerFactory(resolveToolContext, writeAccess);
|
|
1265
|
+
const toolAuthMiddleware = createToolAuthMiddleware(externalApiKeyService, internalTokenService, authService);
|
|
1139
1266
|
// Read-only manual endpoints accept the above PLUS a browser JWT, so a
|
|
1140
1267
|
// logged-in user can browse the catalog with their session. Execution routes
|
|
1141
1268
|
// keep `toolAuthMiddleware` (no JWT), so a session can read but not invoke.
|
|
@@ -1187,7 +1314,10 @@ export async function createCoreServices(
|
|
|
1187
1314
|
name: recoveryBot.name,
|
|
1188
1315
|
},
|
|
1189
1316
|
});
|
|
1190
|
-
|
|
1317
|
+
// Holdable: a move to another repository stops the worker for as long as
|
|
1318
|
+
// working copies are being set aside and cloned again, without giving up
|
|
1319
|
+
// the lease (see `holdable` in `core/lifecycle.ts`).
|
|
1320
|
+
const leased = holdable(withStartupTask(pendingCommitsWorker, reconcileQueue));
|
|
1191
1321
|
|
|
1192
1322
|
// SSO providers. The array REFERENCE is shared with the caller's port — an
|
|
1193
1323
|
// overlay pushes its own plugins into it after construction (they mount when
|
|
@@ -1283,6 +1413,7 @@ export async function createCoreServices(
|
|
|
1283
1413
|
db,
|
|
1284
1414
|
gitRunner,
|
|
1285
1415
|
commitWorker,
|
|
1416
|
+
whileCommitsHeld: (work) => leased.whileHeld(work),
|
|
1286
1417
|
startupRetry: null,
|
|
1287
1418
|
tenantKey,
|
|
1288
1419
|
secretsScope,
|
|
@@ -1298,11 +1429,11 @@ export async function createCoreServices(
|
|
|
1298
1429
|
kb,
|
|
1299
1430
|
kbDirName,
|
|
1300
1431
|
spillStore,
|
|
1432
|
+
agentUploadStore,
|
|
1301
1433
|
docExtractService,
|
|
1302
1434
|
accessControl,
|
|
1303
1435
|
creatorAccess,
|
|
1304
1436
|
changeGate,
|
|
1305
|
-
sessionOntologyService,
|
|
1306
1437
|
routineWritePolicy,
|
|
1307
1438
|
skillService,
|
|
1308
1439
|
pendingSkillsService,
|
|
@@ -1353,6 +1484,7 @@ export async function createCoreServices(
|
|
|
1353
1484
|
toolAuthMiddleware,
|
|
1354
1485
|
manualAuthMiddleware,
|
|
1355
1486
|
toolHandlerFactory,
|
|
1487
|
+
writeAccess,
|
|
1356
1488
|
// Server-time seams — defaults here; the enterprise overlay overwrites
|
|
1357
1489
|
// (or, for the array, pushes into) these after construction.
|
|
1358
1490
|
sessionSink: ports.sessionSink ?? new UuidSessionSink(),
|