Skip to content

Commit 36b2889

Browse files
test(plugin-security): retire the declared-permission seeder suites (#15204 stage 6b-2, T1) (#22897)
Part of #15204 Clause-②: no **T1 of stage 6b-2**: tests only. It deletes the suites that pin the declared-permission seeder, drift, the `managed_by` normalizer and the seed-refusal diagnostics, and trims the cases in shared suites that pin them. It is split off the 6b-2 code PR (#22900) so that PR falls under 3,000 changed lines (the ruling: tests land inside or before their code PR). No production file changes. The modules these suites pinned are deleted by #22900. **Landing, as sequenced by the seat:** T1, T2 and the 6b-2 code PR (#22900) stay drafts until #22900's own gates clear (the #22865 pickers and objectui PR-4), then land back to back, **T1 → T2 → #22900**. That way the publish materializer and the seeders are never live on `main` with their pins gone. 6b-2a (#22899) is independent and goes to the maintainer separately. ## Deleted (whole files) - `bootstrap-declared-permissions.test.ts` - `walled-platform-bucket-diagnostic.test.ts` - `permission-set-drift.test.ts` - `bootstrap-seed-round-trips.test.ts` - `declared-permission-reload-projection.test.ts` - `normalize-managed-by.test.ts` ## Trimmed (only the cases that pin a deleted module) - `per-organization-catalog.test.ts`: case 6 (resolver bleed) is kept. - `permission-set-name-collision.test.ts`: the shared-derivation describe is kept. - `read-fault-distinguishability.test.ts`: reading 1 goes. - `engine-find-bare-array.pin.test.ts`: blocks 3 and 6 go. - `seed-name-lookup-degradation-audible.test.ts`: the lit control reports through `seed-refusal-sink` directly, not through the retiring diagnostics module. - `builtin-capabilities.boot.test.ts`: the platform-name-refusal constant goes. - `objects/rbac-objects.test.ts`: the `drift_status` pin goes (the field leaves in 6b-2). ## Re-pinned here The #11451 fence (a caller that passes no predicate emits only the `where` key `name`) rode `bootstrap-seed-round-trips.test.ts`, but the behaviour it pins outlives the seeder: `permission-set-projection.ts`' overlay pass calls `buildExistingByName` with no predicate. It is now pinned at the function in `seed-name-lookup-degradation-audible.test.ts`, on both the batched read and the per-item degradation read, with a predicate-carrying positive control. Ablation: making both reads spread `{ managed_by: undefined }` turned both fences red ("expected [ 'name', 'managed_by' ] to deeply equal [ 'name' ]"), the control stayed green, and restoring the file (same sha) brought 8/8 back. ## Gate ledgers The double-contract ledgers (`engine-double-contract.{baseline,pinned}.json`, `objectql-double-limit.baseline.json`) drop the deleted suites' entries. ## Size 16 files, +86 / −2,749 (2,835 changed lines). ## Verification On this branch: `check:engine-double-contract` and `check:objectql-double-limit` green. The 7 trimmed suites: 7 files, 60 passed; with the new fence, `seed-name-lookup-degradation-audible` is 8 passed. `check:where-matcher` green. plugin-security typecheck green. `check:adr-0087-registration`, `check:changeset-no-major`, `check:cli-command-ids`, `check:nul-bytes` green. **Not covered after this PR:** no retained test imports `bootstrap-declared-permissions`, `permission-set-drift`, `normalize-managed-by` or `seed-refusal-diagnostics`. Only the boot-level suites exercise them in passing. They run unpinned until #22900 removes them, which is why the seat lands this PR directly before #22900. **Merge note:** this PR and #22899 delete adjacent entries in `scripts/engine-double-contract.baseline.json` and `scripts/objectql-double-limit.baseline.json`, so whichever lands second meets a textual conflict there. The resolution is to drop both entries. Test-only: `skip-changeset`. --- 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 55828c5 commit 36b2889

16 files changed

Lines changed: 86 additions & 2749 deletions

‎packages/plugins/plugin-security/src/bootstrap-declared-permissions.test.ts‎

Lines changed: 0 additions & 655 deletions
This file was deleted.

‎packages/plugins/plugin-security/src/bootstrap-seed-round-trips.test.ts‎

Lines changed: 0 additions & 368 deletions
This file was deleted.

‎packages/plugins/plugin-security/src/builtin-capabilities.boot.test.ts‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ import { SysUser, SysAccount, SysMember, SysOrganization } from '@objectstack/pl
4444
import { SecurityPlugin } from './security-plugin.js';
4545
import { securityObjects, SECURITY_PLUGIN_ID } from './manifest.js';
4646
import { defaultPermissionSets } from './objects/default-permission-sets.js';
47-
import { CAPABILITY_PLATFORM_NAME_REFUSED } from './seed-refusal-diagnostics.js';
4847

4948
const SYS = { isSystem: true } as const;
5049
const POSTURE_ENV = 'OS_TENANCY_POSTURE';
@@ -255,7 +254,6 @@ describe.each(SCENARIOS)('a $posture boot, the stack capability $declared', ({ p
255254

256255
it('no capability seeder refuses or reports the platform’s own declarations', () => {
257256
for (const booted of [fresh, reseeded]) {
258-
expect(booted.warnings.filter((w) => w.includes(CAPABILITY_PLATFORM_NAME_REFUSED))).toEqual([]);
259257
expect(booted.warnings.filter((w) => w.includes('capabilit'))).toEqual([]);
260258
}
261259
});

‎packages/plugins/plugin-security/src/declared-permission-reload-projection.test.ts‎

Lines changed: 0 additions & 160 deletions
This file was deleted.

‎packages/plugins/plugin-security/src/engine-find-bare-array.pin.test.ts‎

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@
1717
* Every seam answered `[object Array]`, with no own `records` key, on a
1818
* populated page and an empty one alike.
1919
*
20-
* ⚠️ These are six pins, not one pin repeated. A single reading of "the engine
20+
* ⚠️ These are four pins, not one pin repeated. A single reading of "the engine
2121
* returns an array" would say nothing about whether a given seam is even
22-
* reachable — six of them sit behind a trigger (a truncated page, a refused
23-
* bulk write, a publish-materializer call path), and a seam nothing reaches is
22+
* reachable — some of them sit behind a trigger (a truncated page, a refused
23+
* bulk write), and a seam nothing reaches is
2424
* precisely how a dead limb survives review. So each case DRIVES its own block
2525
* through the real function and asserts the answer that block produced, and
2626
* {@link assertBareArrayPage} then reads back the value the engine handed it.
2727
*
28-
* The seventh seam, `security-plugin.ts`'s `sys_permission_set` loader, is
29-
* gone: the plugin takes a set's body from the security catalog
28+
* Blocks 3 and 6 (the declared-permission seeder's per-name read and the
29+
* `managed_by` normalizer's scan) retired with their modules (ADR-0131 D3:
30+
* the boot writes no catalog row). The seventh seam, `security-plugin.ts`'s
31+
* `sys_permission_set` loader, is gone too: the plugin takes a set's body from the security catalog
3032
* (ADR-0131 D3/D4) and reads no `sys_permission_set` row, so it has no
3133
* engine page to pin. Its fault direction (a read that did not answer
3234
* propagates, and `PermissionEvaluator`'s #2565 warn fires) is pinned on the
@@ -51,10 +53,8 @@ import {
5153
} from '@objectstack/metadata-core';
5254

5355
import { buildExistingByName } from './seed-name-lookup.js';
54-
import { upsertPackagePermissionSet } from './bootstrap-declared-permissions.js';
5556
import { reconcileOrgAdminGrant } from './auto-org-admin-grant.js';
5657
import { claimSeedOwnership } from './claim-seed-ownership.js';
57-
import { normalizeManagedByVocab } from './normalize-managed-by.js';
5858

5959
const SYS = { context: { isSystem: true } } as any;
6060
const ORG = 'org_a';
@@ -243,29 +243,6 @@ describe('[#15598] block 2 — seed-name-lookup perItemIndex (the DEGRADATION re
243243
}, 120_000);
244244
});
245245

246-
describe('[#15598] block 3 — bootstrap-declared-permissions defaultLookup', () => {
247-
it('answers from one bare array on the publish-materializer path', async () => {
248-
const engine = await boot();
249-
const seen: Seen = [];
250-
251-
// No `existingByName` — the ADR-0086 P2 publish materializer path, which is
252-
// the only caller that reaches `defaultLookup`'s own read.
253-
const outcome = await upsertPackagePermissionSet(
254-
observed(engine, seen),
255-
{ name: 'ps_published', label: 'Published', objects: {} } as any,
256-
'com.acme.crm',
257-
undefined,
258-
{} as any,
259-
);
260-
261-
assertBareArrayPage(seen, 'defaultLookup');
262-
// `unreadable` is what a seam that cannot read its page reports, and it is
263-
// one-hot with `seeded` — so this pair is the discriminator.
264-
expect(outcome.unreadable).toBe(0);
265-
expect(outcome.seeded).toBe(1);
266-
}, 120_000);
267-
});
268-
269246
describe('[#15598] block 4 — auto-org-admin-grant tryFind', () => {
270247
it('reads the set and the membership out of bare arrays, and grants on them', async () => {
271248
const engine = await boot();
@@ -321,19 +298,3 @@ describe('[#15598] block 5 — claim-seed-ownership idsFrom (the PAGING fallback
321298
expect(rows[0].owner_id).toBe(ADMIN);
322299
}, 120_000);
323300
});
324-
325-
describe('[#15598] block 6 — normalize-managed-by tryFind', () => {
326-
it('reads the legacy rows out of one bare array and rewrites them', async () => {
327-
const engine = await boot();
328-
await (engine as any).insert('sys_position', { name: 'pos_legacy', label: 'Legacy', managed_by: 'system' }, SYS);
329-
const seen: Seen = [];
330-
331-
const counts = await normalizeManagedByVocab(observed(engine, seen), {});
332-
333-
assertBareArrayPage(seen, 'normalize-managed-by tryFind');
334-
// The rewrite happened, which it cannot if the scan read nothing.
335-
expect(counts.positions).toBe(1);
336-
const rows = await (engine as any).find('sys_position', { where: { name: 'pos_legacy' } }, SYS);
337-
expect(rows[0].managed_by).toBe('platform');
338-
}, 120_000);
339-
});

‎packages/plugins/plugin-security/src/normalize-managed-by.test.ts‎

Lines changed: 0 additions & 77 deletions
This file was deleted.

‎packages/plugins/plugin-security/src/objects/rbac-objects.test.ts‎

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -208,20 +208,6 @@ describe('RBAC object canonical names + row actions', () => {
208208
]);
209209
});
210210

211-
it('[field report — rc→GA declared≠enforced surfacing] SysPermissionSet.drift_status is a select naming the two detected causes, and appears in the "Needs Attention" list view', () => {
212-
const f: any = (SysPermissionSet.fields as any).drift_status;
213-
expect(f, 'drift_status field exists').toBeDefined();
214-
expect(f.type).toBe('select');
215-
expect(f.readonly).toBe(true);
216-
const opts = (f.options ?? []).map((o: any) => o.value).sort();
217-
expect(opts).toEqual(['other', 'overlay_shadow', 'provenance_skip']);
218-
219-
const views: any = SysPermissionSet.listViews;
220-
expect(views.drifted, 'drifted list view exists').toBeDefined();
221-
expect(views.drifted.columns).toContain('drift_status');
222-
expect(views.all_permsets.columns).toContain('drift_status');
223-
});
224-
225211
it('[A4 #2920] SysPermissionSet.managed_by is a select on the unified platform/package/admin vocab', () => {
226212
const f: any = (SysPermissionSet.fields as any).managed_by;
227213
expect(f, 'managed_by field exists').toBeDefined();

0 commit comments

Comments
 (0)