@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
|
@@ -3,7 +3,7 @@ import fs from 'node:fs/promises';
|
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { NodeGitRunner } from '../node-git-runner.js';
|
|
6
|
-
import { GitRunError, isGitTimeout } from '../../../../shared/git.contract.js';
|
|
6
|
+
import { GitRunError, gitCredentials, isGitTimeout } from '../../../../shared/git.contract.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* These run REAL git, like the rest of this module's suites: the behaviours
|
|
@@ -94,10 +94,48 @@ describe('NodeGitRunner', () => {
|
|
|
94
94
|
expect(true).toBe(true);
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
+
/**
|
|
98
|
+
* The helper the runner's callers stamp into a clone, reduced to the one
|
|
99
|
+
* thing under test here: what `$GITHUB_TOKEN` is in the child. `credential
|
|
100
|
+
* fill` runs it through git's own shell and prints what it answered, which
|
|
101
|
+
* is the same path a push takes to its password.
|
|
102
|
+
*/
|
|
103
|
+
const ECHO_TOKEN_HELPER = `!f() { printf '%s\\n' "username=u" "password=\${GITHUB_TOKEN-none}"; }; f`;
|
|
104
|
+
const fill = (runner: NodeGitRunner, env?: NodeJS.ProcessEnv) =>
|
|
105
|
+
runner.run(dir, ['-c', `credential.helper=${ECHO_TOKEN_HELPER}`, 'credential', 'fill'], {
|
|
106
|
+
input: 'protocol=https\nhost=example.test\n\n',
|
|
107
|
+
env,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('hands its token to the child, where the helper reads it, and never puts it in argv', async () => {
|
|
111
|
+
const runner = new NodeGitRunner(undefined, gitCredentials('x-access-token', 'ghp_child_secret'));
|
|
112
|
+
const { stdout } = await fill(runner);
|
|
113
|
+
expect(stdout).toContain('password=ghp_child_secret');
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('drops a token this process inherited: only the credentials in effect reach git', async () => {
|
|
117
|
+
const previous = process.env.GITHUB_TOKEN;
|
|
118
|
+
process.env.GITHUB_TOKEN = 'ghp_stale_in_process_env';
|
|
119
|
+
try {
|
|
120
|
+
const { stdout } = await fill(new NodeGitRunner());
|
|
121
|
+
expect(stdout).toContain('password=none');
|
|
122
|
+
expect(stdout).not.toContain('ghp_stale_in_process_env');
|
|
123
|
+
} finally {
|
|
124
|
+
if (previous === undefined) delete process.env.GITHUB_TOKEN;
|
|
125
|
+
else process.env.GITHUB_TOKEN = previous;
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('lets a per-call environment entry win over its own token: the setup probe checks the token it was given', async () => {
|
|
130
|
+
const runner = new NodeGitRunner(undefined, gitCredentials('x-access-token', 'ghp_in_effect'));
|
|
131
|
+
const { stdout } = await fill(runner, { GITHUB_TOKEN: 'ghp_being_checked' });
|
|
132
|
+
expect(stdout).toContain('password=ghp_being_checked');
|
|
133
|
+
});
|
|
134
|
+
|
|
97
135
|
it('keeps the configured git token out of failures', async () => {
|
|
98
|
-
const runner = new NodeGitRunner();
|
|
136
|
+
const runner = new NodeGitRunner(undefined, gitCredentials('x-access-token', 'ghp_secret_value_here'));
|
|
99
137
|
const previous = process.env.GITHUB_TOKEN;
|
|
100
|
-
process.env.GITHUB_TOKEN
|
|
138
|
+
delete process.env.GITHUB_TOKEN;
|
|
101
139
|
try {
|
|
102
140
|
const err = await runner
|
|
103
141
|
.run(dir, ['ls-remote', 'https://x-access-token:ghp_secret_value_here@127.0.0.1:1/r.git'], {
|
|
@@ -49,7 +49,13 @@ describe('PullRequestService.getPrDetail — git work per read', () => {
|
|
|
49
49
|
const resolvePrShas = vi.fn(async () => ({ baseSha: BASE, headSha: HEAD }));
|
|
50
50
|
const changedFilesForPr = vi.fn(async () => []);
|
|
51
51
|
const forkPointForPr = vi.fn(async () => ({ mergeBaseSha: FORK, behind: true }));
|
|
52
|
-
const
|
|
52
|
+
const pathsChangedBetween = vi.fn(async () => []);
|
|
53
|
+
const git = {
|
|
54
|
+
resolvePrShas,
|
|
55
|
+
changedFilesForPr,
|
|
56
|
+
forkPointForPr,
|
|
57
|
+
pathsChangedBetween,
|
|
58
|
+
} as unknown as GitService;
|
|
53
59
|
const workspace = {
|
|
54
60
|
findAnyWorkspaceId: async () => 'ws-main',
|
|
55
61
|
ensureRemotesFetched: async () => undefined,
|
|
@@ -63,7 +69,14 @@ describe('PullRequestService.getPrDetail — git work per read', () => {
|
|
|
63
69
|
getApprovalStates,
|
|
64
70
|
evaluateMergeGate: () => ({ mergeable: false, reasons: [], warnings: [] }),
|
|
65
71
|
});
|
|
66
|
-
return {
|
|
72
|
+
return {
|
|
73
|
+
svc,
|
|
74
|
+
resolvePrShas,
|
|
75
|
+
changedFilesForPr,
|
|
76
|
+
forkPointForPr,
|
|
77
|
+
pathsChangedBetween,
|
|
78
|
+
getApprovalStates,
|
|
79
|
+
};
|
|
67
80
|
}
|
|
68
81
|
|
|
69
82
|
it('pins the file list to the SHAs it just resolved, and keeps patches for a client read', async () => {
|
|
@@ -179,3 +192,133 @@ describe('PullRequestService — change request link', () => {
|
|
|
179
192
|
expect(detail?.urlNote).toBe('Set PUBLIC_FRONTEND_URL to get absolute links.');
|
|
180
193
|
});
|
|
181
194
|
});
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* `needsUpdate` — the answer the dialog acts on, as distinct from `behind`.
|
|
198
|
+
*
|
|
199
|
+
* `behind` is the honest git fact that the two branches have diverged. On a
|
|
200
|
+
* knowledge base where every shared save commits to the default branch it is
|
|
201
|
+
* true again minutes after every update, and acting on it made opening a
|
|
202
|
+
* request pay for a merge on almost every open — for changes to files the
|
|
203
|
+
* request does not contain. `needsUpdate` adds the half that matters: the
|
|
204
|
+
* target changed a file THIS request also changes.
|
|
205
|
+
*/
|
|
206
|
+
describe('PullRequestService.getPrDetail — needsUpdate', () => {
|
|
207
|
+
const FILE = 'Sales/Deal.md';
|
|
208
|
+
const OTHER = 'Ops/Runbook.md';
|
|
209
|
+
|
|
210
|
+
function harness(opts: {
|
|
211
|
+
behind?: boolean;
|
|
212
|
+
mergeBaseSha?: string | null;
|
|
213
|
+
files?: { path: string; previousPath?: string }[];
|
|
214
|
+
changedOnTarget?: string[];
|
|
215
|
+
changedOnTargetError?: Error;
|
|
216
|
+
state?: string;
|
|
217
|
+
} = {}) {
|
|
218
|
+
const resolvePrShas = vi.fn(async () => ({ baseSha: BASE, headSha: HEAD }));
|
|
219
|
+
const changedFilesForPr = vi.fn(async () => (opts.files ?? [{ path: FILE }]) as never);
|
|
220
|
+
const forkPointForPr = vi.fn(async () => ({
|
|
221
|
+
mergeBaseSha: opts.mergeBaseSha === undefined ? FORK : opts.mergeBaseSha,
|
|
222
|
+
behind: opts.behind ?? true,
|
|
223
|
+
}));
|
|
224
|
+
const pathsChangedBetween = opts.changedOnTargetError
|
|
225
|
+
? vi.fn().mockRejectedValue(opts.changedOnTargetError)
|
|
226
|
+
: vi.fn(async () => opts.changedOnTarget ?? []);
|
|
227
|
+
const git = {
|
|
228
|
+
resolvePrShas,
|
|
229
|
+
changedFilesForPr,
|
|
230
|
+
forkPointForPr,
|
|
231
|
+
pathsChangedBetween,
|
|
232
|
+
} as unknown as GitService;
|
|
233
|
+
const workspace = {
|
|
234
|
+
findAnyWorkspaceId: async () => 'ws-main',
|
|
235
|
+
ensureRemotesFetched: async () => undefined,
|
|
236
|
+
} as unknown as WorkspaceService;
|
|
237
|
+
const access = { canWriteAtRef: async () => false } as unknown as IAccessControl;
|
|
238
|
+
const db = {
|
|
239
|
+
select: () => ({
|
|
240
|
+
from: () => ({
|
|
241
|
+
where: () => ({ limit: async () => [{ ...ROW, state: opts.state ?? 'open' }] }),
|
|
242
|
+
}),
|
|
243
|
+
}),
|
|
244
|
+
} as unknown as Database;
|
|
245
|
+
const svc = new PullRequestService(db, workspace, access, git);
|
|
246
|
+
svc.setDetailEnricher({
|
|
247
|
+
listComments: async () => [],
|
|
248
|
+
getApprovalStates: async () => [],
|
|
249
|
+
evaluateMergeGate: () => ({ mergeable: false, reasons: [], warnings: [] }),
|
|
250
|
+
});
|
|
251
|
+
return { svc, pathsChangedBetween };
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
it('is false when the target moved in files this request does not change', async () => {
|
|
255
|
+
// The case that made the message appear on essentially every open: a
|
|
256
|
+
// shared save somewhere else in the knowledge base.
|
|
257
|
+
const h = harness({ files: [{ path: FILE }], changedOnTarget: [OTHER] });
|
|
258
|
+
const detail = await h.svc.getPrDetail(7, { fresh: true });
|
|
259
|
+
expect(detail?.behind).toBe(true);
|
|
260
|
+
expect(detail?.needsUpdate).toBe(false);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('is true when the target changed a file this request also changes', async () => {
|
|
264
|
+
const h = harness({ files: [{ path: FILE }], changedOnTarget: [OTHER, FILE] });
|
|
265
|
+
const detail = await h.svc.getPrDetail(7, { fresh: true });
|
|
266
|
+
expect(detail?.needsUpdate).toBe(true);
|
|
267
|
+
// Intersected over the fork point → the target's tip: the same two
|
|
268
|
+
// commits the rest of the detail is pinned to.
|
|
269
|
+
expect(h.pathsChangedBetween).toHaveBeenCalledWith('ws-main', FORK, BASE);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('asks git nothing at all when the request is not behind', async () => {
|
|
273
|
+
// The common case, and the one that has to stay free.
|
|
274
|
+
const h = harness({ behind: false });
|
|
275
|
+
const detail = await h.svc.getPrDetail(7, { fresh: true });
|
|
276
|
+
expect(detail?.needsUpdate).toBe(false);
|
|
277
|
+
expect(h.pathsChangedBetween).not.toHaveBeenCalled();
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('asks git nothing when the request changes no files', async () => {
|
|
281
|
+
const h = harness({ files: [], changedOnTarget: [FILE] });
|
|
282
|
+
const detail = await h.svc.getPrDetail(7, { fresh: true });
|
|
283
|
+
expect(detail?.needsUpdate).toBe(false);
|
|
284
|
+
expect(h.pathsChangedBetween).not.toHaveBeenCalled();
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('counts a file the target RENAMED, under either of its names', async () => {
|
|
288
|
+
// `pathsChangedBetween` runs without rename detection, so the target's
|
|
289
|
+
// rename reports the path it left as well as the one it arrived at — and
|
|
290
|
+
// a request still editing the old name is affected.
|
|
291
|
+
const h = harness({
|
|
292
|
+
files: [{ path: FILE }],
|
|
293
|
+
changedOnTarget: [FILE, 'Sales/Deal-2026.md'],
|
|
294
|
+
});
|
|
295
|
+
expect((await h.svc.getPrDetail(7, { fresh: true }))?.needsUpdate).toBe(true);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('counts a file THIS request renamed, under the name it came from', async () => {
|
|
299
|
+
const h = harness({
|
|
300
|
+
files: [{ path: 'Sales/Deal-final.md', previousPath: FILE }],
|
|
301
|
+
changedOnTarget: [FILE],
|
|
302
|
+
});
|
|
303
|
+
expect((await h.svc.getPrDetail(7, { fresh: true }))?.needsUpdate).toBe(true);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
it('is true when the branches share no history — there is nothing to intersect', async () => {
|
|
307
|
+
const h = harness({ mergeBaseSha: null });
|
|
308
|
+
const detail = await h.svc.getPrDetail(7, { fresh: true });
|
|
309
|
+
expect(detail?.needsUpdate).toBe(true);
|
|
310
|
+
expect(h.pathsChangedBetween).not.toHaveBeenCalled();
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('is true when the comparison itself fails — an infra error is not "this is fine"', async () => {
|
|
314
|
+
const h = harness({ changedOnTargetError: new Error('git exploded') });
|
|
315
|
+
expect((await h.svc.getPrDetail(7, { fresh: true }))?.needsUpdate).toBe(true);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it('is false for a request that is not open, whatever git says', async () => {
|
|
319
|
+
const h = harness({ state: 'merged', changedOnTarget: [FILE] });
|
|
320
|
+
const detail = await h.svc.getPrDetail(7, { fresh: true });
|
|
321
|
+
expect(detail?.needsUpdate).toBe(false);
|
|
322
|
+
expect(detail?.behind).toBe(false);
|
|
323
|
+
});
|
|
324
|
+
});
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { computeViewerCanDelete } from '../pull-request.service.js';
|
|
3
|
+
import { hashEmail } from '../../../../shared/email-identity.js';
|
|
4
|
+
|
|
5
|
+
const EMAIL = 'juan@bevel.software';
|
|
6
|
+
const AUTHOR_HASH = hashEmail(EMAIL);
|
|
7
|
+
const OTHER_AUTHOR_HASH = hashEmail('someone-else@bevel.software');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The truth table for who may delete a request outright — close it AND retire
|
|
11
|
+
* its branch. It must mirror `deleteChangeRequest`'s own check, which is why
|
|
12
|
+
* the interesting rows here are the ones where it DIFFERS from its siblings:
|
|
13
|
+
* an owner of every changed file is absent (they decline, they do not
|
|
14
|
+
* destroy), and a closed request still says yes (its leftover branch is still
|
|
15
|
+
* the server's to retire).
|
|
16
|
+
*/
|
|
17
|
+
describe('computeViewerCanDelete', () => {
|
|
18
|
+
it('lets the author delete their own open request', () => {
|
|
19
|
+
expect(
|
|
20
|
+
computeViewerCanDelete({
|
|
21
|
+
state: 'open',
|
|
22
|
+
authorId: AUTHOR_HASH,
|
|
23
|
+
viewerEmail: EMAIL,
|
|
24
|
+
viewerCanBypassMerge: false,
|
|
25
|
+
}),
|
|
26
|
+
).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('lets an admin delete someone else’s open request', () => {
|
|
30
|
+
expect(
|
|
31
|
+
computeViewerCanDelete({
|
|
32
|
+
state: 'open',
|
|
33
|
+
authorId: OTHER_AUTHOR_HASH,
|
|
34
|
+
viewerEmail: EMAIL,
|
|
35
|
+
viewerCanBypassMerge: true,
|
|
36
|
+
}),
|
|
37
|
+
).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('says yes once for a viewer who is both author and admin', () => {
|
|
41
|
+
expect(
|
|
42
|
+
computeViewerCanDelete({
|
|
43
|
+
state: 'open',
|
|
44
|
+
authorId: AUTHOR_HASH,
|
|
45
|
+
viewerEmail: EMAIL,
|
|
46
|
+
viewerCanBypassMerge: true,
|
|
47
|
+
}),
|
|
48
|
+
).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('refuses a signed-in user who is neither author nor admin', () => {
|
|
52
|
+
expect(
|
|
53
|
+
computeViewerCanDelete({
|
|
54
|
+
state: 'open',
|
|
55
|
+
authorId: OTHER_AUTHOR_HASH,
|
|
56
|
+
viewerEmail: EMAIL,
|
|
57
|
+
viewerCanBypassMerge: false,
|
|
58
|
+
}),
|
|
59
|
+
).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('fails closed with no viewer, even on one’s own-looking request', () => {
|
|
63
|
+
expect(
|
|
64
|
+
computeViewerCanDelete({
|
|
65
|
+
state: 'open',
|
|
66
|
+
authorId: AUTHOR_HASH,
|
|
67
|
+
viewerEmail: undefined,
|
|
68
|
+
viewerCanBypassMerge: false,
|
|
69
|
+
}),
|
|
70
|
+
).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('fails closed for an anonymous admin-flagged read', () => {
|
|
74
|
+
expect(
|
|
75
|
+
computeViewerCanDelete({
|
|
76
|
+
state: 'open',
|
|
77
|
+
authorId: OTHER_AUTHOR_HASH,
|
|
78
|
+
viewerEmail: undefined,
|
|
79
|
+
viewerCanBypassMerge: true,
|
|
80
|
+
}),
|
|
81
|
+
).toBe(false);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('refuses an APPLIED request to its author — applied history is nobody’s to delete', () => {
|
|
85
|
+
expect(
|
|
86
|
+
computeViewerCanDelete({
|
|
87
|
+
state: 'merged',
|
|
88
|
+
authorId: AUTHOR_HASH,
|
|
89
|
+
viewerEmail: EMAIL,
|
|
90
|
+
viewerCanBypassMerge: false,
|
|
91
|
+
}),
|
|
92
|
+
).toBe(false);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('refuses an APPLIED request to an admin too', () => {
|
|
96
|
+
expect(
|
|
97
|
+
computeViewerCanDelete({
|
|
98
|
+
state: 'merged',
|
|
99
|
+
authorId: OTHER_AUTHOR_HASH,
|
|
100
|
+
viewerEmail: EMAIL,
|
|
101
|
+
viewerCanBypassMerge: true,
|
|
102
|
+
}),
|
|
103
|
+
).toBe(false);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('still says yes on a CLOSED request: the leftover branch is the delete’s job', () => {
|
|
107
|
+
// Withdrawn in another tab. The server's delete still succeeds there and
|
|
108
|
+
// removes the branch the withdraw left behind, so the hint must not go
|
|
109
|
+
// quiet the moment the row flips — unlike `viewerCanCancel`, which is
|
|
110
|
+
// open-only because there is nothing left to cancel.
|
|
111
|
+
expect(
|
|
112
|
+
computeViewerCanDelete({
|
|
113
|
+
state: 'closed',
|
|
114
|
+
authorId: AUTHOR_HASH,
|
|
115
|
+
viewerEmail: EMAIL,
|
|
116
|
+
viewerCanBypassMerge: false,
|
|
117
|
+
}),
|
|
118
|
+
).toBe(true);
|
|
119
|
+
expect(
|
|
120
|
+
computeViewerCanDelete({
|
|
121
|
+
state: 'closed',
|
|
122
|
+
authorId: OTHER_AUTHOR_HASH,
|
|
123
|
+
viewerEmail: EMAIL,
|
|
124
|
+
viewerCanBypassMerge: true,
|
|
125
|
+
}),
|
|
126
|
+
).toBe(true);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('refuses a request with no stored author to a non-admin (opened outside this backend)', () => {
|
|
130
|
+
expect(
|
|
131
|
+
computeViewerCanDelete({
|
|
132
|
+
state: 'open',
|
|
133
|
+
authorId: undefined,
|
|
134
|
+
viewerEmail: EMAIL,
|
|
135
|
+
viewerCanBypassMerge: false,
|
|
136
|
+
}),
|
|
137
|
+
).toBe(false);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('leaves normalization to hashEmail, exactly as its siblings do', () => {
|
|
141
|
+
expect(
|
|
142
|
+
computeViewerCanDelete({
|
|
143
|
+
state: 'open',
|
|
144
|
+
authorId: AUTHOR_HASH,
|
|
145
|
+
viewerEmail: ' Juan@Bevel.Software ',
|
|
146
|
+
viewerCanBypassMerge: false,
|
|
147
|
+
}),
|
|
148
|
+
).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('does NOT grant the owner of every changed file — it takes no such input', () => {
|
|
152
|
+
// Decision 4. The owner of every changed file is exactly the person
|
|
153
|
+
// `computeViewerCanCancel` says yes to and this predicate must not: they
|
|
154
|
+
// may decline the request, which leaves the author's branch to rework.
|
|
155
|
+
// There is no input here to express that grant, and the row a
|
|
156
|
+
// file-owning non-admin produces reads false.
|
|
157
|
+
expect(
|
|
158
|
+
computeViewerCanDelete({
|
|
159
|
+
state: 'open',
|
|
160
|
+
authorId: OTHER_AUTHOR_HASH,
|
|
161
|
+
viewerEmail: EMAIL,
|
|
162
|
+
viewerCanBypassMerge: false,
|
|
163
|
+
}),
|
|
164
|
+
).toBe(false);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
@@ -26,9 +26,8 @@ import {
|
|
|
26
26
|
assertValidRelativePath,
|
|
27
27
|
isBranchAuthoredBy,
|
|
28
28
|
isOwnSuggestionsBranch,
|
|
29
|
-
isProtectedBranch,
|
|
30
|
-
PROTECTED_BRANCHES,
|
|
31
29
|
} from '../../kb-fs/branch-name.js';
|
|
30
|
+
import type { KbContext } from '../../../shared/kb-context.js';
|
|
32
31
|
import {
|
|
33
32
|
BranchAuthorshipError,
|
|
34
33
|
WorkflowDomainError,
|
|
@@ -42,6 +41,7 @@ import {
|
|
|
42
41
|
GitRunError,
|
|
43
42
|
isGitTimeout,
|
|
44
43
|
redactGitToken,
|
|
44
|
+
type GitCredentials,
|
|
45
45
|
type GitRunOptions,
|
|
46
46
|
type GitRunResult,
|
|
47
47
|
type IGitRunner,
|
|
@@ -296,7 +296,7 @@ export class GitService implements IGitService {
|
|
|
296
296
|
* safe because validation is advisory and never blocks a commit.
|
|
297
297
|
*/
|
|
298
298
|
private readonly hooks: WorkflowHooks,
|
|
299
|
-
private readonly
|
|
299
|
+
private readonly kb: KbContext,
|
|
300
300
|
private readonly mutex: WorkspaceMutex = new WorkspaceMutex(),
|
|
301
301
|
private readonly accessControl: IAccessControl | null = null,
|
|
302
302
|
/**
|
|
@@ -309,6 +309,18 @@ export class GitService implements IGitService {
|
|
|
309
309
|
private readonly gitRunner: IGitRunner = new NodeGitRunner(),
|
|
310
310
|
) {}
|
|
311
311
|
|
|
312
|
+
private get kbDirName(): string {
|
|
313
|
+
return this.kb.kbDirName;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* The credentials the runner authenticates with — for the services above
|
|
318
|
+
* this one that scrub a message git or the host echoed a token into.
|
|
319
|
+
*/
|
|
320
|
+
get credentials(): GitCredentials {
|
|
321
|
+
return this.gitRunner.credentials;
|
|
322
|
+
}
|
|
323
|
+
|
|
312
324
|
/**
|
|
313
325
|
* "Does the pending-commits queue hold rows for this workspace?" — used by
|
|
314
326
|
* `statusInternal` to tell an expected dirty tree (queued saves still
|
|
@@ -552,7 +564,7 @@ export class GitService implements IGitService {
|
|
|
552
564
|
);
|
|
553
565
|
infos[i] = {
|
|
554
566
|
name: row.shortName,
|
|
555
|
-
isProtected: isProtectedBranch(row.shortName),
|
|
567
|
+
isProtected: this.kb.isProtectedBranch(row.shortName),
|
|
556
568
|
ahead,
|
|
557
569
|
behind,
|
|
558
570
|
hasRemote: row.hasRemote,
|
|
@@ -655,7 +667,7 @@ export class GitService implements IGitService {
|
|
|
655
667
|
fromBase?: string,
|
|
656
668
|
): Promise<BranchInfo> {
|
|
657
669
|
assertValidBranchName(name);
|
|
658
|
-
if (isProtectedBranch(name)) {
|
|
670
|
+
if (this.kb.isProtectedBranch(name)) {
|
|
659
671
|
throw new ProtectedBranchError(name, 'creating a protected branch');
|
|
660
672
|
}
|
|
661
673
|
if (fromBase) assertValidBranchName(fromBase);
|
|
@@ -731,7 +743,7 @@ export class GitService implements IGitService {
|
|
|
731
743
|
opts: { onlyIfNoRemote?: boolean; systemCleanup?: boolean } = {},
|
|
732
744
|
): Promise<void> {
|
|
733
745
|
assertValidBranchName(name);
|
|
734
|
-
if (isProtectedBranch(name)) {
|
|
746
|
+
if (this.kb.isProtectedBranch(name)) {
|
|
735
747
|
throw new ProtectedBranchError(name, 'deleting a protected branch');
|
|
736
748
|
}
|
|
737
749
|
return this.mutex.run(workspaceId, async () => {
|
|
@@ -895,7 +907,7 @@ export class GitService implements IGitService {
|
|
|
895
907
|
// boundary. Without this guard, the standard "fork to draft then
|
|
896
908
|
// propose" workflow would 403 for non-admins — they can't write
|
|
897
909
|
// protected, can't write the draft they forked from it either.
|
|
898
|
-
if (isProtectedBranch(branch)) {
|
|
910
|
+
if (this.kb.isProtectedBranch(branch)) {
|
|
899
911
|
// Gate against the access tree as it exists at HEAD — the pre-commit
|
|
900
912
|
// state. Reading from the working tree would let the user broaden
|
|
901
913
|
// their own access by editing access.md alongside the change they're
|
|
@@ -1172,7 +1184,7 @@ export class GitService implements IGitService {
|
|
|
1172
1184
|
// Protected-branch access gate (defence in depth — callers already gate at
|
|
1173
1185
|
// lock-acquire / upload-mint, but this primitive is generic). Gate every
|
|
1174
1186
|
// touched path against the access tree at HEAD, like `commit()`.
|
|
1175
|
-
if (isProtectedBranch(branch)) {
|
|
1187
|
+
if (this.kb.isProtectedBranch(branch)) {
|
|
1176
1188
|
await this.assertCanWriteAtRef(workspaceId, 'HEAD', user.email, touched);
|
|
1177
1189
|
}
|
|
1178
1190
|
|
|
@@ -1292,7 +1304,7 @@ export class GitService implements IGitService {
|
|
|
1292
1304
|
// decided the write is legitimate (unused name, exclusive create);
|
|
1293
1305
|
// gating it here again just refuses every non-admin the product
|
|
1294
1306
|
// promised a plugin to.
|
|
1295
|
-
if (isProtectedBranch(branch) && !opts?.systemAuthorized) {
|
|
1307
|
+
if (this.kb.isProtectedBranch(branch) && !opts?.systemAuthorized) {
|
|
1296
1308
|
const touched = await this.unpushedTouchedPaths(cwd);
|
|
1297
1309
|
await this.assertCanWriteAtRef(
|
|
1298
1310
|
workspaceId,
|
|
@@ -1542,6 +1554,7 @@ export class GitService implements IGitService {
|
|
|
1542
1554
|
throw new Error(
|
|
1543
1555
|
`git merge failed without detectable conflicts: ${redactGitToken(
|
|
1544
1556
|
err instanceof Error ? err.message : String(err),
|
|
1557
|
+
this.credentials.token(),
|
|
1545
1558
|
)}`,
|
|
1546
1559
|
);
|
|
1547
1560
|
}
|
|
@@ -1747,7 +1760,12 @@ export class GitService implements IGitService {
|
|
|
1747
1760
|
* conflict into the typed error the workflow layer queues recovery for.
|
|
1748
1761
|
* Shared by `pull` and `syncFromRemote` so the two cannot drift.
|
|
1749
1762
|
*/
|
|
1750
|
-
private async rebaseOntoRemote(
|
|
1763
|
+
private async rebaseOntoRemote(
|
|
1764
|
+
cwd: string,
|
|
1765
|
+
branch: string,
|
|
1766
|
+
remoteRef: string,
|
|
1767
|
+
opts: { preserveMerges?: boolean } = {},
|
|
1768
|
+
): Promise<void> {
|
|
1751
1769
|
// An UNBORN HEAD (a clone of an upstream that was empty when cloned) has
|
|
1752
1770
|
// no commit to replay and `git rebase` refuses to start from it, so the
|
|
1753
1771
|
// branch is moved to the remote commit instead. That is only safe while
|
|
@@ -1785,7 +1803,20 @@ export class GitService implements IGitService {
|
|
|
1785
1803
|
// the local commits onto origin, then reapplies them, so the retry
|
|
1786
1804
|
// push can fast-forward. Untracked files don't block rebase and are
|
|
1787
1805
|
// left untouched.
|
|
1788
|
-
|
|
1806
|
+
// `--rebase-merges` is what keeps an unpushed MERGE a merge. Plain
|
|
1807
|
+
// rebase replays `--no-merges upstream..HEAD`, which turns a merge
|
|
1808
|
+
// commit the clone holds but origin has not seen into cherry-picks of
|
|
1809
|
+
// the commits it merged — the merged branch stops being a parent, so
|
|
1810
|
+
// "does the published head contain the target's head" answers no
|
|
1811
|
+
// however many times the update runs. Only the change-request update
|
|
1812
|
+
// asks for it; every other pull replays plain saves, where the two
|
|
1813
|
+
// spellings produce the same history.
|
|
1814
|
+
await this.git(cwd, [
|
|
1815
|
+
'rebase',
|
|
1816
|
+
'--autostash',
|
|
1817
|
+
...(opts.preserveMerges ? ['--rebase-merges'] : []),
|
|
1818
|
+
remoteRef,
|
|
1819
|
+
]);
|
|
1789
1820
|
} catch (err) {
|
|
1790
1821
|
// Capture the contested paths BEFORE the abort wipes the rebase
|
|
1791
1822
|
// state — `--diff-filter=U` lists exactly the files whose replay
|
|
@@ -1909,7 +1940,10 @@ export class GitService implements IGitService {
|
|
|
1909
1940
|
});
|
|
1910
1941
|
}
|
|
1911
1942
|
|
|
1912
|
-
async pull(
|
|
1943
|
+
async pull(
|
|
1944
|
+
workspaceId: string,
|
|
1945
|
+
opts: { preserveMerges?: boolean } = {},
|
|
1946
|
+
): Promise<{ treeChanged: boolean }> {
|
|
1913
1947
|
return this.mutex.run(workspaceId, async () => {
|
|
1914
1948
|
const cwd = await this.repoDir(workspaceId);
|
|
1915
1949
|
const branch = await this.checkedOutBranch(cwd);
|
|
@@ -1922,7 +1956,7 @@ export class GitService implements IGitService {
|
|
|
1922
1956
|
// Refresh WITHOUT `git pull`, and without touching `FETCH_HEAD` — see
|
|
1923
1957
|
// `refreshRemoteBranchRef` for why both halves are load-bearing.
|
|
1924
1958
|
const remoteRef = await this.refreshRemoteBranchRef(cwd, branch);
|
|
1925
|
-
await this.rebaseOntoRemote(cwd, branch, remoteRef);
|
|
1959
|
+
await this.rebaseOntoRemote(cwd, branch, remoteRef, opts);
|
|
1926
1960
|
this.accessControl?.invalidate(workspaceId);
|
|
1927
1961
|
const treeAfter = (await this.revParseOrNull(cwd, 'HEAD^{tree}')) ?? '';
|
|
1928
1962
|
return { treeChanged: treeAfter !== treeBefore };
|
|
@@ -2109,7 +2143,7 @@ export class GitService implements IGitService {
|
|
|
2109
2143
|
return this.mutex.run(workspaceId, async () => {
|
|
2110
2144
|
const cwd = await this.repoDir(workspaceId);
|
|
2111
2145
|
let best: { base: string; ahead: number } | null = null;
|
|
2112
|
-
for (const p of
|
|
2146
|
+
for (const p of this.kb.protectedBranches) {
|
|
2113
2147
|
if (p === branch) continue;
|
|
2114
2148
|
const res = await this.tryAheadBehind(cwd, branch, `origin/${p}`);
|
|
2115
2149
|
if (res && (best === null || res.ahead < best.ahead)) {
|
|
@@ -3133,7 +3167,7 @@ export class GitService implements IGitService {
|
|
|
3133
3167
|
}
|
|
3134
3168
|
|
|
3135
3169
|
let best: { ahead: number; behind: number } | null = null;
|
|
3136
|
-
for (const p of
|
|
3170
|
+
for (const p of this.kb.protectedBranches) {
|
|
3137
3171
|
if (p === shortName) continue;
|
|
3138
3172
|
const res = await this.tryAheadBehind(cwd, ref, `refs/remotes/origin/${p}`);
|
|
3139
3173
|
if (res && (best === null || res.ahead < best.ahead)) best = res;
|
|
@@ -3447,5 +3481,3 @@ export function parseNumstatZ(out: string): NumstatEntry[] {
|
|
|
3447
3481
|
}
|
|
3448
3482
|
return entries;
|
|
3449
3483
|
}
|
|
3450
|
-
|
|
3451
|
-
export { PROTECTED_BRANCHES };
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { spawn, type ChildProcess, type SpawnOptions } from 'node:child_process';
|
|
2
2
|
import {
|
|
3
|
+
GIT_TOKEN_ENV,
|
|
3
4
|
GitRunError,
|
|
5
|
+
NO_GIT_CREDENTIALS,
|
|
4
6
|
redactGitToken,
|
|
7
|
+
type GitCredentials,
|
|
5
8
|
type GitRunOptions,
|
|
6
9
|
type GitRunResult,
|
|
7
10
|
type IGitRunner,
|
|
@@ -212,7 +215,33 @@ function spawnGit(args: string[], options: SpawnOptions & { maxBuffer: number })
|
|
|
212
215
|
* `WorkspaceMutex`'s job and stays the caller's to have done.
|
|
213
216
|
*/
|
|
214
217
|
export class NodeGitRunner implements IGitRunner {
|
|
215
|
-
constructor(
|
|
218
|
+
constructor(
|
|
219
|
+
readonly defaultTimeoutMs: number = DEFAULT_GIT_TIMEOUT_MS,
|
|
220
|
+
/**
|
|
221
|
+
* What every call authenticates with. The token goes into the CHILD's
|
|
222
|
+
* environment only (see {@link childEnv}); a runner built without one
|
|
223
|
+
* runs git unauthenticated, which is what a directly constructed service
|
|
224
|
+
* in a test gets.
|
|
225
|
+
*/
|
|
226
|
+
readonly credentials: GitCredentials = NO_GIT_CREDENTIALS,
|
|
227
|
+
) {}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* The environment one invocation runs under. The token in effect goes in
|
|
231
|
+
* under {@link GIT_TOKEN_ENV}, and a stale one this process inherited from
|
|
232
|
+
* its own environment goes OUT: a server hosting several knowledge bases
|
|
233
|
+
* must never let one knowledge base's git call find another's token, or an
|
|
234
|
+
* operator's, lying in `process.env`. A caller's per-call entry still wins
|
|
235
|
+
* over the provider's (the setup probe runs with the token it is checking,
|
|
236
|
+
* not the one in effect), and the fixed entries win over everything.
|
|
237
|
+
*/
|
|
238
|
+
private childEnv(overrides: NodeJS.ProcessEnv | undefined): NodeJS.ProcessEnv {
|
|
239
|
+
const env: NodeJS.ProcessEnv = { ...process.env };
|
|
240
|
+
delete env[GIT_TOKEN_ENV];
|
|
241
|
+
const token = this.credentials.token();
|
|
242
|
+
if (token) env[GIT_TOKEN_ENV] = token;
|
|
243
|
+
return { ...env, ...overrides, ...FIXED_ENV };
|
|
244
|
+
}
|
|
216
245
|
|
|
217
246
|
run(cwd: string, args: string[], opts: GitRunOptions & { encoding: 'buffer' }): Promise<GitRunResult<Buffer>>;
|
|
218
247
|
run(cwd: string, args: string[], opts?: GitRunOptions & { encoding?: 'utf8' }): Promise<GitRunResult>;
|
|
@@ -221,10 +250,16 @@ export class NodeGitRunner implements IGitRunner {
|
|
|
221
250
|
const timers: NodeJS.Timeout[] = [];
|
|
222
251
|
let timedOut = false;
|
|
223
252
|
|
|
253
|
+
// A credential that expires is renewed before it is read. Renewing is
|
|
254
|
+
// the credential's own business and its failure is not this call's:
|
|
255
|
+
// plenty of git never leaves the disk, and a call that does is told by
|
|
256
|
+
// the host what the token in hand is worth.
|
|
257
|
+
await this.credentials.prepare?.().catch(() => undefined);
|
|
258
|
+
|
|
224
259
|
try {
|
|
225
260
|
const { promise: pending, child } = spawnGit(args, {
|
|
226
261
|
cwd,
|
|
227
|
-
env:
|
|
262
|
+
env: this.childEnv(opts.env),
|
|
228
263
|
maxBuffer: MAX_OUTPUT_BYTES,
|
|
229
264
|
// Makes the child a process-group leader so that `killTree` can signal
|
|
230
265
|
// the transport helpers it spawns, not just git itself. Not on Windows,
|
|
@@ -291,9 +326,13 @@ export class NodeGitRunner implements IGitRunner {
|
|
|
291
326
|
: Buffer.isBuffer(original.stderr)
|
|
292
327
|
? original.stderr.toString()
|
|
293
328
|
: undefined;
|
|
294
|
-
|
|
329
|
+
// Scrubbed with the token THIS runner handed the child, and the one a
|
|
330
|
+
// caller laid over it for the call: both can be echoed back by git.
|
|
331
|
+
const secrets = [this.credentials.token(), opts.env?.[GIT_TOKEN_ENV]];
|
|
332
|
+
const scrub = (text: string): string => secrets.reduce<string>((out, token) => redactGitToken(out, token), text);
|
|
333
|
+
throw new GitRunError(`git ${subcommand} failed: ${scrub(message)}`, {
|
|
295
334
|
exitCode: typeof original.code === 'number' ? original.code : undefined,
|
|
296
|
-
stderr: stderr === undefined ? undefined :
|
|
335
|
+
stderr: stderr === undefined ? undefined : scrub(stderr),
|
|
297
336
|
});
|
|
298
337
|
} finally {
|
|
299
338
|
// Every timer is cleared on every path. The later ones in particular
|