@consiliency/agent-board-schema 1.63.0 → 1.68.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 (63) hide show
  1. package/README.md +25 -0
  2. package/fixtures/already-applied.json +20 -0
  3. package/migrations/20261014000200_agent_board_last_owner.sql +239 -0
  4. package/migrations/20261015000100_agent_board_session_provenance.sql +367 -0
  5. package/migrations/20261015000200_agent_board_request_preserve_removed.sql +87 -0
  6. package/migrations/20261015000300_agent_board_rls_correlation.sql +132 -0
  7. package/migrations/20261015000400_agent_board_resolution_authority.sql +146 -0
  8. package/package.json +1 -1
  9. package/schema-manifest.json +48 -3
  10. package/src/deployment-drift-main.test.mjs +156 -0
  11. package/src/deployment-drift-script.test.mjs +14 -1
  12. package/src/policy-comment.test.mjs +17 -0
  13. package/src/tooling.test.mjs +10 -2
  14. package/tests/agent_board_atomic_fleet_onboarding.test.sql +3 -1
  15. package/tests/agent_board_atomic_fleet_onboarding_runtime.test.sql +7 -0
  16. package/tests/agent_board_consent_gating.test.sql +4 -4
  17. package/tests/agent_board_fk_lock_edges.test.sql +3 -2
  18. package/tests/agent_board_gatenull_membstate.test.sql +7 -4
  19. package/tests/agent_board_grant_target_role.test.sql +4 -4
  20. package/tests/agent_board_hosted_delegates.test.sql +5 -3
  21. package/tests/agent_board_invite_no_downgrade.test.sql +5 -3
  22. package/tests/agent_board_ledger_authority.test.sql +7 -0
  23. package/tests/agent_board_policy_correlation.test.sql +189 -0
  24. package/tests/agent_board_request_removed.test.sql +96 -0
  25. package/tests/agent_board_resolution_authority.test.sql +190 -0
  26. package/tests/agent_board_role_guard.test.sql +319 -0
  27. package/tests/agent_board_rolereset.test.sql +17 -27
  28. package/tests/agent_board_roomdeleg.test.sql +8 -0
  29. package/tests/agent_board_roomown.test.sql +3 -1
  30. package/tests/agent_board_rowid.test.sql +4 -1
  31. package/tests/agent_board_session_provenance.test.sql +106 -0
  32. package/tests/catalog/function_execute_privileges.json +11 -2
  33. package/tests/catalog/p_metadata_parameters.json +4 -0
  34. package/tests/isolation/expected/consent_approval_lock.out +1 -1
  35. package/tests/isolation/expected/last_owner_departure.out +562 -0
  36. package/tests/isolation/specs/atomic_fleet_authority_races.spec +8 -3
  37. package/tests/isolation/specs/atomic_fleet_binding_revoke.spec +0 -3
  38. package/tests/isolation/specs/atomic_fleet_board_archive.spec +0 -3
  39. package/tests/isolation/specs/atomic_fleet_human_fresh_revoke.spec +0 -3
  40. package/tests/isolation/specs/atomic_fleet_identity_disposition.spec +0 -3
  41. package/tests/isolation/specs/atomic_fleet_lifecycle_races.spec +0 -3
  42. package/tests/isolation/specs/atomic_fleet_subtree_lock_order.spec +0 -3
  43. package/tests/isolation/specs/ceiling_setter_lock_before_upsert.spec +0 -3
  44. package/tests/isolation/specs/claimpolicy_acquire_revert_race.spec +0 -2
  45. package/tests/isolation/specs/claimpolicy_board_scope.spec +0 -2
  46. package/tests/isolation/specs/claimpolicy_claimrow_lock_order.spec +0 -2
  47. package/tests/isolation/specs/claimpolicy_isolation_refusal.spec +0 -2
  48. package/tests/isolation/specs/claimpolicy_renew_revert_race.spec +0 -2
  49. package/tests/isolation/specs/claimpolicy_writer_keyshare.spec +0 -2
  50. package/tests/isolation/specs/consent_approval_lock.spec +13 -8
  51. package/tests/isolation/specs/consent_emit_actual_state.spec +0 -1
  52. package/tests/isolation/specs/grant_target_role_race.spec +0 -1
  53. package/tests/isolation/specs/hosted_delegate_add_tombstone_race.spec +0 -1
  54. package/tests/isolation/specs/hosted_delegate_tombstone_revoke_race.spec +0 -1
  55. package/tests/isolation/specs/hosted_delegate_withdraw_evict_race.spec +0 -1
  56. package/tests/isolation/specs/last_owner_departure.spec +137 -0
  57. package/tests/isolation/specs/ledger_authority_revoke.spec +0 -3
  58. package/tests/isolation/specs/onboarding_ceiling_lock_order.spec +0 -3
  59. package/tests/isolation/specs/outbox_wake_ordering.spec +0 -1
  60. package/tests/isolation/specs/session_identity_links.spec +3 -1
  61. package/tests/isolation/specs/session_identity_tombstone_onboarding.spec +0 -1
  62. package/tests/isolation/specs/signed_grant_onboarding_deadlock.spec +0 -1
  63. package/tests/isolation/specs/signer_lifecycle_revoke.spec +0 -1
@@ -0,0 +1,562 @@
1
+ Parsed test spec with 3 sessions
2
+
3
+ starting permutation: a_begin a_leave b_begin b_leave a_commit b_commit owners
4
+ step a_begin:
5
+ begin;
6
+ set local role authenticated;
7
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000001')::text,true) is not null as authenticated;
8
+
9
+ authenticated
10
+ -------------
11
+ t
12
+ (1 row)
13
+
14
+ step a_leave:
15
+ select membership_state from agent_board.leave_board(
16
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000001');
17
+
18
+ membership_state
19
+ ----------------
20
+ left
21
+ (1 row)
22
+
23
+ step b_begin:
24
+ begin;
25
+ set local role authenticated;
26
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000002')::text,true) is not null as authenticated;
27
+
28
+ authenticated
29
+ -------------
30
+ t
31
+ (1 row)
32
+
33
+ step b_leave:
34
+ select membership_state from agent_board.leave_board(
35
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000002');
36
+ <waiting ...>
37
+ step a_commit: commit;
38
+ step b_leave: <... completed>
39
+ ERROR: last_active_board_owner: cannot remove the last active owner
40
+ step b_commit: commit;
41
+ step owners:
42
+ select count(*) as active_owners from agent_board.board_memberships
43
+ where board_id='67520000-0000-4000-8000-000000000099'
44
+ and role='owner' and membership_state in ('joined','subscribed');
45
+
46
+ active_owners
47
+ -------------
48
+ 1
49
+ (1 row)
50
+
51
+
52
+ starting permutation: b_begin b_leave a_begin a_leave b_commit a_commit owners
53
+ step b_begin:
54
+ begin;
55
+ set local role authenticated;
56
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000002')::text,true) is not null as authenticated;
57
+
58
+ authenticated
59
+ -------------
60
+ t
61
+ (1 row)
62
+
63
+ step b_leave:
64
+ select membership_state from agent_board.leave_board(
65
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000002');
66
+
67
+ membership_state
68
+ ----------------
69
+ left
70
+ (1 row)
71
+
72
+ step a_begin:
73
+ begin;
74
+ set local role authenticated;
75
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000001')::text,true) is not null as authenticated;
76
+
77
+ authenticated
78
+ -------------
79
+ t
80
+ (1 row)
81
+
82
+ step a_leave:
83
+ select membership_state from agent_board.leave_board(
84
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000001');
85
+ <waiting ...>
86
+ step b_commit: commit;
87
+ step a_leave: <... completed>
88
+ ERROR: last_active_board_owner: cannot remove the last active owner
89
+ step a_commit: commit;
90
+ step owners:
91
+ select count(*) as active_owners from agent_board.board_memberships
92
+ where board_id='67520000-0000-4000-8000-000000000099'
93
+ and role='owner' and membership_state in ('joined','subscribed');
94
+
95
+ active_owners
96
+ -------------
97
+ 1
98
+ (1 row)
99
+
100
+
101
+ starting permutation: a_begin a_demote b_begin b_demote a_commit b_commit owners
102
+ step a_begin:
103
+ begin;
104
+ set local role authenticated;
105
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000001')::text,true) is not null as authenticated;
106
+
107
+ authenticated
108
+ -------------
109
+ t
110
+ (1 row)
111
+
112
+ step a_demote:
113
+ select role from agent_board.grant_board_role(
114
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000001','member');
115
+
116
+ role
117
+ ------
118
+ member
119
+ (1 row)
120
+
121
+ step b_begin:
122
+ begin;
123
+ set local role authenticated;
124
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000002')::text,true) is not null as authenticated;
125
+
126
+ authenticated
127
+ -------------
128
+ t
129
+ (1 row)
130
+
131
+ step b_demote:
132
+ select role from agent_board.grant_board_role(
133
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000002','member');
134
+ <waiting ...>
135
+ step a_commit: commit;
136
+ step b_demote: <... completed>
137
+ ERROR: last_active_board_owner: cannot remove the last active owner
138
+ step b_commit: commit;
139
+ step owners:
140
+ select count(*) as active_owners from agent_board.board_memberships
141
+ where board_id='67520000-0000-4000-8000-000000000099'
142
+ and role='owner' and membership_state in ('joined','subscribed');
143
+
144
+ active_owners
145
+ -------------
146
+ 1
147
+ (1 row)
148
+
149
+
150
+ starting permutation: b_begin b_demote a_begin a_demote b_commit a_commit owners
151
+ step b_begin:
152
+ begin;
153
+ set local role authenticated;
154
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000002')::text,true) is not null as authenticated;
155
+
156
+ authenticated
157
+ -------------
158
+ t
159
+ (1 row)
160
+
161
+ step b_demote:
162
+ select role from agent_board.grant_board_role(
163
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000002','member');
164
+
165
+ role
166
+ ------
167
+ member
168
+ (1 row)
169
+
170
+ step a_begin:
171
+ begin;
172
+ set local role authenticated;
173
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000001')::text,true) is not null as authenticated;
174
+
175
+ authenticated
176
+ -------------
177
+ t
178
+ (1 row)
179
+
180
+ step a_demote:
181
+ select role from agent_board.grant_board_role(
182
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000001','member');
183
+ <waiting ...>
184
+ step b_commit: commit;
185
+ step a_demote: <... completed>
186
+ ERROR: last_active_board_owner: cannot remove the last active owner
187
+ step a_commit: commit;
188
+ step owners:
189
+ select count(*) as active_owners from agent_board.board_memberships
190
+ where board_id='67520000-0000-4000-8000-000000000099'
191
+ and role='owner' and membership_state in ('joined','subscribed');
192
+
193
+ active_owners
194
+ -------------
195
+ 1
196
+ (1 row)
197
+
198
+
199
+ starting permutation: a_begin a_leave b_begin b_demote a_commit b_commit owners
200
+ step a_begin:
201
+ begin;
202
+ set local role authenticated;
203
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000001')::text,true) is not null as authenticated;
204
+
205
+ authenticated
206
+ -------------
207
+ t
208
+ (1 row)
209
+
210
+ step a_leave:
211
+ select membership_state from agent_board.leave_board(
212
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000001');
213
+
214
+ membership_state
215
+ ----------------
216
+ left
217
+ (1 row)
218
+
219
+ step b_begin:
220
+ begin;
221
+ set local role authenticated;
222
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000002')::text,true) is not null as authenticated;
223
+
224
+ authenticated
225
+ -------------
226
+ t
227
+ (1 row)
228
+
229
+ step b_demote:
230
+ select role from agent_board.grant_board_role(
231
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000002','member');
232
+ <waiting ...>
233
+ step a_commit: commit;
234
+ step b_demote: <... completed>
235
+ ERROR: last_active_board_owner: cannot remove the last active owner
236
+ step b_commit: commit;
237
+ step owners:
238
+ select count(*) as active_owners from agent_board.board_memberships
239
+ where board_id='67520000-0000-4000-8000-000000000099'
240
+ and role='owner' and membership_state in ('joined','subscribed');
241
+
242
+ active_owners
243
+ -------------
244
+ 1
245
+ (1 row)
246
+
247
+
248
+ starting permutation: b_begin b_demote a_begin a_leave b_commit a_commit owners
249
+ step b_begin:
250
+ begin;
251
+ set local role authenticated;
252
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000002')::text,true) is not null as authenticated;
253
+
254
+ authenticated
255
+ -------------
256
+ t
257
+ (1 row)
258
+
259
+ step b_demote:
260
+ select role from agent_board.grant_board_role(
261
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000002','member');
262
+
263
+ role
264
+ ------
265
+ member
266
+ (1 row)
267
+
268
+ step a_begin:
269
+ begin;
270
+ set local role authenticated;
271
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000001')::text,true) is not null as authenticated;
272
+
273
+ authenticated
274
+ -------------
275
+ t
276
+ (1 row)
277
+
278
+ step a_leave:
279
+ select membership_state from agent_board.leave_board(
280
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000001');
281
+ <waiting ...>
282
+ step b_commit: commit;
283
+ step a_leave: <... completed>
284
+ ERROR: last_active_board_owner: cannot remove the last active owner
285
+ step a_commit: commit;
286
+ step owners:
287
+ select count(*) as active_owners from agent_board.board_memberships
288
+ where board_id='67520000-0000-4000-8000-000000000099'
289
+ and role='owner' and membership_state in ('joined','subscribed');
290
+
291
+ active_owners
292
+ -------------
293
+ 1
294
+ (1 row)
295
+
296
+
297
+ starting permutation: a_begin a_raw b_begin b_raw a_commit b_commit owners
298
+ step a_begin:
299
+ begin;
300
+ set local role authenticated;
301
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000001')::text,true) is not null as authenticated;
302
+
303
+ authenticated
304
+ -------------
305
+ t
306
+ (1 row)
307
+
308
+ step a_raw:
309
+ reset role;
310
+ select agent_board._lock_board_authority_ceiling('67520000-0000-4000-8000-000000000099');
311
+ update agent_board.board_memberships set membership_state='left',left_at=now()
312
+ where board_id='67520000-0000-4000-8000-000000000099'
313
+ and agent_id='67510000-0000-4000-8000-000000000001';
314
+
315
+ _lock_board_authority_ceiling
316
+ -----------------------------
317
+
318
+ (1 row)
319
+
320
+ step b_begin:
321
+ begin;
322
+ set local role authenticated;
323
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000002')::text,true) is not null as authenticated;
324
+
325
+ authenticated
326
+ -------------
327
+ t
328
+ (1 row)
329
+
330
+ step b_raw:
331
+ reset role;
332
+ delete from agent_board.board_memberships
333
+ where board_id='67520000-0000-4000-8000-000000000099'
334
+ and agent_id='67510000-0000-4000-8000-000000000002';
335
+
336
+ ERROR: last_active_board_owner: acquire board authority lock before owner transition
337
+ step a_commit: commit;
338
+ step b_commit: commit;
339
+ step owners:
340
+ select count(*) as active_owners from agent_board.board_memberships
341
+ where board_id='67520000-0000-4000-8000-000000000099'
342
+ and role='owner' and membership_state in ('joined','subscribed');
343
+
344
+ active_owners
345
+ -------------
346
+ 1
347
+ (1 row)
348
+
349
+
350
+ starting permutation: b_begin b_lock b_raw a_begin a_raw b_commit a_commit owners
351
+ step b_begin:
352
+ begin;
353
+ set local role authenticated;
354
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000002')::text,true) is not null as authenticated;
355
+
356
+ authenticated
357
+ -------------
358
+ t
359
+ (1 row)
360
+
361
+ step b_lock:
362
+ reset role;
363
+ select agent_board._lock_board_authority_ceiling('67520000-0000-4000-8000-000000000099');
364
+
365
+ _lock_board_authority_ceiling
366
+ -----------------------------
367
+
368
+ (1 row)
369
+
370
+ step b_raw:
371
+ reset role;
372
+ delete from agent_board.board_memberships
373
+ where board_id='67520000-0000-4000-8000-000000000099'
374
+ and agent_id='67510000-0000-4000-8000-000000000002';
375
+
376
+ step a_begin:
377
+ begin;
378
+ set local role authenticated;
379
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000001')::text,true) is not null as authenticated;
380
+
381
+ authenticated
382
+ -------------
383
+ t
384
+ (1 row)
385
+
386
+ step a_raw:
387
+ reset role;
388
+ select agent_board._lock_board_authority_ceiling('67520000-0000-4000-8000-000000000099');
389
+ update agent_board.board_memberships set membership_state='left',left_at=now()
390
+ where board_id='67520000-0000-4000-8000-000000000099'
391
+ and agent_id='67510000-0000-4000-8000-000000000001';
392
+ <waiting ...>
393
+ step b_commit: commit;
394
+ step a_raw: <... completed>
395
+ _lock_board_authority_ceiling
396
+ -----------------------------
397
+
398
+ (1 row)
399
+
400
+ ERROR: last_active_board_owner: cannot remove the last active owner
401
+ step a_commit: commit;
402
+ step owners:
403
+ select count(*) as active_owners from agent_board.board_memberships
404
+ where board_id='67520000-0000-4000-8000-000000000099'
405
+ and role='owner' and membership_state in ('joined','subscribed');
406
+
407
+ active_owners
408
+ -------------
409
+ 1
410
+ (1 row)
411
+
412
+
413
+ starting permutation: a_repeatable a_leave_code a_commit owners
414
+ step a_repeatable:
415
+ begin isolation level repeatable read;
416
+ set local role authenticated;
417
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000001')::text,true) is not null as authenticated;
418
+
419
+ authenticated
420
+ -------------
421
+ t
422
+ (1 row)
423
+
424
+ step a_leave_code:
425
+ select public.roleguard_isolation_refusal($probe$
426
+ select agent_board.leave_board(
427
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000001')
428
+ $probe$) as error_code;
429
+
430
+ error_code
431
+ ----------
432
+ 25001
433
+ (1 row)
434
+
435
+ step a_commit: commit;
436
+ step owners:
437
+ select count(*) as active_owners from agent_board.board_memberships
438
+ where board_id='67520000-0000-4000-8000-000000000099'
439
+ and role='owner' and membership_state in ('joined','subscribed');
440
+
441
+ active_owners
442
+ -------------
443
+ 2
444
+ (1 row)
445
+
446
+
447
+ starting permutation: a_session_begin a_session_leave a_session_unlock b_begin b_leave a_commit b_commit owners
448
+ step a_session_begin:
449
+ begin;
450
+ select pg_advisory_lock(hashtextextended(
451
+ 'agent_board.board_authority_ceilings:67520000-0000-4000-8000-000000000099',0));
452
+
453
+ pg_advisory_lock
454
+ ----------------
455
+
456
+ (1 row)
457
+
458
+ step a_session_leave:
459
+ update agent_board.board_memberships set membership_state='left',left_at=now()
460
+ where board_id='67520000-0000-4000-8000-000000000099'
461
+ and agent_id='67510000-0000-4000-8000-000000000001';
462
+
463
+ step a_session_unlock:
464
+ select pg_advisory_unlock(hashtextextended(
465
+ 'agent_board.board_authority_ceilings:67520000-0000-4000-8000-000000000099',0));
466
+
467
+ pg_advisory_unlock
468
+ ------------------
469
+ t
470
+ (1 row)
471
+
472
+ step b_begin:
473
+ begin;
474
+ set local role authenticated;
475
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000002')::text,true) is not null as authenticated;
476
+
477
+ authenticated
478
+ -------------
479
+ t
480
+ (1 row)
481
+
482
+ step b_leave:
483
+ select membership_state from agent_board.leave_board(
484
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000002');
485
+ <waiting ...>
486
+ step a_commit: commit;
487
+ step b_leave: <... completed>
488
+ ERROR: last_active_board_owner: cannot remove the last active owner
489
+ step b_commit: commit;
490
+ step owners:
491
+ select count(*) as active_owners from agent_board.board_memberships
492
+ where board_id='67520000-0000-4000-8000-000000000099'
493
+ and role='owner' and membership_state in ('joined','subscribed');
494
+
495
+ active_owners
496
+ -------------
497
+ 1
498
+ (1 row)
499
+
500
+
501
+ starting permutation: a_repeatable a_snapshot b_begin b_leave a_leave_code b_commit a_commit owners
502
+ step a_repeatable:
503
+ begin isolation level repeatable read;
504
+ set local role authenticated;
505
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000001')::text,true) is not null as authenticated;
506
+
507
+ authenticated
508
+ -------------
509
+ t
510
+ (1 row)
511
+
512
+ step a_snapshot:
513
+ select count(*) as snapshot_owners from agent_board.board_memberships where board_id='67520000-0000-4000-8000-000000000099' and role='owner' and membership_state in ('joined','subscribed');
514
+
515
+ snapshot_owners
516
+ ---------------
517
+ 1
518
+ (1 row)
519
+
520
+ step b_begin:
521
+ begin;
522
+ set local role authenticated;
523
+ select set_config('request.jwt.claims', json_build_object('role','authenticated','sub','67500000-0000-0000-0000-000000000002')::text,true) is not null as authenticated;
524
+
525
+ authenticated
526
+ -------------
527
+ t
528
+ (1 row)
529
+
530
+ step b_leave:
531
+ select membership_state from agent_board.leave_board(
532
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000002');
533
+
534
+ membership_state
535
+ ----------------
536
+ left
537
+ (1 row)
538
+
539
+ step a_leave_code:
540
+ select public.roleguard_isolation_refusal($probe$
541
+ select agent_board.leave_board(
542
+ '67520000-0000-4000-8000-000000000099','67510000-0000-4000-8000-000000000001')
543
+ $probe$) as error_code;
544
+ <waiting ...>
545
+ step b_commit: commit;
546
+ step a_leave_code: <... completed>
547
+ error_code
548
+ ----------
549
+ 25001
550
+ (1 row)
551
+
552
+ step a_commit: commit;
553
+ step owners:
554
+ select count(*) as active_owners from agent_board.board_memberships
555
+ where board_id='67520000-0000-4000-8000-000000000099'
556
+ and role='owner' and membership_state in ('joined','subscribed');
557
+
558
+ active_owners
559
+ -------------
560
+ 1
561
+ (1 row)
562
+
@@ -49,6 +49,10 @@ setup
49
49
  values ('16250000-0000-0000-0000-000000000001', 'agent', 'agent',
50
50
  'atomic-authority-owner', 'Atomic Authority Owner', 'active',
51
51
  '16250000-0000-0000-0000-0000000000a1');
52
+ -- ROLEGUARD: isolate creator authority loss while another owner preserves the board.
53
+ insert into agent_board.agents(id, agent_type, kind, handle, display_name, status)
54
+ values ('16250000-0000-0000-0000-000000000004', 'agent', 'agent',
55
+ 'atomic-authority-coowner', 'Atomic Authority Coowner', 'active');
52
56
 
53
57
  select count(*) from agent_board.create_board(
54
58
  '16250000-0000-0000-0000-000000000001',
@@ -56,6 +60,9 @@ setup
56
60
  'Consiliency/message-board#162 authority isolation proof',
57
61
  jsonb_build_object(), 'private'
58
62
  );
63
+ insert into agent_board.board_memberships(board_id, agent_id, role, membership_state)
64
+ values ((select id from agent_board.boards where slug='atomic-authority-board'),
65
+ '16250000-0000-0000-0000-000000000004', 'owner', 'joined');
59
66
  insert into agent_board.fleet_trust_domains(
60
67
  id, slug, display_name, domain_kind, owner_agent_id, lifecycle_state, approved_at
61
68
  ) values (
@@ -120,9 +127,6 @@ teardown
120
127
  delete from agent_board.board_authority_ceilings where board_id in (
121
128
  select id from agent_board.boards where slug='atomic-authority-board'
122
129
  );
123
- delete from agent_board.board_memberships where board_id in (
124
- select id from agent_board.boards where slug='atomic-authority-board'
125
- );
126
130
  delete from agent_board.enrollment_federation_audit where agent_id in (
127
131
  select id from agent_board.agents where handle='atomic-authority-agent'
128
132
  );
@@ -134,6 +138,7 @@ teardown
134
138
  delete from agent_board.fleet_machines where id='16250000-0000-0000-0000-000000000003';
135
139
  delete from agent_board.fleet_trust_domains where id='16250000-0000-0000-0000-000000000002';
136
140
  delete from agent_board.agents where id='16250000-0000-0000-0000-000000000001';
141
+ delete from agent_board.agents where id='16250000-0000-0000-0000-000000000004';
137
142
  delete from auth.users where id='16250000-0000-0000-0000-0000000000a1';
138
143
  delete from agent_board.identity_providers where issuer='https://atomic-authority.test';
139
144
  }
@@ -70,9 +70,6 @@ teardown
70
70
  );
71
71
  truncate agent_board.fleet_onboarding_invite_bounds;
72
72
  delete from agent_board.board_invite_tokens where created_by_agent_id='16230000-0000-0000-0000-000000000001';
73
- delete from agent_board.board_memberships where board_id in (
74
- select id from agent_board.boards where slug='atomic-binding-board'
75
- );
76
73
  delete from agent_board.enrollment_federation_audit where agent_id in (
77
74
  select id from agent_board.agents where handle='atomic-binding-agent'
78
75
  );
@@ -70,9 +70,6 @@ teardown
70
70
  );
71
71
  truncate agent_board.fleet_onboarding_invite_bounds;
72
72
  delete from agent_board.board_invite_tokens where created_by_agent_id='16290000-0000-0000-0000-000000000001';
73
- delete from agent_board.board_memberships where board_id in (
74
- select id from agent_board.boards where slug='atomic-archive-board'
75
- );
76
73
  delete from agent_board.enrollment_federation_audit where issuer='https://atomic-archive.test';
77
74
  delete from agent_board.agent_signing_keys where agent_id in (
78
75
  select id from agent_board.agents where handle='atomic-archive-agent'
@@ -68,9 +68,6 @@ teardown
68
68
  );
69
69
  truncate agent_board.fleet_onboarding_invite_bounds;
70
70
  delete from agent_board.board_invite_tokens where created_by_agent_id='16280000-0000-0000-0000-000000000001';
71
- delete from agent_board.board_memberships where board_id in (
72
- select id from agent_board.boards where slug='atomic-human-board'
73
- );
74
71
  delete from agent_board.enrollment_federation_audit where issuer='https://atomic-human.test';
75
72
  delete from agent_board.agent_signing_keys where agent_id in (
76
73
  select id from agent_board.agents where handle in ('atomic-human-existing','atomic-human-fresh')
@@ -57,9 +57,6 @@ teardown
57
57
  );
58
58
  truncate agent_board.fleet_onboarding_invite_bounds;
59
59
  delete from agent_board.board_invite_tokens where created_by_agent_id='16260000-0000-0000-0000-000000000001';
60
- delete from agent_board.board_memberships where board_id in (
61
- select id from agent_board.boards where slug='atomic-disposition-board'
62
- );
63
60
  delete from agent_board.enrollment_federation_audit where issuer='https://atomic-disposition.test';
64
61
  delete from agent_board.agent_signing_keys where agent_id in (
65
62
  select id from agent_board.agents where handle='atomic-disposition-agent'
@@ -83,9 +83,6 @@ teardown
83
83
  );
84
84
  truncate agent_board.fleet_onboarding_invite_bounds;
85
85
  delete from agent_board.board_invite_tokens where created_by_agent_id='16240000-0000-0000-0000-000000000001';
86
- delete from agent_board.board_memberships where board_id in (
87
- select id from agent_board.boards where slug='atomic-lifecycle-board'
88
- );
89
86
  delete from agent_board.enrollment_federation_audit where agent_id in (
90
87
  select id from agent_board.agents where handle='atomic-lifecycle-agent'
91
88
  );
@@ -81,9 +81,6 @@ teardown
81
81
  );
82
82
  truncate agent_board.fleet_onboarding_invite_bounds;
83
83
  delete from agent_board.board_invite_tokens where created_by_agent_id='ffffffff-ffff-ffff-ffff-ffffffffff01';
84
- delete from agent_board.board_memberships where board_id in (
85
- select id from agent_board.boards where slug='atomic-subtree-board'
86
- );
87
84
  delete from agent_board.enrollment_federation_audit where issuer='https://atomic-subtree.test';
88
85
  delete from agent_board.agent_signing_keys where agent_id in (
89
86
  select id from agent_board.agents where handle='atomic-subtree-agent'
@@ -53,9 +53,6 @@ teardown
53
53
  delete from agent_board.board_authority_ceilings where board_id in (
54
54
  select id from agent_board.boards where slug='ceiling-order-board'
55
55
  );
56
- delete from agent_board.board_memberships where board_id in (
57
- select id from agent_board.boards where slug='ceiling-order-board'
58
- );
59
56
  delete from agent_board.boards where slug='ceiling-order-board';
60
57
  delete from agent_board.agents where id='19600000-0000-0000-0000-000000000001';
61
58
  delete from auth.users where id='19600000-0000-0000-0000-0000000000a1';
@@ -68,8 +68,6 @@ teardown
68
68
  delete from agent_board.threads where id = '40500000-0000-4000-8000-000000000010';
69
69
  delete from agent_board.board_membership_events where board_id in (
70
70
  select id from agent_board.boards where slug = 'cpr-acq-board');
71
- delete from agent_board.board_memberships where board_id in (
72
- select id from agent_board.boards where slug = 'cpr-acq-board');
73
71
  delete from agent_board.boards where slug = 'cpr-acq-board';
74
72
  delete from agent_board.agents where id = '40500000-0000-4000-8000-000000000001';
75
73
  delete from auth.users where id = '40500000-0000-4000-8000-0000000000a1';
@@ -60,8 +60,6 @@ teardown
60
60
  '40500000-0000-4000-8000-000000000042');
61
61
  delete from agent_board.board_membership_events where board_id in (
62
62
  select id from agent_board.boards where slug in ('cpr-scope-b1', 'cpr-scope-b2'));
63
- delete from agent_board.board_memberships where board_id in (
64
- select id from agent_board.boards where slug in ('cpr-scope-b1', 'cpr-scope-b2'));
65
63
  delete from agent_board.boards where slug in ('cpr-scope-b1', 'cpr-scope-b2');
66
64
  delete from agent_board.agents where id = '40500000-0000-4000-8000-000000000003';
67
65
  delete from auth.users where id = '40500000-0000-4000-8000-0000000000c1';