@bevel-software/platform-core-backend 0.28.1 → 0.30.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/agent-guide/access-control.md +15 -0
- package/agent-guide/skills.md +8 -0
- package/dist/__tests__/test-repositories.d.ts +3 -0
- package/dist/__tests__/test-repositories.d.ts.map +1 -0
- package/dist/__tests__/test-repositories.js +18 -0
- package/dist/__tests__/test-repositories.js.map +1 -0
- package/dist/core/catalog-revision.d.ts.map +1 -1
- package/dist/core/catalog-revision.js +4 -2
- package/dist/core/catalog-revision.js.map +1 -1
- package/dist/core/compose-embed.d.ts +35 -0
- package/dist/core/compose-embed.d.ts.map +1 -0
- package/dist/core/compose-embed.js +14 -0
- package/dist/core/compose-embed.js.map +1 -0
- package/dist/core/core-ports.d.ts +10 -0
- package/dist/core/core-ports.d.ts.map +1 -1
- package/dist/core/core-ports.js.map +1 -1
- package/dist/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +8 -2
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +4 -1
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +57 -18
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core/lifecycle.d.ts +19 -6
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +17 -6
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/modules/access/access-control.interface.d.ts +20 -0
- package/dist/modules/access/access-control.interface.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +68 -15
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +282 -58
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/access.routes.d.ts.map +1 -1
- package/dist/modules/access/access.routes.js +20 -6
- package/dist/modules/access/access.routes.js.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.d.ts +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.js +1 -1
- package/dist/modules/auth/index.d.ts +15 -0
- package/dist/modules/auth/index.d.ts.map +1 -0
- package/dist/modules/auth/index.js +20 -0
- package/dist/modules/auth/index.js.map +1 -0
- package/dist/modules/diff/diff.service.d.ts.map +1 -1
- package/dist/modules/diff/diff.service.js +7 -1
- package/dist/modules/diff/diff.service.js.map +1 -1
- package/dist/modules/embed/embed.interface.d.ts +22 -0
- package/dist/modules/embed/embed.interface.d.ts.map +1 -1
- package/dist/modules/embed/embed.service.d.ts +28 -14
- package/dist/modules/embed/embed.service.d.ts.map +1 -1
- package/dist/modules/embed/embed.service.js +38 -17
- package/dist/modules/embed/embed.service.js.map +1 -1
- package/dist/modules/embed/embed.tools.d.ts.map +1 -1
- package/dist/modules/embed/embed.tools.js +10 -2
- package/dist/modules/embed/embed.tools.js.map +1 -1
- package/dist/modules/kb-fs/git-dir.d.ts +21 -0
- package/dist/modules/kb-fs/git-dir.d.ts.map +1 -0
- package/dist/modules/kb-fs/git-dir.js +58 -0
- package/dist/modules/kb-fs/git-dir.js.map +1 -0
- package/dist/modules/kb-fs/index.d.ts +9 -0
- package/dist/modules/kb-fs/index.d.ts.map +1 -0
- package/dist/modules/kb-fs/index.js +3 -0
- package/dist/modules/kb-fs/index.js.map +1 -0
- package/dist/modules/kb-fs/ref-files.d.ts +63 -0
- package/dist/modules/kb-fs/ref-files.d.ts.map +1 -0
- package/dist/modules/kb-fs/ref-files.js +249 -0
- package/dist/modules/kb-fs/ref-files.js.map +1 -0
- package/dist/modules/plugins/join-request-jobs.service.d.ts.map +1 -1
- package/dist/modules/plugins/join-request-jobs.service.js +43 -8
- package/dist/modules/plugins/join-request-jobs.service.js.map +1 -1
- package/dist/modules/plugins/teams.routes.d.ts +4 -0
- package/dist/modules/plugins/teams.routes.d.ts.map +1 -1
- package/dist/modules/plugins/teams.routes.js +9 -1
- package/dist/modules/plugins/teams.routes.js.map +1 -1
- package/dist/modules/skills/skills.contract.d.ts.map +1 -1
- package/dist/modules/skills/skills.tools.d.ts +8 -1
- package/dist/modules/skills/skills.tools.d.ts.map +1 -1
- package/dist/modules/skills/skills.tools.js +115 -11
- package/dist/modules/skills/skills.tools.js.map +1 -1
- package/dist/modules/tool-auth/internal-token.service.d.ts +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts +1 -2
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.js +1 -2
- package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
- package/dist/modules/tool-helpers/default-branch-write.d.ts +69 -0
- package/dist/modules/tool-helpers/default-branch-write.d.ts.map +1 -0
- package/dist/modules/tool-helpers/default-branch-write.js +63 -0
- package/dist/modules/tool-helpers/default-branch-write.js.map +1 -0
- package/dist/modules/tool-helpers/index.d.ts +1 -0
- package/dist/modules/tool-helpers/index.d.ts.map +1 -1
- package/dist/modules/tool-helpers/index.js +1 -0
- package/dist/modules/tool-helpers/index.js.map +1 -1
- package/dist/modules/tool-helpers/tool-handler.d.ts +2 -2
- package/dist/modules/tool-helpers/tool.contract.d.ts +2 -2
- package/dist/modules/workflow/file-lock.service.d.ts +27 -5
- package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
- package/dist/modules/workflow/file-lock.service.js +70 -18
- package/dist/modules/workflow/file-lock.service.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +42 -0
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +201 -24
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/index.d.ts +8 -0
- package/dist/modules/workflow/index.d.ts.map +1 -0
- package/dist/modules/workflow/index.js +8 -0
- package/dist/modules/workflow/index.js.map +1 -0
- package/dist/modules/workflow/pending-commits.service.d.ts +2 -17
- package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
- package/dist/modules/workflow/pending-commits.service.js +4 -24
- package/dist/modules/workflow/pending-commits.service.js.map +1 -1
- package/dist/modules/workflow/workflow-hooks.d.ts +1 -1
- package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.routes.js +20 -1
- package/dist/modules/workflow/workflow.routes.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +5 -3
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/agent-access.gate.d.ts +2 -2
- package/dist/modules/workspace/agent-access.gate.js +2 -2
- package/dist/modules/workspace/bounded-matcher.d.ts +79 -0
- package/dist/modules/workspace/bounded-matcher.d.ts.map +1 -0
- package/dist/modules/workspace/bounded-matcher.js +261 -0
- package/dist/modules/workspace/bounded-matcher.js.map +1 -0
- package/dist/modules/workspace/fetch-instant.d.ts +9 -0
- package/dist/modules/workspace/fetch-instant.d.ts.map +1 -0
- package/dist/modules/workspace/fetch-instant.js +13 -0
- package/dist/modules/workspace/fetch-instant.js.map +1 -0
- package/dist/modules/workspace/index.d.ts +17 -0
- package/dist/modules/workspace/index.d.ts.map +1 -0
- package/dist/modules/workspace/index.js +16 -0
- package/dist/modules/workspace/index.js.map +1 -0
- package/dist/modules/workspace/kb-repository.contract.d.ts +124 -0
- package/dist/modules/workspace/kb-repository.contract.d.ts.map +1 -0
- package/dist/modules/workspace/kb-repository.contract.js +19 -0
- package/dist/modules/workspace/kb-repository.contract.js.map +1 -0
- package/dist/modules/workspace/kb-repository.d.ts +236 -0
- package/dist/modules/workspace/kb-repository.d.ts.map +1 -0
- package/dist/modules/workspace/kb-repository.js +811 -0
- package/dist/modules/workspace/kb-repository.js.map +1 -0
- package/dist/modules/workspace/pattern-matcher.contract.d.ts +50 -0
- package/dist/modules/workspace/pattern-matcher.contract.d.ts.map +1 -0
- package/dist/modules/workspace/pattern-matcher.contract.js +27 -0
- package/dist/modules/workspace/pattern-matcher.contract.js.map +1 -0
- package/dist/modules/workspace/routine-write-policy.d.ts +0 -7
- package/dist/modules/workspace/routine-write-policy.d.ts.map +1 -1
- package/dist/modules/workspace/routine-write-policy.js +0 -5
- package/dist/modules/workspace/routine-write-policy.js.map +1 -1
- package/dist/modules/workspace/set-aside-clone.d.ts +40 -0
- package/dist/modules/workspace/set-aside-clone.d.ts.map +1 -1
- package/dist/modules/workspace/set-aside-clone.js +139 -0
- package/dist/modules/workspace/set-aside-clone.js.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts +99 -0
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.js +407 -29
- package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +68 -32
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +240 -161
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts +13 -4
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +268 -356
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/shared/workspace-id.d.ts +17 -0
- package/dist/shared/workspace-id.d.ts.map +1 -1
- package/dist/shared/workspace-id.js +24 -0
- package/dist/shared/workspace-id.js.map +1 -1
- package/dist/test-setup.js +4 -0
- package/dist/test-setup.js.map +1 -1
- package/mcp-app/page.html +142 -8
- package/package.json +3 -3
- package/src/__tests__/test-repositories.ts +22 -0
- package/src/__tests__/workspace-service.ts +69 -0
- package/src/core/__tests__/compose-embed.test.ts +65 -0
- package/src/core/__tests__/lifecycle.test.ts +45 -26
- package/src/core/catalog-revision.ts +4 -2
- package/src/core/compose-embed.ts +50 -0
- package/src/core/core-ports.ts +10 -0
- package/src/core/create-core-server.ts +8 -2
- package/src/core/create-core-services.ts +63 -24
- package/src/core/lifecycle.ts +34 -12
- package/src/modules/access/__tests__/access-control.atref-cache.test.ts +443 -25
- package/src/modules/access/__tests__/access-control.group-read.test.ts +73 -0
- package/src/modules/access/__tests__/access.routes.group-grant.test.ts +66 -0
- package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +2 -0
- package/src/modules/access/access-control.interface.ts +22 -0
- package/src/modules/access/access-control.service.ts +302 -58
- package/src/modules/access/access.routes.ts +22 -6
- package/src/modules/agent-instructions/shared-file-rules.ts +1 -1
- package/src/modules/auth/index.ts +29 -0
- package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +2 -1
- package/src/modules/diff/__tests__/diff.service.test.ts +2 -1
- package/src/modules/diff/__tests__/diff.service.worktree.test.ts +76 -0
- package/src/modules/diff/diff.service.ts +6 -4
- package/src/modules/embed/__tests__/embed.service.test.ts +76 -3
- package/src/modules/embed/__tests__/embed.tools.test.ts +29 -0
- package/src/modules/embed/embed.interface.ts +24 -0
- package/src/modules/embed/embed.service.ts +44 -19
- package/src/modules/embed/embed.tools.ts +10 -2
- package/src/modules/kb-fs/__tests__/git-dir.test.ts +77 -0
- package/src/modules/kb-fs/__tests__/ref-files.test.ts +338 -0
- package/src/modules/kb-fs/git-dir.ts +53 -0
- package/src/modules/kb-fs/index.ts +8 -0
- package/src/modules/kb-fs/ref-files.ts +279 -0
- package/src/modules/plugins/__tests__/join-request-jobs.service.test.ts +73 -6
- package/src/modules/plugins/__tests__/teams.routes.test.ts +55 -0
- package/src/modules/plugins/join-request-jobs.service.ts +45 -8
- package/src/modules/plugins/teams.routes.ts +14 -1
- package/src/modules/settings/__tests__/setup.routes.layout-phase.test.ts +2 -2
- package/src/modules/settings/__tests__/setup.routes.managed-phase.test.ts +2 -2
- package/src/modules/skills/__tests__/branch-skills.tools.test.ts +1 -1
- package/src/modules/skills/skills.contract.ts +4 -0
- package/src/modules/skills/skills.tools.ts +120 -10
- package/src/modules/tool-auth/internal-token.service.ts +1 -1
- package/src/modules/tool-auth/tool-auth.middleware.ts +1 -2
- package/src/modules/tool-helpers/__tests__/branch-declaration.test.ts +2 -2
- package/src/modules/tool-helpers/__tests__/can-write.tools.test.ts +581 -0
- package/src/modules/tool-helpers/default-branch-write.ts +90 -0
- package/src/modules/tool-helpers/index.ts +5 -0
- package/src/modules/tool-helpers/tool-handler.ts +2 -2
- package/src/modules/tool-helpers/tool.contract.ts +2 -2
- package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +42 -3
- package/src/modules/workflow/__tests__/fake-file-lock-db.ts +13 -2
- package/src/modules/workflow/__tests__/workflow.routes.lock-path.test.ts +168 -1
- package/src/modules/workflow/__tests__/workflow.service.delete-branch.test.ts +102 -6
- package/src/modules/workflow/file-lock.service.ts +79 -18
- package/src/modules/workflow/git/__tests__/git.service.changedPathsMemo.test.ts +175 -0
- package/src/modules/workflow/git/__tests__/git.service.readFileAtRef.test.ts +42 -0
- package/src/modules/workflow/git/__tests__/git.service.worktrees.test.ts +284 -0
- package/src/modules/workflow/git/git.service.ts +207 -22
- package/src/modules/workflow/index.ts +7 -0
- package/src/modules/workflow/pending-commits.service.ts +4 -23
- package/src/modules/workflow/workflow-hooks.ts +1 -1
- package/src/modules/workflow/workflow.routes.ts +24 -1
- package/src/modules/workflow/workflow.service.ts +3 -2
- package/src/modules/workspace/__tests__/agent-downloads.test.ts +2 -2
- package/src/modules/workspace/__tests__/bounded-matcher.test.ts +213 -0
- package/src/modules/workspace/__tests__/git-internals.security.test.ts +22 -7
- package/src/modules/workspace/__tests__/kb-repository.test.ts +481 -0
- package/src/modules/workspace/__tests__/rest-tool-arguments.test.ts +14 -0
- package/src/modules/workspace/__tests__/routine-write-policy.test.ts +0 -11
- package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.routes.folder-zip-access.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.routes.folders.test.ts +4 -3
- package/src/modules/workspace/__tests__/workspace.service.any-workspace-credentials.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.service.ensure-remotes-fetched.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.service.forget-clone-races.test.ts +12 -5
- package/src/modules/workspace/__tests__/workspace.service.list-cloned.test.ts +6 -6
- package/src/modules/workspace/__tests__/workspace.service.move-never-overwrites.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.replaced-repository.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.test.ts +24 -23
- package/src/modules/workspace/__tests__/workspace.service.unknown-branch.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.worktrees.test.ts +620 -0
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +15 -1
- package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +71 -5
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +174 -309
- package/src/modules/workspace/agent-access.gate.ts +2 -2
- package/src/modules/workspace/bounded-matcher.ts +328 -0
- package/src/modules/workspace/fetch-instant.ts +13 -0
- package/src/modules/workspace/index.ts +26 -0
- package/src/modules/workspace/kb-repository.contract.ts +124 -0
- package/src/modules/workspace/kb-repository.ts +844 -0
- package/src/modules/workspace/pattern-matcher.contract.ts +69 -0
- package/src/modules/workspace/routine-write-policy.ts +0 -15
- package/src/modules/workspace/set-aside-clone.ts +140 -0
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.degraded.test.ts +3 -2
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +12 -10
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.worktrees.test.ts +613 -0
- package/src/modules/workspace/startup/kb-startup-runner.ts +422 -29
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +4 -3
- package/src/modules/workspace/workspace.service.ts +247 -169
- package/src/modules/workspace/workspace.tools.ts +299 -385
- package/src/shared/workspace-id.ts +24 -0
- package/src/test-setup.ts +5 -0
|
@@ -4,6 +4,7 @@ import express from 'express';
|
|
|
4
4
|
import { describe, it, expect, afterEach, vi } from 'vitest';
|
|
5
5
|
|
|
6
6
|
import type { IAccessControl } from '../access-control.interface.js';
|
|
7
|
+
import { AccessControlService } from '../access-control.service.js';
|
|
7
8
|
import type { WorkspaceService } from '../../workspace/workspace.service.js';
|
|
8
9
|
import type { AuthService } from '../../auth/auth.service.js';
|
|
9
10
|
import type { WorkflowService } from '../../workflow/workflow.service.js';
|
|
@@ -31,6 +32,10 @@ async function makeHarness(opts: {
|
|
|
31
32
|
files?: Record<string, string>;
|
|
32
33
|
roles?: string[];
|
|
33
34
|
groups?: string[];
|
|
35
|
+
/** Whether the caller is an admin, who is offered every group. Defaults to true. */
|
|
36
|
+
admin?: boolean;
|
|
37
|
+
/** The groups the caller is a member of — all a non-admin is offered, or may grant to. */
|
|
38
|
+
memberOf?: string[];
|
|
34
39
|
}): Promise<{ server: Server; baseUrl: string; files: Map<string, string> }> {
|
|
35
40
|
const files = new Map<string, string>(Object.entries(opts.files ?? {}));
|
|
36
41
|
|
|
@@ -46,6 +51,12 @@ async function makeHarness(opts: {
|
|
|
46
51
|
groups: opts.groups ?? [],
|
|
47
52
|
people: [],
|
|
48
53
|
})),
|
|
54
|
+
holdsAdminRootWrite: vi.fn(async () => opts.admin ?? true),
|
|
55
|
+
groupsOfUser: vi.fn(async () => opts.memberOf ?? []),
|
|
56
|
+
// The real policy over the two stubs above: who sees which group is the
|
|
57
|
+
// resolver's one answer, not something a route (or this double) decides.
|
|
58
|
+
visibleGroups: (wsId: string, email: string, groups: readonly string[]) =>
|
|
59
|
+
AccessControlService.prototype.visibleGroups.call(accessControl, wsId, email, groups),
|
|
49
60
|
eligibleWriters: vi.fn(async () => ({ roles: [], users: [] })),
|
|
50
61
|
eligibleReaders: vi.fn(async () => ({ restricted: true, roles: [], users: [] })),
|
|
51
62
|
eligibleOwners: vi.fn(async () => ({ roles: [], users: [] })),
|
|
@@ -213,6 +224,61 @@ describe('group principals on the share surface', () => {
|
|
|
213
224
|
expect(body.plugins).toEqual(body.roles);
|
|
214
225
|
});
|
|
215
226
|
|
|
227
|
+
it("suggest offers someone who is not an admin only the groups they are in, never another group's name", async () => {
|
|
228
|
+
h = await makeHarness({ roles: ['Everyone'], groups: ['GTM Team', 'Product'], admin: false, memberOf: ['Product'] });
|
|
229
|
+
const res = await fetch(`${h.baseUrl}/api/workspace/${encodeURIComponent(WS)}/access/suggest?q=`);
|
|
230
|
+
expect(res.status).toBe(200);
|
|
231
|
+
const body = (await res.json()) as { roles: string[]; groups: string[] };
|
|
232
|
+
expect(body.groups).toEqual(['Product']);
|
|
233
|
+
expect(body.roles).toEqual(['Everyone']); // roles are not withheld
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('suggest offers someone in no group, who is not an admin, no groups at all', async () => {
|
|
237
|
+
h = await makeHarness({ groups: ['GTM Team', 'Product'], admin: false });
|
|
238
|
+
const res = await fetch(`${h.baseUrl}/api/workspace/${encodeURIComponent(WS)}/access/suggest?q=`);
|
|
239
|
+
const body = (await res.json()) as { groups: string[] };
|
|
240
|
+
expect(body.groups).toEqual([]);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('a non-admin grants to a group they are in', async () => {
|
|
244
|
+
h = await makeHarness({ groups: ['GTM Team', 'Product'], admin: false, memberOf: ['Product'] });
|
|
245
|
+
const res = await post('grant', {
|
|
246
|
+
path: `${KB}/Sales`,
|
|
247
|
+
kind: 'folder',
|
|
248
|
+
verb: 'read',
|
|
249
|
+
principal: { kind: 'group', group: 'Product' },
|
|
250
|
+
});
|
|
251
|
+
expect(res.status).toBe(200);
|
|
252
|
+
expect(h.files.get(`${KB}/Sales/access.md`)).toContain('- Product');
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('a non-admin granting to a group they are not in is refused exactly like an unknown group', async () => {
|
|
256
|
+
h = await makeHarness({ groups: ['GTM Team', 'Product'], admin: false, memberOf: ['Product'] });
|
|
257
|
+
const res = await post('grant', {
|
|
258
|
+
path: `${KB}/Sales`,
|
|
259
|
+
kind: 'folder',
|
|
260
|
+
verb: 'read',
|
|
261
|
+
principal: { kind: 'group', group: 'GTM Team' },
|
|
262
|
+
});
|
|
263
|
+
// Same status, same body as a group that does not exist — the WHOLE
|
|
264
|
+
// answer, message included, with only the name asked about differing —
|
|
265
|
+
// so the grant route confirms no group name the picker would not have
|
|
266
|
+
// offered.
|
|
267
|
+
const ghost = await post('grant', {
|
|
268
|
+
path: `${KB}/Sales`,
|
|
269
|
+
kind: 'folder',
|
|
270
|
+
verb: 'read',
|
|
271
|
+
principal: { kind: 'group', group: 'Ghost Team' },
|
|
272
|
+
});
|
|
273
|
+
expect(res.status).toBe(404);
|
|
274
|
+
expect(ghost.status).toBe(404);
|
|
275
|
+
const hiddenBody = (await res.json()) as Record<string, unknown>;
|
|
276
|
+
const ghostBody = (await ghost.json()) as Record<string, unknown>;
|
|
277
|
+
expect(hiddenBody).toMatchObject({ kind: 'unknown-group', group: 'GTM Team' });
|
|
278
|
+
expect(JSON.stringify(hiddenBody).replaceAll('GTM Team', 'Ghost Team')).toBe(JSON.stringify(ghostBody));
|
|
279
|
+
expect(h.files.has(`${KB}/Sales/access.md`)).toBe(false);
|
|
280
|
+
});
|
|
281
|
+
|
|
216
282
|
it('revokes with a group principal (name-based, no existence check)', async () => {
|
|
217
283
|
h = await makeHarness({
|
|
218
284
|
groups: ['GTM Team'],
|
|
@@ -55,6 +55,8 @@ async function makeHarness(opts: {
|
|
|
55
55
|
grantSources: vi.fn(async () => ({ read: [{ kind: 'direct' }] })),
|
|
56
56
|
invalidate: vi.fn(),
|
|
57
57
|
kbPrincipals: vi.fn(async () => ({ roles: [], groups: [], people: opts.kbPeople ?? [] })),
|
|
58
|
+
// No groups in this source, so the answer is the empty list the service gives for one.
|
|
59
|
+
visibleGroups: vi.fn(async (_w: string, _e: string, groups: readonly string[]) => [...groups]),
|
|
58
60
|
eligibleWriters: vi.fn(async () => ({ roles: [], users: granted })),
|
|
59
61
|
eligibleReaders: vi.fn(async () => ({ restricted: true, roles: [], users: granted })),
|
|
60
62
|
eligibleOwners: vi.fn(async () => ({ roles: [], users: [] })),
|
|
@@ -234,6 +234,28 @@ export interface IAccessControl {
|
|
|
234
234
|
*/
|
|
235
235
|
canReadAsEveryoneBatch(workspaceId: string, relativePaths: string[]): Promise<Map<string, boolean>>;
|
|
236
236
|
|
|
237
|
+
/**
|
|
238
|
+
* The display names of the groups `userEmail` is a member of, in the
|
|
239
|
+
* active group source (`groups.yaml`, or the IdP-synced file), spelled as
|
|
240
|
+
* `kbPrincipals` spells them. Direct membership only: a role that lists a
|
|
241
|
+
* group does not make its holders members of it. Empty when the person is
|
|
242
|
+
* in no group.
|
|
243
|
+
*/
|
|
244
|
+
groupsOfUser(workspaceId: string, userEmail: string): Promise<string[]>;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Which of `groups` (names from the active group source) `userEmail` may
|
|
248
|
+
* SEE: every one for an admin, who manages them all, and only the groups
|
|
249
|
+
* they are a member of ({@link groupsOfUser}) for anyone else. A group's
|
|
250
|
+
* name is information — on a deployment that gives each client, author or
|
|
251
|
+
* customer a group of its own, the list of groups is the client list — so
|
|
252
|
+
* this ONE answer is what the Library's Groups tab lists, what the share
|
|
253
|
+
* dialog offers as a grantee, and what a grant may name; a group outside it
|
|
254
|
+
* is treated as one that does not exist. Order and spelling of `groups` are
|
|
255
|
+
* kept.
|
|
256
|
+
*/
|
|
257
|
+
visibleGroups(workspaceId: string, userEmail: string, groups: readonly string[]): Promise<string[]>;
|
|
258
|
+
|
|
237
259
|
/**
|
|
238
260
|
* Batched canWrite for PR diffs and commit-time gating. Returns a map keyed
|
|
239
261
|
* by the input paths, with `true` / `false` for each. Reuses one config
|