@bevel-software/platform-core-backend 0.35.0 → 0.36.1
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/agent-guide/directory-structure.md +1 -1
- package/agent-guide/onboarding.md +111 -0
- package/agent-guide/start-here.md +1 -0
- package/agent-guide/tool-manuals.md +1 -0
- package/dist/core/catalog-cache-invalidation.d.ts +2 -2
- package/dist/core/catalog-cache-invalidation.d.ts.map +1 -1
- package/dist/core/compose-embed.d.ts +2 -2
- package/dist/core/compose-embed.d.ts.map +1 -1
- package/dist/core/compose-embed.js +1 -1
- package/dist/core/compose-embed.js.map +1 -1
- package/dist/core/core-ports.d.ts +19 -4
- 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.map +1 -1
- package/dist/core/create-core-server.js +26 -24
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +19 -13
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +68 -56
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core/lifecycle.d.ts +4 -4
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +5 -5
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/core-config.d.ts +2 -2
- package/dist/core-config.js +3 -3
- package/dist/core-config.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/modules/access/access-control.service.js +1 -1
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/access-declarations.d.ts +2 -2
- package/dist/modules/access/access-declarations.d.ts.map +1 -1
- package/dist/modules/access/access-declarations.js +2 -2
- package/dist/modules/access/access-declarations.js.map +1 -1
- package/dist/modules/access/access-mutation.service.d.ts +2 -2
- package/dist/modules/access/access-mutation.service.d.ts.map +1 -1
- package/dist/modules/access/access-mutation.service.js +2 -2
- package/dist/modules/access/access-mutation.service.js.map +1 -1
- package/dist/modules/access/access-requests.routes.d.ts +2 -2
- package/dist/modules/access/access-requests.routes.d.ts.map +1 -1
- package/dist/modules/access/access-requests.routes.js +5 -5
- package/dist/modules/access/access-requests.routes.js.map +1 -1
- package/dist/modules/access/access-requests.service.d.ts +2 -2
- package/dist/modules/access/access-requests.service.d.ts.map +1 -1
- package/dist/modules/access/access-requests.service.js +11 -11
- package/dist/modules/access/access-requests.service.js.map +1 -1
- package/dist/modules/access/access.routes.d.ts +2 -2
- package/dist/modules/access/access.routes.d.ts.map +1 -1
- package/dist/modules/access/access.routes.js +9 -9
- package/dist/modules/access/access.routes.js.map +1 -1
- package/dist/modules/access/admin-locked-commit.d.ts +5 -5
- package/dist/modules/access/admin-locked-commit.d.ts.map +1 -1
- package/dist/modules/access/admin-locked-commit.js +7 -7
- package/dist/modules/access/admin-locked-commit.js.map +1 -1
- package/dist/modules/access/admin-route-helpers.d.ts +1 -1
- package/dist/modules/access/admin-route-helpers.js +5 -5
- package/dist/modules/access/admin-route-helpers.js.map +1 -1
- package/dist/modules/access/change-read-gate.d.ts +1 -1
- package/dist/modules/access/change-read-gate.js +1 -1
- package/dist/modules/access/groups-admin.service.d.ts +7 -7
- package/dist/modules/access/groups-admin.service.d.ts.map +1 -1
- package/dist/modules/access/groups-admin.service.js +6 -6
- package/dist/modules/access/groups-admin.service.js.map +1 -1
- package/dist/modules/access/reference-scan.d.ts +1 -1
- package/dist/modules/access/roles-admin.service.d.ts +7 -7
- package/dist/modules/access/roles-admin.service.d.ts.map +1 -1
- package/dist/modules/access/roles-admin.service.js +8 -8
- package/dist/modules/access/roles-admin.service.js.map +1 -1
- package/dist/modules/access/synced-groups-committer.d.ts +4 -4
- package/dist/modules/access/synced-groups-committer.d.ts.map +1 -1
- package/dist/modules/access/synced-groups-committer.js +7 -7
- package/dist/modules/access/synced-groups-committer.js.map +1 -1
- package/dist/modules/access/user-access-removal.service.d.ts +6 -6
- package/dist/modules/access/user-access-removal.service.d.ts.map +1 -1
- package/dist/modules/access/user-access-removal.service.js +4 -4
- package/dist/modules/access/user-access-removal.service.js.map +1 -1
- package/dist/modules/access-model/access-errors.d.ts +4 -4
- package/dist/modules/access-model/access-errors.d.ts.map +1 -1
- package/dist/modules/access-model/access-errors.js +4 -4
- package/dist/modules/access-model/access-errors.js.map +1 -1
- package/dist/modules/access-model/access-grammar.d.ts +1 -1
- package/dist/modules/access-model/access-grammar.js +4 -4
- package/dist/modules/access-model/change-gate.d.ts +1 -1
- package/dist/modules/access-model/change-gate.js +1 -1
- package/dist/modules/access-model/roles-yaml-guard.d.ts +4 -4
- package/dist/modules/access-model/roles-yaml-guard.d.ts.map +1 -1
- package/dist/modules/access-model/roles-yaml-guard.js +4 -4
- package/dist/modules/access-model/roles-yaml-guard.js.map +1 -1
- package/dist/modules/agent-guide/agent-guide.d.ts +19 -14
- package/dist/modules/agent-guide/agent-guide.d.ts.map +1 -1
- package/dist/modules/agent-guide/agent-guide.js +42 -18
- package/dist/modules/agent-guide/agent-guide.js.map +1 -1
- package/dist/modules/agent-guide/guide-budget.d.ts +5 -2
- package/dist/modules/agent-guide/guide-budget.d.ts.map +1 -1
- package/dist/modules/agent-guide/guide-budget.js +6 -2
- package/dist/modules/agent-guide/guide-budget.js.map +1 -1
- package/dist/modules/agent-instructions/agent-instructions.routes.d.ts +12 -5
- package/dist/modules/agent-instructions/agent-instructions.routes.d.ts.map +1 -1
- package/dist/modules/agent-instructions/agent-instructions.routes.js +13 -6
- package/dist/modules/agent-instructions/agent-instructions.routes.js.map +1 -1
- package/dist/modules/agent-instructions/compose.d.ts +15 -8
- package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
- package/dist/modules/agent-instructions/compose.js +24 -10
- package/dist/modules/agent-instructions/compose.js.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.d.ts +14 -6
- package/dist/modules/agent-instructions/shared-file-rules.d.ts.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.js +51 -11
- package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -1
- package/dist/modules/auth/account-erasure.service.d.ts +36 -7
- package/dist/modules/auth/account-erasure.service.d.ts.map +1 -1
- package/dist/modules/auth/account-erasure.service.js +30 -10
- package/dist/modules/auth/account-erasure.service.js.map +1 -1
- package/dist/modules/auth/account-hooks.d.ts +20 -0
- package/dist/modules/auth/account-hooks.d.ts.map +1 -1
- package/dist/modules/auth/account-hooks.js +10 -0
- package/dist/modules/auth/account-hooks.js.map +1 -1
- package/dist/modules/auth/account-switch-lock.js +2 -2
- package/dist/modules/auth/account-switch-lock.js.map +1 -1
- package/dist/modules/auth/account.routes.d.ts +7 -2
- package/dist/modules/auth/account.routes.d.ts.map +1 -1
- package/dist/modules/auth/account.routes.js +23 -4
- package/dist/modules/auth/account.routes.js.map +1 -1
- package/dist/modules/auth/auth.service.d.ts +1 -1
- package/dist/modules/auth/auth.service.js +4 -4
- package/dist/modules/auth/auth.service.js.map +1 -1
- package/dist/modules/auth/index.d.ts +1 -0
- package/dist/modules/auth/index.d.ts.map +1 -1
- package/dist/modules/database/core-schema.js +2 -2
- package/dist/modules/database/core-schema.js.map +1 -1
- package/dist/modules/diff/diff.routes.d.ts +3 -3
- package/dist/modules/diff/diff.routes.d.ts.map +1 -1
- package/dist/modules/diff/diff.routes.js +7 -7
- package/dist/modules/diff/diff.routes.js.map +1 -1
- package/dist/modules/embed/embed.routes.js +1 -1
- package/dist/modules/embed/embed.routes.js.map +1 -1
- package/dist/modules/embed/embed.service.d.ts +4 -4
- package/dist/modules/embed/embed.service.d.ts.map +1 -1
- package/dist/modules/embed/embed.service.js +18 -18
- package/dist/modules/embed/embed.service.js.map +1 -1
- package/dist/modules/kb-fs/branch-name.js +8 -8
- package/dist/modules/kb-fs/branch-name.js.map +1 -1
- package/dist/modules/kb-fs/file-change-notifier.d.ts +2 -2
- package/dist/modules/kb-fs/locking-filesystem.d.ts +9 -9
- package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
- package/dist/modules/kb-fs/locking-filesystem.js +27 -27
- package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
- package/dist/modules/kb-fs/repo-path.js +5 -5
- package/dist/modules/kb-fs/repo-path.js.map +1 -1
- package/dist/modules/kb-fs/tmp-ref.d.ts +2 -2
- package/dist/modules/kb-fs/tmp-ref.d.ts.map +1 -1
- package/dist/modules/kb-fs/tmp-ref.js +2 -2
- package/dist/modules/kb-fs/tmp-ref.js.map +1 -1
- package/dist/modules/kb-sync/index.d.ts +1 -1
- package/dist/modules/kb-sync/index.d.ts.map +1 -1
- package/dist/modules/kb-sync/kb-sync.interface.d.ts +3 -3
- package/dist/modules/kb-sync/kb-sync.interface.d.ts.map +1 -1
- package/dist/modules/kb-sync/kb-sync.service.d.ts +3 -3
- package/dist/modules/kb-sync/kb-sync.service.d.ts.map +1 -1
- package/dist/modules/kb-sync/kb-sync.service.js +10 -10
- package/dist/modules/kb-sync/kb-sync.service.js.map +1 -1
- package/dist/modules/mcp/mcp.service.d.ts +11 -4
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +75 -19
- package/dist/modules/mcp/mcp.service.js.map +1 -1
- package/dist/modules/onboarding/onboarding.contract.d.ts +1 -1
- package/dist/modules/onboarding/onboarding.routes.js +2 -2
- package/dist/modules/onboarding/onboarding.routes.js.map +1 -1
- package/dist/modules/onboarding/starter-pack.service.d.ts +4 -4
- package/dist/modules/onboarding/starter-pack.service.d.ts.map +1 -1
- package/dist/modules/onboarding/starter-pack.service.js +4 -4
- package/dist/modules/onboarding/starter-pack.service.js.map +1 -1
- package/dist/modules/plugins/join-request-jobs.service.d.ts +2 -2
- package/dist/modules/plugins/join-request-jobs.service.d.ts.map +1 -1
- package/dist/modules/plugins/join-request-jobs.service.js +7 -7
- package/dist/modules/plugins/join-request-jobs.service.js.map +1 -1
- package/dist/modules/plugins/join-requests.service.d.ts +3 -3
- package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
- package/dist/modules/plugins/join-requests.service.js +5 -5
- package/dist/modules/plugins/join-requests.service.js.map +1 -1
- package/dist/modules/plugins/plugin-rename.service.js +1 -1
- package/dist/modules/plugins/plugin-rename.service.js.map +1 -1
- package/dist/modules/plugins/plugins.routes.d.ts +2 -2
- package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.routes.js +8 -8
- package/dist/modules/plugins/plugins.routes.js.map +1 -1
- package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts +77 -2
- package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts.map +1 -1
- package/dist/modules/secrets-vault/db-secrets-vault.service.js +479 -53
- package/dist/modules/secrets-vault/db-secrets-vault.service.js.map +1 -1
- package/dist/modules/secrets-vault/index.d.ts +2 -1
- package/dist/modules/secrets-vault/index.d.ts.map +1 -1
- package/dist/modules/secrets-vault/index.js +1 -0
- package/dist/modules/secrets-vault/index.js.map +1 -1
- package/dist/modules/secrets-vault/managed-sign-in-erasure.d.ts +36 -0
- package/dist/modules/secrets-vault/managed-sign-in-erasure.d.ts.map +1 -0
- package/dist/modules/secrets-vault/managed-sign-in-erasure.js +37 -0
- package/dist/modules/secrets-vault/managed-sign-in-erasure.js.map +1 -0
- package/dist/modules/secrets-vault/secrets-vault.contract.d.ts +152 -0
- package/dist/modules/secrets-vault/secrets-vault.contract.d.ts.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.contract.js.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +7 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.js +125 -10
- package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
- package/dist/modules/settings/connection-check.js +1 -1
- package/dist/modules/settings/connection-check.js.map +1 -1
- package/dist/modules/settings/deployment-settings.service.js +1 -1
- package/dist/modules/settings/git-root-folders.js +1 -1
- package/dist/modules/settings/git-root-folders.js.map +1 -1
- package/dist/modules/settings/setup.routes.d.ts +1 -1
- package/dist/modules/settings/setup.routes.js +1 -1
- package/dist/modules/skills/pending-skills.service.d.ts +3 -3
- package/dist/modules/skills/pending-skills.service.d.ts.map +1 -1
- package/dist/modules/skills/pending-skills.service.js +4 -4
- package/dist/modules/skills/pending-skills.service.js.map +1 -1
- package/dist/modules/skills/skill-access-requests.routes.d.ts +2 -2
- package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -1
- package/dist/modules/skills/skill-access-requests.routes.js +5 -5
- package/dist/modules/skills/skill-access-requests.routes.js.map +1 -1
- package/dist/modules/tool-helpers/tool-context.d.ts +4 -4
- package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool-context.js +2 -2
- package/dist/modules/tool-helpers/tool-context.js.map +1 -1
- package/dist/modules/tool-helpers/tool-handler.js +2 -2
- package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
- package/dist/modules/tool-helpers/tool.contract.d.ts +4 -4
- package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
- package/dist/modules/tool-manuals/mcp-server-edit.service.js +1 -1
- package/dist/modules/tool-manuals/mcp-server-edit.service.js.map +1 -1
- package/dist/modules/tool-manuals/pending-tools.service.d.ts +3 -3
- package/dist/modules/tool-manuals/pending-tools.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/pending-tools.service.js +4 -4
- package/dist/modules/tool-manuals/pending-tools.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-delete.service.js +1 -1
- package/dist/modules/tool-manuals/tool-delete.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +43 -3
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts +6 -0
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +51 -5
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +3 -0
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +36 -15
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/version-control/agent-tools/change-request-read-shape.d.ts.map +1 -0
- package/dist/modules/version-control/agent-tools/change-request-read-shape.js.map +1 -0
- package/dist/modules/version-control/agent-tools/change-request-read.tools.d.ts.map +1 -0
- package/dist/modules/{workflow → version-control}/agent-tools/change-request-read.tools.js +2 -2
- package/dist/modules/version-control/agent-tools/change-request-read.tools.js.map +1 -0
- package/dist/modules/version-control/agent-tools/change-request-summary.d.ts.map +1 -0
- package/dist/modules/version-control/agent-tools/change-request-summary.js.map +1 -0
- package/dist/modules/{workflow/agent-tools/workflow.tools.d.ts → version-control/agent-tools/version-control.tools.d.ts} +4 -4
- package/dist/modules/version-control/agent-tools/version-control.tools.d.ts.map +1 -0
- package/dist/modules/{workflow/agent-tools/workflow.tools.js → version-control/agent-tools/version-control.tools.js} +31 -31
- package/dist/modules/version-control/agent-tools/version-control.tools.js.map +1 -0
- package/dist/modules/{workflow → version-control}/change-request-hooks.d.ts +1 -1
- package/dist/modules/version-control/change-request-hooks.d.ts.map +1 -0
- package/dist/modules/version-control/change-request-hooks.js.map +1 -0
- package/dist/modules/version-control/change-request-review/approval-lock.d.ts.map +1 -0
- package/dist/modules/version-control/change-request-review/approval-lock.js.map +1 -0
- package/dist/modules/{workflow/review-workflow/review-workflow.interface.d.ts → version-control/change-request-review/change-request-review.interface.d.ts} +2 -2
- package/dist/modules/version-control/change-request-review/change-request-review.interface.d.ts.map +1 -0
- package/dist/modules/version-control/change-request-review/change-request-review.interface.js +2 -0
- package/dist/modules/version-control/change-request-review/change-request-review.interface.js.map +1 -0
- package/dist/modules/{workflow/review-workflow/review-workflow.service.d.ts → version-control/change-request-review/change-request-review.service.d.ts} +3 -3
- package/dist/modules/version-control/change-request-review/change-request-review.service.d.ts.map +1 -0
- package/dist/modules/{workflow/review-workflow/review-workflow.service.js → version-control/change-request-review/change-request-review.service.js} +26 -26
- package/dist/modules/version-control/change-request-review/change-request-review.service.js.map +1 -0
- package/dist/modules/{workflow → version-control}/event-bus.d.ts +8 -8
- package/dist/modules/version-control/event-bus.d.ts.map +1 -0
- package/dist/modules/{workflow → version-control}/event-bus.js +4 -4
- package/dist/modules/version-control/event-bus.js.map +1 -0
- package/dist/modules/{workflow → version-control}/events-delivery.d.ts +4 -4
- package/dist/modules/version-control/events-delivery.d.ts.map +1 -0
- package/dist/modules/version-control/events-delivery.js.map +1 -0
- package/dist/modules/{workflow → version-control}/events.routes.d.ts +4 -4
- package/dist/modules/version-control/events.routes.d.ts.map +1 -0
- package/dist/modules/version-control/events.routes.js.map +1 -0
- package/dist/modules/{workflow → version-control}/file-lock.service.d.ts +2 -2
- package/dist/modules/version-control/file-lock.service.d.ts.map +1 -0
- package/dist/modules/{workflow → version-control}/file-lock.service.js +6 -6
- package/dist/modules/version-control/file-lock.service.js.map +1 -0
- package/dist/modules/version-control/git/change-request-link.d.ts.map +1 -0
- package/dist/modules/version-control/git/change-request-link.js.map +1 -0
- package/dist/modules/version-control/git/git-version.d.ts.map +1 -0
- package/dist/modules/version-control/git/git-version.js.map +1 -0
- package/dist/modules/{workflow → version-control}/git/git.service.d.ts +8 -8
- package/dist/modules/version-control/git/git.service.d.ts.map +1 -0
- package/dist/modules/{workflow → version-control}/git/git.service.js +53 -53
- package/dist/modules/version-control/git/git.service.js.map +1 -0
- package/dist/modules/version-control/git/merge-commit.d.ts.map +1 -0
- package/dist/modules/version-control/git/merge-commit.js.map +1 -0
- package/dist/modules/version-control/git/node-git-runner.d.ts.map +1 -0
- package/dist/modules/{workflow → version-control}/git/node-git-runner.js +1 -1
- package/dist/modules/version-control/git/node-git-runner.js.map +1 -0
- package/dist/modules/{workflow → version-control}/git/pull-request.service.d.ts +5 -5
- package/dist/modules/version-control/git/pull-request.service.d.ts.map +1 -0
- package/dist/modules/{workflow → version-control}/git/pull-request.service.js +10 -10
- package/dist/modules/version-control/git/pull-request.service.js.map +1 -0
- package/dist/modules/{workflow → version-control}/index.d.ts +6 -5
- package/dist/modules/version-control/index.d.ts.map +1 -0
- package/dist/modules/{workflow → version-control}/index.js +3 -2
- package/dist/modules/version-control/index.js.map +1 -0
- package/dist/modules/{workflow → version-control}/pending-commits.service.d.ts +2 -2
- package/dist/modules/version-control/pending-commits.service.d.ts.map +1 -0
- package/dist/modules/{workflow → version-control}/pending-commits.service.js +2 -2
- package/dist/modules/version-control/pending-commits.service.js.map +1 -0
- package/dist/modules/{workflow → version-control}/pending-commits.worker.d.ts +5 -5
- package/dist/modules/version-control/pending-commits.worker.d.ts.map +1 -0
- package/dist/modules/{workflow → version-control}/pending-commits.worker.js +3 -3
- package/dist/modules/version-control/pending-commits.worker.js.map +1 -0
- package/dist/modules/{workflow → version-control}/read-on-branch.d.ts +2 -2
- package/dist/modules/version-control/read-on-branch.d.ts.map +1 -0
- package/dist/modules/{workflow → version-control}/read-on-branch.js +2 -2
- package/dist/modules/version-control/read-on-branch.js.map +1 -0
- package/dist/modules/version-control/recovery-bot.d.ts.map +1 -0
- package/dist/modules/version-control/recovery-bot.js.map +1 -0
- package/dist/modules/version-control/sanitize-error.d.ts.map +1 -0
- package/dist/modules/version-control/sanitize-error.js.map +1 -0
- package/dist/modules/{workflow/workflow-hooks.d.ts → version-control/version-control-hooks.d.ts} +4 -4
- package/dist/modules/version-control/version-control-hooks.d.ts.map +1 -0
- package/dist/modules/{workflow/workflow-hooks.js → version-control/version-control-hooks.js} +3 -3
- package/dist/modules/version-control/version-control-hooks.js.map +1 -0
- package/dist/modules/{workflow/workflow.routes.d.ts → version-control/version-control.routes.d.ts} +6 -5
- package/dist/modules/version-control/version-control.routes.d.ts.map +1 -0
- package/dist/modules/{workflow/workflow.routes.js → version-control/version-control.routes.js} +61 -60
- package/dist/modules/version-control/version-control.routes.js.map +1 -0
- package/dist/modules/{workflow/workflow.service.d.ts → version-control/version-control.service.d.ts} +26 -31
- package/dist/modules/version-control/version-control.service.d.ts.map +1 -0
- package/dist/modules/{workflow/workflow.service.js → version-control/version-control.service.js} +89 -94
- package/dist/modules/version-control/version-control.service.js.map +1 -0
- package/dist/modules/workspace/agent-access.gate.d.ts +5 -5
- package/dist/modules/workspace/agent-access.gate.d.ts.map +1 -1
- package/dist/modules/workspace/agent-access.gate.js +1 -1
- package/dist/modules/workspace/git-internals.middleware.d.ts +1 -1
- package/dist/modules/workspace/git-internals.middleware.js +2 -2
- package/dist/modules/workspace/kb-repository.js +1 -1
- package/dist/modules/workspace/kb-repository.js.map +1 -1
- package/dist/modules/workspace/startup/kb-git.d.ts +1 -1
- package/dist/modules/workspace/startup/kb-git.d.ts.map +1 -1
- package/dist/modules/workspace/startup/kb-git.js +1 -1
- package/dist/modules/workspace/startup/kb-git.js.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts +2 -2
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.js +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts +2 -2
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-files.step.js +2 -2
- package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.d.ts +17 -4
- package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.js +8 -5
- package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
- package/dist/modules/workspace/workspace-tmp.js +3 -3
- package/dist/modules/workspace/workspace-tmp.js.map +1 -1
- package/dist/modules/workspace/workspace.routes.d.ts +4 -4
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.routes.js +22 -22
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +6 -6
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +11 -11
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts +2 -1
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +15 -10
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/shared/canonical-file-identity.d.ts +2 -2
- package/dist/shared/canonical-file-identity.js +5 -5
- package/dist/shared/canonical-file-identity.js.map +1 -1
- package/dist/shared/domain-errors.d.ts +39 -39
- package/dist/shared/domain-errors.d.ts.map +1 -1
- package/dist/shared/domain-errors.js +44 -44
- package/dist/shared/domain-errors.js.map +1 -1
- package/dist/shared/git.contract.d.ts +1 -1
- package/dist/shared/git.contract.js +1 -1
- package/dist/shared/http-errors.d.ts +3 -3
- package/dist/shared/http-errors.d.ts.map +1 -1
- package/dist/shared/http-errors.js +1 -1
- package/dist/shared/http-errors.js.map +1 -1
- package/dist/shared/pending-proposals.d.ts +3 -3
- package/dist/shared/pending-proposals.d.ts.map +1 -1
- package/dist/shared/pending-proposals.js +2 -2
- package/dist/shared/pending-proposals.js.map +1 -1
- package/dist/tenancy/static-tenant-source.js +1 -1
- package/dist/tenancy/static-tenant-source.js.map +1 -1
- package/migrations/0012_agent_audit.sql +40 -40
- package/migrations/0013_agent_identity_and_key_soft_delete.sql +29 -29
- package/migrations/meta/0012_snapshot.json +2246 -2246
- package/migrations/meta/0013_snapshot.json +2258 -2258
- package/package.json +4 -4
- package/src/__tests__/account-admin.ts +27 -0
- package/src/__tests__/hexis-catalog.ts +4 -4
- package/src/__tests__/kb-context.ts +30 -30
- package/src/__tests__/kb-layout-config.test.ts +21 -0
- package/src/__tests__/open-change-gate.ts +1 -1
- package/src/__tests__/tool-handler.ts +15 -0
- package/src/__tests__/tool-wiring.ts +10 -4
- package/src/__tests__/workspace-service.ts +1 -1
- package/src/core/__tests__/catalog-cache-invalidation.test.ts +3 -3
- package/src/core/__tests__/compose-embed.test.ts +1 -1
- package/src/core/__tests__/damaged-document.tools.test.ts +3 -3
- package/src/core/__tests__/erasure-slices-wired-once.test.ts +46 -0
- package/src/core/__tests__/gated-boot.test.ts +2 -2
- package/src/core/__tests__/lifecycle.test.ts +9 -9
- package/src/core/catalog-cache-invalidation.ts +2 -2
- package/src/core/compose-embed.ts +3 -3
- package/src/core/core-ports.ts +19 -4
- package/src/core/create-core-server.ts +39 -25
- package/src/core/create-core-services.ts +79 -63
- package/src/core/lifecycle.ts +9 -9
- package/src/core-config.ts +3 -3
- package/src/index.ts +5 -5
- package/src/modules/access/__tests__/access-control.admin-root-floor.test.ts +4 -4
- package/src/modules/access/__tests__/access-own-read-grant.test.ts +14 -14
- package/src/modules/access/__tests__/access-requests.routes.test.ts +20 -20
- package/src/modules/access/__tests__/access.routes.admins.test.ts +4 -4
- package/src/modules/access/__tests__/access.routes.batch.test.ts +4 -4
- package/src/modules/access/__tests__/access.routes.folder-governs.test.ts +6 -6
- package/src/modules/access/__tests__/access.routes.group-grant.test.ts +6 -6
- package/src/modules/access/__tests__/access.routes.overrides.test.ts +5 -5
- package/src/modules/access/__tests__/access.routes.proposal-branch.test.ts +6 -6
- package/src/modules/access/__tests__/access.routes.prospective.test.ts +3 -3
- package/src/modules/access/__tests__/access.routes.revoke.test.ts +6 -6
- package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +6 -6
- package/src/modules/access/__tests__/admin-locked-commit.test.ts +6 -6
- package/src/modules/access/__tests__/admin-route-helpers.test.ts +5 -5
- package/src/modules/access/__tests__/groups-admin.service.test.ts +27 -27
- package/src/modules/access/__tests__/roles-admin.security.test.ts +14 -13
- package/src/modules/access/__tests__/roles-admin.service.test.ts +27 -27
- package/src/modules/access/__tests__/roles-capabilities.test.ts +19 -19
- package/src/modules/access/__tests__/roles.routes.test.ts +6 -6
- package/src/modules/access/__tests__/synced-groups-committer.test.ts +13 -13
- package/src/modules/access/__tests__/user-access-removal.service.test.ts +29 -29
- package/src/modules/access/access-control.service.ts +1 -1
- package/src/modules/access/access-declarations.ts +2 -2
- package/src/modules/access/access-mutation.service.ts +2 -2
- package/src/modules/access/access-requests.routes.ts +7 -7
- package/src/modules/access/access-requests.service.ts +13 -13
- package/src/modules/access/access.routes.ts +11 -11
- package/src/modules/access/admin-locked-commit.ts +11 -11
- package/src/modules/access/admin-route-helpers.ts +5 -5
- package/src/modules/access/change-read-gate.ts +1 -1
- package/src/modules/access/groups-admin.service.ts +7 -7
- package/src/modules/access/reference-scan.ts +1 -1
- package/src/modules/access/roles-admin.service.ts +9 -9
- package/src/modules/access/synced-groups-committer.ts +11 -11
- package/src/modules/access/user-access-removal.service.ts +7 -7
- package/src/modules/access-model/__tests__/access-grammar.test.ts +2 -2
- package/src/modules/access-model/access-errors.ts +4 -4
- package/src/modules/access-model/access-grammar.ts +4 -4
- package/src/modules/access-model/change-gate.ts +1 -1
- package/src/modules/access-model/roles-yaml-guard.ts +4 -4
- package/src/modules/agent-guide/__tests__/agent-guide.test.ts +19 -4
- package/src/modules/agent-guide/__tests__/agent-guide.tools.test.ts +1 -1
- package/src/modules/agent-guide/__tests__/guide-matches-code.test.ts +2 -2
- package/src/modules/agent-guide/agent-guide.ts +48 -22
- package/src/modules/agent-guide/guide-budget.ts +6 -2
- package/src/modules/agent-instructions/__tests__/agent-instructions.route.test.ts +4 -5
- package/src/modules/agent-instructions/__tests__/compose.test.ts +1 -1
- package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +113 -7
- package/src/modules/agent-instructions/agent-instructions.routes.ts +12 -5
- package/src/modules/agent-instructions/compose.ts +24 -9
- package/src/modules/agent-instructions/shared-file-rules.ts +53 -11
- package/src/modules/agent-scope/__tests__/agent-surfaces.connect-as.test.ts +1 -1
- package/src/modules/audit/__tests__/agent-rest-audit.middleware.test.ts +113 -113
- package/src/modules/audit/__tests__/event-classifier.test.ts +121 -121
- package/src/modules/audit/event-classifier.ts +155 -155
- package/src/modules/auth/__tests__/account-deactivation.test.ts +1 -1
- package/src/modules/auth/__tests__/account-erasure.approval-gate.test.ts +4 -4
- package/src/modules/auth/__tests__/account-erasure.participants.test.ts +56 -0
- package/src/modules/auth/__tests__/account-switch-lock.pg.test.ts +2 -2
- package/src/modules/auth/__tests__/account-switch-lock.test.ts +2 -2
- package/src/modules/auth/__tests__/account.routes.test.ts +73 -11
- package/src/modules/auth/__tests__/auth.service.test.ts +1 -1
- package/src/modules/auth/account-erasure.service.ts +27 -9
- package/src/modules/auth/account-hooks.ts +34 -0
- package/src/modules/auth/account-switch-lock.ts +2 -2
- package/src/modules/auth/account.routes.ts +23 -5
- package/src/modules/auth/auth.service.ts +4 -4
- package/src/modules/auth/index.ts +1 -0
- package/src/modules/database/__tests__/advisory-lock.test.ts +169 -169
- package/src/modules/database/__tests__/migrations-unqualified.test.ts +32 -32
- package/src/modules/database/core-schema.ts +2 -2
- package/src/modules/diff/__tests__/diff.routes.read-gate.test.ts +2 -2
- package/src/modules/diff/__tests__/diff.routes.rejectPathsLocked.test.ts +12 -12
- package/src/modules/diff/diff.routes.ts +8 -8
- package/src/modules/embed/__tests__/embed.service.lock.test.ts +7 -7
- package/src/modules/embed/__tests__/embed.service.test.ts +42 -42
- package/src/modules/embed/__tests__/embed.tools.test.ts +1 -1
- package/src/modules/embed/embed.routes.ts +1 -1
- package/src/modules/embed/embed.service.ts +17 -17
- package/src/modules/kb-fs/__tests__/branch-name.test.ts +2 -2
- package/src/modules/kb-fs/__tests__/locking-filesystem.test.ts +260 -260
- package/src/modules/kb-fs/__tests__/move-with-edits.test.ts +34 -34
- package/src/modules/kb-fs/__tests__/repo-path.test.ts +8 -8
- package/src/modules/kb-fs/branch-name.ts +8 -8
- package/src/modules/kb-fs/file-change-notifier.ts +2 -2
- package/src/modules/kb-fs/locking-filesystem.ts +30 -30
- package/src/modules/kb-fs/repo-path.ts +5 -5
- package/src/modules/kb-fs/tmp-ref.ts +3 -3
- package/src/modules/kb-sync/__tests__/kb-sync.service.test.ts +36 -36
- package/src/modules/kb-sync/index.ts +1 -1
- package/src/modules/kb-sync/kb-sync.interface.ts +3 -3
- package/src/modules/kb-sync/kb-sync.service.ts +9 -9
- package/src/modules/marketplace/__tests__/github-facade.test.ts +1 -1
- package/src/modules/marketplace/__tests__/marketplace-git.test.ts +1 -1
- package/src/modules/mcp/__tests__/mcp-proxy-helpers.test.ts +4 -2
- package/src/modules/mcp/__tests__/mcp.e2e.test.ts +69 -8
- package/src/modules/mcp/__tests__/mcp.service.test.ts +91 -13
- package/src/modules/mcp/__tests__/read-only-hint.pg.test.ts +194 -0
- package/src/modules/mcp/mcp.service.ts +89 -28
- package/src/modules/onboarding/__tests__/starter-pack.service.test.ts +55 -55
- package/src/modules/onboarding/onboarding.contract.ts +1 -1
- package/src/modules/onboarding/onboarding.routes.ts +2 -2
- package/src/modules/onboarding/starter-pack.service.ts +6 -6
- package/src/modules/plugins/__tests__/bundle-dialect.e2e.test.ts +1 -1
- package/src/modules/plugins/__tests__/compile-marketplace.test.ts +1 -1
- package/src/modules/plugins/__tests__/join-request-jobs.service.test.ts +43 -43
- package/src/modules/plugins/__tests__/join-requests.service.test.ts +19 -19
- package/src/modules/plugins/__tests__/join-requests.settlement.test.ts +26 -26
- package/src/modules/plugins/__tests__/plugins.routes.test.ts +25 -25
- package/src/modules/plugins/join-request-jobs.service.ts +10 -10
- package/src/modules/plugins/join-requests.service.ts +4 -4
- package/src/modules/plugins/plugin-rename.service.ts +1 -1
- package/src/modules/plugins/plugins.routes.ts +9 -9
- package/src/modules/secrets-vault/__tests__/db-secrets-vault.managed.test.ts +773 -0
- package/src/modules/secrets-vault/__tests__/db-secrets-vault.oauth.test.ts +28 -1
- package/src/modules/secrets-vault/__tests__/managed-sign-in.route.test.ts +351 -0
- package/src/modules/secrets-vault/db-secrets-vault.service.ts +562 -95
- package/src/modules/secrets-vault/index.ts +7 -0
- package/src/modules/secrets-vault/managed-sign-in-erasure.ts +41 -0
- package/src/modules/secrets-vault/secrets-variable-loader.ts +134 -134
- package/src/modules/secrets-vault/secrets-vault.contract.ts +152 -0
- package/src/modules/secrets-vault/secrets-vault.routes.ts +157 -10
- package/src/modules/settings/__tests__/repository-source.test.ts +1 -1
- package/src/modules/settings/__tests__/setup.routes.layout-phase.test.ts +1 -1
- package/src/modules/settings/__tests__/setup.routes.managed-phase.test.ts +1 -1
- package/src/modules/settings/connection-check.ts +1 -1
- package/src/modules/settings/deployment-settings.service.ts +1 -1
- package/src/modules/settings/git-root-folders.ts +1 -1
- package/src/modules/settings/setup.routes.ts +1 -1
- package/src/modules/skills/__tests__/allowed-tools-warn.tools.test.ts +3 -3
- package/src/modules/skills/__tests__/branch-skills.tools.test.ts +1 -1
- package/src/modules/skills/__tests__/pending-skills.service.test.ts +8 -8
- package/src/modules/skills/__tests__/skill-access-requests.routes.test.ts +18 -18
- package/src/modules/skills/__tests__/skills.service.test.ts +3 -3
- package/src/modules/skills/pending-skills.service.ts +3 -3
- package/src/modules/skills/skill-access-requests.routes.ts +7 -7
- package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +4 -4
- package/src/modules/tool-helpers/__tests__/branch-declaration.test.ts +3 -3
- package/src/modules/tool-helpers/__tests__/can-write.tools.test.ts +3 -3
- package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +4 -4
- package/src/modules/tool-helpers/__tests__/tools-surface.test.ts +3 -3
- package/src/modules/tool-helpers/__tests__/validate-token.test.ts +1 -1
- package/src/modules/tool-helpers/tool-context.ts +6 -6
- package/src/modules/tool-helpers/tool-handler.ts +2 -2
- package/src/modules/tool-helpers/tool.contract.ts +4 -4
- package/src/modules/tool-manuals/__tests__/pending-tools.service.test.ts +9 -9
- package/src/modules/tool-manuals/__tests__/tool-manuals.managed-sign-in.test.ts +89 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.restart.test.ts +1 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +36 -1
- package/src/modules/tool-manuals/mcp-server-edit.service.ts +1 -1
- package/src/modules/tool-manuals/pending-tools.service.ts +3 -3
- package/src/modules/tool-manuals/tool-delete.service.ts +1 -1
- package/src/modules/tool-manuals/tool-manuals.contract.ts +41 -3
- package/src/modules/tool-manuals/tool-manuals.service.ts +53 -5
- package/src/modules/tool-manuals/tool-manuals.tools.ts +41 -15
- package/src/modules/tool-registry/__tests__/own-tool-schemas.test.ts +4 -4
- package/src/modules/tool-registry/__tests__/read-only-hints.test.ts +3 -3
- package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +6 -6
- package/src/modules/{workflow → version-control}/__tests__/apply-failure.test.ts +54 -54
- package/src/modules/{workflow → version-control}/__tests__/event-bus.test.ts +27 -27
- package/src/modules/{workflow → version-control}/__tests__/events-delivery.test.ts +37 -37
- package/src/modules/{workflow → version-control}/__tests__/file-lock.service.deletion-gate.test.ts +2 -2
- package/src/modules/{workflow → version-control}/__tests__/file-lock.service.path-identity.test.ts +8 -8
- package/src/modules/{workflow → version-control}/__tests__/merge-announces-tree.test.ts +11 -11
- package/src/modules/{workflow → version-control}/__tests__/pending-commits.worker.concurrency.test.ts +9 -9
- package/src/modules/{workflow → version-control}/__tests__/pending-commits.worker.test.ts +25 -25
- package/src/modules/{workflow → version-control}/__tests__/preserve-roles-yaml.test.ts +42 -42
- package/src/modules/version-control/__tests__/public-surface.test.ts +114 -0
- package/src/modules/{workflow/__tests__/workflow.routes.folder-proposals.test.ts → version-control/__tests__/version-control.routes.folder-proposals.test.ts} +18 -18
- package/src/modules/{workflow/__tests__/workflow.routes.fork-point-file.test.ts → version-control/__tests__/version-control.routes.fork-point-file.test.ts} +19 -19
- package/src/modules/{workflow/__tests__/workflow.routes.history-read-gate.test.ts → version-control/__tests__/version-control.routes.history-read-gate.test.ts} +13 -13
- package/src/modules/{workflow/__tests__/workflow.routes.lock-path.test.ts → version-control/__tests__/version-control.routes.lock-path.test.ts} +18 -18
- package/src/modules/{workflow/__tests__/workflow.routes.open-change-request.test.ts → version-control/__tests__/version-control.routes.open-change-request.test.ts} +7 -7
- package/src/modules/{workflow/__tests__/workflow.routes.push-refused.test.ts → version-control/__tests__/version-control.routes.push-refused.test.ts} +14 -14
- package/src/modules/{workflow/__tests__/workflow.service.branch-in-use.test.ts → version-control/__tests__/version-control.service.branch-in-use.test.ts} +6 -6
- package/src/modules/{workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts → version-control/__tests__/version-control.service.commitFileWhileLocked.test.ts} +14 -14
- package/src/modules/{workflow/__tests__/workflow.service.delete-branch.test.ts → version-control/__tests__/version-control.service.delete-branch.test.ts} +14 -14
- package/src/modules/{workflow/__tests__/workflow.service.deleted-branch-sweep.test.ts → version-control/__tests__/version-control.service.deleted-branch-sweep.test.ts} +4 -4
- package/src/modules/{workflow/__tests__/workflow.service.facade.test.ts → version-control/__tests__/version-control.service.facade.test.ts} +97 -99
- package/src/modules/{workflow/__tests__/workflow.service.folder-proposals.test.ts → version-control/__tests__/version-control.service.folder-proposals.test.ts} +7 -7
- package/src/modules/{workflow/__tests__/workflow.service.platform-restore.test.ts → version-control/__tests__/version-control.service.platform-restore.test.ts} +6 -6
- package/src/modules/{workflow/__tests__/workflow.service.read-gate.test.ts → version-control/__tests__/version-control.service.read-gate.test.ts} +9 -9
- package/src/modules/{workflow/__tests__/workflow.service.releaseLock.test.ts → version-control/__tests__/version-control.service.releaseLock.test.ts} +42 -42
- package/src/modules/{workflow/__tests__/workflow.service.repository-replaced.test.ts → version-control/__tests__/version-control.service.repository-replaced.test.ts} +4 -4
- package/src/modules/{workflow/__tests__/workflow.service.sync.test.ts → version-control/__tests__/version-control.service.sync.test.ts} +17 -17
- package/src/modules/{workflow/__tests__/workflow.service.update-change-request.pg.test.ts → version-control/__tests__/version-control.service.update-change-request.pg.test.ts} +6 -6
- package/src/modules/{workflow/__tests__/workflow.service.update-change-request.test.ts → version-control/__tests__/version-control.service.update-change-request.test.ts} +11 -11
- package/src/modules/{workflow/__tests__/workflow.service.update-from-target.test.ts → version-control/__tests__/version-control.service.update-from-target.test.ts} +22 -22
- package/src/modules/{workflow → version-control}/agent-tools/__tests__/change-request-read.tools.test.ts +3 -3
- package/src/modules/{workflow → version-control}/agent-tools/__tests__/update-change-request.parity.test.ts +16 -16
- package/src/modules/{workflow/agent-tools/__tests__/workflow.tools.test.ts → version-control/agent-tools/__tests__/version-control.tools.test.ts} +9 -9
- package/src/modules/{workflow → version-control}/agent-tools/change-request-read.tools.ts +2 -2
- package/src/modules/{workflow/agent-tools/workflow.tools.ts → version-control/agent-tools/version-control.tools.ts} +30 -30
- package/src/modules/{workflow → version-control}/change-request-hooks.ts +1 -1
- package/src/modules/{workflow/review-workflow → version-control/change-request-review}/__tests__/approval-states.test.ts +5 -5
- package/src/modules/{workflow/review-workflow → version-control/change-request-review}/__tests__/cancel-pr.test.ts +8 -8
- package/src/modules/{workflow/review-workflow → version-control/change-request-review}/__tests__/carry-approvals-forward.test.ts +6 -6
- package/src/modules/{workflow/review-workflow → version-control/change-request-review}/__tests__/erase-approver.test.ts +5 -5
- package/src/modules/{workflow/review-workflow → version-control/change-request-review}/__tests__/merge-gate.test.ts +3 -3
- package/src/modules/{workflow/review-workflow → version-control/change-request-review}/__tests__/merge-records-own-commit.test.ts +3 -3
- package/src/modules/{workflow/review-workflow/review-workflow.interface.ts → version-control/change-request-review/change-request-review.interface.ts} +1 -1
- package/src/modules/{workflow/review-workflow/review-workflow.service.ts → version-control/change-request-review/change-request-review.service.ts} +28 -28
- package/src/modules/{workflow → version-control}/event-bus.ts +14 -14
- package/src/modules/{workflow → version-control}/events-delivery.ts +11 -11
- package/src/modules/{workflow → version-control}/events.routes.ts +5 -5
- package/src/modules/{workflow → version-control}/file-lock.service.ts +6 -6
- package/src/modules/{workflow → version-control}/git/__tests__/git-test-helpers.ts +3 -3
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.accessGating.test.ts +5 -5
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.appliedChange.test.ts +4 -4
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.changedFilesForPr.test.ts +16 -16
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.changedPathsMemo.test.ts +2 -2
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.commitChanges.test.ts +3 -3
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.commitFile.strayPath.test.ts +10 -10
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.commitFile.test.ts +3 -3
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.createBranch.test.ts +3 -3
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.deleteBranch.test.ts +7 -7
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.diffFileAtCommit.test.ts +9 -9
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.diffFileBetweenBranches.test.ts +23 -23
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.fileBytesAtCommit.test.ts +7 -7
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.fileContentsAtCommit.test.ts +3 -3
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.forkPoint.test.ts +2 -2
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.history-guards.test.ts +2 -2
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.list-branches.test.ts +12 -12
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.listTrackedFiles.test.ts +2 -2
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.logForFile.test.ts +6 -6
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.mergeChangeRequest.test.ts +20 -20
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.mergeIntoBranch.test.ts +16 -16
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.pendingChanges.test.ts +2 -2
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.postMergePull.test.ts +5 -5
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.prFetchFailure.test.ts +2 -2
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.pull.test.ts +12 -12
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.readFileAtRef.test.ts +3 -3
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.revertPathsAndPush.test.ts +2 -2
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.status.test.ts +4 -4
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.syncFromRemote.test.ts +8 -8
- package/src/modules/{workflow → version-control}/git/__tests__/git.service.worktrees.test.ts +4 -4
- package/src/modules/{workflow → version-control}/git/__tests__/pull-request.service.list-fetch.test.ts +2 -2
- package/src/modules/{workflow → version-control}/git/__tests__/pull-request.service.test.ts +6 -6
- package/src/modules/{workflow → version-control}/git/git.service.ts +57 -57
- package/src/modules/{workflow → version-control}/git/node-git-runner.ts +1 -1
- package/src/modules/{workflow → version-control}/git/pull-request.service.ts +12 -12
- package/src/modules/{workflow → version-control}/index.ts +6 -5
- package/src/modules/{workflow → version-control}/pending-commits.service.ts +2 -2
- package/src/modules/{workflow → version-control}/pending-commits.worker.ts +8 -8
- package/src/modules/{workflow → version-control}/read-on-branch.ts +2 -2
- package/src/modules/{workflow/workflow-hooks.ts → version-control/version-control-hooks.ts} +3 -3
- package/src/modules/{workflow/workflow.routes.ts → version-control/version-control.routes.ts} +64 -63
- package/src/modules/{workflow/workflow.service.ts → version-control/version-control.service.ts} +92 -97
- package/src/modules/workspace/__tests__/agent-access.gate.test.ts +8 -8
- package/src/modules/workspace/__tests__/agent-downloads.test.ts +13 -16
- package/src/modules/workspace/__tests__/agent-uploads.test.ts +11 -12
- package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +11 -16
- package/src/modules/workspace/__tests__/file-stat-access.test.ts +3 -3
- package/src/modules/workspace/__tests__/git-internals.security.test.ts +27 -27
- package/src/modules/workspace/__tests__/kb-repository.test.ts +1 -1
- package/src/modules/workspace/__tests__/rest-tool-arguments.test.ts +3 -3
- package/src/modules/workspace/__tests__/start-session.default-branch.test.ts +152 -0
- package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +6 -6
- package/src/modules/workspace/__tests__/workspace-tmp.tools.test.ts +13 -14
- package/src/modules/workspace/__tests__/workspace.routes.at-ref.test.ts +6 -6
- package/src/modules/workspace/__tests__/workspace.routes.branch-errors.test.ts +4 -4
- package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +6 -6
- package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +8 -8
- package/src/modules/workspace/__tests__/workspace.routes.download-implies-read.test.ts +4 -4
- package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +6 -6
- package/src/modules/workspace/__tests__/workspace.routes.file-writes.test.ts +6 -6
- package/src/modules/workspace/__tests__/workspace.routes.folder-zip-access.test.ts +4 -4
- package/src/modules/workspace/__tests__/workspace.routes.folders.test.ts +6 -6
- package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +7 -7
- package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +13 -13
- package/src/modules/workspace/__tests__/workspace.service.any-workspace-credentials.test.ts +1 -1
- package/src/modules/workspace/__tests__/workspace.service.replaced-repository.test.ts +1 -1
- package/src/modules/workspace/__tests__/workspace.service.worktrees.test.ts +1 -1
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +5 -5
- package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +5 -5
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +27 -27
- package/src/modules/workspace/agent-access.gate.ts +5 -5
- package/src/modules/workspace/git-internals.middleware.ts +2 -2
- package/src/modules/workspace/kb-repository.ts +1 -1
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.degraded.test.ts +1 -1
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +1 -1
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.worktrees.test.ts +1 -1
- package/src/modules/workspace/startup/kb-git.ts +1 -1
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +94 -70
- package/src/modules/workspace/startup/steps/seed-tree.ts +4 -5
- package/src/modules/workspace/startup/steps/template-files.step.ts +4 -5
- package/src/modules/workspace/startup/steps/template-source.ts +21 -6
- package/src/modules/workspace/workspace-tmp.ts +4 -4
- package/src/modules/workspace/workspace.routes.ts +26 -26
- package/src/modules/workspace/workspace.service.ts +11 -11
- package/src/modules/workspace/workspace.tools.ts +17 -10
- package/src/shared/__tests__/canonical-file-identity.test.ts +5 -5
- package/src/shared/__tests__/http-errors.test.ts +4 -4
- package/src/shared/canonical-file-identity.ts +5 -5
- package/src/shared/domain-errors.ts +44 -44
- package/src/shared/git.contract.ts +1 -1
- package/src/shared/http-errors.ts +3 -3
- package/src/shared/kb-context.ts +130 -130
- package/src/shared/pending-proposals.ts +4 -4
- package/src/tenancy/__tests__/tenant-host.test.ts +372 -372
- package/src/tenancy/__tests__/tenant-runtime.test.ts +221 -221
- package/src/tenancy/__tests__/tenant-secrets.test.ts +35 -35
- package/src/tenancy/index.ts +35 -35
- package/src/tenancy/static-tenant-source.ts +1 -1
- package/src/tenancy/tenant-host.ts +261 -261
- package/src/tenancy/tenant-runtime.ts +208 -208
- package/src/tenancy/tenant-source.contract.ts +59 -59
- package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts.map +0 -1
- package/dist/modules/workflow/agent-tools/change-request-read-shape.js.map +0 -1
- package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts.map +0 -1
- package/dist/modules/workflow/agent-tools/change-request-read.tools.js.map +0 -1
- package/dist/modules/workflow/agent-tools/change-request-summary.d.ts.map +0 -1
- package/dist/modules/workflow/agent-tools/change-request-summary.js.map +0 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +0 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +0 -1
- package/dist/modules/workflow/change-request-hooks.d.ts.map +0 -1
- package/dist/modules/workflow/change-request-hooks.js.map +0 -1
- package/dist/modules/workflow/event-bus.d.ts.map +0 -1
- package/dist/modules/workflow/event-bus.js.map +0 -1
- package/dist/modules/workflow/events-delivery.d.ts.map +0 -1
- package/dist/modules/workflow/events-delivery.js.map +0 -1
- package/dist/modules/workflow/events.routes.d.ts.map +0 -1
- package/dist/modules/workflow/events.routes.js.map +0 -1
- package/dist/modules/workflow/file-lock.service.d.ts.map +0 -1
- package/dist/modules/workflow/file-lock.service.js.map +0 -1
- package/dist/modules/workflow/git/change-request-link.d.ts.map +0 -1
- package/dist/modules/workflow/git/change-request-link.js.map +0 -1
- package/dist/modules/workflow/git/git-version.d.ts.map +0 -1
- package/dist/modules/workflow/git/git-version.js.map +0 -1
- package/dist/modules/workflow/git/git.service.d.ts.map +0 -1
- package/dist/modules/workflow/git/git.service.js.map +0 -1
- package/dist/modules/workflow/git/merge-commit.d.ts.map +0 -1
- package/dist/modules/workflow/git/merge-commit.js.map +0 -1
- package/dist/modules/workflow/git/node-git-runner.d.ts.map +0 -1
- package/dist/modules/workflow/git/node-git-runner.js.map +0 -1
- package/dist/modules/workflow/git/pull-request.service.d.ts.map +0 -1
- package/dist/modules/workflow/git/pull-request.service.js.map +0 -1
- package/dist/modules/workflow/index.d.ts.map +0 -1
- package/dist/modules/workflow/index.js.map +0 -1
- package/dist/modules/workflow/pending-commits.service.d.ts.map +0 -1
- package/dist/modules/workflow/pending-commits.service.js.map +0 -1
- package/dist/modules/workflow/pending-commits.worker.d.ts.map +0 -1
- package/dist/modules/workflow/pending-commits.worker.js.map +0 -1
- package/dist/modules/workflow/read-on-branch.d.ts.map +0 -1
- package/dist/modules/workflow/read-on-branch.js.map +0 -1
- package/dist/modules/workflow/recovery-bot.d.ts.map +0 -1
- package/dist/modules/workflow/recovery-bot.js.map +0 -1
- package/dist/modules/workflow/review-workflow/approval-lock.d.ts.map +0 -1
- package/dist/modules/workflow/review-workflow/approval-lock.js.map +0 -1
- package/dist/modules/workflow/review-workflow/review-workflow.interface.d.ts.map +0 -1
- package/dist/modules/workflow/review-workflow/review-workflow.interface.js +0 -2
- package/dist/modules/workflow/review-workflow/review-workflow.interface.js.map +0 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +0 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +0 -1
- package/dist/modules/workflow/sanitize-error.d.ts.map +0 -1
- package/dist/modules/workflow/sanitize-error.js.map +0 -1
- package/dist/modules/workflow/workflow-hooks.d.ts.map +0 -1
- package/dist/modules/workflow/workflow-hooks.js.map +0 -1
- package/dist/modules/workflow/workflow.routes.d.ts.map +0 -1
- package/dist/modules/workflow/workflow.routes.js.map +0 -1
- package/dist/modules/workflow/workflow.service.d.ts.map +0 -1
- package/dist/modules/workflow/workflow.service.js.map +0 -1
- package/src/modules/mcp/__tests__/read-only-hint.e2e.test.ts +0 -213
- /package/dist/modules/{workflow → version-control}/agent-tools/change-request-read-shape.d.ts +0 -0
- /package/dist/modules/{workflow → version-control}/agent-tools/change-request-read-shape.js +0 -0
- /package/dist/modules/{workflow → version-control}/agent-tools/change-request-read.tools.d.ts +0 -0
- /package/dist/modules/{workflow → version-control}/agent-tools/change-request-summary.d.ts +0 -0
- /package/dist/modules/{workflow → version-control}/agent-tools/change-request-summary.js +0 -0
- /package/dist/modules/{workflow → version-control}/change-request-hooks.js +0 -0
- /package/dist/modules/{workflow/review-workflow → version-control/change-request-review}/approval-lock.d.ts +0 -0
- /package/dist/modules/{workflow/review-workflow → version-control/change-request-review}/approval-lock.js +0 -0
- /package/dist/modules/{workflow → version-control}/events-delivery.js +0 -0
- /package/dist/modules/{workflow → version-control}/events.routes.js +0 -0
- /package/dist/modules/{workflow → version-control}/git/change-request-link.d.ts +0 -0
- /package/dist/modules/{workflow → version-control}/git/change-request-link.js +0 -0
- /package/dist/modules/{workflow → version-control}/git/git-version.d.ts +0 -0
- /package/dist/modules/{workflow → version-control}/git/git-version.js +0 -0
- /package/dist/modules/{workflow → version-control}/git/merge-commit.d.ts +0 -0
- /package/dist/modules/{workflow → version-control}/git/merge-commit.js +0 -0
- /package/dist/modules/{workflow → version-control}/git/node-git-runner.d.ts +0 -0
- /package/dist/modules/{workflow → version-control}/recovery-bot.d.ts +0 -0
- /package/dist/modules/{workflow → version-control}/recovery-bot.js +0 -0
- /package/dist/modules/{workflow → version-control}/sanitize-error.d.ts +0 -0
- /package/dist/modules/{workflow → version-control}/sanitize-error.js +0 -0
- /package/src/modules/{workflow → version-control}/__tests__/change-request-hooks.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/__tests__/fake-file-lock-db.ts +0 -0
- /package/src/modules/{workflow → version-control}/__tests__/pending-commits.canonical.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/__tests__/pending-commits.enqueue-if-absent.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/__tests__/pending-commits.repository-replaced.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/__tests__/sanitize-error.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/agent-tools/__tests__/change-request-read-shape.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/agent-tools/change-request-read-shape.ts +0 -0
- /package/src/modules/{workflow → version-control}/agent-tools/change-request-summary.ts +0 -0
- /package/src/modules/{workflow/review-workflow → version-control/change-request-review}/approval-lock.ts +0 -0
- /package/src/modules/{workflow → version-control}/git/__tests__/branchAuthor.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/git/__tests__/change-request-link.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/git/__tests__/git-version.failure.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/git/__tests__/git-version.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/git/__tests__/node-git-runner.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/git/__tests__/pull-request.service.getPrDetail.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/git/__tests__/pull-request.service.placeholder.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/git/__tests__/pull-request.service.viewer-can-cancel.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/git/__tests__/pull-request.service.viewer-can-delete.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/git/__tests__/pull-request.service.viewer-can-update.test.ts +0 -0
- /package/src/modules/{workflow → version-control}/git/change-request-link.ts +0 -0
- /package/src/modules/{workflow → version-control}/git/git-version.ts +0 -0
- /package/src/modules/{workflow → version-control}/git/merge-commit.ts +0 -0
- /package/src/modules/{workflow → version-control}/recovery-bot.ts +0 -0
- /package/src/modules/{workflow → version-control}/sanitize-error.ts +0 -0
|
@@ -1,261 +1,261 @@
|
|
|
1
|
-
import express, { type Express, type Request } from 'express';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { isIP } from 'node:net';
|
|
4
|
-
import type { ProcessConfig } from '../core-config.js';
|
|
5
|
-
import { GIT_SHA } from '../version.js';
|
|
6
|
-
import { logger } from '../shared/logging.js';
|
|
7
|
-
import { TenantRuntime, type TenantRuntimeDeps } from './tenant-runtime.js';
|
|
8
|
-
import { TENANT_SLUG_PATTERN, normalizeHost, type TenantDescriptor, type TenantSource } from './tenant-source.contract.js';
|
|
9
|
-
|
|
10
|
-
const log = logger('tenancy');
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* The path prefix under which a process reaches ONE of its own tenants over
|
|
14
|
-
* loopback: `http://127.0.0.1:<port>/_tenant/<slug>/api/...`. The MCP proxy
|
|
15
|
-
* and the UTCP manuals it seeds dial the tenant's own REST surface this way,
|
|
16
|
-
* because a loopback request carries no tenant host name and a header cannot
|
|
17
|
-
* ride a UTCP call (the proxy is a passthrough; it reshapes nothing).
|
|
18
|
-
*
|
|
19
|
-
* The host honours the prefix only for a request that came from this
|
|
20
|
-
* machine AND was forwarded by nobody: the socket peer is loopback and there
|
|
21
|
-
* is no `X-Forwarded-For`. A reverse proxy on the same host (nginx, a
|
|
22
|
-
* Coolify proxy) delivers every public request from a loopback socket, and
|
|
23
|
-
* every such proxy adds that header; the process's own dial never does.
|
|
24
|
-
* What the prefix could grant anyone who got past this is only what the
|
|
25
|
-
* tenant's host name grants already — sessions, keys and tokens are per
|
|
26
|
-
* tenant — but the addressing rule is stated so it can be relied on.
|
|
27
|
-
*/
|
|
28
|
-
export const LOOPBACK_TENANT_PREFIX = '/_tenant';
|
|
29
|
-
|
|
30
|
-
/** The base URL a tenant's graph dials itself at — see {@link LOOPBACK_TENANT_PREFIX}. */
|
|
31
|
-
export function loopbackTenantBaseUrl(port: number, slug: string): string {
|
|
32
|
-
return `http://127.0.0.1:${port}${LOOPBACK_TENANT_PREFIX}/${slug}`;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/** Whether `address` is this machine talking to itself. */
|
|
36
|
-
export function isLoopbackAddress(address: string | undefined): boolean {
|
|
37
|
-
if (!address) return false;
|
|
38
|
-
const bare = address.startsWith('::ffff:') ? address.slice('::ffff:'.length) : address;
|
|
39
|
-
if (bare === '::1') return true;
|
|
40
|
-
return isIP(bare) === 4 && bare.startsWith('127.');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** How a request names its tenant: by the loopback prefix, or by its host. */
|
|
44
|
-
export type TenantSelector = { kind: 'slug'; slug: string; rest: string } | { kind: 'host'; host: string };
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Which tenant a request is for. The loopback prefix wins, but only from a
|
|
48
|
-
* loopback peer that no proxy forwarded (no `X-Forwarded-For`); everything
|
|
49
|
-
* else is decided by the host name (the `X-Forwarded-Host` a trusted proxy
|
|
50
|
-
* set, else `Host`), lowercase and without its port.
|
|
51
|
-
*/
|
|
52
|
-
export function selectTenant(req: {
|
|
53
|
-
hostname: string;
|
|
54
|
-
url: string;
|
|
55
|
-
peer: string | undefined;
|
|
56
|
-
forwardedFor?: string | string[] | undefined;
|
|
57
|
-
}): TenantSelector {
|
|
58
|
-
const forwarded = Array.isArray(req.forwardedFor) ? req.forwardedFor.length > 0 : Boolean(req.forwardedFor);
|
|
59
|
-
if (isLoopbackAddress(req.peer) && !forwarded && req.url.startsWith(`${LOOPBACK_TENANT_PREFIX}/`)) {
|
|
60
|
-
const afterPrefix = req.url.slice(LOOPBACK_TENANT_PREFIX.length + 1);
|
|
61
|
-
const end = afterPrefix.search(/[/?#]/);
|
|
62
|
-
const slug = end === -1 ? afterPrefix : afterPrefix.slice(0, end);
|
|
63
|
-
if (TENANT_SLUG_PATTERN.test(slug)) {
|
|
64
|
-
const rest = end === -1 ? '/' : afterPrefix.slice(end).replace(/^(?=[?#])/, '/');
|
|
65
|
-
return { kind: 'slug', slug, rest };
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return { kind: 'host', host: normalizeHost(req.hostname || '') };
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export interface TenantHostOptions {
|
|
72
|
-
source: TenantSource;
|
|
73
|
-
process: ProcessConfig;
|
|
74
|
-
/** The built SPA, served once for every resolved tenant. */
|
|
75
|
-
staticDir?: string;
|
|
76
|
-
/** Minutes without a request after which a tenant's graph is stopped. Default 30; 0 never evicts. */
|
|
77
|
-
idleMinutes?: number;
|
|
78
|
-
/** How long a request waits for an activation in flight before answering 503. Default 60s. */
|
|
79
|
-
activationWaitMs?: number;
|
|
80
|
-
/** Seams for the runtimes the host builds — a suite's fake graphs. */
|
|
81
|
-
runtime?: TenantRuntimeDeps;
|
|
82
|
-
/** How often idle tenants are looked for. Default: once a minute. */
|
|
83
|
-
sweepIntervalMs?: number;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export interface TenantHost {
|
|
87
|
-
/** The app the process listens on. */
|
|
88
|
-
app: Express;
|
|
89
|
-
/** The runtimes built so far, by slug. */
|
|
90
|
-
runtimes(): ReadonlyMap<string, TenantRuntime>;
|
|
91
|
-
/** Stop every active tenant; the host keeps serving and reactivates on demand. */
|
|
92
|
-
evictAll(): Promise<void>;
|
|
93
|
-
/** Stop the idle sweep and every tenant: the process's shutdown. */
|
|
94
|
-
stop(): Promise<void>;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const DEFAULT_ACTIVATION_WAIT_MS = 60_000;
|
|
98
|
-
const DEFAULT_IDLE_MINUTES = 30;
|
|
99
|
-
const DEFAULT_SWEEP_INTERVAL_MS = 60_000;
|
|
100
|
-
|
|
101
|
-
/** `promise`, or `null` once `ms` have passed. */
|
|
102
|
-
function within<T>(promise: Promise<T>, ms: number): Promise<T | null> {
|
|
103
|
-
let timer: NodeJS.Timeout | undefined;
|
|
104
|
-
const late = new Promise<null>((resolve) => {
|
|
105
|
-
timer = setTimeout(() => resolve(null), ms);
|
|
106
|
-
});
|
|
107
|
-
return Promise.race([promise, late]).finally(() => clearTimeout(timer));
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* One Express app in front of many tenants' apps. It answers process health
|
|
112
|
-
* itself, resolves each request to a tenant (see {@link selectTenant}),
|
|
113
|
-
* activates that tenant's graph on first use, hands the request to the
|
|
114
|
-
* tenant's app, and serves the SPA for whatever the tenant's app leaves
|
|
115
|
-
* unhandled. Nothing below it knows there are other tenants: each graph was
|
|
116
|
-
* built by the same composition root a single-tenant deployment uses.
|
|
117
|
-
*/
|
|
118
|
-
export function createTenantHost(opts: TenantHostOptions): TenantHost {
|
|
119
|
-
const runtimes = new Map<string, TenantRuntime>();
|
|
120
|
-
const activationWaitMs = opts.activationWaitMs ?? DEFAULT_ACTIVATION_WAIT_MS;
|
|
121
|
-
const idleMs = (opts.idleMinutes ?? DEFAULT_IDLE_MINUTES) * 60_000;
|
|
122
|
-
|
|
123
|
-
const runtimeFor = (descriptor: TenantDescriptor): TenantRuntime => {
|
|
124
|
-
let runtime = runtimes.get(descriptor.slug);
|
|
125
|
-
if (!runtime) {
|
|
126
|
-
runtime = new TenantRuntime(descriptor, opts.runtime);
|
|
127
|
-
runtimes.set(descriptor.slug, runtime);
|
|
128
|
-
}
|
|
129
|
-
return runtime;
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
const app = express();
|
|
133
|
-
// Forwarded headers are honoured exactly as a single-tenant deployment
|
|
134
|
-
// honours them, and for the same reason: `req.hostname` is what picks the
|
|
135
|
-
// tenant, and behind a proxy it lives in `X-Forwarded-Host`.
|
|
136
|
-
if (opts.process.trustProxy) {
|
|
137
|
-
const raw = opts.process.trustProxy;
|
|
138
|
-
app.set('trust proxy', /^\d+$/.test(raw) ? Number(raw) : raw);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// The process's own health, before any tenant is involved: a load balancer
|
|
142
|
-
// asks with whatever host name it likes, and a process with no active
|
|
143
|
-
// tenant is still a healthy process.
|
|
144
|
-
app.get('/api/health', (_req, res) => {
|
|
145
|
-
res.json({ status: 'ok', sha: GIT_SHA, timestamp: Date.now(), tenants: runtimes.size });
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
app.use(async (req: Request, res, next) => {
|
|
149
|
-
const selector = selectTenant({
|
|
150
|
-
hostname: req.hostname,
|
|
151
|
-
url: req.url,
|
|
152
|
-
peer: req.socket.remoteAddress,
|
|
153
|
-
forwardedFor: req.headers['x-forwarded-for'],
|
|
154
|
-
});
|
|
155
|
-
let descriptor: TenantDescriptor | null;
|
|
156
|
-
try {
|
|
157
|
-
descriptor =
|
|
158
|
-
selector.kind === 'slug'
|
|
159
|
-
? await opts.source.describe(selector.slug)
|
|
160
|
-
: await opts.source.resolveByHost(selector.host);
|
|
161
|
-
} catch (err) {
|
|
162
|
-
log.error('tenant lookup failed:', { err });
|
|
163
|
-
res.status(503).set('Retry-After', '5').json({ error: 'Tenant lookup failed' });
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
if (!descriptor) {
|
|
167
|
-
if (req.path.startsWith('/api/') || req.path.startsWith(LOOPBACK_TENANT_PREFIX)) {
|
|
168
|
-
res.status(404).json({ error: 'No workspace at this address' });
|
|
169
|
-
} else {
|
|
170
|
-
res.status(404).type('text/plain').send('No workspace at this address.');
|
|
171
|
-
}
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
if (selector.kind === 'slug') req.url = selector.rest;
|
|
175
|
-
|
|
176
|
-
const runtime = runtimeFor(descriptor);
|
|
177
|
-
// Counted from here, before the graph is even asked for, until the
|
|
178
|
-
// response closes however it ends — a 503 below included. An open
|
|
179
|
-
// response is what keeps a tenant from being evicted from under it.
|
|
180
|
-
// Left exactly once: a client that dropped during the tenant lookup
|
|
181
|
-
// above has had its `close` already, and that event will not come
|
|
182
|
-
// again, so the socket is asked directly; a socket destroyed but not
|
|
183
|
-
// yet closed would otherwise be left twice, once here and once by the
|
|
184
|
-
// listener, taking another request's count with it.
|
|
185
|
-
runtime.enter();
|
|
186
|
-
let left = false;
|
|
187
|
-
const leave = () => {
|
|
188
|
-
if (left) return;
|
|
189
|
-
left = true;
|
|
190
|
-
runtime.leave();
|
|
191
|
-
};
|
|
192
|
-
res.on('close', leave);
|
|
193
|
-
if (req.socket.destroyed) {
|
|
194
|
-
leave();
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
let graph: Awaited<ReturnType<TenantRuntime['handle']>> | null;
|
|
198
|
-
try {
|
|
199
|
-
graph = await within(runtime.handle(), activationWaitMs);
|
|
200
|
-
} catch {
|
|
201
|
-
// Logged by the runtime; the caller learns only that it may try again.
|
|
202
|
-
res.status(503).set('Retry-After', '5').json({ error: 'This workspace could not be started; try again shortly' });
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
if (!graph) {
|
|
206
|
-
res.status(503).set('Retry-After', '5').json({ error: 'This workspace is starting; try again shortly' });
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
graph.app(req, res, next);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// Whatever a tenant's app left unhandled: the SPA, with the same rule a
|
|
213
|
-
// single-tenant deployment applies to the namespaces that must never
|
|
214
|
-
// resolve to `index.html` (see `createCoreServer`).
|
|
215
|
-
if (opts.staticDir) {
|
|
216
|
-
const frontendDist = opts.staticDir;
|
|
217
|
-
app.use(express.static(frontendDist));
|
|
218
|
-
app.get('{*path}', (req, res) => {
|
|
219
|
-
if (
|
|
220
|
-
req.path.startsWith('/.well-known/') ||
|
|
221
|
-
req.path.startsWith('/api/') ||
|
|
222
|
-
req.path.startsWith('/login/oauth/')
|
|
223
|
-
) {
|
|
224
|
-
res.status(404).json({ error: 'Not found' });
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
res.sendFile(path.join(frontendDist, 'index.html'));
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// Idle tenants are stopped on a timer, never on the request that would
|
|
232
|
-
// have been their last: a graph whose last response closed `idleMs` ago,
|
|
233
|
-
// with none still open and no queued commit, is not worth its pool and
|
|
234
|
-
// its lease. `busy()` is what keeps an event stream's tenant alive.
|
|
235
|
-
const sweep = async () => {
|
|
236
|
-
for (const runtime of runtimes.values()) {
|
|
237
|
-
if (runtime.state !== 'active' || runtime.idleFor() < idleMs) continue;
|
|
238
|
-
if (await runtime.busy()) continue;
|
|
239
|
-
await runtime.evict().catch((err: unknown) => log.warn(`evicting tenant "${runtime.slug}" failed:`, { err }));
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
const sweeper =
|
|
243
|
-
idleMs > 0
|
|
244
|
-
? setInterval(() => void sweep(), Math.min(opts.sweepIntervalMs ?? DEFAULT_SWEEP_INTERVAL_MS, idleMs))
|
|
245
|
-
: null;
|
|
246
|
-
sweeper?.unref();
|
|
247
|
-
|
|
248
|
-
const evictAll = async () => {
|
|
249
|
-
await Promise.all([...runtimes.values()].map((runtime) => runtime.evict().catch(() => undefined)));
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
return {
|
|
253
|
-
app,
|
|
254
|
-
runtimes: () => runtimes,
|
|
255
|
-
evictAll,
|
|
256
|
-
async stop() {
|
|
257
|
-
if (sweeper) clearInterval(sweeper);
|
|
258
|
-
await evictAll();
|
|
259
|
-
},
|
|
260
|
-
};
|
|
261
|
-
}
|
|
1
|
+
import express, { type Express, type Request } from 'express';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { isIP } from 'node:net';
|
|
4
|
+
import type { ProcessConfig } from '../core-config.js';
|
|
5
|
+
import { GIT_SHA } from '../version.js';
|
|
6
|
+
import { logger } from '../shared/logging.js';
|
|
7
|
+
import { TenantRuntime, type TenantRuntimeDeps } from './tenant-runtime.js';
|
|
8
|
+
import { TENANT_SLUG_PATTERN, normalizeHost, type TenantDescriptor, type TenantSource } from './tenant-source.contract.js';
|
|
9
|
+
|
|
10
|
+
const log = logger('tenancy');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The path prefix under which a process reaches ONE of its own tenants over
|
|
14
|
+
* loopback: `http://127.0.0.1:<port>/_tenant/<slug>/api/...`. The MCP proxy
|
|
15
|
+
* and the UTCP manuals it seeds dial the tenant's own REST surface this way,
|
|
16
|
+
* because a loopback request carries no tenant host name and a header cannot
|
|
17
|
+
* ride a UTCP call (the proxy is a passthrough; it reshapes nothing).
|
|
18
|
+
*
|
|
19
|
+
* The host honours the prefix only for a request that came from this
|
|
20
|
+
* machine AND was forwarded by nobody: the socket peer is loopback and there
|
|
21
|
+
* is no `X-Forwarded-For`. A reverse proxy on the same host (nginx, a
|
|
22
|
+
* Coolify proxy) delivers every public request from a loopback socket, and
|
|
23
|
+
* every such proxy adds that header; the process's own dial never does.
|
|
24
|
+
* What the prefix could grant anyone who got past this is only what the
|
|
25
|
+
* tenant's host name grants already — sessions, keys and tokens are per
|
|
26
|
+
* tenant — but the addressing rule is stated so it can be relied on.
|
|
27
|
+
*/
|
|
28
|
+
export const LOOPBACK_TENANT_PREFIX = '/_tenant';
|
|
29
|
+
|
|
30
|
+
/** The base URL a tenant's graph dials itself at — see {@link LOOPBACK_TENANT_PREFIX}. */
|
|
31
|
+
export function loopbackTenantBaseUrl(port: number, slug: string): string {
|
|
32
|
+
return `http://127.0.0.1:${port}${LOOPBACK_TENANT_PREFIX}/${slug}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Whether `address` is this machine talking to itself. */
|
|
36
|
+
export function isLoopbackAddress(address: string | undefined): boolean {
|
|
37
|
+
if (!address) return false;
|
|
38
|
+
const bare = address.startsWith('::ffff:') ? address.slice('::ffff:'.length) : address;
|
|
39
|
+
if (bare === '::1') return true;
|
|
40
|
+
return isIP(bare) === 4 && bare.startsWith('127.');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** How a request names its tenant: by the loopback prefix, or by its host. */
|
|
44
|
+
export type TenantSelector = { kind: 'slug'; slug: string; rest: string } | { kind: 'host'; host: string };
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Which tenant a request is for. The loopback prefix wins, but only from a
|
|
48
|
+
* loopback peer that no proxy forwarded (no `X-Forwarded-For`); everything
|
|
49
|
+
* else is decided by the host name (the `X-Forwarded-Host` a trusted proxy
|
|
50
|
+
* set, else `Host`), lowercase and without its port.
|
|
51
|
+
*/
|
|
52
|
+
export function selectTenant(req: {
|
|
53
|
+
hostname: string;
|
|
54
|
+
url: string;
|
|
55
|
+
peer: string | undefined;
|
|
56
|
+
forwardedFor?: string | string[] | undefined;
|
|
57
|
+
}): TenantSelector {
|
|
58
|
+
const forwarded = Array.isArray(req.forwardedFor) ? req.forwardedFor.length > 0 : Boolean(req.forwardedFor);
|
|
59
|
+
if (isLoopbackAddress(req.peer) && !forwarded && req.url.startsWith(`${LOOPBACK_TENANT_PREFIX}/`)) {
|
|
60
|
+
const afterPrefix = req.url.slice(LOOPBACK_TENANT_PREFIX.length + 1);
|
|
61
|
+
const end = afterPrefix.search(/[/?#]/);
|
|
62
|
+
const slug = end === -1 ? afterPrefix : afterPrefix.slice(0, end);
|
|
63
|
+
if (TENANT_SLUG_PATTERN.test(slug)) {
|
|
64
|
+
const rest = end === -1 ? '/' : afterPrefix.slice(end).replace(/^(?=[?#])/, '/');
|
|
65
|
+
return { kind: 'slug', slug, rest };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return { kind: 'host', host: normalizeHost(req.hostname || '') };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface TenantHostOptions {
|
|
72
|
+
source: TenantSource;
|
|
73
|
+
process: ProcessConfig;
|
|
74
|
+
/** The built SPA, served once for every resolved tenant. */
|
|
75
|
+
staticDir?: string;
|
|
76
|
+
/** Minutes without a request after which a tenant's graph is stopped. Default 30; 0 never evicts. */
|
|
77
|
+
idleMinutes?: number;
|
|
78
|
+
/** How long a request waits for an activation in flight before answering 503. Default 60s. */
|
|
79
|
+
activationWaitMs?: number;
|
|
80
|
+
/** Seams for the runtimes the host builds — a suite's fake graphs. */
|
|
81
|
+
runtime?: TenantRuntimeDeps;
|
|
82
|
+
/** How often idle tenants are looked for. Default: once a minute. */
|
|
83
|
+
sweepIntervalMs?: number;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface TenantHost {
|
|
87
|
+
/** The app the process listens on. */
|
|
88
|
+
app: Express;
|
|
89
|
+
/** The runtimes built so far, by slug. */
|
|
90
|
+
runtimes(): ReadonlyMap<string, TenantRuntime>;
|
|
91
|
+
/** Stop every active tenant; the host keeps serving and reactivates on demand. */
|
|
92
|
+
evictAll(): Promise<void>;
|
|
93
|
+
/** Stop the idle sweep and every tenant: the process's shutdown. */
|
|
94
|
+
stop(): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const DEFAULT_ACTIVATION_WAIT_MS = 60_000;
|
|
98
|
+
const DEFAULT_IDLE_MINUTES = 30;
|
|
99
|
+
const DEFAULT_SWEEP_INTERVAL_MS = 60_000;
|
|
100
|
+
|
|
101
|
+
/** `promise`, or `null` once `ms` have passed. */
|
|
102
|
+
function within<T>(promise: Promise<T>, ms: number): Promise<T | null> {
|
|
103
|
+
let timer: NodeJS.Timeout | undefined;
|
|
104
|
+
const late = new Promise<null>((resolve) => {
|
|
105
|
+
timer = setTimeout(() => resolve(null), ms);
|
|
106
|
+
});
|
|
107
|
+
return Promise.race([promise, late]).finally(() => clearTimeout(timer));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* One Express app in front of many tenants' apps. It answers process health
|
|
112
|
+
* itself, resolves each request to a tenant (see {@link selectTenant}),
|
|
113
|
+
* activates that tenant's graph on first use, hands the request to the
|
|
114
|
+
* tenant's app, and serves the SPA for whatever the tenant's app leaves
|
|
115
|
+
* unhandled. Nothing below it knows there are other tenants: each graph was
|
|
116
|
+
* built by the same composition root a single-tenant deployment uses.
|
|
117
|
+
*/
|
|
118
|
+
export function createTenantHost(opts: TenantHostOptions): TenantHost {
|
|
119
|
+
const runtimes = new Map<string, TenantRuntime>();
|
|
120
|
+
const activationWaitMs = opts.activationWaitMs ?? DEFAULT_ACTIVATION_WAIT_MS;
|
|
121
|
+
const idleMs = (opts.idleMinutes ?? DEFAULT_IDLE_MINUTES) * 60_000;
|
|
122
|
+
|
|
123
|
+
const runtimeFor = (descriptor: TenantDescriptor): TenantRuntime => {
|
|
124
|
+
let runtime = runtimes.get(descriptor.slug);
|
|
125
|
+
if (!runtime) {
|
|
126
|
+
runtime = new TenantRuntime(descriptor, opts.runtime);
|
|
127
|
+
runtimes.set(descriptor.slug, runtime);
|
|
128
|
+
}
|
|
129
|
+
return runtime;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const app = express();
|
|
133
|
+
// Forwarded headers are honoured exactly as a single-tenant deployment
|
|
134
|
+
// honours them, and for the same reason: `req.hostname` is what picks the
|
|
135
|
+
// tenant, and behind a proxy it lives in `X-Forwarded-Host`.
|
|
136
|
+
if (opts.process.trustProxy) {
|
|
137
|
+
const raw = opts.process.trustProxy;
|
|
138
|
+
app.set('trust proxy', /^\d+$/.test(raw) ? Number(raw) : raw);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// The process's own health, before any tenant is involved: a load balancer
|
|
142
|
+
// asks with whatever host name it likes, and a process with no active
|
|
143
|
+
// tenant is still a healthy process.
|
|
144
|
+
app.get('/api/health', (_req, res) => {
|
|
145
|
+
res.json({ status: 'ok', sha: GIT_SHA, timestamp: Date.now(), tenants: runtimes.size });
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
app.use(async (req: Request, res, next) => {
|
|
149
|
+
const selector = selectTenant({
|
|
150
|
+
hostname: req.hostname,
|
|
151
|
+
url: req.url,
|
|
152
|
+
peer: req.socket.remoteAddress,
|
|
153
|
+
forwardedFor: req.headers['x-forwarded-for'],
|
|
154
|
+
});
|
|
155
|
+
let descriptor: TenantDescriptor | null;
|
|
156
|
+
try {
|
|
157
|
+
descriptor =
|
|
158
|
+
selector.kind === 'slug'
|
|
159
|
+
? await opts.source.describe(selector.slug)
|
|
160
|
+
: await opts.source.resolveByHost(selector.host);
|
|
161
|
+
} catch (err) {
|
|
162
|
+
log.error('tenant lookup failed:', { err });
|
|
163
|
+
res.status(503).set('Retry-After', '5').json({ error: 'Tenant lookup failed' });
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (!descriptor) {
|
|
167
|
+
if (req.path.startsWith('/api/') || req.path.startsWith(LOOPBACK_TENANT_PREFIX)) {
|
|
168
|
+
res.status(404).json({ error: 'No workspace at this address' });
|
|
169
|
+
} else {
|
|
170
|
+
res.status(404).type('text/plain').send('No workspace at this address.');
|
|
171
|
+
}
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (selector.kind === 'slug') req.url = selector.rest;
|
|
175
|
+
|
|
176
|
+
const runtime = runtimeFor(descriptor);
|
|
177
|
+
// Counted from here, before the graph is even asked for, until the
|
|
178
|
+
// response closes however it ends — a 503 below included. An open
|
|
179
|
+
// response is what keeps a tenant from being evicted from under it.
|
|
180
|
+
// Left exactly once: a client that dropped during the tenant lookup
|
|
181
|
+
// above has had its `close` already, and that event will not come
|
|
182
|
+
// again, so the socket is asked directly; a socket destroyed but not
|
|
183
|
+
// yet closed would otherwise be left twice, once here and once by the
|
|
184
|
+
// listener, taking another request's count with it.
|
|
185
|
+
runtime.enter();
|
|
186
|
+
let left = false;
|
|
187
|
+
const leave = () => {
|
|
188
|
+
if (left) return;
|
|
189
|
+
left = true;
|
|
190
|
+
runtime.leave();
|
|
191
|
+
};
|
|
192
|
+
res.on('close', leave);
|
|
193
|
+
if (req.socket.destroyed) {
|
|
194
|
+
leave();
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
let graph: Awaited<ReturnType<TenantRuntime['handle']>> | null;
|
|
198
|
+
try {
|
|
199
|
+
graph = await within(runtime.handle(), activationWaitMs);
|
|
200
|
+
} catch {
|
|
201
|
+
// Logged by the runtime; the caller learns only that it may try again.
|
|
202
|
+
res.status(503).set('Retry-After', '5').json({ error: 'This workspace could not be started; try again shortly' });
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (!graph) {
|
|
206
|
+
res.status(503).set('Retry-After', '5').json({ error: 'This workspace is starting; try again shortly' });
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
graph.app(req, res, next);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// Whatever a tenant's app left unhandled: the SPA, with the same rule a
|
|
213
|
+
// single-tenant deployment applies to the namespaces that must never
|
|
214
|
+
// resolve to `index.html` (see `createCoreServer`).
|
|
215
|
+
if (opts.staticDir) {
|
|
216
|
+
const frontendDist = opts.staticDir;
|
|
217
|
+
app.use(express.static(frontendDist));
|
|
218
|
+
app.get('{*path}', (req, res) => {
|
|
219
|
+
if (
|
|
220
|
+
req.path.startsWith('/.well-known/') ||
|
|
221
|
+
req.path.startsWith('/api/') ||
|
|
222
|
+
req.path.startsWith('/login/oauth/')
|
|
223
|
+
) {
|
|
224
|
+
res.status(404).json({ error: 'Not found' });
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
res.sendFile(path.join(frontendDist, 'index.html'));
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Idle tenants are stopped on a timer, never on the request that would
|
|
232
|
+
// have been their last: a graph whose last response closed `idleMs` ago,
|
|
233
|
+
// with none still open and no queued commit, is not worth its pool and
|
|
234
|
+
// its lease. `busy()` is what keeps an event stream's tenant alive.
|
|
235
|
+
const sweep = async () => {
|
|
236
|
+
for (const runtime of runtimes.values()) {
|
|
237
|
+
if (runtime.state !== 'active' || runtime.idleFor() < idleMs) continue;
|
|
238
|
+
if (await runtime.busy()) continue;
|
|
239
|
+
await runtime.evict().catch((err: unknown) => log.warn(`evicting tenant "${runtime.slug}" failed:`, { err }));
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
const sweeper =
|
|
243
|
+
idleMs > 0
|
|
244
|
+
? setInterval(() => void sweep(), Math.min(opts.sweepIntervalMs ?? DEFAULT_SWEEP_INTERVAL_MS, idleMs))
|
|
245
|
+
: null;
|
|
246
|
+
sweeper?.unref();
|
|
247
|
+
|
|
248
|
+
const evictAll = async () => {
|
|
249
|
+
await Promise.all([...runtimes.values()].map((runtime) => runtime.evict().catch(() => undefined)));
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
return {
|
|
253
|
+
app,
|
|
254
|
+
runtimes: () => runtimes,
|
|
255
|
+
evictAll,
|
|
256
|
+
async stop() {
|
|
257
|
+
if (sweeper) clearInterval(sweeper);
|
|
258
|
+
await evictAll();
|
|
259
|
+
},
|
|
260
|
+
};
|
|
261
|
+
}
|