@consiliency/agent-board-schema 1.22.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 (60) hide show
  1. package/fixtures/already-applied.json +36 -0
  2. package/migrations/20260901000100_agent_board_atomic_fleet_onboarding.sql +1496 -0
  3. package/migrations/20260901000110_agent_board_fleet_onboarding_ceiling_lock.sql +604 -0
  4. package/migrations/20260901000120_agent_board_human_revocation_evidence_completeness.sql +78 -0
  5. package/migrations/20260901000130_agent_board_fedsession_human_revocation_gate.sql +74 -0
  6. package/migrations/20260901000140_agent_board_fedsession_board_owner_lock_order.sql +102 -0
  7. package/migrations/20260902000100_agent_board_outbox_wake_ordering.sql +184 -0
  8. package/migrations/20260903000100_agent_board_enroll_identity_board_owner_lock_order.sql +604 -0
  9. package/migrations/20260903000200_agent_board_fedsession_provider_absence_gate.sql +177 -0
  10. package/migrations/20260904000100_agent_board_wake_recovery_surface.sql +155 -0
  11. package/package.json +1 -1
  12. package/schema-manifest.json +84 -3
  13. package/src/tooling.test.mjs +2 -2
  14. package/tests/agent_board_atomic_fleet_onboarding.test.sql +623 -0
  15. package/tests/agent_board_atomic_fleet_onboarding_backfill.test.sql +142 -0
  16. package/tests/agent_board_atomic_fleet_onboarding_runtime.test.sql +1250 -0
  17. package/tests/agent_board_enroll_federated_identity.test.sql +3 -3
  18. package/tests/agent_board_enroll_pop_binding.test.sql +13 -3
  19. package/tests/agent_board_enrollment_audit_content.test.sql +11 -7
  20. package/tests/agent_board_federated_lock_order_class.test.sql +390 -0
  21. package/tests/agent_board_fedsession.test.sql +46 -2
  22. package/tests/agent_board_fedsession_provider_absence_gate.test.sql +170 -0
  23. package/tests/agent_board_inbox_reads.test.sql +16 -19
  24. package/tests/agent_board_outbox_wake_ordering.test.sql +452 -0
  25. package/tests/agent_board_portal_offline_invariant.test.sql +1 -1
  26. package/tests/agent_board_roomlink.test.sql +2 -2
  27. package/tests/agent_board_wake_recovery.test.sql +756 -0
  28. package/tests/isolation/expected/atomic_fedsession_fleet_lock_order.out +79 -0
  29. package/tests/isolation/expected/atomic_fedsession_human_revoke.out +87 -0
  30. package/tests/isolation/expected/atomic_fleet_authority_races.out +469 -0
  31. package/tests/isolation/expected/atomic_fleet_binding_revoke.out +103 -0
  32. package/tests/isolation/expected/atomic_fleet_board_archive.out +117 -0
  33. package/tests/isolation/expected/atomic_fleet_human_fresh_revoke.out +136 -0
  34. package/tests/isolation/expected/atomic_fleet_identity_disposition.out +61 -0
  35. package/tests/isolation/expected/atomic_fleet_lifecycle_races.out +1479 -0
  36. package/tests/isolation/expected/atomic_fleet_onboarding.out +75 -0
  37. package/tests/isolation/expected/atomic_fleet_subtree_lock_order.out +60 -0
  38. package/tests/isolation/expected/ceiling_setter_lock_before_upsert.out +95 -0
  39. package/tests/isolation/expected/enroll_identity_board_owner_lock_order.out +55 -0
  40. package/tests/isolation/expected/fedsession_provider_absent_owner_lock.out +37 -0
  41. package/tests/isolation/expected/onboarding_ceiling_lock_order.out +123 -0
  42. package/tests/isolation/expected/outbox_wake_ordering.out +86 -0
  43. package/tests/isolation/expected/wake_recovery_late_commit.out +89 -0
  44. package/tests/isolation/specs/atomic_fedsession_fleet_lock_order.spec +117 -0
  45. package/tests/isolation/specs/atomic_fedsession_human_revoke.spec +66 -0
  46. package/tests/isolation/specs/atomic_fleet_authority_races.spec +235 -0
  47. package/tests/isolation/specs/atomic_fleet_binding_revoke.spec +127 -0
  48. package/tests/isolation/specs/atomic_fleet_board_archive.spec +134 -0
  49. package/tests/isolation/specs/atomic_fleet_human_fresh_revoke.spec +142 -0
  50. package/tests/isolation/specs/atomic_fleet_identity_disposition.spec +118 -0
  51. package/tests/isolation/specs/atomic_fleet_lifecycle_races.spec +244 -0
  52. package/tests/isolation/specs/atomic_fleet_onboarding.spec +106 -0
  53. package/tests/isolation/specs/atomic_fleet_subtree_lock_order.spec +147 -0
  54. package/tests/isolation/specs/ceiling_setter_lock_before_upsert.spec +117 -0
  55. package/tests/isolation/specs/enroll_identity_board_owner_lock_order.spec +117 -0
  56. package/tests/isolation/specs/fedsession_provider_absent_owner_lock.spec +63 -0
  57. package/tests/isolation/specs/onboarding_ceiling_lock_order.spec +183 -0
  58. package/tests/isolation/specs/outbox_wake_ordering.spec +202 -0
  59. package/tests/isolation/specs/wake_recovery_late_commit.spec +207 -0
  60. package/tests/seeds/20260901000100_agent_board_atomic_fleet_onboarding.sql.pre.sql +110 -0
@@ -0,0 +1,75 @@
1
+ Parsed test spec with 3 sessions
2
+
3
+ starting permutation: first_begin first_onboard second_begin second_onboard first_commit second_commit check
4
+ count
5
+ -----
6
+ 1
7
+ (1 row)
8
+
9
+ step first_begin: BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role';
10
+ step first_onboard:
11
+ select identity_disposition, membership_disposition, binding_disposition
12
+ from agent_board.onboard_federated_fleet_agent(
13
+ 'https://atomic-race.test', 'message-board', 'human-race',
14
+ jsonb_build_object('iss','https://atomic-race.test','aud','message-board','sub','human-race','iat',100),
15
+ 'atomic-race-agent',
16
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0',
17
+ 'raw_ed25519_base64url',
18
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8',
19
+ true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
20
+ (select code from agent_board.board_invite_tokens where created_by_agent_id = '16220000-0000-0000-0000-000000000001'),
21
+ (select id from agent_board.boards where slug = 'atomic-race-board'),
22
+ '16220000-0000-0000-0000-000000000003',
23
+ 'codex', 'phase-loop', 'message-board', 'sha256:atomic-race-repo',
24
+ 'worker', 'phase_worker', 'atomic-race-agent'
25
+ );
26
+
27
+ identity_disposition|membership_disposition|binding_disposition
28
+ --------------------+----------------------+-------------------
29
+ created |created |created
30
+ (1 row)
31
+
32
+ step second_begin: BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role';
33
+ step second_onboard:
34
+ select identity_disposition, membership_disposition, binding_disposition
35
+ from agent_board.onboard_federated_fleet_agent(
36
+ 'https://atomic-race.test', 'message-board', 'human-race',
37
+ jsonb_build_object('iss','https://atomic-race.test','aud','message-board','sub','human-race','iat',200,'jti','rotated'),
38
+ 'atomic-race-agent',
39
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0',
40
+ 'raw_ed25519_base64url',
41
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8',
42
+ true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
43
+ (select code from agent_board.board_invite_tokens where created_by_agent_id = '16220000-0000-0000-0000-000000000001'),
44
+ (select id from agent_board.boards where slug = 'atomic-race-board'),
45
+ '16220000-0000-0000-0000-000000000003',
46
+ 'codex', 'phase-loop', 'message-board', 'sha256:atomic-race-repo',
47
+ 'worker', 'phase_worker', 'atomic-race-agent'
48
+ );
49
+ <waiting ...>
50
+ step first_commit: COMMIT;
51
+ step second_onboard: <... completed>
52
+ identity_disposition|membership_disposition|binding_disposition
53
+ --------------------+----------------------+-------------------
54
+ reused |reused |reused
55
+ (1 row)
56
+
57
+ step second_commit: COMMIT;
58
+ step check:
59
+ select count(*) as agents,
60
+ (select count(*) from agent_board.agent_signing_keys k
61
+ join agent_board.agents a on a.id=k.agent_id
62
+ where a.handle='atomic-race-agent') as keys,
63
+ (select count(*) from agent_board.board_invite_redemptions r
64
+ join agent_board.board_invite_tokens i on i.id=r.invite_id
65
+ where i.created_by_agent_id='16220000-0000-0000-0000-000000000001') as redemptions,
66
+ (select count(*) from agent_board.fleet_machine_agents b
67
+ join agent_board.agents a on a.id=b.agent_id
68
+ where a.handle='atomic-race-agent') as bindings
69
+ from agent_board.agents where handle='atomic-race-agent';
70
+
71
+ agents|keys|redemptions|bindings
72
+ ------+----+-----------+--------
73
+ 1| 1| 1| 1
74
+ (1 row)
75
+
@@ -0,0 +1,60 @@
1
+ Parsed test spec with 4 sessions
2
+
3
+ starting permutation: blocker_begin blocker_lock retry_begin retry_onboard subtree_begin revoke_human_subtree blocker_commit subtree_commit retry_commit check
4
+ step blocker_begin: BEGIN;
5
+ step blocker_lock:
6
+ select pg_advisory_xact_lock(hashtextextended('sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA', 0));
7
+
8
+ pg_advisory_xact_lock
9
+ ---------------------
10
+
11
+ (1 row)
12
+
13
+ step retry_begin: BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role';
14
+ step retry_onboard:
15
+ select identity_disposition, binding_disposition
16
+ from agent_board.onboard_federated_fleet_agent(
17
+ 'https://atomic-subtree.test', 'message-board', 'human-subtree',
18
+ jsonb_build_object('iss','https://atomic-subtree.test','aud','message-board','sub','human-subtree','iat',200),
19
+ 'atomic-subtree-agent',
20
+ 'yd_DIFGWGusVg3SbktDJQ1bE5UWvtR33xln4b05JIhk',
21
+ 'raw_ed25519_base64url',
22
+ 'sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA',
23
+ true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
24
+ (select code from agent_board.board_invite_tokens where created_by_agent_id='ffffffff-ffff-ffff-ffff-ffffffffff01'),
25
+ (select id from agent_board.boards where slug='atomic-subtree-board'),
26
+ '16270000-0000-0000-0000-000000000003', 'codex', 'phase-loop',
27
+ 'message-board', 'sha256:atomic-subtree-repo', 'worker', 'phase_worker',
28
+ 'atomic-subtree-agent'
29
+ );
30
+ <waiting ...>
31
+ step subtree_begin: BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role';
32
+ step revoke_human_subtree:
33
+ select revoked_agent_count
34
+ from agent_board.revoke_human_subtree(
35
+ (select owner_user_id from agent_board.agents where handle='atomic-subtree-agent'),
36
+ 'ffffffff-ffff-ffff-ffff-ffffffffff01', 'isolation subtree revoke'
37
+ );
38
+
39
+ revoked_agent_count
40
+ -------------------
41
+ 2
42
+ (1 row)
43
+
44
+ step blocker_commit: COMMIT;
45
+ step subtree_commit: COMMIT;
46
+ step retry_onboard: <... completed>
47
+ ERROR: human owner has been revoked
48
+ step retry_commit: COMMIT;
49
+ step check:
50
+ select
51
+ (select status from agent_board.agents where id='ffffffff-ffff-ffff-ffff-ffffffffff01') as creator_status,
52
+ (select status from agent_board.agents where handle='atomic-subtree-agent') as enrolled_status,
53
+ (select status from agent_board.agent_signing_keys where fingerprint='sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA') as key_status,
54
+ (select count(*) from agent_board.fleet_machine_agents where machine_id='16270000-0000-0000-0000-000000000003') as bindings;
55
+
56
+ creator_status|enrolled_status|key_status|bindings
57
+ --------------+---------------+----------+--------
58
+ revoked |revoked |revoked | 1
59
+ (1 row)
60
+
@@ -0,0 +1,95 @@
1
+ Parsed test spec with 4 sessions
2
+
3
+ starting permutation: holder_begin hold_ceiling_lock setter_begin set_ceiling probe_begin probe_ceiling_row probe_commit holder_commit setter_commit check
4
+ step holder_begin: BEGIN;
5
+ step hold_ceiling_lock:
6
+ select agent_board._lock_board_authority_ceiling(
7
+ (select id from agent_board.boards where slug='ceiling-order-board')) as locked;
8
+
9
+ locked
10
+ ------
11
+
12
+ (1 row)
13
+
14
+ step setter_begin:
15
+ BEGIN;
16
+ SET LOCAL ROLE authenticated;
17
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
18
+ SET LOCAL "request.jwt.claim.sub" = '19600000-0000-0000-0000-0000000000a1';
19
+
20
+ step set_ceiling:
21
+ select ceiling_max_grantable_role from agent_board.set_board_authority_ceiling(
22
+ (select id from agent_board.boards where slug='ceiling-order-board'),
23
+ 'member'
24
+ );
25
+ <waiting ...>
26
+ step probe_begin: BEGIN;
27
+ step probe_ceiling_row:
28
+ select max_grantable_role from agent_board.board_authority_ceilings
29
+ where board_id = (select id from agent_board.boards where slug='ceiling-order-board')
30
+ for update nowait;
31
+
32
+ max_grantable_role
33
+ ------------------
34
+ admin
35
+ (1 row)
36
+
37
+ step probe_commit: COMMIT;
38
+ step holder_commit: COMMIT;
39
+ step set_ceiling: <... completed>
40
+ ceiling_max_grantable_role
41
+ --------------------------
42
+ member
43
+ (1 row)
44
+
45
+ step setter_commit: COMMIT;
46
+ step check:
47
+ select max_grantable_role from agent_board.board_authority_ceilings
48
+ where board_id = (select id from agent_board.boards where slug='ceiling-order-board');
49
+
50
+ max_grantable_role
51
+ ------------------
52
+ member
53
+ (1 row)
54
+
55
+
56
+ starting permutation: setter_begin set_ceiling setter_commit probe_begin probe_ceiling_row probe_commit check
57
+ step setter_begin:
58
+ BEGIN;
59
+ SET LOCAL ROLE authenticated;
60
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
61
+ SET LOCAL "request.jwt.claim.sub" = '19600000-0000-0000-0000-0000000000a1';
62
+
63
+ step set_ceiling:
64
+ select ceiling_max_grantable_role from agent_board.set_board_authority_ceiling(
65
+ (select id from agent_board.boards where slug='ceiling-order-board'),
66
+ 'member'
67
+ );
68
+
69
+ ceiling_max_grantable_role
70
+ --------------------------
71
+ member
72
+ (1 row)
73
+
74
+ step setter_commit: COMMIT;
75
+ step probe_begin: BEGIN;
76
+ step probe_ceiling_row:
77
+ select max_grantable_role from agent_board.board_authority_ceilings
78
+ where board_id = (select id from agent_board.boards where slug='ceiling-order-board')
79
+ for update nowait;
80
+
81
+ max_grantable_role
82
+ ------------------
83
+ member
84
+ (1 row)
85
+
86
+ step probe_commit: COMMIT;
87
+ step check:
88
+ select max_grantable_role from agent_board.board_authority_ceilings
89
+ where board_id = (select id from agent_board.boards where slug='ceiling-order-board');
90
+
91
+ max_grantable_role
92
+ ------------------
93
+ member
94
+ (1 row)
95
+
@@ -0,0 +1,55 @@
1
+ Parsed test spec with 4 sessions
2
+
3
+ starting permutation: ohold_begin ohold_lock enroll_begin enroll_enroll bprobe_board_nowait ohold_commit enroll_commit check
4
+ step ohold_begin: BEGIN;
5
+ step ohold_lock:
6
+ select 1 as locked from auth.users u
7
+ where u.id = (select uid from lo194_owner)
8
+ for update;
9
+
10
+ locked
11
+ ------
12
+ 1
13
+ (1 row)
14
+
15
+ step enroll_begin: BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role';
16
+ step enroll_enroll:
17
+ select agent_handle, invite_redeemed
18
+ from agent_board.enroll_federated_identity(
19
+ 'https://lo194-iso.test', 'message-board', 'iso-human',
20
+ jsonb_build_object('iss','https://lo194-iso.test','aud','message-board','sub','iso-human'),
21
+ 'lo194-iso-agent',
22
+ public.test_pubkey('lo194-iso-k1'), 'raw_ed25519_base64url',
23
+ public.test_key_fingerprint('lo194-iso-k1'),
24
+ true, null, 'agent', ARRAY[]::text[], ARRAY[]::text[],
25
+ 'lo194-iso-code'
26
+ );
27
+ <waiting ...>
28
+ step bprobe_board_nowait:
29
+ select slug from agent_board.boards where slug='lo194-iso-board' for update nowait;
30
+
31
+ ERROR: could not obtain lock on row in relation "boards"
32
+ step ohold_commit: COMMIT;
33
+ step enroll_enroll: <... completed>
34
+ agent_handle |invite_redeemed
35
+ ---------------+---------------
36
+ lo194-iso-agent|t
37
+ (1 row)
38
+
39
+ step enroll_commit: COMMIT;
40
+ step check:
41
+ select
42
+ (select count(*) from agent_board.board_memberships m
43
+ join agent_board.agents a on a.id = m.agent_id
44
+ where m.board_id = (select id from agent_board.boards where slug='lo194-iso-board')
45
+ and a.handle = 'lo194-iso-agent'
46
+ and m.membership_state = 'joined') as enrolled_agent_memberships,
47
+ (select count(*) from agent_board.board_invite_redemptions r
48
+ join agent_board.board_invite_tokens t on t.id = r.invite_id
49
+ where t.code = 'lo194-iso-code') as redemptions;
50
+
51
+ enrolled_agent_memberships|redemptions
52
+ --------------------------+-----------
53
+ 1| 1
54
+ (1 row)
55
+
@@ -0,0 +1,37 @@
1
+ Parsed test spec with 3 sessions
2
+
3
+ starting permutation: ohold_begin ohold_lock portal_begin portal_enroll ohold_commit portal_commit check
4
+ step ohold_begin: BEGIN;
5
+ step ohold_lock:
6
+ select 1 as locked from auth.users u
7
+ where u.id = (select uid from lo193_owner)
8
+ for update;
9
+
10
+ locked
11
+ ------
12
+ 1
13
+ (1 row)
14
+
15
+ step portal_begin: BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role';
16
+ step portal_enroll:
17
+ select status from agent_board.enroll_federated_human(
18
+ 'https://lo193-iso.test', 'message-board', 'iso-orphan',
19
+ jsonb_build_object('sub','iso-orphan'), 'Iso Orphan'
20
+ );
21
+
22
+ ERROR: issuer/audience not in the identity-provider allowlist (rejected before any owner or board lock)
23
+ step ohold_commit: COMMIT;
24
+ step portal_commit: COMMIT;
25
+ step check:
26
+ select
27
+ (select count(*) from agent_board.agents a
28
+ where a.kind = 'human'
29
+ and a.metadata #>> ARRAY['federation','subject'] = 'iso-orphan') as human_agents,
30
+ (select count(*) from agent_board.identity_providers ip
31
+ where ip.issuer = 'https://lo193-iso.test') as providers;
32
+
33
+ human_agents|providers
34
+ ------------+---------
35
+ 0| 0
36
+ (1 row)
37
+
@@ -0,0 +1,123 @@
1
+ Parsed test spec with 4 sessions
2
+
3
+ starting permutation: holder_begin hold_ceiling_lock onboard_begin onboard_call probe_begin probe_boards_row probe_commit holder_commit onboard_commit check
4
+ count
5
+ -----
6
+ 1
7
+ (1 row)
8
+
9
+ step holder_begin: BEGIN;
10
+ step hold_ceiling_lock:
11
+ select agent_board._lock_board_authority_ceiling(
12
+ (select id from agent_board.boards where slug='onboard-ceiling-board')) as locked;
13
+
14
+ locked
15
+ ------
16
+
17
+ (1 row)
18
+
19
+ step onboard_begin: BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role';
20
+ step onboard_call:
21
+ select identity_disposition, membership_disposition, binding_disposition
22
+ from agent_board.onboard_federated_fleet_agent(
23
+ 'https://onboard-ceiling.test', 'message-board', 'human-onboard-ceiling',
24
+ jsonb_build_object('iss','https://onboard-ceiling.test','aud','message-board','sub','human-onboard-ceiling'),
25
+ 'onboard-ceiling-agent',
26
+ 'yd_DIFGWGusVg3SbktDJQ1bE5UWvtR33xln4b05JIhk',
27
+ 'raw_ed25519_base64url',
28
+ 'sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA',
29
+ true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
30
+ (select code from agent_board.board_invite_tokens where created_by_agent_id='19610000-0000-0000-0000-000000000001'),
31
+ (select id from agent_board.boards where slug='onboard-ceiling-board'),
32
+ '19610000-0000-0000-0000-000000000003', 'codex', 'phase-loop',
33
+ 'message-board', 'sha256:onboard-ceiling-repo', 'worker', 'phase_worker',
34
+ 'onboard-ceiling-agent'
35
+ );
36
+ <waiting ...>
37
+ step probe_begin: BEGIN;
38
+ step probe_boards_row:
39
+ select status from agent_board.boards
40
+ where id = (select id from agent_board.boards where slug='onboard-ceiling-board')
41
+ for update nowait;
42
+
43
+ status
44
+ ------
45
+ active
46
+ (1 row)
47
+
48
+ step probe_commit: COMMIT;
49
+ step holder_commit: COMMIT;
50
+ step onboard_call: <... completed>
51
+ identity_disposition|membership_disposition|binding_disposition
52
+ --------------------+----------------------+-------------------
53
+ created |created |created
54
+ (1 row)
55
+
56
+ step onboard_commit: COMMIT;
57
+ step check:
58
+ select
59
+ (select count(*) from agent_board.agents where handle='onboard-ceiling-agent') as onboarded_agents,
60
+ (select count(*) from agent_board.board_memberships bm
61
+ where bm.board_id=(select id from agent_board.boards where slug='onboard-ceiling-board')
62
+ and bm.agent_id in (select id from agent_board.agents where handle='onboard-ceiling-agent')) as memberships;
63
+
64
+ onboarded_agents|memberships
65
+ ----------------+-----------
66
+ 1| 1
67
+ (1 row)
68
+
69
+
70
+ starting permutation: onboard_begin onboard_call onboard_commit probe_begin probe_boards_row probe_commit check
71
+ count
72
+ -----
73
+ 1
74
+ (1 row)
75
+
76
+ step onboard_begin: BEGIN; SET LOCAL "request.jwt.claim.role" = 'service_role';
77
+ step onboard_call:
78
+ select identity_disposition, membership_disposition, binding_disposition
79
+ from agent_board.onboard_federated_fleet_agent(
80
+ 'https://onboard-ceiling.test', 'message-board', 'human-onboard-ceiling',
81
+ jsonb_build_object('iss','https://onboard-ceiling.test','aud','message-board','sub','human-onboard-ceiling'),
82
+ 'onboard-ceiling-agent',
83
+ 'yd_DIFGWGusVg3SbktDJQ1bE5UWvtR33xln4b05JIhk',
84
+ 'raw_ed25519_base64url',
85
+ 'sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA',
86
+ true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
87
+ (select code from agent_board.board_invite_tokens where created_by_agent_id='19610000-0000-0000-0000-000000000001'),
88
+ (select id from agent_board.boards where slug='onboard-ceiling-board'),
89
+ '19610000-0000-0000-0000-000000000003', 'codex', 'phase-loop',
90
+ 'message-board', 'sha256:onboard-ceiling-repo', 'worker', 'phase_worker',
91
+ 'onboard-ceiling-agent'
92
+ );
93
+
94
+ identity_disposition|membership_disposition|binding_disposition
95
+ --------------------+----------------------+-------------------
96
+ created |created |created
97
+ (1 row)
98
+
99
+ step onboard_commit: COMMIT;
100
+ step probe_begin: BEGIN;
101
+ step probe_boards_row:
102
+ select status from agent_board.boards
103
+ where id = (select id from agent_board.boards where slug='onboard-ceiling-board')
104
+ for update nowait;
105
+
106
+ status
107
+ ------
108
+ active
109
+ (1 row)
110
+
111
+ step probe_commit: COMMIT;
112
+ step check:
113
+ select
114
+ (select count(*) from agent_board.agents where handle='onboard-ceiling-agent') as onboarded_agents,
115
+ (select count(*) from agent_board.board_memberships bm
116
+ where bm.board_id=(select id from agent_board.boards where slug='onboard-ceiling-board')
117
+ and bm.agent_id in (select id from agent_board.agents where handle='onboard-ceiling-agent')) as memberships;
118
+
119
+ onboarded_agents|memberships
120
+ ----------------+-----------
121
+ 1| 1
122
+ (1 row)
123
+
@@ -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,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
+