Skip to content

Commit 9d55c05

Browse files
committed
test(plugin-security): the uninstall-cleanup suite hands the sweep D's declared names shape
D (#22900) landed the uninstall cleanup's declared names as `UninstallDeclared` ({ permission: string[] }), not the bare name array the stage-8 branch was built against. The suite now passes that shape and drops its signature cast; D's two named-grant pins are restated over S8-T's fixture so each holds whether the sweep also reaches the package's catalog rows (main) or reaches its sets by the declared names alone (after C3 stage 8). The runner suite's comment attributes `declared` to the names D captures. Claude-Session: https://claude.ai/code/session_01ADzJtzYTLUfgrRZHxkagkX Co-Authored-By: Claude <noreply@anthropic.com>
1 parent a805619 commit 9d55c05

2 files changed

Lines changed: 22 additions & 22 deletions

File tree

‎packages/metadata-protocol/src/protocol.uninstall-cleanups-runner.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ describe('#21490: runUninstallCleanups — the uninstall-cleanup registry\'s one
9999

100100
const res = await protocol.deletePackage(request);
101101

102-
// Its own request — plus, since C3 stage 8, the catalog items the package
103-
// declared (`declared`), read before its withdrawal.
102+
// Its own request — plus, when the package declared permission sets, their
103+
// names (`declared`, ADR-0131 D4), read before its withdrawal.
104104
expect(runner.mock.calls).toEqual([[expect.objectContaining(request)]]);
105105
expect(res.cleanups).toEqual(await runner.mock.results[0]!.value);
106106
expect(res.cleanups).toEqual([{ name: 'security.package-permissions', success: true, removed: 4 }]);

‎packages/plugins/plugin-security/src/cleanup-package-permissions.test.ts‎

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,15 @@
33
// (ADR-0086 D3 provenance consumed at last; ADR-0090 D5 "no ghost grants").
44

55
import { describe, it, expect } from 'vitest';
6-
import { cleanupPackagePermissions as cleanup } from './cleanup-package-permissions';
6+
import { cleanupPackagePermissions } from './cleanup-package-permissions';
77

88
/**
9-
* The sweep, with the declared-names argument C3 stage 8 adds. Spelled through
10-
* this signature so the suite compiles against the module before and after
11-
* that stage: before it, the sweep finds the package's sets by its catalog
12-
* rows and ignores the names; after it, it finds them by the names.
9+
* The permission-set names the uninstalling door read off the package before
10+
* its withdrawal (`UninstallDeclared`, ADR-0131 D4). Handed to the sweep, they
11+
* revoke the same grants whether it also finds the package's sets by their
12+
* catalog rows (before C3 stage 8) or by these names alone (after it).
1313
*/
14-
const cleanupPackagePermissions = cleanup as (
15-
ql: any,
16-
packageId: string,
17-
logger?: Parameters<typeof cleanup>[2],
18-
declaredSetNames?: readonly string[],
19-
) => ReturnType<typeof cleanup>;
20-
21-
/** The permission-set names the uninstalled package declared (read off it before its withdrawal). */
22-
const DECLARED = ['crm_readonly', 'crm_admin'];
14+
const DECLARED = { permission: ['crm_readonly', 'crm_admin'] };
2315

2416
/**
2517
* A store holding both shapes a grant has carried: every grant names its set
@@ -188,17 +180,25 @@ describe('[ADR-0131 D4, ADR-0090 D5] the grants naming a set the package declare
188180

189181
it('revokes every user grant naming a declared set, and only those', async () => {
190182
const ql = withNamedGrants();
191-
const out = await cleanupPackagePermissions(ql, 'com.example.crm', undefined, { permission: ['crm_catalog_user'] });
183+
const out = await cleanupPackagePermissions(ql, 'com.example.crm', undefined, {
184+
permission: [...DECLARED.permission, 'crm_catalog_user'],
185+
});
192186

193-
expect(out.userGrants).toBe(3); // the legacy row's grant (ups_1) and the two naming the declared set
194-
expect(ql.tables.sys_user_permission_set.map((r: any) => r.id)).toEqual(['ups_env', 'ups_named_other']);
187+
// The two grants naming the package's row-backed sets and the two naming
188+
// its registry-only set.
189+
expect(out.userGrants).toBe(4);
190+
expect(ql.tables.sys_user_permission_set.map((r: any) => r.id)).toEqual(['ups_env', 'ups_other', 'ups_named_other']);
195191
});
196192

197-
it('control — handed no names, a grant naming a catalog set survives: the cleanup is as it was', async () => {
193+
it('control — handed no names, a grant naming a registry-only set survives', async () => {
198194
const ql = withNamedGrants();
199195
const out = await cleanupPackagePermissions(ql, 'com.example.crm');
200196

201-
expect(out).toEqual({ sets: 2, positionBindings: 2, userGrants: 1, suggestions: 2, refused: 0 });
202-
expect(ql.tables.sys_user_permission_set.map((r: any) => r.id)).toEqual(['ups_env', 'ups_named_1', 'ups_named_2', 'ups_named_other']);
197+
expect(out).toMatchObject({ suggestions: 2, refused: 0 });
198+
// Whatever the row legs reach while the catalog rows still exist, no grant
199+
// naming a set the sweep was not handed is revoked.
200+
expect(ql.tables.sys_user_permission_set.map((r: any) => r.id)).toEqual(
201+
expect.arrayContaining(['ups_env', 'ups_other', 'ups_named_1', 'ups_named_2', 'ups_named_other']),
202+
);
203203
});
204204
});

0 commit comments

Comments
 (0)