@consiliency/agent-board-schema 1.12.0 → 1.23.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 (156) hide show
  1. package/fixtures/already-applied.json +160 -0
  2. package/migrations/20260731000100_agent_board_agentsdir_column_scope.sql +88 -0
  3. package/migrations/20260801000100_agent_board_leaveidem_terminal_noop.sql +317 -0
  4. package/migrations/20260802000100_agent_board_rolereset_reentry_clamp.sql +237 -0
  5. package/migrations/20260803000100_agent_board_rowid_total_order.sql +1201 -0
  6. package/migrations/20260804000100_agent_board_hygiene_actor_binding_rls.sql +229 -0
  7. package/migrations/20260806000100_agent_board_consent_substrate.sql +339 -0
  8. package/migrations/20260807000100_agent_board_consent_emission.sql +619 -0
  9. package/migrations/20260808000100_agent_board_rejectsem.sql +145 -0
  10. package/migrations/20260809000100_agent_board_consent_gating.sql +492 -0
  11. package/migrations/20260810000100_agent_board_consent_locking.sql +485 -0
  12. package/migrations/20260811000100_agent_board_retention_metadata_revoke.sql +23 -0
  13. package/migrations/20260812000100_agent_board_pubexec_class_revoke.sql +54 -0
  14. package/migrations/20260813000100_agent_board_invitepolicy_block.sql +420 -0
  15. package/migrations/20260814000100_agent_board_obsgate_thread_post_policy.sql +239 -0
  16. package/migrations/20260815000100_agent_board_obsgate2_authoring_gates.sql +287 -0
  17. package/migrations/20260816000100_agent_board_obsgate3_task_lifecycle.sql +118 -0
  18. package/migrations/20260817000100_agent_board_obsgate4_claims_lifecycle.sql +250 -0
  19. package/migrations/20260818000100_agent_board_fleet_machines_rls_correlation.sql +43 -0
  20. package/migrations/20260819000100_agent_board_resolve_noop_retire.sql +166 -0
  21. package/migrations/20260820000100_agent_board_roomdeleg_lane_b.sql +206 -0
  22. package/migrations/20260821000100_agent_board_claimgate_claimkey.sql +372 -0
  23. package/migrations/20260822000100_agent_board_mint_harden.sql +710 -0
  24. package/migrations/20260822000200_agent_board_mint_harden_fingerprint_backfill.sql +207 -0
  25. package/migrations/20260823000100_agent_board_fleet_machine_hijack.sql +106 -0
  26. package/migrations/20260824000100_agent_board_claimgate_shadow.sql +443 -0
  27. package/migrations/20260825000100_agent_board_claimgate_enforce.sql +660 -0
  28. package/migrations/20260826000100_agent_board_fleet_machine_reactivation.sql +514 -0
  29. package/migrations/20260828000100_agent_board_delegation_cap_ceiling.sql +474 -0
  30. package/migrations/20260829000100_agent_board_fleet_machine_reclaim.sql +432 -0
  31. package/migrations/20260830000100_agent_board_delegation_sole_writer.sql +41 -0
  32. package/migrations/20260831000100_agent_board_fleet_domain_reclaim.sql +389 -0
  33. package/migrations/20260901000100_agent_board_atomic_fleet_onboarding.sql +1496 -0
  34. package/migrations/20260901000110_agent_board_fleet_onboarding_ceiling_lock.sql +604 -0
  35. package/migrations/20260901000120_agent_board_human_revocation_evidence_completeness.sql +78 -0
  36. package/migrations/20260901000130_agent_board_fedsession_human_revocation_gate.sql +74 -0
  37. package/migrations/20260901000140_agent_board_fedsession_board_owner_lock_order.sql +102 -0
  38. package/migrations/20260902000100_agent_board_outbox_wake_ordering.sql +184 -0
  39. package/migrations/20260903000100_agent_board_enroll_identity_board_owner_lock_order.sql +604 -0
  40. package/migrations/20260903000200_agent_board_fedsession_provider_absence_gate.sql +177 -0
  41. package/migrations/20260904000100_agent_board_wake_recovery_surface.sql +155 -0
  42. package/package.json +1 -1
  43. package/schema-manifest.json +363 -3
  44. package/src/tooling.test.mjs +113 -2
  45. package/tests/agent_board_actorspoof.test.sql +349 -0
  46. package/tests/agent_board_agentsdir.test.sql +154 -0
  47. package/tests/agent_board_atomic_fleet_onboarding.test.sql +623 -0
  48. package/tests/agent_board_atomic_fleet_onboarding_backfill.test.sql +142 -0
  49. package/tests/agent_board_atomic_fleet_onboarding_runtime.test.sql +1250 -0
  50. package/tests/agent_board_authbound_boundary.test.sql +9 -1
  51. package/tests/agent_board_claimgate_enforce.test.sql +464 -0
  52. package/tests/agent_board_claimgate_predicate.test.sql +360 -0
  53. package/tests/agent_board_claimkey.test.sql +229 -0
  54. package/tests/agent_board_consent_backfill.test.sql +48 -0
  55. package/tests/agent_board_consent_emission.test.sql +601 -0
  56. package/tests/agent_board_consent_gating.test.sql +489 -0
  57. package/tests/agent_board_consent_substrate.test.sql +720 -0
  58. package/tests/agent_board_delegation_cap_ceiling.test.sql +303 -0
  59. package/tests/agent_board_delegation_enforcement.test.sql +55 -6
  60. package/tests/agent_board_delegation_policies.test.sql +107 -1
  61. package/tests/agent_board_enroll_federated_identity.test.sql +3 -3
  62. package/tests/agent_board_enroll_pop_binding.test.sql +13 -3
  63. package/tests/agent_board_enrollment_audit_content.test.sql +11 -7
  64. package/tests/agent_board_federated_lock_order_class.test.sql +390 -0
  65. package/tests/agent_board_fedsession.test.sql +51 -5
  66. package/tests/agent_board_fedsession_provider_absence_gate.test.sql +170 -0
  67. package/tests/agent_board_fleet_domain_reclaim.test.sql +419 -0
  68. package/tests/agent_board_fleet_machine_hijack.test.sql +190 -0
  69. package/tests/agent_board_fleet_machine_reactivation.test.sql +426 -0
  70. package/tests/agent_board_fleet_machine_reclaim.test.sql +509 -0
  71. package/tests/agent_board_fleet_machines_rls.test.sql +79 -0
  72. package/tests/agent_board_fleet_policy.test.sql +2 -2
  73. package/tests/agent_board_grants_hygiene.test.sql +408 -0
  74. package/tests/agent_board_identity_providers.test.sql +9 -0
  75. package/tests/agent_board_inbox_reads.test.sql +45 -31
  76. package/tests/agent_board_inbox_rpcs.test.sql +44 -34
  77. package/tests/agent_board_invitepolicy.test.sql +205 -0
  78. package/tests/agent_board_leaveidem.test.sql +194 -0
  79. package/tests/agent_board_mint_fleet_agent_session.test.sql +10 -10
  80. package/tests/agent_board_mint_harden.test.sql +303 -0
  81. package/tests/agent_board_mint_harden_backfill.test.sql +95 -0
  82. package/tests/agent_board_obsgate.test.sql +178 -0
  83. package/tests/agent_board_obsgate2.test.sql +153 -0
  84. package/tests/agent_board_obsgate3.test.sql +170 -0
  85. package/tests/agent_board_obsgate4.test.sql +196 -0
  86. package/tests/agent_board_outbox_wake_ordering.test.sql +452 -0
  87. package/tests/agent_board_portal_offline_invariant.test.sql +14 -3
  88. package/tests/agent_board_pubexec_class.test.sql +53 -0
  89. package/tests/agent_board_rejectsem.test.sql +271 -0
  90. package/tests/agent_board_resigning_refresh.test.sql +1 -1
  91. package/tests/agent_board_resolve_noop_retire.test.sql +71 -0
  92. package/tests/agent_board_retention_metadata_acl.test.sql +53 -0
  93. package/tests/agent_board_revoke_agent_subtree.test.sql +3 -3
  94. package/tests/agent_board_rolereset.test.sql +351 -0
  95. package/tests/agent_board_roomdeleg.test.sql +5 -3
  96. package/tests/agent_board_roomdeleg_lane_b.test.sql +144 -0
  97. package/tests/agent_board_roomlink.test.sql +27 -11
  98. package/tests/agent_board_rowid.test.sql +1274 -0
  99. package/tests/agent_board_signature_rls_reads.test.sql +3 -3
  100. package/tests/agent_board_signed_write_gateway.test.sql +3 -3
  101. package/tests/agent_board_signing_challenge_pending_cap.test.sql +2 -2
  102. package/tests/agent_board_signing_challenge_reaper.test.sql +2 -2
  103. package/tests/agent_board_signing_proof_rpcs.test.sql +4 -4
  104. package/tests/agent_board_signing_store.test.sql +6 -6
  105. package/tests/agent_board_wake_recovery.test.sql +756 -0
  106. package/tests/fixtures/isolation-substrate.sql +93 -0
  107. package/tests/fixtures/test-prereqs.sql +33 -0
  108. package/tests/isolation/expected/atomic_fedsession_fleet_lock_order.out +79 -0
  109. package/tests/isolation/expected/atomic_fedsession_human_revoke.out +87 -0
  110. package/tests/isolation/expected/atomic_fleet_authority_races.out +469 -0
  111. package/tests/isolation/expected/atomic_fleet_binding_revoke.out +103 -0
  112. package/tests/isolation/expected/atomic_fleet_board_archive.out +117 -0
  113. package/tests/isolation/expected/atomic_fleet_human_fresh_revoke.out +136 -0
  114. package/tests/isolation/expected/atomic_fleet_identity_disposition.out +61 -0
  115. package/tests/isolation/expected/atomic_fleet_lifecycle_races.out +1479 -0
  116. package/tests/isolation/expected/atomic_fleet_onboarding.out +75 -0
  117. package/tests/isolation/expected/atomic_fleet_subtree_lock_order.out +60 -0
  118. package/tests/isolation/expected/ceiling_setter_lock_before_upsert.out +95 -0
  119. package/tests/isolation/expected/claimgate_ownerless_quota.out +36 -0
  120. package/tests/isolation/expected/claimkey_renew_race.out +38 -0
  121. package/tests/isolation/expected/consent_approval_lock.out +43 -0
  122. package/tests/isolation/expected/consent_emit_actual_state.out +37 -0
  123. package/tests/isolation/expected/domain_reclaim_revoke_race.out +40 -0
  124. package/tests/isolation/expected/enroll_identity_board_owner_lock_order.out +55 -0
  125. package/tests/isolation/expected/fedsession_provider_absent_owner_lock.out +37 -0
  126. package/tests/isolation/expected/onboarding_ceiling_lock_order.out +123 -0
  127. package/tests/isolation/expected/outbox_wake_ordering.out +86 -0
  128. package/tests/isolation/expected/reactivate_revoke_race.out +80 -0
  129. package/tests/isolation/expected/reclaim_revoke_race.out +40 -0
  130. package/tests/isolation/expected/wake_recovery_late_commit.out +89 -0
  131. package/tests/isolation/specs/atomic_fedsession_fleet_lock_order.spec +117 -0
  132. package/tests/isolation/specs/atomic_fedsession_human_revoke.spec +66 -0
  133. package/tests/isolation/specs/atomic_fleet_authority_races.spec +235 -0
  134. package/tests/isolation/specs/atomic_fleet_binding_revoke.spec +127 -0
  135. package/tests/isolation/specs/atomic_fleet_board_archive.spec +134 -0
  136. package/tests/isolation/specs/atomic_fleet_human_fresh_revoke.spec +142 -0
  137. package/tests/isolation/specs/atomic_fleet_identity_disposition.spec +118 -0
  138. package/tests/isolation/specs/atomic_fleet_lifecycle_races.spec +244 -0
  139. package/tests/isolation/specs/atomic_fleet_onboarding.spec +106 -0
  140. package/tests/isolation/specs/atomic_fleet_subtree_lock_order.spec +147 -0
  141. package/tests/isolation/specs/ceiling_setter_lock_before_upsert.spec +117 -0
  142. package/tests/isolation/specs/claimgate_ownerless_quota.spec +77 -0
  143. package/tests/isolation/specs/claimkey_renew_race.spec +67 -0
  144. package/tests/isolation/specs/consent_approval_lock.spec +98 -0
  145. package/tests/isolation/specs/consent_emit_actual_state.spec +79 -0
  146. package/tests/isolation/specs/domain_reclaim_revoke_race.spec +88 -0
  147. package/tests/isolation/specs/enroll_identity_board_owner_lock_order.spec +117 -0
  148. package/tests/isolation/specs/fedsession_provider_absent_owner_lock.spec +63 -0
  149. package/tests/isolation/specs/onboarding_ceiling_lock_order.spec +183 -0
  150. package/tests/isolation/specs/outbox_wake_ordering.spec +202 -0
  151. package/tests/isolation/specs/reactivate_revoke_race.spec +115 -0
  152. package/tests/isolation/specs/reclaim_revoke_race.spec +94 -0
  153. package/tests/isolation/specs/wake_recovery_late_commit.spec +207 -0
  154. package/tests/seeds/20260806000100_agent_board_consent_substrate.sql.pre.sql +19 -0
  155. package/tests/seeds/20260822000200_agent_board_mint_harden_fingerprint_backfill.sql.pre.sql +39 -0
  156. package/tests/seeds/20260901000100_agent_board_atomic_fleet_onboarding.sql.pre.sql +110 -0
@@ -0,0 +1,86 @@
1
+ Parsed test spec with 3 sessions
2
+
3
+ starting permutation: l_begin l_insert l_mark f_begin f_fanout f_mark f_report f_commit c_first l_commit c_second
4
+ step l_begin: BEGIN;
5
+ step l_insert:
6
+ select agent_board._queue_board_post_callbacks(
7
+ '18701000-0000-4000-8000-00000000000b'::uuid,
8
+ '18703000-0000-4000-8000-00000000000b'::uuid,
9
+ 'Iso187 late', 'Iso187 late preview', 'high', jsonb_build_object()) as late_rows_written;
10
+
11
+ late_rows_written
12
+ -----------------
13
+ 1
14
+ (1 row)
15
+
16
+ step l_mark:
17
+ insert into public.iso187_marks(kind, val)
18
+ select 'late_seq', min(seq) from agent_board.callback_outbox_events
19
+ where board_id = '18701000-0000-4000-8000-00000000000b';
20
+
21
+ step f_begin: BEGIN;
22
+ step f_fanout:
23
+ select agent_board._queue_board_post_callbacks(
24
+ '18701000-0000-4000-8000-00000000000a'::uuid,
25
+ '18703000-0000-4000-8000-00000000000a'::uuid,
26
+ 'Iso187 fanout', 'Iso187 fanout preview', 'high', jsonb_build_object()) as fanout_rows_written;
27
+
28
+ fanout_rows_written
29
+ -------------------
30
+ 8
31
+ (1 row)
32
+
33
+ step f_mark:
34
+ insert into public.iso187_marks(kind, val)
35
+ select 'fan_base', min(seq) from agent_board.callback_outbox_events
36
+ where board_id = '18701000-0000-4000-8000-00000000000a';
37
+
38
+ step f_report:
39
+ select count(*) as rows_written,
40
+ count(distinct created_at) as distinct_created_at,
41
+ count(distinct seq) as distinct_seq,
42
+ (max(seq) - min(seq) + 1) as seq_span
43
+ from agent_board.callback_outbox_events
44
+ where board_id = '18701000-0000-4000-8000-00000000000a';
45
+
46
+ rows_written|distinct_created_at|distinct_seq|seq_span
47
+ ------------+-------------------+------------+--------
48
+ 8| 1| 8| 8
49
+ (1 row)
50
+
51
+ step f_commit: COMMIT;
52
+ step c_first:
53
+ select (select array_agg(outbox_seq) from agent_board.claim_callback_outbox_events(4))
54
+ = (select array_agg(g order by g)
55
+ from generate_series((select val from public.iso187_marks where kind = 'fan_base'),
56
+ (select val from public.iso187_marks where kind = 'fan_base') + 3) g)
57
+ as claimed_lowest_four_in_seq_order;
58
+
59
+ claimed_lowest_four_in_seq_order
60
+ --------------------------------
61
+ t
62
+ (1 row)
63
+
64
+ step l_commit: COMMIT;
65
+ step c_second:
66
+ with claimed as (
67
+ select array_agg(outbox_seq) as got from agent_board.claim_callback_outbox_events(4)
68
+ ),
69
+ marks as (
70
+ select (select val from public.iso187_marks where kind = 'late_seq') as late_seq,
71
+ (select val from public.iso187_marks where kind = 'fan_base') as fan_base
72
+ )
73
+ select (select got from claimed)
74
+ = array[(select late_seq from marks)]
75
+ || (select array_agg(g order by g)
76
+ from generate_series((select fan_base from marks) + 4,
77
+ (select fan_base from marks) + 6) g)
78
+ as late_row_claimed_first_then_next_fan_rows,
79
+ (select late_seq from marks) < (select fan_base from marks)
80
+ as late_committer_holds_a_lower_seq_than_the_persisted_cursor;
81
+
82
+ late_row_claimed_first_then_next_fan_rows|late_committer_holds_a_lower_seq_than_the_persisted_cursor
83
+ -----------------------------------------+----------------------------------------------------------
84
+ t |t
85
+ (1 row)
86
+
@@ -0,0 +1,80 @@
1
+ Parsed test spec with 3 sessions
2
+
3
+ starting permutation: ra_begin ra_react rb_begin rb_revoke ra_commit rb_commit chk
4
+ step ra_begin: BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role';
5
+ step ra_react:
6
+ select lifecycle_state
7
+ from agent_board.reactivate_fleet_machine(
8
+ '60000000-0000-4000-8000-000000000001', 'a0000000-0000-4000-8000-000000000001', 'iso reactivate');
9
+
10
+ lifecycle_state
11
+ ---------------
12
+ active
13
+ (1 row)
14
+
15
+ step rb_begin: BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role';
16
+ step rb_revoke:
17
+ select revocation_event_id
18
+ from agent_board.revoke_fleet_subject(
19
+ 'machine', '60000000-0000-4000-8000-000000000001', 'a0000000-0000-4000-8000-000000000001',
20
+ 'iso re-revoke', jsonb_build_object('redacted', true));
21
+ <waiting ...>
22
+ step ra_commit: COMMIT;
23
+ step rb_revoke: <... completed>
24
+ revocation_event_id
25
+ ------------------------------------
26
+ e0000000-0000-4000-8000-000000000001
27
+ (1 row)
28
+
29
+ step rb_commit: COMMIT;
30
+ step chk:
31
+ select fm.lifecycle_state,
32
+ (select denial_class
33
+ from agent_board.evaluate_fleet_sender_policy(
34
+ 'a0000000-0000-4000-8000-000000000002', 'a0000000-0000-4000-8000-000000000003',
35
+ fm.id, null, 'send_direct_message', null, false)) as denial_class
36
+ from agent_board.fleet_machines fm
37
+ where fm.id = '60000000-0000-4000-8000-000000000001';
38
+
39
+ lifecycle_state|denial_class
40
+ ---------------+---------------
41
+ revoked |machine_revoked
42
+ (1 row)
43
+
44
+
45
+ starting permutation: ra_begin ra_react rb_begin rb_react ra_commit rb_commit chk
46
+ step ra_begin: BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role';
47
+ step ra_react:
48
+ select lifecycle_state
49
+ from agent_board.reactivate_fleet_machine(
50
+ '60000000-0000-4000-8000-000000000001', 'a0000000-0000-4000-8000-000000000001', 'iso reactivate');
51
+
52
+ lifecycle_state
53
+ ---------------
54
+ active
55
+ (1 row)
56
+
57
+ step rb_begin: BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role';
58
+ step rb_react:
59
+ select lifecycle_state
60
+ from agent_board.reactivate_fleet_machine(
61
+ '60000000-0000-4000-8000-000000000001', 'a0000000-0000-4000-8000-000000000001', 'iso second reactivate');
62
+ <waiting ...>
63
+ step ra_commit: COMMIT;
64
+ step rb_react: <... completed>
65
+ ERROR: fleet machine is not revoked; nothing to reactivate
66
+ step rb_commit: COMMIT;
67
+ step chk:
68
+ select fm.lifecycle_state,
69
+ (select denial_class
70
+ from agent_board.evaluate_fleet_sender_policy(
71
+ 'a0000000-0000-4000-8000-000000000002', 'a0000000-0000-4000-8000-000000000003',
72
+ fm.id, null, 'send_direct_message', null, false)) as denial_class
73
+ from agent_board.fleet_machines fm
74
+ where fm.id = '60000000-0000-4000-8000-000000000001';
75
+
76
+ lifecycle_state|denial_class
77
+ ---------------+------------
78
+ active |
79
+ (1 row)
80
+
@@ -0,0 +1,40 @@
1
+ Parsed test spec with 3 sessions
2
+
3
+ starting permutation: ra_begin ra_reclaim rb_begin rb_revoke ra_commit rb_commit chk
4
+ step ra_begin: BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role';
5
+ step ra_reclaim:
6
+ select owner_agent_id
7
+ from agent_board.reclaim_fleet_machine(
8
+ '61000000-0000-4000-8000-000000000001', 'a1000000-0000-4000-8000-000000000003',
9
+ 'a1000000-0000-4000-8000-000000000001', 'iso operator reclaim');
10
+
11
+ owner_agent_id
12
+ ------------------------------------
13
+ a1000000-0000-4000-8000-000000000003
14
+ (1 row)
15
+
16
+ step rb_begin:
17
+ BEGIN;
18
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
19
+ SET LOCAL "request.jwt.claim.sub" = 'b1000000-0000-4000-8000-000000000002';
20
+
21
+ step rb_revoke:
22
+ select revocation_event_id
23
+ from agent_board.revoke_fleet_subject(
24
+ 'machine', '61000000-0000-4000-8000-000000000001', 'a1000000-0000-4000-8000-000000000002',
25
+ 'iso squatter revoke', jsonb_build_object('redacted', true));
26
+ <waiting ...>
27
+ step ra_commit: COMMIT;
28
+ step rb_revoke: <... completed>
29
+ ERROR: machine is not owned by current_agent_id()
30
+ step rb_commit: COMMIT;
31
+ step chk:
32
+ select owner_agent_id, lifecycle_state
33
+ from agent_board.fleet_machines
34
+ where id = '61000000-0000-4000-8000-000000000001';
35
+
36
+ owner_agent_id |lifecycle_state
37
+ ------------------------------------+---------------
38
+ a1000000-0000-4000-8000-000000000003|active
39
+ (1 row)
40
+
@@ -0,0 +1,89 @@
1
+ Parsed test spec with 3 sessions
2
+
3
+ starting permutation: c_auth l_begin l_insert l_mark m_begin m_insert m_commit c_first c_persist l_commit c_second
4
+ step c_auth:
5
+ select set_config('request.jwt.claim.sub', '19116000-0000-4000-8000-000000000002', false)
6
+ = '19116000-0000-4000-8000-000000000002' as consumer_session_bound_to_recipient;
7
+
8
+ consumer_session_bound_to_recipient
9
+ -----------------------------------
10
+ t
11
+ (1 row)
12
+
13
+ step l_begin: BEGIN;
14
+ step l_insert:
15
+ with dr as (
16
+ insert into agent_board.delivery_recipients(id, delivery_mode, recipient_agent_id, source_kind, source_message_id)
17
+ values ('19114000-0000-4000-8000-00000000000e', 'direct',
18
+ '19110000-0000-4000-8000-000000000002', 'message',
19
+ '19113000-0000-4000-8000-00000000000e')
20
+ returning id
21
+ )
22
+ insert into agent_board.inbox_items(
23
+ id, delivery_recipient_id, recipient_agent_id, delivery_mode, source_kind, source_message_id,
24
+ subject, preview, priority, action_state, visible_in_inbox, visible_in_board_feed, fetch_descriptor)
25
+ select '19115000-0000-4000-8000-00000000000e', dr.id,
26
+ '19110000-0000-4000-8000-000000000002', 'direct', 'message',
27
+ '19113000-0000-4000-8000-00000000000e',
28
+ 'Iso191 late', 'iso191 late preview', 'high', 'new', true, false, jsonb_build_object()
29
+ from dr;
30
+
31
+ step l_mark:
32
+ insert into public.iso191_marks(kind, val)
33
+ select 'late_created_at', created_at from agent_board.inbox_items
34
+ where id = '19115000-0000-4000-8000-00000000000e';
35
+
36
+ step m_begin: BEGIN;
37
+ step m_insert:
38
+ with dr as (
39
+ insert into agent_board.delivery_recipients(id, delivery_mode, recipient_agent_id, source_kind, source_message_id)
40
+ values ('19114000-0000-4000-8000-00000000000d', 'direct',
41
+ '19110000-0000-4000-8000-000000000002', 'message',
42
+ '19113000-0000-4000-8000-00000000000d')
43
+ returning id
44
+ )
45
+ insert into agent_board.inbox_items(
46
+ id, delivery_recipient_id, recipient_agent_id, delivery_mode, source_kind, source_message_id,
47
+ subject, preview, priority, action_state, visible_in_inbox, visible_in_board_feed, fetch_descriptor)
48
+ select '19115000-0000-4000-8000-00000000000d', dr.id,
49
+ '19110000-0000-4000-8000-000000000002', 'direct', 'message',
50
+ '19113000-0000-4000-8000-00000000000d',
51
+ 'Iso191 mid', 'iso191 mid preview', 'high', 'new', true, false, jsonb_build_object()
52
+ from dr;
53
+
54
+ step m_commit: COMMIT;
55
+ step c_first:
56
+ select count(*) = 1 as first_read_sees_one_unhandled_item,
57
+ bool_and(w.inbox_item_id = '19115000-0000-4000-8000-00000000000d') as the_visible_item_is_the_committed_one
58
+ from agent_board.v_agent_wake_recovery w
59
+ where w.recipient_agent_id = '19110000-0000-4000-8000-000000000002';
60
+
61
+ first_read_sees_one_unhandled_item|the_visible_item_is_the_committed_one
62
+ ----------------------------------+-------------------------------------
63
+ t |t
64
+ (1 row)
65
+
66
+ step c_persist:
67
+ insert into public.iso191_marks(kind, val)
68
+ select 'naive_cursor', max(created_at) from agent_board.v_agent_wake_recovery
69
+ where recipient_agent_id = '19110000-0000-4000-8000-000000000002';
70
+
71
+ step l_commit: COMMIT;
72
+ step c_second:
73
+ select exists (select 1 from agent_board.v_agent_wake_recovery w
74
+ where w.recipient_agent_id = '19110000-0000-4000-8000-000000000002'
75
+ and w.inbox_item_id = '19115000-0000-4000-8000-00000000000e')
76
+ as late_committer_recovered_by_status,
77
+ (select l.val from public.iso191_marks l where l.kind = 'late_created_at')
78
+ <= (select c.val from public.iso191_marks c where c.kind = 'naive_cursor')
79
+ as late_committer_skipped_by_timestamp_cursor,
80
+ not exists (select 1 from agent_board.v_agent_wake_recovery w
81
+ where w.recipient_agent_id = '19110000-0000-4000-8000-000000000002'
82
+ and w.created_at > (select c.val from public.iso191_marks c where c.kind = 'naive_cursor'))
83
+ as a_created_at_cursor_read_returns_nothing_new;
84
+
85
+ late_committer_recovered_by_status|late_committer_skipped_by_timestamp_cursor|a_created_at_cursor_read_returns_nothing_new
86
+ ----------------------------------+------------------------------------------+--------------------------------------------
87
+ t |t |t
88
+ (1 row)
89
+
@@ -0,0 +1,117 @@
1
+ # Consiliency/message-board#162 — fleet onboarding and /portal-session may
2
+ # share both a human owner and the provider's default board. Prove the routes
3
+ # agree on board -> owner and cannot form the old board/owner ABBA cycle.
4
+
5
+ setup
6
+ {
7
+ insert into agent_board.agents(id, agent_type, kind, handle, display_name, status)
8
+ values ('162a0000-0000-0000-0000-000000000001', 'agent', 'agent',
9
+ 'atomic-cross-owner', 'Atomic Cross Owner', 'active');
10
+
11
+ select count(*) from agent_board.create_board(
12
+ '162a0000-0000-0000-0000-000000000001',
13
+ 'atomic-cross-board', 'Atomic Cross Board',
14
+ 'Consiliency/message-board#162 cross-route lock proof', jsonb_build_object(), 'private'
15
+ );
16
+
17
+ insert into agent_board.fleet_trust_domains(
18
+ id, slug, display_name, domain_kind, owner_agent_id, lifecycle_state, approved_at
19
+ ) values (
20
+ '162a0000-0000-0000-0000-000000000002', 'atomic-cross-domain',
21
+ 'Atomic Cross Domain', 'tailnet', '162a0000-0000-0000-0000-000000000001',
22
+ 'active', now()
23
+ );
24
+ insert into agent_board.fleet_machines(
25
+ id, trust_domain_id, owner_agent_id, machine_label, machine_fingerprint,
26
+ lifecycle_state, enrollment_source, enrolled_at
27
+ ) values (
28
+ '162a0000-0000-0000-0000-000000000003',
29
+ '162a0000-0000-0000-0000-000000000002',
30
+ '162a0000-0000-0000-0000-000000000001',
31
+ 'claw', 'sha256:atomic-cross-machine', 'active', 'portal', now()
32
+ );
33
+ insert into agent_board.identity_providers(
34
+ issuer, audience, supported, policy_approved,
35
+ allowed_scopes, allowed_board_scopes, allowed_agent_kinds
36
+ ) values (
37
+ 'https://atomic-cross.test', 'message-board', true, true,
38
+ ARRAY['board:send'], ARRAY[]::text[], ARRAY['agent','human']
39
+ );
40
+
41
+ -- Materialize the shared human owner while auto-join is still disabled.
42
+ select count(*) from agent_board.enroll_federated_human(
43
+ 'https://atomic-cross.test', 'message-board', 'cross-human',
44
+ jsonb_build_object('sub','cross-human'), 'Cross Human'
45
+ );
46
+ update agent_board.identity_providers
47
+ set default_board_id=(select id from agent_board.boards where slug='atomic-cross-board')
48
+ where issuer='https://atomic-cross.test';
49
+
50
+ select count(*) from agent_board.create_fleet_onboarding_invite(
51
+ (select id from agent_board.boards where slug='atomic-cross-board'),
52
+ '162a0000-0000-0000-0000-000000000003',
53
+ 'codex', 'phase-loop', 'message-board', 'sha256:atomic-cross-repo',
54
+ 'worker', 'phase_worker', 'atomic-cross-agent', 1,
55
+ now() + interval '1 hour', '162a0000-0000-0000-0000-000000000001',
56
+ jsonb_build_object()
57
+ );
58
+ }
59
+
60
+ session "guard"
61
+ step "guard_begin" { BEGIN; }
62
+ step "guard_board_key_share" {
63
+ select slug from agent_board.boards
64
+ where slug='atomic-cross-board' for key share;
65
+ }
66
+ step "guard_commit" { COMMIT; }
67
+
68
+ session "fleet"
69
+ step "fleet_begin" { BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role'; }
70
+ step "fleet_onboard" {
71
+ select identity_disposition, membership_disposition, binding_disposition
72
+ from agent_board.onboard_federated_fleet_agent(
73
+ 'https://atomic-cross.test', 'message-board', 'cross-human',
74
+ jsonb_build_object('iss','https://atomic-cross.test','aud','message-board','sub','cross-human','iat',100),
75
+ 'atomic-cross-agent',
76
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0',
77
+ 'raw_ed25519_base64url',
78
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8',
79
+ true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
80
+ (select code from agent_board.board_invite_tokens where created_by_agent_id='162a0000-0000-0000-0000-000000000001'),
81
+ (select id from agent_board.boards where slug='atomic-cross-board'),
82
+ '162a0000-0000-0000-0000-000000000003',
83
+ 'codex', 'phase-loop', 'message-board', 'sha256:atomic-cross-repo',
84
+ 'worker', 'phase_worker', 'atomic-cross-agent'
85
+ );
86
+ }
87
+ step "fleet_commit" { COMMIT; }
88
+
89
+ session "portal"
90
+ step "portal_begin" { BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role'; }
91
+ step "portal_enroll" {
92
+ select status from agent_board.enroll_federated_human(
93
+ 'https://atomic-cross.test', 'message-board', 'cross-human',
94
+ jsonb_build_object('sub','cross-human','iat',200), 'Cross Human'
95
+ );
96
+ }
97
+ step "portal_commit" { COMMIT; }
98
+
99
+ session "check"
100
+ step "check" {
101
+ select
102
+ (select count(*) from agent_board.agents
103
+ where owner_user_id=(select auth_user_id from agent_board.agents
104
+ where metadata #>> ARRAY['federation','subject']='cross-human'
105
+ order by kind='human' desc limit 1)) as owned_agents,
106
+ (select count(*) from agent_board.board_memberships m
107
+ join agent_board.agents a on a.id=m.agent_id
108
+ where m.board_id=(select id from agent_board.boards where slug='atomic-cross-board')
109
+ and a.owner_user_id=(select auth_user_id from agent_board.agents
110
+ where metadata #>> ARRAY['federation','subject']='cross-human'
111
+ order by kind='human' desc limit 1)) as memberships,
112
+ (select count(*) from agent_board.fleet_machine_agents b
113
+ join agent_board.agents a on a.id=b.agent_id
114
+ where a.handle='atomic-cross-agent') as bindings;
115
+ }
116
+
117
+ permutation "guard_begin" "guard_board_key_share" "fleet_begin" "fleet_onboard" "portal_begin" "portal_enroll" "guard_commit" "fleet_commit" "portal_commit" "check"
@@ -0,0 +1,66 @@
1
+ # Consiliency/message-board#162 — /portal-session's enroll_federated_human RPC
2
+ # shares the deterministic auth.users owner lock with total-human revocation.
3
+ # Prove both orders: session first completes before revocation; revocation first
4
+ # commits the marker and the waiting session fails closed.
5
+
6
+ setup
7
+ {
8
+ insert into agent_board.agents(id, agent_type, kind, handle, display_name, status)
9
+ values ('16290000-0000-0000-0000-000000000001', 'agent', 'agent',
10
+ 'atomic-fedsession-revoker', 'Atomic Fedsession Revoker', 'active');
11
+ insert into agent_board.identity_providers(
12
+ issuer, audience, supported, policy_approved, allowed_scopes, allowed_board_scopes, allowed_agent_kinds
13
+ ) values (
14
+ 'https://atomic-fedsession.test', 'message-board', true, true,
15
+ ARRAY[]::text[], ARRAY[]::text[], ARRAY['human']
16
+ );
17
+ select count(*) from agent_board.enroll_federated_human(
18
+ 'https://atomic-fedsession.test', 'message-board', 'portal-human-race',
19
+ jsonb_build_object('sub','portal-human-race'), 'Portal Human Race'
20
+ );
21
+ }
22
+
23
+ teardown
24
+ {
25
+ delete from agent_board.enrollment_federation_audit where issuer='https://atomic-fedsession.test';
26
+ delete from agent_board.fleet_human_revocations where issuer='https://atomic-fedsession.test';
27
+ delete from agent_board.fleet_revocation_events
28
+ where revoked_by_agent_id='16290000-0000-0000-0000-000000000001'
29
+ or agent_id in (
30
+ select id from agent_board.agents
31
+ where metadata #>> ARRAY['federation','subject'] = 'portal-human-race'
32
+ );
33
+ delete from agent_board.agents where handle like 'fed-human-%' or id='16290000-0000-0000-0000-000000000001';
34
+ delete from agent_board.identity_providers where issuer='https://atomic-fedsession.test';
35
+ }
36
+
37
+ session "portal"
38
+ step "portal_begin" { BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role'; }
39
+ step "portal_enroll" {
40
+ select status from agent_board.enroll_federated_human(
41
+ 'https://atomic-fedsession.test', 'message-board', 'portal-human-race',
42
+ jsonb_build_object('sub','portal-human-race','iat',200), 'Portal Human Race'
43
+ );
44
+ }
45
+ step "portal_commit" { COMMIT; }
46
+
47
+ session "revoke"
48
+ step "revoke_begin" { BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role'; }
49
+ step "revoke_human" {
50
+ select revoked_agent_count from agent_board.revoke_human_subtree(
51
+ (select auth_user_id from agent_board.agents where metadata #>> ARRAY['federation','subject'] = 'portal-human-race'),
52
+ '16290000-0000-0000-0000-000000000001', 'portal race revoke'
53
+ );
54
+ }
55
+ step "revoke_commit" { COMMIT; }
56
+
57
+ session "check"
58
+ step "check" {
59
+ select
60
+ (select count(*) from agent_board.fleet_human_revocations where issuer='https://atomic-fedsession.test') as markers,
61
+ (select count(*) from agent_board.agents where metadata #>> ARRAY['federation','subject'] = 'portal-human-race' and status='active') as active_humans,
62
+ (select count(*) from agent_board.enrollment_federation_audit where issuer='https://atomic-fedsession.test') as audits;
63
+ }
64
+
65
+ permutation "portal_begin" "portal_enroll" "revoke_begin" "revoke_human" "portal_commit" "revoke_commit" "check"
66
+ permutation "revoke_begin" "revoke_human" "portal_begin" "portal_enroll" "revoke_commit" "portal_commit" "check"