@bevel-software/platform-core-backend 0.13.6 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD-PARTY-NOTICES.md +6 -6
- package/dist/core/catalog-cache-invalidation.d.ts +29 -0
- package/dist/core/catalog-cache-invalidation.d.ts.map +1 -0
- package/dist/core/catalog-cache-invalidation.js +71 -0
- package/dist/core/catalog-cache-invalidation.js.map +1 -0
- package/dist/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +101 -9
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +20 -1
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +105 -43
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core-config.d.ts.map +1 -1
- package/dist/core-config.js +12 -5
- package/dist/core-config.js.map +1 -1
- package/dist/modules/access/access-control.interface.d.ts +18 -6
- package/dist/modules/access/access-control.interface.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +26 -1
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +213 -71
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/access.routes.d.ts.map +1 -1
- package/dist/modules/access/access.routes.js +59 -7
- package/dist/modules/access/access.routes.js.map +1 -1
- package/dist/modules/access-model/access-grammar.d.ts +51 -1
- package/dist/modules/access-model/access-grammar.d.ts.map +1 -1
- package/dist/modules/access-model/access-grammar.js +95 -1
- package/dist/modules/access-model/access-grammar.js.map +1 -1
- package/dist/modules/access-model/group-files.d.ts.map +1 -1
- package/dist/modules/access-model/group-files.js +4 -1
- package/dist/modules/access-model/group-files.js.map +1 -1
- package/dist/modules/access-model/kb-read-filter.d.ts +12 -0
- package/dist/modules/access-model/kb-read-filter.d.ts.map +1 -1
- package/dist/modules/access-model/kb-read-filter.js +15 -0
- package/dist/modules/access-model/kb-read-filter.js.map +1 -1
- package/dist/modules/access-model/plugin-principals.d.ts +49 -0
- package/dist/modules/access-model/plugin-principals.d.ts.map +1 -0
- package/dist/modules/access-model/plugin-principals.js +125 -0
- package/dist/modules/access-model/plugin-principals.js.map +1 -0
- package/dist/modules/connection-probe/connection-probe.contract.d.ts +43 -0
- package/dist/modules/connection-probe/connection-probe.contract.d.ts.map +1 -0
- package/dist/modules/connection-probe/connection-probe.contract.js +2 -0
- package/dist/modules/connection-probe/connection-probe.contract.js.map +1 -0
- package/dist/modules/connection-probe/connection-probe.service.d.ts +94 -0
- package/dist/modules/connection-probe/connection-probe.service.d.ts.map +1 -0
- package/dist/modules/connection-probe/connection-probe.service.js +684 -0
- package/dist/modules/connection-probe/connection-probe.service.js.map +1 -0
- package/dist/modules/connection-probe/index.d.ts +3 -0
- package/dist/modules/connection-probe/index.d.ts.map +1 -0
- package/dist/modules/connection-probe/index.js +3 -0
- package/dist/modules/connection-probe/index.js.map +1 -0
- package/dist/modules/database/core-schema.d.ts +326 -0
- package/dist/modules/database/core-schema.d.ts.map +1 -1
- package/dist/modules/database/core-schema.js +52 -0
- package/dist/modules/database/core-schema.js.map +1 -1
- package/dist/modules/diff/diff.routes.d.ts.map +1 -1
- package/dist/modules/diff/diff.routes.js +3 -5
- package/dist/modules/diff/diff.routes.js.map +1 -1
- package/dist/modules/kb-fs/mutex.d.ts +37 -0
- package/dist/modules/kb-fs/mutex.d.ts.map +1 -1
- package/dist/modules/kb-fs/mutex.js +48 -5
- package/dist/modules/kb-fs/mutex.js.map +1 -1
- package/dist/modules/kb-sync/index.d.ts +6 -0
- package/dist/modules/kb-sync/index.d.ts.map +1 -0
- package/dist/modules/kb-sync/index.js +5 -0
- package/dist/modules/kb-sync/index.js.map +1 -0
- package/dist/modules/kb-sync/kb-sync.interface.d.ts +77 -0
- package/dist/modules/kb-sync/kb-sync.interface.d.ts.map +1 -0
- package/dist/modules/kb-sync/kb-sync.interface.js +2 -0
- package/dist/modules/kb-sync/kb-sync.interface.js.map +1 -0
- package/dist/modules/kb-sync/kb-sync.routes.d.ts +70 -0
- package/dist/modules/kb-sync/kb-sync.routes.d.ts.map +1 -0
- package/dist/modules/kb-sync/kb-sync.routes.js +135 -0
- package/dist/modules/kb-sync/kb-sync.routes.js.map +1 -0
- package/dist/modules/kb-sync/kb-sync.service.d.ts +45 -0
- package/dist/modules/kb-sync/kb-sync.service.d.ts.map +1 -0
- package/dist/modules/kb-sync/kb-sync.service.js +183 -0
- package/dist/modules/kb-sync/kb-sync.service.js.map +1 -0
- package/dist/modules/kb-sync/sync-auth.d.ts +59 -0
- package/dist/modules/kb-sync/sync-auth.d.ts.map +1 -0
- package/dist/modules/kb-sync/sync-auth.js +62 -0
- package/dist/modules/kb-sync/sync-auth.js.map +1 -0
- package/dist/modules/kb-sync/sync-payload.d.ts +32 -0
- package/dist/modules/kb-sync/sync-payload.d.ts.map +1 -0
- package/dist/modules/kb-sync/sync-payload.js +105 -0
- package/dist/modules/kb-sync/sync-payload.js.map +1 -0
- package/dist/modules/marketplace/git-http.routes.d.ts +42 -0
- package/dist/modules/marketplace/git-http.routes.d.ts.map +1 -0
- package/dist/modules/marketplace/git-http.routes.js +190 -0
- package/dist/modules/marketplace/git-http.routes.js.map +1 -0
- package/dist/modules/marketplace/github-facade/github-facade-admin.routes.d.ts +23 -0
- package/dist/modules/marketplace/github-facade/github-facade-admin.routes.d.ts.map +1 -0
- package/dist/modules/marketplace/github-facade/github-facade-admin.routes.js +59 -0
- package/dist/modules/marketplace/github-facade/github-facade-admin.routes.js.map +1 -0
- package/dist/modules/marketplace/github-facade/github-facade-codes.store.d.ts +59 -0
- package/dist/modules/marketplace/github-facade/github-facade-codes.store.d.ts.map +1 -0
- package/dist/modules/marketplace/github-facade/github-facade-codes.store.js +96 -0
- package/dist/modules/marketplace/github-facade/github-facade-codes.store.js.map +1 -0
- package/dist/modules/marketplace/github-facade/github-facade-credentials.service.d.ts +99 -0
- package/dist/modules/marketplace/github-facade/github-facade-credentials.service.d.ts.map +1 -0
- package/dist/modules/marketplace/github-facade/github-facade-credentials.service.js +147 -0
- package/dist/modules/marketplace/github-facade/github-facade-credentials.service.js.map +1 -0
- package/dist/modules/marketplace/github-facade/github-facade.routes.d.ts +47 -0
- package/dist/modules/marketplace/github-facade/github-facade.routes.d.ts.map +1 -0
- package/dist/modules/marketplace/github-facade/github-facade.routes.js +228 -0
- package/dist/modules/marketplace/github-facade/github-facade.routes.js.map +1 -0
- package/dist/modules/marketplace/github-facade/github-facade.service.d.ts +109 -0
- package/dist/modules/marketplace/github-facade/github-facade.service.d.ts.map +1 -0
- package/dist/modules/marketplace/github-facade/github-facade.service.js +172 -0
- package/dist/modules/marketplace/github-facade/github-facade.service.js.map +1 -0
- package/dist/modules/marketplace/github-facade/index.d.ts +6 -0
- package/dist/modules/marketplace/github-facade/index.d.ts.map +1 -0
- package/dist/modules/marketplace/github-facade/index.js +6 -0
- package/dist/modules/marketplace/github-facade/index.js.map +1 -0
- package/dist/modules/marketplace/index.d.ts +4 -0
- package/dist/modules/marketplace/index.d.ts.map +1 -0
- package/dist/modules/marketplace/index.js +4 -0
- package/dist/modules/marketplace/index.js.map +1 -0
- package/dist/modules/marketplace/marketplace-repo.service.d.ts +122 -0
- package/dist/modules/marketplace/marketplace-repo.service.d.ts.map +1 -0
- package/dist/modules/marketplace/marketplace-repo.service.js +300 -0
- package/dist/modules/marketplace/marketplace-repo.service.js.map +1 -0
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js +4 -0
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
- package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts +14 -8
- package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts.map +1 -1
- package/dist/modules/mcp/oauth/oauth-consent.routes.js +13 -1
- package/dist/modules/mcp/oauth/oauth-consent.routes.js.map +1 -1
- package/dist/modules/mcp/oauth/oauth-state.d.ts +13 -2
- package/dist/modules/mcp/oauth/oauth-state.d.ts.map +1 -1
- package/dist/modules/mcp/oauth/oauth-state.js +3 -1
- package/dist/modules/mcp/oauth/oauth-state.js.map +1 -1
- package/dist/modules/plugins/compile/compile-marketplace.d.ts +97 -0
- package/dist/modules/plugins/compile/compile-marketplace.d.ts.map +1 -0
- package/dist/modules/plugins/compile/compile-marketplace.js +240 -0
- package/dist/modules/plugins/compile/compile-marketplace.js.map +1 -0
- package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts +66 -0
- package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts.map +1 -0
- package/dist/modules/plugins/compile/marketplace-compiler.service.js +132 -0
- package/dist/modules/plugins/compile/marketplace-compiler.service.js.map +1 -0
- package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts +37 -0
- package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts.map +1 -0
- package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js +135 -0
- package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js.map +1 -0
- package/dist/modules/plugins/discovery/bundle-dialect/registry.d.ts +45 -0
- package/dist/modules/plugins/discovery/bundle-dialect/registry.d.ts.map +1 -0
- package/dist/modules/plugins/discovery/bundle-dialect/registry.js +147 -0
- package/dist/modules/plugins/discovery/bundle-dialect/registry.js.map +1 -0
- package/dist/modules/plugins/discovery/kb-plugin-source.d.ts +37 -0
- package/dist/modules/plugins/discovery/kb-plugin-source.d.ts.map +1 -0
- package/dist/modules/plugins/discovery/kb-plugin-source.js +107 -0
- package/dist/modules/plugins/discovery/kb-plugin-source.js.map +1 -0
- package/dist/modules/plugins/discovery/native.source.d.ts +15 -0
- package/dist/modules/plugins/discovery/native.source.d.ts.map +1 -0
- package/dist/modules/plugins/discovery/native.source.js +102 -0
- package/dist/modules/plugins/discovery/native.source.js.map +1 -0
- package/dist/modules/plugins/discovery/plugin-source.d.ts +96 -0
- package/dist/modules/plugins/discovery/plugin-source.d.ts.map +1 -0
- package/dist/modules/plugins/discovery/plugin-source.js +2 -0
- package/dist/modules/plugins/discovery/plugin-source.js.map +1 -0
- package/dist/modules/plugins/index.d.ts +10 -1
- package/dist/modules/plugins/index.d.ts.map +1 -1
- package/dist/modules/plugins/index.js +8 -0
- package/dist/modules/plugins/index.js.map +1 -1
- package/dist/modules/plugins/plugin-links.d.ts +66 -0
- package/dist/modules/plugins/plugin-links.d.ts.map +1 -0
- package/dist/modules/plugins/plugin-links.js +160 -0
- package/dist/modules/plugins/plugin-links.js.map +1 -0
- package/dist/modules/plugins/plugin-links.service.d.ts +114 -0
- package/dist/modules/plugins/plugin-links.service.d.ts.map +1 -0
- package/dist/modules/plugins/plugin-links.service.js +304 -0
- package/dist/modules/plugins/plugin-links.service.js.map +1 -0
- package/dist/modules/plugins/plugin-provision.service.d.ts +39 -3
- package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
- package/dist/modules/plugins/plugin-provision.service.js +152 -52
- package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
- package/dist/modules/plugins/plugin-rename.service.d.ts +69 -0
- package/dist/modules/plugins/plugin-rename.service.d.ts.map +1 -0
- package/dist/modules/plugins/plugin-rename.service.js +245 -0
- package/dist/modules/plugins/plugin-rename.service.js.map +1 -0
- package/dist/modules/plugins/plugins.contract.d.ts +27 -1
- package/dist/modules/plugins/plugins.contract.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.routes.d.ts +7 -1
- package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.routes.js +120 -12
- package/dist/modules/plugins/plugins.routes.js.map +1 -1
- package/dist/modules/plugins/plugins.service.d.ts +50 -3
- package/dist/modules/plugins/plugins.service.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.service.js +108 -47
- package/dist/modules/plugins/plugins.service.js.map +1 -1
- package/dist/modules/secrets-vault/db-secrets-vault.service.js +1 -1
- package/dist/modules/secrets-vault/db-secrets-vault.service.js.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +6 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.js +31 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
- package/dist/modules/settings/deployment-settings.service.d.ts +9 -0
- package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
- package/dist/modules/settings/deployment-settings.service.js +82 -2
- package/dist/modules/settings/deployment-settings.service.js.map +1 -1
- package/dist/modules/settings/setup.routes.d.ts +26 -0
- package/dist/modules/settings/setup.routes.d.ts.map +1 -1
- package/dist/modules/settings/setup.routes.js +9 -1
- package/dist/modules/settings/setup.routes.js.map +1 -1
- package/dist/modules/skills/index.d.ts +1 -0
- package/dist/modules/skills/index.d.ts.map +1 -1
- package/dist/modules/skills/index.js +1 -0
- package/dist/modules/skills/index.js.map +1 -1
- package/dist/modules/skills/pending-skills.service.d.ts.map +1 -1
- package/dist/modules/skills/pending-skills.service.js +9 -4
- package/dist/modules/skills/pending-skills.service.js.map +1 -1
- package/dist/modules/skills/skill-access-requests.routes.d.ts +38 -0
- package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -0
- package/dist/modules/skills/skill-access-requests.routes.js +168 -0
- package/dist/modules/skills/skill-access-requests.routes.js.map +1 -0
- package/dist/modules/skills/skills.contract.d.ts +31 -0
- package/dist/modules/skills/skills.contract.d.ts.map +1 -1
- package/dist/modules/skills/skills.routes.d.ts +28 -3
- package/dist/modules/skills/skills.routes.d.ts.map +1 -1
- package/dist/modules/skills/skills.routes.js +42 -3
- package/dist/modules/skills/skills.routes.js.map +1 -1
- package/dist/modules/skills/skills.service.d.ts +4 -0
- package/dist/modules/skills/skills.service.d.ts.map +1 -1
- package/dist/modules/skills/skills.service.js +83 -22
- package/dist/modules/skills/skills.service.js.map +1 -1
- package/dist/modules/tool-auth/external-api-key.interface.d.ts +18 -1
- package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -1
- package/dist/modules/tool-auth/external-api-key.interface.js +2 -1
- package/dist/modules/tool-auth/external-api-key.interface.js.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.d.ts +13 -4
- package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.js +26 -9
- package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.d.ts +36 -0
- package/dist/modules/tool-manuals/mcp-json-discovery.d.ts.map +1 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.js +130 -83
- package/dist/modules/tool-manuals/mcp-json-discovery.js.map +1 -1
- package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/mcp-server-edit.service.js +10 -4
- package/dist/modules/tool-manuals/mcp-server-edit.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +83 -0
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts +15 -2
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +199 -38
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +58 -3
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +325 -60
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/git/pull-request.service.d.ts +6 -0
- package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/pull-request.service.js +8 -0
- package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
- package/dist/modules/workflow/workflow.routes.d.ts +2 -1
- package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.routes.js +98 -9
- package/dist/modules/workflow/workflow.routes.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts +133 -9
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +462 -52
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts +35 -0
- package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts.map +1 -0
- package/dist/modules/workspace/startup/steps/plugin-manifests.step.js +121 -0
- package/dist/modules/workspace/startup/steps/plugin-manifests.step.js.map +1 -0
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.js +46 -2
- package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-files.step.js +112 -25
- package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.routes.js +11 -14
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +38 -1
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +131 -20
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/shared/domain-errors.d.ts +20 -0
- package/dist/shared/domain-errors.d.ts.map +1 -1
- package/dist/shared/domain-errors.js +29 -0
- package/dist/shared/domain-errors.js.map +1 -1
- package/dist/shared/fs-errors.d.ts +8 -0
- package/dist/shared/fs-errors.d.ts.map +1 -0
- package/dist/shared/fs-errors.js +11 -0
- package/dist/shared/fs-errors.js.map +1 -0
- package/dist/shared/fs-walk.d.ts +20 -6
- package/dist/shared/fs-walk.d.ts.map +1 -1
- package/dist/shared/fs-walk.js +35 -27
- package/dist/shared/fs-walk.js.map +1 -1
- package/dist/shared/kb-walk.d.ts +52 -0
- package/dist/shared/kb-walk.d.ts.map +1 -0
- package/dist/shared/kb-walk.js +76 -0
- package/dist/shared/kb-walk.js.map +1 -0
- package/dist/shared/path-order.d.ts +18 -0
- package/dist/shared/path-order.d.ts.map +1 -0
- package/dist/shared/path-order.js +35 -0
- package/dist/shared/path-order.js.map +1 -0
- package/dist/shared/token-crypto.d.ts +17 -2
- package/dist/shared/token-crypto.d.ts.map +1 -1
- package/dist/shared/token-crypto.js +25 -8
- package/dist/shared/token-crypto.js.map +1 -1
- package/dist/shared/ttl-cache.d.ts +28 -1
- package/dist/shared/ttl-cache.d.ts.map +1 -1
- package/dist/shared/ttl-cache.js +33 -1
- package/dist/shared/ttl-cache.js.map +1 -1
- package/kb-template/.bevelignore +1 -1
- package/kb-template/AGENTS.md +95 -30
- package/kb-template/Skills/.gitkeep +0 -0
- package/migrations/0005_github_facade.sql +25 -0
- package/migrations/meta/0005_snapshot.json +1717 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +6 -6
- package/src/__tests__/core-config.admin.test.ts +21 -0
- package/src/__tests__/kb-layout-config.test.ts +110 -0
- package/src/core/__tests__/catalog-cache-invalidation.test.ts +146 -0
- package/src/core/catalog-cache-invalidation.ts +92 -0
- package/src/core/create-core-server.ts +126 -7
- package/src/core/create-core-services.ts +173 -41
- package/src/core-config.ts +14 -7
- package/src/modules/access/__tests__/access-control.invalidate-race.test.ts +86 -0
- package/src/modules/access/__tests__/access-control.service.test.ts +19 -3
- package/src/modules/access/__tests__/access-plugin-principals.test.ts +368 -0
- package/src/modules/access/__tests__/groups-admin.service.test.ts +8 -0
- package/src/modules/access/access-control.interface.ts +20 -9
- package/src/modules/access/access-control.service.ts +240 -78
- package/src/modules/access/access.routes.ts +96 -14
- package/src/modules/access-model/__tests__/access-grammar.test.ts +18 -0
- package/src/modules/access-model/__tests__/plugin-token-canonical.test.ts +40 -0
- package/src/modules/access-model/access-grammar.ts +114 -2
- package/src/modules/access-model/group-files.ts +4 -0
- package/src/modules/access-model/kb-read-filter.ts +22 -0
- package/src/modules/access-model/plugin-principals.ts +137 -0
- package/src/modules/connection-probe/__tests__/connection-probe.service.test.ts +685 -0
- package/src/modules/connection-probe/connection-probe.contract.ts +44 -0
- package/src/modules/connection-probe/connection-probe.service.ts +734 -0
- package/src/modules/connection-probe/index.ts +2 -0
- package/src/modules/database/core-schema.ts +54 -0
- package/src/modules/diff/diff.routes.ts +9 -5
- package/src/modules/kb-fs/__tests__/mutex.test.ts +107 -0
- package/src/modules/kb-fs/mutex.ts +50 -5
- package/src/modules/kb-sync/__tests__/kb-sync.routes.test.ts +297 -0
- package/src/modules/kb-sync/__tests__/kb-sync.service.test.ts +295 -0
- package/src/modules/kb-sync/__tests__/sync-auth.test.ts +118 -0
- package/src/modules/kb-sync/__tests__/sync-payload.test.ts +148 -0
- package/src/modules/kb-sync/index.ts +19 -0
- package/src/modules/kb-sync/kb-sync.interface.ts +79 -0
- package/src/modules/kb-sync/kb-sync.routes.ts +197 -0
- package/src/modules/kb-sync/kb-sync.service.ts +201 -0
- package/src/modules/kb-sync/sync-auth.ts +118 -0
- package/src/modules/kb-sync/sync-payload.ts +143 -0
- package/src/modules/marketplace/__tests__/github-facade.test.ts +443 -0
- package/src/modules/marketplace/__tests__/marketplace-git.test.ts +179 -0
- package/src/modules/marketplace/git-http.routes.ts +193 -0
- package/src/modules/marketplace/github-facade/github-facade-admin.routes.ts +78 -0
- package/src/modules/marketplace/github-facade/github-facade-codes.store.ts +145 -0
- package/src/modules/marketplace/github-facade/github-facade-credentials.service.ts +208 -0
- package/src/modules/marketplace/github-facade/github-facade.routes.ts +268 -0
- package/src/modules/marketplace/github-facade/github-facade.service.ts +221 -0
- package/src/modules/marketplace/github-facade/index.ts +25 -0
- package/src/modules/marketplace/index.ts +3 -0
- package/src/modules/marketplace/marketplace-repo.service.ts +337 -0
- package/src/modules/mcp/oauth/bevel-oauth-provider.ts +3 -0
- package/src/modules/mcp/oauth/oauth-consent.routes.ts +24 -2
- package/src/modules/mcp/oauth/oauth-state.ts +15 -3
- package/src/modules/plugins/__tests__/bundle-dialect.e2e.test.ts +163 -0
- package/src/modules/plugins/__tests__/compile-marketplace.test.ts +294 -0
- package/src/modules/plugins/__tests__/plugin-index.service.test.ts +56 -12
- package/src/modules/plugins/__tests__/plugin-links.service.test.ts +287 -0
- package/src/modules/plugins/__tests__/plugin-provision.service.test.ts +205 -5
- package/src/modules/plugins/__tests__/plugin-rename.service.test.ts +394 -0
- package/src/modules/plugins/__tests__/plugins.routes.test.ts +80 -33
- package/src/modules/plugins/compile/compile-marketplace.ts +403 -0
- package/src/modules/plugins/compile/marketplace-compiler.service.ts +150 -0
- package/src/modules/plugins/discovery/__tests__/kb-plugin-source.test.ts +329 -0
- package/src/modules/plugins/discovery/bundle-dialect/bundle.source.ts +140 -0
- package/src/modules/plugins/discovery/bundle-dialect/registry.ts +175 -0
- package/src/modules/plugins/discovery/kb-plugin-source.ts +114 -0
- package/src/modules/plugins/discovery/native.source.ts +122 -0
- package/src/modules/plugins/discovery/plugin-source.ts +99 -0
- package/src/modules/plugins/index.ts +10 -0
- package/src/modules/plugins/plugin-links.service.ts +363 -0
- package/src/modules/plugins/plugin-links.ts +184 -0
- package/src/modules/plugins/plugin-provision.service.ts +160 -54
- package/src/modules/plugins/plugin-rename.service.ts +298 -0
- package/src/modules/plugins/plugins.contract.ts +28 -1
- package/src/modules/plugins/plugins.routes.ts +128 -11
- package/src/modules/plugins/plugins.service.ts +106 -53
- package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +12 -0
- package/src/modules/secrets-vault/__tests__/oauth-return-to.route.test.ts +10 -3
- package/src/modules/secrets-vault/__tests__/tool-owner-gate.route.test.ts +26 -0
- package/src/modules/secrets-vault/db-secrets-vault.service.ts +1 -1
- package/src/modules/secrets-vault/secrets-vault.routes.ts +35 -1
- package/src/modules/settings/__tests__/deployment-settings.service.test.ts +57 -0
- package/src/modules/settings/__tests__/setup.routes.sync-status.test.ts +77 -0
- package/src/modules/settings/deployment-settings.service.ts +95 -2
- package/src/modules/settings/setup.routes.ts +24 -0
- package/src/modules/skills/__tests__/skill-access-requests.routes.test.ts +128 -0
- package/src/modules/skills/__tests__/skills.service.test.ts +85 -0
- package/src/modules/skills/index.ts +1 -0
- package/src/modules/skills/pending-skills.service.ts +7 -5
- package/src/modules/skills/skill-access-requests.routes.ts +199 -0
- package/src/modules/skills/skills.contract.ts +32 -0
- package/src/modules/skills/skills.routes.ts +59 -3
- package/src/modules/skills/skills.service.ts +84 -22
- package/src/modules/tool-auth/external-api-key.interface.ts +20 -1
- package/src/modules/tool-auth/external-api-key.service.ts +31 -13
- package/src/modules/tool-manuals/__tests__/mcp-json-discovery.test.ts +35 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.cli.test.ts +2 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.health-check.test.ts +104 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +56 -0
- package/src/modules/tool-manuals/mcp-json-discovery.ts +154 -76
- package/src/modules/tool-manuals/mcp-server-edit.service.ts +13 -4
- package/src/modules/tool-manuals/tool-manuals.contract.ts +89 -0
- package/src/modules/tool-manuals/tool-manuals.service.ts +210 -37
- package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +1 -1
- package/src/modules/workflow/__tests__/workflow.routes.history-read-gate.test.ts +139 -0
- package/src/modules/workflow/__tests__/workflow.service.branch-in-use.test.ts +337 -0
- package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +1 -0
- package/src/modules/workflow/__tests__/workflow.service.deleted-branch-sweep.test.ts +7 -1
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +97 -10
- package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +119 -2
- package/src/modules/workflow/__tests__/workflow.service.sync.test.ts +437 -0
- package/src/modules/workflow/git/__tests__/git.service.history-guards.test.ts +86 -0
- package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +3 -3
- package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +47 -4
- package/src/modules/workflow/git/__tests__/git.service.syncFromRemote.test.ts +253 -0
- package/src/modules/workflow/git/git.service.ts +354 -63
- package/src/modules/workflow/git/pull-request.service.ts +9 -0
- package/src/modules/workflow/workflow.routes.ts +104 -4
- package/src/modules/workflow/workflow.service.ts +505 -64
- package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +6 -7
- package/src/modules/workspace/__tests__/workspace.service.list-cloned.test.ts +93 -0
- package/src/modules/workspace/__tests__/workspace.service.missing-branch.test.ts +28 -0
- package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +42 -12
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +219 -4
- package/src/modules/workspace/startup/steps/plugin-manifests.step.ts +129 -0
- package/src/modules/workspace/startup/steps/seed-tree.ts +44 -2
- package/src/modules/workspace/startup/steps/template-files.step.ts +131 -27
- package/src/modules/workspace/workspace.routes.ts +17 -21
- package/src/modules/workspace/workspace.service.ts +128 -19
- package/src/shared/__tests__/filename.test.ts +0 -0
- package/src/shared/__tests__/fs-walk.test.ts +22 -1
- package/src/shared/__tests__/kb-walk.test.ts +107 -0
- package/src/shared/__tests__/path-order.test.ts +24 -0
- package/src/shared/__tests__/token-crypto.test.ts +34 -0
- package/src/shared/__tests__/ttl-cache.test.ts +55 -0
- package/src/shared/domain-errors.ts +29 -0
- package/src/shared/fs-errors.ts +10 -0
- package/src/shared/fs-walk.ts +38 -23
- package/src/shared/kb-walk.ts +95 -0
- package/src/shared/path-order.ts +33 -0
- package/src/shared/token-crypto.ts +28 -10
- package/src/shared/ttl-cache.ts +33 -1
|
@@ -7,5 +7,42 @@
|
|
|
7
7
|
export declare class WorkspaceMutex {
|
|
8
8
|
private readonly tails;
|
|
9
9
|
run<T>(key: string, fn: () => Promise<T>): Promise<T>;
|
|
10
|
+
/**
|
|
11
|
+
* Reserve SEVERAL keys for one operation, atomically.
|
|
12
|
+
*
|
|
13
|
+
* Nesting `run(a, () => run(b, fn))` does NOT do this: between taking `a`
|
|
14
|
+
* and taking `b` there is a gap in which another operation can take `b`,
|
|
15
|
+
* finish, and release it — so an operation holding both keys can still be
|
|
16
|
+
* interleaved with one holding just the second. For branch lifecycle that
|
|
17
|
+
* gap is the whole bug: a change request being opened `Y -> X` would hold
|
|
18
|
+
* one branch's key while the other was deleted out from under it.
|
|
19
|
+
*
|
|
20
|
+
* This reserves the set in ONE synchronous step. The tails are read and
|
|
21
|
+
* rewritten without an await between, so no other call can observe a
|
|
22
|
+
* half-taken set: a concurrent `run` on any of these keys either already
|
|
23
|
+
* sits in `prev` (it goes first) or chains onto `next` (it goes after).
|
|
24
|
+
* Within one call nothing is ever held while waiting for something else,
|
|
25
|
+
* so callers that do not nest need no ordering discipline and cannot
|
|
26
|
+
* deadlock.
|
|
27
|
+
*
|
|
28
|
+
* NESTING is the one way to reintroduce hold-and-wait, so never nest
|
|
29
|
+
* `run`/`runAll` calls on the same instance. An inner call chains behind
|
|
30
|
+
* everything already queued on its keys, which can include a `runAll` that
|
|
31
|
+
* is itself waiting for the outer call to finish: `run(b, () => run(a, …))`
|
|
32
|
+
* was harmless when every operation took a single key, but against a
|
|
33
|
+
* concurrent `runAll([a, b])` it deadlocks — outer waits inner, inner
|
|
34
|
+
* waits the pair, the pair waits outer. No caller nests today; keep it
|
|
35
|
+
* that way, or hand the full key set to one `runAll` at the top.
|
|
36
|
+
*
|
|
37
|
+
* Duplicate keys collapse; the operation waits on each distinct key once.
|
|
38
|
+
*
|
|
39
|
+
* Each predecessor is caught INDIVIDUALLY, before the `Promise.all`. A bare
|
|
40
|
+
* `Promise.all` settles on the first rejection rather than waiting for the
|
|
41
|
+
* rest, so one key's task failing early would start this one while another
|
|
42
|
+
* key was still held — a failure on any key would punch a hole in the
|
|
43
|
+
* mutual exclusion of every key beside it. Catching first makes the
|
|
44
|
+
* combined promise wait for all of them to settle, however each ends.
|
|
45
|
+
*/
|
|
46
|
+
runAll<T>(keys: string[], fn: () => Promise<T>): Promise<T>;
|
|
10
47
|
}
|
|
11
48
|
//# sourceMappingURL=mutex.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutex.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-fs/mutex.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;IAEvD,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"mutex.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-fs/mutex.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;IAEvD,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAI3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACG,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAiBlE"}
|
|
@@ -7,15 +7,58 @@
|
|
|
7
7
|
export class WorkspaceMutex {
|
|
8
8
|
tails = new Map();
|
|
9
9
|
async run(key, fn) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
return this.runAll([key], fn);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Reserve SEVERAL keys for one operation, atomically.
|
|
14
|
+
*
|
|
15
|
+
* Nesting `run(a, () => run(b, fn))` does NOT do this: between taking `a`
|
|
16
|
+
* and taking `b` there is a gap in which another operation can take `b`,
|
|
17
|
+
* finish, and release it — so an operation holding both keys can still be
|
|
18
|
+
* interleaved with one holding just the second. For branch lifecycle that
|
|
19
|
+
* gap is the whole bug: a change request being opened `Y -> X` would hold
|
|
20
|
+
* one branch's key while the other was deleted out from under it.
|
|
21
|
+
*
|
|
22
|
+
* This reserves the set in ONE synchronous step. The tails are read and
|
|
23
|
+
* rewritten without an await between, so no other call can observe a
|
|
24
|
+
* half-taken set: a concurrent `run` on any of these keys either already
|
|
25
|
+
* sits in `prev` (it goes first) or chains onto `next` (it goes after).
|
|
26
|
+
* Within one call nothing is ever held while waiting for something else,
|
|
27
|
+
* so callers that do not nest need no ordering discipline and cannot
|
|
28
|
+
* deadlock.
|
|
29
|
+
*
|
|
30
|
+
* NESTING is the one way to reintroduce hold-and-wait, so never nest
|
|
31
|
+
* `run`/`runAll` calls on the same instance. An inner call chains behind
|
|
32
|
+
* everything already queued on its keys, which can include a `runAll` that
|
|
33
|
+
* is itself waiting for the outer call to finish: `run(b, () => run(a, …))`
|
|
34
|
+
* was harmless when every operation took a single key, but against a
|
|
35
|
+
* concurrent `runAll([a, b])` it deadlocks — outer waits inner, inner
|
|
36
|
+
* waits the pair, the pair waits outer. No caller nests today; keep it
|
|
37
|
+
* that way, or hand the full key set to one `runAll` at the top.
|
|
38
|
+
*
|
|
39
|
+
* Duplicate keys collapse; the operation waits on each distinct key once.
|
|
40
|
+
*
|
|
41
|
+
* Each predecessor is caught INDIVIDUALLY, before the `Promise.all`. A bare
|
|
42
|
+
* `Promise.all` settles on the first rejection rather than waiting for the
|
|
43
|
+
* rest, so one key's task failing early would start this one while another
|
|
44
|
+
* key was still held — a failure on any key would punch a hole in the
|
|
45
|
+
* mutual exclusion of every key beside it. Catching first makes the
|
|
46
|
+
* combined promise wait for all of them to settle, however each ends.
|
|
47
|
+
*/
|
|
48
|
+
async runAll(keys, fn) {
|
|
49
|
+
const distinct = [...new Set(keys)];
|
|
50
|
+
const prev = Promise.all(distinct.map((k) => (this.tails.get(k) ?? Promise.resolve()).catch(() => undefined)));
|
|
51
|
+
const next = prev.then(fn);
|
|
52
|
+
for (const k of distinct)
|
|
53
|
+
this.tails.set(k, next);
|
|
13
54
|
try {
|
|
14
55
|
return await next;
|
|
15
56
|
}
|
|
16
57
|
finally {
|
|
17
|
-
|
|
18
|
-
this.tails.
|
|
58
|
+
for (const k of distinct) {
|
|
59
|
+
if (this.tails.get(k) === next) {
|
|
60
|
+
this.tails.delete(k);
|
|
61
|
+
}
|
|
19
62
|
}
|
|
20
63
|
}
|
|
21
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutex.js","sourceRoot":"","sources":["../../../src/modules/kb-fs/mutex.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,OAAO,cAAc;IACR,KAAK,GAAG,IAAI,GAAG,EAA4B,CAAC;IAE7D,KAAK,CAAC,GAAG,CAAI,GAAW,EAAE,EAAoB;QAC5C,
|
|
1
|
+
{"version":3,"file":"mutex.js","sourceRoot":"","sources":["../../../src/modules/kb-fs/mutex.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,OAAO,cAAc;IACR,KAAK,GAAG,IAAI,GAAG,EAA4B,CAAC;IAE7D,KAAK,CAAC,GAAG,CAAI,GAAW,EAAE,EAAoB;QAC5C,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,KAAK,CAAC,MAAM,CAAI,IAAc,EAAE,EAAoB;QAClD,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CACtB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CACrF,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3B,KAAK,MAAM,CAAC,IAAI,QAAQ;YAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC;QACpB,CAAC;gBAAS,CAAC;YACT,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACzB,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;oBAC/B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { IKbSyncService, LastSync, SyncRequest, SyncResult, SyncWorkflowPort, SyncWorkspacePort, } from './kb-sync.interface.js';
|
|
2
|
+
export { KbSyncService } from './kb-sync.service.js';
|
|
3
|
+
export { createKbSyncRoutes, httpStatusFor, isSyncRawBodyPath, SYNC_RESPONSE_HEADER, SYNC_RESPONSE_MARKER, type KbSyncRouteDeps, } from './kb-sync.routes.js';
|
|
4
|
+
export { parseSyncPayload, type ParsedSyncPayload, type SyncPayloadSource } from './sync-payload.js';
|
|
5
|
+
export { verifySyncCredential, type SyncAuthInput, type SyncAuthResult, type SyncCredential } from './sync-auth.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-sync/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,QAAQ,EACR,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,eAAe,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACrG,OAAO,EAAE,oBAAoB,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { KbSyncService } from './kb-sync.service.js';
|
|
2
|
+
export { createKbSyncRoutes, httpStatusFor, isSyncRawBodyPath, SYNC_RESPONSE_HEADER, SYNC_RESPONSE_MARKER, } from './kb-sync.routes.js';
|
|
3
|
+
export { parseSyncPayload } from './sync-payload.js';
|
|
4
|
+
export { verifySyncCredential } from './sync-auth.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/kb-sync/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,GAErB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAkD,MAAM,mBAAmB,CAAC;AACrG,OAAO,EAAE,oBAAoB,EAAgE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { BranchSyncOutcome } from '@bevel-software/platform-shared';
|
|
2
|
+
/**
|
|
3
|
+
* Remote sync: a git host (Azure DevOps, GitHub, GitLab, a pipeline) tells
|
|
4
|
+
* Hexis "the repository changed" and Hexis brings the clones it holds up to
|
|
5
|
+
* date. The module owns the HTTP surface, the credential check, the payload
|
|
6
|
+
* parsing and the coalescing; every git operation happens behind the
|
|
7
|
+
* workflow port below, never here.
|
|
8
|
+
*/
|
|
9
|
+
/** Which branches a caller asked to sync. `'all'` = every clone Hexis holds. */
|
|
10
|
+
export interface SyncRequest {
|
|
11
|
+
branches: string[] | 'all';
|
|
12
|
+
/** Who asked — a credential kind or an admin's email — for the last-sync record. */
|
|
13
|
+
by?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* What the most recent sync did, for the admin's Deployment page. Kept in
|
|
17
|
+
* memory only: it answers "is the hook wired up and working?", and a restart
|
|
18
|
+
* resetting it to "none yet" is the honest answer for a fresh process.
|
|
19
|
+
*/
|
|
20
|
+
export interface LastSync {
|
|
21
|
+
/** Epoch ms when the sync finished. */
|
|
22
|
+
at: number;
|
|
23
|
+
by: string;
|
|
24
|
+
status: SyncResult['status'];
|
|
25
|
+
/** One entry per branch, as the response carried them. */
|
|
26
|
+
results: BranchSyncOutcome[];
|
|
27
|
+
}
|
|
28
|
+
export interface SyncResult {
|
|
29
|
+
/** `synced` when no branch needs a person or a retry; `partial` otherwise. */
|
|
30
|
+
status: 'synced' | 'partial';
|
|
31
|
+
results: BranchSyncOutcome[];
|
|
32
|
+
changeRequests: {
|
|
33
|
+
/** Open change requests closed because one of their branches is gone from the host. */
|
|
34
|
+
closedDeletedBranch: number;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export interface IKbSyncService {
|
|
38
|
+
/**
|
|
39
|
+
* Sync the requested branches. One sync runs at a time; a request arriving
|
|
40
|
+
* mid-run is folded into a single queued follow-up (the union of every
|
|
41
|
+
* request that arrived meanwhile) and resolves with that follow-up's result.
|
|
42
|
+
* Never rejects for a per-branch failure — those are outcomes.
|
|
43
|
+
*/
|
|
44
|
+
sync(request: SyncRequest): Promise<SyncResult>;
|
|
45
|
+
/** The most recent completed sync in this process, or null before the first. */
|
|
46
|
+
lastSync(): LastSync | null;
|
|
47
|
+
}
|
|
48
|
+
/** The slice of the workflow module a sync drives. */
|
|
49
|
+
export interface SyncWorkflowPort {
|
|
50
|
+
syncWorkspaceFromRemote(workspaceId: string): Promise<BranchSyncOutcome>;
|
|
51
|
+
/**
|
|
52
|
+
* Retire the clone of a branch the host deleted, under the branch-lifecycle
|
|
53
|
+
* lock and only if origin still lacks it. Returns whether it was removed.
|
|
54
|
+
*/
|
|
55
|
+
retireRemoteGoneClone(workspaceId: string): Promise<boolean>;
|
|
56
|
+
/** The existing sweep; returns how many requests it closed. */
|
|
57
|
+
closeChangeRequestsWithDeletedBranches(): Promise<number>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The slice of the workspace module a sync reads: which clones exist ON
|
|
61
|
+
* DISK. Not the in-memory "seen this process" cache — clones survive a
|
|
62
|
+
* restart and a hook that fires before anyone has opened a branch must still
|
|
63
|
+
* find them.
|
|
64
|
+
*/
|
|
65
|
+
export interface SyncWorkspacePort {
|
|
66
|
+
/**
|
|
67
|
+
* `unreadable` names a clone the listing could see but not probe (an ACL,
|
|
68
|
+
* a half-deleted directory); the sync reports it as that branch's error
|
|
69
|
+
* rather than letting one bad directory fail every other branch.
|
|
70
|
+
*/
|
|
71
|
+
listClonedWorkspaces(): Promise<Array<{
|
|
72
|
+
id: string;
|
|
73
|
+
branch: string;
|
|
74
|
+
unreadable?: string;
|
|
75
|
+
}>>;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=kb-sync.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kb-sync.interface.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-sync/kb-sync.interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAEzE;;;;;;GAMG;AAEH,gFAAgF;AAChF,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAC3B,oFAAoF;IACpF,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,uCAAuC;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC7B,0DAA0D;IAC1D,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,UAAU;IACzB,8EAA8E;IAC9E,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,cAAc,EAAE;QACd,uFAAuF;QACvF,mBAAmB,EAAE,MAAM,CAAC;KAC7B,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAChD,gFAAgF;IAChF,QAAQ,IAAI,QAAQ,GAAG,IAAI,CAAC;CAC7B;AAED,sDAAsD;AACtD,MAAM,WAAW,gBAAgB;IAC/B,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACzE;;;OAGG;IACH,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,+DAA+D;IAC/D,sCAAsC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3D;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,oBAAoB,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;CAC7F"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kb-sync.interface.js","sourceRoot":"","sources":["../../../src/modules/kb-sync/kb-sync.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import type { IAdminAccessService } from '../admin/admin.interface.js';
|
|
3
|
+
import type { IKbSyncService, SyncResult } from './kb-sync.interface.js';
|
|
4
|
+
/**
|
|
5
|
+
* Remote sync — a git host or a pipeline tells Hexis the repository changed.
|
|
6
|
+
*
|
|
7
|
+
* POST /api/sync/<branch> sync that one branch — the branch whose change
|
|
8
|
+
* made the call. What a GitHub Action or a
|
|
9
|
+
* pipeline step uses: the branch name goes in the
|
|
10
|
+
* URL, the body is ignored for branch selection.
|
|
11
|
+
* POST /api/sync the branches named by the body — an Azure
|
|
12
|
+
* DevOps service hook or a GitHub/GitLab webhook
|
|
13
|
+
* payload (they cannot template the URL), an
|
|
14
|
+
* explicit `{ "branches": [...] }`, or nothing,
|
|
15
|
+
* which syncs every clone Hexis holds.
|
|
16
|
+
*
|
|
17
|
+
* Mounted BEFORE every JWT-protected `/api` mount: the caller is a machine
|
|
18
|
+
* holding the deployment's sync secret, not a browser session, and Express 5
|
|
19
|
+
* would otherwise 401 it in the first protected mount. The route parses its
|
|
20
|
+
* own body as raw bytes (the global JSON parser skips this path) because the
|
|
21
|
+
* GitHub-style credential is an HMAC over exactly the bytes that arrived.
|
|
22
|
+
*
|
|
23
|
+
* Status codes are chosen for the two kinds of caller. A pipeline's
|
|
24
|
+
* `curl --fail` must fail exactly when Hexis is not in sync; a webhook host
|
|
25
|
+
* retries 5xx and gives up on 4xx:
|
|
26
|
+
*
|
|
27
|
+
* 200 every branch updated, already current, or not cloned here
|
|
28
|
+
* 409 a branch has a CONFLICT: Hexis-side commits clash with the host.
|
|
29
|
+
* Automatic recovery is queued, but the branch is not in sync at the
|
|
30
|
+
* time of the answer; the body's `error` names the files. A retry
|
|
31
|
+
* answers 200 once recovery (or a person) has cleared it.
|
|
32
|
+
* 503 a branch could not be pulled (origin unreachable, credential
|
|
33
|
+
* refused) — retriable. Also: no sync secret configured.
|
|
34
|
+
* 401 missing or wrong credential
|
|
35
|
+
* 400 a branch name git would refuse, or a body that is not JSON
|
|
36
|
+
*/
|
|
37
|
+
export interface KbSyncRouteDeps {
|
|
38
|
+
kbSync: IKbSyncService;
|
|
39
|
+
/** The configured secret, read per request so a setup-screen save applies at once. */
|
|
40
|
+
syncSecret: () => string;
|
|
41
|
+
authService: {
|
|
42
|
+
verifyToken(token: string): {
|
|
43
|
+
userId: string;
|
|
44
|
+
email: string;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
adminAccess: IAdminAccessService;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Stamped on EVERY response this router writes. The endpoint answers 503 for
|
|
51
|
+
* an ordinary result (a branch could not be pulled), and a reverse proxy
|
|
52
|
+
* answers 503 when the backend is down; by status alone the browser cannot
|
|
53
|
+
* tell them apart, and it must — one is a line on the page, the other the
|
|
54
|
+
* maintenance overlay. A proxy standing in for a dead upstream never sets
|
|
55
|
+
* this header. Exposed to cross-origin callers in `create-core-server.ts`.
|
|
56
|
+
*/
|
|
57
|
+
export declare const SYNC_RESPONSE_HEADER = "X-Hexis-Sync";
|
|
58
|
+
export declare const SYNC_RESPONSE_MARKER = "result";
|
|
59
|
+
/**
|
|
60
|
+
* Whether a request path belongs to this router and must reach it with its
|
|
61
|
+
* body UNPARSED. The server's global JSON parser consults this: once that
|
|
62
|
+
* parser has read the stream, `express.raw` below sees nothing and the
|
|
63
|
+
* signature credential has no bytes to verify. Both routes share the check,
|
|
64
|
+
* so the branch form (`/api/sync/<branch>`) is covered as well as the bare
|
|
65
|
+
* one — an exact-path exemption used to protect only the latter.
|
|
66
|
+
*/
|
|
67
|
+
export declare function isSyncRawBodyPath(path: string): boolean;
|
|
68
|
+
export declare function httpStatusFor(result: SyncResult): 200 | 409 | 503;
|
|
69
|
+
export declare function createKbSyncRoutes(deps: KbSyncRouteDeps): express.Router;
|
|
70
|
+
//# sourceMappingURL=kb-sync.routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kb-sync.routes.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-sync/kb-sync.routes.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAIzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,cAAc,CAAC;IACvB,sFAAsF;IACtF,UAAU,EAAE,MAAM,MAAM,CAAC;IACzB,WAAW,EAAE;QAAE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAC/E,WAAW,EAAE,mBAAmB,CAAC;CAClC;AAKD;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,iBAAiB,CAAC;AACnD,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAE7C;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASvD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAIjE;AAID,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAsGxE"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { assertValidBranchName } from '../kb-fs/branch-name.js';
|
|
3
|
+
import { parseSyncPayload } from './sync-payload.js';
|
|
4
|
+
import { verifySyncCredential } from './sync-auth.js';
|
|
5
|
+
/** Cap on a webhook body. ADO's PR payloads run to a few hundred KB. */
|
|
6
|
+
const BODY_LIMIT = '2mb';
|
|
7
|
+
/**
|
|
8
|
+
* Stamped on EVERY response this router writes. The endpoint answers 503 for
|
|
9
|
+
* an ordinary result (a branch could not be pulled), and a reverse proxy
|
|
10
|
+
* answers 503 when the backend is down; by status alone the browser cannot
|
|
11
|
+
* tell them apart, and it must — one is a line on the page, the other the
|
|
12
|
+
* maintenance overlay. A proxy standing in for a dead upstream never sets
|
|
13
|
+
* this header. Exposed to cross-origin callers in `create-core-server.ts`.
|
|
14
|
+
*/
|
|
15
|
+
export const SYNC_RESPONSE_HEADER = 'X-Hexis-Sync';
|
|
16
|
+
export const SYNC_RESPONSE_MARKER = 'result';
|
|
17
|
+
/**
|
|
18
|
+
* Whether a request path belongs to this router and must reach it with its
|
|
19
|
+
* body UNPARSED. The server's global JSON parser consults this: once that
|
|
20
|
+
* parser has read the stream, `express.raw` below sees nothing and the
|
|
21
|
+
* signature credential has no bytes to verify. Both routes share the check,
|
|
22
|
+
* so the branch form (`/api/sync/<branch>`) is covered as well as the bare
|
|
23
|
+
* one — an exact-path exemption used to protect only the latter.
|
|
24
|
+
*/
|
|
25
|
+
export function isSyncRawBodyPath(path) {
|
|
26
|
+
// Case-insensitive, because Express routing is: `/api/Sync` reaches this
|
|
27
|
+
// router, and if this check said no the global parser would eat the body
|
|
28
|
+
// first. On either form a signed call would then 401 (no bytes to verify).
|
|
29
|
+
// On the bare form a bearer call would silently sync every clone, since a
|
|
30
|
+
// body that is no longer a Buffer parses as "no body"; the branch form is
|
|
31
|
+
// unaffected there, its branch comes from the URL.
|
|
32
|
+
const lower = path.toLowerCase();
|
|
33
|
+
return lower === '/api/sync' || lower.startsWith('/api/sync/');
|
|
34
|
+
}
|
|
35
|
+
export function httpStatusFor(result) {
|
|
36
|
+
if (result.results.some((r) => r.outcome === 'conflict'))
|
|
37
|
+
return 409;
|
|
38
|
+
if (result.results.some((r) => r.outcome === 'error'))
|
|
39
|
+
return 503;
|
|
40
|
+
return 200;
|
|
41
|
+
}
|
|
42
|
+
export function createKbSyncRoutes(deps) {
|
|
43
|
+
const router = express.Router();
|
|
44
|
+
const rawBody = express.raw({ type: () => true, limit: BODY_LIMIT });
|
|
45
|
+
/**
|
|
46
|
+
* Everything both routes share: the credential check, then the sync and
|
|
47
|
+
* its answer. `select` turns the request into the branches to sync, or
|
|
48
|
+
* sends its own 400 and returns null.
|
|
49
|
+
*/
|
|
50
|
+
async function handle(req, res, select) {
|
|
51
|
+
res.setHeader(SYNC_RESPONSE_HEADER, SYNC_RESPONSE_MARKER);
|
|
52
|
+
const raw = Buffer.isBuffer(req.body) ? req.body : undefined;
|
|
53
|
+
const auth = await verifySyncCredential({
|
|
54
|
+
secret: deps.syncSecret(),
|
|
55
|
+
authorization: header(req, 'authorization'),
|
|
56
|
+
gitlabToken: header(req, 'x-gitlab-token'),
|
|
57
|
+
hubSignature: header(req, 'x-hub-signature-256'),
|
|
58
|
+
rawBody: raw,
|
|
59
|
+
}, {
|
|
60
|
+
verifyJwt: (token) => {
|
|
61
|
+
try {
|
|
62
|
+
return { email: deps.authService.verifyToken(token).email };
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
isAdmin: (email) => deps.adminAccess.isAdmin(email),
|
|
69
|
+
});
|
|
70
|
+
if (!auth.ok) {
|
|
71
|
+
if (auth.status === 401)
|
|
72
|
+
res.setHeader('WWW-Authenticate', 'Bearer realm="hexis-sync"');
|
|
73
|
+
res.status(auth.status).json({ error: auth.message });
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const selection = select();
|
|
77
|
+
if (!selection)
|
|
78
|
+
return;
|
|
79
|
+
const who = auth.credential.kind === 'admin-session' ? auth.credential.email : auth.credential.kind;
|
|
80
|
+
const asked = selection.branches === 'all' ? 'all cloned branches' : selection.branches.join(', ') || '(none)';
|
|
81
|
+
try {
|
|
82
|
+
const result = await deps.kbSync.sync({ branches: selection.branches, by: who });
|
|
83
|
+
const summary = result.results.map((r) => `${r.branch}=${r.outcome}`).join(' ');
|
|
84
|
+
console.log(`[sync] by ${who} via ${selection.source} for ${asked}: ${result.status} ${summary}`);
|
|
85
|
+
res.status(httpStatusFor(result)).json(result);
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
console.error('[sync] unhandled error:', err);
|
|
89
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// The branch in the URL. A wildcard rather than `:branch` so a branch with
|
|
93
|
+
// slashes (`ali/new-skill`) works spelled either way — as segments or
|
|
94
|
+
// percent-encoded as one.
|
|
95
|
+
router.post('/sync/*branch', rawBody, (req, res) => handle(req, res, () => {
|
|
96
|
+
const param = req.params.branch;
|
|
97
|
+
const branch = (Array.isArray(param) ? param.join('/') : String(param ?? '')).trim();
|
|
98
|
+
try {
|
|
99
|
+
assertValidBranchName(branch);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
res.status(400).json({ error: `Not a valid branch name: ${branch}` });
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
return { source: 'path', branches: [branch] };
|
|
106
|
+
}));
|
|
107
|
+
router.post('/sync', rawBody, (req, res) => handle(req, res, () => {
|
|
108
|
+
const raw = Buffer.isBuffer(req.body) ? req.body : undefined;
|
|
109
|
+
let body = undefined;
|
|
110
|
+
if (raw && raw.length > 0) {
|
|
111
|
+
try {
|
|
112
|
+
body = JSON.parse(raw.toString('utf8'));
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
res.status(400).json({ error: 'The request body is not valid JSON.' });
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const parsed = parseSyncPayload(body);
|
|
120
|
+
if (parsed.invalid.length > 0) {
|
|
121
|
+
res.status(400).json({
|
|
122
|
+
error: `Not a valid branch name: ${parsed.invalid.join(', ')}`,
|
|
123
|
+
invalid: parsed.invalid,
|
|
124
|
+
});
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
return { source: parsed.source, branches: parsed.branches };
|
|
128
|
+
}));
|
|
129
|
+
return router;
|
|
130
|
+
}
|
|
131
|
+
function header(req, name) {
|
|
132
|
+
const v = req.headers[name];
|
|
133
|
+
return typeof v === 'string' ? v : undefined;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=kb-sync.routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kb-sync.routes.js","sourceRoot":"","sources":["../../../src/modules/kb-sync/kb-sync.routes.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAA0B,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AA2CtD,wEAAwE;AACxE,MAAM,UAAU,GAAG,KAAK,CAAC;AAEzB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,cAAc,CAAC;AACnD,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAAC;AAE7C;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,yEAAyE;IACzE,yEAAyE;IACzE,2EAA2E;IAC3E,0EAA0E;IAC1E,0EAA0E;IAC1E,mDAAmD;IACnD,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,OAAO,KAAK,KAAK,WAAW,IAAI,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAkB;IAC9C,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,UAAU,CAAC;QAAE,OAAO,GAAG,CAAC;IACrE,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC;QAAE,OAAO,GAAG,CAAC;IAClE,OAAO,GAAG,CAAC;AACb,CAAC;AAID,MAAM,UAAU,kBAAkB,CAAC,IAAqB;IACtD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAEhC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;IAErE;;;;OAIG;IACH,KAAK,UAAU,MAAM,CACnB,GAAoB,EACpB,GAAqB,EACrB,MAA8B;QAE9B,GAAG,CAAC,SAAS,CAAC,oBAAoB,EAAE,oBAAoB,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAuB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QAEjF,MAAM,IAAI,GAAG,MAAM,oBAAoB,CACrC;YACE,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE;YACzB,aAAa,EAAE,MAAM,CAAC,GAAG,EAAE,eAAe,CAAC;YAC3C,WAAW,EAAE,MAAM,CAAC,GAAG,EAAE,gBAAgB,CAAC;YAC1C,YAAY,EAAE,MAAM,CAAC,GAAG,EAAE,qBAAqB,CAAC;YAChD,OAAO,EAAE,GAAG;SACb,EACD;YACE,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;gBACnB,IAAI,CAAC;oBACH,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC;gBAC9D,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;SACpD,CACF,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG;gBAAE,GAAG,CAAC,SAAS,CAAC,kBAAkB,EAAE,2BAA2B,CAAC,CAAC;YACxF,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YACtD,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,SAAS;YAAE,OAAO;QAEvB,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QACpG,MAAM,KAAK,GACT,SAAS,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC;QACnG,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;YACjF,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChF,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,QAAQ,SAAS,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,CAAC,MAAM,IAAI,OAAO,EAAE,CAAC,CAAC;YAClG,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC;YAC9C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,2EAA2E;IAC3E,sEAAsE;IACtE,0BAA0B;IAC1B,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CACjD,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;QACpB,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,MAAiB,CAAC;QAC3C,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACrF,IAAI,CAAC;YACH,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,4BAA4B,MAAM,EAAE,EAAE,CAAC,CAAC;YACtE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;IAChD,CAAC,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CACzC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;QACpB,MAAM,GAAG,GAAuB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QACjF,IAAI,IAAI,GAAY,SAAS,CAAC;QAC9B,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qCAAqC,EAAE,CAAC,CAAC;gBACvE,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE,4BAA4B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAC9D,OAAO,EAAE,MAAM,CAAC,OAAO;aACxB,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC9D,CAAC,CAAC,CACH,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,MAAM,CAAC,GAAoB,EAAE,IAAY;IAChD,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { IKbSyncService, LastSync, SyncRequest, SyncResult, SyncWorkflowPort, SyncWorkspacePort } from './kb-sync.interface.js';
|
|
2
|
+
/**
|
|
3
|
+
* Runs remote syncs one at a time and folds everything that arrives
|
|
4
|
+
* mid-run into ONE follow-up.
|
|
5
|
+
*
|
|
6
|
+
* Why coalesce: a git host fires several hooks for one event — Azure DevOps
|
|
7
|
+
* sends a push, a PR-updated and a PR-merged within a second of each other —
|
|
8
|
+
* and each would otherwise queue behind the workspace mutex to pull the same
|
|
9
|
+
* tree again. The follow-up pulls the union of every request that arrived
|
|
10
|
+
* during the run (an "all" absorbs the rest).
|
|
11
|
+
*
|
|
12
|
+
* But each caller is answered for the branches IT asked about. The endpoint
|
|
13
|
+
* promises to fail exactly when the caller's branch is not in sync; a hook
|
|
14
|
+
* for branch A answered with branch B's conflict would fail the wrong
|
|
15
|
+
* subscription — and a host that disables subscriptions after repeated
|
|
16
|
+
* failures would disable the wrong one.
|
|
17
|
+
*
|
|
18
|
+
* Branches are pulled sequentially. N is small (only cloned branches count),
|
|
19
|
+
* the per-clone mutex serialises them anyway, and one slow origin round-trip
|
|
20
|
+
* at a time keeps the process calm during a burst.
|
|
21
|
+
*/
|
|
22
|
+
export declare class KbSyncService implements IKbSyncService {
|
|
23
|
+
private readonly workflow;
|
|
24
|
+
private readonly workspaces;
|
|
25
|
+
private readonly now;
|
|
26
|
+
private inFlight;
|
|
27
|
+
/** Everyone who arrived mid-run, each with what they asked for. */
|
|
28
|
+
private waiters;
|
|
29
|
+
private last;
|
|
30
|
+
constructor(workflow: SyncWorkflowPort, workspaces: SyncWorkspacePort, now?: () => number);
|
|
31
|
+
lastSync(): LastSync | null;
|
|
32
|
+
sync(request: SyncRequest): Promise<SyncResult>;
|
|
33
|
+
private start;
|
|
34
|
+
/**
|
|
35
|
+
* Run ONE follow-up for everyone who arrived during the last run: the union
|
|
36
|
+
* of their branches, then each waiter answered from its own share of the
|
|
37
|
+
* result — never from another caller's branches.
|
|
38
|
+
*/
|
|
39
|
+
private drain;
|
|
40
|
+
/** The part of a union run that answers one caller: its branches, and its status over them. */
|
|
41
|
+
private static subsetFor;
|
|
42
|
+
private static statusOf;
|
|
43
|
+
private run;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=kb-sync.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kb-sync.service.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-sync/kb-sync.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EACd,QAAQ,EACR,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAEhC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,aAAc,YAAW,cAAc;IAYhD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG;IAbtB,OAAO,CAAC,QAAQ,CAAiC;IACjD,mEAAmE;IACnE,OAAO,CAAC,OAAO,CAKP;IACR,OAAO,CAAC,IAAI,CAAyB;gBAGlB,QAAQ,EAAE,gBAAgB,EAC1B,UAAU,EAAE,iBAAiB,EAC7B,GAAG,GAAE,MAAM,MAAyB;IAGvD,QAAQ,IAAI,QAAQ,GAAG,IAAI;IAI3B,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAW/C,OAAO,CAAC,KAAK;IASb;;;;OAIG;IACH,OAAO,CAAC,KAAK;IA2Bb,+FAA+F;IAC/F,OAAO,CAAC,MAAM,CAAC,SAAS;IAWxB,OAAO,CAAC,MAAM,CAAC,QAAQ;YAWT,GAAG;CAyElB"}
|