@bevel-software/platform-core-backend 0.11.1 → 0.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/create-core-services.d.ts +1 -1
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +2 -2
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +1 -253
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +3 -632
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/access-declarations.d.ts +2 -2
- package/dist/modules/access/access-declarations.d.ts.map +1 -1
- package/dist/modules/access/access-declarations.js +2 -2
- package/dist/modules/access/access-declarations.js.map +1 -1
- package/dist/modules/access/access-mutation.service.d.ts +3 -3
- package/dist/modules/access/access-mutation.service.d.ts.map +1 -1
- package/dist/modules/access/access-mutation.service.js +3 -3
- package/dist/modules/access/access-mutation.service.js.map +1 -1
- package/dist/modules/access/access.routes.js +4 -4
- package/dist/modules/access/access.routes.js.map +1 -1
- package/dist/modules/access/admin-locked-commit.d.ts +2 -2
- package/dist/modules/access/admin-locked-commit.d.ts.map +1 -1
- package/dist/modules/access/admin-locked-commit.js +2 -2
- package/dist/modules/access/admin-locked-commit.js.map +1 -1
- package/dist/modules/access/admin-route-helpers.js +1 -1
- package/dist/modules/access/admin-route-helpers.js.map +1 -1
- package/dist/modules/access/capability-registry.js +1 -1
- package/dist/modules/access/capability-registry.js.map +1 -1
- package/dist/modules/access/creator-access.d.ts +1 -45
- package/dist/modules/access/creator-access.d.ts.map +1 -1
- package/dist/modules/access/creator-access.js +4 -24
- package/dist/modules/access/creator-access.js.map +1 -1
- package/dist/modules/access/groups-admin.routes.js +1 -1
- package/dist/modules/access/groups-admin.routes.js.map +1 -1
- package/dist/modules/access/groups-admin.service.d.ts +1 -1
- package/dist/modules/access/groups-admin.service.d.ts.map +1 -1
- package/dist/modules/access/groups-admin.service.js +6 -5
- package/dist/modules/access/groups-admin.service.js.map +1 -1
- package/dist/modules/access/groups-edit.js +2 -2
- package/dist/modules/access/groups-edit.js.map +1 -1
- package/dist/modules/access/reference-scan.js +1 -1
- package/dist/modules/access/reference-scan.js.map +1 -1
- package/dist/modules/access/roles-admin.service.d.ts +1 -1
- package/dist/modules/access/roles-admin.service.d.ts.map +1 -1
- package/dist/modules/access/roles-admin.service.js +8 -7
- package/dist/modules/access/roles-admin.service.js.map +1 -1
- package/dist/modules/access/roles-edit.js +1 -1
- package/dist/modules/access/roles-edit.js.map +1 -1
- package/dist/modules/access/synced-groups-committer.js +4 -4
- package/dist/modules/access/synced-groups-committer.js.map +1 -1
- package/dist/modules/access/synced-groups-writer.js +2 -2
- package/dist/modules/access/synced-groups-writer.js.map +1 -1
- package/dist/modules/access-model/access-errors.d.ts +34 -0
- package/dist/modules/access-model/access-errors.d.ts.map +1 -0
- package/dist/modules/access-model/access-errors.js +40 -0
- package/dist/modules/access-model/access-errors.js.map +1 -0
- package/dist/modules/access-model/access-grammar.d.ts +266 -0
- package/dist/modules/access-model/access-grammar.d.ts.map +1 -0
- package/dist/modules/access-model/access-grammar.js +644 -0
- package/dist/modules/access-model/access-grammar.js.map +1 -0
- package/dist/modules/access-model/access-splice.d.ts +140 -0
- package/dist/modules/access-model/access-splice.d.ts.map +1 -0
- package/dist/modules/access-model/access-splice.js +389 -0
- package/dist/modules/access-model/access-splice.js.map +1 -0
- package/dist/modules/access-model/creator.d.ts +54 -0
- package/dist/modules/access-model/creator.d.ts.map +1 -0
- package/dist/modules/access-model/creator.js +30 -0
- package/dist/modules/access-model/creator.js.map +1 -0
- package/dist/modules/access-model/group-files.d.ts +83 -0
- package/dist/modules/access-model/group-files.d.ts.map +1 -0
- package/dist/modules/access-model/group-files.js +167 -0
- package/dist/modules/access-model/group-files.js.map +1 -0
- package/dist/modules/access-model/kb-read-filter.d.ts +41 -0
- package/dist/modules/access-model/kb-read-filter.d.ts.map +1 -0
- package/dist/modules/access-model/kb-read-filter.js +60 -0
- package/dist/modules/access-model/kb-read-filter.js.map +1 -0
- package/dist/modules/access-model/render-roles-yaml.d.ts +22 -0
- package/dist/modules/access-model/render-roles-yaml.d.ts.map +1 -0
- package/dist/modules/access-model/render-roles-yaml.js +56 -0
- package/dist/modules/access-model/render-roles-yaml.js.map +1 -0
- package/dist/modules/access-model/roles-yaml-guard.d.ts +56 -0
- package/dist/modules/access-model/roles-yaml-guard.d.ts.map +1 -0
- package/dist/modules/access-model/roles-yaml-guard.js +79 -0
- package/dist/modules/access-model/roles-yaml-guard.js.map +1 -0
- package/dist/modules/admin/admin-access.service.d.ts.map +1 -1
- package/dist/modules/admin/admin-access.service.js +1 -1
- package/dist/modules/admin/admin-access.service.js.map +1 -1
- package/dist/modules/diff/diff.routes.js +4 -4
- package/dist/modules/diff/diff.routes.js.map +1 -1
- package/dist/modules/diff/diff.service.d.ts +1 -1
- package/dist/modules/diff/diff.service.d.ts.map +1 -1
- package/dist/modules/kb-fs/branch-name.d.ts +10 -0
- package/dist/modules/kb-fs/branch-name.d.ts.map +1 -0
- package/dist/modules/kb-fs/branch-name.js +76 -0
- package/dist/modules/kb-fs/branch-name.js.map +1 -0
- package/dist/modules/kb-fs/clone-config.d.ts +61 -0
- package/dist/modules/kb-fs/clone-config.d.ts.map +1 -0
- package/dist/modules/kb-fs/clone-config.js +69 -0
- package/dist/modules/kb-fs/clone-config.js.map +1 -0
- package/dist/modules/kb-fs/file-change-notifier.d.ts +38 -0
- package/dist/modules/kb-fs/file-change-notifier.d.ts.map +1 -0
- package/dist/modules/kb-fs/file-change-notifier.js +22 -0
- package/dist/modules/kb-fs/file-change-notifier.js.map +1 -0
- package/dist/modules/kb-fs/locking-filesystem.d.ts +137 -0
- package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -0
- package/dist/modules/kb-fs/locking-filesystem.js +553 -0
- package/dist/modules/kb-fs/locking-filesystem.js.map +1 -0
- package/dist/modules/kb-fs/mutex.d.ts +11 -0
- package/dist/modules/kb-fs/mutex.d.ts.map +1 -0
- package/dist/modules/kb-fs/mutex.js +23 -0
- package/dist/modules/kb-fs/mutex.js.map +1 -0
- package/dist/modules/kb-fs/read-only-filesystem.d.ts +24 -0
- package/dist/modules/kb-fs/read-only-filesystem.d.ts.map +1 -0
- package/dist/modules/kb-fs/read-only-filesystem.js +39 -0
- package/dist/modules/kb-fs/read-only-filesystem.js.map +1 -0
- package/dist/modules/plugins/join-proposals.d.ts +1 -1
- package/dist/modules/plugins/join-proposals.d.ts.map +1 -1
- package/dist/modules/plugins/join-proposals.js +1 -1
- package/dist/modules/plugins/join-proposals.js.map +1 -1
- package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
- package/dist/modules/plugins/join-requests.service.js +1 -1
- package/dist/modules/plugins/join-requests.service.js.map +1 -1
- package/dist/modules/plugins/plugin-provision.service.js +3 -3
- package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
- package/dist/modules/plugins/plugins.routes.js +2 -2
- package/dist/modules/plugins/plugins.routes.js.map +1 -1
- package/dist/modules/plugins/plugins.service.js +1 -1
- package/dist/modules/plugins/plugins.service.js.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.js +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
- package/dist/modules/skills/pending-skills.service.d.ts.map +1 -1
- package/dist/modules/skills/pending-skills.service.js +1 -1
- package/dist/modules/skills/pending-skills.service.js.map +1 -1
- package/dist/modules/skills/skills.service.js +1 -1
- package/dist/modules/skills/skills.service.js.map +1 -1
- package/dist/modules/tool-helpers/tool-context.d.ts +2 -2
- package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool-context.js +4 -4
- package/dist/modules/tool-helpers/tool-context.js.map +1 -1
- package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts +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 +1 -1
- package/dist/modules/tool-manuals/mcp-server-edit.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.js +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.js +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
- package/dist/modules/workflow/file-lock.service.js +1 -1
- package/dist/modules/workflow/file-lock.service.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +2 -2
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +5 -5
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/git/pull-request.service.js +1 -1
- package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.js +2 -2
- package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
- package/dist/modules/workflow/session-ontology.service.js +1 -1
- package/dist/modules/workflow/session-ontology.service.js.map +1 -1
- package/dist/modules/workflow/workflow.routes.js +2 -2
- package/dist/modules/workflow/workflow.routes.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts +1 -1
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +4 -4
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.js +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
- package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js +1 -1
- package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/roles-yaml.step.d.ts +1 -1
- package/dist/modules/workspace/startup/steps/roles-yaml.step.js +2 -2
- package/dist/modules/workspace/startup/steps/roles-yaml.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.js +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
- package/dist/modules/workspace/workspace.routes.d.ts +1 -1
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.routes.js +5 -4
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +2 -9
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +14 -15
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +3 -3
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/shared/domain-errors.d.ts +202 -0
- package/dist/shared/domain-errors.d.ts.map +1 -0
- package/dist/shared/domain-errors.js +303 -0
- package/dist/shared/domain-errors.js.map +1 -0
- package/dist/shared/workspace-id.d.ts +27 -0
- package/dist/shared/workspace-id.d.ts.map +1 -0
- package/dist/shared/workspace-id.js +36 -0
- package/dist/shared/workspace-id.js.map +1 -0
- package/package.json +3 -3
- package/src/core/create-core-services.ts +2 -2
- package/src/modules/access/__tests__/access-control.service.test.ts +1 -1
- package/src/modules/access/__tests__/access-groups.test.ts +6 -5
- package/src/modules/access/__tests__/access-md-format.test.ts +3 -3
- package/src/modules/access/__tests__/access-mutation.service.test.ts +1 -1
- package/src/modules/access/__tests__/admin-locked-commit.test.ts +1 -1
- package/src/modules/access/__tests__/admin-route-helpers.test.ts +1 -1
- package/src/modules/access/__tests__/roles-admin.service.test.ts +2 -2
- package/src/modules/access/__tests__/roles-edit.test.ts +1 -1
- package/src/modules/access/__tests__/synced-groups-committer.test.ts +1 -1
- package/src/modules/access/__tests__/synced-groups-writer.test.ts +1 -1
- package/src/modules/access/access-control.service.ts +23 -768
- package/src/modules/access/access-declarations.ts +2 -2
- package/src/modules/access/access-mutation.service.ts +3 -3
- package/src/modules/access/access.routes.ts +5 -5
- package/src/modules/access/admin-locked-commit.ts +2 -2
- package/src/modules/access/admin-route-helpers.ts +1 -1
- package/src/modules/access/capability-registry.ts +1 -1
- package/src/modules/access/creator-access.ts +9 -72
- package/src/modules/access/groups-admin.routes.ts +1 -1
- package/src/modules/access/groups-admin.service.ts +6 -7
- package/src/modules/access/groups-edit.ts +2 -2
- package/src/modules/access/reference-scan.ts +1 -1
- package/src/modules/access/roles-admin.service.ts +8 -8
- package/src/modules/access/roles-edit.ts +1 -1
- package/src/modules/access/synced-groups-committer.ts +4 -4
- package/src/modules/access/synced-groups-writer.ts +2 -2
- package/src/modules/access-model/__tests__/access-grammar.test.ts +31 -0
- package/src/modules/{access → access-model}/__tests__/access-splice.test.ts +268 -268
- package/src/modules/{access → access-model}/access-errors.ts +1 -1
- package/src/modules/access-model/access-grammar.ts +778 -0
- package/src/modules/{access → access-model}/access-splice.ts +1 -1
- package/src/modules/access-model/creator.ts +79 -0
- package/src/modules/{access → access-model}/group-files.ts +1 -1
- package/src/modules/{access → access-model}/render-roles-yaml.ts +1 -1
- package/src/modules/{access → access-model}/roles-yaml-guard.ts +2 -2
- package/src/modules/admin/admin-access.service.ts +2 -1
- package/src/modules/diff/__tests__/diff.routes.rejectPathsLocked.test.ts +2 -2
- package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +3 -2
- package/src/modules/diff/__tests__/diff.service.test.ts +3 -2
- package/src/modules/diff/diff.routes.ts +4 -4
- package/src/modules/diff/diff.service.ts +1 -1
- package/src/modules/{workflow/git → kb-fs}/__tests__/branch-name.test.ts +1 -1
- package/src/modules/{workflow → kb-fs}/__tests__/locking-filesystem.test.ts +1 -1
- package/src/modules/{workflow/git → kb-fs}/branch-name.ts +1 -1
- package/src/modules/{workflow → kb-fs}/locking-filesystem.ts +2 -2
- package/src/modules/plugins/__tests__/join-requests.service.test.ts +2 -4
- package/src/modules/plugins/__tests__/plugin-index.service.test.ts +1 -1
- package/src/modules/plugins/__tests__/plugins.routes.test.ts +1 -1
- package/src/modules/plugins/join-proposals.ts +1 -1
- package/src/modules/plugins/join-requests.service.ts +2 -1
- package/src/modules/plugins/plugin-provision.service.ts +3 -3
- package/src/modules/plugins/plugins.routes.ts +2 -2
- package/src/modules/plugins/plugins.service.ts +1 -1
- package/src/modules/secrets-vault/secrets-vault.routes.ts +1 -1
- package/src/modules/skills/__tests__/skills.service.test.ts +1 -1
- package/src/modules/skills/pending-skills.service.ts +2 -1
- package/src/modules/skills/skills.service.ts +1 -1
- package/src/modules/tool-helpers/tool-context.ts +6 -5
- package/src/modules/tool-manuals/__tests__/mcp-server-edit.service.test.ts +1 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.archive.route.test.ts +1 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +1 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +1 -1
- package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +1 -1
- package/src/modules/tool-manuals/mcp-server-edit.service.ts +2 -1
- package/src/modules/tool-manuals/tool-manuals.routes.ts +2 -1
- package/src/modules/tool-manuals/tool-manuals.service.ts +1 -1
- package/src/modules/tool-manuals/tool-manuals.tools.ts +1 -1
- package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +1 -1
- package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +1 -1
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +1 -1
- package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +1 -1
- package/src/modules/workflow/agent-tools/workflow.tools.ts +1 -1
- package/src/modules/workflow/file-lock.service.ts +1 -1
- package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +1 -1
- package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +1 -1
- package/src/modules/workflow/git/__tests__/git.service.diffFileAtCommit.test.ts +1 -1
- package/src/modules/workflow/git/__tests__/git.service.diffFileBetweenBranches.test.ts +1 -1
- package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +1 -1
- package/src/modules/workflow/git/git.service.ts +5 -5
- package/src/modules/workflow/git/pull-request.service.ts +1 -1
- package/src/modules/workflow/review-workflow/__tests__/cancel-pr.test.ts +1 -1
- package/src/modules/workflow/review-workflow/review-workflow.service.ts +2 -2
- package/src/modules/workflow/session-ontology.service.ts +1 -1
- package/src/modules/workflow/workflow.routes.ts +2 -2
- package/src/modules/workflow/workflow.service.ts +5 -5
- package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +1 -1
- package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +1 -1
- package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +1 -1
- package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +2 -5
- package/src/modules/workspace/__tests__/workspace.service.test.ts +13 -1
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +1 -1
- package/src/modules/workspace/startup/kb-startup-runner.ts +1 -1
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +1 -1
- package/src/modules/workspace/startup/steps/groups-to-plugins.step.ts +1 -1
- package/src/modules/workspace/startup/steps/roles-yaml.step.ts +2 -2
- package/src/modules/workspace/startup/steps/seed-tree.ts +1 -1
- package/src/modules/workspace/workspace.routes.ts +6 -5
- package/src/modules/workspace/workspace.service.ts +14 -18
- package/src/modules/workspace/workspace.tools.ts +3 -3
- package/src/shared/__tests__/join-request.test.ts +1 -1
- package/src/shared/__tests__/workspace-id.test.ts +17 -0
- package/src/{modules/workflow/workflow.errors.ts → shared/domain-errors.ts} +6 -1
- package/src/shared/workspace-id.ts +36 -0
- /package/src/modules/{access → access-model}/__tests__/kb-read-filter.test.ts +0 -0
- /package/src/modules/{access → access-model}/__tests__/roles-yaml-guard.test.ts +0 -0
- /package/src/modules/{access → access-model}/kb-read-filter.ts +0 -0
- /package/src/modules/{workflow/git → kb-fs}/__tests__/clone-config.test.ts +0 -0
- /package/src/modules/{workflow → kb-fs}/__tests__/file-change-notifier.test.ts +0 -0
- /package/src/modules/{workflow/git → kb-fs}/__tests__/mutex.test.ts +0 -0
- /package/src/modules/{workflow/git → kb-fs}/clone-config.ts +0 -0
- /package/src/modules/{workflow → kb-fs}/file-change-notifier.ts +0 -0
- /package/src/modules/{workflow/git → kb-fs}/mutex.ts +0 -0
- /package/src/modules/{workflow → kb-fs}/read-only-filesystem.ts +0 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow domain errors. This is the single source of truth — every error
|
|
3
|
+
* raised by the workflow domain (branches, changes, change requests, access
|
|
4
|
+
* control, locks) lives here. Route handlers shape responses via the
|
|
5
|
+
* `.status` + `.payload` contract on the base class.
|
|
6
|
+
*
|
|
7
|
+
* Lives in `src/shared` (not `modules/workflow`) because the classes are
|
|
8
|
+
* consumed across module boundaries — access, diff, plugins and workspace all
|
|
9
|
+
* catch or raise them — and `src/shared` is the layer with no module imports.
|
|
10
|
+
* Only a type from `@bevel-software/platform-shared` comes in; nothing else.
|
|
11
|
+
*
|
|
12
|
+
* Naming: classes use workflow vocabulary. `WorkflowDomainError` is the
|
|
13
|
+
* abstract base; specific subclasses describe the workflow concept that
|
|
14
|
+
* went wrong (`BranchNameError`, `ProtectedBranchError`, etc.). Where a
|
|
15
|
+
* concept is purely git mechanics with no workflow analogue
|
|
16
|
+
* (`NoSharedHistoryError`), the name keeps its git flavour because
|
|
17
|
+
* consumers actually need to discriminate on it.
|
|
18
|
+
*/
|
|
19
|
+
export class WorkflowDomainError extends Error {
|
|
20
|
+
status;
|
|
21
|
+
payload;
|
|
22
|
+
constructor(message, status, payload) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = 'WorkflowDomainError';
|
|
25
|
+
this.status = status;
|
|
26
|
+
this.payload = payload;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export class BranchNameError extends WorkflowDomainError {
|
|
30
|
+
branchName;
|
|
31
|
+
constructor(reason, branchName) {
|
|
32
|
+
super(`Invalid branch name "${branchName}": ${reason}`, 400);
|
|
33
|
+
this.branchName = branchName;
|
|
34
|
+
this.name = 'BranchNameError';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export class ProtectedBranchError extends WorkflowDomainError {
|
|
38
|
+
branchName;
|
|
39
|
+
action;
|
|
40
|
+
constructor(branchName, action) {
|
|
41
|
+
super(`Branch "${branchName}" is protected — ${action} is not allowed.`, 403);
|
|
42
|
+
this.branchName = branchName;
|
|
43
|
+
this.action = action;
|
|
44
|
+
this.name = 'ProtectedBranchError';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The caller tried to delete a branch they don't own. Authorship is inferred
|
|
49
|
+
* from the `<email-localpart>/<slug>` naming convention used by
|
|
50
|
+
* `slugifyDraftName` — see `isBranchAuthoredBy` in `@bevel-software/platform-shared`.
|
|
51
|
+
*
|
|
52
|
+
* Distinct from `AccessDeniedError` because that error is path-based
|
|
53
|
+
* (file-level write permission via `roles.yaml`/`access.md`). Branch
|
|
54
|
+
* authorship is identity-based and has no eligible-roles list to surface —
|
|
55
|
+
* the only way for someone else to delete a non-author's branch is to push
|
|
56
|
+
* the delete via git CLI directly.
|
|
57
|
+
*/
|
|
58
|
+
export class BranchAuthorshipError extends WorkflowDomainError {
|
|
59
|
+
branchName;
|
|
60
|
+
kind = 'branch-authorship';
|
|
61
|
+
constructor(branchName) {
|
|
62
|
+
super(`Only the author of "${branchName}" can delete it.`, 403, { kind: 'branch-authorship', branchName });
|
|
63
|
+
this.branchName = branchName;
|
|
64
|
+
this.name = 'BranchAuthorshipError';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// `DirtyWorkingTreeError` removed: under save=share + per-branch workspaces
|
|
68
|
+
// no operation in the workflow can legitimately encounter a dirty working
|
|
69
|
+
// tree. The two former callers (`switchBranch` and `mergeFromOrigin`'s
|
|
70
|
+
// pre-flight) are gone / relaxed; if a dirty tree ever shows up it's an
|
|
71
|
+
// internal bug that gets server-side-logged in `statusInternal`, never
|
|
72
|
+
// surfaced as a user-facing 409.
|
|
73
|
+
/**
|
|
74
|
+
* The local commit landed but pushing it to origin failed because the
|
|
75
|
+
* remote diverged (a teammate or the agent landed competing commits while
|
|
76
|
+
* the lock was held). The cooperative recovery — `pull --rebase` + retry
|
|
77
|
+
* push — also failed, because the divergence touches the same file and the
|
|
78
|
+
* rebase conflicts.
|
|
79
|
+
*
|
|
80
|
+
* Per the "disk is the source of truth" rule we do NOT auto-force-push
|
|
81
|
+
* from the workflow layer (that's a destructive history rewrite that can
|
|
82
|
+
* lose teammate work irrecoverably). Instead we surface this structured
|
|
83
|
+
* error so the frontend can seed an agent prompt — the agent has git + gh
|
|
84
|
+
* CLI access plus the lock-aware write tool, so it can read both sides,
|
|
85
|
+
* semantically merge, and save the resolved file through the normal
|
|
86
|
+
* save=share pipeline. The user sees only a loading indicator; the agent
|
|
87
|
+
* does the reconciliation.
|
|
88
|
+
*
|
|
89
|
+
* State at the moment this fires:
|
|
90
|
+
* - The local branch has the user's just-committed change as its HEAD.
|
|
91
|
+
* - The lock has already been released (lock release runs BEFORE the
|
|
92
|
+
* push attempt). The agent can acquire its own lock.
|
|
93
|
+
* - `origin/<branch>` has commits the local clone doesn't reach.
|
|
94
|
+
* - The working tree is clean (the commit landed).
|
|
95
|
+
*
|
|
96
|
+
* The payload carries enough context that the prompt builder can phrase
|
|
97
|
+
* the resolution request to the agent without further server round-trips.
|
|
98
|
+
*/
|
|
99
|
+
export class PushNeedsAgentResolutionError extends WorkflowDomainError {
|
|
100
|
+
branch;
|
|
101
|
+
path;
|
|
102
|
+
originalDetail;
|
|
103
|
+
recoveryDetail;
|
|
104
|
+
kind = 'push-needs-resolution';
|
|
105
|
+
constructor(branch, path, originalDetail, recoveryDetail) {
|
|
106
|
+
super(`Saved locally on "${branch}" but couldn't share with the team automatically — ` +
|
|
107
|
+
`the remote diverged on "${path}" and the cooperative rebase couldn't reconcile. ` +
|
|
108
|
+
`The agent will resolve this.`, 409, {
|
|
109
|
+
kind: 'push-needs-resolution',
|
|
110
|
+
branch,
|
|
111
|
+
path,
|
|
112
|
+
originalDetail,
|
|
113
|
+
recoveryDetail,
|
|
114
|
+
});
|
|
115
|
+
this.branch = branch;
|
|
116
|
+
this.path = path;
|
|
117
|
+
this.originalDetail = originalDetail;
|
|
118
|
+
this.recoveryDetail = recoveryDetail;
|
|
119
|
+
this.name = 'PushNeedsAgentResolutionError';
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Refreshing a workspace from origin (`GitService.pull`) hit a rebase
|
|
124
|
+
* conflict: the workspace carries local commits origin doesn't have, origin
|
|
125
|
+
* moved ahead with changes that touch the same files, and replaying the
|
|
126
|
+
* local commits conflicts. The rebase has already been aborted — the
|
|
127
|
+
* workspace is back in its pre-pull state (diverged, clean tree).
|
|
128
|
+
*
|
|
129
|
+
* This state does NOT resolve itself: every subsequent pull hits the same
|
|
130
|
+
* conflict, and the local commits (someone's saved content, under
|
|
131
|
+
* save=share) stay unshared until the divergence is reconciled. The service
|
|
132
|
+
* layer therefore reacts by queueing a background recovery run (see
|
|
133
|
+
* `WorkflowService.updateFromRemote`); this error tells the caller what
|
|
134
|
+
* happened and which paths are contested.
|
|
135
|
+
*
|
|
136
|
+
* 409 like the other conflict errors — the operation needs the divergence
|
|
137
|
+
* cleared before it can succeed. `detail` (the raw git failure, already
|
|
138
|
+
* credential-redacted by `GitService.git`) is kept OFF the payload; it's for
|
|
139
|
+
* server logs and the recovery pipeline, not the client.
|
|
140
|
+
*/
|
|
141
|
+
export class PullRebaseConflictError extends WorkflowDomainError {
|
|
142
|
+
branch;
|
|
143
|
+
conflictedPaths;
|
|
144
|
+
detail;
|
|
145
|
+
kind = 'pull-rebase-conflict';
|
|
146
|
+
constructor(branch, conflictedPaths, detail) {
|
|
147
|
+
const list = conflictedPaths.join(', ');
|
|
148
|
+
super(`Updating "${branch}" from origin hit conflicts in ${conflictedPaths.length} file(s): ${list}. ` +
|
|
149
|
+
`Automatic background recovery has been queued.`, 409, {
|
|
150
|
+
kind: 'pull-rebase-conflict',
|
|
151
|
+
branch,
|
|
152
|
+
conflictedPaths,
|
|
153
|
+
});
|
|
154
|
+
this.branch = branch;
|
|
155
|
+
this.conflictedPaths = conflictedPaths;
|
|
156
|
+
this.detail = detail;
|
|
157
|
+
this.name = 'PullRebaseConflictError';
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Generic 400 for workflow-input validation (malformed branch names, missing
|
|
162
|
+
* fields, etc.). Carries an optional payload so callers can attach typed
|
|
163
|
+
* discriminators (`kind: '...'`) when the frontend needs to switch on the
|
|
164
|
+
* specific failure mode.
|
|
165
|
+
*/
|
|
166
|
+
export class WorkflowValidationError extends WorkflowDomainError {
|
|
167
|
+
constructor(message, payload) {
|
|
168
|
+
super(message, 400, payload);
|
|
169
|
+
this.name = 'WorkflowValidationError';
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* The draft branch doesn't share history with the target branch, so GitHub
|
|
174
|
+
* would reject the change request with `no history in common`. Surfaced as
|
|
175
|
+
* a structured payload so the frontend's typed-error parser can route into
|
|
176
|
+
* the agent recovery flow.
|
|
177
|
+
*/
|
|
178
|
+
export class NoSharedHistoryError extends WorkflowDomainError {
|
|
179
|
+
head;
|
|
180
|
+
base;
|
|
181
|
+
kind = 'no-shared-history';
|
|
182
|
+
constructor(head, base) {
|
|
183
|
+
super(`The draft "${head}" doesn't share history with "${base}". ` +
|
|
184
|
+
`It was likely started outside the app or from an unrelated point.`, 400, { kind: 'no-shared-history', head, base });
|
|
185
|
+
this.head = head;
|
|
186
|
+
this.base = base;
|
|
187
|
+
this.name = 'NoSharedHistoryError';
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* The KB validator reported `mustFix` issues (DANGLING LINK / ASYMMETRY /
|
|
192
|
+
* ERROR) — the change cannot land until they're resolved. The payload
|
|
193
|
+
* carries the structured report so the UI / agent can render the items
|
|
194
|
+
* the user must fix without re-running the validator.
|
|
195
|
+
*/
|
|
196
|
+
export class ValidationFailedError extends WorkflowDomainError {
|
|
197
|
+
validation;
|
|
198
|
+
constructor(report) {
|
|
199
|
+
super(`Cannot commit — knowledge graph has ${report.mustFix.length} unresolved issue(s).`, 422, {
|
|
200
|
+
validation: {
|
|
201
|
+
ok: report.ok,
|
|
202
|
+
mustFix: report.mustFix,
|
|
203
|
+
warnings: report.warnings,
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
this.name = 'ValidationFailedError';
|
|
207
|
+
this.validation = report;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Method exists on the workflow interface but has no backing implementation
|
|
212
|
+
* yet. 501 so the frontend can light up "coming soon" affordances without
|
|
213
|
+
* confusing them with 5xx infra failures. `feature` is the workflow method
|
|
214
|
+
* name; clients switch on it to render targeted copy.
|
|
215
|
+
*/
|
|
216
|
+
export class NotImplementedWorkflowError extends WorkflowDomainError {
|
|
217
|
+
feature;
|
|
218
|
+
kind = 'not-implemented';
|
|
219
|
+
constructor(feature) {
|
|
220
|
+
super(`Workflow feature "${feature}" is not yet implemented in this build.`, 501, { kind: 'not-implemented', feature });
|
|
221
|
+
this.feature = feature;
|
|
222
|
+
this.name = 'NotImplementedWorkflowError';
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Attempting to reconcile two branches (opening a change request, refreshing
|
|
227
|
+
* one from target, or executing a merge) hit conflicts that the workflow
|
|
228
|
+
* cannot auto-resolve. The structured payload carries the list of
|
|
229
|
+
* conflicting paths so the frontend / agent can route into the resolution
|
|
230
|
+
* flow without a second round-trip.
|
|
231
|
+
*
|
|
232
|
+
* 409 because the conflict is a precondition the caller has to clear (by
|
|
233
|
+
* resolving + committing on the source branch) before the operation can
|
|
234
|
+
* succeed — same semantics git itself uses for merge conflicts.
|
|
235
|
+
*/
|
|
236
|
+
export class ChangeRequestConflictsError extends WorkflowDomainError {
|
|
237
|
+
sourceBranch;
|
|
238
|
+
targetBranch;
|
|
239
|
+
conflictedPaths;
|
|
240
|
+
kind = 'change-request-conflicts';
|
|
241
|
+
constructor(sourceBranch, targetBranch, conflictedPaths) {
|
|
242
|
+
const list = conflictedPaths.join(', ');
|
|
243
|
+
super(`Conflicts merging "${targetBranch}" into "${sourceBranch}". ` +
|
|
244
|
+
`${conflictedPaths.length} file(s): ${list}. Resolve on "${sourceBranch}" and try again.`, 409, {
|
|
245
|
+
kind: 'change-request-conflicts',
|
|
246
|
+
sourceBranch,
|
|
247
|
+
targetBranch,
|
|
248
|
+
conflictedPaths,
|
|
249
|
+
});
|
|
250
|
+
this.sourceBranch = sourceBranch;
|
|
251
|
+
this.targetBranch = targetBranch;
|
|
252
|
+
this.conflictedPaths = conflictedPaths;
|
|
253
|
+
this.name = 'ChangeRequestConflictsError';
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Caller tried to open a change request for a `(source, target)` pair that
|
|
258
|
+
* already has one open. Spec rule: A→B blocks A→B (B→A is allowed). Carries
|
|
259
|
+
* the existing CR number so the UI / agent can deep-link to it instead of
|
|
260
|
+
* trying to recover.
|
|
261
|
+
*/
|
|
262
|
+
export class DuplicateChangeRequestError extends WorkflowDomainError {
|
|
263
|
+
sourceBranch;
|
|
264
|
+
targetBranch;
|
|
265
|
+
existingNumber;
|
|
266
|
+
kind = 'duplicate-change-request';
|
|
267
|
+
constructor(sourceBranch, targetBranch, existingNumber) {
|
|
268
|
+
super(`An open change request already exists from "${sourceBranch}" to "${targetBranch}" (#${existingNumber}).`, 409, {
|
|
269
|
+
kind: 'duplicate-change-request',
|
|
270
|
+
sourceBranch,
|
|
271
|
+
targetBranch,
|
|
272
|
+
existingNumber,
|
|
273
|
+
});
|
|
274
|
+
this.sourceBranch = sourceBranch;
|
|
275
|
+
this.targetBranch = targetBranch;
|
|
276
|
+
this.existingNumber = existingNumber;
|
|
277
|
+
this.name = 'DuplicateChangeRequestError';
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Raised when a merge must neutralise a CR's `roles.yaml` change (restore the
|
|
282
|
+
* base branch's version on the source branch) but that preservation write fails.
|
|
283
|
+
* `roles.yaml` decides admin membership and is mutable ONLY via the admin Roles
|
|
284
|
+
* & Members surface — a CR must never carry a roles.yaml change across a merge,
|
|
285
|
+
* so if we cannot guarantee the base version is preserved we abort the merge
|
|
286
|
+
* rather than risk landing the CR's version on a protected branch. 502: the
|
|
287
|
+
* failure is an internal git/push hiccup, not the caller's fault.
|
|
288
|
+
*/
|
|
289
|
+
export class RolesYamlPreservationError extends WorkflowDomainError {
|
|
290
|
+
kind = 'roles-yaml-preservation-failed';
|
|
291
|
+
/**
|
|
292
|
+
* The underlying git/push failure. Kept OFF the client-facing message (which
|
|
293
|
+
* stays generic for the 502) so raw git internals / paths don't leak to the
|
|
294
|
+
* caller — log this server-side for diagnostics instead.
|
|
295
|
+
*/
|
|
296
|
+
detail;
|
|
297
|
+
constructor(reason) {
|
|
298
|
+
super('Could not preserve the official roles.yaml while merging — merge aborted so no roles.yaml change can ride in.', 502, { kind: 'roles-yaml-preservation-failed' });
|
|
299
|
+
this.name = 'RolesYamlPreservationError';
|
|
300
|
+
this.detail = reason;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
//# sourceMappingURL=domain-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-errors.js","sourceRoot":"","sources":["../../src/shared/domain-errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The branch ↔ workspace-directory naming convention. Workspaces are
|
|
3
|
+
* per-branch (one on-disk clone per branch name), and the workspace id IS the
|
|
4
|
+
* URL-encoded branch name — deterministic both ways, so every caller
|
|
5
|
+
* (backend, frontend, agent) can compute one from the other without a DB
|
|
6
|
+
* round-trip. Consumed by nearly every module that touches a workspace, so it
|
|
7
|
+
* lives in `backend/src/shared` rather than inside the workspace module.
|
|
8
|
+
*
|
|
9
|
+
* Pure string handling — no IO, no DB.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Map a branch name to the directory that contains its workspace clone.
|
|
13
|
+
* `encodeURIComponent` handles `/` in branch names (e.g. `alice/foo`) by
|
|
14
|
+
* encoding it to `%2F` — single-segment-safe on every supported filesystem.
|
|
15
|
+
*/
|
|
16
|
+
export declare function workspaceIdForBranch(branch: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Map a workspace id back to its branch name. Workspace ids come in from
|
|
19
|
+
* request paths and from directory names on disk, so malformed input (a lone
|
|
20
|
+
* `%`, `%` without two hex digits) must not throw — `decodeURIComponent`
|
|
21
|
+
* would raise a `URIError` that surfaces as an unhandled 500 in every route
|
|
22
|
+
* that resolves an id. A malformed id can never equal a valid encoding, so
|
|
23
|
+
* returning it unchanged is safe: it simply names a branch that does not
|
|
24
|
+
* exist, and the caller's own lookup fails with its normal not-found path.
|
|
25
|
+
*/
|
|
26
|
+
export declare function branchForWorkspaceId(workspaceId: string): string;
|
|
27
|
+
//# sourceMappingURL=workspace-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-id.d.ts","sourceRoot":"","sources":["../../src/shared/workspace-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAMhE"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The branch ↔ workspace-directory naming convention. Workspaces are
|
|
3
|
+
* per-branch (one on-disk clone per branch name), and the workspace id IS the
|
|
4
|
+
* URL-encoded branch name — deterministic both ways, so every caller
|
|
5
|
+
* (backend, frontend, agent) can compute one from the other without a DB
|
|
6
|
+
* round-trip. Consumed by nearly every module that touches a workspace, so it
|
|
7
|
+
* lives in `backend/src/shared` rather than inside the workspace module.
|
|
8
|
+
*
|
|
9
|
+
* Pure string handling — no IO, no DB.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Map a branch name to the directory that contains its workspace clone.
|
|
13
|
+
* `encodeURIComponent` handles `/` in branch names (e.g. `alice/foo`) by
|
|
14
|
+
* encoding it to `%2F` — single-segment-safe on every supported filesystem.
|
|
15
|
+
*/
|
|
16
|
+
export function workspaceIdForBranch(branch) {
|
|
17
|
+
return encodeURIComponent(branch);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Map a workspace id back to its branch name. Workspace ids come in from
|
|
21
|
+
* request paths and from directory names on disk, so malformed input (a lone
|
|
22
|
+
* `%`, `%` without two hex digits) must not throw — `decodeURIComponent`
|
|
23
|
+
* would raise a `URIError` that surfaces as an unhandled 500 in every route
|
|
24
|
+
* that resolves an id. A malformed id can never equal a valid encoding, so
|
|
25
|
+
* returning it unchanged is safe: it simply names a branch that does not
|
|
26
|
+
* exist, and the caller's own lookup fails with its normal not-found path.
|
|
27
|
+
*/
|
|
28
|
+
export function branchForWorkspaceId(workspaceId) {
|
|
29
|
+
try {
|
|
30
|
+
return decodeURIComponent(workspaceId);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return workspaceId;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=workspace-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-id.js","sourceRoot":"","sources":["../../src/shared/workspace-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACtD,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,WAAW,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,WAAW,CAAC;IACrB,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bevel-software/platform-core-backend",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"description": "Open-source core backend of the Bevel platform: git-backed knowledge workspace, workflow (branches/change requests/locks/SSE), skills, tools, secrets vault, access control and the remote MCP surface.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"pg": "^8.20.0",
|
|
47
47
|
"yaml": "^2.9.0",
|
|
48
48
|
"zod": "^3.24.0",
|
|
49
|
-
"@bevel-software/platform-mcp-core": "0.11.
|
|
50
|
-
"@bevel-software/platform-shared": "0.11.
|
|
49
|
+
"@bevel-software/platform-mcp-core": "0.11.2",
|
|
50
|
+
"@bevel-software/platform-shared": "0.11.2"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/adm-zip": "^0.5.8",
|
|
@@ -47,13 +47,13 @@ import {
|
|
|
47
47
|
} from '../modules/secrets-vault/index.js';
|
|
48
48
|
import { GitService } from '../modules/workflow/git/git.service.js';
|
|
49
49
|
import { PullRequestService } from '../modules/workflow/git/pull-request.service.js';
|
|
50
|
-
import { WorkspaceMutex } from '../modules/
|
|
50
|
+
import { WorkspaceMutex } from '../modules/kb-fs/mutex.js';
|
|
51
51
|
import { assertGitVersion } from '../modules/workflow/git/git-version.js';
|
|
52
52
|
import { DiffService } from '../modules/diff/diff.service.js';
|
|
53
53
|
import { ReviewWorkflowService } from '../modules/workflow/review-workflow/review-workflow.service.js';
|
|
54
54
|
import { FileLockService } from '../modules/workflow/file-lock.service.js';
|
|
55
55
|
import { WorkflowEventBus } from '../modules/workflow/event-bus.js';
|
|
56
|
-
import { FileChangeNotifier } from '../modules/
|
|
56
|
+
import { FileChangeNotifier } from '../modules/kb-fs/file-change-notifier.js';
|
|
57
57
|
import { WorkflowService } from '../modules/workflow/workflow.service.js';
|
|
58
58
|
import { WorkflowHooks } from '../modules/workflow/workflow-hooks.js';
|
|
59
59
|
import { SessionOntologyService } from '../modules/workflow/session-ontology.service.js';
|
|
@@ -5,7 +5,7 @@ import os from 'node:os';
|
|
|
5
5
|
|
|
6
6
|
import type { WorkspaceService } from '../../workspace/workspace.service.js';
|
|
7
7
|
import { AccessControlService } from '../access-control.service.js';
|
|
8
|
-
import { AccessConfigError } from '
|
|
8
|
+
import { AccessConfigError } from '../../access-model/access-errors.js';
|
|
9
9
|
|
|
10
10
|
const PROCESS_MAP_DIR = 'knowledge-base';
|
|
11
11
|
|
|
@@ -6,8 +6,9 @@ import { execFile } from 'node:child_process';
|
|
|
6
6
|
import { promisify } from 'node:util';
|
|
7
7
|
|
|
8
8
|
import type { WorkspaceService } from '../../workspace/workspace.service.js';
|
|
9
|
-
import { AccessControlService
|
|
10
|
-
import {
|
|
9
|
+
import { AccessControlService } from '../access-control.service.js';
|
|
10
|
+
import { parseRolesYaml } from '../../access-model/access-grammar.js';
|
|
11
|
+
import { AccessConfigError } from '../../access-model/access-errors.js';
|
|
11
12
|
import { addMember, parseRolesModel, emitRolesModel } from '../roles-edit.js';
|
|
12
13
|
|
|
13
14
|
const execFileAsync = promisify(execFile);
|
|
@@ -102,7 +103,7 @@ describe('group files as access principals', () => {
|
|
|
102
103
|
});
|
|
103
104
|
|
|
104
105
|
it('validateGroupsFile (the WRITE gate) still refuses blank keys the reader forgives', async () => {
|
|
105
|
-
const { validateGroupsFile } = await import('
|
|
106
|
+
const { validateGroupsFile } = await import('../../access-model/group-files.js');
|
|
106
107
|
// Inside `groups:` — refused via the entry warning (strict gate).
|
|
107
108
|
expect(validateGroupsFile('groups:\n :\n - a@x.io\n', 'groups.yaml').ok).toBe(false);
|
|
108
109
|
// At the ROOT — the tolerant reader silently drops this without any
|
|
@@ -114,7 +115,7 @@ describe('group files as access principals', () => {
|
|
|
114
115
|
});
|
|
115
116
|
|
|
116
117
|
it('parseGroupsFile applies the shared name-safety predicate (warn-and-skip), and the write gate refuses', async () => {
|
|
117
|
-
const { parseGroupsFile, validateGroupsFile } = await import('
|
|
118
|
+
const { parseGroupsFile, validateGroupsFile } = await import('../../access-model/group-files.js');
|
|
118
119
|
// `<`/`>` and control characters pass the YAML subset as plain keys but
|
|
119
120
|
// fail unsafeNameReason — the parser must skip them (other groups keep
|
|
120
121
|
// resolving) and the strict write gate must refuse the whole candidate.
|
|
@@ -133,7 +134,7 @@ describe('group files as access principals', () => {
|
|
|
133
134
|
});
|
|
134
135
|
|
|
135
136
|
it("parseGroupsFile skips a 'group:'-prefixed member (shapes like an email, but is the ref token)", async () => {
|
|
136
|
-
const { parseGroupsFile, validateGroupsFile } = await import('
|
|
137
|
+
const { parseGroupsFile, validateGroupsFile } = await import('../../access-model/group-files.js');
|
|
137
138
|
// `group:lee@x.io` PASSES the email regex — without the explicit skip it
|
|
138
139
|
// would land as a member "email" nothing can ever log in as.
|
|
139
140
|
const text = 'groups:\n Team:\n - group:lee@x.io\n - real@x.io\n';
|
|
@@ -4,13 +4,13 @@ import path from 'node:path';
|
|
|
4
4
|
import os from 'node:os';
|
|
5
5
|
|
|
6
6
|
import type { WorkspaceService } from '../../workspace/workspace.service.js';
|
|
7
|
+
import { AccessControlService } from '../access-control.service.js';
|
|
7
8
|
import {
|
|
8
|
-
AccessControlService,
|
|
9
9
|
accessMdDeclaresBodyRules,
|
|
10
10
|
accessMdSelfEntries,
|
|
11
11
|
parseAccessFile,
|
|
12
|
-
} from '
|
|
13
|
-
import { spliceGrant, spliceRevoke } from '
|
|
12
|
+
} from '../../access-model/access-grammar.js';
|
|
13
|
+
import { spliceGrant, spliceRevoke } from '../../access-model/access-splice.js';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* The two-format `access.md` story:
|
|
@@ -6,7 +6,7 @@ import os from 'node:os';
|
|
|
6
6
|
import type { WorkspaceService } from '../../workspace/workspace.service.js';
|
|
7
7
|
import { AccessControlService } from '../access-control.service.js';
|
|
8
8
|
import { AccessMutationService, AccessMutationError } from '../access-mutation.service.js';
|
|
9
|
-
import type { Principal } from '
|
|
9
|
+
import type { Principal } from '../../access-model/access-splice.js';
|
|
10
10
|
|
|
11
11
|
const KB = 'knowledge-base';
|
|
12
12
|
const WS = 'ws-mut-1';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect, vi } from 'vitest';
|
|
2
2
|
|
|
3
3
|
import { AdminLockedCommits } from '../admin-locked-commit.js';
|
|
4
|
-
import { PushNeedsAgentResolutionError, WorkflowDomainError } from '
|
|
4
|
+
import { PushNeedsAgentResolutionError, WorkflowDomainError } from '../../../shared/domain-errors.js';
|
|
5
5
|
import type { AuthUser, IWorkspaceService, IWorkflowService } from '@bevel-software/platform-shared';
|
|
6
6
|
|
|
7
7
|
const KB = 'knowledge-base';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
2
2
|
|
|
3
3
|
import { toHttpError, requireNonEmptyString } from '../admin-route-helpers.js';
|
|
4
|
-
import { WorkflowDomainError } from '
|
|
4
|
+
import { WorkflowDomainError } from '../../../shared/domain-errors.js';
|
|
5
5
|
import { AccessMutationError } from '../access-mutation.service.js';
|
|
6
6
|
|
|
7
7
|
describe('toHttpError — the shared access-family error shape', () => {
|
|
@@ -7,11 +7,11 @@ import type { WorkspaceService } from '../../workspace/workspace.service.js';
|
|
|
7
7
|
import type { WorkflowService } from '../../workflow/workflow.service.js';
|
|
8
8
|
import type { WorkflowEventBus } from '../../workflow/event-bus.js';
|
|
9
9
|
import type { FileTreeEntry, WorkflowEventPayload } from '@bevel-software/platform-shared';
|
|
10
|
-
import { workspaceIdForBranch } from '
|
|
10
|
+
import { workspaceIdForBranch } from '../../../shared/workspace-id.js';
|
|
11
11
|
import { AccessControlService } from '../access-control.service.js';
|
|
12
12
|
import { RolesAdminService } from '../roles-admin.service.js';
|
|
13
13
|
import { rewriteRoleTokensInText, findRoleRefsInText } from '../reference-scan.js';
|
|
14
|
-
import { PushNeedsAgentResolutionError } from '
|
|
14
|
+
import { PushNeedsAgentResolutionError } from '../../../shared/domain-errors.js';
|
|
15
15
|
import type { AuthUser } from '@bevel-software/platform-shared';
|
|
16
16
|
import { DEFAULT_BRANCH } from '@bevel-software/platform-shared';
|
|
17
17
|
|
|
@@ -8,7 +8,7 @@ import type { WorkspaceService } from '../../workspace/workspace.service.js';
|
|
|
8
8
|
import type { AccessControlService } from '../access-control.service.js';
|
|
9
9
|
import type { WorkflowEventBus } from '../../workflow/event-bus.js';
|
|
10
10
|
import { createSyncedGroupsCommitter } from '../synced-groups-committer.js';
|
|
11
|
-
import { PushNeedsAgentResolutionError, WorkflowValidationError } from '
|
|
11
|
+
import { PushNeedsAgentResolutionError, WorkflowValidationError } from '../../../shared/domain-errors.js';
|
|
12
12
|
|
|
13
13
|
const KB = 'knowledge-base';
|
|
14
14
|
const BOT: AuthUser = { id: 'bot-1', email: 'directory-sync@bevel.local', name: 'Directory Sync Bot' };
|