@bevel-software/platform-core-backend 0.20.0 → 0.21.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 +23 -105
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +30 -5
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +136 -81
- 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.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/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 +19 -1
- package/dist/modules/auth/auth.service.d.ts.map +1 -1
- package/dist/modules/auth/auth.service.js +33 -1
- 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/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/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-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 +3 -1
- package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
- package/dist/modules/plugins/join-requests.service.js +9 -8
- 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 +45 -15
- 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 +12 -8
- package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
- package/dist/modules/settings/deployment-settings.service.js +20 -22
- package/dist/modules/settings/deployment-settings.service.js.map +1 -1
- package/dist/modules/settings/setup.routes.d.ts +9 -2
- package/dist/modules/settings/setup.routes.d.ts.map +1 -1
- package/dist/modules/settings/setup.routes.js +20 -14
- 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 +2 -1
- package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -1
- package/dist/modules/skills/skill-access-requests.routes.js +6 -6
- 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-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 +9 -9
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +11 -5
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +23 -14
- 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 +35 -5
- package/dist/modules/workflow/git/node-git-runner.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.service.d.ts +8 -3
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +33 -23
- 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 +5 -8
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.js +35 -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 +32 -28
- 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 +20 -18
- 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/git.contract.d.ts +52 -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 +27 -106
- package/src/core/create-core-services.ts +180 -95
- 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.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.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/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 +60 -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 +33 -1
- 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/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/branch-name.ts +3 -3
- package/src/modules/kb-fs/clone-config.ts +15 -12
- 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-request-jobs.service.test.ts +2 -1
- package/src/modules/plugins/__tests__/join-requests.service.test.ts +2 -1
- 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 +11 -2
- 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-request-jobs.service.ts +8 -7
- package/src/modules/plugins/join-requests.service.ts +7 -7
- 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 +45 -15
- 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__/setup.routes.boot-failure.test.ts +2 -1
- package/src/modules/settings/__tests__/setup.routes.layout-phase.test.ts +7 -4
- 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 +21 -20
- package/src/modules/settings/setup.routes.ts +26 -16
- 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 +2 -1
- 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 +7 -7
- 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-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 +2 -1
- 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 +28 -27
- 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 +2 -1
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +2 -1
- package/src/modules/workflow/agent-tools/workflow.tools.ts +11 -9
- 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 +9 -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/git.service.ts +24 -13
- package/src/modules/workflow/git/node-git-runner.ts +37 -4
- 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.service.ts +31 -24
- 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 +2 -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 +4 -3
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +9 -8
- 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 +29 -21
- package/src/modules/workspace/startup/kb-git.ts +15 -22
- package/src/modules/workspace/startup/kb-startup-runner.ts +40 -46
- 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 +30 -27
- package/src/modules/workspace/workspace.tools.ts +21 -20
- package/src/modules/workspace/write-denial.ts +7 -5
- package/src/shared/__tests__/kb-layout.plugin.test.ts +19 -16
- package/src/shared/git.contract.ts +70 -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
|
@@ -9,7 +9,6 @@ import type { IAdminAccessService } from '../admin/admin.interface.js';
|
|
|
9
9
|
import express from 'express';
|
|
10
10
|
import type { AuthUser, IWorkflowService } from '@bevel-software/platform-shared';
|
|
11
11
|
import {
|
|
12
|
-
DEFAULT_BRANCH,
|
|
13
12
|
KNOWLEDGE_DIR,
|
|
14
13
|
canonicalRelativePath,
|
|
15
14
|
folderPlaceholderPath,
|
|
@@ -21,6 +20,7 @@ import {
|
|
|
21
20
|
} from '@bevel-software/platform-shared';
|
|
22
21
|
import { FolderTooLargeError, type ReadTreeFilter } from './workspace.service.js';
|
|
23
22
|
import { branchForWorkspaceId } from '../../shared/workspace-id.js';
|
|
23
|
+
import type { KbContext } from '../../shared/kb-context.js';
|
|
24
24
|
import { EntryExistsError, type WorkspaceService } from './workspace.service.js';
|
|
25
25
|
import type { AuthService } from '../auth/auth.service.js';
|
|
26
26
|
import type { IAccessControl } from '../access/access-control.interface.js';
|
|
@@ -82,7 +82,7 @@ export function createWorkspaceRoutes(
|
|
|
82
82
|
workflowService: IWorkflowService,
|
|
83
83
|
eventBus: WorkflowEventBus,
|
|
84
84
|
accessControl: IAccessControl,
|
|
85
|
-
|
|
85
|
+
kb: KbContext,
|
|
86
86
|
creatorAccess: ICreatorAccess,
|
|
87
87
|
adminAccess: IAdminAccessService,
|
|
88
88
|
disk: ITreeWalker,
|
|
@@ -97,6 +97,7 @@ export function createWorkspaceRoutes(
|
|
|
97
97
|
changeGate?: IChangeReadGate,
|
|
98
98
|
): express.Router {
|
|
99
99
|
const router = express.Router();
|
|
100
|
+
const { kbDirName } = kb;
|
|
100
101
|
const gitInternalsRouteGuard = createGitInternalsRouteGuard(workspaceService);
|
|
101
102
|
|
|
102
103
|
// The git folder is refused ahead of every route here by
|
|
@@ -463,7 +464,7 @@ export function createWorkspaceRoutes(
|
|
|
463
464
|
}
|
|
464
465
|
const branch = typeof req.query.branch === 'string' && req.query.branch.length > 0
|
|
465
466
|
? req.query.branch
|
|
466
|
-
:
|
|
467
|
+
: kb.defaultBranch;
|
|
467
468
|
const workspace = await workspaceService.getOrCreateForBranch(branch);
|
|
468
469
|
// Bootstrap must use the same read-filtered tree as GET /workspace/:id/files.
|
|
469
470
|
// Otherwise the first sidebar render can expose restricted nodes until the
|
|
@@ -663,7 +664,7 @@ export function createWorkspaceRoutes(
|
|
|
663
664
|
// same treatment so legacy clones don't collapse. Only the folders
|
|
664
665
|
// themselves are forced visible — their contents stay gated by the
|
|
665
666
|
// verdict above.
|
|
666
|
-
const structuralRoots = new Set([...reservedRootDirNames(), KNOWLEDGE_DIR]);
|
|
667
|
+
const structuralRoots = new Set([...reservedRootDirNames(kb.layout), KNOWLEDGE_DIR]);
|
|
667
668
|
for (const wp of wsRelPaths) {
|
|
668
669
|
const rel = toKbRelative(wp, kbDirName);
|
|
669
670
|
if (rel !== null && structuralRoots.has(rel)) verdict.set(wp, true);
|
|
@@ -1128,11 +1129,11 @@ export function createWorkspaceRoutes(
|
|
|
1128
1129
|
const oldRel = toKbRelative(oldPath, kbDirName);
|
|
1129
1130
|
const newRel = toKbRelative(newPath, kbDirName);
|
|
1130
1131
|
let platformRestore = false;
|
|
1131
|
-
if (oldRel !== null && newRel !== null && isPlatformRestoreShape(oldRel, newRel)) {
|
|
1132
|
+
if (oldRel !== null && newRel !== null && isPlatformRestoreShape(oldRel, newRel, kb.layout)) {
|
|
1132
1133
|
platformRestore = await accessControl.canRestorePlatformFile(id, user.email, newRel);
|
|
1133
1134
|
}
|
|
1134
1135
|
// A platform file stays where the platform reads it …
|
|
1135
|
-
if (oldRel !== null && isPlatformFile(oldRel) && !platformRestore) {
|
|
1136
|
+
if (oldRel !== null && isPlatformFile(oldRel, kb.layout) && !platformRestore) {
|
|
1136
1137
|
res.status(409).json({ error: platformFileRefusal(oldRel) });
|
|
1137
1138
|
return;
|
|
1138
1139
|
}
|
|
@@ -1145,7 +1146,7 @@ export function createWorkspaceRoutes(
|
|
|
1145
1146
|
// from the same place. Only the restore lands on a platform path, and
|
|
1146
1147
|
// only where the file is missing (`canRestorePlatformFile` checked the
|
|
1147
1148
|
// disk; the destination lock below checks it again, under the lock).
|
|
1148
|
-
if (newRel !== null && isPlatformFile(newRel) && !platformRestore) {
|
|
1149
|
+
if (newRel !== null && isPlatformFile(newRel, kb.layout) && !platformRestore) {
|
|
1149
1150
|
res.status(409).json({ error: platformFileCreationRefusal(newRel) });
|
|
1150
1151
|
return;
|
|
1151
1152
|
}
|
|
@@ -9,7 +9,6 @@ import { AsyncLocalStorage } from 'node:async_hooks';
|
|
|
9
9
|
import {
|
|
10
10
|
validateRelativePath,
|
|
11
11
|
validateFilename,
|
|
12
|
-
DEFAULT_BRANCH,
|
|
13
12
|
FOLDER_PLACEHOLDER,
|
|
14
13
|
isFolderPlaceholder,
|
|
15
14
|
entryExistsMessage,
|
|
@@ -22,6 +21,7 @@ import {
|
|
|
22
21
|
renameNoReplace,
|
|
23
22
|
} from '../../shared/rename-no-replace.js';
|
|
24
23
|
import type { IGitRunner } from '../../shared/git.contract.js';
|
|
24
|
+
import type { KbContext } from '../../shared/kb-context.js';
|
|
25
25
|
import { NodeGitRunner } from '../workflow/git/node-git-runner.js';
|
|
26
26
|
import { assertWithinDirectory } from '../../shared/path-containment.js';
|
|
27
27
|
import { assertRepoRootNameFree, normalizeWorkspacePath } from '../kb-fs/repo-path.js';
|
|
@@ -149,9 +149,8 @@ const CLONE_TIMEOUT_MS = 600_000;
|
|
|
149
149
|
const BOT_NAME = 'Bevel Workflow';
|
|
150
150
|
const BOT_EMAIL = 'bevel-workflow@bevel.software';
|
|
151
151
|
|
|
152
|
-
/** Redact
|
|
153
|
-
function redactError(err: unknown): string {
|
|
154
|
-
const token = process.env.GITHUB_TOKEN;
|
|
152
|
+
/** Redact the token the runner authenticates with from an error message. */
|
|
153
|
+
function redactError(err: unknown, token: string | null): string {
|
|
155
154
|
const msg = err instanceof Error ? err.message : String(err);
|
|
156
155
|
return token ? msg.replaceAll(token, '***') : msg;
|
|
157
156
|
}
|
|
@@ -297,23 +296,26 @@ export class WorkspaceService implements IWorkspaceService {
|
|
|
297
296
|
* buy an inconsistency rather than a feature.
|
|
298
297
|
*/
|
|
299
298
|
kbRepoUrl: string | (() => string),
|
|
300
|
-
|
|
299
|
+
/** The checkout folder's name, and which branch a caller lands on when naming none. */
|
|
300
|
+
private readonly kb: Pick<KbContext, 'kbDirName' | 'defaultBranch'>,
|
|
301
301
|
private readonly disk: ITreeWalker,
|
|
302
|
-
gitUsername: string | (() => string) = 'x-access-token',
|
|
303
302
|
/**
|
|
304
303
|
* How git is run — see `shared/git.contract.ts`. The composition root
|
|
305
|
-
* passes the one runner carrying the deployment's deadline
|
|
306
|
-
*
|
|
307
|
-
*
|
|
304
|
+
* passes the one runner carrying the deployment's deadline and the
|
|
305
|
+
* credentials every clone authenticates with; the default is the same
|
|
306
|
+
* runner on its default deadline and no token, for a directly
|
|
307
|
+
* constructed service.
|
|
308
308
|
*/
|
|
309
309
|
private readonly gitRunner: IGitRunner = new NodeGitRunner(),
|
|
310
310
|
) {
|
|
311
311
|
this.kbRepoUrl = typeof kbRepoUrl === 'function' ? kbRepoUrl : () => kbRepoUrl;
|
|
312
|
-
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private get kbDirName(): string {
|
|
315
|
+
return this.kb.kbDirName;
|
|
313
316
|
}
|
|
314
317
|
|
|
315
318
|
private readonly kbRepoUrl: () => string;
|
|
316
|
-
private readonly gitUsername: () => string;
|
|
317
319
|
|
|
318
320
|
setDiffService(diffService: IDiffService): void {
|
|
319
321
|
this.diffService = diffService;
|
|
@@ -417,7 +419,7 @@ export class WorkspaceService implements IWorkspaceService {
|
|
|
417
419
|
// Persisted into the new repo's config (`clone --config`), not just applied
|
|
418
420
|
// to this invocation — every later push from this clone depends on finding
|
|
419
421
|
// the helper there. See `cloneCredentialArgs`.
|
|
420
|
-
args.push(...cloneCredentialArgs(this.
|
|
422
|
+
args.push(...cloneCredentialArgs(this.gitRunner.credentials));
|
|
421
423
|
args.push(this.kbRepoUrl(), targetDir);
|
|
422
424
|
return args;
|
|
423
425
|
}
|
|
@@ -531,7 +533,7 @@ export class WorkspaceService implements IWorkspaceService {
|
|
|
531
533
|
cloned.push({
|
|
532
534
|
id: entry.name,
|
|
533
535
|
branch,
|
|
534
|
-
unreadable: `Could not read this branch's clone: ${redactError(err)}`,
|
|
536
|
+
unreadable: `Could not read this branch's clone: ${redactError(err, this.gitRunner.credentials.token())}`,
|
|
535
537
|
});
|
|
536
538
|
continue;
|
|
537
539
|
}
|
|
@@ -566,7 +568,7 @@ export class WorkspaceService implements IWorkspaceService {
|
|
|
566
568
|
return;
|
|
567
569
|
} catch (err) {
|
|
568
570
|
log.warn(`referenced clone for "${branch}" failed, retrying without reference:`, {
|
|
569
|
-
detail: redactError(err),
|
|
571
|
+
detail: redactError(err, this.gitRunner.credentials.token()),
|
|
570
572
|
});
|
|
571
573
|
// Clear any partial output so the retry clones into a clean dir.
|
|
572
574
|
await fs.rm(targetDir, { recursive: true, force: true }).catch(() => {});
|
|
@@ -675,7 +677,7 @@ export class WorkspaceService implements IWorkspaceService {
|
|
|
675
677
|
* `branch` is passed.
|
|
676
678
|
*/
|
|
677
679
|
async getOrCreateForUser(_user: AuthUser, branch?: string): Promise<WorkspaceInfo> {
|
|
678
|
-
return this.getOrCreateForBranch(branch ??
|
|
680
|
+
return this.getOrCreateForBranch(branch ?? this.kb.defaultBranch);
|
|
679
681
|
}
|
|
680
682
|
|
|
681
683
|
private buildWorkspaceInfo(branch: string, workspaceDir: string): WorkspaceInfo {
|
|
@@ -741,7 +743,7 @@ export class WorkspaceService implements IWorkspaceService {
|
|
|
741
743
|
} catch (err) {
|
|
742
744
|
// One line per branch, not per key: every key writes to the same
|
|
743
745
|
// `.git/config`, so what fails for one fails for all.
|
|
744
|
-
log.warn(`could not normalize the config of the "${branch}" clone:`, { detail: redactError(err) });
|
|
746
|
+
log.warn(`could not normalize the config of the "${branch}" clone:`, { detail: redactError(err, this.gitRunner.credentials.token()) });
|
|
745
747
|
}
|
|
746
748
|
await this.stampCredentialHelper(repoDir, branch);
|
|
747
749
|
}
|
|
@@ -750,12 +752,13 @@ export class WorkspaceService implements IWorkspaceService {
|
|
|
750
752
|
* Fingerprint of the credential state a clone's helper is derived from: the
|
|
751
753
|
* username (baked into the helper literal) and whether a token exists at all
|
|
752
754
|
* (the helper is present-or-absent on that). The token VALUE is deliberately
|
|
753
|
-
* excluded — the helper reads `$GITHUB_TOKEN`
|
|
754
|
-
* token needs no re-stamp; only
|
|
755
|
-
* disappearing does.
|
|
755
|
+
* excluded — the helper reads `$GITHUB_TOKEN` from the environment the
|
|
756
|
+
* runner hands each git call, so rotating the token needs no re-stamp; only
|
|
757
|
+
* a username change or a token appearing / disappearing does.
|
|
756
758
|
*/
|
|
757
759
|
private credentialFingerprint(): string {
|
|
758
|
-
|
|
760
|
+
const { credentials } = this.gitRunner;
|
|
761
|
+
return `${credentials.username()}::${credentials.token() ? '1' : '0'}`;
|
|
759
762
|
}
|
|
760
763
|
|
|
761
764
|
/** Last credential fingerprint stamped into each branch's clone, this process. */
|
|
@@ -772,7 +775,7 @@ export class WorkspaceService implements IWorkspaceService {
|
|
|
772
775
|
private async stampCredentialHelper(repoDir: string, branch: string): Promise<void> {
|
|
773
776
|
let argLists: string[][];
|
|
774
777
|
try {
|
|
775
|
-
argLists = cloneCredentialConfigArgs(this.
|
|
778
|
+
argLists = cloneCredentialConfigArgs(this.gitRunner.credentials);
|
|
776
779
|
} catch (err) {
|
|
777
780
|
// `credentialHelperValue` fails closed on a username outside its safe
|
|
778
781
|
// charset. Normally unreachable (CoreConfig and the settings service
|
|
@@ -782,7 +785,7 @@ export class WorkspaceService implements IWorkspaceService {
|
|
|
782
785
|
// re-clone that fails on the same validation — masking the real cause.
|
|
783
786
|
// Contain it as a loud non-stamp instead; `normalizeCloneConfig`'s
|
|
784
787
|
// never-throws contract stays true.
|
|
785
|
-
log.warn(`refusing to stamp the credential helper of the "${branch}" clone:`, { detail: redactError(err) });
|
|
788
|
+
log.warn(`refusing to stamp the credential helper of the "${branch}" clone:`, { detail: redactError(err, this.gitRunner.credentials.token()) });
|
|
786
789
|
this.stampedCredentialFingerprint.delete(branch);
|
|
787
790
|
return;
|
|
788
791
|
}
|
|
@@ -798,7 +801,7 @@ export class WorkspaceService implements IWorkspaceService {
|
|
|
798
801
|
if (!(args.includes('--unset-all') && code === 5)) {
|
|
799
802
|
stamped = false;
|
|
800
803
|
log.warn(`could not stamp the credential helper of the "${branch}" clone:`, {
|
|
801
|
-
detail: redactError(err),
|
|
804
|
+
detail: redactError(err, this.gitRunner.credentials.token()),
|
|
802
805
|
});
|
|
803
806
|
}
|
|
804
807
|
}
|
|
@@ -914,11 +917,11 @@ export class WorkspaceService implements IWorkspaceService {
|
|
|
914
917
|
this.onWorkspaceCloned?.(workspaceIdForBranch(branch));
|
|
915
918
|
} catch (listenerErr) {
|
|
916
919
|
log.error(`onWorkspaceCloned listener failed for branch "${branch}":`, {
|
|
917
|
-
detail: redactError(listenerErr),
|
|
920
|
+
detail: redactError(listenerErr, this.gitRunner.credentials.token()),
|
|
918
921
|
});
|
|
919
922
|
}
|
|
920
923
|
} catch (err) {
|
|
921
|
-
const redacted = redactError(err);
|
|
924
|
+
const redacted = redactError(err, this.gitRunner.credentials.token());
|
|
922
925
|
// Roll back partial state so the next bootstrap retries cleanly.
|
|
923
926
|
await fs.rm(targetDir, { recursive: true, force: true }).catch(() => {});
|
|
924
927
|
// A branch origin does not have is a fact about the branch, not a
|
|
@@ -936,7 +939,7 @@ export class WorkspaceService implements IWorkspaceService {
|
|
|
936
939
|
// two stories this is — and guessing either one states something
|
|
937
940
|
// about the branch that we do not know. Our failure, so: 500.
|
|
938
941
|
log.error(`Could not tell whether branch "${branch}" was ever known here:`, {
|
|
939
|
-
detail: redactError(probeErr),
|
|
942
|
+
detail: redactError(probeErr, this.gitRunner.credentials.token()),
|
|
940
943
|
});
|
|
941
944
|
throw new Error(`Failed to clone process map: ${redacted}`);
|
|
942
945
|
}
|
|
@@ -1255,7 +1258,7 @@ export class WorkspaceService implements IWorkspaceService {
|
|
|
1255
1258
|
})
|
|
1256
1259
|
.catch((err) => {
|
|
1257
1260
|
this.lastFetchOk.set(repoDir, false);
|
|
1258
|
-
log.warn('git fetch origin failed:', { detail: redactError(err) });
|
|
1261
|
+
log.warn('git fetch origin failed:', { detail: redactError(err, this.gitRunner.credentials.token()) });
|
|
1259
1262
|
})
|
|
1260
1263
|
.finally(() => {
|
|
1261
1264
|
if (this.inFlightFetches.get(repoDir) === promise) {
|
|
@@ -39,21 +39,20 @@ import { createFileReaderRegistry } from './file-readers/file-reader.registry.js
|
|
|
39
39
|
import { DocumentReader } from './file-readers/document-reader.js';
|
|
40
40
|
import { mcpImageResult } from '@bevel-software/platform-mcp-core';
|
|
41
41
|
import {
|
|
42
|
-
AGENTS_FILE,
|
|
43
42
|
LEGACY_AGENTS_FILE,
|
|
44
43
|
folderPlaceholderPath,
|
|
45
44
|
isFolderPlaceholder,
|
|
46
45
|
isPlatformFile,
|
|
47
46
|
isPlatformFolder,
|
|
48
|
-
isProtectedBranch,
|
|
49
|
-
onKbLayoutApplied,
|
|
50
47
|
platformFileCreationRefusal,
|
|
51
48
|
platformFileNames,
|
|
52
49
|
platformFileRefusal,
|
|
53
50
|
platformFolderRefusal,
|
|
54
51
|
entryExistsMessage,
|
|
55
52
|
type ExistingEntryKind,
|
|
53
|
+
type KbLayout,
|
|
56
54
|
} from '@bevel-software/platform-shared';
|
|
55
|
+
import type { KbContext } from '../../shared/kb-context.js';
|
|
57
56
|
import { AccessDeniedError } from '../access-model/access-errors.js';
|
|
58
57
|
import { removeEmptyDirs } from './empty-dirs.js';
|
|
59
58
|
import { PROPOSAL_ROUTE_NOTE, rethrowAsWriteDenial } from './write-denial.js';
|
|
@@ -216,22 +215,23 @@ async function keepFolderOf(
|
|
|
216
215
|
* working in their knowledge base. Under the default name the wording collapses
|
|
217
216
|
* to the one file it has always named.
|
|
218
217
|
*
|
|
219
|
-
* A FUNCTION, called
|
|
220
|
-
*
|
|
218
|
+
* A FUNCTION of the layout, called when a description is built: the name is a
|
|
219
|
+
* deployment setting, and a module-scope string would snapshot the default.
|
|
221
220
|
*/
|
|
222
|
-
function kbConventionsNote(): string {
|
|
223
|
-
|
|
221
|
+
function kbConventionsNote(layout: KbLayout): string {
|
|
222
|
+
const agentsFile = layout.agentsFile ?? LEGACY_AGENTS_FILE;
|
|
223
|
+
if (agentsFile === LEGACY_AGENTS_FILE) {
|
|
224
224
|
return ' Before your first read or change in a workspace, read `AGENTS.md` at the KB root — or `CLAUDE.md` on a knowledge base seeded before it was renamed — if either exists: it holds the author\'s conventions for this knowledge base, and you should follow them.';
|
|
225
225
|
}
|
|
226
226
|
return (
|
|
227
|
-
` Before your first read or change in a workspace, read \`${
|
|
227
|
+
` Before your first read or change in a workspace, read \`${agentsFile}\` at the KB root, then ` +
|
|
228
228
|
'`AGENTS.md` if it also exists (the organisation\'s own conventions) — or `CLAUDE.md` on a knowledge base seeded before it was renamed: together they hold the conventions for this knowledge base, and you should follow them.'
|
|
229
229
|
);
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
/** The platform files as a tool description lists them — the guide under its own name. */
|
|
233
|
-
function platformFileList(): string {
|
|
234
|
-
return platformFileNames()
|
|
233
|
+
function platformFileList(layout: KbLayout): string {
|
|
234
|
+
return platformFileNames(layout)
|
|
235
235
|
.map((name) => `\`${name}\``)
|
|
236
236
|
.join(', ');
|
|
237
237
|
}
|
|
@@ -679,7 +679,7 @@ export function registerWorkspaceTools(
|
|
|
679
679
|
spillStore: SpillStore,
|
|
680
680
|
docExtract: DocExtractService,
|
|
681
681
|
accessControl: IAccessControl,
|
|
682
|
-
|
|
682
|
+
kb: KbContext,
|
|
683
683
|
sessionOntologyGate: SessionOntologyGate,
|
|
684
684
|
writePolicy: IRoutineWritePolicy,
|
|
685
685
|
sessionSink: ISessionSink,
|
|
@@ -697,6 +697,7 @@ export function registerWorkspaceTools(
|
|
|
697
697
|
*/
|
|
698
698
|
changeGate?: IChangeReadGate,
|
|
699
699
|
): void {
|
|
700
|
+
const { kbDirName } = kb;
|
|
700
701
|
/**
|
|
701
702
|
* The one extension→reader registry every read-shaped decision routes
|
|
702
703
|
* through: read_file dispatches on it, grep asks it for searchable text,
|
|
@@ -871,7 +872,7 @@ export function registerWorkspaceTools(
|
|
|
871
872
|
* branch only through a change request.
|
|
872
873
|
*/
|
|
873
874
|
const writeBlocked = async (branch: string, ctx: ToolContext, paths: string[]): Promise<string[]> => {
|
|
874
|
-
if (!isProtectedBranch(branch)) return [];
|
|
875
|
+
if (!kb.isProtectedBranch(branch)) return [];
|
|
875
876
|
const byRel = new Map<string, string>();
|
|
876
877
|
for (const p of paths) {
|
|
877
878
|
const rel = toKbRelative(p, kbDirName);
|
|
@@ -934,11 +935,11 @@ export function registerWorkspaceTools(
|
|
|
934
935
|
if (isGitMetadata(norm)) return `"${norm}" is git metadata and cannot be moved or deleted.`;
|
|
935
936
|
if (kind === 'file') {
|
|
936
937
|
const rel = toKbRelative(norm, kbDirName);
|
|
937
|
-
return rel !== null && isPlatformFile(rel) ? platformFileRefusal(rel) : undefined;
|
|
938
|
+
return rel !== null && isPlatformFile(rel, kb.layout) ? platformFileRefusal(rel) : undefined;
|
|
938
939
|
}
|
|
939
940
|
if (norm === '' || norm === kbDirName) return platformFolderRefusal('');
|
|
940
941
|
const rel = toKbRelative(norm, kbDirName);
|
|
941
|
-
return rel !== null && isPlatformFolder(rel) ? platformFolderRefusal(rel) : undefined;
|
|
942
|
+
return rel !== null && isPlatformFolder(rel, kb.layout) ? platformFolderRefusal(rel) : undefined;
|
|
942
943
|
};
|
|
943
944
|
|
|
944
945
|
/** The workspace root on disk for `branch`. */
|
|
@@ -1181,7 +1182,7 @@ export function registerWorkspaceTools(
|
|
|
1181
1182
|
(typeof spec.description === 'function' ? spec.description() : spec.description) +
|
|
1182
1183
|
(spec.proposable ? PROPOSAL_ROUTE_NOTE : '') +
|
|
1183
1184
|
(spec.fileTool === false ? '' : CONTENT_RULE) +
|
|
1184
|
-
kbConventionsNote();
|
|
1185
|
+
kbConventionsNote(kb.layout);
|
|
1185
1186
|
const def = toolDef({
|
|
1186
1187
|
name: spec.name,
|
|
1187
1188
|
description: describe(),
|
|
@@ -1199,7 +1200,7 @@ export function registerWorkspaceTools(
|
|
|
1199
1200
|
// move the text with them. Rewritten in place: the registry holds this
|
|
1200
1201
|
// object, both surfaces hold the same one, and re-registering would be a
|
|
1201
1202
|
// duplicate name.
|
|
1202
|
-
|
|
1203
|
+
kb.onLayoutApplied(() => {
|
|
1203
1204
|
def.description = describe();
|
|
1204
1205
|
});
|
|
1205
1206
|
// Internal-only tools (e.g. `execute_command`) keep their route mounted —
|
|
@@ -1250,7 +1251,7 @@ export function registerWorkspaceTools(
|
|
|
1250
1251
|
err,
|
|
1251
1252
|
{ tool: spec.name, branch: args.branch, userEmail: ctx.user.email, userId: ctx.user.id },
|
|
1252
1253
|
accessControl,
|
|
1253
|
-
|
|
1254
|
+
kb,
|
|
1254
1255
|
changeGate,
|
|
1255
1256
|
);
|
|
1256
1257
|
}
|
|
@@ -1432,7 +1433,7 @@ export function registerWorkspaceTools(
|
|
|
1432
1433
|
description: () =>
|
|
1433
1434
|
'Get a file/directory\'s metadata (name, type, size, …) without returning content. A file also reports `contentMode`: `text` (read, write and edit it as text), `document` (read returns an extraction; replace it by upload) or `binary` (bytes: copy, move, delete, or replace by upload), plus `kind` (`text` | `document` | `image` | `binary`), `mime`, `mimeSource` and `textEditable` — decided by the same file readers read_file, grep and the write tools use, so an extensionless text file is `text/plain`.' +
|
|
1434
1435
|
' Every entry also reports what you may DO with it. ' +
|
|
1435
|
-
`\`managed\` is true for a platform item — a platform file (${platformFileList()}) or a platform folder (the repository root or a reserved root folder such as \`KnowledgeBase/\`); managed items are never movable or deletable through these tools. ` +
|
|
1436
|
+
`\`managed\` is true for a platform item — a platform file (${platformFileList(kb.layout)}) or a platform folder (the repository root or a reserved root folder such as \`KnowledgeBase/\`); managed items are never movable or deletable through these tools. ` +
|
|
1436
1437
|
'`access: { read, write, download, owner }` is your own verdict under the access rules; pass `explainAccess: true` to learn why, and who else holds each verb. `movable` and `deletable` say whether `move_file` / `delete_file` / `delete_folder` would be allowed for you, judged like their dry runs: not managed, no symbolic link, and on a protected branch you hold write on the item AND on every file under a folder (on a draft branch writes are not gated). `movable` judges the source side only; the destination is judged by a `move_file` dry run. ' +
|
|
1437
1438
|
'For a folder, `descendants` is the number of files under it at any depth; counting stops at 10000 and `descendantsTruncated` says so, and past that point `movable` and `deletable` are false because a folder that large was not judged in full — run the `move_file` or `delete_folder` dry run for the real verdict. ' +
|
|
1438
1439
|
'Call this before a move or delete to see what it would touch.' +
|
|
@@ -2042,7 +2043,7 @@ export function registerWorkspaceTools(
|
|
|
2042
2043
|
name: 'delete_file',
|
|
2043
2044
|
description: () =>
|
|
2044
2045
|
'Delete ONE workspace file (a symbolic link is refused: links are never followed or removed). Committed + pushed as you. Its folder stays, even when this was its last file. Files only: a folder is refused with a pointer to `delete_folder`. ' +
|
|
2045
|
-
`A platform file (\`access.md\` or \`.bevelignore\` in any folder, \`roles.yaml\` or \`${
|
|
2046
|
+
`A platform file (\`access.md\` or \`.bevelignore\` in any folder, \`roles.yaml\` or \`${kb.layout.agentsFile}\` at the repository root) and git metadata are refused.` +
|
|
2046
2047
|
ONTOLOGY_BOUNDARY_NOTE,
|
|
2047
2048
|
inputs: {
|
|
2048
2049
|
type: 'object',
|
|
@@ -2262,7 +2263,7 @@ export function registerWorkspaceTools(
|
|
|
2262
2263
|
name: 'move_file',
|
|
2263
2264
|
description: () =>
|
|
2264
2265
|
'Move or rename a workspace FILE or FOLDER; a folder moves recursively, with everything under it. `dest` is the full new path, not the folder to move into. Lands as a delete + create, committed + pushed as you. ' +
|
|
2265
|
-
`Rules: the destination must not exist — a move never overwrites a file or merges into a folder; a platform file (\`access.md\` or \`.bevelignore\` in any folder, \`roles.yaml\` or \`${
|
|
2266
|
+
`Rules: the destination must not exist — a move never overwrites a file or merges into a folder; a platform file (\`access.md\` or \`.bevelignore\` in any folder, \`roles.yaml\` or \`${kb.layout.agentsFile}\` at the repository root) is refused with "<name> is a platform file and stays in its folder." — a folder that moves takes its own platform files along, still in their folder; a platform folder (the repository root or a reserved root folder such as \`KnowledgeBase/\`) and git metadata are refused; a move cannot create a platform file or folder at \`dest\` either (renaming a note to \`access.md\` is refused); a path through a symbolic link is refused, since links are never followed; on a protected branch you must be able to write both ends — for a folder, every file under it at its old and its new path. ` +
|
|
2266
2267
|
'Access follows the destination folder. Preflight first: `dryRun: true` changes nothing and answers `{ src, dest, kind, descendants, access: { before, after }, accessChanges, allowed, reason? }` — `access` is your own `{ read, write, download, owner }` at the source and at the destination. ' +
|
|
2267
2268
|
'A move whose `accessChanges` is true runs only with `confirm: true`; without it the call moves nothing and returns the same impact with `confirmationRequired: true`. Do NOT set `confirm: true` on your first call — dry-run, check the impact, then confirm.' +
|
|
2268
2269
|
ONTOLOGY_BOUNDARY_NOTE,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { branchAuthorLocalpart,
|
|
1
|
+
import { branchAuthorLocalpart, suggestionsBranchPrefixFor } from '@bevel-software/platform-shared';
|
|
2
|
+
import type { KbContext } from '../../shared/kb-context.js';
|
|
2
3
|
import { ToolError } from '../tool-helpers/tool.contract.js';
|
|
3
4
|
import { AccessDeniedError } from '../access-model/access-errors.js';
|
|
4
5
|
import type { IChangeReadGate } from '../access-model/change-gate.js';
|
|
@@ -111,9 +112,10 @@ export async function writeDenial(
|
|
|
111
112
|
err: AccessDeniedError,
|
|
112
113
|
input: { tool: string; branch: string; userEmail: string; userId: string },
|
|
113
114
|
accessControl: IAccessControl,
|
|
114
|
-
|
|
115
|
+
kb: Pick<KbContext, 'kbDirName' | 'isProtectedBranch'>,
|
|
115
116
|
changeGate?: IChangeReadGate,
|
|
116
117
|
): Promise<ToolError> {
|
|
118
|
+
const { kbDirName } = kb;
|
|
117
119
|
const path = err.access.path;
|
|
118
120
|
const base = { kind: 'write-denied' as const, path, reason: reasonOf(err) };
|
|
119
121
|
const refuse = (cannotProposeReason: string): ToolError => {
|
|
@@ -121,7 +123,7 @@ export async function writeDenial(
|
|
|
121
123
|
return new ToolError(`${err.message} ${cannotProposeReason}`, 403, { ...details });
|
|
122
124
|
};
|
|
123
125
|
|
|
124
|
-
if (!isProtectedBranch(input.branch)) {
|
|
126
|
+
if (!kb.isProtectedBranch(input.branch)) {
|
|
125
127
|
return refuse(`Proposing is not available: "${input.branch}" is not a branch that accepts change requests.`);
|
|
126
128
|
}
|
|
127
129
|
// The lock gate reports workspace paths, the git gates repo-relative ones.
|
|
@@ -179,11 +181,11 @@ export async function rethrowAsWriteDenial(
|
|
|
179
181
|
err: unknown,
|
|
180
182
|
input: { tool: string; branch: unknown; userEmail: string; userId: string },
|
|
181
183
|
accessControl: IAccessControl,
|
|
182
|
-
|
|
184
|
+
kb: Pick<KbContext, 'kbDirName' | 'isProtectedBranch'>,
|
|
183
185
|
changeGate?: IChangeReadGate,
|
|
184
186
|
): Promise<never> {
|
|
185
187
|
if (err instanceof AccessDeniedError && typeof input.branch === 'string') {
|
|
186
|
-
throw await writeDenial(err, { ...input, branch: input.branch }, accessControl,
|
|
188
|
+
throw await writeDenial(err, { ...input, branch: input.branch }, accessControl, kb, changeGate);
|
|
187
189
|
}
|
|
188
190
|
throw err;
|
|
189
191
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { pluginOfPath, PLUGINS_DIR } from '@bevel-software/platform-shared';
|
|
2
|
+
import { DEFAULT_KB_LAYOUT, pluginOfPath, PLUGINS_DIR } from '@bevel-software/platform-shared';
|
|
3
|
+
|
|
4
|
+
/** `pluginOfPath` under the default layout, which these cases are written against. */
|
|
5
|
+
const plugin = (path: string) => pluginOfPath(path, DEFAULT_KB_LAYOUT);
|
|
3
6
|
|
|
4
7
|
/**
|
|
5
8
|
* `pluginOfPath` is the whole of the grouping contract — the sidebar, the
|
|
@@ -9,9 +12,9 @@ import { pluginOfPath, PLUGINS_DIR } from '@bevel-software/platform-shared';
|
|
|
9
12
|
*/
|
|
10
13
|
describe('pluginOfPath', () => {
|
|
11
14
|
it('reads the plugin from the Plugins root', () => {
|
|
12
|
-
expect(
|
|
13
|
-
expect(
|
|
14
|
-
expect(
|
|
15
|
+
expect(plugin(`${PLUGINS_DIR}/GTM/heyreach-campaign/SKILL.md`)).toBe('GTM');
|
|
16
|
+
expect(plugin(`${PLUGINS_DIR}/GTM/heyreach.tool`)).toBe('GTM');
|
|
17
|
+
expect(plugin(`${PLUGINS_DIR}/Engineering/review/architecture-review`)).toBe(
|
|
15
18
|
'Engineering',
|
|
16
19
|
);
|
|
17
20
|
});
|
|
@@ -19,27 +22,27 @@ describe('pluginOfPath', () => {
|
|
|
19
22
|
it('returns null for content directly under the root — it has no plugin folder', () => {
|
|
20
23
|
// The regression this guards: `Plugins/slack.tool` must NOT report a plugin
|
|
21
24
|
// called "slack.tool", and `Plugins/GTM` must not report itself.
|
|
22
|
-
expect(
|
|
23
|
-
expect(
|
|
24
|
-
expect(
|
|
25
|
+
expect(plugin(`${PLUGINS_DIR}/slack.tool`)).toBeNull();
|
|
26
|
+
expect(plugin(`${PLUGINS_DIR}/GTM`)).toBeNull();
|
|
27
|
+
expect(plugin(PLUGINS_DIR)).toBeNull();
|
|
25
28
|
});
|
|
26
29
|
|
|
27
30
|
it('returns null outside the plugin root', () => {
|
|
28
|
-
expect(
|
|
29
|
-
expect(
|
|
31
|
+
expect(plugin('KnowledgeBase/Product/Knowledge/Foo.md')).toBeNull();
|
|
32
|
+
expect(plugin('Data/Engineering/Knowledge/Bar.md')).toBeNull();
|
|
30
33
|
// The retired pre-merge roots are ordinary non-plugin folders now.
|
|
31
|
-
expect(
|
|
32
|
-
expect(
|
|
33
|
-
expect(
|
|
34
|
-
expect(
|
|
34
|
+
expect(plugin('Skills/GTM/heyreach-campaign')).toBeNull();
|
|
35
|
+
expect(plugin('Tools/NewsAgent/serper.tool')).toBeNull();
|
|
36
|
+
expect(plugin('access.md')).toBeNull();
|
|
37
|
+
expect(plugin('')).toBeNull();
|
|
35
38
|
});
|
|
36
39
|
|
|
37
40
|
it('is not fooled by a prefix match on the root name', () => {
|
|
38
|
-
expect(
|
|
41
|
+
expect(plugin('PluginsOld/GTM/x')).toBeNull();
|
|
39
42
|
});
|
|
40
43
|
|
|
41
44
|
it('tolerates leading and doubled separators', () => {
|
|
42
|
-
expect(
|
|
43
|
-
expect(
|
|
45
|
+
expect(plugin(`/${PLUGINS_DIR}/GTM/x`)).toBe('GTM');
|
|
46
|
+
expect(plugin(`${PLUGINS_DIR}//GTM//x`)).toBe('GTM');
|
|
44
47
|
});
|
|
45
48
|
});
|
|
@@ -39,21 +39,76 @@
|
|
|
39
39
|
*/
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
42
|
+
* The credential git authenticates a knowledge base's remote with: the
|
|
43
|
+
* Basic-auth username the host expects and the token that is its password.
|
|
44
|
+
*
|
|
45
|
+
* A PROVIDER, read at every call, not a value captured at boot: the setup
|
|
46
|
+
* screen can supply a token after the graph is built, and a token rotated in
|
|
47
|
+
* the settings has to be the one the next push carries. The runner puts the
|
|
48
|
+
* token into the child's environment under {@link GIT_TOKEN_ENV}, which is
|
|
49
|
+
* the only place git reads it from (the inline credential helper spells
|
|
50
|
+
* `password=$GITHUB_TOKEN`), so the value never enters argv, a clone's
|
|
51
|
+
* config, or a message that quotes either. Nothing writes it into THIS
|
|
52
|
+
* process's environment: a server hosting several knowledge bases has one
|
|
53
|
+
* environment and several tokens.
|
|
54
|
+
*/
|
|
55
|
+
export interface GitCredentials {
|
|
56
|
+
/**
|
|
57
|
+
* The username sent in the Basic credential: GitHub `x-access-token`,
|
|
58
|
+
* GitLab `oauth2`, Bitbucket `x-token-auth`. Interpolated into the helper
|
|
59
|
+
* snippet, so callers validate it against `[A-Za-z0-9._-]+` before it
|
|
60
|
+
* gets here.
|
|
61
|
+
*/
|
|
62
|
+
username(): string;
|
|
63
|
+
/** The token in effect, or null when the deployment has none configured. */
|
|
64
|
+
token(): string | null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** The username git is given when a deployment names none. */
|
|
68
|
+
export const DEFAULT_GIT_USERNAME = 'x-access-token';
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The environment variable the child git process reads the token from. The
|
|
72
|
+
* name is historical (the first supported host), and it is the literal every
|
|
73
|
+
* app-stamped credential helper carries, which is what lets a re-stamp find
|
|
74
|
+
* its own helpers in a clone's config and leave an operator's alone.
|
|
75
|
+
*/
|
|
76
|
+
export const GIT_TOKEN_ENV = 'GITHUB_TOKEN';
|
|
77
|
+
|
|
78
|
+
/** No token, the default username: an unauthenticated runner. */
|
|
79
|
+
export const NO_GIT_CREDENTIALS: GitCredentials = Object.freeze({
|
|
80
|
+
username: () => DEFAULT_GIT_USERNAME,
|
|
81
|
+
token: () => null,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
/** A provider from values or thunks, for a composition root or a test. */
|
|
85
|
+
export function gitCredentials(
|
|
86
|
+
username: string | (() => string) = DEFAULT_GIT_USERNAME,
|
|
87
|
+
token: string | null | (() => string | null) = null,
|
|
88
|
+
): GitCredentials {
|
|
89
|
+
const user = typeof username === 'function' ? username : () => username;
|
|
90
|
+
const secret = typeof token === 'function' ? token : () => token;
|
|
91
|
+
return {
|
|
92
|
+
username: () => user() || DEFAULT_GIT_USERNAME,
|
|
93
|
+
token: () => secret() || null,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Strip a git token out of text on its way into an error, a log line or a
|
|
99
|
+
* response.
|
|
44
100
|
*
|
|
45
101
|
* git puts the remote URL into a great many of its messages, and on a
|
|
46
102
|
* token-authenticated remote that URL carries the credential. Without this, a
|
|
47
103
|
* push failure writes the deployment's token into the container log, the API
|
|
48
104
|
* response, and any change request the recovery agent opens about it.
|
|
49
105
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
106
|
+
* The token is the caller's to name (the runner names its own), never read
|
|
107
|
+
* from this process's environment: the environment holds no per-knowledge-
|
|
108
|
+
* base token any more, and a scrub that silently found none there would look
|
|
109
|
+
* like one that worked.
|
|
54
110
|
*/
|
|
55
|
-
export function redactGitToken(text: string): string {
|
|
56
|
-
const token = process.env.GITHUB_TOKEN;
|
|
111
|
+
export function redactGitToken(text: string, token: string | null | undefined): string {
|
|
57
112
|
const scrubbed = token ? text.replaceAll(token, '***') : text;
|
|
58
113
|
// URL userinfo as well: a remote spelled `https://user:pass@host` would
|
|
59
114
|
// otherwise leak `pass` verbatim through every git failure that quotes the
|
|
@@ -165,6 +220,13 @@ export interface IGitRunner {
|
|
|
165
220
|
* constant.
|
|
166
221
|
*/
|
|
167
222
|
readonly defaultTimeoutMs: number;
|
|
223
|
+
/**
|
|
224
|
+
* The credential every call through this runner authenticates with — see
|
|
225
|
+
* {@link GitCredentials}. Exposed so the code that stamps a clone's helper
|
|
226
|
+
* or scrubs a message can ask the same runner it runs git through whether
|
|
227
|
+
* a token is in effect, rather than a second source that could disagree.
|
|
228
|
+
*/
|
|
229
|
+
readonly credentials: GitCredentials;
|
|
168
230
|
run(cwd: string, args: string[], opts: GitRunOptions & { encoding: 'buffer' }): Promise<GitRunResult<Buffer>>;
|
|
169
231
|
run(cwd: string, args: string[], opts?: GitRunOptions & { encoding?: 'utf8' }): Promise<GitRunResult>;
|
|
170
232
|
}
|