@consiliency/agent-board-schema 1.23.0 → 1.25.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.
Files changed (32) hide show
  1. package/README.md +75 -1
  2. package/fixtures/already-applied.json +12 -0
  3. package/migrations/20260905000100_agent_board_consent_gating_reconcile.sql +151 -0
  4. package/migrations/20260906000100_agent_board_enroll_resumption.sql +749 -0
  5. package/migrations/20260907000100_agent_board_signed_authority_provenance.sql +243 -0
  6. package/package.json +1 -1
  7. package/schema-manifest.json +30 -3
  8. package/src/check.js +23 -0
  9. package/src/index.js +20 -0
  10. package/src/plan.js +79 -5
  11. package/src/tooling.test.mjs +237 -4
  12. package/tests/agent_board_atomic_fleet_onboarding.test.sql +124 -112
  13. package/tests/agent_board_claimkey.test.sql +25 -3
  14. package/tests/agent_board_consent_emission.test.sql +17 -13
  15. package/tests/agent_board_consent_gating.test.sql +55 -11
  16. package/tests/agent_board_delegation_policies.test.sql +3 -1
  17. package/tests/agent_board_enroll_resumption.test.sql +412 -0
  18. package/tests/agent_board_federated_lock_order_class.test.sql +1 -3
  19. package/tests/agent_board_fedsession_provider_absence_gate.test.sql +9 -6
  20. package/tests/agent_board_fleet_machine_reactivation.test.sql +56 -5
  21. package/tests/agent_board_mint_harden.test.sql +39 -4
  22. package/tests/agent_board_outbox_wake_ordering.test.sql +27 -12
  23. package/tests/agent_board_rejectsem.test.sql +1 -1
  24. package/tests/agent_board_rolereset.test.sql +23 -2
  25. package/tests/agent_board_rowid.test.sql +24 -13
  26. package/tests/agent_board_scoped_send_regrant.test.sql +8 -4
  27. package/tests/agent_board_signed_authority_provenance.test.sql +454 -0
  28. package/tests/agent_board_source_strip_helper.test.sql +285 -0
  29. package/tests/agent_board_wake_recovery.test.sql +58 -40
  30. package/tests/catalog/p_metadata_parameters.json +689 -0
  31. package/tests/fixtures/test-prereqs.sql +313 -0
  32. package/tests/isolation/expected/atomic_fleet_lifecycle_races.out +3 -3
@@ -5,7 +5,8 @@ import { join } from 'node:path';
5
5
  import { loadManifest, loadOrderedMigrations, sha256 } from './index.js';
6
6
  import { materialize } from './materialize.js';
7
7
  import { plan } from './plan.js';
8
- import { check, EXIT } from './check.js';
8
+ import { check, EXIT, POSTURE_ACTIONS } from './check.js';
9
+ import { COLLISION_REMEDIATIONS } from './index.js';
9
10
 
10
11
  const manifest = loadManifest();
11
12
  const ordered = loadOrderedMigrations();
@@ -37,9 +38,9 @@ describe('manifest integrity', () => {
37
38
  expect(manifest.schemaVersion).toBe(8);
38
39
  expect(manifest.minClientVersion).toMatch(/^\d+\.\d+\.\d+$/);
39
40
  });
40
- it('registers the four MBAUTHZ + four MBSENDAUTHZ + four MBSESSION + four MBDELEG + three MBFED + three MBHARDEN + two MBPORTALGATE + two MBPORTAL-PR32 + two ROOMOWN + two ROOMLINK + one ROOMDELEG + one LOCALAUTH + one ROOMUIAPI + one FEDSESSION + one FEDSESSION-AUTOJOIN + one GATENULL + one MEMBSTATE + one AGENTSDIR + one LEAVEIDEM + one ROLERESET + one MBROWID + one MBHYGIENE + one MBCONSENT-A + one MBCONSENT-B(a) + one MBCONSENT-B(i) + one MBCONSENT-B(ii) + one MBCONSENT-B(iii) + one MBHARDEN-#97 + one MBHARDEN-#118 + one INVITEPOLICY + one OBSGATE + one OBSGATE-2 + one OBSGATE-3 + one OBSGATE-4 + one FLEETMACHINERLS + one RESOLVENOOP + one ROOMDELEG-LANEB + one CLAIMKEY + two MINTHARDEN + one FLEETMACHINEHIJACK + one CLAIMGATE-SHADOW + one CLAIMGATE-ENFORCE + one FLEETMACHINEREACTIVATION + one DELEGCAPCEILING + one FLEETMACHINERECLAIM + one DELEGSOLEWRITER + one FLEETDOMAINRECLAIM + five ATOMICFLEETONBOARDING (onboarding + ceiling-lock + revocation-evidence + fedsession-gate + fedsession-lock-order) + one OUTBOXWAKE + one ENROLLLOCKORDER + one FEDPROVIDERABSENCE + one WAKERECOVERY forward migrations (migrationCount = prior 113 + 5 + 1 + 1 + 1 + 1 = 122)', () => {
41
+ it('registers the four MBAUTHZ + four MBSENDAUTHZ + four MBSESSION + four MBDELEG + three MBFED + three MBHARDEN + two MBPORTALGATE + two MBPORTAL-PR32 + two ROOMOWN + two ROOMLINK + one ROOMDELEG + one LOCALAUTH + one ROOMUIAPI + one FEDSESSION + one FEDSESSION-AUTOJOIN + one GATENULL + one MEMBSTATE + one AGENTSDIR + one LEAVEIDEM + one ROLERESET + one MBROWID + one MBHYGIENE + one MBCONSENT-A + one MBCONSENT-B(a) + one MBCONSENT-B(i) + one MBCONSENT-B(ii) + one MBCONSENT-B(iii) + one MBHARDEN-#97 + one MBHARDEN-#118 + one INVITEPOLICY + one OBSGATE + one OBSGATE-2 + one OBSGATE-3 + one OBSGATE-4 + one FLEETMACHINERLS + one RESOLVENOOP + one ROOMDELEG-LANEB + one CLAIMKEY + two MINTHARDEN + one FLEETMACHINEHIJACK + one CLAIMGATE-SHADOW + one CLAIMGATE-ENFORCE + one FLEETMACHINEREACTIVATION + one DELEGCAPCEILING + one FLEETMACHINERECLAIM + one DELEGSOLEWRITER + one FLEETDOMAINRECLAIM + five ATOMICFLEETONBOARDING (onboarding + ceiling-lock + revocation-evidence + fedsession-gate + fedsession-lock-order) + one OUTBOXWAKE + one ENROLLLOCKORDER + one FEDPROVIDERABSENCE + one WAKERECOVERY + one CONSENTRECONCILE + one ENROLLRESUMPTION + one SIGNEDAUTHORITY forward migrations (migrationCount = prior 113 + 5 + 1 + 1 + 1 + 1 + 1 + 1 + 1 = 125)', () => {
41
42
  expect(manifest.migrationCount).toBe(manifest.migrations.length);
42
- expect(manifest.migrationCount).toBe(122);
43
+ expect(manifest.migrationCount).toBe(125);
43
44
  // MBSESSION switched enforcement on (scoped-send re-grant): the client-visible
44
45
  // schema version bumped to 8. MBDELEG tightens delegation and MBFED adds only
45
46
  // enrollment-only additive surface (identity_providers registry, enrollment audit,
@@ -199,7 +200,239 @@ describe('plan / check postures + exit codes (SemVer contract)', () => {
199
200
  expect(check({ applied }).exitCode).toBe(11);
200
201
  });
201
202
  it('exit-code map is a frozen SemVer surface', () => {
202
- expect(EXIT).toEqual({ exact: 0, behind: 10, ahead: 11, divergent: 12, error: 13 });
203
+ expect(EXIT).toEqual({ exact: 0, behind: 10, ahead: 11, divergent: 12, error: 13, collision: 14 });
204
+ });
205
+
206
+ // VERSION COLLISION (message-board#217). Supabase keys schema_migrations on the
207
+ // 14-digit version prefix alone, so an adopter migration authored at a bundle
208
+ // migration's version makes the bundle's file skip SILENTLY -- no error, and
209
+ // schema_version still reports the bundle's number. The reported case is real:
210
+ // consiliency-portal recorded 20260809000100 as reconcile_panel_schema_drift.
211
+ // The adopter's own migration occupies the bundle's version, so the bundle's
212
+ // file was skipped. Two DISTINCT states matter, and conflating them is the
213
+ // defect a review seat caught: the collision ROW is permanent (Supabase keys
214
+ // schema_migrations on version, which is its primary key), so reporting on the
215
+ // row alone would fail a fully-healed database forever -- and an adopter forced
216
+ // to ignore exit 14 stops seeing genuine behind/divergent states too.
217
+ const portalHistory = (opts = {}) => ({
218
+ applied: [
219
+ ...ordered
220
+ .filter((m) => m.id !== '20260809000100_agent_board_consent_gating')
221
+ .filter((m) => opts.healed || m.id !== '20260905000100_agent_board_consent_gating_reconcile')
222
+ .map((m) => ({ id: m.id, sha256: m.sha256 })),
223
+ { id: '20260809000100_reconcile_panel_schema_drift', sha256: 'aa' },
224
+ ],
225
+ });
226
+
227
+ it('collision when an adopter migration occupies a bundle version and is unhealed', () => {
228
+ const c = check(portalHistory());
229
+ expect(c.posture).toBe('collision');
230
+ expect(c.exitCode).toBe(14);
231
+ });
232
+
233
+ it('collision names BOTH sides, so the report is an instruction not a puzzle', () => {
234
+ expect(plan(portalHistory()).collisions).toEqual([
235
+ {
236
+ version: '20260809000100',
237
+ expected: '20260809000100_agent_board_consent_gating',
238
+ recordedAs: '20260809000100_reconcile_panel_schema_drift',
239
+ remediatedBy: '20260905000100_agent_board_consent_gating_reconcile',
240
+ },
241
+ ]);
242
+ });
243
+
244
+ it('collision outranks behind — "behind" invites re-applying, which is the no-op that leaves the DB wrong', () => {
245
+ const p = plan(portalHistory());
246
+ expect(p.perId.filter((r) => r.action === 'pending').map((r) => r.id)).toContain(
247
+ '20260809000100_agent_board_consent_gating',
248
+ );
249
+ expect(p.posture).toBe('collision');
250
+ });
251
+
252
+ it('a HEALED database reports exact/0 — not merely "not collision"', () => {
253
+ // Asserting "not collision / not 14" was too weak and a review seat broke it:
254
+ // both halves of a remediated pair are PERMANENT (the bundle migration can
255
+ // never be applied on that database because its version is taken, and the
256
+ // adopter's row can never be removed), so leaving them in the counts gated
257
+ // the healed database at behind/10 forever — a different permanent red than
258
+ // the one being fixed. The claim is exact/0, so that is what is asserted.
259
+ const p = plan(portalHistory({ healed: true }));
260
+ expect(p.collisions).toEqual([]);
261
+ expect(p.collisionsRemediated.map((c) => c.expected)).toEqual([
262
+ '20260809000100_agent_board_consent_gating',
263
+ ]);
264
+ expect(p.counts.pending ?? 0).toBe(0);
265
+ expect(p.ahead).toEqual([]);
266
+ expect(p.posture).toBe('exact');
267
+ expect(check(portalHistory({ healed: true })).exitCode).toBe(0);
268
+ });
269
+
270
+ it('a NULL migration name is indeterminate, not a collision', () => {
271
+ // schema_migrations.name is nullable, and the documented psql recipe renders
272
+ // such a row as `<version>_`. A substring test for '_' called that a named
273
+ // row and invented a collision from a legitimate history.
274
+ const applied = [
275
+ ...ordered
276
+ .filter((m) => m.id !== '20260809000100_agent_board_consent_gating')
277
+ .map((m) => ({ id: m.id, sha256: m.sha256 })),
278
+ { id: '20260809000100_', sha256: 'aa' },
279
+ ];
280
+ const p = plan({ applied });
281
+ expect(p.collisions).toEqual([]);
282
+ expect(check({ applied }).exitCode).toBe(10); // behind, which is true: the DDL is absent
283
+ });
284
+
285
+ it('a DIVERGENT healer does not remediate — it is not the migration we shipped', () => {
286
+ // The database applied something under the healer's id that is not this
287
+ // bundle's bytes, so nothing here can claim the skipped DDL was restored.
288
+ // Posture already goes divergent, but reporting the collision as REMEDIATED
289
+ // would be the same false-success the detector exists to prevent.
290
+ const healer = '20260905000100_agent_board_consent_gating_reconcile';
291
+ const applied = [
292
+ ...ordered
293
+ .filter((m) => m.id !== '20260809000100_agent_board_consent_gating')
294
+ .map((m) => ({ id: m.id, sha256: m.id === healer ? 'deadbeef' : m.sha256 })),
295
+ { id: '20260809000100_reconcile_panel_schema_drift', sha256: 'aa' },
296
+ ];
297
+ const p = plan({ applied });
298
+ expect(p.collisionsRemediated).toEqual([]);
299
+ expect(p.collisions).toHaveLength(1);
300
+ expect(p.posture).toBe('collision');
301
+ });
302
+
303
+ it('an UNKNOWN healer digest still remediates — digest-less histories are supported', () => {
304
+ // normalizeHistory accepts entries without a digest. Requiring one would
305
+ // strand those adopters in the permanent red this design removes.
306
+ const applied = [
307
+ ...ordered.filter((m) => m.id !== '20260809000100_agent_board_consent_gating').map((m) => m.id),
308
+ '20260809000100_reconcile_panel_schema_drift',
309
+ ];
310
+ const p = plan({ applied });
311
+ expect(p.collisionsRemediated).toHaveLength(1);
312
+ expect(p.collisions).toEqual([]);
313
+ });
314
+
315
+ it('the healer being present is what clears it — not merely being declared', () => {
316
+ // Same declaration, healer unapplied: still live. Without this the previous
317
+ // test would pass on a map lookup rather than on the database's actual state.
318
+ expect(plan(portalHistory()).collisionsRemediated).toEqual([]);
319
+ expect(plan(portalHistory()).collisions).toHaveLength(1);
320
+ });
321
+
322
+ it('a bare-version history is indeterminate, not one collision per bundled migration', () => {
323
+ // normalizeHistory accepts plain version strings. Such an entry carries no
324
+ // name, so it cannot be told apart from the bundle's own migration at that
325
+ // version — reporting it as a collision turns a supported input shape into a
326
+ // wall of false positives.
327
+ const p = plan({ applied: ordered.map((m) => m.id.split('_')[0]) });
328
+ expect(p.collisions).toEqual([]);
329
+ });
330
+
331
+ it('an unrelated adopter migration is NOT a collision, even with a bundle migration pending', () => {
332
+ // The history MUST have something pending as well as something ahead. A first
333
+ // draft of this test used an exact history plus one extra entry, and a mutation
334
+ // that reported every ahead entry as a collision SURVIVED it: with nothing
335
+ // pending there is no cross-product to over-report, so the assertion passed
336
+ // while checking nothing. A negative assertion driven by a clean input proves
337
+ // nothing (CLAUDE.md rule 2).
338
+ const applied = [
339
+ ...ordered
340
+ .filter((m) => m.id !== '20260809000100_agent_board_consent_gating')
341
+ .map((m) => ({ id: m.id, sha256: m.sha256 })),
342
+ { id: '99999999999999_extra', sha256: 'ff' },
343
+ ];
344
+ const p = plan({ applied });
345
+ expect(p.perId.some((r) => r.action === 'pending')).toBe(true); // the input is not clean
346
+ expect(p.ahead).toContain('99999999999999_extra');
347
+ expect(p.collisions).toEqual([]);
348
+ expect(p.posture).toBe('behind');
349
+ });
350
+ });
351
+
352
+ // OPERATOR GUIDANCE. Checks EXIT and POSTURE_ACTIONS agree with each other.
353
+ //
354
+ // This is NOT the completeness guard, and an earlier version of this comment
355
+ // claimed it was. EXIT is a SECOND hand list, not the catalog: a posture added to
356
+ // plan() without an EXIT entry passes everything here, falls through check()'s
357
+ // `EXIT[p.posture] ?? EXIT.error` to exit 13, and prints no action. The real
358
+ // catalog is the set of values plan() assigns, and scripts/check-posture-consumers.mjs
359
+ // reads it from there -- and also holds the live-drift consumer to using
360
+ // POSTURE_ACTIONS, which no test in this package can see. That script runs in
361
+ // `schema:verify`. What follows is the in-package half: the two tables stay
362
+ // consistent, and the collision action never tells an operator to re-apply.
363
+ describe('every posture has operator guidance', () => {
364
+ const postures = Object.keys(EXIT).filter((k) => k !== 'error');
365
+
366
+ it('EXIT and POSTURE_ACTIONS cover the same postures', () => {
367
+ expect(Object.keys(POSTURE_ACTIONS).sort()).toEqual(postures.sort());
368
+ });
369
+
370
+ it('every non-exact posture has a non-empty action', () => {
371
+ for (const posture of postures) {
372
+ if (posture === 'exact') {
373
+ expect(POSTURE_ACTIONS.exact).toBeNull(); // nothing to do is not a missing action
374
+ continue;
375
+ }
376
+ expect(typeof POSTURE_ACTIONS[posture]).toBe('string');
377
+ expect(POSTURE_ACTIONS[posture].length).toBeGreaterThan(20);
378
+ }
379
+ });
380
+
381
+ it("the collision action does NOT tell an operator to re-apply", () => {
382
+ // Re-applying is the no-op that leaves the database wrong: the version is taken.
383
+ expect(POSTURE_ACTIONS.collision).toMatch(/no-op|not simply re-apply|Do NOT/i);
384
+ });
385
+ });
386
+
387
+ // COLLISION REMEDIATION (message-board#217). The reconcile migration's whole
388
+ // no-op-on-a-healthy-database property rests on its join_board body being
389
+ // byte-identical to the one in the migration an affected database skipped. The
390
+ // PR asserted that in prose and nothing checked it -- the exact shape this repo
391
+ // keeps getting caught by. The digest tests freeze each file's bytes, which is
392
+ // not the same claim: two files can both be frozen and still differ.
393
+ describe('collision remediation is real, not merely declared', () => {
394
+ const read = (id) =>
395
+ readFileSync(new URL(`../migrations/${id}.sql`, import.meta.url), 'utf8');
396
+ const joinBoardBlock = (sql) => {
397
+ const start = sql.search(/create or replace function agent_board\.join_board\b/i);
398
+ const rest = sql.slice(start + 10);
399
+ const next = rest.search(/create or replace function agent_board\./i);
400
+ return (next === -1 ? rest : rest.slice(0, next)).trimEnd();
401
+ };
402
+
403
+ it('every declared remediation names migrations that exist in the bundle', () => {
404
+ const ids = new Set(ordered.map((m) => m.id));
405
+ for (const [skipped, healer] of Object.entries(COLLISION_REMEDIATIONS)) {
406
+ expect(ids.has(skipped)).toBe(true);
407
+ expect(ids.has(healer)).toBe(true);
408
+ // The healer must come LATER, or it cannot run after the skip.
409
+ expect(healer > skipped).toBe(true);
410
+ }
411
+ });
412
+
413
+ it('the healer restates the skipped function BYTE-IDENTICALLY, so a healthy DB is a true no-op', () => {
414
+ const skipped = joinBoardBlock(read('20260809000100_agent_board_consent_gating'));
415
+ const healer = joinBoardBlock(read('20260905000100_agent_board_consent_gating_reconcile'));
416
+ expect(healer.length).toBeGreaterThan(1000);
417
+ expect(healer).toBe(skipped);
418
+ });
419
+
420
+ it('the healer touches ONLY the stale function, so it cannot clobber a later definition', () => {
421
+ // resolve_board_request and update_board_membership are superseded by
422
+ // 20260819000100 and 20260813000100. Restating them here would re-apply the
423
+ // older bodies over the newer ones on every healthy database.
424
+ const sql = read('20260905000100_agent_board_consent_gating_reconcile');
425
+ const defined = [...sql.matchAll(/create or replace function agent_board\.(\w+)/gi)].map((m) => m[1]);
426
+ expect(defined).toEqual(['join_board']);
427
+ });
428
+
429
+ it('the healer adds no grant, revoke or comment — create-or-replace preserves the ACL', () => {
430
+ const sql = read('20260905000100_agent_board_consent_gating_reconcile')
431
+ .split('\n').filter((l) => !l.trimStart().startsWith('--')).join('\n');
432
+ expect(sql).not.toMatch(/\bgrant\b/i);
433
+ expect(sql).not.toMatch(/\brevoke\b/i);
434
+ expect(sql).not.toMatch(/comment\s+on/i);
435
+ expect(sql).not.toMatch(/drop\s+function/i);
203
436
  });
204
437
  });
205
438
 
@@ -12,7 +12,7 @@
12
12
  -- runtime backstop at all.
13
13
  --
14
14
  -- WHAT THE FIX IS. Each positional assertion now locates its markers on
15
- -- `pg_temp._stripped_body(<fn>)` -- prosrc with dollar-quoted blocks, single-quoted
15
+ -- `agent_board_test.stripped_body(<fn>)` -- prosrc with dollar-quoted blocks, single-quoted
16
16
  -- literals, line comments and block comments removed in ONE alternation pass. The
17
17
  -- regex is copied BYTE-FOR-BYTE from agent_board_federated_lock_order_class.test.sql,
18
18
  -- where its three failure modes were found the hard way: a block comment whose body
@@ -123,24 +123,23 @@ create extension if not exists pgtap with schema extensions;
123
123
  set search_path = extensions, public, agent_board;
124
124
 
125
125
  begin;
126
- select plan(52);
126
+ select plan(54);
127
127
 
128
128
  -- ---------------------------------------------------------------------------
129
- -- The stripped-body reader every positional assertion below uses. A shared SQL
130
- -- include is not workable in this harness -- the runner pipes
131
- -- `begin; \i <file>; rollback;` into psql, so there is no reliable relative
132
- -- include path -- so it is defined ONCE here instead of being copy-pasted into
133
- -- nine call sites, which would guarantee drift. The regex is byte-identical to
134
- -- agent_board_federated_lock_order_class.test.sql; see the header.
129
+ -- The stripped-body reader every positional assertion below uses is
130
+ -- agent_board_test.stripped_body(), defined ONCE for the whole suite in
131
+ -- tests/fixtures/test-prereqs.sql (the runner applies that fixture before any
132
+ -- test, so it needs no include path).
133
+ --
134
+ -- It used to be a local regex copied here and kept byte-identical to
135
+ -- agent_board_federated_lock_order_class.test.sql so the two could not drift.
136
+ -- They could not drift, and they were both WRONG: no regular expression can
137
+ -- match a NESTED block comment, and `/* note /* x */ <code> */` therefore hid
138
+ -- <code> from both files at once (message-board#199) -- 52/52 and 15/15 green
139
+ -- with the boards lock genuinely relocated. The shared helper is a character
140
+ -- scanner for that reason; see its header for the full enumeration of escape
141
+ -- hatches and which ones a regex can and cannot close.
135
142
  -- ---------------------------------------------------------------------------
136
- create function pg_temp._stripped_body(p_fn regprocedure) returns text
137
- language sql stable as $strip$
138
- select regexp_replace(p.prosrc,
139
- $re$(\$[A-Za-z_0-9]*\$).*?\1|('([^']|'')*')|(--[^\n]*)|(/\*([^*]|\*+[^*/])*\*+/)$re$,
140
- ' ', 'g')
141
- from pg_proc p
142
- where p.oid = p_fn;
143
- $strip$;
144
143
 
145
144
  select has_table('agent_board', 'fleet_onboarding_invite_bounds', 'immutable fleet invite bounds table exists');
146
145
  select has_pk('agent_board', 'fleet_onboarding_invite_bounds', 'fleet invite bounds are keyed by invite id');
@@ -248,38 +247,22 @@ select ok(
248
247
  'binding revocation is a permanent tombstone'
249
248
  );
250
249
  select ok(
251
- strpos(
252
- pg_temp._stripped_body('agent_board.revoke_fleet_machine_agent_binding(uuid,uuid,text,jsonb)'::regprocedure),
253
- 'from agent_board.fleet_machines m'
250
+ strpos(lower(agent_board_test.stripped_body('agent_board.revoke_fleet_machine_agent_binding(uuid,uuid,text,jsonb)'::regprocedure)), 'from agent_board.fleet_machines m'
254
251
  ) > 0
255
- and strpos(
256
- pg_temp._stripped_body('agent_board.revoke_fleet_machine_agent_binding(uuid,uuid,text,jsonb)'::regprocedure),
257
- 'from agent_board.fleet_machine_agents b where b.id = p_binding_id for update'
252
+ and strpos(lower(agent_board_test.stripped_body('agent_board.revoke_fleet_machine_agent_binding(uuid,uuid,text,jsonb)'::regprocedure)), 'from agent_board.fleet_machine_agents b where b.id = p_binding_id for update'
258
253
  ) > 0
259
- and strpos(
260
- pg_temp._stripped_body('agent_board.revoke_fleet_machine_agent_binding(uuid,uuid,text,jsonb)'::regprocedure),
261
- 'from agent_board.fleet_machines m'
262
- ) < strpos(
263
- pg_temp._stripped_body('agent_board.revoke_fleet_machine_agent_binding(uuid,uuid,text,jsonb)'::regprocedure),
264
- 'from agent_board.fleet_machine_agents b where b.id = p_binding_id for update'
254
+ and strpos(lower(agent_board_test.stripped_body('agent_board.revoke_fleet_machine_agent_binding(uuid,uuid,text,jsonb)'::regprocedure)), 'from agent_board.fleet_machines m'
255
+ ) < strpos(lower(agent_board_test.stripped_body('agent_board.revoke_fleet_machine_agent_binding(uuid,uuid,text,jsonb)'::regprocedure)), 'from agent_board.fleet_machine_agents b where b.id = p_binding_id for update'
265
256
  ),
266
257
  'exact binding revocation locks the machine before the binding [SOLE PIN: no isolation spec discriminates this ordering -- measured against all 20]'
267
258
  );
268
259
  select ok(
269
- strpos(
270
- pg_temp._stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure),
271
- 'where fm.id = p_machine_id for update'
260
+ strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'where fm.id = p_machine_id for update'
272
261
  ) > 0
273
- and strpos(
274
- pg_temp._stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure),
275
- 'from agent_board.agents a where a.id = v_enroll.agent_id for update'
262
+ and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.agents a where a.id = v_enroll.agent_id for update'
276
263
  ) > 0
277
- and strpos(
278
- pg_temp._stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure),
279
- 'where fm.id = p_machine_id for update'
280
- ) < strpos(
281
- pg_temp._stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure),
282
- 'from agent_board.agents a where a.id = v_enroll.agent_id for update'
264
+ and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'where fm.id = p_machine_id for update'
265
+ ) < strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.agents a where a.id = v_enroll.agent_id for update'
283
266
  ),
284
267
  'atomic onboarding locks the machine before its enrolled agent [CONFIRMATORY: atomic_fleet_binding_revoke.spec and atomic_fleet_lifecycle_races.spec both discriminate the inversion]'
285
268
  );
@@ -299,7 +282,7 @@ select ok(
299
282
  -- does not fail the claim.
300
283
  select ok(
301
284
  (with b as (
302
- select pg_temp._stripped_body(
285
+ select agent_board_test.stripped_body(
303
286
  'agent_board.revoke_fleet_subject(text,uuid,uuid,text,jsonb)'::regprocedure) as t),
304
287
  p as (
305
288
  select t,
@@ -318,20 +301,12 @@ select ok(
318
301
  'agent fleet revocation takes its machine locks before the agent lock [SOLE PIN: no isolation spec discriminates this ordering -- measured against all 20]'
319
302
  );
320
303
  select ok(
321
- strpos(
322
- pg_temp._stripped_body('agent_board._revoke_agent_principal(uuid,uuid,text)'::regprocedure),
323
- 'from agent_board.agents a where a.id = p_agent_id for update'
304
+ strpos(lower(agent_board_test.stripped_body('agent_board._revoke_agent_principal(uuid,uuid,text)'::regprocedure)), 'from agent_board.agents a where a.id = p_agent_id for update'
324
305
  ) > 0
325
- and strpos(
326
- pg_temp._stripped_body('agent_board._revoke_agent_principal(uuid,uuid,text)'::regprocedure),
327
- 'from agent_board.agent_signing_keys'
306
+ and strpos(lower(agent_board_test.stripped_body('agent_board._revoke_agent_principal(uuid,uuid,text)'::regprocedure)), 'from agent_board.agent_signing_keys'
328
307
  ) > 0
329
- and strpos(
330
- pg_temp._stripped_body('agent_board._revoke_agent_principal(uuid,uuid,text)'::regprocedure),
331
- 'from agent_board.agents a where a.id = p_agent_id for update'
332
- ) < strpos(
333
- pg_temp._stripped_body('agent_board._revoke_agent_principal(uuid,uuid,text)'::regprocedure),
334
- 'from agent_board.agent_signing_keys'
308
+ and strpos(lower(agent_board_test.stripped_body('agent_board._revoke_agent_principal(uuid,uuid,text)'::regprocedure)), 'from agent_board.agents a where a.id = p_agent_id for update'
309
+ ) < strpos(lower(agent_board_test.stripped_body('agent_board._revoke_agent_principal(uuid,uuid,text)'::regprocedure)), 'from agent_board.agent_signing_keys'
335
310
  ),
336
311
  'subtree primitive locks the agent before signing keys [SOLE PIN: no isolation spec discriminates this ordering -- measured against all 20]'
337
312
  );
@@ -359,20 +334,12 @@ select ok(
359
334
  -- not-found case fail instead of pass; the other eight positional claims in this
360
335
  -- file already carried them.
361
336
  select ok(
362
- strpos(
363
- pg_temp._stripped_body('agent_board.revoke_agent(uuid,text)'::regprocedure),
364
- 'update agent_board.agents'
337
+ strpos(lower(agent_board_test.stripped_body('agent_board.revoke_agent(uuid,text)'::regprocedure)), 'update agent_board.agents'
365
338
  ) > 0
366
- and strpos(
367
- pg_temp._stripped_body('agent_board.revoke_agent(uuid,text)'::regprocedure),
368
- 'update agent_board.agent_credentials'
339
+ and strpos(lower(agent_board_test.stripped_body('agent_board.revoke_agent(uuid,text)'::regprocedure)), 'update agent_board.agent_credentials'
369
340
  ) > 0
370
- and strpos(
371
- pg_temp._stripped_body('agent_board.revoke_agent(uuid,text)'::regprocedure),
372
- 'update agent_board.agents'
373
- ) < strpos(
374
- pg_temp._stripped_body('agent_board.revoke_agent(uuid,text)'::regprocedure),
375
- 'update agent_board.agent_credentials'
341
+ and strpos(lower(agent_board_test.stripped_body('agent_board.revoke_agent(uuid,text)'::regprocedure)), 'update agent_board.agents'
342
+ ) < strpos(lower(agent_board_test.stripped_body('agent_board.revoke_agent(uuid,text)'::regprocedure)), 'update agent_board.agent_credentials'
376
343
  ),
377
344
  'legacy authenticated revoke_agent preserves agent-before-credential ordering [HISTORICAL: legacy platform-admin path, no live fleet counterparty and no isolation spec]'
378
345
  );
@@ -404,10 +371,18 @@ select ok(
404
371
  like '%from auth.users u where u.id = v_owner_user_id for update%fleet_human_revocations%r.issuer = p_issuer and r.subject = p_subject%',
405
372
  'identity enrollment locks the human owner and rejects durable total revocation'
406
373
  );
374
+ -- LITERALS KEPT (the `true` second argument): every marker below is itself a
375
+ -- string literal in the body -- `''federation''`, `''object''`, the
376
+ -- `'{federation,replay,issuer}'` path, the raise message. Stripping literals here
377
+ -- would delete the very text being located and make the `not like` vacuously true
378
+ -- forever. Comments (all forms, INCLUDING NESTED) are still removed, so the
379
+ -- message-board#196 comment masks are closed; a literal mask is inherent to a
380
+ -- literal marker, which is why the isolation spec and not this line is the
381
+ -- load-bearing guard.
407
382
  select ok(
408
- pg_get_functiondef('agent_board.revoke_human_subtree(uuid,uuid,text)'::regprocedure)
383
+ agent_board_test.stripped_body('agent_board.revoke_human_subtree(uuid,uuid,text)'::regprocedure, true)
409
384
  like '%from auth.users u where u.id = p_owner_user_id for update%where a.owner_user_id = p_owner_user_id%jsonb_typeof(a.metadata -> ''federation'') = ''object''%not exists (%from agent_board.enrollment_federation_audit e%where e.agent_id = a.id%stable federation evidence not found for every linked agent%insert into agent_board.fleet_human_revocations%issuer, subject, owner_user_id%on conflict (issuer, subject) do nothing%where owner_user_id = p_owner_user_id%order by id%'
410
- and pg_get_functiondef('agent_board.revoke_human_subtree(uuid,uuid,text)'::regprocedure)
385
+ and agent_board_test.stripped_body('agent_board.revoke_human_subtree(uuid,uuid,text)'::regprocedure, true)
411
386
  not like '%metadata #>> ''{federation,replay,issuer}''%',
412
387
  'total human revocation requires per-agent audit evidence before marking and enumeration'
413
388
  );
@@ -458,16 +433,10 @@ select ok(
458
433
  -- Ordering, not mere presence: the lock has to be held BEFORE the authorization
459
434
  -- decision reads the (possibly absent) ceiling, and BEFORE the writer upserts it.
460
435
  select ok(
461
- strpos(
462
- pg_temp._stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure),
463
- 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
436
+ strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
464
437
  ) > 0
465
- and strpos(
466
- pg_temp._stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure),
467
- 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
468
- ) < strpos(
469
- pg_temp._stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure),
470
- 'agent_board._grant_within_ceiling('
438
+ and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
439
+ ) < strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'agent_board._grant_within_ceiling('
471
440
  ),
472
441
  'atomic onboarding holds the board ceiling lock before evaluating creator authority [REDUNDANT: implied by the advisory-before-boards and boards-before-ceiling-read claims below; an advisory moved between those two points violates the real ordering and still passes THIS one]'
473
442
  );
@@ -479,16 +448,10 @@ select ok(
479
448
  -- that catches the inversion; it is deliberately separate from the "before the
480
449
  -- ceiling read" assertion below, because that one passes in BOTH orders.
481
450
  select ok(
482
- strpos(
483
- pg_temp._stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure),
484
- 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
451
+ strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
485
452
  ) > 0
486
- and strpos(
487
- pg_temp._stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure),
488
- 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
489
- ) < strpos(
490
- pg_temp._stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure),
491
- 'from agent_board.boards b
453
+ and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
454
+ ) < strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.boards b
492
455
  where b.id = v_inv.board_id
493
456
  for update'
494
457
  ),
@@ -508,34 +471,22 @@ select ok(
508
471
  -- ordering nothing else states, because the boards lock is taken for board liveness,
509
472
  -- not for the ceiling. Pin the ordering so a refactor that moves it is not silent.
510
473
  select ok(
511
- strpos(
512
- pg_temp._stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure),
513
- 'from agent_board.boards b
474
+ strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.boards b
514
475
  where b.id = v_inv.board_id
515
476
  for update'
516
477
  ) > 0
517
- and strpos(
518
- pg_temp._stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure),
519
- 'from agent_board.boards b
478
+ and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.boards b
520
479
  where b.id = v_inv.board_id
521
480
  for update'
522
- ) < strpos(
523
- pg_temp._stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure),
524
- 'agent_board._grant_within_ceiling('
481
+ ) < strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'agent_board._grant_within_ceiling('
525
482
  ),
526
483
  'atomic onboarding holds the boards row FOR UPDATE before it reads the ceiling [CONFIRMATORY FOR FLAT MASKS ONLY: agent_board_federated_lock_order_class.test.sql EC-3 fails by name on the comment/literal mutants, but it carries the SAME strip, so a NESTED block comment takes this assertion and EC-3 green together -- see #199 in the header; atomic_fleet_authority_races.spec pins the OUTCOME only when this lock and the advisory are BOTH gone, and atomic_fleet_board_archive.spec BLOCKS rather than failing by name]'
527
484
  );
528
485
  select ok(
529
- strpos(
530
- pg_temp._stripped_body('agent_board.set_board_authority_ceiling(uuid,text)'::regprocedure),
531
- 'perform agent_board._lock_board_authority_ceiling(p_board_id)'
486
+ strpos(lower(agent_board_test.stripped_body('agent_board.set_board_authority_ceiling(uuid,text,uuid)'::regprocedure)), 'perform agent_board._lock_board_authority_ceiling(p_board_id)'
532
487
  ) > 0
533
- and strpos(
534
- pg_temp._stripped_body('agent_board.set_board_authority_ceiling(uuid,text)'::regprocedure),
535
- 'perform agent_board._lock_board_authority_ceiling(p_board_id)'
536
- ) < strpos(
537
- pg_temp._stripped_body('agent_board.set_board_authority_ceiling(uuid,text)'::regprocedure),
538
- 'insert into agent_board.board_authority_ceilings'
488
+ and strpos(lower(agent_board_test.stripped_body('agent_board.set_board_authority_ceiling(uuid,text,uuid)'::regprocedure)), 'perform agent_board._lock_board_authority_ceiling(p_board_id)'
489
+ ) < strpos(lower(agent_board_test.stripped_body('agent_board.set_board_authority_ceiling(uuid,text,uuid)'::regprocedure)), 'insert into agent_board.board_authority_ceilings'
539
490
  ),
540
491
  'the ceiling setter holds the same lock before its owner gate and upsert [BACKSTOP: tests/isolation/specs/ceiling_setter_lock_before_upsert.spec]'
541
492
  );
@@ -550,12 +501,22 @@ select ok(
550
501
  select is( -- pgtap-allow-raise-checked: catalog read only; the RPC names below are string literals in the expected array, never invoked
551
502
  (select array_agg(entry order by entry) from (
552
503
  select 'agent_board.' || regexp_replace(p.oid::regprocedure::text, '^([^(]*\.)?', '') || ' => ' ||
553
- case when strpos(p.prosrc, '_lock_board_authority_ceiling') > 0
504
+ -- CALL SHAPE, not strpos on a bare name: this is the dangerous
505
+ -- direction -- a reader that DROPS the lock but keeps a variable named
506
+ -- after it would still print "serialized".
507
+ -- SCHEMA-QUALIFIED, because a bare-name anchor proves call SYNTAX, not callee
508
+ -- IDENTITY: `\m_lock_board_authority_ceiling\s*\(` also matches
509
+ -- `zz_other._lock_board_authority_ceiling(...)` (measured true). Every live call
510
+ -- site in agent_board is `agent_board.`-qualified, so requiring the
511
+ -- qualification costs nothing today and is fail-CLOSED if someone later writes
512
+ -- an unqualified call (it reads as NOT calling). Overload count is pinned
513
+ -- separately, so schema + name is the identity.
514
+ case when agent_board_test.stripped_body(p.oid) ~* '\magent_board\._lock_board_authority_ceiling\s*\('
554
515
  then 'serialized' else 'UNSERIALIZED' end as entry
555
516
  from pg_proc p
556
517
  join pg_namespace n on n.oid = p.pronamespace
557
518
  where n.nspname = 'agent_board'
558
- and strpos(p.prosrc, '_grant_within_ceiling') > 0
519
+ and strpos(lower(agent_board_test.stripped_body(p.oid)), '_grant_within_ceiling') > 0
559
520
  ) readers),
560
521
  array[
561
522
  'agent_board._redeem_unbounded_invite_for_agent(text,uuid) => UNSERIALIZED',
@@ -594,11 +555,18 @@ select is( -- pgtap-allow-raise-checked: catalog read only; the RPC names below
594
555
  from pg_proc p
595
556
  join pg_namespace n on n.oid = p.pronamespace
596
557
  where n.nspname = 'agent_board'
597
- and (strpos(p.prosrc, 'fleet_onboarding_invite_bounds') > 0
598
- or strpos(p.prosrc, 'fleet_human_revocations') > 0
599
- or strpos(p.prosrc, 'fleet_revocation_events') > 0
600
- or strpos(p.prosrc, '_lock_board_authority_ceiling') > 0
601
- or strpos(p.prosrc, 'board_authority_ceilings:') > 0)
558
+ -- The first four markers are CODE (relation and function names), so the
559
+ -- body is read with literals stripped. The fifth is the advisory-lock key
560
+ -- prefix, which exists ONLY as a string literal
561
+ -- (`hashtextextended('agent_board.board_authority_ceilings:' || ...)`), so
562
+ -- that one predicate must KEEP literals or _lock_board_authority_ceiling --
563
+ -- the single function this migration creates -- silently leaves the class.
564
+ -- Comments are stripped in both modes.
565
+ and (strpos(lower(agent_board_test.stripped_body(p.oid)), 'fleet_onboarding_invite_bounds') > 0
566
+ or strpos(lower(agent_board_test.stripped_body(p.oid)), 'fleet_human_revocations') > 0
567
+ or strpos(lower(agent_board_test.stripped_body(p.oid)), 'fleet_revocation_events') > 0
568
+ or strpos(lower(agent_board_test.stripped_body(p.oid)), '_lock_board_authority_ceiling') > 0
569
+ or strpos(agent_board_test.stripped_body(p.oid, true), 'board_authority_ceilings:') > 0)
602
570
  ) definers),
603
571
  array[
604
572
  'agent_board._lock_board_authority_ceiling(uuid) [invoker] => service_role',
@@ -611,13 +579,57 @@ select is( -- pgtap-allow-raise-checked: catalog read only; the RPC names below
611
579
  'agent_board.evaluate_fleet_sender_policy(uuid,uuid,uuid,uuid,text,uuid,boolean) [definer] => authenticated,service_role',
612
580
  'agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text) [definer] => service_role',
613
581
  'agent_board.reactivate_fleet_machine(uuid,uuid,text) [definer] => service_role',
614
- 'agent_board.reclaim_fleet_machine(uuid,uuid,uuid,text,uuid) [definer] => service_role',
615
582
  'agent_board.revoke_fleet_subject(text,uuid,uuid,text,jsonb) [definer] => authenticated,service_role',
616
583
  'agent_board.revoke_human_subtree(uuid,uuid,text) [definer] => service_role',
617
- 'agent_board.set_board_authority_ceiling(uuid,text) [definer] => authenticated,service_role'
584
+ 'agent_board.set_board_authority_ceiling(uuid,text,uuid) [definer] => authenticated,service_role'
618
585
  ]::text[],
619
586
  'every function on this migration set''s surface is declared with its definer flag and exact EXECUTE grantees'
620
587
  );
621
588
 
589
+ -- WHAT THE message-board#196 CONVERSION REMOVED FROM THE CLASS ABOVE, and why
590
+ -- it is restated here instead of being silently dropped.
591
+ --
592
+ -- reclaim_fleet_machine was a member of that class while the predicate read RAW
593
+ -- prosrc -- and ONLY because a `--` comment in its body says "no
594
+ -- fleet_revocation_events row is written per binding". It was in the surface
595
+ -- class for SAYING IT IS NOT ON THE SURFACE. Reading the stripped body removes
596
+ -- it, which is correct: it touches none of the five surfaces.
597
+ --
598
+ -- Its exact-grantee pin was real coverage, though, and an accidental member's
599
+ -- coverage is still coverage. Per CLAUDE.md rule 1 an exemption is asserted
600
+ -- POSITIVELY, never by absence of a match, so the claim it used to carry is
601
+ -- restated as its own assertion.
602
+ select is(
603
+ (select coalesce((
604
+ select string_agg(distinct coalesce(pg_get_userbyid(nullif(a.grantee, 0)), 'PUBLIC'), ','
605
+ order by coalesce(pg_get_userbyid(nullif(a.grantee, 0)), 'PUBLIC'))
606
+ from aclexplode(p.proacl) a
607
+ where a.privilege_type = 'EXECUTE'
608
+ and a.grantee <> p.proowner), '(none)')
609
+ || case when p.prosecdef then ' [definer]' else ' [invoker]' end
610
+ from pg_proc p
611
+ join pg_namespace n on n.oid = p.pronamespace
612
+ where n.nspname = 'agent_board'
613
+ -- identity by OID + identity-arguments, never by a rendered regprocedure:
614
+ -- this file puts agent_board on search_path, so `oid::regprocedure::text`
615
+ -- renders UNQUALIFIED and an 'agent_board.…' comparison silently matches
616
+ -- nothing (measured: this assertion read NULL until it was written this way).
617
+ and 'agent_board.' || regexp_replace(p.oid::regprocedure::text, '^([^(]*\.)?', '')
618
+ = 'agent_board.reclaim_fleet_machine(uuid,uuid,uuid,text,uuid)'),
619
+ 'service_role [definer]',
620
+ 'reclaim_fleet_machine -- off this surface once comments are stripped -- keeps its service_role-only definer grant'
621
+ );
622
+
623
+
624
+ -- The schema-qualified call anchor above treats `agent_board._lock_board_authority_ceiling` as an
625
+ -- IDENTITY. That is only true while the name resolves to exactly one function:
626
+ -- a second overload would be a different implementation the same anchor accepts.
627
+ -- Catalog-derived, so a new overload fails here and the count names itself.
628
+ select is(
629
+ (select count(*)::int from pg_proc p join pg_namespace n on n.oid = p.pronamespace
630
+ where n.nspname = 'agent_board' and p.proname = '_lock_board_authority_ceiling'),
631
+ 1,
632
+ 'agent_board._lock_board_authority_ceiling has exactly ONE overload, so the schema-qualified call anchor identifies it uniquely');
633
+
622
634
  select * from finish();
623
635
  rollback;