@bevel-software/platform-core-backend 0.20.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/catalog-cache-invalidation.d.ts +7 -2
- package/dist/core/catalog-cache-invalidation.d.ts.map +1 -1
- package/dist/core/catalog-cache-invalidation.js +8 -9
- package/dist/core/catalog-cache-invalidation.js.map +1 -1
- package/dist/core/core-ports.d.ts +19 -0
- package/dist/core/core-ports.d.ts.map +1 -1
- package/dist/core/core-ports.js.map +1 -1
- package/dist/core/create-core-server.d.ts +2 -0
- package/dist/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +55 -107
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +41 -4
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +183 -82
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core/lifecycle.d.ts +74 -28
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +157 -20
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/core/public-config.d.ts +5 -1
- package/dist/core/public-config.d.ts.map +1 -1
- package/dist/core/public-config.js +7 -5
- package/dist/core/public-config.js.map +1 -1
- package/dist/core-config.d.ts +95 -1
- package/dist/core-config.d.ts.map +1 -1
- package/dist/core-config.js +24 -8
- package/dist/core-config.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +18 -1
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +19 -8
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/access-requests.contract.d.ts +75 -0
- package/dist/modules/access/access-requests.contract.d.ts.map +1 -0
- package/dist/modules/access/access-requests.contract.js +20 -0
- package/dist/modules/access/access-requests.contract.js.map +1 -0
- package/dist/modules/access/access-requests.routes.d.ts +35 -0
- package/dist/modules/access/access-requests.routes.d.ts.map +1 -0
- package/dist/modules/access/access-requests.routes.js +237 -0
- package/dist/modules/access/access-requests.routes.js.map +1 -0
- package/dist/modules/access/access-requests.service.d.ts +123 -0
- package/dist/modules/access/access-requests.service.d.ts.map +1 -0
- package/dist/modules/access/access-requests.service.js +337 -0
- package/dist/modules/access/access-requests.service.js.map +1 -0
- package/dist/modules/access/access.routes.d.ts +2 -1
- package/dist/modules/access/access.routes.d.ts.map +1 -1
- package/dist/modules/access/access.routes.js +10 -10
- package/dist/modules/access/access.routes.js.map +1 -1
- package/dist/modules/access/change-read-gate.d.ts +6 -3
- package/dist/modules/access/change-read-gate.d.ts.map +1 -1
- package/dist/modules/access/change-read-gate.js +9 -6
- package/dist/modules/access/change-read-gate.js.map +1 -1
- package/dist/modules/access/creator-access.d.ts +4 -2
- package/dist/modules/access/creator-access.d.ts.map +1 -1
- package/dist/modules/access/creator-access.js +7 -4
- package/dist/modules/access/creator-access.js.map +1 -1
- package/dist/modules/access-model/access-grammar.d.ts +12 -0
- package/dist/modules/access-model/access-grammar.d.ts.map +1 -1
- package/dist/modules/access-model/access-grammar.js +24 -0
- package/dist/modules/access-model/access-grammar.js.map +1 -1
- package/dist/modules/agent-instructions/read-preamble.d.ts +2 -1
- package/dist/modules/agent-instructions/read-preamble.d.ts.map +1 -1
- package/dist/modules/agent-instructions/read-preamble.js +6 -9
- package/dist/modules/agent-instructions/read-preamble.js.map +1 -1
- package/dist/modules/auth/account-admission.d.ts +40 -0
- package/dist/modules/auth/account-admission.d.ts.map +1 -0
- package/dist/modules/auth/account-admission.js +17 -0
- package/dist/modules/auth/account-admission.js.map +1 -0
- package/dist/modules/auth/account.routes.d.ts.map +1 -1
- package/dist/modules/auth/account.routes.js +4 -1
- package/dist/modules/auth/account.routes.js.map +1 -1
- package/dist/modules/auth/auth.service.d.ts +45 -2
- package/dist/modules/auth/auth.service.d.ts.map +1 -1
- package/dist/modules/auth/auth.service.js +44 -3
- package/dist/modules/auth/auth.service.js.map +1 -1
- package/dist/modules/auth/oidc-auth-provider.d.ts.map +1 -1
- package/dist/modules/auth/oidc-auth-provider.js +9 -0
- package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
- package/dist/modules/connection-probe/connection-probe.service.d.ts +13 -1
- package/dist/modules/connection-probe/connection-probe.service.d.ts.map +1 -1
- package/dist/modules/connection-probe/connection-probe.service.js +10 -2
- package/dist/modules/connection-probe/connection-probe.service.js.map +1 -1
- package/dist/modules/database/advisory-lock.d.ts +17 -0
- package/dist/modules/database/advisory-lock.d.ts.map +1 -1
- package/dist/modules/database/advisory-lock.js +24 -3
- package/dist/modules/database/advisory-lock.js.map +1 -1
- package/dist/modules/database/connection.d.ts +67 -2
- package/dist/modules/database/connection.d.ts.map +1 -1
- package/dist/modules/database/connection.js +118 -12
- package/dist/modules/database/connection.js.map +1 -1
- package/dist/modules/database/migrate.d.ts +1 -1
- package/dist/modules/database/migrate.d.ts.map +1 -1
- package/dist/modules/database/migrate.js +27 -3
- package/dist/modules/database/migrate.js.map +1 -1
- package/dist/modules/github-app/github-app.client.d.ts +101 -0
- package/dist/modules/github-app/github-app.client.d.ts.map +1 -0
- package/dist/modules/github-app/github-app.client.js +222 -0
- package/dist/modules/github-app/github-app.client.js.map +1 -0
- package/dist/modules/github-app/github-app.connection.d.ts +102 -0
- package/dist/modules/github-app/github-app.connection.d.ts.map +1 -0
- package/dist/modules/github-app/github-app.connection.js +185 -0
- package/dist/modules/github-app/github-app.connection.js.map +1 -0
- package/dist/modules/github-app/github-app.routes.d.ts +59 -0
- package/dist/modules/github-app/github-app.routes.d.ts.map +1 -0
- package/dist/modules/github-app/github-app.routes.js +323 -0
- package/dist/modules/github-app/github-app.routes.js.map +1 -0
- package/dist/modules/github-app/index.d.ts +4 -0
- package/dist/modules/github-app/index.d.ts.map +1 -0
- package/dist/modules/github-app/index.js +4 -0
- package/dist/modules/github-app/index.js.map +1 -0
- package/dist/modules/kb-fs/branch-name.d.ts +0 -1
- package/dist/modules/kb-fs/branch-name.d.ts.map +1 -1
- package/dist/modules/kb-fs/branch-name.js +3 -3
- package/dist/modules/kb-fs/branch-name.js.map +1 -1
- package/dist/modules/kb-fs/clone-config.d.ts +9 -8
- package/dist/modules/kb-fs/clone-config.d.ts.map +1 -1
- package/dist/modules/kb-fs/clone-config.js +14 -12
- package/dist/modules/kb-fs/clone-config.js.map +1 -1
- package/dist/modules/kb-fs/remote-url.d.ts +22 -0
- package/dist/modules/kb-fs/remote-url.d.ts.map +1 -0
- package/dist/modules/kb-fs/remote-url.js +35 -0
- package/dist/modules/kb-fs/remote-url.js.map +1 -0
- package/dist/modules/mcp/mcp.service.d.ts +7 -0
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +4 -4
- package/dist/modules/mcp/mcp.service.js.map +1 -1
- package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts +4 -4
- package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts.map +1 -1
- package/dist/modules/plugins/compile/marketplace-compiler.service.js +7 -10
- package/dist/modules/plugins/compile/marketplace-compiler.service.js.map +1 -1
- package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts +4 -1
- package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts.map +1 -1
- package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js +5 -3
- package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js.map +1 -1
- package/dist/modules/plugins/discovery/kb-plugin-source.d.ts +6 -1
- package/dist/modules/plugins/discovery/kb-plugin-source.d.ts.map +1 -1
- package/dist/modules/plugins/discovery/kb-plugin-source.js +14 -9
- package/dist/modules/plugins/discovery/kb-plugin-source.js.map +1 -1
- package/dist/modules/plugins/discovery/native.source.d.ts +4 -1
- package/dist/modules/plugins/discovery/native.source.d.ts.map +1 -1
- package/dist/modules/plugins/discovery/native.source.js +4 -2
- package/dist/modules/plugins/discovery/native.source.js.map +1 -1
- package/dist/modules/plugins/index.d.ts +1 -1
- package/dist/modules/plugins/index.d.ts.map +1 -1
- package/dist/modules/plugins/index.js +1 -1
- package/dist/modules/plugins/index.js.map +1 -1
- package/dist/modules/plugins/join-proposals.d.ts +17 -5
- package/dist/modules/plugins/join-proposals.d.ts.map +1 -1
- package/dist/modules/plugins/join-proposals.js +76 -22
- package/dist/modules/plugins/join-proposals.js.map +1 -1
- package/dist/modules/plugins/join-request-jobs.service.d.ts +3 -1
- package/dist/modules/plugins/join-request-jobs.service.d.ts.map +1 -1
- package/dist/modules/plugins/join-request-jobs.service.js +6 -6
- package/dist/modules/plugins/join-request-jobs.service.js.map +1 -1
- package/dist/modules/plugins/join-requests.service.d.ts +113 -18
- package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
- package/dist/modules/plugins/join-requests.service.js +178 -33
- package/dist/modules/plugins/join-requests.service.js.map +1 -1
- package/dist/modules/plugins/plugin-links.d.ts +65 -10
- package/dist/modules/plugins/plugin-links.d.ts.map +1 -1
- package/dist/modules/plugins/plugin-links.js +136 -31
- package/dist/modules/plugins/plugin-links.js.map +1 -1
- package/dist/modules/plugins/plugin-links.service.d.ts +107 -5
- package/dist/modules/plugins/plugin-links.service.d.ts.map +1 -1
- package/dist/modules/plugins/plugin-links.service.js +151 -21
- package/dist/modules/plugins/plugin-links.service.js.map +1 -1
- package/dist/modules/plugins/plugin-provision.service.d.ts +10 -3
- package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
- package/dist/modules/plugins/plugin-provision.service.js +33 -26
- package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
- package/dist/modules/plugins/plugin-rename.service.d.ts +4 -2
- package/dist/modules/plugins/plugin-rename.service.d.ts.map +1 -1
- package/dist/modules/plugins/plugin-rename.service.js +10 -12
- package/dist/modules/plugins/plugin-rename.service.js.map +1 -1
- package/dist/modules/plugins/plugins.routes.d.ts +3 -0
- package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.routes.js +48 -17
- package/dist/modules/plugins/plugins.routes.js.map +1 -1
- package/dist/modules/plugins/plugins.service.d.ts +4 -4
- package/dist/modules/plugins/plugins.service.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.service.js +7 -10
- package/dist/modules/plugins/plugins.service.js.map +1 -1
- package/dist/modules/plugins/teams.routes.d.ts +4 -1
- package/dist/modules/plugins/teams.routes.d.ts.map +1 -1
- package/dist/modules/plugins/teams.routes.js +11 -9
- package/dist/modules/plugins/teams.routes.js.map +1 -1
- package/dist/modules/secrets-vault/index.d.ts +1 -1
- package/dist/modules/secrets-vault/index.d.ts.map +1 -1
- package/dist/modules/secrets-vault/index.js +1 -1
- package/dist/modules/secrets-vault/index.js.map +1 -1
- package/dist/modules/secrets-vault/secrets-variable-loader.d.ts +29 -11
- package/dist/modules/secrets-vault/secrets-variable-loader.d.ts.map +1 -1
- package/dist/modules/secrets-vault/secrets-variable-loader.js +46 -21
- package/dist/modules/secrets-vault/secrets-variable-loader.js.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +3 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.js +4 -6
- package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
- package/dist/modules/settings/deployment-settings.service.d.ts +34 -9
- package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
- package/dist/modules/settings/deployment-settings.service.js +113 -26
- package/dist/modules/settings/deployment-settings.service.js.map +1 -1
- package/dist/modules/settings/managed-repository.d.ts +43 -0
- package/dist/modules/settings/managed-repository.d.ts.map +1 -0
- package/dist/modules/settings/managed-repository.js +60 -0
- package/dist/modules/settings/managed-repository.js.map +1 -0
- package/dist/modules/settings/repository-source.d.ts +128 -0
- package/dist/modules/settings/repository-source.d.ts.map +1 -0
- package/dist/modules/settings/repository-source.js +150 -0
- package/dist/modules/settings/repository-source.js.map +1 -0
- package/dist/modules/settings/setup.routes.d.ts +34 -4
- package/dist/modules/settings/setup.routes.d.ts.map +1 -1
- package/dist/modules/settings/setup.routes.js +198 -18
- package/dist/modules/settings/setup.routes.js.map +1 -1
- package/dist/modules/skills/allowed-tools-check.d.ts +4 -3
- package/dist/modules/skills/allowed-tools-check.d.ts.map +1 -1
- package/dist/modules/skills/allowed-tools-check.js +8 -8
- package/dist/modules/skills/allowed-tools-check.js.map +1 -1
- package/dist/modules/skills/pending-skills.service.d.ts +3 -1
- package/dist/modules/skills/pending-skills.service.d.ts.map +1 -1
- package/dist/modules/skills/pending-skills.service.js +9 -6
- package/dist/modules/skills/pending-skills.service.js.map +1 -1
- package/dist/modules/skills/skill-access-requests.routes.d.ts +8 -9
- package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -1
- package/dist/modules/skills/skill-access-requests.routes.js +26 -65
- package/dist/modules/skills/skill-access-requests.routes.js.map +1 -1
- package/dist/modules/skills/skills.routes.d.ts +4 -1
- package/dist/modules/skills/skills.routes.d.ts.map +1 -1
- package/dist/modules/skills/skills.routes.js +4 -4
- package/dist/modules/skills/skills.routes.js.map +1 -1
- package/dist/modules/skills/skills.service.d.ts +4 -2
- package/dist/modules/skills/skills.service.d.ts.map +1 -1
- package/dist/modules/skills/skills.service.js +13 -11
- package/dist/modules/skills/skills.service.js.map +1 -1
- package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool-context.js +15 -0
- package/dist/modules/tool-helpers/tool-context.js.map +1 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.d.ts +2 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.d.ts.map +1 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.js +6 -5
- package/dist/modules/tool-manuals/mcp-json-discovery.js.map +1 -1
- package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts +4 -2
- package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/mcp-server-edit.service.js +12 -10
- package/dist/modules/tool-manuals/mcp-server-edit.service.js.map +1 -1
- package/dist/modules/tool-manuals/pending-tools.service.d.ts +3 -1
- package/dist/modules/tool-manuals/pending-tools.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/pending-tools.service.js +19 -16
- package/dist/modules/tool-manuals/pending-tools.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-delete.service.d.ts +4 -2
- package/dist/modules/tool-manuals/tool-delete.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-delete.service.js +14 -12
- package/dist/modules/tool-manuals/tool-delete.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +3 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.js +7 -7
- package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts +4 -2
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +15 -12
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +3 -0
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +4 -6
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +3 -2
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.js +47 -11
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +14 -6
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +40 -18
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/git/node-git-runner.d.ts +26 -2
- package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -1
- package/dist/modules/workflow/git/node-git-runner.js +40 -5
- package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
- package/dist/modules/workflow/git/pull-request.service.d.ts +45 -0
- package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/pull-request.service.js +99 -0
- package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.js +9 -4
- package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
- package/dist/modules/workflow/session-ontology.service.d.ts +6 -1
- package/dist/modules/workflow/session-ontology.service.d.ts.map +1 -1
- package/dist/modules/workflow/session-ontology.service.js +6 -2
- package/dist/modules/workflow/session-ontology.service.js.map +1 -1
- package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.routes.js +3 -1
- package/dist/modules/workflow/workflow.routes.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts +42 -10
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +181 -71
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/session-ontology.gate.d.ts +3 -1
- package/dist/modules/workspace/session-ontology.gate.d.ts.map +1 -1
- package/dist/modules/workspace/session-ontology.gate.js +3 -3
- package/dist/modules/workspace/session-ontology.gate.js.map +1 -1
- package/dist/modules/workspace/startup/kb-git.d.ts +4 -3
- package/dist/modules/workspace/startup/kb-git.d.ts.map +1 -1
- package/dist/modules/workspace/startup/kb-git.js +15 -13
- package/dist/modules/workspace/startup/kb-git.js.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts +70 -7
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.js +183 -38
- package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
- package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts +7 -1
- package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js +23 -16
- package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/personal-spaces.step.d.ts +7 -1
- package/dist/modules/workspace/startup/steps/personal-spaces.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/personal-spaces.step.js +12 -5
- package/dist/modules/workspace/startup/steps/personal-spaces.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/plugin-display-names.step.d.ts +7 -1
- package/dist/modules/workspace/startup/steps/plugin-display-names.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/plugin-display-names.step.js +12 -5
- package/dist/modules/workspace/startup/steps/plugin-display-names.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts +7 -1
- package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/plugin-manifests.step.js +12 -5
- package/dist/modules/workspace/startup/steps/plugin-manifests.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts +4 -1
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.js +14 -11
- package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts +17 -3
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-files.step.js +36 -30
- package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.d.ts +6 -1
- package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.js +10 -6
- package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
- package/dist/modules/workspace/workspace.routes.d.ts +2 -1
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.routes.js +8 -7
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +18 -12
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +49 -29
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts +2 -1
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +48 -20
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/modules/workspace/write-denial.d.ts +3 -2
- package/dist/modules/workspace/write-denial.d.ts.map +1 -1
- package/dist/modules/workspace/write-denial.js +6 -5
- package/dist/modules/workspace/write-denial.js.map +1 -1
- package/dist/shared/domain-errors.d.ts +39 -0
- package/dist/shared/domain-errors.d.ts.map +1 -1
- package/dist/shared/domain-errors.js +55 -0
- package/dist/shared/domain-errors.js.map +1 -1
- package/dist/shared/git.contract.d.ts +62 -7
- package/dist/shared/git.contract.d.ts.map +1 -1
- package/dist/shared/git.contract.js +30 -8
- package/dist/shared/git.contract.js.map +1 -1
- package/dist/shared/kb-context.d.ts +76 -0
- package/dist/shared/kb-context.d.ts.map +1 -0
- package/dist/shared/kb-context.js +108 -0
- package/dist/shared/kb-context.js.map +1 -0
- package/dist/shared/kb-layout.d.ts +3 -2
- package/dist/shared/kb-layout.d.ts.map +1 -1
- package/dist/shared/kb-layout.js +4 -3
- package/dist/shared/kb-layout.js.map +1 -1
- package/dist/shared/kb-layout.test.js +35 -27
- package/dist/shared/kb-layout.test.js.map +1 -1
- package/dist/shared/pending-proposals.d.ts +4 -1
- package/dist/shared/pending-proposals.d.ts.map +1 -1
- package/dist/shared/pending-proposals.js +3 -4
- package/dist/shared/pending-proposals.js.map +1 -1
- package/dist/shared/redact-secret.d.ts +5 -5
- package/dist/shared/redact-secret.js +5 -5
- package/dist/tenancy/index.d.ts +13 -0
- package/dist/tenancy/index.d.ts.map +1 -0
- package/dist/tenancy/index.js +13 -0
- package/dist/tenancy/index.js.map +1 -0
- package/dist/tenancy/static-tenant-source.d.ts +98 -0
- package/dist/tenancy/static-tenant-source.d.ts.map +1 -0
- package/dist/tenancy/static-tenant-source.js +220 -0
- package/dist/tenancy/static-tenant-source.js.map +1 -0
- package/dist/tenancy/tenant-host.d.ts +80 -0
- package/dist/tenancy/tenant-host.d.ts.map +1 -0
- package/dist/tenancy/tenant-host.js +217 -0
- package/dist/tenancy/tenant-host.js.map +1 -0
- package/dist/tenancy/tenant-runtime.d.ts +91 -0
- package/dist/tenancy/tenant-runtime.d.ts.map +1 -0
- package/dist/tenancy/tenant-runtime.js +174 -0
- package/dist/tenancy/tenant-runtime.js.map +1 -0
- package/dist/tenancy/tenant-secrets.d.ts +24 -0
- package/dist/tenancy/tenant-secrets.d.ts.map +1 -0
- package/dist/tenancy/tenant-secrets.js +30 -0
- package/dist/tenancy/tenant-secrets.js.map +1 -0
- package/dist/tenancy/tenant-source.contract.d.ts +45 -0
- package/dist/tenancy/tenant-source.contract.d.ts.map +1 -0
- package/dist/tenancy/tenant-source.contract.js +21 -0
- package/dist/tenancy/tenant-source.contract.js.map +1 -0
- package/migrations/0000_core_init.sql +14 -14
- package/migrations/0003_deployment_settings.sql +1 -1
- package/migrations/0005_github_facade.sql +1 -1
- package/migrations/0012_agent_audit.sql +6 -6
- package/package.json +3 -3
- package/src/__tests__/branch-model.test.ts +7 -6
- package/src/__tests__/kb-context.ts +30 -0
- package/src/__tests__/kb-layout-config.test.ts +35 -30
- package/src/core/__tests__/catalog-cache-invalidation.test.ts +2 -1
- package/src/core/__tests__/lifecycle.test.ts +78 -1
- package/src/core/__tests__/public-config.test.ts +5 -1
- package/src/core/catalog-cache-invalidation.ts +16 -11
- package/src/core/core-ports.ts +19 -0
- package/src/core/create-core-server.ts +64 -107
- package/src/core/create-core-services.ts +238 -96
- package/src/core/lifecycle.ts +214 -29
- package/src/core/public-config.ts +8 -5
- package/src/core-config.ts +107 -8
- package/src/index.ts +25 -2
- package/src/modules/access/__tests__/access-control.admin-root-floor.test.ts +2 -1
- package/src/modules/access/__tests__/access-requests.recut.test.ts +134 -0
- package/src/modules/access/__tests__/access-requests.routes.test.ts +610 -0
- package/src/modules/access/__tests__/access.routes.batch.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.folder-governs.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.group-grant.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.overrides.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.proposal-branch.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.prospective.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.revoke.test.ts +2 -1
- package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +2 -1
- package/src/modules/access/__tests__/change-read-gate.test.ts +13 -11
- package/src/modules/access/__tests__/creator-access.test.ts +3 -2
- package/src/modules/access/__tests__/roles.routes.test.ts +2 -1
- package/src/modules/access/access-control.service.ts +20 -6
- package/src/modules/access/access-requests.contract.ts +93 -0
- package/src/modules/access/access-requests.routes.ts +286 -0
- package/src/modules/access/access-requests.service.ts +420 -0
- package/src/modules/access/access.routes.ts +10 -13
- package/src/modules/access/change-read-gate.ts +10 -4
- package/src/modules/access/creator-access.ts +7 -2
- package/src/modules/access-model/access-grammar.ts +22 -0
- package/src/modules/agent-instructions/__tests__/read-preamble.test.ts +13 -12
- package/src/modules/agent-instructions/read-preamble.ts +10 -12
- package/src/modules/auth/__tests__/account.routes.test.ts +15 -0
- package/src/modules/auth/__tests__/auth.service.test.ts +98 -0
- package/src/modules/auth/account-admission.ts +44 -0
- package/src/modules/auth/account.routes.ts +4 -1
- package/src/modules/auth/auth.service.ts +61 -2
- package/src/modules/auth/oidc-auth-provider.ts +9 -0
- package/src/modules/connection-probe/connection-probe.service.ts +7 -1
- package/src/modules/database/__tests__/advisory-lock.test.ts +23 -1
- package/src/modules/database/__tests__/connection.test.ts +98 -0
- package/src/modules/database/__tests__/migrations-unqualified.test.ts +32 -0
- package/src/modules/database/advisory-lock.ts +28 -4
- package/src/modules/database/connection.ts +143 -13
- package/src/modules/database/migrate.ts +48 -14
- package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +2 -1
- package/src/modules/diff/__tests__/diff.service.test.ts +2 -1
- package/src/modules/github-app/__tests__/github-app.test.ts +848 -0
- package/src/modules/github-app/github-app.client.ts +268 -0
- package/src/modules/github-app/github-app.connection.ts +204 -0
- package/src/modules/github-app/github-app.routes.ts +359 -0
- package/src/modules/github-app/index.ts +19 -0
- package/src/modules/kb-fs/__tests__/branch-name.test.ts +6 -6
- package/src/modules/kb-fs/__tests__/clone-config.test.ts +24 -20
- package/src/modules/kb-fs/__tests__/remote-url.test.ts +38 -0
- package/src/modules/kb-fs/branch-name.ts +3 -3
- package/src/modules/kb-fs/clone-config.ts +15 -12
- package/src/modules/kb-fs/remote-url.ts +35 -0
- package/src/modules/marketplace/__tests__/marketplace-repo.head.test.ts +2 -1
- package/src/modules/mcp/mcp.service.ts +11 -4
- package/src/modules/plugins/__tests__/bundle-dialect.e2e.test.ts +12 -11
- package/src/modules/plugins/__tests__/bundle-dialect.test.ts +2 -1
- package/src/modules/plugins/__tests__/compile-marketplace.test.ts +6 -4
- package/src/modules/plugins/__tests__/join-proposals.test.ts +100 -19
- package/src/modules/plugins/__tests__/join-request-jobs.service.test.ts +2 -1
- package/src/modules/plugins/__tests__/join-requests.service.test.ts +28 -11
- package/src/modules/plugins/__tests__/join-requests.settlement.test.ts +371 -0
- package/src/modules/plugins/__tests__/plugin-creation-display-name.test.ts +4 -3
- package/src/modules/plugins/__tests__/plugin-index.service.test.ts +6 -4
- package/src/modules/plugins/__tests__/plugin-links.service.test.ts +220 -5
- package/src/modules/plugins/__tests__/plugin-provision.service.test.ts +3 -1
- package/src/modules/plugins/__tests__/plugin-rename.service.test.ts +7 -6
- package/src/modules/plugins/__tests__/plugins.routes.test.ts +12 -3
- package/src/modules/plugins/__tests__/teams.routes.test.ts +2 -1
- package/src/modules/plugins/compile/marketplace-compiler.service.ts +7 -9
- package/src/modules/plugins/discovery/__tests__/kb-plugin-source.test.ts +20 -16
- package/src/modules/plugins/discovery/bundle-dialect/bundle.source.ts +9 -2
- package/src/modules/plugins/discovery/kb-plugin-source.ts +15 -8
- package/src/modules/plugins/discovery/native.source.ts +4 -1
- package/src/modules/plugins/index.ts +1 -1
- package/src/modules/plugins/join-proposals.ts +87 -19
- package/src/modules/plugins/join-request-jobs.service.ts +8 -7
- package/src/modules/plugins/join-requests.service.ts +203 -43
- package/src/modules/plugins/plugin-links.service.ts +192 -19
- package/src/modules/plugins/plugin-links.ts +147 -27
- package/src/modules/plugins/plugin-provision.service.ts +54 -27
- package/src/modules/plugins/plugin-rename.service.ts +10 -10
- package/src/modules/plugins/plugins.routes.ts +48 -17
- package/src/modules/plugins/plugins.service.ts +7 -11
- package/src/modules/plugins/teams.routes.ts +16 -8
- package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +7 -0
- package/src/modules/secrets-vault/__tests__/secrets-variable-loader.test.ts +40 -0
- package/src/modules/secrets-vault/__tests__/tool-owner-gate.route.test.ts +2 -0
- package/src/modules/secrets-vault/index.ts +2 -0
- package/src/modules/secrets-vault/secrets-variable-loader.ts +51 -21
- package/src/modules/secrets-vault/secrets-vault.routes.ts +7 -6
- package/src/modules/settings/__tests__/deployment-settings.service.test.ts +24 -11
- package/src/modules/settings/__tests__/git-root-folders.test.ts +2 -1
- package/src/modules/settings/__tests__/repository-source.test.ts +191 -0
- package/src/modules/settings/__tests__/setup.routes.boot-failure.test.ts +2 -1
- package/src/modules/settings/__tests__/setup.routes.git-mode.test.ts +353 -0
- package/src/modules/settings/__tests__/setup.routes.github-app.test.ts +282 -0
- package/src/modules/settings/__tests__/setup.routes.layout-phase.test.ts +7 -4
- package/src/modules/settings/__tests__/setup.routes.managed-phase.test.ts +233 -0
- package/src/modules/settings/__tests__/setup.routes.oidc.test.ts +2 -0
- package/src/modules/settings/__tests__/setup.routes.sync-status.test.ts +2 -0
- package/src/modules/settings/__tests__/setup.routes.test.ts +33 -52
- package/src/modules/settings/deployment-settings.service.ts +130 -23
- package/src/modules/settings/managed-repository.ts +68 -0
- package/src/modules/settings/repository-source.ts +197 -0
- package/src/modules/settings/setup.routes.ts +233 -19
- package/src/modules/skills/__tests__/allowed-tools-check.test.ts +11 -10
- package/src/modules/skills/__tests__/allowed-tools-warn.tools.test.ts +4 -3
- package/src/modules/skills/__tests__/pending-skills.service.test.ts +3 -1
- package/src/modules/skills/__tests__/skill-access-requests.routes.test.ts +7 -2
- package/src/modules/skills/__tests__/skills.routes.warnings.test.ts +2 -1
- package/src/modules/skills/__tests__/skills.service.test.ts +3 -2
- package/src/modules/skills/allowed-tools-check.ts +7 -6
- package/src/modules/skills/pending-skills.service.ts +9 -8
- package/src/modules/skills/skill-access-requests.routes.ts +29 -79
- package/src/modules/skills/skills.routes.ts +4 -3
- package/src/modules/skills/skills.service.ts +13 -9
- package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +3 -2
- package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +3 -2
- package/src/modules/tool-helpers/tool-context.ts +15 -0
- package/src/modules/tool-manuals/__tests__/mcp-json-discovery.test.ts +17 -12
- package/src/modules/tool-manuals/__tests__/mcp-server-edit.service.test.ts +2 -1
- package/src/modules/tool-manuals/__tests__/pending-tools.service.test.ts +4 -1
- package/src/modules/tool-manuals/__tests__/tool-delete.service.test.ts +2 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.archive.route.test.ts +2 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.cli.test.ts +5 -4
- package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +2 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.invalid.routes.test.ts +4 -2
- package/src/modules/tool-manuals/__tests__/tool-manuals.invalid.test.ts +13 -5
- package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +2 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.restart.test.ts +9 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +3 -2
- package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +2 -0
- package/src/modules/tool-manuals/mcp-json-discovery.ts +6 -4
- package/src/modules/tool-manuals/mcp-server-edit.service.ts +13 -11
- package/src/modules/tool-manuals/pending-tools.service.ts +19 -16
- package/src/modules/tool-manuals/tool-delete.service.ts +13 -10
- package/src/modules/tool-manuals/tool-manuals.routes.ts +10 -8
- package/src/modules/tool-manuals/tool-manuals.service.ts +15 -13
- package/src/modules/tool-manuals/tool-manuals.tools.ts +7 -6
- package/src/modules/workflow/__tests__/apply-failure.test.ts +11 -2
- package/src/modules/workflow/__tests__/merge-announces-tree.test.ts +14 -26
- package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +2 -1
- package/src/modules/workflow/__tests__/session-ontology.service.test.ts +3 -2
- package/src/modules/workflow/__tests__/workflow.routes.lock-path.test.ts +2 -1
- package/src/modules/workflow/__tests__/workflow.service.branch-in-use.test.ts +3 -10
- package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +2 -1
- package/src/modules/workflow/__tests__/workflow.service.deleted-branch-sweep.test.ts +3 -10
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +187 -35
- package/src/modules/workflow/__tests__/workflow.service.folder-proposals.test.ts +2 -1
- package/src/modules/workflow/__tests__/workflow.service.platform-restore.test.ts +2 -1
- package/src/modules/workflow/__tests__/workflow.service.read-gate.test.ts +3 -2
- package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +2 -1
- package/src/modules/workflow/__tests__/workflow.service.sync.test.ts +5 -4
- package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +148 -41
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +143 -2
- package/src/modules/workflow/agent-tools/workflow.tools.ts +60 -12
- package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +5 -4
- package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +12 -11
- package/src/modules/workflow/git/__tests__/git.service.commitChanges.test.ts +9 -8
- package/src/modules/workflow/git/__tests__/git.service.commitFile.strayPath.test.ts +8 -7
- package/src/modules/workflow/git/__tests__/git.service.commitFile.test.ts +6 -5
- package/src/modules/workflow/git/__tests__/git.service.createBranch.test.ts +3 -2
- package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +3 -2
- package/src/modules/workflow/git/__tests__/git.service.diffFileAtCommit.test.ts +7 -6
- package/src/modules/workflow/git/__tests__/git.service.diffFileBetweenBranches.test.ts +16 -15
- package/src/modules/workflow/git/__tests__/git.service.fileContentsAtCommit.test.ts +3 -2
- package/src/modules/workflow/git/__tests__/git.service.forkPoint.test.ts +2 -1
- package/src/modules/workflow/git/__tests__/git.service.history-guards.test.ts +2 -1
- package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +10 -9
- package/src/modules/workflow/git/__tests__/git.service.listTrackedFiles.test.ts +2 -1
- package/src/modules/workflow/git/__tests__/git.service.logForFile.test.ts +6 -5
- package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +9 -8
- package/src/modules/workflow/git/__tests__/git.service.pendingChanges.test.ts +2 -1
- package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +4 -3
- package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +130 -8
- package/src/modules/workflow/git/__tests__/git.service.readFileAtRef.test.ts +2 -1
- package/src/modules/workflow/git/__tests__/git.service.revertPathsAndPush.test.ts +2 -1
- package/src/modules/workflow/git/__tests__/git.service.status.test.ts +4 -3
- package/src/modules/workflow/git/__tests__/git.service.syncFromRemote.test.ts +8 -7
- package/src/modules/workflow/git/__tests__/node-git-runner.test.ts +41 -3
- package/src/modules/workflow/git/__tests__/pull-request.service.getPrDetail.test.ts +145 -2
- package/src/modules/workflow/git/__tests__/pull-request.service.viewer-can-delete.test.ts +166 -0
- package/src/modules/workflow/git/git.service.ts +49 -17
- package/src/modules/workflow/git/node-git-runner.ts +43 -4
- package/src/modules/workflow/git/pull-request.service.ts +119 -0
- package/src/modules/workflow/review-workflow/review-workflow.service.ts +9 -6
- package/src/modules/workflow/session-ontology.service.ts +7 -2
- package/src/modules/workflow/workflow.routes.ts +3 -1
- package/src/modules/workflow/workflow.service.ts +201 -76
- package/src/modules/workspace/__tests__/file-stat-access.test.ts +3 -2
- package/src/modules/workspace/__tests__/git-internals.security.test.ts +10 -9
- package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +4 -2
- package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +3 -2
- package/src/modules/workspace/__tests__/workspace.routes.branch-errors.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.routes.download-implies-read.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.routes.file-writes.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.routes.folders.test.ts +5 -4
- package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.ensure-remotes-fetched.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.service.list-cloned.test.ts +6 -5
- package/src/modules/workspace/__tests__/workspace.service.move-never-overwrites.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.test.ts +84 -50
- package/src/modules/workspace/__tests__/workspace.service.unknown-branch.test.ts +45 -1
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +10 -7
- package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +237 -10
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +44 -11
- package/src/modules/workspace/__tests__/write-denial.test.ts +5 -4
- package/src/modules/workspace/session-ontology.gate.ts +6 -4
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.degraded.test.ts +6 -2
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +240 -21
- package/src/modules/workspace/startup/kb-git.ts +15 -22
- package/src/modules/workspace/startup/kb-startup-runner.ts +198 -45
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +104 -98
- package/src/modules/workspace/startup/steps/groups-to-plugins.step.ts +24 -16
- package/src/modules/workspace/startup/steps/personal-spaces.step.ts +14 -5
- package/src/modules/workspace/startup/steps/plugin-display-names.step.ts +13 -5
- package/src/modules/workspace/startup/steps/plugin-manifests.step.ts +14 -5
- package/src/modules/workspace/startup/steps/seed-tree.ts +11 -9
- package/src/modules/workspace/startup/steps/template-files.step.ts +43 -34
- package/src/modules/workspace/startup/steps/template-source.ts +8 -5
- package/src/modules/workspace/workspace.routes.ts +8 -7
- package/src/modules/workspace/workspace.service.ts +47 -28
- package/src/modules/workspace/workspace.tools.ts +56 -20
- package/src/modules/workspace/write-denial.ts +7 -5
- package/src/shared/__tests__/kb-layout.plugin.test.ts +19 -16
- package/src/shared/domain-errors.ts +58 -0
- package/src/shared/git.contract.ts +80 -8
- package/src/shared/kb-context.ts +130 -0
- package/src/shared/kb-layout.test.ts +37 -27
- package/src/shared/kb-layout.ts +4 -3
- package/src/shared/pending-proposals.ts +7 -4
- package/src/shared/redact-secret.ts +5 -5
- package/src/tenancy/__tests__/static-tenant-source.test.ts +177 -0
- package/src/tenancy/__tests__/tenant-host.test.ts +372 -0
- package/src/tenancy/__tests__/tenant-runtime.test.ts +221 -0
- package/src/tenancy/__tests__/tenant-secrets.test.ts +35 -0
- package/src/tenancy/index.ts +35 -0
- package/src/tenancy/static-tenant-source.ts +296 -0
- package/src/tenancy/tenant-host.ts +261 -0
- package/src/tenancy/tenant-runtime.ts +208 -0
- package/src/tenancy/tenant-secrets.ts +41 -0
- package/src/tenancy/tenant-source.contract.ts +59 -0
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
import { ontologyOf } from '../../shared/kb-layout.js';
|
|
25
|
+
import type { KbContext } from '../../shared/kb-context.js';
|
|
25
26
|
import type { JsonSchema } from '../tool-registry/tool.contract.js';
|
|
26
27
|
import { ToolError, type ToolContext } from '../tool-helpers/tool.contract.js';
|
|
27
28
|
import type { ISessionOntologyService } from '../workflow/session-ontology.service.js';
|
|
@@ -75,7 +76,8 @@ export class MissingSessionError extends ToolError {
|
|
|
75
76
|
export interface SessionOntologyGate {
|
|
76
77
|
service: ISessionOntologyService;
|
|
77
78
|
enabled: boolean;
|
|
78
|
-
|
|
79
|
+
/** The checkout folder and the layout a path is classified under. */
|
|
80
|
+
kb: Pick<KbContext, 'kbDirName' | 'layout'>;
|
|
79
81
|
/** Lowercased email of the recovery/merge bot, which is exempt. */
|
|
80
82
|
recoveryBotEmail: string;
|
|
81
83
|
/**
|
|
@@ -103,7 +105,7 @@ function isAgentSource(ctx: ToolContext): boolean {
|
|
|
103
105
|
function resolveGatedSession(gate: SessionOntologyGate, ctx: ToolContext, wsPath: string): string | 'skip' {
|
|
104
106
|
if (!gate.enabled) return 'skip';
|
|
105
107
|
// Neutral paths never pin/record/block — skip before any identity work.
|
|
106
|
-
if (ontologyOf(wsPath, gate.kbDirName) === null) return 'skip';
|
|
108
|
+
if (ontologyOf(wsPath, gate.kb.layout, gate.kb.kbDirName) === null) return 'skip';
|
|
107
109
|
// Humans (UI routes) and browser-JWT callers never hit these tools; only
|
|
108
110
|
// agent tool calls are gated.
|
|
109
111
|
if (!isAgentSource(ctx)) return 'skip';
|
|
@@ -125,7 +127,7 @@ export async function recordOntologyRead(gate: SessionOntologyGate, ctx: ToolCon
|
|
|
125
127
|
const sessionId = resolveGatedSession(gate, ctx, wsPath);
|
|
126
128
|
if (sessionId === 'skip') return;
|
|
127
129
|
// checkOperation(isWrite=false) records the touch and always allows.
|
|
128
|
-
await gate.service.checkOperation(sessionId, wsPath, false, gate.kbDirName);
|
|
130
|
+
await gate.service.checkOperation(sessionId, wsPath, false, gate.kb.kbDirName);
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
/**
|
|
@@ -155,7 +157,7 @@ export async function assertOntologyWriteAllowed(
|
|
|
155
157
|
// Tracking stays core: record the (now-allowed) write's ontology touch.
|
|
156
158
|
// A blocked write never reaches this line, so it records nothing — same as
|
|
157
159
|
// before the hook split.
|
|
158
|
-
await gate.service.checkOperation(sessionId, wsPath, false, gate.kbDirName);
|
|
160
|
+
await gate.service.checkOperation(sessionId, wsPath, false, gate.kb.kbDirName);
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
/**
|
|
@@ -6,7 +6,7 @@ import os from 'node:os';
|
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
import { KbRemoteUnreachableError, KbStartupRunner } from '../kb-startup-runner.js';
|
|
8
8
|
import { NodeGitRunner } from '../../../workflow/git/node-git-runner.js';
|
|
9
|
-
import { GitRunError, type IGitRunner } from '../../../../shared/git.contract.js';
|
|
9
|
+
import { GitRunError, NO_GIT_CREDENTIALS, type IGitRunner } from '../../../../shared/git.contract.js';
|
|
10
10
|
import type { OnServerStart, ServerStartContext, StepResult } from '../on-server-start.js';
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -69,7 +69,6 @@ function makeRunner(steps: OnServerStart[], url: () => string, gitRunner: IGitRu
|
|
|
69
69
|
return new KbStartupRunner({
|
|
70
70
|
gitRunner,
|
|
71
71
|
kbRepoUrl: url,
|
|
72
|
-
gitUsername: () => 'x-access-token',
|
|
73
72
|
workspacesRoot,
|
|
74
73
|
kbDirName: 'knowledge-base',
|
|
75
74
|
templateDir: path.join(root, 'template'),
|
|
@@ -101,6 +100,7 @@ describe('KbStartupRunner with an unreachable remote', () => {
|
|
|
101
100
|
it('a git that never ran is not "unreachable" either: that failure is this host, and it stops the boot', async () => {
|
|
102
101
|
const noGit: IGitRunner = {
|
|
103
102
|
defaultTimeoutMs: 1000,
|
|
103
|
+
credentials: NO_GIT_CREDENTIALS,
|
|
104
104
|
run: (async () => {
|
|
105
105
|
throw new GitRunError('git ls-remote failed: spawn git ENOENT');
|
|
106
106
|
}) as IGitRunner['run'],
|
|
@@ -251,6 +251,7 @@ describe('KbStartupRunner with a remote that rejects the credentials', () => {
|
|
|
251
251
|
// re-dial a host that will never accept the token.
|
|
252
252
|
const rejecting: IGitRunner = {
|
|
253
253
|
defaultTimeoutMs: 1000,
|
|
254
|
+
credentials: NO_GIT_CREDENTIALS,
|
|
254
255
|
run: (async () => {
|
|
255
256
|
// The shape `NodeGitRunner` throws: git's words in the message (that
|
|
256
257
|
// is what the boot classifies) and again in `stderr`.
|
|
@@ -275,6 +276,7 @@ describe('KbStartupRunner retry after a boot that survived a rejected token', ()
|
|
|
275
276
|
let dials = 0;
|
|
276
277
|
const rejecting: IGitRunner = {
|
|
277
278
|
defaultTimeoutMs: 1000,
|
|
279
|
+
credentials: NO_GIT_CREDENTIALS,
|
|
278
280
|
run: (async () => {
|
|
279
281
|
dials += 1;
|
|
280
282
|
const said = "fatal: Authentication failed for 'https://example.com/acme/kb.git/'";
|
|
@@ -319,6 +321,7 @@ describe('KbStartupRunner retry when the token is rejected while it sleeps', ()
|
|
|
319
321
|
let dials = 0;
|
|
320
322
|
const rejecting: IGitRunner = {
|
|
321
323
|
defaultTimeoutMs: 1000,
|
|
324
|
+
credentials: NO_GIT_CREDENTIALS,
|
|
322
325
|
run: (async () => {
|
|
323
326
|
dials += 1;
|
|
324
327
|
const said = "fatal: Authentication failed for 'https://example.com/acme/kb.git/'";
|
|
@@ -331,6 +334,7 @@ describe('KbStartupRunner retry when the token is rejected while it sleeps', ()
|
|
|
331
334
|
let current: IGitRunner = new NodeGitRunner();
|
|
332
335
|
const switching: IGitRunner = {
|
|
333
336
|
defaultTimeoutMs: 1000,
|
|
337
|
+
credentials: NO_GIT_CREDENTIALS,
|
|
334
338
|
run: ((...args: Parameters<IGitRunner['run']>) => current.run(...args)) as IGitRunner['run'],
|
|
335
339
|
};
|
|
336
340
|
let url = path.join(root, 'nowhere.git');
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
+
import { testKbContext } from '../../../../__tests__/kb-context.js';
|
|
2
3
|
import { NodeFs } from '../../../kb-fs/node-fs.js';
|
|
3
4
|
import { execFile } from 'node:child_process';
|
|
4
5
|
import { promisify } from 'node:util';
|
|
@@ -9,8 +10,18 @@ import { KbStartupRunner } from '../kb-startup-runner.js';
|
|
|
9
10
|
import { WorkspaceService } from '../../workspace.service.js';
|
|
10
11
|
import { NodeGitRunner } from '../../../workflow/git/node-git-runner.js';
|
|
11
12
|
import { ClassifiedFailure, classifyGitFailure, failureOf } from '../../../../shared/git-failure.js';
|
|
13
|
+
import { gitCredentials } from '../../../../shared/git.contract.js';
|
|
12
14
|
import type { OnServerStart, ServerStartContext, StepResult } from '../on-server-start.js';
|
|
13
15
|
|
|
16
|
+
/**
|
|
17
|
+
* The token in effect for the runners these suites build, changed by the
|
|
18
|
+
* cases that need one — the way the setup screen changes it on a running
|
|
19
|
+
* deployment: through the provider the runner reads on every call, never
|
|
20
|
+
* through this process's environment.
|
|
21
|
+
*/
|
|
22
|
+
let token: string | null = null;
|
|
23
|
+
const credentials = gitCredentials('x-access-token', () => token);
|
|
24
|
+
|
|
14
25
|
const execFileAsync = promisify(execFile);
|
|
15
26
|
|
|
16
27
|
const PROTECTED = ['current-company-state', 'target-company-state'];
|
|
@@ -65,10 +76,10 @@ function makeRunner(steps: OnServerStart[], overrides: Partial<Parameters<typeof
|
|
|
65
76
|
|
|
66
77
|
function runnerOpts(steps: OnServerStart[], overrides: Record<string, unknown> = {}) {
|
|
67
78
|
return {
|
|
68
|
-
gitRunner: new NodeGitRunner(),
|
|
79
|
+
gitRunner: new NodeGitRunner(undefined, credentials),
|
|
69
80
|
kbRepoUrl: () => upstream,
|
|
70
|
-
gitUsername: () => 'x-access-token',
|
|
71
81
|
workspacesRoot,
|
|
82
|
+
setAsideRoot: path.join(root, 'set-aside'),
|
|
72
83
|
kbDirName: 'knowledge-base',
|
|
73
84
|
templateDir: path.join(root, 'template'),
|
|
74
85
|
defaultBranch: () => DEFAULT_BRANCH,
|
|
@@ -93,6 +104,216 @@ async function checkout(branch: string): Promise<string> {
|
|
|
93
104
|
return dir;
|
|
94
105
|
}
|
|
95
106
|
|
|
107
|
+
/**
|
|
108
|
+
* The configured repository was replaced while working copies of the old one
|
|
109
|
+
* were still on disk. A clone fetches through its OWN stored address, so
|
|
110
|
+
* every one of them kept asking the repository that was gone: the boot
|
|
111
|
+
* stopped on "repository not found" and took the setup screen with it.
|
|
112
|
+
*/
|
|
113
|
+
describe('KbStartupRunner — the repository was replaced', () => {
|
|
114
|
+
const touchDefault = step('touch', async (ctx) => {
|
|
115
|
+
await (await ctx.defaultBranch()).repoDir();
|
|
116
|
+
return { outcome: 'ok' };
|
|
117
|
+
});
|
|
118
|
+
const cloneDir = (branch: string) => path.join(workspacesRoot, encodeURIComponent(branch), 'knowledge-base');
|
|
119
|
+
|
|
120
|
+
/** A second, unrelated repository with the same branch names. */
|
|
121
|
+
async function replacementUpstream(): Promise<string> {
|
|
122
|
+
const other = path.join(root, 'replacement.git');
|
|
123
|
+
await git(root, ['init', '--bare', '-b', DEFAULT_BRANCH, other]);
|
|
124
|
+
const seed = path.join(root, '.seed-replacement');
|
|
125
|
+
await fs.mkdir(seed);
|
|
126
|
+
await git(seed, ['init', '-b', DEFAULT_BRANCH]);
|
|
127
|
+
await fs.writeFile(path.join(seed, 'marker.txt'), 'replacement', 'utf8');
|
|
128
|
+
await git(seed, ['add', '-A']);
|
|
129
|
+
await git(seed, ['commit', '-m', 'init']);
|
|
130
|
+
await git(seed, ['branch', PROTECTED[1]!]);
|
|
131
|
+
await git(seed, ['remote', 'add', 'origin', other]);
|
|
132
|
+
await git(seed, ['push', 'origin', ...PROTECTED]);
|
|
133
|
+
return other;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Boot once against the first repository, and leave a draft's clone beside it. */
|
|
137
|
+
async function bootedOnTheOldRepository(): Promise<void> {
|
|
138
|
+
await populatedUpstream();
|
|
139
|
+
await makeRunner([touchDefault]).runAll();
|
|
140
|
+
await fs.mkdir(path.dirname(cloneDir('someone/draft')), { recursive: true });
|
|
141
|
+
await git(root, ['clone', '-b', DEFAULT_BRANCH, upstream, cloneDir('someone/draft')]);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Where one run set its working copies aside: the single dated folder under the root. */
|
|
145
|
+
async function setAside(): Promise<string> {
|
|
146
|
+
const runs = await fs.readdir(path.join(root, 'set-aside'));
|
|
147
|
+
expect(runs).toHaveLength(1);
|
|
148
|
+
return path.join(root, 'set-aside', runs[0]!);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
it('clones the new repository in place of the old one\'s clones, even with the old one gone', async () => {
|
|
152
|
+
await bootedOnTheOldRepository();
|
|
153
|
+
const replacement = await replacementUpstream();
|
|
154
|
+
// Gone, as it was in production: any fetch through the old address fails.
|
|
155
|
+
await fs.rm(upstream, { recursive: true, force: true });
|
|
156
|
+
|
|
157
|
+
await makeRunner([touchDefault], { kbRepoUrl: () => replacement }).runAll();
|
|
158
|
+
|
|
159
|
+
const repo = cloneDir(DEFAULT_BRANCH);
|
|
160
|
+
expect((await git(repo, ['config', '--get', 'remote.origin.url'])).trim()).toBe(replacement);
|
|
161
|
+
expect(await fs.readFile(path.join(repo, 'marker.txt'), 'utf8')).toBe('replacement');
|
|
162
|
+
// A clone this boot had no reason to touch leaves the workspaces root
|
|
163
|
+
// too: the workspace service would otherwise adopt it and fetch from the
|
|
164
|
+
// old address.
|
|
165
|
+
await expect(fs.access(cloneDir('someone/draft'))).rejects.toThrow();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* The old repository is GONE, so its clones are the last copy of what it
|
|
170
|
+
* held, and the commit nobody pushed exists nowhere else at all. They
|
|
171
|
+
* leave the workspaces root and nothing else happens to them.
|
|
172
|
+
*/
|
|
173
|
+
it('sets the old repository\'s clones aside whole, unpushed work included, and deletes nothing', async () => {
|
|
174
|
+
await bootedOnTheOldRepository();
|
|
175
|
+
const old = cloneDir(DEFAULT_BRANCH);
|
|
176
|
+
await fs.writeFile(path.join(old, 'unpushed.md'), 'the only copy', 'utf8');
|
|
177
|
+
await git(old, ['add', '-A']);
|
|
178
|
+
await git(old, ['commit', '-m', 'never pushed']);
|
|
179
|
+
const head = (await git(old, ['rev-parse', 'HEAD'])).trim();
|
|
180
|
+
const replacement = await replacementUpstream();
|
|
181
|
+
await fs.rm(upstream, { recursive: true, force: true });
|
|
182
|
+
|
|
183
|
+
await makeRunner([touchDefault], { kbRepoUrl: () => replacement }).runAll();
|
|
184
|
+
|
|
185
|
+
const kept = await setAside();
|
|
186
|
+
const keptDefault = path.join(kept, encodeURIComponent(DEFAULT_BRANCH));
|
|
187
|
+
expect((await git(keptDefault, ['rev-parse', 'HEAD'])).trim()).toBe(head);
|
|
188
|
+
expect(await fs.readFile(path.join(keptDefault, 'unpushed.md'), 'utf8')).toBe('the only copy');
|
|
189
|
+
expect(await fs.readFile(path.join(keptDefault, 'marker.txt'), 'utf8')).toBe('seeded');
|
|
190
|
+
// The draft's clone too, under its own workspace's name.
|
|
191
|
+
await expect(fs.access(path.join(kept, encodeURIComponent('someone/draft'), '.git'))).resolves.toBeUndefined();
|
|
192
|
+
// And the probe that compared the histories left no refs behind in it.
|
|
193
|
+
expect((await git(keptDefault, ['for-each-ref', 'refs/hexis-probe/'])).trim()).toBe('');
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* The shipped compose files mount the backups root as a volume of its own,
|
|
198
|
+
* where a rename across to it is refused. That is the path production
|
|
199
|
+
* takes: a copy, and the original removed only once the copy is whole.
|
|
200
|
+
*/
|
|
201
|
+
it('sets a clone aside across volumes, by copying it whole', async () => {
|
|
202
|
+
await bootedOnTheOldRepository();
|
|
203
|
+
const old = cloneDir(DEFAULT_BRANCH);
|
|
204
|
+
await fs.writeFile(path.join(old, 'unpushed.md'), 'the only copy', 'utf8');
|
|
205
|
+
await git(old, ['add', '-A']);
|
|
206
|
+
await git(old, ['commit', '-m', 'never pushed']);
|
|
207
|
+
const head = (await git(old, ['rev-parse', 'HEAD'])).trim();
|
|
208
|
+
const replacement = await replacementUpstream();
|
|
209
|
+
await fs.rm(upstream, { recursive: true, force: true });
|
|
210
|
+
const crossDevice = Object.assign(new Error('EXDEV: cross-device link not permitted'), { code: 'EXDEV' });
|
|
211
|
+
const rename = vi.spyOn(fs, 'rename').mockRejectedValue(crossDevice);
|
|
212
|
+
try {
|
|
213
|
+
await makeRunner([touchDefault], { kbRepoUrl: () => replacement }).runAll();
|
|
214
|
+
} finally {
|
|
215
|
+
rename.mockRestore();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const keptDefault = path.join(await setAside(), encodeURIComponent(DEFAULT_BRANCH));
|
|
219
|
+
expect((await git(keptDefault, ['rev-parse', 'HEAD'])).trim()).toBe(head);
|
|
220
|
+
expect(await fs.readFile(path.join(keptDefault, 'unpushed.md'), 'utf8')).toBe('the only copy');
|
|
221
|
+
expect(await fs.readFile(path.join(cloneDir(DEFAULT_BRANCH), 'marker.txt'), 'utf8')).toBe('replacement');
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* A clone that cannot be set aside stays exactly where it is, and the boot
|
|
226
|
+
* stops saying why: deleting it to get past would be the one outcome this
|
|
227
|
+
* whole path exists to rule out.
|
|
228
|
+
*/
|
|
229
|
+
it('deletes nothing when a clone cannot be set aside, and says why', async () => {
|
|
230
|
+
await bootedOnTheOldRepository();
|
|
231
|
+
const old = cloneDir(DEFAULT_BRANCH);
|
|
232
|
+
const head = (await git(old, ['rev-parse', 'HEAD'])).trim();
|
|
233
|
+
const replacement = await replacementUpstream();
|
|
234
|
+
await fs.rm(upstream, { recursive: true, force: true });
|
|
235
|
+
const rename = vi.spyOn(fs, 'rename').mockRejectedValue(Object.assign(new Error('EXDEV'), { code: 'EXDEV' }));
|
|
236
|
+
const cp = vi.spyOn(fs, 'cp').mockRejectedValue(Object.assign(new Error('ENOSPC: no space left on device'), { code: 'ENOSPC' }));
|
|
237
|
+
try {
|
|
238
|
+
await expect(makeRunner([touchDefault], { kbRepoUrl: () => replacement }).runAll()).rejects.toThrow(
|
|
239
|
+
/Could not set aside the working copy.*no space left.*Nothing was deleted/s,
|
|
240
|
+
);
|
|
241
|
+
} finally {
|
|
242
|
+
rename.mockRestore();
|
|
243
|
+
cp.mockRestore();
|
|
244
|
+
}
|
|
245
|
+
expect((await git(old, ['rev-parse', 'HEAD'])).trim()).toBe(head);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* The one change the setup screen tells an admin to make: the same
|
|
250
|
+
* repository, moved. The clone is pointed at the new address and kept, and
|
|
251
|
+
* the commit that was never pushed goes on to be pushed there.
|
|
252
|
+
*/
|
|
253
|
+
it('keeps a clone of the same repository at a new address, and points it there', async () => {
|
|
254
|
+
await bootedOnTheOldRepository();
|
|
255
|
+
const repo = cloneDir(DEFAULT_BRANCH);
|
|
256
|
+
await fs.writeFile(path.join(repo, 'unpushed.md'), 'local work', 'utf8');
|
|
257
|
+
await git(repo, ['add', '-A']);
|
|
258
|
+
await git(repo, ['commit', '-m', 'local work']);
|
|
259
|
+
const head = (await git(repo, ['rev-parse', 'HEAD'])).trim();
|
|
260
|
+
// Moved: everything the old address held is at the new one, and the old
|
|
261
|
+
// one answers nothing any more.
|
|
262
|
+
const moved = path.join(root, 'moved.git');
|
|
263
|
+
await git(root, ['clone', '--bare', upstream, moved]);
|
|
264
|
+
await fs.rm(upstream, { recursive: true, force: true });
|
|
265
|
+
|
|
266
|
+
await makeRunner([touchDefault], { kbRepoUrl: () => moved }).runAll();
|
|
267
|
+
|
|
268
|
+
expect((await git(repo, ['config', '--get', 'remote.origin.url'])).trim()).toBe(moved);
|
|
269
|
+
expect((await git(repo, ['rev-parse', 'HEAD'])).trim()).toBe(head);
|
|
270
|
+
expect((await git(cloneDir('someone/draft'), ['config', '--get', 'remote.origin.url'])).trim()).toBe(moved);
|
|
271
|
+
expect((await git(repo, ['for-each-ref', 'refs/hexis-probe/'])).trim()).toBe('');
|
|
272
|
+
// Nothing was another repository's, so nothing was set aside.
|
|
273
|
+
await expect(fs.access(path.join(root, 'set-aside'))).rejects.toThrow();
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it('leaves a clone of the configured repository alone, unpushed work included', async () => {
|
|
277
|
+
await bootedOnTheOldRepository();
|
|
278
|
+
const repo = cloneDir(DEFAULT_BRANCH);
|
|
279
|
+
await fs.writeFile(path.join(repo, 'unpushed.md'), 'local work', 'utf8');
|
|
280
|
+
await git(repo, ['add', '-A']);
|
|
281
|
+
await git(repo, ['commit', '-m', 'local work']);
|
|
282
|
+
const head = (await git(repo, ['rev-parse', 'HEAD'])).trim();
|
|
283
|
+
|
|
284
|
+
await makeRunner([touchDefault]).runAll();
|
|
285
|
+
|
|
286
|
+
expect((await git(repo, ['rev-parse', 'HEAD'])).trim()).toBe(head);
|
|
287
|
+
await expect(fs.access(cloneDir('someone/draft'))).resolves.toBeUndefined();
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('does not take a different spelling of the same address for another repository', async () => {
|
|
291
|
+
await bootedOnTheOldRepository();
|
|
292
|
+
const repo = cloneDir(DEFAULT_BRANCH);
|
|
293
|
+
await fs.writeFile(path.join(repo, 'unpushed.md'), 'local work', 'utf8');
|
|
294
|
+
await git(repo, ['add', '-A']);
|
|
295
|
+
await git(repo, ['commit', '-m', 'local work']);
|
|
296
|
+
const head = (await git(repo, ['rev-parse', 'HEAD'])).trim();
|
|
297
|
+
|
|
298
|
+
// `upstream` ends in `.git`; the same repository without it, and with a
|
|
299
|
+
// trailing slash.
|
|
300
|
+
await makeRunner([touchDefault], { kbRepoUrl: () => `${upstream.replace(/\.git$/, '')}/` }).runAll().catch(() => {});
|
|
301
|
+
|
|
302
|
+
expect((await git(repo, ['rev-parse', 'HEAD'])).trim()).toBe(head);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('keeps every clone when the configured repository cannot be reached', async () => {
|
|
306
|
+
// A typo in the address must not cost the working copies: the sweep runs
|
|
307
|
+
// only once the configured remote has answered.
|
|
308
|
+
await bootedOnTheOldRepository();
|
|
309
|
+
await expect(
|
|
310
|
+
makeRunner([touchDefault], { kbRepoUrl: () => path.join(root, 'no-such-repository.git') }).runAll(),
|
|
311
|
+
).rejects.toThrow();
|
|
312
|
+
await expect(fs.access(path.join(cloneDir(DEFAULT_BRANCH), '.git'))).resolves.toBeUndefined();
|
|
313
|
+
await expect(fs.access(cloneDir('someone/draft'))).resolves.toBeUndefined();
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
|
|
96
317
|
describe('KbStartupRunner', () => {
|
|
97
318
|
it('seeds an empty remote with every protected branch before any step runs', async () => {
|
|
98
319
|
const seen: string[] = [];
|
|
@@ -486,7 +707,7 @@ describe('KbStartupRunner — what a failed phase throws', () => {
|
|
|
486
707
|
try {
|
|
487
708
|
const err = await makeRunner([step('noop', async () => ({ outcome: 'ok' }))], {
|
|
488
709
|
kbRepoUrl: () => 'https://127.0.0.1:1/kb.git?X-Amz-Signature=SECRETSIG',
|
|
489
|
-
|
|
710
|
+
gitRunner: new NodeGitRunner(undefined, gitCredentials('x-access-token', 'access')),
|
|
490
711
|
})
|
|
491
712
|
.runAll()
|
|
492
713
|
.then(
|
|
@@ -518,7 +739,7 @@ describe('KbStartupRunner redaction', () => {
|
|
|
518
739
|
throw new Error('the host said ghp_settingsonly42 is not welcome');
|
|
519
740
|
}),
|
|
520
741
|
],
|
|
521
|
-
{
|
|
742
|
+
{ gitRunner: new NodeGitRunner(undefined, gitCredentials('x-access-token', 'ghp_settingsonly42')) },
|
|
522
743
|
);
|
|
523
744
|
const err = await runner.runAll().then(
|
|
524
745
|
() => null,
|
|
@@ -540,10 +761,8 @@ describe('KbStartupRunner credentials', () => {
|
|
|
540
761
|
// the repo with nothing, so every later push prompts for a username, finds
|
|
541
762
|
// no tty, and dies — commits pile up locally and reach the remote never.
|
|
542
763
|
// Only real git tells the two spellings apart, so this drives real git.
|
|
543
|
-
const ORIGINAL = process.env.GITHUB_TOKEN;
|
|
544
764
|
afterEach(() => {
|
|
545
|
-
|
|
546
|
-
else process.env.GITHUB_TOKEN = ORIGINAL;
|
|
765
|
+
token = null;
|
|
547
766
|
});
|
|
548
767
|
|
|
549
768
|
|
|
@@ -561,7 +780,7 @@ describe('KbStartupRunner credentials', () => {
|
|
|
561
780
|
}
|
|
562
781
|
|
|
563
782
|
it('leaves the boot clone able to authenticate a push of its own', async () => {
|
|
564
|
-
|
|
783
|
+
token = 'ghp_boot';
|
|
565
784
|
await populatedUpstream();
|
|
566
785
|
// The branch handle clones lazily, so a step has to actually reach for the
|
|
567
786
|
// repo before there is anything on disk to inspect.
|
|
@@ -585,7 +804,7 @@ describe('KbStartupRunner credentials', () => {
|
|
|
585
804
|
// path (`--replace-all`), so drift a second value in out of band and let
|
|
586
805
|
// WorkspaceService adopt the clone — that is the code the guarantee is
|
|
587
806
|
// about.
|
|
588
|
-
|
|
807
|
+
token = 'ghp_boot';
|
|
589
808
|
await populatedUpstream();
|
|
590
809
|
const repo = await materializeDefaultBranchClone();
|
|
591
810
|
// App-shaped drift: a second stamp of OURS with a stale username — the
|
|
@@ -594,7 +813,7 @@ describe('KbStartupRunner credentials', () => {
|
|
|
594
813
|
await git(repo, ['config', '--add', 'credential.helper',
|
|
595
814
|
'!f() { echo "username=stale-user"; echo "password=$GITHUB_TOKEN"; }; f']);
|
|
596
815
|
|
|
597
|
-
const ws = new WorkspaceService(workspacesRoot, upstream,
|
|
816
|
+
const ws = new WorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs(), new NodeGitRunner(undefined, credentials));
|
|
598
817
|
await ws.getOrCreateForBranch(DEFAULT_BRANCH);
|
|
599
818
|
|
|
600
819
|
const all = (await git(repo, ['config', '--local', '--get-all', 'credential.helper'])).trim();
|
|
@@ -607,19 +826,19 @@ describe('KbStartupRunner credentials', () => {
|
|
|
607
826
|
// git chains every configured helper, so an operator's clone-local
|
|
608
827
|
// `cache`/`store`/custom helper coexists with ours — and losing it on a
|
|
609
828
|
// token change would break the very fallback auth they set up.
|
|
610
|
-
|
|
829
|
+
token = 'ghp_boot';
|
|
611
830
|
await populatedUpstream();
|
|
612
831
|
const repo = await materializeDefaultBranchClone();
|
|
613
832
|
await git(repo, ['config', '--add', 'credential.helper', 'cache --timeout=300']);
|
|
614
833
|
|
|
615
|
-
const ws = new WorkspaceService(workspacesRoot, upstream,
|
|
834
|
+
const ws = new WorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs(), new NodeGitRunner(undefined, credentials));
|
|
616
835
|
await ws.getOrCreateForBranch(DEFAULT_BRANCH); // stamp with token
|
|
617
836
|
let all = (await git(repo, ['config', '--local', '--get-all', 'credential.helper'])).trim();
|
|
618
837
|
expect(all).toContain('cache --timeout=300');
|
|
619
838
|
expect(all).toContain('password=$GITHUB_TOKEN');
|
|
620
839
|
|
|
621
|
-
|
|
622
|
-
const ws2 =
|
|
840
|
+
token = null;
|
|
841
|
+
const ws2 =new WorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs(), new NodeGitRunner(undefined, credentials));
|
|
623
842
|
await ws2.getOrCreateForBranch(DEFAULT_BRANCH); // unset OUR helper only
|
|
624
843
|
all = (await git(repo, ['config', '--local', '--get-all', 'credential.helper'])).trim();
|
|
625
844
|
expect(all).toContain('cache --timeout=300');
|
|
@@ -630,12 +849,12 @@ describe('KbStartupRunner credentials', () => {
|
|
|
630
849
|
// A deployment that lost its token must not keep a clone-local helper
|
|
631
850
|
// answering with an empty password — it would shadow whatever fallback
|
|
632
851
|
// auth the operator switched to.
|
|
633
|
-
|
|
852
|
+
token = 'ghp_boot';
|
|
634
853
|
await populatedUpstream();
|
|
635
854
|
const repo = await materializeDefaultBranchClone(); // stamped
|
|
636
|
-
|
|
855
|
+
token = null;
|
|
637
856
|
|
|
638
|
-
const ws = new WorkspaceService(workspacesRoot, upstream,
|
|
857
|
+
const ws = new WorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs(), new NodeGitRunner(undefined, credentials));
|
|
639
858
|
await ws.getOrCreateForBranch(DEFAULT_BRANCH);
|
|
640
859
|
|
|
641
860
|
await expect(git(repo, ['config', '--local', '--get', 'credential.helper']))
|
|
@@ -646,13 +865,13 @@ describe('KbStartupRunner credentials', () => {
|
|
|
646
865
|
// The rotation gap: the setup screen can supply a token AFTER a branch
|
|
647
866
|
// was first opened, and the cached fast path returns before the adoption
|
|
648
867
|
// re-stamp. The fingerprint check must catch the change there.
|
|
649
|
-
|
|
868
|
+
token = null;
|
|
650
869
|
await populatedUpstream();
|
|
651
870
|
const repo = await materializeDefaultBranchClone(); // no helper
|
|
652
871
|
|
|
653
|
-
const ws = new WorkspaceService(workspacesRoot, upstream,
|
|
872
|
+
const ws = new WorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs(), new NodeGitRunner(undefined, credentials));
|
|
654
873
|
await ws.getOrCreateForBranch(DEFAULT_BRANCH); // adopt, tokenless
|
|
655
|
-
|
|
874
|
+
token = 'ghp_late';
|
|
656
875
|
await ws.getOrCreateForBranch(DEFAULT_BRANCH); // cached fast path
|
|
657
876
|
|
|
658
877
|
const helper = (await git(repo, ['config', '--local', '--get', 'credential.helper'])).trim();
|
|
@@ -661,7 +880,7 @@ describe('KbStartupRunner credentials', () => {
|
|
|
661
880
|
});
|
|
662
881
|
|
|
663
882
|
it('clones without a helper when the deployment has no token — an open remote still boots', async () => {
|
|
664
|
-
|
|
883
|
+
token = null;
|
|
665
884
|
await populatedUpstream();
|
|
666
885
|
const repo = await materializeDefaultBranchClone();
|
|
667
886
|
// `--get` exits 1 when the key is unset. Assert on that exit code rather
|
|
@@ -29,12 +29,13 @@ const STARTUP_GIT_TIMEOUT_MS = 600_000;
|
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Per-invocation `-c` config. Long paths always (Windows checkouts of deep
|
|
32
|
-
* KB trees); when a token
|
|
33
|
-
* it from the environment at call time — the secret never
|
|
32
|
+
* KB trees); when the runner carries a token, an inline credential helper
|
|
33
|
+
* that reads it from the child's environment at call time — the secret never
|
|
34
|
+
* appears in argv.
|
|
34
35
|
*/
|
|
35
|
-
function credArgs(
|
|
36
|
+
function credArgs(runner: IGitRunner): string[] {
|
|
36
37
|
const args = ['-c', 'core.longpaths=true'];
|
|
37
|
-
const helper = credentialHelperValue(
|
|
38
|
+
const helper = credentialHelperValue(runner.credentials);
|
|
38
39
|
if (helper) args.push('-c', `credential.helper=${helper}`);
|
|
39
40
|
return args;
|
|
40
41
|
}
|
|
@@ -49,18 +50,14 @@ function credArgs(gitUsername: string): string[] {
|
|
|
49
50
|
* clone to carry its own credentials. Persist them with `clone --config` (which
|
|
50
51
|
* only means "write into the new repo" after the subcommand) so it does.
|
|
51
52
|
*/
|
|
52
|
-
function withPersistedCloneConfig(
|
|
53
|
+
function withPersistedCloneConfig(runner: IGitRunner, args: string[]): string[] {
|
|
53
54
|
if (args[0] !== 'clone') return args;
|
|
54
|
-
return [args[0], ...cloneCredentialArgs(
|
|
55
|
+
return [args[0], ...cloneCredentialArgs(runner.credentials), ...args.slice(1)];
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
gitUsername: string,
|
|
61
|
-
args: string[],
|
|
62
|
-
): Promise<string> {
|
|
63
|
-
const argv = [...credArgs(gitUsername), ...withPersistedCloneConfig(gitUsername, args)];
|
|
58
|
+
/** Run one git command of the phase, authenticated with the runner's own credentials. */
|
|
59
|
+
export async function git(runner: IGitRunner, cwd: string, args: string[]): Promise<string> {
|
|
60
|
+
const argv = [...credArgs(runner), ...withPersistedCloneConfig(runner, args)];
|
|
64
61
|
try {
|
|
65
62
|
// A floor under the configured ceiling, not a replacement for it: an
|
|
66
63
|
// operator who raised GIT_TIMEOUT_MS past ten minutes gets that here too.
|
|
@@ -83,18 +80,14 @@ export async function git(
|
|
|
83
80
|
}
|
|
84
81
|
}
|
|
85
82
|
|
|
86
|
-
export async function stampIdentity(runner: IGitRunner, repo: string
|
|
87
|
-
await git(runner, repo,
|
|
88
|
-
await git(runner, repo,
|
|
83
|
+
export async function stampIdentity(runner: IGitRunner, repo: string): Promise<void> {
|
|
84
|
+
await git(runner, repo, ['config', 'user.name', BOT_NAME]);
|
|
85
|
+
await git(runner, repo, ['config', 'user.email', BOT_EMAIL]);
|
|
89
86
|
}
|
|
90
87
|
|
|
91
88
|
/** Branch names present on the remote, from `ls-remote --heads`. */
|
|
92
|
-
export async function lsRemoteHeads(
|
|
93
|
-
runner
|
|
94
|
-
repoUrl: string,
|
|
95
|
-
gitUsername: string,
|
|
96
|
-
): Promise<Set<string>> {
|
|
97
|
-
const out = await git(runner, os.tmpdir(), gitUsername, ['ls-remote', '--heads', repoUrl]);
|
|
89
|
+
export async function lsRemoteHeads(runner: IGitRunner, repoUrl: string): Promise<Set<string>> {
|
|
90
|
+
const out = await git(runner, os.tmpdir(), ['ls-remote', '--heads', repoUrl]);
|
|
98
91
|
const heads = new Set<string>();
|
|
99
92
|
for (const line of out.split('\n')) {
|
|
100
93
|
const m = /\srefs\/heads\/(.+)$/.exec(line.trim());
|