@consiliency/agent-board-schema 1.59.0 → 1.63.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 (73) hide show
  1. package/README.md +80 -0
  2. package/fixtures/already-applied.json +16 -0
  3. package/migrations/20261010000100_agent_board_own_post_not_delivered.sql +637 -0
  4. package/migrations/20261011000100_agent_board_session_identities.sql +1964 -0
  5. package/migrations/20261012000100_agent_board_sidowner.sql +209 -0
  6. package/migrations/20261014000100_agent_board_grant_target_role.sql +218 -0
  7. package/package.json +1 -1
  8. package/schema-manifest.json +39 -3
  9. package/src/tooling.test.mjs +9 -2
  10. package/tests/agent_board_addressing.test.sql +3 -1
  11. package/tests/agent_board_atomic_fleet_onboarding.test.sql +13 -4
  12. package/tests/agent_board_consent_emission.test.sql +30 -11
  13. package/tests/agent_board_consent_gating.test.sql +16 -2
  14. package/tests/agent_board_delegate_role_class.test.sql +1 -1
  15. package/tests/agent_board_delegation_cap_ceiling.test.sql +26 -15
  16. package/tests/agent_board_delegation_enforcement.test.sql +1 -1
  17. package/tests/agent_board_enroll_resumption.test.sql +22 -4
  18. package/tests/agent_board_enroll_token_single_use.test.sql +18 -3
  19. package/tests/agent_board_federated_lock_order_class.test.sql +2 -2
  20. package/tests/agent_board_fk_lock_edges.test.sql +74 -14
  21. package/tests/agent_board_grant_target_role.test.sql +1118 -0
  22. package/tests/agent_board_inbox_rpcs.test.sql +5 -2
  23. package/tests/agent_board_invite_no_downgrade.test.sql +10 -8
  24. package/tests/agent_board_ledger_authority.test.sql +70 -12
  25. package/tests/agent_board_membership_current_row_class.test.sql +9 -1
  26. package/tests/agent_board_mint_fleet_agent_session.test.sql +2 -2
  27. package/tests/agent_board_mint_harden.test.sql +38 -27
  28. package/tests/agent_board_own_post_not_delivered.test.sql +490 -0
  29. package/tests/agent_board_rolereset.test.sql +8 -2
  30. package/tests/agent_board_roomdeleg_lane_b.test.sql +6 -6
  31. package/tests/agent_board_rowid.test.sql +3 -1
  32. package/tests/agent_board_session_identity_approval_revocation.test.sql +334 -0
  33. package/tests/agent_board_session_identity_backfill.test.sql +82 -0
  34. package/tests/agent_board_session_identity_backfill_refusal.test.sql +14 -0
  35. package/tests/agent_board_session_identity_behavior_classes.test.sql +176 -0
  36. package/tests/agent_board_session_identity_class.test.sql +118 -0
  37. package/tests/agent_board_session_identity_fingerprint.test.sql +271 -0
  38. package/tests/agent_board_session_identity_labels_limits.test.sql +205 -0
  39. package/tests/agent_board_session_identity_lease.test.sql +235 -0
  40. package/tests/agent_board_session_identity_lifetime.test.sql +230 -0
  41. package/tests/agent_board_session_identity_limits.test.sql +208 -0
  42. package/tests/agent_board_session_identity_lineage.test.sql +64 -0
  43. package/tests/agent_board_session_identity_link.test.sql +201 -0
  44. package/tests/agent_board_session_identity_mint.test.sql +233 -0
  45. package/tests/agent_board_session_identity_panel_r1.test.sql +194 -0
  46. package/tests/agent_board_session_identity_panel_r2.test.sql +174 -0
  47. package/tests/agent_board_session_identity_protected_actions.test.sql +156 -0
  48. package/tests/agent_board_session_identity_revoke_closure.test.sql +131 -0
  49. package/tests/agent_board_sidowner_leases.test.sql +107 -0
  50. package/tests/agent_board_sidowner_owner_required.test.sql +97 -0
  51. package/tests/agent_board_sidowner_read_class.test.sql +171 -0
  52. package/tests/agent_board_sidowner_reads.test.sql +136 -0
  53. package/tests/agent_board_signer_lifecycle.test.sql +26 -4
  54. package/tests/agent_board_signing_challenge_pending_cap.test.sql +1 -1
  55. package/tests/agent_board_v2_invariants.test.sql +4 -4
  56. package/tests/agent_board_write_enforcement_class.test.sql +74 -15
  57. package/tests/catalog/function_execute_privileges.json +218 -2
  58. package/tests/catalog/p_metadata_parameters.json +98 -2
  59. package/tests/isolation/expected/grant_target_role_race.out +348 -0
  60. package/tests/isolation/expected/session_identity_limits.out +165 -0
  61. package/tests/isolation/expected/session_identity_links.out +235 -0
  62. package/tests/isolation/expected/session_identity_reclaim.out +253 -0
  63. package/tests/isolation/expected/session_identity_renew_revoke.out +115 -0
  64. package/tests/isolation/expected/session_identity_renew_revoke_key_gate.out +138 -0
  65. package/tests/isolation/expected/session_identity_tombstone_onboarding.out +247 -0
  66. package/tests/isolation/specs/grant_target_role_race.spec +207 -0
  67. package/tests/isolation/specs/session_identity_limits.spec +81 -0
  68. package/tests/isolation/specs/session_identity_links.spec +80 -0
  69. package/tests/isolation/specs/session_identity_reclaim.spec +125 -0
  70. package/tests/isolation/specs/session_identity_renew_revoke.spec +84 -0
  71. package/tests/isolation/specs/session_identity_renew_revoke_key_gate.spec +94 -0
  72. package/tests/isolation/specs/session_identity_tombstone_onboarding.spec +108 -0
  73. package/tests/seeds/20261011000100_agent_board_session_identities.sql.pre.sql +47 -0
@@ -249,6 +249,10 @@
249
249
  "signature": "_mint_agent_refresh_token()",
250
250
  "declares_p_metadata": false
251
251
  },
252
+ {
253
+ "signature": "_mint_fleet_agent_session_legacy(p_challenge_id uuid, p_nonce text, p_signing_key_id uuid, p_agent_id uuid, p_max_ttl_seconds integer)",
254
+ "declares_p_metadata": false
255
+ },
252
256
  {
253
257
  "signature": "_next_callback_attempt_number(p_outbox_event_id uuid)",
254
258
  "declares_p_metadata": false
@@ -345,6 +349,10 @@
345
349
  "signature": "_revoke_agent_principal(p_agent_id uuid, p_revoked_by_agent_id uuid, p_reason text)",
346
350
  "declares_p_metadata": false
347
351
  },
352
+ {
353
+ "signature": "_revoke_session_identity_family(p_agent_id uuid, p_actor uuid, p_reason text)",
354
+ "declares_p_metadata": false
355
+ },
348
356
  {
349
357
  "signature": "_role_rank(p_role text)",
350
358
  "declares_p_metadata": false
@@ -353,6 +361,50 @@
353
361
  "signature": "_send_fleet_scope_mode(p_scope_key text)",
354
362
  "declares_p_metadata": false
355
363
  },
364
+ {
365
+ "signature": "_session_identity_agent_lineage()",
366
+ "declares_p_metadata": false
367
+ },
368
+ {
369
+ "signature": "_session_identity_ancestor_actor(p_identity_agent_id uuid)",
370
+ "declares_p_metadata": false
371
+ },
372
+ {
373
+ "signature": "_session_identity_ancestor_ceiling(p_agent_id uuid)",
374
+ "declares_p_metadata": false
375
+ },
376
+ {
377
+ "signature": "_session_identity_check_limits(p_root uuid, p_parent uuid, p_reactivation uuid)",
378
+ "declares_p_metadata": false
379
+ },
380
+ {
381
+ "signature": "_session_identity_has_human_owner(p_root_agent_id uuid)",
382
+ "declares_p_metadata": false
383
+ },
384
+ {
385
+ "signature": "_session_identity_kind_immutable()",
386
+ "declares_p_metadata": false
387
+ },
388
+ {
389
+ "signature": "_session_identity_lease_live(p_identity uuid)",
390
+ "declares_p_metadata": false
391
+ },
392
+ {
393
+ "signature": "_session_identity_lineage()",
394
+ "declares_p_metadata": false
395
+ },
396
+ {
397
+ "signature": "_session_identity_owner(p_identity_agent_id uuid)",
398
+ "declares_p_metadata": false
399
+ },
400
+ {
401
+ "signature": "_session_identity_read_allowed(p_identity_agent_id uuid)",
402
+ "declares_p_metadata": false
403
+ },
404
+ {
405
+ "signature": "_session_identity_revocation_actor(p_identity_agent_id uuid)",
406
+ "declares_p_metadata": false
407
+ },
356
408
  {
357
409
  "signature": "_signed_write_actor_id(p_payload jsonb, p_gateway_decision jsonb, p_actor_field text)",
358
410
  "declares_p_metadata": false
@@ -393,6 +445,10 @@
393
445
  "signature": "append_task_event(p_task_id uuid, p_actor_agent_id uuid, p_event_type text, p_payload jsonb, p_status text, p_assigned_agent_id uuid, p_completed_at timestamp with time zone)",
394
446
  "declares_p_metadata": false
395
447
  },
448
+ {
449
+ "signature": "approve_identity_state(p_identity_agent_id uuid, p_risky_digest text, p_recorded_fingerprint jsonb)",
450
+ "declares_p_metadata": false
451
+ },
396
452
  {
397
453
  "signature": "block_board_inviter(p_board_id uuid, p_inviter_agent_id uuid, p_target_agent_id uuid, p_metadata jsonb)",
398
454
  "declares_p_metadata": true
@@ -493,6 +549,10 @@
493
549
  "signature": "get_schema_version()",
494
550
  "declares_p_metadata": false
495
551
  },
552
+ {
553
+ "signature": "get_session_identity_state(p_identity_agent_id uuid)",
554
+ "declares_p_metadata": false
555
+ },
496
556
  {
497
557
  "signature": "grant_board_role(p_board_id uuid, p_agent_id uuid, p_grantee_role text, p_grantor_agent_id uuid)",
498
558
  "declares_p_metadata": false
@@ -501,6 +561,10 @@
501
561
  "signature": "heartbeat(p_agent_id uuid, p_thread_id uuid, p_availability text, p_activity_summary text, p_expires_in interval, p_metadata jsonb)",
502
562
  "declares_p_metadata": true
503
563
  },
564
+ {
565
+ "signature": "heartbeat_session_identity(p_identity_agent_id uuid)",
566
+ "declares_p_metadata": false
567
+ },
504
568
  {
505
569
  "signature": "invite_board_for_display(p_code_sha256 text)",
506
570
  "declares_p_metadata": false
@@ -521,6 +585,10 @@
521
585
  "signature": "leave_board(p_board_id uuid, p_agent_id uuid, p_metadata jsonb)",
522
586
  "declares_p_metadata": true
523
587
  },
588
+ {
589
+ "signature": "link_session_alias(p_identity_agent_id uuid, p_identity_lease_epoch text, p_session_id text)",
590
+ "declares_p_metadata": false
591
+ },
524
592
  {
525
593
  "signature": "list_board_members(p_board_id uuid)",
526
594
  "declares_p_metadata": false
@@ -533,6 +601,10 @@
533
601
  "signature": "list_my_board_requests()",
534
602
  "declares_p_metadata": false
535
603
  },
604
+ {
605
+ "signature": "list_session_children(p_parent_agent_id uuid)",
606
+ "declares_p_metadata": false
607
+ },
536
608
  {
537
609
  "signature": "mark_read(p_thread_id uuid, p_agent_id uuid, p_last_read_message_sequence bigint)",
538
610
  "declares_p_metadata": false
@@ -542,11 +614,11 @@
542
614
  "declares_p_metadata": false
543
615
  },
544
616
  {
545
- "signature": "mint_delegated_child(p_root_agent_id uuid, p_child_slug text, p_requested_scopes jsonb, p_child_public_key text, p_ttl interval, p_self_service boolean)",
617
+ "signature": "mint_delegated_child(p_root_agent_id uuid, p_child_slug text, p_requested_scopes jsonb, p_child_public_key text, p_ttl interval, p_self_service boolean, p_session_harness text, p_session_id text, p_minter_lease_epoch text, p_requested_rooms jsonb, p_fingerprint jsonb, p_forked_from uuid)",
546
618
  "declares_p_metadata": false
547
619
  },
548
620
  {
549
- "signature": "mint_fleet_agent_session(p_challenge_id uuid, p_nonce text, p_signing_key_id uuid, p_agent_id uuid, p_max_ttl_seconds integer)",
621
+ "signature": "mint_fleet_agent_session(p_challenge_id uuid, p_nonce text, p_signing_key_id uuid, p_agent_id uuid, p_max_ttl_seconds integer, p_holder_secret text, p_session_id text)",
550
622
  "declares_p_metadata": false
551
623
  },
552
624
  {
@@ -585,6 +657,10 @@
585
657
  "signature": "reactivate_fleet_machine(p_machine_id uuid, p_reactivated_by_agent_id uuid, p_reactivation_reason text)",
586
658
  "declares_p_metadata": false
587
659
  },
660
+ {
661
+ "signature": "readmit_session_identity(p_identity_agent_id uuid, p_child_slug text, p_child_public_key text, p_requested_scopes jsonb, p_requested_rooms jsonb, p_ttl interval)",
662
+ "declares_p_metadata": false
663
+ },
588
664
  {
589
665
  "signature": "reap_expired_enroll_rate_events(p_older_than interval)",
590
666
  "declares_p_metadata": false
@@ -621,6 +697,10 @@
621
697
  "signature": "record_callback_delivery_terminal_failure(p_outbox_event_id uuid, p_endpoint_id uuid, p_http_status integer, p_error_summary text, p_metadata jsonb)",
622
698
  "declares_p_metadata": true
623
699
  },
700
+ {
701
+ "signature": "record_session_identity_state(p_identity_agent_id uuid, p_fingerprint jsonb)",
702
+ "declares_p_metadata": false
703
+ },
624
704
  {
625
705
  "signature": "record_signing_key_proof_result(p_challenge_id uuid, p_agent_id uuid, p_key_id text, p_verified boolean, p_failure_class text, p_metadata jsonb)",
626
706
  "declares_p_metadata": true
@@ -645,6 +725,10 @@
645
725
  "signature": "release_claim(p_lease_token uuid)",
646
726
  "declares_p_metadata": false
647
727
  },
728
+ {
729
+ "signature": "rename_agent(p_agent_id uuid, p_display_name text)",
730
+ "declares_p_metadata": false
731
+ },
648
732
  {
649
733
  "signature": "renew_claim(p_lease_token uuid, p_lease_expires_at timestamp with time zone)",
650
734
  "declares_p_metadata": false
@@ -653,6 +737,10 @@
653
737
  "signature": "renew_delegated_grant(p_child_agent_id uuid, p_extend interval)",
654
738
  "declares_p_metadata": false
655
739
  },
740
+ {
741
+ "signature": "renew_session_identity(p_identity_agent_id uuid, p_risky_digest text)",
742
+ "declares_p_metadata": false
743
+ },
656
744
  {
657
745
  "signature": "request_join_board(p_board_id uuid, p_agent_id uuid, p_metadata jsonb)",
658
746
  "declares_p_metadata": true
@@ -705,6 +793,10 @@
705
793
  "signature": "revoke_invite_link(p_code text, p_metadata jsonb)",
706
794
  "declares_p_metadata": true
707
795
  },
796
+ {
797
+ "signature": "revoke_session_identity(p_identity_agent_id uuid)",
798
+ "declares_p_metadata": false
799
+ },
708
800
  {
709
801
  "signature": "rotate_agent_token(p_agent_id uuid)",
710
802
  "declares_p_metadata": false
@@ -741,6 +833,10 @@
741
833
  "signature": "set_board_claim_policy(p_board_id uuid, p_claim_policy text)",
742
834
  "declares_p_metadata": false
743
835
  },
836
+ {
837
+ "signature": "set_board_member_label(p_board_id uuid, p_agent_id uuid, p_label text)",
838
+ "declares_p_metadata": false
839
+ },
744
840
  {
745
841
  "signature": "set_board_role_gate(p_board_id uuid, p_enforced boolean)",
746
842
  "declares_p_metadata": false
@@ -0,0 +1,348 @@
1
+ Parsed test spec with 7 sessions
2
+
3
+ starting permutation: m_begin m_redeem a_begin a_grant_m_observer m_commit a_rollback check
4
+ count
5
+ -----
6
+ 1
7
+ (1 row)
8
+
9
+ step m_begin:
10
+ BEGIN;
11
+ select set_config('g674.code', (select code from agent_board.board_invite_tokens
12
+ where board_id = '67430000-0000-4000-8000-000000000001' and preset_role = 'admin'), true) is not null as have_code;
13
+ SET LOCAL ROLE authenticated;
14
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
15
+ SET LOCAL "request.jwt.claim.sub" = '67410000-0000-4000-8000-000000000003';
16
+
17
+ have_code
18
+ ---------
19
+ t
20
+ (1 row)
21
+
22
+ step m_redeem: select role, membership_state from agent_board.redeem_invite_link(current_setting('g674.code'));
23
+ role |membership_state
24
+ -----+----------------
25
+ admin|joined
26
+ (1 row)
27
+
28
+ step a_begin:
29
+ BEGIN;
30
+ SET LOCAL ROLE authenticated;
31
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
32
+ SET LOCAL "request.jwt.claim.sub" = '67410000-0000-4000-8000-000000000002';
33
+
34
+ step a_grant_m_observer:
35
+ select role from agent_board.grant_board_role('67430000-0000-4000-8000-000000000001',
36
+ '67420000-0000-4000-8000-000000000003', 'observer');
37
+ <waiting ...>
38
+ step m_commit: COMMIT;
39
+ step a_grant_m_observer: <... completed>
40
+ ERROR: grant requires a higher board role than the target
41
+ step a_rollback: ROLLBACK;
42
+ step check:
43
+ select a.handle, bm.role, bm.membership_state
44
+ from agent_board.board_memberships bm join agent_board.agents a on a.id = bm.agent_id
45
+ where bm.board_id = '67430000-0000-4000-8000-000000000001'
46
+ order by a.handle, bm.membership_state;
47
+
48
+ handle |role |membership_state
49
+ -----------+--------+----------------
50
+ g674-iso-a1|admin |joined
51
+ g674-iso-g |member |joined
52
+ g674-iso-m |admin |joined
53
+ g674-iso-o |owner |joined
54
+ g674-iso-v |observer|joined
55
+ (5 rows)
56
+
57
+
58
+ starting permutation: o_begin o_remove_m a_begin a_grant_m_observer o_commit a_rollback check
59
+ count
60
+ -----
61
+ 1
62
+ (1 row)
63
+
64
+ step o_begin:
65
+ BEGIN;
66
+ SET LOCAL ROLE authenticated;
67
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
68
+ SET LOCAL "request.jwt.claim.sub" = '67410000-0000-4000-8000-000000000001';
69
+
70
+ step o_remove_m:
71
+ select membership_state from agent_board.update_board_membership('67430000-0000-4000-8000-000000000001',
72
+ '67420000-0000-4000-8000-000000000003', 'removed');
73
+
74
+ membership_state
75
+ ----------------
76
+ removed
77
+ (1 row)
78
+
79
+ step a_begin:
80
+ BEGIN;
81
+ SET LOCAL ROLE authenticated;
82
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
83
+ SET LOCAL "request.jwt.claim.sub" = '67410000-0000-4000-8000-000000000002';
84
+
85
+ step a_grant_m_observer:
86
+ select role from agent_board.grant_board_role('67430000-0000-4000-8000-000000000001',
87
+ '67420000-0000-4000-8000-000000000003', 'observer');
88
+ <waiting ...>
89
+ step o_commit: COMMIT;
90
+ step a_grant_m_observer: <... completed>
91
+ ERROR: grantee has no membership on this board
92
+ step a_rollback: ROLLBACK;
93
+ step check:
94
+ select a.handle, bm.role, bm.membership_state
95
+ from agent_board.board_memberships bm join agent_board.agents a on a.id = bm.agent_id
96
+ where bm.board_id = '67430000-0000-4000-8000-000000000001'
97
+ order by a.handle, bm.membership_state;
98
+
99
+ handle |role |membership_state
100
+ -----------+--------+----------------
101
+ g674-iso-a1|admin |joined
102
+ g674-iso-g |member |joined
103
+ g674-iso-m |member |removed
104
+ g674-iso-o |owner |joined
105
+ g674-iso-v |observer|joined
106
+ (5 rows)
107
+
108
+
109
+ starting permutation: o_begin o_demote_a a_begin a_grant_m_observer o_commit a_rollback check
110
+ count
111
+ -----
112
+ 1
113
+ (1 row)
114
+
115
+ step o_begin:
116
+ BEGIN;
117
+ SET LOCAL ROLE authenticated;
118
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
119
+ SET LOCAL "request.jwt.claim.sub" = '67410000-0000-4000-8000-000000000001';
120
+
121
+ step o_demote_a:
122
+ select role from agent_board.grant_board_role('67430000-0000-4000-8000-000000000001',
123
+ '67420000-0000-4000-8000-000000000002', 'member');
124
+
125
+ role
126
+ ------
127
+ member
128
+ (1 row)
129
+
130
+ step a_begin:
131
+ BEGIN;
132
+ SET LOCAL ROLE authenticated;
133
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
134
+ SET LOCAL "request.jwt.claim.sub" = '67410000-0000-4000-8000-000000000002';
135
+
136
+ step a_grant_m_observer:
137
+ select role from agent_board.grant_board_role('67430000-0000-4000-8000-000000000001',
138
+ '67420000-0000-4000-8000-000000000003', 'observer');
139
+ <waiting ...>
140
+ step o_commit: COMMIT;
141
+ step a_grant_m_observer: <... completed>
142
+ ERROR: grant on another member requires owner or admin role
143
+ step a_rollback: ROLLBACK;
144
+ step check:
145
+ select a.handle, bm.role, bm.membership_state
146
+ from agent_board.board_memberships bm join agent_board.agents a on a.id = bm.agent_id
147
+ where bm.board_id = '67430000-0000-4000-8000-000000000001'
148
+ order by a.handle, bm.membership_state;
149
+
150
+ handle |role |membership_state
151
+ -----------+--------+----------------
152
+ g674-iso-a1|member |joined
153
+ g674-iso-g |member |joined
154
+ g674-iso-m |member |joined
155
+ g674-iso-o |owner |joined
156
+ g674-iso-v |observer|joined
157
+ (5 rows)
158
+
159
+
160
+ starting permutation: a_begin a_grant_m_observer o_begin o_demote_a a_commit o_commit check
161
+ count
162
+ -----
163
+ 1
164
+ (1 row)
165
+
166
+ step a_begin:
167
+ BEGIN;
168
+ SET LOCAL ROLE authenticated;
169
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
170
+ SET LOCAL "request.jwt.claim.sub" = '67410000-0000-4000-8000-000000000002';
171
+
172
+ step a_grant_m_observer:
173
+ select role from agent_board.grant_board_role('67430000-0000-4000-8000-000000000001',
174
+ '67420000-0000-4000-8000-000000000003', 'observer');
175
+
176
+ role
177
+ --------
178
+ observer
179
+ (1 row)
180
+
181
+ step o_begin:
182
+ BEGIN;
183
+ SET LOCAL ROLE authenticated;
184
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
185
+ SET LOCAL "request.jwt.claim.sub" = '67410000-0000-4000-8000-000000000001';
186
+
187
+ step o_demote_a:
188
+ select role from agent_board.grant_board_role('67430000-0000-4000-8000-000000000001',
189
+ '67420000-0000-4000-8000-000000000002', 'member');
190
+ <waiting ...>
191
+ step a_commit: COMMIT;
192
+ step o_demote_a: <... completed>
193
+ role
194
+ ------
195
+ member
196
+ (1 row)
197
+
198
+ step o_commit: COMMIT;
199
+ step check:
200
+ select a.handle, bm.role, bm.membership_state
201
+ from agent_board.board_memberships bm join agent_board.agents a on a.id = bm.agent_id
202
+ where bm.board_id = '67430000-0000-4000-8000-000000000001'
203
+ order by a.handle, bm.membership_state;
204
+
205
+ handle |role |membership_state
206
+ -----------+--------+----------------
207
+ g674-iso-a1|member |joined
208
+ g674-iso-g |member |joined
209
+ g674-iso-m |observer|joined
210
+ g674-iso-o |owner |joined
211
+ g674-iso-v |observer|joined
212
+ (5 rows)
213
+
214
+
215
+ starting permutation: p_begin p_post p_holds_m_fk o_begin o_grant_m_observer p_commit o_commit check
216
+ count
217
+ -----
218
+ 1
219
+ (1 row)
220
+
221
+ step p_begin:
222
+ BEGIN;
223
+ SET LOCAL ROLE authenticated;
224
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
225
+ SET LOCAL "request.jwt.claim.sub" = '67410000-0000-4000-8000-000000000001';
226
+
227
+ step p_post:
228
+ select count(*) > 0 as posted from agent_board.post_board_message('67440000-0000-4000-8000-000000000001',
229
+ '67420000-0000-4000-8000-000000000001', '67430000-0000-4000-8000-000000000001', 'g674 iso', 'fan-out to M');
230
+
231
+ posted
232
+ ------
233
+ t
234
+ (1 row)
235
+
236
+ step p_holds_m_fk:
237
+ RESET ROLE;
238
+ select count(*) as m_delivery_rows from agent_board.delivery_recipients dr
239
+ join agent_board.board_memberships bm on bm.id = dr.board_membership_id
240
+ where bm.board_id = '67430000-0000-4000-8000-000000000001' and bm.agent_id = '67420000-0000-4000-8000-000000000003';
241
+
242
+ m_delivery_rows
243
+ ---------------
244
+ 1
245
+ (1 row)
246
+
247
+ step o_begin:
248
+ BEGIN;
249
+ SET LOCAL ROLE authenticated;
250
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
251
+ SET LOCAL "request.jwt.claim.sub" = '67410000-0000-4000-8000-000000000001';
252
+
253
+ step o_grant_m_observer:
254
+ select role from agent_board.grant_board_role('67430000-0000-4000-8000-000000000001',
255
+ '67420000-0000-4000-8000-000000000003', 'observer');
256
+
257
+ role
258
+ --------
259
+ observer
260
+ (1 row)
261
+
262
+ step p_commit: COMMIT;
263
+ step o_commit: COMMIT;
264
+ step check:
265
+ select a.handle, bm.role, bm.membership_state
266
+ from agent_board.board_memberships bm join agent_board.agents a on a.id = bm.agent_id
267
+ where bm.board_id = '67430000-0000-4000-8000-000000000001'
268
+ order by a.handle, bm.membership_state;
269
+
270
+ handle |role |membership_state
271
+ -----------+--------+----------------
272
+ g674-iso-a1|admin |joined
273
+ g674-iso-g |member |joined
274
+ g674-iso-m |observer|joined
275
+ g674-iso-o |owner |joined
276
+ g674-iso-v |observer|joined
277
+ (5 rows)
278
+
279
+
280
+ starting permutation: g_begin g_redeem g2_begin g2_grant_v_member g2_rollback g_commit g2_retry_begin g2_retry_grant_v_member g2_commit check
281
+ count
282
+ -----
283
+ 1
284
+ (1 row)
285
+
286
+ step g_begin:
287
+ BEGIN;
288
+ select set_config('g674.code', (select code from agent_board.board_invite_tokens
289
+ where board_id = '67430000-0000-4000-8000-000000000001' and preset_role = 'admin'), true) is not null as have_code;
290
+ SET LOCAL ROLE authenticated;
291
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
292
+ SET LOCAL "request.jwt.claim.sub" = '67410000-0000-4000-8000-000000000005';
293
+
294
+ have_code
295
+ ---------
296
+ t
297
+ (1 row)
298
+
299
+ step g_redeem: select role, membership_state from agent_board.redeem_invite_link(current_setting('g674.code'));
300
+ role |membership_state
301
+ -----+----------------
302
+ admin|joined
303
+ (1 row)
304
+
305
+ step g2_begin:
306
+ BEGIN;
307
+ SET LOCAL ROLE authenticated;
308
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
309
+ SET LOCAL "request.jwt.claim.sub" = '67410000-0000-4000-8000-000000000005';
310
+
311
+ step g2_grant_v_member:
312
+ select role from agent_board.grant_board_role('67430000-0000-4000-8000-000000000001',
313
+ '67420000-0000-4000-8000-000000000004', 'member');
314
+
315
+ ERROR: grant on another member requires owner or admin role
316
+ step g2_rollback: ROLLBACK;
317
+ step g_commit: COMMIT;
318
+ step g2_retry_begin:
319
+ BEGIN;
320
+ SET LOCAL ROLE authenticated;
321
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
322
+ SET LOCAL "request.jwt.claim.sub" = '67410000-0000-4000-8000-000000000005';
323
+
324
+ step g2_retry_grant_v_member:
325
+ select role from agent_board.grant_board_role('67430000-0000-4000-8000-000000000001',
326
+ '67420000-0000-4000-8000-000000000004', 'member');
327
+
328
+ role
329
+ ------
330
+ member
331
+ (1 row)
332
+
333
+ step g2_commit: COMMIT;
334
+ step check:
335
+ select a.handle, bm.role, bm.membership_state
336
+ from agent_board.board_memberships bm join agent_board.agents a on a.id = bm.agent_id
337
+ where bm.board_id = '67430000-0000-4000-8000-000000000001'
338
+ order by a.handle, bm.membership_state;
339
+
340
+ handle |role |membership_state
341
+ -----------+------+----------------
342
+ g674-iso-a1|admin |joined
343
+ g674-iso-g |admin |joined
344
+ g674-iso-m |member|joined
345
+ g674-iso-o |owner |joined
346
+ g674-iso-v |member|joined
347
+ (5 rows)
348
+