@@ -6,7 +6,6 @@ import { fileURLToPath } from 'node:url';
66
77import { describe , it , expect , vi } from 'vitest' ;
88import { bootstrapDeclaredCapabilities } from './bootstrap-declared-capabilities.js' ;
9- import { bootstrapSystemCapabilities } from './bootstrap-system-capabilities.js' ;
109import { CAPABILITY_NAME_COLLISION } from './capability-name-collision.js' ;
1110import {
1211 CAPABILITY_DECLARATION_UNOWNED ,
@@ -40,10 +39,9 @@ function makeQl(declared: any[] = []) {
4039 // matches null-or-missing through mingo (its reference matcher, retired by
4140 // commit `8fec76a2b`, used `value == condition`), and MongoDB matches
4241 // null-or-missing — none of them
43- // is strict equality against an ABSENT key. `bootstrapSystemCapabilities`
44- // (called by several cases below) scopes its curated lookup with
45- // `organization_id: null`, which strict `===` would make unsatisfiable
46- // here while it works in production.
42+ // is strict equality against an ABSENT key; strict `===` would make an
43+ // `organization_id: null` lookup unsatisfiable here while it works in
44+ // production.
4745 // [#11096] `$in` is supported because the real engine supports it — the
4846 // seeder now issues ONE batched `{ name: { $in: [...] } }` existence read
4947 // for the whole declaration. ⛔ A double that did not match it would
@@ -64,8 +62,7 @@ function makeQl(declared: any[] = []) {
6462 ) ;
6563 // [commit e1d773eb7] `limit` is HONOURED, and a paged read is ordered by `id`
6664 // ascending (#4363's pagination tie-breaker). Both are properties of the
67- // shipped drivers, measured for the sibling double in
68- // `bootstrap-system-capabilities.test.ts`; this one ignored `limit`
65+ // shipped drivers; this double once ignored `limit`
6966 // entirely, which made the whole class of page-cap defect INEXPRESSIBLE
7067 // here — including the cap commit e1d773eb7 fixed, whose consequence lands on THIS seeder.
7168 if ( q ?. limit === undefined ) return matched ;
@@ -161,10 +158,10 @@ describe('bootstrapDeclaredCapabilities (ADR-0066 D1 package declaration)', () =
161158 } ) ;
162159
163160 it ( 'CLAIMS a derived-from-systemPermissions platform placeholder' , async ( ) => {
164- // Simulate the back-compat path: bootstrapSystemCapabilities derived a
165- // placeholder from a permission set's systemPermissions .
161+ // A platform placeholder row, as the retired derive-from-systemPermissions
162+ // seeder left one on an existing database .
166163 const ql = makeQl ( [ { name : 'export_data' , label : 'Export Data' , description : 'Nice.' , scope : 'org' , _packageId : 'com.acme.reports' } ] ) ;
167- await bootstrapSystemCapabilities ( ql , [ { systemPermissions : [ ' export_data' ] } ] ) ;
164+ ql . rows . push ( { id : 'cap_derived' , name : 'export_data' , label : 'Export Data' , description : 'Capability export_data.' , managed_by : 'platform' } ) ;
168165 const derived = ql . rows . find ( ( r ) => r . name === 'export_data' ) ;
169166 expect ( derived . managed_by ) . toBe ( 'platform' ) ;
170167 // Now the explicit declaration claims it.
@@ -175,19 +172,6 @@ describe('bootstrapDeclaredCapabilities (ADR-0066 D1 package declaration)', () =
175172 expect ( ql . rows . filter ( ( r ) => r . name === 'export_data' ) ) . toHaveLength ( 1 ) ;
176173 } ) ;
177174
178- it ( 'declared name suppresses the implicit derived placeholder (no clobber)' , async ( ) => {
179- // Full boot order: declared first, then system with materializedNames.
180- const ql = makeQl ( [ { name : 'export_data' , label : 'Export Data' , scope : 'org' , _packageId : 'com.acme.reports' } ] ) ;
181- const cap = await bootstrapDeclaredCapabilities ( ql , null ) ;
182- await bootstrapSystemCapabilities ( ql , [ { systemPermissions : [ 'export_data' ] } ] , {
183- materializedCapabilityNames : cap . materializedNames ,
184- } ) ;
185- const row = ql . rows . find ( ( r ) => r . name === 'export_data' ) ;
186- // The package row is untouched — no humanized placeholder overwrote it.
187- expect ( row ) . toMatchObject ( { managed_by : 'package' , label : 'Export Data' , scope : 'org' } ) ;
188- expect ( ql . rows . filter ( ( r ) => r . name === 'export_data' ) ) . toHaveLength ( 1 ) ;
189- } ) ;
190-
191175 it ( 'returns an empty outcome when nothing is declared' , async ( ) => {
192176 const ql = makeQl ( [ ] ) ;
193177 const out = await bootstrapDeclaredCapabilities ( ql , null ) ;
@@ -196,138 +180,11 @@ describe('bootstrapDeclaredCapabilities (ADR-0066 D1 package declaration)', () =
196180} ) ;
197181
198182// ───────────────────────────────────────────────────────────────────────────
199- // [#4967 Part 1] A REFUSED declaration must not suppress the back-compat
200- // derivation. `materializedNames` reports the names this pass CONFIRMED have a
201- // row — the three refusal paths land on different sides of that line, for
202- // different reasons, so each gets its own pin (and, where the direction is not
203- // obvious, the reverse case that shows what the other answer would cost).
183+ // [#4967 Part 1] `materializedNames` reports the names this pass CONFIRMED have
184+ // a row — the refusal paths land on different sides of that line. The cases
185+ // that paired it with the back-compat derivation went with that seeder.
204186// ───────────────────────────────────────────────────────────────────────────
205187describe ( 'refused declarations vs. the derived placeholder (#4967 Part 1)' , ( ) => {
206- const OPS_SETS = [ { name : 'showcase_ops' , systemPermissions : [ 'setup.access' , 'showcase.export_data' ] } ] ;
207-
208- it ( 'NO OWNING PACKAGE + no row: falls through, so the derivation materializes it' , async ( ) => {
209- // The showcase repro: `showcase.export_data` declared without a resolvable
210- // owner, granted by `showcase_ops`.
211- const ql = makeQl ( [ { name : 'showcase.export_data' , label : 'Export Data' } ] ) ;
212- const out = await bootstrapDeclaredCapabilities ( ql , null , { permissionSets : OPS_SETS } ) ;
213-
214- // The declaration is refused — no package row, and (the fix) the name is
215- // NOT reported as materialized.
216- expect ( out . seeded ) . toBe ( 0 ) ;
217- expect ( out . skippedUnowned ) . toBe ( 1 ) ;
218- expect ( out . materializedNames ) . toEqual ( [ ] ) ;
219-
220- // Second pass — the capability now exists, as the back-compat placeholder
221- // it would have had if the declaration had never been written.
222- await bootstrapSystemCapabilities ( ql , OPS_SETS , { materializedCapabilityNames : out . materializedNames } ) ;
223- expect ( ql . rows . find ( ( r ) => r . name === 'showcase.export_data' ) ) . toMatchObject ( {
224- name : 'showcase.export_data' , managed_by : 'platform' , active : true ,
225- } ) ;
226- // …and it RESOLVES by name, which is what the granting permission set needs
227- // from the registry (Setup listing, provenance, ADR-0066 ⑨ lint sources).
228- expect ( await ql . find ( 'sys_capability' , { where : { name : 'showcase.export_data' } } ) ) . toHaveLength ( 1 ) ;
229- } ) ;
230-
231- it ( 'REVERSE: the pre-#4967 list (every declared name) leaves the capability in no row at all' , async ( ) => {
232- // Same fixture, same second pass — only the skip list is the old one, which
233- // reported a name the first pass refused to write. Nothing derives it and
234- // nothing declared it: the hole.
235- const ql = makeQl ( [ { name : 'showcase.export_data' , label : 'Export Data' } ] ) ;
236- await bootstrapDeclaredCapabilities ( ql , null , { permissionSets : OPS_SETS } ) ;
237- await bootstrapSystemCapabilities ( ql , OPS_SETS , {
238- materializedCapabilityNames : [ 'showcase.export_data' ] , // ← the old `declaredNames`
239- } ) ;
240- expect ( ql . rows . find ( ( r ) => r . name === 'showcase.export_data' ) ) . toBeUndefined ( ) ;
241- } ) ;
242-
243- it ( 'is stable across boots: the refusal re-derives nothing and duplicates nothing' , async ( ) => {
244- const ql = makeQl ( [ { name : 'showcase.export_data' , label : 'Export Data' } ] ) ;
245- for ( let boot = 0 ; boot < 2 ; boot += 1 ) {
246- const out = await bootstrapDeclaredCapabilities ( ql , null , { permissionSets : OPS_SETS } ) ;
247- await bootstrapSystemCapabilities ( ql , OPS_SETS , { materializedCapabilityNames : out . materializedNames } ) ;
248- }
249- expect ( ql . rows . filter ( ( r ) => r . name === 'showcase.export_data' ) ) . toHaveLength ( 1 ) ;
250- // Boot 2 finds the placeholder, so the refusal now reports the name — the
251- // row exists and must not be re-derived over.
252- const out2 = await bootstrapDeclaredCapabilities ( ql , null , { permissionSets : OPS_SETS } ) ;
253- expect ( out2 . skippedUnowned ) . toBe ( 1 ) ;
254- expect ( out2 . materializedNames ) . toEqual ( [ 'showcase.export_data' ] ) ;
255- } ) ;
256-
257- it ( 'NO OWNING PACKAGE + an admin row: still suppresses, so the placeholder cannot clobber it' , async ( ) => {
258- const ql = makeQl ( [ { name : 'showcase.export_data' , label : 'Declared Label' } ] ) ;
259- ql . rows . push ( { id : 'cap_admin' , name : 'showcase.export_data' , label : 'Admin Made' , description : 'Admin wrote this.' , managed_by : 'admin' } ) ;
260- const out = await bootstrapDeclaredCapabilities ( ql , null , { permissionSets : OPS_SETS } ) ;
261- expect ( out . skippedUnowned ) . toBe ( 1 ) ;
262- expect ( out . materializedNames ) . toEqual ( [ 'showcase.export_data' ] ) ;
263- await bootstrapSystemCapabilities ( ql , OPS_SETS , { materializedCapabilityNames : out . materializedNames } ) ;
264- expect ( ql . rows . find ( ( r ) => r . name === 'showcase.export_data' ) ) . toMatchObject ( {
265- label : 'Admin Made' , description : 'Admin wrote this.' , managed_by : 'admin' ,
266- } ) ;
267- } ) ;
268-
269- it ( 'SECOND LAYER (#5876): dropping that name from the list no longer overwrites the admin row' , async ( ) => {
270- // This pin was written by #5875 (as `REVERSE: dropping that name from the
271- // list lets the derivation overwrite the admin row`) to justify why the
272- // unowned path checks for an EXISTING row instead of always falling
273- // through: back then the derived defaults refreshed label/description on
274- // ANY row they found, so the skip list was the ONLY thing standing between
275- // an admin-authored row and a humanized placeholder. That fact is fixed —
276- // #5876 guards the derived reconcile by `managed_by`, so the write site
277- // now refuses the clobber even when the call site forgets to suppress it.
278- //
279- // The suppression list keeps its job (it is what states the boot-order
280- // contract, and it stops the derivation doing work on names another pass
281- // owns), but it is no longer load-bearing for THIS shape — which is the
282- // point of a second layer.
283- const ql = makeQl ( [ ] ) ;
284- ql . rows . push ( { id : 'cap_admin' , name : 'showcase.export_data' , label : 'Admin Made' , description : 'Admin wrote this.' , managed_by : 'admin' } ) ;
285- await bootstrapSystemCapabilities ( ql , OPS_SETS , { materializedCapabilityNames : [ ] } ) ;
286- expect ( ql . rows . find ( ( r ) => r . name === 'showcase.export_data' ) ) . toMatchObject ( {
287- label : 'Admin Made' , description : 'Admin wrote this.' , managed_by : 'admin' ,
288- } ) ;
289- } ) ;
290-
291- it ( 'DISCRIMINATION (#5876): with the name dropped, a PLATFORM placeholder is still refreshed' , async ( ) => {
292- // The guard above must not read as "the derivation stopped writing". Same
293- // fixture, same empty skip list, provenance flipped to the one the derived
294- // pass owns → the reconcile happens exactly as it always did.
295- const ql = makeQl ( [ ] ) ;
296- ql . rows . push ( { id : 'cap_derived' , name : 'showcase.export_data' , label : 'Stale Placeholder' , description : 'Stale.' , managed_by : 'platform' } ) ;
297- await bootstrapSystemCapabilities ( ql , OPS_SETS , { materializedCapabilityNames : [ ] } ) ;
298- expect ( ql . rows . find ( ( r ) => r . name === 'showcase.export_data' ) ) . toMatchObject ( {
299- label : 'Showcase Export Data' , description : 'Capability showcase.export_data.' , managed_by : 'platform' ,
300- } ) ;
301- } ) ;
302-
303- it ( 'FOREIGN owner: suppresses, because the other package authored that row' , async ( ) => {
304- const sets = [ { name : 'ops' , systemPermissions : [ 'shared_cap' ] } ] ;
305- const ql = makeQl ( [ { name : 'shared_cap' , label : 'Mine' , _packageId : 'com.b' } ] ) ;
306- ql . rows . push ( { id : 'cap_x' , name : 'shared_cap' , label : 'Owner Label' , description : 'Owner wrote this.' , managed_by : 'package' , package_id : 'com.a' } ) ;
307- const out = await bootstrapDeclaredCapabilities ( ql , null , { permissionSets : sets } ) ;
308- expect ( out . skippedForeign ) . toBe ( 1 ) ;
309- expect ( out . materializedNames ) . toEqual ( [ 'shared_cap' ] ) ;
310- await bootstrapSystemCapabilities ( ql , sets , { materializedCapabilityNames : out . materializedNames } ) ;
311- expect ( ql . rows . find ( ( r ) => r . name === 'shared_cap' ) ) . toMatchObject ( {
312- label : 'Owner Label' , description : 'Owner wrote this.' , package_id : 'com.a' ,
313- } ) ;
314- } ) ;
315-
316- it ( 'CURATED platform name: suppresses, and the curated pass seeds the row regardless' , async ( ) => {
317- // A no-op for the skip list (the derived path never reaches a curated name
318- // — it is already in the curated map), but a truthful answer: the row
319- // exists after the second pass either way.
320- const sets = [ { name : 'ops' , systemPermissions : [ 'manage_users' ] } ] ;
321- const ql = makeQl ( [ { name : 'manage_users' , label : 'Evil' , _packageId : 'com.acme.evil' } ] ) ;
322- const out = await bootstrapDeclaredCapabilities ( ql , null , { permissionSets : sets } ) ;
323- expect ( out . skippedPlatform ) . toBe ( 1 ) ;
324- expect ( out . materializedNames ) . toEqual ( [ 'manage_users' ] ) ;
325- await bootstrapSystemCapabilities ( ql , sets , { materializedCapabilityNames : out . materializedNames } ) ;
326- expect ( ql . rows . find ( ( r ) => r . name === 'manage_users' ) ) . toMatchObject ( {
327- label : 'Manage Users' , managed_by : 'platform' , // curated definition, not the package's
328- } ) ;
329- } ) ;
330-
331188 it ( 'materializedNames reconciles with the outcome counters' , async ( ) => {
332189 const ql = makeQl ( [
333190 { name : 'a.new' , _packageId : 'com.a' } , // → seeded
0 commit comments