Skip to content

Commit a38b54f

Browse files
committed
test(plugin-auth): the grant-reader suites write the legacy platform-bucket rows they read
The plugin-auth twins of the plugin-security grant-reader suites read the organization-less `sys_permission_set` rows the platform-admin bootstrap seeded (organization_admin to clone per organization; viewer_readonly to point a legacy id at). Once the boot writes no such row, those reads come back empty. Each suite now models the existing database it describes and writes the rows itself, before the bootstrap, through a plugin-auth copy of the plugin-security testkit: same shape, organization-less, idempotent. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49
1 parent 752c5df commit a38b54f

3 files changed

Lines changed: 67 additions & 0 deletions

File tree

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
/**
4+
* Test scaffolding: the organization-less `sys_permission_set` rows an EARLIER
5+
* release's platform-admin bootstrap seeded for the platform's default sets
6+
* (the "platform bucket").
7+
*
8+
* [C3 stage 6b-2] No boot writes these rows any more (ADR-0131 D3: the sets are
9+
* served from the security catalog, and a grant names its set). A suite that
10+
* models an EXISTING database — a grant written before the name column, whose
11+
* `permission_set_id` points at one of these rows; an organization's copy cloned
12+
* from the bucket — writes them itself, here, in the shape the retired seeder
13+
* wrote: `managed_by: 'platform'`, active, the set's facets as JSON columns.
14+
* Idempotent: a name that already has an organization-less row is left alone.
15+
*
16+
* The plugin-auth copy of plugin-security's testkit of the same name, in the
17+
* same shape: a test-only helper is not exported across the package boundary.
18+
*/
19+
20+
import type { PermissionSet } from '@objectstack/spec/security';
21+
22+
const SYS = { isSystem: true } as const;
23+
24+
/** The legacy row id for a default set — stable, so a fixture can point a grant at it. */
25+
export function legacyBucketRowId(name: string): string {
26+
return `ps_bucket_${name}`;
27+
}
28+
29+
/** Write the legacy platform-bucket row for each set; returns `name → id`. */
30+
export async function seedLegacyPlatformBucket(
31+
engine: { find: (...args: any[]) => Promise<any>; insert: (...args: any[]) => Promise<any> },
32+
sets: readonly PermissionSet[],
33+
): Promise<Record<string, string>> {
34+
const ids: Record<string, string> = {};
35+
for (const ps of sets) {
36+
if (!ps.name) continue;
37+
const existing = ((await engine.find('sys_permission_set', { where: { name: ps.name }, context: SYS })) ?? []) as any[];
38+
const own = existing.find((r) => !r.organization_id);
39+
if (own?.id) {
40+
ids[ps.name] = String(own.id);
41+
continue;
42+
}
43+
const id = legacyBucketRowId(ps.name);
44+
await engine.insert('sys_permission_set', {
45+
id,
46+
name: ps.name,
47+
label: ps.label ?? ps.name,
48+
description: (ps as any).description ?? null,
49+
object_permissions: JSON.stringify(ps.objects ?? {}),
50+
field_permissions: JSON.stringify(ps.fields ?? {}),
51+
system_permissions: JSON.stringify(ps.systemPermissions ?? []),
52+
row_level_security: JSON.stringify(ps.rowLevelSecurity ?? []),
53+
tab_permissions: JSON.stringify(ps.tabPermissions ?? {}),
54+
admin_scope: (ps as any).adminScope ? JSON.stringify((ps as any).adminScope) : null,
55+
active: true,
56+
managed_by: 'platform',
57+
}, { context: SYS });
58+
ids[ps.name] = id;
59+
}
60+
return ids;
61+
}

‎packages/plugins/plugin-auth/src/grant-readers-by-name.golden.test.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import { SysMetadataActivation } from '@objectstack/platform-objects/system';
4040

4141
import { registerLastAdminGuard, type LastAdminGuardEngine } from './last-admin-guard.js';
4242
import { ensureDefaultOrganization } from './ensure-default-organization.js';
43+
import { seedLegacyPlatformBucket } from './__tests__/legacy-catalog-rows.testkit.js';
4344

4445
const SYS = { isSystem: true } as const;
4546
const POSTURE_ENV = 'OS_TENANCY_POSTURE';
@@ -153,6 +154,8 @@ async function standingByReader(posture: Posture): Promise<Record<string, unknow
153154
await user('usr_member', 'member@gra.example', '2025-03-01T00:00:00.000Z');
154155
await user('usr_agent', 'agent@gra.example', '2025-04-01T00:00:00.000Z');
155156

157+
// An existing database: the platform-bucket rows an earlier release seeded.
158+
await seedLegacyPlatformBucket(engine, bootstrapSets);
156159
const boot = await bootstrapPlatformAdmin(engine, bootstrapSets);
157160
expect(boot.adminPromoted).toBe(posture === 'single');
158161
if (walled) {

‎packages/plugins/plugin-auth/src/grant-readers-unnamed-grant.test.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { SysUser, SysAccount, SysMember, SysOrganization } from '@objectstack/pl
3636

3737
import { registerLastAdminGuard, type LastAdminGuardEngine } from './last-admin-guard.js';
3838
import { ensureDefaultOrganization } from './ensure-default-organization.js';
39+
import { seedLegacyPlatformBucket } from './__tests__/legacy-catalog-rows.testkit.js';
3940

4041
const SYS = { context: { isSystem: true } } as any;
4142
const GUARD_PACKAGE = 'test.grant-readers-unnamed';
@@ -122,6 +123,8 @@ async function soleGrantAnchoredAdmin(): Promise<Rig> {
122123
'sys_account', { id: `acc_${id}`, user_id: id, account_id: `${id}@un.example`, provider_id: 'credential' }, SYS,
123124
);
124125
}
126+
// An existing database: the platform-bucket rows an earlier release seeded.
127+
await seedLegacyPlatformBucket(engine, (manifest.permissions ?? []) as any[]);
125128
const boot = await bootstrapPlatformAdmin(engine, (manifest.permissions ?? []) as any[]);
126129
expect(boot).toMatchObject({ adminPromoted: true });
127130
return { engine };

0 commit comments

Comments
 (0)