@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
@@ -0,0 +1,165 @@
1
+ Parsed test spec with 3 sessions
2
+
3
+ starting permutation: a_begin a_mint b_begin b_mint a_commit b_commit check
4
+ step a_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
5
+ step a_mint:
6
+ do $$ begin
7
+ perform * from agent_board.mint_delegated_child('78000000-0000-4000-8000-000000000001', 'sid-limit-a', '[]',
8
+ public.test_pubkey('sid-limit-a'), interval '1 hour', false, 'codex', 'limit-a');
9
+ end $$;
10
+
11
+ step b_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
12
+ step b_mint:
13
+ do $$ begin
14
+ perform * from agent_board.mint_delegated_child('78000000-0000-4000-8000-000000000001', 'sid-limit-b', '[]',
15
+ public.test_pubkey('sid-limit-b'), interval '1 hour', false, 'codex', 'limit-b');
16
+ end $$;
17
+ <waiting ...>
18
+ step a_commit: COMMIT;
19
+ step b_mint: <... completed>
20
+ ERROR: identity_limit_hourly_exceeded
21
+ step b_commit: COMMIT;
22
+ step check:
23
+ select count(*) as mixed_hourly, count(*) filter (where revoked_at is not null) as tombstoned_hourly
24
+ from agent_board.delegation_grants where root_agent_id = '78000000-0000-4000-8000-000000000001';
25
+ select count(*) as new_principals from agent_board.agents where handle in ('sid-limit-a', 'sid-limit-b');
26
+ select count(*) as aliases from agent_board.session_id_aliases where root_agent_id = '78000000-0000-4000-8000-000000000001';
27
+
28
+ mixed_hourly|tombstoned_hourly
29
+ ------------+-----------------
30
+ 60| 29
31
+ (1 row)
32
+
33
+ new_principals
34
+ --------------
35
+ 1
36
+ (1 row)
37
+
38
+ aliases
39
+ -------
40
+ 1
41
+ (1 row)
42
+
43
+
44
+ starting permutation: b_begin b_mint a_begin a_mint b_commit a_commit check
45
+ step b_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
46
+ step b_mint:
47
+ do $$ begin
48
+ perform * from agent_board.mint_delegated_child('78000000-0000-4000-8000-000000000001', 'sid-limit-b', '[]',
49
+ public.test_pubkey('sid-limit-b'), interval '1 hour', false, 'codex', 'limit-b');
50
+ end $$;
51
+
52
+ step a_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
53
+ step a_mint:
54
+ do $$ begin
55
+ perform * from agent_board.mint_delegated_child('78000000-0000-4000-8000-000000000001', 'sid-limit-a', '[]',
56
+ public.test_pubkey('sid-limit-a'), interval '1 hour', false, 'codex', 'limit-a');
57
+ end $$;
58
+ <waiting ...>
59
+ step b_commit: COMMIT;
60
+ step a_mint: <... completed>
61
+ ERROR: identity_limit_hourly_exceeded
62
+ step a_commit: COMMIT;
63
+ step check:
64
+ select count(*) as mixed_hourly, count(*) filter (where revoked_at is not null) as tombstoned_hourly
65
+ from agent_board.delegation_grants where root_agent_id = '78000000-0000-4000-8000-000000000001';
66
+ select count(*) as new_principals from agent_board.agents where handle in ('sid-limit-a', 'sid-limit-b');
67
+ select count(*) as aliases from agent_board.session_id_aliases where root_agent_id = '78000000-0000-4000-8000-000000000001';
68
+
69
+ mixed_hourly|tombstoned_hourly
70
+ ------------+-----------------
71
+ 60| 29
72
+ (1 row)
73
+
74
+ new_principals
75
+ --------------
76
+ 1
77
+ (1 row)
78
+
79
+ aliases
80
+ -------
81
+ 1
82
+ (1 row)
83
+
84
+
85
+ starting permutation: a_begin a_mint b_begin b_duplicate a_commit b_commit check
86
+ step a_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
87
+ step a_mint:
88
+ do $$ begin
89
+ perform * from agent_board.mint_delegated_child('78000000-0000-4000-8000-000000000001', 'sid-limit-a', '[]',
90
+ public.test_pubkey('sid-limit-a'), interval '1 hour', false, 'codex', 'limit-a');
91
+ end $$;
92
+
93
+ step b_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
94
+ step b_duplicate:
95
+ do $$ begin
96
+ perform * from agent_board.mint_delegated_child('78000000-0000-4000-8000-000000000001', 'sid-limit-b', '[]',
97
+ public.test_pubkey('sid-limit-b'), interval '1 hour', false, 'codex', 'limit-a');
98
+ end $$;
99
+ <waiting ...>
100
+ step a_commit: COMMIT;
101
+ step b_duplicate: <... completed>
102
+ ERROR: identity_lease_live
103
+ step b_commit: COMMIT;
104
+ step check:
105
+ select count(*) as mixed_hourly, count(*) filter (where revoked_at is not null) as tombstoned_hourly
106
+ from agent_board.delegation_grants where root_agent_id = '78000000-0000-4000-8000-000000000001';
107
+ select count(*) as new_principals from agent_board.agents where handle in ('sid-limit-a', 'sid-limit-b');
108
+ select count(*) as aliases from agent_board.session_id_aliases where root_agent_id = '78000000-0000-4000-8000-000000000001';
109
+
110
+ mixed_hourly|tombstoned_hourly
111
+ ------------+-----------------
112
+ 60| 29
113
+ (1 row)
114
+
115
+ new_principals
116
+ --------------
117
+ 1
118
+ (1 row)
119
+
120
+ aliases
121
+ -------
122
+ 1
123
+ (1 row)
124
+
125
+
126
+ starting permutation: b_begin b_duplicate a_begin a_mint b_commit a_commit check
127
+ step b_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
128
+ step b_duplicate:
129
+ do $$ begin
130
+ perform * from agent_board.mint_delegated_child('78000000-0000-4000-8000-000000000001', 'sid-limit-b', '[]',
131
+ public.test_pubkey('sid-limit-b'), interval '1 hour', false, 'codex', 'limit-a');
132
+ end $$;
133
+
134
+ step a_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
135
+ step a_mint:
136
+ do $$ begin
137
+ perform * from agent_board.mint_delegated_child('78000000-0000-4000-8000-000000000001', 'sid-limit-a', '[]',
138
+ public.test_pubkey('sid-limit-a'), interval '1 hour', false, 'codex', 'limit-a');
139
+ end $$;
140
+ <waiting ...>
141
+ step b_commit: COMMIT;
142
+ step a_mint: <... completed>
143
+ ERROR: identity_lease_live
144
+ step a_commit: COMMIT;
145
+ step check:
146
+ select count(*) as mixed_hourly, count(*) filter (where revoked_at is not null) as tombstoned_hourly
147
+ from agent_board.delegation_grants where root_agent_id = '78000000-0000-4000-8000-000000000001';
148
+ select count(*) as new_principals from agent_board.agents where handle in ('sid-limit-a', 'sid-limit-b');
149
+ select count(*) as aliases from agent_board.session_id_aliases where root_agent_id = '78000000-0000-4000-8000-000000000001';
150
+
151
+ mixed_hourly|tombstoned_hourly
152
+ ------------+-----------------
153
+ 60| 29
154
+ (1 row)
155
+
156
+ new_principals
157
+ --------------
158
+ 1
159
+ (1 row)
160
+
161
+ aliases
162
+ -------
163
+ 1
164
+ (1 row)
165
+
@@ -0,0 +1,235 @@
1
+ Parsed test spec with 3 sessions
2
+
3
+ starting permutation: a_begin a_link b_begin b_same a_commit b_commit check
4
+ step a_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role'; SET LOCAL "request.jwt.claim.sub" = '71000000-0000-4000-8000-000000000001';
5
+ step a_link: select agent_board.link_session_alias('72000000-0000-4000-8000-000000000002', '0', 'continued-a');
6
+ link_session_alias
7
+ ------------------
8
+
9
+ (1 row)
10
+
11
+ step b_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role'; SET LOCAL "request.jwt.claim.sub" = '71000000-0000-4000-8000-000000000001';
12
+ step b_same: select agent_board.link_session_alias('72000000-0000-4000-8000-000000000002', '0', 'continued-a'); <waiting ...>
13
+ step a_commit: COMMIT;
14
+ step b_same: <... completed>
15
+ link_session_alias
16
+ ------------------
17
+
18
+ (1 row)
19
+
20
+ step b_commit: COMMIT;
21
+ step check:
22
+ select count(*) as aliases, count(distinct identity_agent_id) as identities
23
+ from agent_board.session_id_aliases where root_agent_id = '72000000-0000-4000-8000-000000000001';
24
+ select credential_epoch, holder_secret_hash = extensions.digest('isolation-holder', 'sha256') as unchanged_holder
25
+ from agent_board.session_identities where agent_id = '72000000-0000-4000-8000-000000000002';
26
+ select granted_scopes, role from agent_board.delegation_grants g join agent_board.board_memberships bm on bm.agent_id = g.child_agent_id
27
+ where g.child_agent_id = '72000000-0000-4000-8000-000000000002' and bm.board_id = '74000000-0000-4000-8000-000000000002';
28
+
29
+ aliases|identities
30
+ -------+----------
31
+ 2| 1
32
+ (1 row)
33
+
34
+ credential_epoch|unchanged_holder
35
+ ----------------+----------------
36
+ 0|t
37
+ (1 row)
38
+
39
+ granted_scopes |role
40
+ -----------------+-----
41
+ ["read", "write"]|admin
42
+ (1 row)
43
+
44
+
45
+ starting permutation: b_begin b_same a_begin a_link b_commit a_commit check
46
+ step b_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role'; SET LOCAL "request.jwt.claim.sub" = '71000000-0000-4000-8000-000000000001';
47
+ step b_same: select agent_board.link_session_alias('72000000-0000-4000-8000-000000000002', '0', 'continued-a');
48
+ link_session_alias
49
+ ------------------
50
+
51
+ (1 row)
52
+
53
+ step a_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role'; SET LOCAL "request.jwt.claim.sub" = '71000000-0000-4000-8000-000000000001';
54
+ step a_link: select agent_board.link_session_alias('72000000-0000-4000-8000-000000000002', '0', 'continued-a'); <waiting ...>
55
+ step b_commit: COMMIT;
56
+ step a_link: <... completed>
57
+ link_session_alias
58
+ ------------------
59
+
60
+ (1 row)
61
+
62
+ step a_commit: COMMIT;
63
+ step check:
64
+ select count(*) as aliases, count(distinct identity_agent_id) as identities
65
+ from agent_board.session_id_aliases where root_agent_id = '72000000-0000-4000-8000-000000000001';
66
+ select credential_epoch, holder_secret_hash = extensions.digest('isolation-holder', 'sha256') as unchanged_holder
67
+ from agent_board.session_identities where agent_id = '72000000-0000-4000-8000-000000000002';
68
+ select granted_scopes, role from agent_board.delegation_grants g join agent_board.board_memberships bm on bm.agent_id = g.child_agent_id
69
+ where g.child_agent_id = '72000000-0000-4000-8000-000000000002' and bm.board_id = '74000000-0000-4000-8000-000000000002';
70
+
71
+ aliases|identities
72
+ -------+----------
73
+ 2| 1
74
+ (1 row)
75
+
76
+ credential_epoch|unchanged_holder
77
+ ----------------+----------------
78
+ 0|t
79
+ (1 row)
80
+
81
+ granted_scopes |role
82
+ -----------------+-----
83
+ ["read", "write"]|admin
84
+ (1 row)
85
+
86
+
87
+ starting permutation: a_begin a_link b_begin b_other a_commit b_commit check
88
+ step a_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role'; SET LOCAL "request.jwt.claim.sub" = '71000000-0000-4000-8000-000000000001';
89
+ step a_link: select agent_board.link_session_alias('72000000-0000-4000-8000-000000000002', '0', 'continued-a');
90
+ link_session_alias
91
+ ------------------
92
+
93
+ (1 row)
94
+
95
+ step b_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role'; SET LOCAL "request.jwt.claim.sub" = '71000000-0000-4000-8000-000000000001';
96
+ step b_other: select agent_board.link_session_alias('72000000-0000-4000-8000-000000000002', '0', 'continued-b'); <waiting ...>
97
+ step a_commit: COMMIT;
98
+ step b_other: <... completed>
99
+ link_session_alias
100
+ ------------------
101
+
102
+ (1 row)
103
+
104
+ step b_commit: COMMIT;
105
+ step check:
106
+ select count(*) as aliases, count(distinct identity_agent_id) as identities
107
+ from agent_board.session_id_aliases where root_agent_id = '72000000-0000-4000-8000-000000000001';
108
+ select credential_epoch, holder_secret_hash = extensions.digest('isolation-holder', 'sha256') as unchanged_holder
109
+ from agent_board.session_identities where agent_id = '72000000-0000-4000-8000-000000000002';
110
+ select granted_scopes, role from agent_board.delegation_grants g join agent_board.board_memberships bm on bm.agent_id = g.child_agent_id
111
+ where g.child_agent_id = '72000000-0000-4000-8000-000000000002' and bm.board_id = '74000000-0000-4000-8000-000000000002';
112
+
113
+ aliases|identities
114
+ -------+----------
115
+ 3| 1
116
+ (1 row)
117
+
118
+ credential_epoch|unchanged_holder
119
+ ----------------+----------------
120
+ 0|t
121
+ (1 row)
122
+
123
+ granted_scopes |role
124
+ -----------------+-----
125
+ ["read", "write"]|admin
126
+ (1 row)
127
+
128
+
129
+ starting permutation: a_begin a_link b_begin b_narrow a_commit b_commit a_rebegin a_relink a_recommit check
130
+ step a_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role'; SET LOCAL "request.jwt.claim.sub" = '71000000-0000-4000-8000-000000000001';
131
+ step a_link: select agent_board.link_session_alias('72000000-0000-4000-8000-000000000002', '0', 'continued-a');
132
+ link_session_alias
133
+ ------------------
134
+
135
+ (1 row)
136
+
137
+ step b_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role'; SET LOCAL "request.jwt.claim.sub" = '71000000-0000-4000-8000-000000000001';
138
+ step b_narrow:
139
+ select role from agent_board.grant_board_role('74000000-0000-4000-8000-000000000002', '72000000-0000-4000-8000-000000000001', 'observer', '72000000-0000-4000-8000-000000000001');
140
+ select allowed_scopes from agent_board.upsert_delegation_policy('72000000-0000-4000-8000-000000000001', 'root_minted', '["read"]', 200, interval '8 hours', true);
141
+ <waiting ...>
142
+ step a_commit: COMMIT;
143
+ step b_narrow: <... completed>
144
+ role
145
+ --------
146
+ observer
147
+ (1 row)
148
+
149
+ allowed_scopes
150
+ --------------
151
+ ["read"]
152
+ (1 row)
153
+
154
+ step b_commit: COMMIT;
155
+ step a_rebegin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role'; SET LOCAL "request.jwt.claim.sub" = '71000000-0000-4000-8000-000000000001';
156
+ step a_relink: select agent_board.link_session_alias('72000000-0000-4000-8000-000000000002', '0', 'continued-a');
157
+ link_session_alias
158
+ ------------------
159
+
160
+ (1 row)
161
+
162
+ step a_recommit: COMMIT;
163
+ step check:
164
+ select count(*) as aliases, count(distinct identity_agent_id) as identities
165
+ from agent_board.session_id_aliases where root_agent_id = '72000000-0000-4000-8000-000000000001';
166
+ select credential_epoch, holder_secret_hash = extensions.digest('isolation-holder', 'sha256') as unchanged_holder
167
+ from agent_board.session_identities where agent_id = '72000000-0000-4000-8000-000000000002';
168
+ select granted_scopes, role from agent_board.delegation_grants g join agent_board.board_memberships bm on bm.agent_id = g.child_agent_id
169
+ where g.child_agent_id = '72000000-0000-4000-8000-000000000002' and bm.board_id = '74000000-0000-4000-8000-000000000002';
170
+
171
+ aliases|identities
172
+ -------+----------
173
+ 2| 1
174
+ (1 row)
175
+
176
+ credential_epoch|unchanged_holder
177
+ ----------------+----------------
178
+ 0|t
179
+ (1 row)
180
+
181
+ granted_scopes|role
182
+ --------------+--------
183
+ ["read"] |observer
184
+ (1 row)
185
+
186
+
187
+ starting permutation: b_begin b_narrow a_begin a_link b_commit a_commit check
188
+ step b_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role'; SET LOCAL "request.jwt.claim.sub" = '71000000-0000-4000-8000-000000000001';
189
+ step b_narrow:
190
+ select role from agent_board.grant_board_role('74000000-0000-4000-8000-000000000002', '72000000-0000-4000-8000-000000000001', 'observer', '72000000-0000-4000-8000-000000000001');
191
+ select allowed_scopes from agent_board.upsert_delegation_policy('72000000-0000-4000-8000-000000000001', 'root_minted', '["read"]', 200, interval '8 hours', true);
192
+
193
+ role
194
+ --------
195
+ observer
196
+ (1 row)
197
+
198
+ allowed_scopes
199
+ --------------
200
+ ["read"]
201
+ (1 row)
202
+
203
+ step a_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role'; SET LOCAL "request.jwt.claim.sub" = '71000000-0000-4000-8000-000000000001';
204
+ step a_link: select agent_board.link_session_alias('72000000-0000-4000-8000-000000000002', '0', 'continued-a'); <waiting ...>
205
+ step b_commit: COMMIT;
206
+ step a_link: <... completed>
207
+ link_session_alias
208
+ ------------------
209
+
210
+ (1 row)
211
+
212
+ step a_commit: COMMIT;
213
+ step check:
214
+ select count(*) as aliases, count(distinct identity_agent_id) as identities
215
+ from agent_board.session_id_aliases where root_agent_id = '72000000-0000-4000-8000-000000000001';
216
+ select credential_epoch, holder_secret_hash = extensions.digest('isolation-holder', 'sha256') as unchanged_holder
217
+ from agent_board.session_identities where agent_id = '72000000-0000-4000-8000-000000000002';
218
+ select granted_scopes, role from agent_board.delegation_grants g join agent_board.board_memberships bm on bm.agent_id = g.child_agent_id
219
+ where g.child_agent_id = '72000000-0000-4000-8000-000000000002' and bm.board_id = '74000000-0000-4000-8000-000000000002';
220
+
221
+ aliases|identities
222
+ -------+----------
223
+ 2| 1
224
+ (1 row)
225
+
226
+ credential_epoch|unchanged_holder
227
+ ----------------+----------------
228
+ 0|t
229
+ (1 row)
230
+
231
+ granted_scopes|role
232
+ --------------+--------
233
+ ["read"] |observer
234
+ (1 row)
235
+
@@ -0,0 +1,253 @@
1
+ Parsed test spec with 3 sessions
2
+
3
+ starting permutation: a_begin a_reclaim b_begin b_reclaim a_commit b_commit check
4
+ step a_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
5
+ step a_reclaim:
6
+ do $$ declare c record; begin
7
+ select * into c from agent_board.issue_signing_key_challenge('75000000-0000-4000-8000-000000000002', 'holder-a');
8
+ perform * from agent_board.mint_fleet_agent_session(c.challenge_id, split_part(c.challenge, ':', 3),
9
+ '76000000-0000-4000-8000-000000000001', '75000000-0000-4000-8000-000000000002', 900, null, 'resumed');
10
+ end; $$;
11
+
12
+ step b_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
13
+ step b_reclaim:
14
+ do $$ declare c record; begin
15
+ select * into c from agent_board.issue_signing_key_challenge('75000000-0000-4000-8000-000000000002', 'holder-b');
16
+ perform * from agent_board.mint_fleet_agent_session(c.challenge_id, split_part(c.challenge, ':', 3),
17
+ '76000000-0000-4000-8000-000000000002', '75000000-0000-4000-8000-000000000002', 900, null, 'resumed');
18
+ end; $$;
19
+ <waiting ...>
20
+ step a_commit: COMMIT;
21
+ step b_reclaim: <... completed>
22
+ ERROR: duplicate_live_session
23
+ step b_commit: COMMIT;
24
+ step check:
25
+ select credential_epoch, holder_secret_hash <> extensions.digest('old-holder', 'sha256') as rotated_holder,
26
+ a.session_id as bound_alias
27
+ from agent_board.session_identities si join agent_board.session_id_aliases a on a.id = si.lease_alias_id
28
+ where si.agent_id = '75000000-0000-4000-8000-000000000002';
29
+ select count(*) as tokens from agent_board.nonfleet_sessions where agent_id = '75000000-0000-4000-8000-000000000002';
30
+ BEGIN;
31
+ SET LOCAL ROLE authenticated;
32
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
33
+ SET LOCAL "request.jwt.claim.sub" = '74000000-0000-4000-8000-000000000001';
34
+ SET LOCAL "request.jwt.claim.identity_lease_epoch" = '0';
35
+ select agent_board.current_agent_id() is null as old_epoch_fenced;
36
+ SET LOCAL "request.jwt.claim.identity_lease_epoch" = '1';
37
+ select agent_board.current_agent_id() = '75000000-0000-4000-8000-000000000002'::uuid as new_epoch_resolves;
38
+ COMMIT;
39
+
40
+ credential_epoch|rotated_holder|bound_alias
41
+ ----------------+--------------+-----------
42
+ 1|t |resumed
43
+ (1 row)
44
+
45
+ tokens
46
+ ------
47
+ 1
48
+ (1 row)
49
+
50
+ old_epoch_fenced
51
+ ----------------
52
+ t
53
+ (1 row)
54
+
55
+ new_epoch_resolves
56
+ ------------------
57
+ t
58
+ (1 row)
59
+
60
+
61
+ starting permutation: b_begin b_reclaim a_begin a_reclaim b_commit a_commit check
62
+ step b_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
63
+ step b_reclaim:
64
+ do $$ declare c record; begin
65
+ select * into c from agent_board.issue_signing_key_challenge('75000000-0000-4000-8000-000000000002', 'holder-b');
66
+ perform * from agent_board.mint_fleet_agent_session(c.challenge_id, split_part(c.challenge, ':', 3),
67
+ '76000000-0000-4000-8000-000000000002', '75000000-0000-4000-8000-000000000002', 900, null, 'resumed');
68
+ end; $$;
69
+
70
+ step a_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
71
+ step a_reclaim:
72
+ do $$ declare c record; begin
73
+ select * into c from agent_board.issue_signing_key_challenge('75000000-0000-4000-8000-000000000002', 'holder-a');
74
+ perform * from agent_board.mint_fleet_agent_session(c.challenge_id, split_part(c.challenge, ':', 3),
75
+ '76000000-0000-4000-8000-000000000001', '75000000-0000-4000-8000-000000000002', 900, null, 'resumed');
76
+ end; $$;
77
+ <waiting ...>
78
+ step b_commit: COMMIT;
79
+ step a_reclaim: <... completed>
80
+ ERROR: duplicate_live_session
81
+ step a_commit: COMMIT;
82
+ step check:
83
+ select credential_epoch, holder_secret_hash <> extensions.digest('old-holder', 'sha256') as rotated_holder,
84
+ a.session_id as bound_alias
85
+ from agent_board.session_identities si join agent_board.session_id_aliases a on a.id = si.lease_alias_id
86
+ where si.agent_id = '75000000-0000-4000-8000-000000000002';
87
+ select count(*) as tokens from agent_board.nonfleet_sessions where agent_id = '75000000-0000-4000-8000-000000000002';
88
+ BEGIN;
89
+ SET LOCAL ROLE authenticated;
90
+ SET LOCAL "request.jwt.claim.role" = 'authenticated';
91
+ SET LOCAL "request.jwt.claim.sub" = '74000000-0000-4000-8000-000000000001';
92
+ SET LOCAL "request.jwt.claim.identity_lease_epoch" = '0';
93
+ select agent_board.current_agent_id() is null as old_epoch_fenced;
94
+ SET LOCAL "request.jwt.claim.identity_lease_epoch" = '1';
95
+ select agent_board.current_agent_id() = '75000000-0000-4000-8000-000000000002'::uuid as new_epoch_resolves;
96
+ COMMIT;
97
+
98
+ credential_epoch|rotated_holder|bound_alias
99
+ ----------------+--------------+-----------
100
+ 1|t |resumed
101
+ (1 row)
102
+
103
+ tokens
104
+ ------
105
+ 1
106
+ (1 row)
107
+
108
+ old_epoch_fenced
109
+ ----------------
110
+ t
111
+ (1 row)
112
+
113
+ new_epoch_resolves
114
+ ------------------
115
+ t
116
+ (1 row)
117
+
118
+
119
+ starting permutation: prepare_stale a_begin a_first_claim b_begin b_supersede a_commit b_commit check_stale
120
+ step prepare_stale:
121
+ update agent_board.agents set owner_user_id = '74000000-0000-4000-8000-000000000001'
122
+ where id = '75000000-0000-4000-8000-000000000001';
123
+ BEGIN;
124
+ SET LOCAL ROLE service_role;
125
+ SET LOCAL "request.jwt.claim.role" = 'service_role';
126
+ select count(*) from agent_board.upsert_delegation_policy('75000000-0000-4000-8000-000000000001', 'root_minted', '[]', 200, interval '8 hours', true);
127
+ do $$ declare m record; begin
128
+ select * into m from agent_board.mint_delegated_child('75000000-0000-4000-8000-000000000001', 'sid-stale-old', '[]',
129
+ public.test_pubkey('sid-stale-old'), interval '1 hour', false, 'claude', 'stale-reservation', null, '[]',
130
+ jsonb_build_object('resolution', 'resolved', 'risky_digest', 'approved'));
131
+ perform * from agent_board.issue_signing_key_challenge(m.child_agent_id, 'delegated-ephemeral');
132
+ end $$;
133
+ COMMIT;
134
+ update agent_board.session_identities set created_at = now() - interval '181 seconds'
135
+ where agent_id = (select id from agent_board.agents where handle = 'sid-stale-old');
136
+
137
+ count
138
+ -----
139
+ 1
140
+ (1 row)
141
+
142
+ step a_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
143
+ step a_first_claim:
144
+ do $$ declare a uuid; k uuid; c record; begin
145
+ select id into a from agent_board.agents where handle = 'sid-stale-old';
146
+ select id into k from agent_board.agent_signing_keys where agent_id = a;
147
+ select id, challenge_nonce into c from agent_board.agent_signing_key_challenges where agent_id = a order by created_at desc limit 1;
148
+ perform * from agent_board.mint_fleet_agent_session(c.id, c.challenge_nonce, k, a, 900, null, 'stale-reservation');
149
+ end $$;
150
+
151
+ step b_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
152
+ step b_supersede:
153
+ do $$ begin
154
+ perform * from agent_board.mint_delegated_child('75000000-0000-4000-8000-000000000001', 'sid-stale-new', '[]',
155
+ public.test_pubkey('sid-stale-new'), interval '1 hour', false, 'claude', 'stale-reservation', null, '[]',
156
+ jsonb_build_object('resolution', 'resolved', 'risky_digest', 'approved'));
157
+ end $$;
158
+ <waiting ...>
159
+ step a_commit: COMMIT;
160
+ step b_supersede: <... completed>
161
+ ERROR: duplicate_live_session
162
+ step b_commit: COMMIT;
163
+ step check_stale:
164
+ select a.status, si.tombstone_reason, si.credential_epoch, si.holder_secret_hash is not null as claimed,
165
+ (select count(*) from agent_board.fleet_revocation_events e where e.subject_id = a.id) as permanent_revocations
166
+ from agent_board.agents a join agent_board.session_identities si on si.agent_id = a.id where a.handle = 'sid-stale-old';
167
+ select a.handle as bound_principal from agent_board.session_id_aliases al join agent_board.agents a on a.id = al.identity_agent_id
168
+ where al.root_agent_id = '75000000-0000-4000-8000-000000000001' and al.session_id = 'stale-reservation';
169
+ select count(*) as successor_principals from agent_board.agents where handle = 'sid-stale-new';
170
+
171
+ status|tombstone_reason|credential_epoch|claimed|permanent_revocations
172
+ ------+----------------+----------------+-------+---------------------
173
+ active| | 0|t | 0
174
+ (1 row)
175
+
176
+ bound_principal
177
+ ---------------
178
+ sid-stale-old
179
+ (1 row)
180
+
181
+ successor_principals
182
+ --------------------
183
+ 0
184
+ (1 row)
185
+
186
+
187
+ starting permutation: prepare_stale b_begin b_supersede a_begin a_first_claim b_commit a_commit check_stale
188
+ step prepare_stale:
189
+ update agent_board.agents set owner_user_id = '74000000-0000-4000-8000-000000000001'
190
+ where id = '75000000-0000-4000-8000-000000000001';
191
+ BEGIN;
192
+ SET LOCAL ROLE service_role;
193
+ SET LOCAL "request.jwt.claim.role" = 'service_role';
194
+ select count(*) from agent_board.upsert_delegation_policy('75000000-0000-4000-8000-000000000001', 'root_minted', '[]', 200, interval '8 hours', true);
195
+ do $$ declare m record; begin
196
+ select * into m from agent_board.mint_delegated_child('75000000-0000-4000-8000-000000000001', 'sid-stale-old', '[]',
197
+ public.test_pubkey('sid-stale-old'), interval '1 hour', false, 'claude', 'stale-reservation', null, '[]',
198
+ jsonb_build_object('resolution', 'resolved', 'risky_digest', 'approved'));
199
+ perform * from agent_board.issue_signing_key_challenge(m.child_agent_id, 'delegated-ephemeral');
200
+ end $$;
201
+ COMMIT;
202
+ update agent_board.session_identities set created_at = now() - interval '181 seconds'
203
+ where agent_id = (select id from agent_board.agents where handle = 'sid-stale-old');
204
+
205
+ count
206
+ -----
207
+ 1
208
+ (1 row)
209
+
210
+ step b_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
211
+ step b_supersede:
212
+ do $$ begin
213
+ perform * from agent_board.mint_delegated_child('75000000-0000-4000-8000-000000000001', 'sid-stale-new', '[]',
214
+ public.test_pubkey('sid-stale-new'), interval '1 hour', false, 'claude', 'stale-reservation', null, '[]',
215
+ jsonb_build_object('resolution', 'resolved', 'risky_digest', 'approved'));
216
+ end $$;
217
+
218
+ step a_begin: BEGIN; SET LOCAL ROLE service_role; SET LOCAL "request.jwt.claim.role" = 'service_role';
219
+ step a_first_claim:
220
+ do $$ declare a uuid; k uuid; c record; begin
221
+ select id into a from agent_board.agents where handle = 'sid-stale-old';
222
+ select id into k from agent_board.agent_signing_keys where agent_id = a;
223
+ select id, challenge_nonce into c from agent_board.agent_signing_key_challenges where agent_id = a order by created_at desc limit 1;
224
+ perform * from agent_board.mint_fleet_agent_session(c.id, c.challenge_nonce, k, a, 900, null, 'stale-reservation');
225
+ end $$;
226
+ <waiting ...>
227
+ step b_commit: COMMIT;
228
+ step a_first_claim: <... completed>
229
+ ERROR: identity_tombstoned
230
+ step a_commit: COMMIT;
231
+ step check_stale:
232
+ select a.status, si.tombstone_reason, si.credential_epoch, si.holder_secret_hash is not null as claimed,
233
+ (select count(*) from agent_board.fleet_revocation_events e where e.subject_id = a.id) as permanent_revocations
234
+ from agent_board.agents a join agent_board.session_identities si on si.agent_id = a.id where a.handle = 'sid-stale-old';
235
+ select a.handle as bound_principal from agent_board.session_id_aliases al join agent_board.agents a on a.id = al.identity_agent_id
236
+ where al.root_agent_id = '75000000-0000-4000-8000-000000000001' and al.session_id = 'stale-reservation';
237
+ select count(*) as successor_principals from agent_board.agents where handle = 'sid-stale-new';
238
+
239
+ status |tombstone_reason |credential_epoch|claimed|permanent_revocations
240
+ -------+--------------------+----------------+-------+---------------------
241
+ revoked|superseded_unclaimed| 1|f | 1
242
+ (1 row)
243
+
244
+ bound_principal
245
+ ---------------
246
+ sid-stale-new
247
+ (1 row)
248
+
249
+ successor_principals
250
+ --------------------
251
+ 1
252
+ (1 row)
253
+