@bevel-software/platform-core-backend 0.1.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/LICENSE +202 -0
- package/dist/assets.d.ts +5 -0
- package/dist/assets.d.ts.map +1 -0
- package/dist/assets.js +23 -0
- package/dist/assets.js.map +1 -0
- package/dist/core/core-ports.d.ts +83 -0
- package/dist/core/core-ports.d.ts.map +1 -0
- package/dist/core/core-ports.js +12 -0
- package/dist/core/core-ports.js.map +1 -0
- package/dist/core/create-core-server.d.ts +62 -0
- package/dist/core/create-core-server.d.ts.map +1 -0
- package/dist/core/create-core-server.js +204 -0
- package/dist/core/create-core-server.js.map +1 -0
- package/dist/core/create-core-services.d.ts +95 -0
- package/dist/core/create-core-services.d.ts.map +1 -0
- package/dist/core/create-core-services.js +352 -0
- package/dist/core/create-core-services.js.map +1 -0
- package/dist/core-config.d.ts +119 -0
- package/dist/core-config.d.ts.map +1 -0
- package/dist/core-config.js +240 -0
- package/dist/core-config.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/access/access-control.interface.d.ts +348 -0
- package/dist/modules/access/access-control.interface.d.ts.map +1 -0
- package/dist/modules/access/access-control.interface.js +2 -0
- package/dist/modules/access/access-control.interface.js.map +1 -0
- package/dist/modules/access/access-control.service.d.ts +323 -0
- package/dist/modules/access/access-control.service.d.ts.map +1 -0
- package/dist/modules/access/access-control.service.js +1431 -0
- package/dist/modules/access/access-control.service.js.map +1 -0
- package/dist/modules/access/access-errors.d.ts +34 -0
- package/dist/modules/access/access-errors.d.ts.map +1 -0
- package/dist/modules/access/access-errors.js +40 -0
- package/dist/modules/access/access-errors.js.map +1 -0
- package/dist/modules/access/access-mutation.service.d.ts +176 -0
- package/dist/modules/access/access-mutation.service.d.ts.map +1 -0
- package/dist/modules/access/access-mutation.service.js +307 -0
- package/dist/modules/access/access-mutation.service.js.map +1 -0
- package/dist/modules/access/access-splice.d.ts +98 -0
- package/dist/modules/access/access-splice.d.ts.map +1 -0
- package/dist/modules/access/access-splice.js +346 -0
- package/dist/modules/access/access-splice.js.map +1 -0
- package/dist/modules/access/access.routes.d.ts +10 -0
- package/dist/modules/access/access.routes.d.ts.map +1 -0
- package/dist/modules/access/access.routes.js +757 -0
- package/dist/modules/access/access.routes.js.map +1 -0
- package/dist/modules/access/creator-access.d.ts +113 -0
- package/dist/modules/access/creator-access.d.ts.map +1 -0
- package/dist/modules/access/creator-access.js +212 -0
- package/dist/modules/access/creator-access.js.map +1 -0
- package/dist/modules/access/kb-read-filter.d.ts +41 -0
- package/dist/modules/access/kb-read-filter.d.ts.map +1 -0
- package/dist/modules/access/kb-read-filter.js +60 -0
- package/dist/modules/access/kb-read-filter.js.map +1 -0
- package/dist/modules/access/roles-admin.service.d.ts +240 -0
- package/dist/modules/access/roles-admin.service.d.ts.map +1 -0
- package/dist/modules/access/roles-admin.service.js +630 -0
- package/dist/modules/access/roles-admin.service.js.map +1 -0
- package/dist/modules/access/roles-edit.d.ts +91 -0
- package/dist/modules/access/roles-edit.d.ts.map +1 -0
- package/dist/modules/access/roles-edit.js +232 -0
- package/dist/modules/access/roles-edit.js.map +1 -0
- package/dist/modules/access/roles-yaml-guard.d.ts +56 -0
- package/dist/modules/access/roles-yaml-guard.d.ts.map +1 -0
- package/dist/modules/access/roles-yaml-guard.js +79 -0
- package/dist/modules/access/roles-yaml-guard.js.map +1 -0
- package/dist/modules/admin/admin-access.routes.d.ts +18 -0
- package/dist/modules/admin/admin-access.routes.d.ts.map +1 -0
- package/dist/modules/admin/admin-access.routes.js +26 -0
- package/dist/modules/admin/admin-access.routes.js.map +1 -0
- package/dist/modules/admin/admin-access.service.d.ts +24 -0
- package/dist/modules/admin/admin-access.service.d.ts.map +1 -0
- package/dist/modules/admin/admin-access.service.js +41 -0
- package/dist/modules/admin/admin-access.service.js.map +1 -0
- package/dist/modules/admin/admin.interface.d.ts +11 -0
- package/dist/modules/admin/admin.interface.d.ts.map +1 -0
- package/dist/modules/admin/admin.interface.js +2 -0
- package/dist/modules/admin/admin.interface.js.map +1 -0
- package/dist/modules/auth/account-erasure.service.d.ts +80 -0
- package/dist/modules/auth/account-erasure.service.d.ts.map +1 -0
- package/dist/modules/auth/account-erasure.service.js +91 -0
- package/dist/modules/auth/account-erasure.service.js.map +1 -0
- package/dist/modules/auth/auth.middleware.d.ts +23 -0
- package/dist/modules/auth/auth.middleware.d.ts.map +1 -0
- package/dist/modules/auth/auth.middleware.js +68 -0
- package/dist/modules/auth/auth.middleware.js.map +1 -0
- package/dist/modules/auth/auth.routes.d.ts +25 -0
- package/dist/modules/auth/auth.routes.d.ts.map +1 -0
- package/dist/modules/auth/auth.routes.js +72 -0
- package/dist/modules/auth/auth.routes.js.map +1 -0
- package/dist/modules/auth/auth.service.d.ts +76 -0
- package/dist/modules/auth/auth.service.d.ts.map +1 -0
- package/dist/modules/auth/auth.service.js +168 -0
- package/dist/modules/auth/auth.service.js.map +1 -0
- package/dist/modules/code-mode/code-mode-names.d.ts +16 -0
- package/dist/modules/code-mode/code-mode-names.d.ts.map +1 -0
- package/dist/modules/code-mode/code-mode-names.js +30 -0
- package/dist/modules/code-mode/code-mode-names.js.map +1 -0
- package/dist/modules/code-mode/code-mode.tool.d.ts +13 -0
- package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -0
- package/dist/modules/code-mode/code-mode.tool.js +112 -0
- package/dist/modules/code-mode/code-mode.tool.js.map +1 -0
- package/dist/modules/code-mode/index.d.ts +3 -0
- package/dist/modules/code-mode/index.d.ts.map +1 -0
- package/dist/modules/code-mode/index.js +3 -0
- package/dist/modules/code-mode/index.js.map +1 -0
- package/dist/modules/database/connection.d.ts +6 -0
- package/dist/modules/database/connection.d.ts.map +1 -0
- package/dist/modules/database/connection.js +12 -0
- package/dist/modules/database/connection.js.map +1 -0
- package/dist/modules/database/core-schema.d.ts +2273 -0
- package/dist/modules/database/core-schema.d.ts.map +1 -0
- package/dist/modules/database/core-schema.js +413 -0
- package/dist/modules/database/core-schema.js.map +1 -0
- package/dist/modules/database/migrate.d.ts +10 -0
- package/dist/modules/database/migrate.d.ts.map +1 -0
- package/dist/modules/database/migrate.js +40 -0
- package/dist/modules/database/migrate.js.map +1 -0
- package/dist/modules/database/schema.d.ts +12 -0
- package/dist/modules/database/schema.d.ts.map +1 -0
- package/dist/modules/database/schema.js +12 -0
- package/dist/modules/database/schema.js.map +1 -0
- package/dist/modules/diff/diff-paths.d.ts +2 -0
- package/dist/modules/diff/diff-paths.d.ts.map +1 -0
- package/dist/modules/diff/diff-paths.js +9 -0
- package/dist/modules/diff/diff-paths.js.map +1 -0
- package/dist/modules/diff/diff.config.d.ts +8 -0
- package/dist/modules/diff/diff.config.d.ts.map +1 -0
- package/dist/modules/diff/diff.config.js +13 -0
- package/dist/modules/diff/diff.config.js.map +1 -0
- package/dist/modules/diff/diff.interface.d.ts +73 -0
- package/dist/modules/diff/diff.interface.d.ts.map +1 -0
- package/dist/modules/diff/diff.interface.js +2 -0
- package/dist/modules/diff/diff.interface.js.map +1 -0
- package/dist/modules/diff/diff.routes.d.ts +35 -0
- package/dist/modules/diff/diff.routes.d.ts.map +1 -0
- package/dist/modules/diff/diff.routes.js +228 -0
- package/dist/modules/diff/diff.routes.js.map +1 -0
- package/dist/modules/diff/diff.service.d.ts +51 -0
- package/dist/modules/diff/diff.service.d.ts.map +1 -0
- package/dist/modules/diff/diff.service.js +489 -0
- package/dist/modules/diff/diff.service.js.map +1 -0
- package/dist/modules/diff/line-diff.d.ts +16 -0
- package/dist/modules/diff/line-diff.d.ts.map +1 -0
- package/dist/modules/diff/line-diff.js +67 -0
- package/dist/modules/diff/line-diff.js.map +1 -0
- package/dist/modules/mcp/mcp-auth.middleware.d.ts +27 -0
- package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -0
- package/dist/modules/mcp/mcp-auth.middleware.js +116 -0
- package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -0
- package/dist/modules/mcp/mcp-session-store.d.ts +74 -0
- package/dist/modules/mcp/mcp-session-store.d.ts.map +1 -0
- package/dist/modules/mcp/mcp-session-store.js +131 -0
- package/dist/modules/mcp/mcp-session-store.js.map +1 -0
- package/dist/modules/mcp/mcp.routes.d.ts +24 -0
- package/dist/modules/mcp/mcp.routes.d.ts.map +1 -0
- package/dist/modules/mcp/mcp.routes.js +229 -0
- package/dist/modules/mcp/mcp.routes.js.map +1 -0
- package/dist/modules/mcp/mcp.service.d.ts +198 -0
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -0
- package/dist/modules/mcp/mcp.service.js +840 -0
- package/dist/modules/mcp/mcp.service.js.map +1 -0
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +76 -0
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -0
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js +291 -0
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -0
- package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts +18 -0
- package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts.map +1 -0
- package/dist/modules/mcp/oauth/oauth-consent.routes.js +52 -0
- package/dist/modules/mcp/oauth/oauth-consent.routes.js.map +1 -0
- package/dist/modules/mcp/oauth/oauth-state.d.ts +32 -0
- package/dist/modules/mcp/oauth/oauth-state.d.ts.map +1 -0
- package/dist/modules/mcp/oauth/oauth-state.js +34 -0
- package/dist/modules/mcp/oauth/oauth-state.js.map +1 -0
- package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts +92 -0
- package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts.map +1 -0
- package/dist/modules/secrets-vault/db-secrets-vault.service.js +728 -0
- package/dist/modules/secrets-vault/db-secrets-vault.service.js.map +1 -0
- package/dist/modules/secrets-vault/index.d.ts +7 -0
- package/dist/modules/secrets-vault/index.d.ts.map +1 -0
- package/dist/modules/secrets-vault/index.js +6 -0
- package/dist/modules/secrets-vault/index.js.map +1 -0
- package/dist/modules/secrets-vault/mcp-oauth-discovery.service.d.ts +63 -0
- package/dist/modules/secrets-vault/mcp-oauth-discovery.service.d.ts.map +1 -0
- package/dist/modules/secrets-vault/mcp-oauth-discovery.service.js +269 -0
- package/dist/modules/secrets-vault/mcp-oauth-discovery.service.js.map +1 -0
- package/dist/modules/secrets-vault/secrets-variable-loader.d.ts +46 -0
- package/dist/modules/secrets-vault/secrets-variable-loader.d.ts.map +1 -0
- package/dist/modules/secrets-vault/secrets-variable-loader.js +87 -0
- package/dist/modules/secrets-vault/secrets-variable-loader.js.map +1 -0
- package/dist/modules/secrets-vault/secrets-vault.contract.d.ts +210 -0
- package/dist/modules/secrets-vault/secrets-vault.contract.d.ts.map +1 -0
- package/dist/modules/secrets-vault/secrets-vault.contract.js +90 -0
- package/dist/modules/secrets-vault/secrets-vault.contract.js.map +1 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +30 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.js +490 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -0
- package/dist/modules/skills/index.d.ts +5 -0
- package/dist/modules/skills/index.d.ts.map +1 -0
- package/dist/modules/skills/index.js +4 -0
- package/dist/modules/skills/index.js.map +1 -0
- package/dist/modules/skills/skills.contract.d.ts +58 -0
- package/dist/modules/skills/skills.contract.d.ts.map +1 -0
- package/dist/modules/skills/skills.contract.js +10 -0
- package/dist/modules/skills/skills.contract.js.map +1 -0
- package/dist/modules/skills/skills.routes.d.ts +15 -0
- package/dist/modules/skills/skills.routes.d.ts.map +1 -0
- package/dist/modules/skills/skills.routes.js +34 -0
- package/dist/modules/skills/skills.routes.js.map +1 -0
- package/dist/modules/skills/skills.service.d.ts +21 -0
- package/dist/modules/skills/skills.service.d.ts.map +1 -0
- package/dist/modules/skills/skills.service.js +202 -0
- package/dist/modules/skills/skills.service.js.map +1 -0
- package/dist/modules/skills/skills.tools.d.ts +15 -0
- package/dist/modules/skills/skills.tools.d.ts.map +1 -0
- package/dist/modules/skills/skills.tools.js +96 -0
- package/dist/modules/skills/skills.tools.js.map +1 -0
- package/dist/modules/tool-auth/external-api-key.errors.d.ts +14 -0
- package/dist/modules/tool-auth/external-api-key.errors.d.ts.map +1 -0
- package/dist/modules/tool-auth/external-api-key.errors.js +23 -0
- package/dist/modules/tool-auth/external-api-key.errors.js.map +1 -0
- package/dist/modules/tool-auth/external-api-key.interface.d.ts +90 -0
- package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -0
- package/dist/modules/tool-auth/external-api-key.interface.js +2 -0
- package/dist/modules/tool-auth/external-api-key.interface.js.map +1 -0
- package/dist/modules/tool-auth/external-api-key.service.d.ts +25 -0
- package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -0
- package/dist/modules/tool-auth/external-api-key.service.js +164 -0
- package/dist/modules/tool-auth/external-api-key.service.js.map +1 -0
- package/dist/modules/tool-auth/internal-token.service.d.ts +62 -0
- package/dist/modules/tool-auth/internal-token.service.d.ts.map +1 -0
- package/dist/modules/tool-auth/internal-token.service.js +85 -0
- package/dist/modules/tool-auth/internal-token.service.js.map +1 -0
- package/dist/modules/tool-auth/llm-usage-meter.d.ts +16 -0
- package/dist/modules/tool-auth/llm-usage-meter.d.ts.map +1 -0
- package/dist/modules/tool-auth/llm-usage-meter.js +6 -0
- package/dist/modules/tool-auth/llm-usage-meter.js.map +1 -0
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts +101 -0
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -0
- package/dist/modules/tool-auth/tool-auth.middleware.js +166 -0
- package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -0
- package/dist/modules/tool-helpers/index.d.ts +19 -0
- package/dist/modules/tool-helpers/index.d.ts.map +1 -0
- package/dist/modules/tool-helpers/index.js +18 -0
- package/dist/modules/tool-helpers/index.js.map +1 -0
- package/dist/modules/tool-helpers/tool-context.d.ts +35 -0
- package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -0
- package/dist/modules/tool-helpers/tool-context.js +66 -0
- package/dist/modules/tool-helpers/tool-context.js.map +1 -0
- package/dist/modules/tool-helpers/tool-def.d.ts +33 -0
- package/dist/modules/tool-helpers/tool-def.d.ts.map +1 -0
- package/dist/modules/tool-helpers/tool-def.js +57 -0
- package/dist/modules/tool-helpers/tool-def.js.map +1 -0
- package/dist/modules/tool-helpers/tool-handler.d.ts +19 -0
- package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -0
- package/dist/modules/tool-helpers/tool-handler.js +84 -0
- package/dist/modules/tool-helpers/tool-handler.js.map +1 -0
- package/dist/modules/tool-helpers/tool.contract.d.ts +64 -0
- package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -0
- package/dist/modules/tool-helpers/tool.contract.js +24 -0
- package/dist/modules/tool-helpers/tool.contract.js.map +1 -0
- package/dist/modules/tool-helpers/validate-token.d.ts +31 -0
- package/dist/modules/tool-helpers/validate-token.d.ts.map +1 -0
- package/dist/modules/tool-helpers/validate-token.js +20 -0
- package/dist/modules/tool-helpers/validate-token.js.map +1 -0
- package/dist/modules/tool-manuals/index.d.ts +5 -0
- package/dist/modules/tool-manuals/index.d.ts.map +1 -0
- package/dist/modules/tool-manuals/index.js +5 -0
- package/dist/modules/tool-manuals/index.js.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +182 -0
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.contract.js +19 -0
- package/dist/modules/tool-manuals/tool-manuals.contract.js.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +24 -0
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.routes.js +102 -0
- package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts +108 -0
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.service.js +710 -0
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +35 -0
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.tools.js +157 -0
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -0
- package/dist/modules/tool-registry/manual.routes.d.ts +6 -0
- package/dist/modules/tool-registry/manual.routes.d.ts.map +1 -0
- package/dist/modules/tool-registry/manual.routes.js +76 -0
- package/dist/modules/tool-registry/manual.routes.js.map +1 -0
- package/dist/modules/tool-registry/tool-registry.d.ts +23 -0
- package/dist/modules/tool-registry/tool-registry.d.ts.map +1 -0
- package/dist/modules/tool-registry/tool-registry.js +46 -0
- package/dist/modules/tool-registry/tool-registry.js.map +1 -0
- package/dist/modules/tool-registry/tool.contract.d.ts +48 -0
- package/dist/modules/tool-registry/tool.contract.d.ts.map +1 -0
- package/dist/modules/tool-registry/tool.contract.js +2 -0
- package/dist/modules/tool-registry/tool.contract.js.map +1 -0
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +14 -0
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -0
- package/dist/modules/workflow/agent-tools/workflow.tools.js +437 -0
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -0
- package/dist/modules/workflow/event-bus.d.ts +107 -0
- package/dist/modules/workflow/event-bus.d.ts.map +1 -0
- package/dist/modules/workflow/event-bus.js +224 -0
- package/dist/modules/workflow/event-bus.js.map +1 -0
- package/dist/modules/workflow/events.routes.d.ts +80 -0
- package/dist/modules/workflow/events.routes.d.ts.map +1 -0
- package/dist/modules/workflow/events.routes.js +216 -0
- package/dist/modules/workflow/events.routes.js.map +1 -0
- package/dist/modules/workflow/file-change-notifier.d.ts +38 -0
- package/dist/modules/workflow/file-change-notifier.d.ts.map +1 -0
- package/dist/modules/workflow/file-change-notifier.js +22 -0
- package/dist/modules/workflow/file-change-notifier.js.map +1 -0
- package/dist/modules/workflow/file-lock.service.d.ts +57 -0
- package/dist/modules/workflow/file-lock.service.d.ts.map +1 -0
- package/dist/modules/workflow/file-lock.service.js +202 -0
- package/dist/modules/workflow/file-lock.service.js.map +1 -0
- package/dist/modules/workflow/git/branch-name.d.ts +10 -0
- package/dist/modules/workflow/git/branch-name.d.ts.map +1 -0
- package/dist/modules/workflow/git/branch-name.js +76 -0
- package/dist/modules/workflow/git/branch-name.js.map +1 -0
- package/dist/modules/workflow/git/clone-config.d.ts +61 -0
- package/dist/modules/workflow/git/clone-config.d.ts.map +1 -0
- package/dist/modules/workflow/git/clone-config.js +69 -0
- package/dist/modules/workflow/git/clone-config.js.map +1 -0
- package/dist/modules/workflow/git/git-version.d.ts +34 -0
- package/dist/modules/workflow/git/git-version.d.ts.map +1 -0
- package/dist/modules/workflow/git/git-version.js +63 -0
- package/dist/modules/workflow/git/git-version.js.map +1 -0
- package/dist/modules/workflow/git/git.service.d.ts +427 -0
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -0
- package/dist/modules/workflow/git/git.service.js +1987 -0
- package/dist/modules/workflow/git/git.service.js.map +1 -0
- package/dist/modules/workflow/git/mutex.d.ts +11 -0
- package/dist/modules/workflow/git/mutex.d.ts.map +1 -0
- package/dist/modules/workflow/git/mutex.js +23 -0
- package/dist/modules/workflow/git/mutex.js.map +1 -0
- package/dist/modules/workflow/git/pull-request.service.d.ts +124 -0
- package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -0
- package/dist/modules/workflow/git/pull-request.service.js +328 -0
- package/dist/modules/workflow/git/pull-request.service.js.map +1 -0
- package/dist/modules/workflow/locking-filesystem.d.ts +133 -0
- package/dist/modules/workflow/locking-filesystem.d.ts.map +1 -0
- package/dist/modules/workflow/locking-filesystem.js +400 -0
- package/dist/modules/workflow/locking-filesystem.js.map +1 -0
- package/dist/modules/workflow/pending-commits.service.d.ts +221 -0
- package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -0
- package/dist/modules/workflow/pending-commits.service.js +364 -0
- package/dist/modules/workflow/pending-commits.service.js.map +1 -0
- package/dist/modules/workflow/pending-commits.worker.d.ts +148 -0
- package/dist/modules/workflow/pending-commits.worker.d.ts.map +1 -0
- package/dist/modules/workflow/pending-commits.worker.js +245 -0
- package/dist/modules/workflow/pending-commits.worker.js.map +1 -0
- package/dist/modules/workflow/read-only-filesystem.d.ts +24 -0
- package/dist/modules/workflow/read-only-filesystem.d.ts.map +1 -0
- package/dist/modules/workflow/read-only-filesystem.js +39 -0
- package/dist/modules/workflow/read-only-filesystem.js.map +1 -0
- package/dist/modules/workflow/recovery-bot.d.ts +31 -0
- package/dist/modules/workflow/recovery-bot.d.ts.map +1 -0
- package/dist/modules/workflow/recovery-bot.js +64 -0
- package/dist/modules/workflow/recovery-bot.js.map +1 -0
- package/dist/modules/workflow/review-workflow/review-workflow.interface.d.ts +137 -0
- package/dist/modules/workflow/review-workflow/review-workflow.interface.d.ts.map +1 -0
- package/dist/modules/workflow/review-workflow/review-workflow.interface.js +2 -0
- package/dist/modules/workflow/review-workflow/review-workflow.interface.js.map +1 -0
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts +26 -0
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -0
- package/dist/modules/workflow/review-workflow/review-workflow.service.js +636 -0
- package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -0
- package/dist/modules/workflow/sanitize-error.d.ts +29 -0
- package/dist/modules/workflow/sanitize-error.d.ts.map +1 -0
- package/dist/modules/workflow/sanitize-error.js +60 -0
- package/dist/modules/workflow/sanitize-error.js.map +1 -0
- package/dist/modules/workflow/session-ontology.policy.d.ts +52 -0
- package/dist/modules/workflow/session-ontology.policy.d.ts.map +1 -0
- package/dist/modules/workflow/session-ontology.policy.js +62 -0
- package/dist/modules/workflow/session-ontology.policy.js.map +1 -0
- package/dist/modules/workflow/session-ontology.service.d.ts +100 -0
- package/dist/modules/workflow/session-ontology.service.d.ts.map +1 -0
- package/dist/modules/workflow/session-ontology.service.js +143 -0
- package/dist/modules/workflow/session-ontology.service.js.map +1 -0
- package/dist/modules/workflow/workflow-hooks.d.ts +87 -0
- package/dist/modules/workflow/workflow-hooks.d.ts.map +1 -0
- package/dist/modules/workflow/workflow-hooks.js +35 -0
- package/dist/modules/workflow/workflow-hooks.js.map +1 -0
- package/dist/modules/workflow/workflow.errors.d.ts +171 -0
- package/dist/modules/workflow/workflow.errors.d.ts.map +1 -0
- package/dist/modules/workflow/workflow.errors.js +260 -0
- package/dist/modules/workflow/workflow.errors.js.map +1 -0
- package/dist/modules/workflow/workflow.routes.d.ts +26 -0
- package/dist/modules/workflow/workflow.routes.d.ts.map +1 -0
- package/dist/modules/workflow/workflow.routes.js +804 -0
- package/dist/modules/workflow/workflow.routes.js.map +1 -0
- package/dist/modules/workflow/workflow.service.d.ts +385 -0
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -0
- package/dist/modules/workflow/workflow.service.js +1155 -0
- package/dist/modules/workflow/workflow.service.js.map +1 -0
- package/dist/modules/workspace/bevel-ignore.d.ts +25 -0
- package/dist/modules/workspace/bevel-ignore.d.ts.map +1 -0
- package/dist/modules/workspace/bevel-ignore.js +57 -0
- package/dist/modules/workspace/bevel-ignore.js.map +1 -0
- package/dist/modules/workspace/kb-seed.interface.d.ts +36 -0
- package/dist/modules/workspace/kb-seed.interface.d.ts.map +1 -0
- package/dist/modules/workspace/kb-seed.interface.js +2 -0
- package/dist/modules/workspace/kb-seed.interface.js.map +1 -0
- package/dist/modules/workspace/kb-seed.service.d.ts +70 -0
- package/dist/modules/workspace/kb-seed.service.d.ts.map +1 -0
- package/dist/modules/workspace/kb-seed.service.js +325 -0
- package/dist/modules/workspace/kb-seed.service.js.map +1 -0
- package/dist/modules/workspace/routine-write-policy.d.ts +49 -0
- package/dist/modules/workspace/routine-write-policy.d.ts.map +1 -0
- package/dist/modules/workspace/routine-write-policy.js +46 -0
- package/dist/modules/workspace/routine-write-policy.js.map +1 -0
- package/dist/modules/workspace/session-ontology.gate.d.ts +112 -0
- package/dist/modules/workspace/session-ontology.gate.d.ts.map +1 -0
- package/dist/modules/workspace/session-ontology.gate.js +161 -0
- package/dist/modules/workspace/session-ontology.gate.js.map +1 -0
- package/dist/modules/workspace/session-sink.d.ts +25 -0
- package/dist/modules/workspace/session-sink.d.ts.map +1 -0
- package/dist/modules/workspace/session-sink.js +8 -0
- package/dist/modules/workspace/session-sink.js.map +1 -0
- package/dist/modules/workspace/spill-store.d.ts +24 -0
- package/dist/modules/workspace/spill-store.d.ts.map +1 -0
- package/dist/modules/workspace/spill-store.js +87 -0
- package/dist/modules/workspace/spill-store.js.map +1 -0
- package/dist/modules/workspace/workspace.routes.d.ts +25 -0
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -0
- package/dist/modules/workspace/workspace.routes.js +1046 -0
- package/dist/modules/workspace/workspace.routes.js.map +1 -0
- package/dist/modules/workspace/workspace.service.d.ts +339 -0
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -0
- package/dist/modules/workspace/workspace.service.js +1221 -0
- package/dist/modules/workspace/workspace.service.js.map +1 -0
- package/dist/modules/workspace/workspace.tools.d.ts +19 -0
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -0
- package/dist/modules/workspace/workspace.tools.js +767 -0
- package/dist/modules/workspace/workspace.tools.js.map +1 -0
- package/dist/shared/frontmatter-id.d.ts +35 -0
- package/dist/shared/frontmatter-id.d.ts.map +1 -0
- package/dist/shared/frontmatter-id.js +68 -0
- package/dist/shared/frontmatter-id.js.map +1 -0
- package/dist/shared/fs-walk.d.ts +9 -0
- package/dist/shared/fs-walk.d.ts.map +1 -0
- package/dist/shared/fs-walk.js +34 -0
- package/dist/shared/fs-walk.js.map +1 -0
- package/dist/shared/hash-email.d.ts +11 -0
- package/dist/shared/hash-email.d.ts.map +1 -0
- package/dist/shared/hash-email.js +14 -0
- package/dist/shared/hash-email.js.map +1 -0
- package/dist/shared/kb-layout.d.ts +38 -0
- package/dist/shared/kb-layout.d.ts.map +1 -0
- package/dist/shared/kb-layout.js +102 -0
- package/dist/shared/kb-layout.js.map +1 -0
- package/dist/shared/kb-layout.test.d.ts +2 -0
- package/dist/shared/kb-layout.test.d.ts.map +1 -0
- package/dist/shared/kb-layout.test.js +67 -0
- package/dist/shared/kb-layout.test.js.map +1 -0
- package/dist/shared/ssrf.d.ts +20 -0
- package/dist/shared/ssrf.d.ts.map +1 -0
- package/dist/shared/ssrf.js +89 -0
- package/dist/shared/ssrf.js.map +1 -0
- package/dist/shared/token-crypto.d.ts +16 -0
- package/dist/shared/token-crypto.d.ts.map +1 -0
- package/dist/shared/token-crypto.js +49 -0
- package/dist/shared/token-crypto.js.map +1 -0
- package/dist/shared/ttl-cache.d.ts +16 -0
- package/dist/shared/ttl-cache.d.ts.map +1 -0
- package/dist/shared/ttl-cache.js +27 -0
- package/dist/shared/ttl-cache.js.map +1 -0
- package/dist/shared/utcp-namespace.d.ts +46 -0
- package/dist/shared/utcp-namespace.d.ts.map +1 -0
- package/dist/shared/utcp-namespace.js +82 -0
- package/dist/shared/utcp-namespace.js.map +1 -0
- package/dist/version.d.ts +17 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +19 -0
- package/dist/version.js.map +1 -0
- package/kb-template/.bevelignore +21 -0
- package/kb-template/Agents/.gitkeep +0 -0
- package/kb-template/Agents/README.md +38 -0
- package/kb-template/CLAUDE.md +419 -0
- package/kb-template/Data/.gitkeep +0 -0
- package/kb-template/Data/README.md +39 -0
- package/kb-template/KnowledgeBase/.gitkeep +0 -0
- package/kb-template/KnowledgeBase/README.md +37 -0
- package/kb-template/Pipelines/.gitkeep +0 -0
- package/kb-template/Pipelines/README.md +38 -0
- package/kb-template/Skills/.gitkeep +0 -0
- package/kb-template/Skills/README.md +32 -0
- package/kb-template/Tools/.gitkeep +0 -0
- package/kb-template/Tools/README.md +42 -0
- package/kb-template/access.md +36 -0
- package/migrations/0000_core_init.sql +243 -0
- package/migrations/meta/0000_snapshot.json +1480 -0
- package/migrations/meta/_journal.json +13 -0
- package/package.json +80 -0
- package/src/assets.ts +25 -0
- package/src/core/core-ports.ts +91 -0
- package/src/core/create-core-server.ts +338 -0
- package/src/core/create-core-services.ts +501 -0
- package/src/core-config.ts +257 -0
- package/src/index.ts +69 -0
- package/src/modules/access/__tests__/access-control.atref-batch.test.ts +98 -0
- package/src/modules/access/__tests__/access-control.read-batch.test.ts +132 -0
- package/src/modules/access/__tests__/access-control.service.test.ts +1011 -0
- package/src/modules/access/__tests__/access-mutation.service.test.ts +439 -0
- package/src/modules/access/__tests__/access-splice.test.ts +247 -0
- package/src/modules/access/__tests__/access.routes.revoke.test.ts +407 -0
- package/src/modules/access/__tests__/creator-access.test.ts +217 -0
- package/src/modules/access/__tests__/grant-sources.test.ts +204 -0
- package/src/modules/access/__tests__/kb-read-filter.test.ts +70 -0
- package/src/modules/access/__tests__/roles-admin.service.test.ts +469 -0
- package/src/modules/access/__tests__/roles-edit.test.ts +138 -0
- package/src/modules/access/__tests__/roles-yaml-guard.test.ts +70 -0
- package/src/modules/access/__tests__/roles.routes.test.ts +234 -0
- package/src/modules/access/access-control.interface.ts +383 -0
- package/src/modules/access/access-control.service.ts +1794 -0
- package/src/modules/access/access-errors.ts +60 -0
- package/src/modules/access/access-mutation.service.ts +369 -0
- package/src/modules/access/access-splice.ts +413 -0
- package/src/modules/access/access.routes.ts +894 -0
- package/src/modules/access/creator-access.ts +270 -0
- package/src/modules/access/kb-read-filter.ts +76 -0
- package/src/modules/access/roles-admin.service.ts +741 -0
- package/src/modules/access/roles-edit.ts +248 -0
- package/src/modules/access/roles-yaml-guard.ts +89 -0
- package/src/modules/admin/admin-access.routes.ts +29 -0
- package/src/modules/admin/admin-access.service.ts +38 -0
- package/src/modules/admin/admin.interface.ts +10 -0
- package/src/modules/auth/account-erasure.service.ts +183 -0
- package/src/modules/auth/auth.middleware.ts +78 -0
- package/src/modules/auth/auth.routes.ts +97 -0
- package/src/modules/auth/auth.service.ts +199 -0
- package/src/modules/code-mode/code-mode-names.ts +38 -0
- package/src/modules/code-mode/code-mode.tool.ts +117 -0
- package/src/modules/code-mode/index.ts +6 -0
- package/src/modules/database/connection.ts +15 -0
- package/src/modules/database/core-schema.ts +431 -0
- package/src/modules/database/migrate.ts +43 -0
- package/src/modules/database/schema.ts +11 -0
- package/src/modules/diff/__tests__/diff.routes.read-gate.test.ts +87 -0
- package/src/modules/diff/__tests__/diff.routes.rejectPathsLocked.test.ts +150 -0
- package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +184 -0
- package/src/modules/diff/__tests__/diff.service.test.ts +202 -0
- package/src/modules/diff/diff-paths.ts +9 -0
- package/src/modules/diff/diff.config.ts +12 -0
- package/src/modules/diff/diff.interface.ts +78 -0
- package/src/modules/diff/diff.routes.ts +277 -0
- package/src/modules/diff/diff.service.ts +508 -0
- package/src/modules/diff/line-diff.ts +79 -0
- package/src/modules/mcp/__tests__/bevel-oauth-provider.test.ts +287 -0
- package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +249 -0
- package/src/modules/mcp/__tests__/mcp-proxy-helpers.test.ts +253 -0
- package/src/modules/mcp/__tests__/mcp-session-store.test.ts +151 -0
- package/src/modules/mcp/__tests__/mcp.e2e.test.ts +150 -0
- package/src/modules/mcp/__tests__/mcp.routes.delete.test.ts +92 -0
- package/src/modules/mcp/__tests__/mcp.service.test.ts +414 -0
- package/src/modules/mcp/mcp-auth.middleware.ts +126 -0
- package/src/modules/mcp/mcp-session-store.ts +162 -0
- package/src/modules/mcp/mcp.routes.ts +263 -0
- package/src/modules/mcp/mcp.service.ts +973 -0
- package/src/modules/mcp/oauth/bevel-oauth-provider.ts +401 -0
- package/src/modules/mcp/oauth/oauth-consent.routes.ts +60 -0
- package/src/modules/mcp/oauth/oauth-state.ts +61 -0
- package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +277 -0
- package/src/modules/secrets-vault/__tests__/db-secrets-vault.oauth.test.ts +206 -0
- package/src/modules/secrets-vault/__tests__/mcp-oauth-discovery.service.test.ts +178 -0
- package/src/modules/secrets-vault/__tests__/scopes-covered.test.ts +101 -0
- package/src/modules/secrets-vault/__tests__/secrets-variable-loader.test.ts +54 -0
- package/src/modules/secrets-vault/__tests__/tool-owner-gate.route.test.ts +143 -0
- package/src/modules/secrets-vault/db-secrets-vault.service.ts +792 -0
- package/src/modules/secrets-vault/index.ts +25 -0
- package/src/modules/secrets-vault/mcp-oauth-discovery.service.ts +289 -0
- package/src/modules/secrets-vault/secrets-variable-loader.ts +104 -0
- package/src/modules/secrets-vault/secrets-vault.contract.ts +270 -0
- package/src/modules/secrets-vault/secrets-vault.routes.ts +526 -0
- package/src/modules/skills/__tests__/skills.service.test.ts +176 -0
- package/src/modules/skills/index.ts +10 -0
- package/src/modules/skills/skills.contract.ts +54 -0
- package/src/modules/skills/skills.routes.ts +38 -0
- package/src/modules/skills/skills.service.ts +245 -0
- package/src/modules/skills/skills.tools.ts +121 -0
- package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +358 -0
- package/src/modules/tool-auth/__tests__/internal-token.service.test.ts +79 -0
- package/src/modules/tool-auth/__tests__/manual-auth.middleware.test.ts +88 -0
- package/src/modules/tool-auth/external-api-key.errors.ts +25 -0
- package/src/modules/tool-auth/external-api-key.interface.ts +99 -0
- package/src/modules/tool-auth/external-api-key.service.ts +209 -0
- package/src/modules/tool-auth/internal-token.service.ts +124 -0
- package/src/modules/tool-auth/llm-usage-meter.ts +19 -0
- package/src/modules/tool-auth/tool-auth.middleware.ts +220 -0
- package/src/modules/tool-helpers/__tests__/phase0-loopback-spike.test.ts +129 -0
- package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +95 -0
- package/src/modules/tool-helpers/__tests__/tools-surface.test.ts +146 -0
- package/src/modules/tool-helpers/__tests__/validate-token.test.ts +75 -0
- package/src/modules/tool-helpers/index.ts +18 -0
- package/src/modules/tool-helpers/tool-context.ts +98 -0
- package/src/modules/tool-helpers/tool-def.ts +73 -0
- package/src/modules/tool-helpers/tool-handler.ts +91 -0
- package/src/modules/tool-helpers/tool.contract.ts +85 -0
- package/src/modules/tool-helpers/validate-token.ts +50 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +200 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +499 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +156 -0
- package/src/modules/tool-manuals/index.ts +12 -0
- package/src/modules/tool-manuals/tool-manuals.contract.ts +183 -0
- package/src/modules/tool-manuals/tool-manuals.routes.ts +110 -0
- package/src/modules/tool-manuals/tool-manuals.service.ts +781 -0
- package/src/modules/tool-manuals/tool-manuals.tools.ts +202 -0
- package/src/modules/tool-registry/__tests__/tool-registry.test.ts +64 -0
- package/src/modules/tool-registry/manual.routes.ts +87 -0
- package/src/modules/tool-registry/tool-registry.ts +55 -0
- package/src/modules/tool-registry/tool.contract.ts +52 -0
- package/src/modules/workflow/__tests__/event-bus.test.ts +322 -0
- package/src/modules/workflow/__tests__/file-change-notifier.test.ts +51 -0
- package/src/modules/workflow/__tests__/format-affected-owners.test.ts +67 -0
- package/src/modules/workflow/__tests__/locking-filesystem.test.ts +445 -0
- package/src/modules/workflow/__tests__/pending-commits.canonical.test.ts +36 -0
- package/src/modules/workflow/__tests__/pending-commits.worker.test.ts +243 -0
- package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +308 -0
- package/src/modules/workflow/__tests__/sanitize-error.test.ts +67 -0
- package/src/modules/workflow/__tests__/session-ontology.policy.test.ts +62 -0
- package/src/modules/workflow/__tests__/session-ontology.service.test.ts +200 -0
- package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +232 -0
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +380 -0
- package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +340 -0
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +192 -0
- package/src/modules/workflow/agent-tools/workflow.tools.ts +502 -0
- package/src/modules/workflow/event-bus.ts +262 -0
- package/src/modules/workflow/events.routes.ts +266 -0
- package/src/modules/workflow/file-change-notifier.ts +54 -0
- package/src/modules/workflow/file-lock.service.ts +269 -0
- package/src/modules/workflow/git/__tests__/branch-name.test.ts +86 -0
- package/src/modules/workflow/git/__tests__/branchAuthor.test.ts +80 -0
- package/src/modules/workflow/git/__tests__/clone-config.test.ts +15 -0
- package/src/modules/workflow/git/__tests__/git-test-helpers.ts +47 -0
- package/src/modules/workflow/git/__tests__/git-version.failure.test.ts +24 -0
- package/src/modules/workflow/git/__tests__/git-version.test.ts +49 -0
- package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +389 -0
- package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +124 -0
- package/src/modules/workflow/git/__tests__/git.service.commitChanges.test.ts +105 -0
- package/src/modules/workflow/git/__tests__/git.service.commitFile.test.ts +211 -0
- package/src/modules/workflow/git/__tests__/git.service.createBranch.test.ts +154 -0
- package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +320 -0
- package/src/modules/workflow/git/__tests__/git.service.diffFileAtCommit.test.ts +202 -0
- package/src/modules/workflow/git/__tests__/git.service.diffFileBetweenBranches.test.ts +453 -0
- package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +198 -0
- package/src/modules/workflow/git/__tests__/git.service.listTrackedFiles.test.ts +125 -0
- package/src/modules/workflow/git/__tests__/git.service.logForFile.test.ts +219 -0
- package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +145 -0
- package/src/modules/workflow/git/__tests__/git.service.pendingChanges.test.ts +240 -0
- package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +272 -0
- package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +232 -0
- package/src/modules/workflow/git/__tests__/git.service.readFileAtRef.test.ts +101 -0
- package/src/modules/workflow/git/__tests__/git.service.status.test.ts +127 -0
- package/src/modules/workflow/git/__tests__/mutex.test.ts +78 -0
- package/src/modules/workflow/git/__tests__/pull-request.service.test.ts +225 -0
- package/src/modules/workflow/git/__tests__/pull-request.service.viewer-can-cancel.test.ts +101 -0
- package/src/modules/workflow/git/branch-name.ts +70 -0
- package/src/modules/workflow/git/clone-config.ts +71 -0
- package/src/modules/workflow/git/git-version.ts +70 -0
- package/src/modules/workflow/git/git.service.ts +2248 -0
- package/src/modules/workflow/git/mutex.ts +22 -0
- package/src/modules/workflow/git/pull-request.service.ts +447 -0
- package/src/modules/workflow/locking-filesystem.ts +489 -0
- package/src/modules/workflow/pending-commits.service.ts +444 -0
- package/src/modules/workflow/pending-commits.worker.ts +361 -0
- package/src/modules/workflow/read-only-filesystem.ts +54 -0
- package/src/modules/workflow/recovery-bot.ts +73 -0
- package/src/modules/workflow/review-workflow/__tests__/approval-states.test.ts +560 -0
- package/src/modules/workflow/review-workflow/__tests__/cancel-pr.test.ts +176 -0
- package/src/modules/workflow/review-workflow/__tests__/merge-gate.test.ts +258 -0
- package/src/modules/workflow/review-workflow/review-workflow.interface.ts +199 -0
- package/src/modules/workflow/review-workflow/review-workflow.service.ts +806 -0
- package/src/modules/workflow/sanitize-error.ts +62 -0
- package/src/modules/workflow/session-ontology.policy.ts +70 -0
- package/src/modules/workflow/session-ontology.service.ts +178 -0
- package/src/modules/workflow/workflow-hooks.ts +101 -0
- package/src/modules/workflow/workflow.errors.ts +285 -0
- package/src/modules/workflow/workflow.routes.ts +858 -0
- package/src/modules/workflow/workflow.service.ts +1555 -0
- package/src/modules/workspace/__tests__/kb-seed.service.test.ts +213 -0
- package/src/modules/workspace/__tests__/routine-write-policy.test.ts +68 -0
- package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +237 -0
- package/src/modules/workspace/__tests__/spill-store.test.ts +43 -0
- package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +233 -0
- package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +176 -0
- package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +303 -0
- package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +276 -0
- package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +120 -0
- package/src/modules/workspace/__tests__/workspace.service.test.ts +565 -0
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +504 -0
- package/src/modules/workspace/bevel-ignore.ts +62 -0
- package/src/modules/workspace/kb-seed.interface.ts +36 -0
- package/src/modules/workspace/kb-seed.service.ts +361 -0
- package/src/modules/workspace/routine-write-policy.ts +79 -0
- package/src/modules/workspace/session-ontology.gate.ts +189 -0
- package/src/modules/workspace/session-sink.ts +25 -0
- package/src/modules/workspace/spill-store.ts +87 -0
- package/src/modules/workspace/workspace.routes.ts +1114 -0
- package/src/modules/workspace/workspace.service.ts +1343 -0
- package/src/modules/workspace/workspace.tools.ts +885 -0
- package/src/shared/__tests__/frontmatter-id.test.ts +88 -0
- package/src/shared/__tests__/fs-walk.test.ts +42 -0
- package/src/shared/__tests__/ssrf.test.ts +53 -0
- package/src/shared/__tests__/utcp-namespace.test.ts +19 -0
- package/src/shared/frontmatter-id.ts +72 -0
- package/src/shared/fs-walk.ts +30 -0
- package/src/shared/hash-email.ts +14 -0
- package/src/shared/kb-layout.test.ts +88 -0
- package/src/shared/kb-layout.ts +101 -0
- package/src/shared/ssrf.ts +78 -0
- package/src/shared/token-crypto.ts +54 -0
- package/src/shared/ttl-cache.ts +27 -0
- package/src/shared/utcp-namespace.ts +88 -0
- package/src/version.ts +19 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-(workspace, branch, path) edit lock store. The spec calls for
|
|
3
|
+
* file-scoped locks acquired on first edit and released either explicitly
|
|
4
|
+
* (with an autosave commit) or implicitly by TTL expiry — preventing a
|
|
5
|
+
* disconnected client from holding a file hostage.
|
|
6
|
+
*
|
|
7
|
+
* Lock state lives in Postgres because workspaces share state across
|
|
8
|
+
* backend instances eventually. The hot read path (does someone hold this
|
|
9
|
+
* lock?) is one indexed lookup; the hot write path (heartbeat) is a single
|
|
10
|
+
* row update. We don't bother caching in process memory — the lock table
|
|
11
|
+
* is the source of truth and any cache would lose its purpose the moment
|
|
12
|
+
* a different replica takes over.
|
|
13
|
+
*
|
|
14
|
+
* Stale-lock semantics: `get`, `acquire`, and `heartbeat` all treat a row
|
|
15
|
+
* with `expires_at <= now()` as if the lock didn't exist. We purge it
|
|
16
|
+
* lazily on next access rather than running a sweeper — the row count is
|
|
17
|
+
* bounded by concurrent editors, not history, so lazy GC is fine.
|
|
18
|
+
*/
|
|
19
|
+
import type { Database } from '../database/connection.js';
|
|
20
|
+
import type { AcquireLockResult, AuthUser, FileLock } from '@bevel-software/platform-shared';
|
|
21
|
+
export declare class FileLockService {
|
|
22
|
+
private readonly db;
|
|
23
|
+
constructor(db: Database);
|
|
24
|
+
/**
|
|
25
|
+
* Acquire a lock for `(workspaceId, branch, path)` on behalf of `user`.
|
|
26
|
+
*
|
|
27
|
+
* Three outcomes folded into the same return shape:
|
|
28
|
+
* - No existing row: insert + return `{ acquired: true, lock }`.
|
|
29
|
+
* - Existing row, expired: take it over (update) + `{ acquired: true }`.
|
|
30
|
+
* - Existing row, live, different user: return `{ acquired: false }`
|
|
31
|
+
* with the current holder's lock state so the UI can render
|
|
32
|
+
* "Locked by X" without a follow-up call.
|
|
33
|
+
* - Existing row, live, same user: refresh TTL + `{ acquired: true }`
|
|
34
|
+
* so re-acquiring your own lock is idempotent.
|
|
35
|
+
*/
|
|
36
|
+
acquire(workspaceId: string, branch: string, targetPath: string, user: AuthUser): Promise<AcquireLockResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Extend the lock's TTL. Refuses if the lock is held by someone else or
|
|
39
|
+
* doesn't exist — the client is then expected to re-call `acquire`,
|
|
40
|
+
* which will either succeed (taking over a stale lock) or surface the
|
|
41
|
+
* current holder.
|
|
42
|
+
*/
|
|
43
|
+
heartbeat(workspaceId: string, branch: string, targetPath: string, user: AuthUser): Promise<FileLock>;
|
|
44
|
+
/**
|
|
45
|
+
* Idempotent release. Deletes the lock row when the caller holds it;
|
|
46
|
+
* silently no-ops otherwise (the lock may have expired and been taken
|
|
47
|
+
* over by someone else — that's not an error from the caller's POV).
|
|
48
|
+
*/
|
|
49
|
+
release(workspaceId: string, branch: string, targetPath: string, user: AuthUser): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Read the current lock for `(workspace, branch, path)`. Returns null when
|
|
52
|
+
* no one holds it, OR when the existing row is expired — expired locks
|
|
53
|
+
* are purged here lazily.
|
|
54
|
+
*/
|
|
55
|
+
get(workspaceId: string, branch: string, targetPath: string): Promise<FileLock | null>;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=file-lock.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-lock.service.d.ts","sourceRoot":"","sources":["../../../src/modules/workflow/file-lock.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAwB7F,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ;IAEzC;;;;;;;;;;;OAWG;IACG,OAAO,CACX,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,iBAAiB,CAAC;IAuF7B;;;;;OAKG;IACG,SAAS,CACb,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,QAAQ,CAAC;IAoCpB;;;;OAIG;IACG,OAAO,CACX,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,IAAI,CAAC;IAahB;;;;OAIG;IACG,GAAG,CACP,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;CAoC5B"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-(workspace, branch, path) edit lock store. The spec calls for
|
|
3
|
+
* file-scoped locks acquired on first edit and released either explicitly
|
|
4
|
+
* (with an autosave commit) or implicitly by TTL expiry — preventing a
|
|
5
|
+
* disconnected client from holding a file hostage.
|
|
6
|
+
*
|
|
7
|
+
* Lock state lives in Postgres because workspaces share state across
|
|
8
|
+
* backend instances eventually. The hot read path (does someone hold this
|
|
9
|
+
* lock?) is one indexed lookup; the hot write path (heartbeat) is a single
|
|
10
|
+
* row update. We don't bother caching in process memory — the lock table
|
|
11
|
+
* is the source of truth and any cache would lose its purpose the moment
|
|
12
|
+
* a different replica takes over.
|
|
13
|
+
*
|
|
14
|
+
* Stale-lock semantics: `get`, `acquire`, and `heartbeat` all treat a row
|
|
15
|
+
* with `expires_at <= now()` as if the lock didn't exist. We purge it
|
|
16
|
+
* lazily on next access rather than running a sweeper — the row count is
|
|
17
|
+
* bounded by concurrent editors, not history, so lazy GC is fine.
|
|
18
|
+
*/
|
|
19
|
+
import { and, eq, gt, lte } from 'drizzle-orm';
|
|
20
|
+
import { fileLocks } from '../database/schema.js';
|
|
21
|
+
import { WorkflowValidationError } from './workflow.errors.js';
|
|
22
|
+
/**
|
|
23
|
+
* Lock lifetime without a heartbeat. The client is expected to heartbeat
|
|
24
|
+
* every ~half this interval so a single missed ping doesn't release the
|
|
25
|
+
* lock out from under them. Bumping the TTL trades off "how long does a
|
|
26
|
+
* crashed client hold a file" against "how forgiving are we of network
|
|
27
|
+
* blips" — 60s is a balance.
|
|
28
|
+
*/
|
|
29
|
+
const LOCK_TTL_MS = 60_000;
|
|
30
|
+
function rowToFileLock(row) {
|
|
31
|
+
return {
|
|
32
|
+
branch: row.branch,
|
|
33
|
+
path: row.path,
|
|
34
|
+
holderUserId: row.holderUserId,
|
|
35
|
+
holderName: row.holderName,
|
|
36
|
+
acquiredAt: row.acquiredAt.toISOString(),
|
|
37
|
+
lastHeartbeatAt: row.lastHeartbeatAt.toISOString(),
|
|
38
|
+
expiresAt: row.expiresAt.toISOString(),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export class FileLockService {
|
|
42
|
+
db;
|
|
43
|
+
constructor(db) {
|
|
44
|
+
this.db = db;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Acquire a lock for `(workspaceId, branch, path)` on behalf of `user`.
|
|
48
|
+
*
|
|
49
|
+
* Three outcomes folded into the same return shape:
|
|
50
|
+
* - No existing row: insert + return `{ acquired: true, lock }`.
|
|
51
|
+
* - Existing row, expired: take it over (update) + `{ acquired: true }`.
|
|
52
|
+
* - Existing row, live, different user: return `{ acquired: false }`
|
|
53
|
+
* with the current holder's lock state so the UI can render
|
|
54
|
+
* "Locked by X" without a follow-up call.
|
|
55
|
+
* - Existing row, live, same user: refresh TTL + `{ acquired: true }`
|
|
56
|
+
* so re-acquiring your own lock is idempotent.
|
|
57
|
+
*/
|
|
58
|
+
async acquire(workspaceId, branch, targetPath, user) {
|
|
59
|
+
const now = new Date();
|
|
60
|
+
const expiresAt = new Date(now.getTime() + LOCK_TTL_MS);
|
|
61
|
+
// Atomic acquire-or-takeover, in a single statement. Two callers
|
|
62
|
+
// racing on the same `(workspace, branch, path)` would otherwise
|
|
63
|
+
// both SELECT no row → both INSERT (one PK-fails) or both SELECT a
|
|
64
|
+
// stale row → both UPDATE (one silently overwrites the other's
|
|
65
|
+
// takeover). PostgreSQL's INSERT ... ON CONFLICT DO UPDATE WHERE
|
|
66
|
+
// collapses both paths into one atomic statement:
|
|
67
|
+
//
|
|
68
|
+
// - No existing row → INSERT succeeds, RETURNING our new row.
|
|
69
|
+
// - Existing row, WHERE matches (stale OR same user) → UPDATE
|
|
70
|
+
// fires, RETURNING the updated row.
|
|
71
|
+
// - Existing row, WHERE doesn't match (live + different user) →
|
|
72
|
+
// the conflict is silently absorbed (PG's documented behavior),
|
|
73
|
+
// RETURNING is empty. We then read the live holder for the
|
|
74
|
+
// "Locked by X" payload.
|
|
75
|
+
//
|
|
76
|
+
// **Only expired rows can be taken over.** The same-user clause used
|
|
77
|
+
// to be here as an "idempotent refresh" shortcut, but it had a nasty
|
|
78
|
+
// side effect: the AGENT and the HUMAN EDITOR share the same `user.id`
|
|
79
|
+
// (agent edits attribute to the human), so the agent's
|
|
80
|
+
// `LockingFilesystem.withLock` would silently steal a lock the human
|
|
81
|
+
// had taken via the Edit button — overwriting their in-flight edits
|
|
82
|
+
// and dropping their lock on agent-release. Removing same-user from
|
|
83
|
+
// setWhere makes acquire strict: a non-expired lock is contended even
|
|
84
|
+
// by yourself, so the agent's retry/skip path kicks in and the human
|
|
85
|
+
// keeps editing. Real refresh-while-holding goes through
|
|
86
|
+
// `heartbeat()` (which has its own same-user UPDATE), and the
|
|
87
|
+
// editor's save flow detects "I already hold it" via `getLock` in
|
|
88
|
+
// `workspace.routes.withLock` rather than re-acquiring.
|
|
89
|
+
const upsertResult = await this.db
|
|
90
|
+
.insert(fileLocks)
|
|
91
|
+
.values({
|
|
92
|
+
workspaceId,
|
|
93
|
+
branch,
|
|
94
|
+
path: targetPath,
|
|
95
|
+
holderUserId: user.id,
|
|
96
|
+
holderName: user.name,
|
|
97
|
+
acquiredAt: now,
|
|
98
|
+
lastHeartbeatAt: now,
|
|
99
|
+
expiresAt,
|
|
100
|
+
})
|
|
101
|
+
.onConflictDoUpdate({
|
|
102
|
+
target: [fileLocks.workspaceId, fileLocks.branch, fileLocks.path],
|
|
103
|
+
set: {
|
|
104
|
+
holderUserId: user.id,
|
|
105
|
+
holderName: user.name,
|
|
106
|
+
acquiredAt: now,
|
|
107
|
+
lastHeartbeatAt: now,
|
|
108
|
+
expiresAt,
|
|
109
|
+
},
|
|
110
|
+
setWhere: lte(fileLocks.expiresAt, now),
|
|
111
|
+
})
|
|
112
|
+
.returning();
|
|
113
|
+
if (upsertResult.length > 0) {
|
|
114
|
+
return { acquired: true, lock: rowToFileLock(upsertResult[0]) };
|
|
115
|
+
}
|
|
116
|
+
// Live lock held by another user. Fetch it for the "Locked by X" UI
|
|
117
|
+
// payload. We don't filter on `expiresAt > now` here because the
|
|
118
|
+
// upsert above already proved an unreclaimable row exists; the only
|
|
119
|
+
// way this read returns null is a tight race where the holder
|
|
120
|
+
// released between the upsert and this select — rare enough to
|
|
121
|
+
// surface as a retryable error rather than complicate the happy path.
|
|
122
|
+
const [holder] = await this.db
|
|
123
|
+
.select()
|
|
124
|
+
.from(fileLocks)
|
|
125
|
+
.where(and(eq(fileLocks.workspaceId, workspaceId), eq(fileLocks.branch, branch), eq(fileLocks.path, targetPath)))
|
|
126
|
+
.limit(1);
|
|
127
|
+
if (!holder) {
|
|
128
|
+
throw new WorkflowValidationError(`Lock contention race on "${targetPath}" — please retry.`, { kind: 'lock-contention-race', branch, path: targetPath });
|
|
129
|
+
}
|
|
130
|
+
return { acquired: false, lock: rowToFileLock(holder) };
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Extend the lock's TTL. Refuses if the lock is held by someone else or
|
|
134
|
+
* doesn't exist — the client is then expected to re-call `acquire`,
|
|
135
|
+
* which will either succeed (taking over a stale lock) or surface the
|
|
136
|
+
* current holder.
|
|
137
|
+
*/
|
|
138
|
+
async heartbeat(workspaceId, branch, targetPath, user) {
|
|
139
|
+
const now = new Date();
|
|
140
|
+
const expiresAt = new Date(now.getTime() + LOCK_TTL_MS);
|
|
141
|
+
// The expiry guard (`expiresAt > now`) matters because an expired
|
|
142
|
+
// lock is conceptually released, even if its row hasn't been swept
|
|
143
|
+
// and no other user has taken it yet. Without it, a client whose
|
|
144
|
+
// tab was suspended past the TTL would silently extend a lock that
|
|
145
|
+
// the rest of the system considers "free for the next acquire" —
|
|
146
|
+
// any subsequent `acquire()` by another user could already have
|
|
147
|
+
// taken it (the upsert's `lte(expiresAt, now)` predicate matches),
|
|
148
|
+
// and the heartbeat would race with that takeover. Failing here
|
|
149
|
+
// forces the client to re-acquire (which goes through the proper
|
|
150
|
+
// takeover path) and surfaces the "your session went stale" state
|
|
151
|
+
// honestly.
|
|
152
|
+
const [updated] = await this.db
|
|
153
|
+
.update(fileLocks)
|
|
154
|
+
.set({ lastHeartbeatAt: now, expiresAt })
|
|
155
|
+
.where(and(eq(fileLocks.workspaceId, workspaceId), eq(fileLocks.branch, branch), eq(fileLocks.path, targetPath), eq(fileLocks.holderUserId, user.id), gt(fileLocks.expiresAt, now)))
|
|
156
|
+
.returning();
|
|
157
|
+
if (!updated) {
|
|
158
|
+
throw new WorkflowValidationError(`Cannot heartbeat lock on "${targetPath}": not held by you (or no longer exists).`, { kind: 'lock-not-held', branch, path: targetPath });
|
|
159
|
+
}
|
|
160
|
+
return rowToFileLock(updated);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Idempotent release. Deletes the lock row when the caller holds it;
|
|
164
|
+
* silently no-ops otherwise (the lock may have expired and been taken
|
|
165
|
+
* over by someone else — that's not an error from the caller's POV).
|
|
166
|
+
*/
|
|
167
|
+
async release(workspaceId, branch, targetPath, user) {
|
|
168
|
+
await this.db
|
|
169
|
+
.delete(fileLocks)
|
|
170
|
+
.where(and(eq(fileLocks.workspaceId, workspaceId), eq(fileLocks.branch, branch), eq(fileLocks.path, targetPath), eq(fileLocks.holderUserId, user.id)));
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Read the current lock for `(workspace, branch, path)`. Returns null when
|
|
174
|
+
* no one holds it, OR when the existing row is expired — expired locks
|
|
175
|
+
* are purged here lazily.
|
|
176
|
+
*/
|
|
177
|
+
async get(workspaceId, branch, targetPath) {
|
|
178
|
+
const rows = await this.db
|
|
179
|
+
.select()
|
|
180
|
+
.from(fileLocks)
|
|
181
|
+
.where(and(eq(fileLocks.workspaceId, workspaceId), eq(fileLocks.branch, branch), eq(fileLocks.path, targetPath)))
|
|
182
|
+
.limit(1);
|
|
183
|
+
if (rows.length === 0)
|
|
184
|
+
return null;
|
|
185
|
+
const row = rows[0];
|
|
186
|
+
if (row.expiresAt.getTime() <= Date.now()) {
|
|
187
|
+
// Lazy GC — drop the stale row so the next `acquire` doesn't have
|
|
188
|
+
// to bypass it. Bind the delete to this exact row's `expiresAt` so
|
|
189
|
+
// a concurrent acquire that wrote a fresh row in the gap between
|
|
190
|
+
// our SELECT and DELETE doesn't get clobbered. Primary key
|
|
191
|
+
// `(workspaceId, branch, path)` alone isn't enough — a new acquire
|
|
192
|
+
// for the same triple updates that row in place with a future
|
|
193
|
+
// expiry, and a path-only delete here would silently nuke it.
|
|
194
|
+
await this.db
|
|
195
|
+
.delete(fileLocks)
|
|
196
|
+
.where(and(eq(fileLocks.workspaceId, workspaceId), eq(fileLocks.branch, branch), eq(fileLocks.path, targetPath), eq(fileLocks.expiresAt, row.expiresAt)));
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
return rowToFileLock(row);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=file-lock.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-lock.service.js","sourceRoot":"","sources":["../../../src/modules/workflow/file-lock.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { PROTECTED_BRANCHES, isProtectedBranch } from '@bevel-software/platform-shared';
|
|
2
|
+
export { branchAuthorLocalpart, isBranchAuthoredBy } from '@bevel-software/platform-shared';
|
|
3
|
+
/** Throw if `name` cannot safely be passed to `git` as a branch name. */
|
|
4
|
+
export declare function assertValidBranchName(name: string): void;
|
|
5
|
+
/**
|
|
6
|
+
* Guard against path traversal and shell-unsafe characters on any workspace-relative
|
|
7
|
+
* path we pass to `git` as a pathspec. Must stay within the repo; forward slashes only.
|
|
8
|
+
*/
|
|
9
|
+
export declare function assertValidRelativePath(relativePath: string): void;
|
|
10
|
+
//# sourceMappingURL=branch-name.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-name.d.ts","sourceRoot":"","sources":["../../../../src/modules/workflow/git/branch-name.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAKxF,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAI5F,yEAAyE;AACzE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAwBxD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAyBlE"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { BranchNameError, WorkflowValidationError } from '../workflow.errors.js';
|
|
2
|
+
// Single source of truth for the protected-branch list lives in `@bevel-software/platform-shared` so
|
|
3
|
+
// the backend guard and the frontend banner/disabling logic can't drift apart.
|
|
4
|
+
export { PROTECTED_BRANCHES, isProtectedBranch } from '@bevel-software/platform-shared';
|
|
5
|
+
// Authorship inference lives in `@bevel-software/platform-shared` for the same reason — the
|
|
6
|
+
// picker's `canDelete` rule and the backend authorisation check on
|
|
7
|
+
// `deleteBranch` must agree on every edge case (uppercase email, dotted
|
|
8
|
+
// localpart, etc.).
|
|
9
|
+
export { branchAuthorLocalpart, isBranchAuthoredBy } from '@bevel-software/platform-shared';
|
|
10
|
+
const VALID_BRANCH_REGEX = /^[A-Za-z0-9][A-Za-z0-9/_\-.]*$/;
|
|
11
|
+
/** Throw if `name` cannot safely be passed to `git` as a branch name. */
|
|
12
|
+
export function assertValidBranchName(name) {
|
|
13
|
+
if (!name)
|
|
14
|
+
throw new BranchNameError('empty name', name);
|
|
15
|
+
if (name.length > 255)
|
|
16
|
+
throw new BranchNameError('too long', name);
|
|
17
|
+
if (!VALID_BRANCH_REGEX.test(name)) {
|
|
18
|
+
throw new BranchNameError('contains invalid characters', name);
|
|
19
|
+
}
|
|
20
|
+
if (name.includes('..'))
|
|
21
|
+
throw new BranchNameError('contains ".."', name);
|
|
22
|
+
if (name.includes('//'))
|
|
23
|
+
throw new BranchNameError('contains "//"', name);
|
|
24
|
+
if (name.endsWith('/') || name.endsWith('.')) {
|
|
25
|
+
throw new BranchNameError('ends with "/" or "."', name);
|
|
26
|
+
}
|
|
27
|
+
if (name.startsWith('-'))
|
|
28
|
+
throw new BranchNameError('starts with "-"', name);
|
|
29
|
+
if (name.includes('@{'))
|
|
30
|
+
throw new BranchNameError('contains "@{"', name);
|
|
31
|
+
// Per-segment rules: git forbids any `/`-separated segment from beginning
|
|
32
|
+
// with "." or ending with ".lock" (e.g. `foo/.tmp`, `foo.lock/bar`).
|
|
33
|
+
// The whole-name checks above can't catch nested violations.
|
|
34
|
+
for (const segment of name.split('/')) {
|
|
35
|
+
if (segment.startsWith('.')) {
|
|
36
|
+
throw new BranchNameError('segment starts with "."', name);
|
|
37
|
+
}
|
|
38
|
+
if (segment.endsWith('.lock')) {
|
|
39
|
+
throw new BranchNameError('segment ends with ".lock"', name);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Guard against path traversal and shell-unsafe characters on any workspace-relative
|
|
45
|
+
* path we pass to `git` as a pathspec. Must stay within the repo; forward slashes only.
|
|
46
|
+
*/
|
|
47
|
+
export function assertValidRelativePath(relativePath) {
|
|
48
|
+
if (!relativePath)
|
|
49
|
+
throw new WorkflowValidationError('path is required');
|
|
50
|
+
if (relativePath.length > 1024)
|
|
51
|
+
throw new WorkflowValidationError('path too long');
|
|
52
|
+
if (relativePath.includes('\0'))
|
|
53
|
+
throw new WorkflowValidationError('path contains NUL');
|
|
54
|
+
if (relativePath.includes('\\')) {
|
|
55
|
+
throw new WorkflowValidationError('path must use forward slashes only');
|
|
56
|
+
}
|
|
57
|
+
if (relativePath.startsWith('/') || /^[A-Za-z]:/.test(relativePath)) {
|
|
58
|
+
throw new WorkflowValidationError('path must be relative');
|
|
59
|
+
}
|
|
60
|
+
const parts = relativePath.split('/');
|
|
61
|
+
if (parts.some((p) => p === '..' || p === '.')) {
|
|
62
|
+
throw new WorkflowValidationError('path must not contain "." or ".."');
|
|
63
|
+
}
|
|
64
|
+
if (relativePath.startsWith('-')) {
|
|
65
|
+
throw new WorkflowValidationError('path must not start with "-"');
|
|
66
|
+
}
|
|
67
|
+
// Pathspec glob characters (`*`, `?`, `[`, `]`, `!`) and pathspec magic (`:(…)`)
|
|
68
|
+
// would otherwise be interpreted by `git add -- <path>` / `git log -- <path>`
|
|
69
|
+
// and match the wrong files. `GitService.git()` sets `GIT_LITERAL_PATHSPECS=1`
|
|
70
|
+
// on every git subprocess, which forces literal interpretation across the
|
|
71
|
+
// board — so KB filenames containing `[Approved]`, `[New]`, etc. round-trip
|
|
72
|
+
// through commit cleanly. The shared `validateFilename` already rejects `:`
|
|
73
|
+
// along with the rest of Windows-forbidden characters before paths reach this
|
|
74
|
+
// layer, so a redundant check here would only confuse the error message.
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=branch-name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-name.js","sourceRoot":"","sources":["../../../../src/modules/workflow/git/branch-name.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The git configuration a per-branch workspace clone must have for its branch
|
|
3
|
+
* to track exactly ONE upstream ref.
|
|
4
|
+
*
|
|
5
|
+
* Why this exists: a clone's config is append-only from git's point of view,
|
|
6
|
+
* and several things write to it:
|
|
7
|
+
*
|
|
8
|
+
* - `git config --add branch.<name>.merge …` / `git branch --set-upstream-to`
|
|
9
|
+
* run out of band (an agent shell session in the workspace, a manual fix)
|
|
10
|
+
* leaves a SECOND `branch.<name>.merge` value;
|
|
11
|
+
* - `git remote set-branches --add origin …`, a re-run `git remote add`, or a
|
|
12
|
+
* hand-edited `.git/config` leaves a SECOND `remote.origin.fetch` refspec,
|
|
13
|
+
* so one fetch maps the same remote branch in twice.
|
|
14
|
+
*
|
|
15
|
+
* A multi-valued `branch.<name>.merge` is what makes a BARE `git fetch origin`
|
|
16
|
+
* write more than one *for-merge* entry into the clone's shared
|
|
17
|
+
* `.git/FETCH_HEAD` — git adds one per configured merge ref. That is the
|
|
18
|
+
* ammunition behind the reported failure: `git pull` reads its rebase target
|
|
19
|
+
* out of that same shared file, so when one of the app's unmutexed bare
|
|
20
|
+
* fetches lands inside the pull's fetch→read window, the pull sees two merge
|
|
21
|
+
* heads and dies with `fatal: Cannot rebase onto multiple branches.`
|
|
22
|
+
*
|
|
23
|
+
* The drift alone is NOT sufficient — an explicit `git pull --rebase origin
|
|
24
|
+
* <branch>` survives every drift shape on its own (verified across the shapes
|
|
25
|
+
* above on git 2.39.5); it takes the concurrent fetch too. `GitService.pull`
|
|
26
|
+
* closes the other half by never reading or writing FETCH_HEAD; normalising
|
|
27
|
+
* the config here removes the ammunition.
|
|
28
|
+
*
|
|
29
|
+
* These are the three keys that pin the clone back to "this branch tracks
|
|
30
|
+
* `origin/<branch>`, nothing else"; applied with `--replace-all` they collapse
|
|
31
|
+
* any accumulated duplicates into one value.
|
|
32
|
+
*
|
|
33
|
+
* Lives here — next to `assertValidBranchName` — as a leaf-level primitive
|
|
34
|
+
* shared by the git layer (self-heal before every pull) and `WorkspaceService`
|
|
35
|
+
* (stamped on new clones, and re-stamped on existing ones the first time this
|
|
36
|
+
* process opens them, which is the migration for clones already on disk).
|
|
37
|
+
*/
|
|
38
|
+
/** The single fetch refspec a workspace clone of the KB is created with. */
|
|
39
|
+
export declare const ORIGIN_FETCH_REFSPEC = "+refs/heads/*:refs/remotes/origin/*";
|
|
40
|
+
/**
|
|
41
|
+
* The one safe shape for an implicit background fetch of a workspace clone —
|
|
42
|
+
* shared by `GitService.fetchOriginIfStale` and
|
|
43
|
+
* `WorkspaceService.ensureRemotesFetched`, both of which run OUTSIDE the
|
|
44
|
+
* workspace mutex. `--no-write-fetch-head` is what makes that safe: without it
|
|
45
|
+
* a bare fetch rewrites the clone's shared `.git/FETCH_HEAD` underneath
|
|
46
|
+
* whatever else is running in it, which is how the post-merge `git pull` read
|
|
47
|
+
* two merge heads and died with "Cannot rebase onto multiple branches" (see
|
|
48
|
+
* the header comment above and `GitService.pull`). These paths only want the
|
|
49
|
+
* remote-tracking refs refreshed; `--prune` keeps deleted remote branches from
|
|
50
|
+
* lingering. Callers prepend their own runner context (`-C <dir>` /
|
|
51
|
+
* `-c http.*` options) but must not vary these arguments.
|
|
52
|
+
*/
|
|
53
|
+
export declare const SAFE_IMPLICIT_FETCH_ARGS: readonly string[];
|
|
54
|
+
/**
|
|
55
|
+
* `git` argument lists that normalise a clone's tracking config for `branch`.
|
|
56
|
+
* Returns the arguments rather than running them so each caller can use its own
|
|
57
|
+
* git runner (the git service's mutex-aware wrapper, `git -C` from the
|
|
58
|
+
* workspace service) — no process is spawned here.
|
|
59
|
+
*/
|
|
60
|
+
export declare function cloneTrackingConfigArgs(branch: string): string[][];
|
|
61
|
+
//# sourceMappingURL=clone-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone-config.d.ts","sourceRoot":"","sources":["../../../../src/modules/workflow/git/clone-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,wCAAwC,CAAC;AAE1E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,EAAE,SAAS,MAAM,EAErD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAMlE"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The git configuration a per-branch workspace clone must have for its branch
|
|
3
|
+
* to track exactly ONE upstream ref.
|
|
4
|
+
*
|
|
5
|
+
* Why this exists: a clone's config is append-only from git's point of view,
|
|
6
|
+
* and several things write to it:
|
|
7
|
+
*
|
|
8
|
+
* - `git config --add branch.<name>.merge …` / `git branch --set-upstream-to`
|
|
9
|
+
* run out of band (an agent shell session in the workspace, a manual fix)
|
|
10
|
+
* leaves a SECOND `branch.<name>.merge` value;
|
|
11
|
+
* - `git remote set-branches --add origin …`, a re-run `git remote add`, or a
|
|
12
|
+
* hand-edited `.git/config` leaves a SECOND `remote.origin.fetch` refspec,
|
|
13
|
+
* so one fetch maps the same remote branch in twice.
|
|
14
|
+
*
|
|
15
|
+
* A multi-valued `branch.<name>.merge` is what makes a BARE `git fetch origin`
|
|
16
|
+
* write more than one *for-merge* entry into the clone's shared
|
|
17
|
+
* `.git/FETCH_HEAD` — git adds one per configured merge ref. That is the
|
|
18
|
+
* ammunition behind the reported failure: `git pull` reads its rebase target
|
|
19
|
+
* out of that same shared file, so when one of the app's unmutexed bare
|
|
20
|
+
* fetches lands inside the pull's fetch→read window, the pull sees two merge
|
|
21
|
+
* heads and dies with `fatal: Cannot rebase onto multiple branches.`
|
|
22
|
+
*
|
|
23
|
+
* The drift alone is NOT sufficient — an explicit `git pull --rebase origin
|
|
24
|
+
* <branch>` survives every drift shape on its own (verified across the shapes
|
|
25
|
+
* above on git 2.39.5); it takes the concurrent fetch too. `GitService.pull`
|
|
26
|
+
* closes the other half by never reading or writing FETCH_HEAD; normalising
|
|
27
|
+
* the config here removes the ammunition.
|
|
28
|
+
*
|
|
29
|
+
* These are the three keys that pin the clone back to "this branch tracks
|
|
30
|
+
* `origin/<branch>`, nothing else"; applied with `--replace-all` they collapse
|
|
31
|
+
* any accumulated duplicates into one value.
|
|
32
|
+
*
|
|
33
|
+
* Lives here — next to `assertValidBranchName` — as a leaf-level primitive
|
|
34
|
+
* shared by the git layer (self-heal before every pull) and `WorkspaceService`
|
|
35
|
+
* (stamped on new clones, and re-stamped on existing ones the first time this
|
|
36
|
+
* process opens them, which is the migration for clones already on disk).
|
|
37
|
+
*/
|
|
38
|
+
/** The single fetch refspec a workspace clone of the KB is created with. */
|
|
39
|
+
export const ORIGIN_FETCH_REFSPEC = '+refs/heads/*:refs/remotes/origin/*';
|
|
40
|
+
/**
|
|
41
|
+
* The one safe shape for an implicit background fetch of a workspace clone —
|
|
42
|
+
* shared by `GitService.fetchOriginIfStale` and
|
|
43
|
+
* `WorkspaceService.ensureRemotesFetched`, both of which run OUTSIDE the
|
|
44
|
+
* workspace mutex. `--no-write-fetch-head` is what makes that safe: without it
|
|
45
|
+
* a bare fetch rewrites the clone's shared `.git/FETCH_HEAD` underneath
|
|
46
|
+
* whatever else is running in it, which is how the post-merge `git pull` read
|
|
47
|
+
* two merge heads and died with "Cannot rebase onto multiple branches" (see
|
|
48
|
+
* the header comment above and `GitService.pull`). These paths only want the
|
|
49
|
+
* remote-tracking refs refreshed; `--prune` keeps deleted remote branches from
|
|
50
|
+
* lingering. Callers prepend their own runner context (`-C <dir>` /
|
|
51
|
+
* `-c http.*` options) but must not vary these arguments.
|
|
52
|
+
*/
|
|
53
|
+
export const SAFE_IMPLICIT_FETCH_ARGS = [
|
|
54
|
+
'fetch', '--prune', '--no-write-fetch-head', 'origin',
|
|
55
|
+
];
|
|
56
|
+
/**
|
|
57
|
+
* `git` argument lists that normalise a clone's tracking config for `branch`.
|
|
58
|
+
* Returns the arguments rather than running them so each caller can use its own
|
|
59
|
+
* git runner (the git service's mutex-aware wrapper, `git -C` from the
|
|
60
|
+
* workspace service) — no process is spawned here.
|
|
61
|
+
*/
|
|
62
|
+
export function cloneTrackingConfigArgs(branch) {
|
|
63
|
+
return [
|
|
64
|
+
['config', '--replace-all', 'remote.origin.fetch', ORIGIN_FETCH_REFSPEC],
|
|
65
|
+
['config', '--replace-all', `branch.${branch}.remote`, 'origin'],
|
|
66
|
+
['config', '--replace-all', `branch.${branch}.merge`, `refs/heads/${branch}`],
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=clone-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone-config.js","sourceRoot":"","sources":["../../../../src/modules/workflow/git/clone-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,4EAA4E;AAC5E,MAAM,CAAC,MAAM,oBAAoB,GAAG,qCAAqC,CAAC;AAE1E;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAsB;IACzD,OAAO,EAAE,SAAS,EAAE,uBAAuB,EAAE,QAAQ;CACtD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,OAAO;QACL,CAAC,QAAQ,EAAE,eAAe,EAAE,qBAAqB,EAAE,oBAAoB,CAAC;QACxE,CAAC,QAAQ,EAAE,eAAe,EAAE,UAAU,MAAM,SAAS,EAAE,QAAQ,CAAC;QAChE,CAAC,QAAQ,EAAE,eAAe,EAAE,UAAU,MAAM,QAAQ,EAAE,cAAc,MAAM,EAAE,CAAC;KAC9E,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `git` floor this app depends on.
|
|
3
|
+
*
|
|
4
|
+
* Every fetch the workspace layer runs passes `--no-write-fetch-head` — the
|
|
5
|
+
* option that keeps one clone's fetches from steering a concurrent refresh
|
|
6
|
+
* through the shared `.git/FETCH_HEAD` (see `GitService.pull`) — and git only
|
|
7
|
+
* learned it in 2.29. On an older binary every one of those fetches dies with
|
|
8
|
+
* `unknown option`, which takes out `pull`, `resetToRemote` and
|
|
9
|
+
* `mergeChangeRequest` at once.
|
|
10
|
+
*
|
|
11
|
+
* The production image installs git from Debian via `node:22-slim`, which is
|
|
12
|
+
* well past the floor, so this guard is about a re-based or swapped runtime
|
|
13
|
+
* image rather than a live problem. Its value is *when* it fires: at boot,
|
|
14
|
+
* naming the installed version, instead of at the first change-request merge
|
|
15
|
+
* with an opaque git error.
|
|
16
|
+
*/
|
|
17
|
+
/** Oldest git that understands `--no-write-fetch-head`. */
|
|
18
|
+
export declare const MIN_GIT_VERSION: readonly [number, number];
|
|
19
|
+
/** `git version 2.39.5 (Apple Git-154)` → `[2, 39]`; null if unrecognisable. */
|
|
20
|
+
export declare function parseGitVersion(stdout: string): [number, number] | null;
|
|
21
|
+
/**
|
|
22
|
+
* Throw when `git --version` output names a version below the floor.
|
|
23
|
+
*
|
|
24
|
+
* An output we can't parse is NOT fatal: a git build with an unusual version
|
|
25
|
+
* string is far more likely than one older than 2.29, and refusing to boot over
|
|
26
|
+
* an unrecognised string would be a worse failure than the one being guarded.
|
|
27
|
+
*/
|
|
28
|
+
export declare function assertSupportedGitVersion(stdout: string): void;
|
|
29
|
+
/**
|
|
30
|
+
* Run `git --version` and apply the floor. Call once during startup, before
|
|
31
|
+
* anything clones or fetches.
|
|
32
|
+
*/
|
|
33
|
+
export declare function assertGitVersion(): Promise<void>;
|
|
34
|
+
//# sourceMappingURL=git-version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-version.d.ts","sourceRoot":"","sources":["../../../../src/modules/workflow/git/git-version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,2DAA2D;AAC3D,eAAO,MAAM,eAAe,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAW,CAAC;AAElE,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAGvE;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAiB9D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQtD"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `git` floor this app depends on.
|
|
3
|
+
*
|
|
4
|
+
* Every fetch the workspace layer runs passes `--no-write-fetch-head` — the
|
|
5
|
+
* option that keeps one clone's fetches from steering a concurrent refresh
|
|
6
|
+
* through the shared `.git/FETCH_HEAD` (see `GitService.pull`) — and git only
|
|
7
|
+
* learned it in 2.29. On an older binary every one of those fetches dies with
|
|
8
|
+
* `unknown option`, which takes out `pull`, `resetToRemote` and
|
|
9
|
+
* `mergeChangeRequest` at once.
|
|
10
|
+
*
|
|
11
|
+
* The production image installs git from Debian via `node:22-slim`, which is
|
|
12
|
+
* well past the floor, so this guard is about a re-based or swapped runtime
|
|
13
|
+
* image rather than a live problem. Its value is *when* it fires: at boot,
|
|
14
|
+
* naming the installed version, instead of at the first change-request merge
|
|
15
|
+
* with an opaque git error.
|
|
16
|
+
*/
|
|
17
|
+
import { execFile } from 'node:child_process';
|
|
18
|
+
import { promisify } from 'node:util';
|
|
19
|
+
const execFileAsync = promisify(execFile);
|
|
20
|
+
/** Oldest git that understands `--no-write-fetch-head`. */
|
|
21
|
+
export const MIN_GIT_VERSION = [2, 29];
|
|
22
|
+
/** `git version 2.39.5 (Apple Git-154)` → `[2, 39]`; null if unrecognisable. */
|
|
23
|
+
export function parseGitVersion(stdout) {
|
|
24
|
+
const m = /^git version (\d+)\.(\d+)/.exec(stdout.trim());
|
|
25
|
+
return m ? [Number(m[1]), Number(m[2])] : null;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Throw when `git --version` output names a version below the floor.
|
|
29
|
+
*
|
|
30
|
+
* An output we can't parse is NOT fatal: a git build with an unusual version
|
|
31
|
+
* string is far more likely than one older than 2.29, and refusing to boot over
|
|
32
|
+
* an unrecognised string would be a worse failure than the one being guarded.
|
|
33
|
+
*/
|
|
34
|
+
export function assertSupportedGitVersion(stdout) {
|
|
35
|
+
const found = parseGitVersion(stdout);
|
|
36
|
+
const [minMajor, minMinor] = MIN_GIT_VERSION;
|
|
37
|
+
if (!found) {
|
|
38
|
+
console.warn(`[git] could not read a version from "${stdout.trim()}" — ` +
|
|
39
|
+
`skipping the git ${minMajor}.${minMinor}+ check`);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const [major, minor] = found;
|
|
43
|
+
if (major > minMajor || (major === minMajor && minor >= minMinor))
|
|
44
|
+
return;
|
|
45
|
+
throw new Error(`git ${minMajor}.${minMinor} or newer is required, found ${major}.${minor}. ` +
|
|
46
|
+
'Every workspace fetch passes --no-write-fetch-head, which older git rejects, ' +
|
|
47
|
+
'so branch refresh and change-request merges cannot work on this runtime.');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Run `git --version` and apply the floor. Call once during startup, before
|
|
51
|
+
* anything clones or fetches.
|
|
52
|
+
*/
|
|
53
|
+
export async function assertGitVersion() {
|
|
54
|
+
let stdout;
|
|
55
|
+
try {
|
|
56
|
+
({ stdout } = await execFileAsync('git', ['--version']));
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
throw new Error(`git is required but could not be run: ${String(err)}`);
|
|
60
|
+
}
|
|
61
|
+
assertSupportedGitVersion(stdout);
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=git-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-version.js","sourceRoot":"","sources":["../../../../src/modules/workflow/git/git-version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,2DAA2D;AAC3D,MAAM,CAAC,MAAM,eAAe,GAA8B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAElE,gFAAgF;AAChF,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,MAAM,CAAC,GAAG,2BAA2B,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAc;IACtD,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACtC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,eAAe,CAAC;IAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CACV,wCAAwC,MAAM,CAAC,IAAI,EAAE,MAAM;YACzD,oBAAoB,QAAQ,IAAI,QAAQ,SAAS,CACpD,CAAC;QACF,OAAO;IACT,CAAC;IACD,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,KAAK,CAAC;IAC7B,IAAI,KAAK,GAAG,QAAQ,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,QAAQ,CAAC;QAAE,OAAO;IAC1E,MAAM,IAAI,KAAK,CACb,OAAO,QAAQ,IAAI,QAAQ,gCAAgC,KAAK,IAAI,KAAK,IAAI;QAC3E,+EAA+E;QAC/E,0EAA0E,CAC7E,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,yCAAyC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,yBAAyB,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC"}
|