@consiliency/agent-board-schema 1.60.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.
- package/README.md +80 -0
- package/fixtures/already-applied.json +12 -0
- package/migrations/20261011000100_agent_board_session_identities.sql +1964 -0
- package/migrations/20261012000100_agent_board_sidowner.sql +209 -0
- package/migrations/20261014000100_agent_board_grant_target_role.sql +218 -0
- package/package.json +1 -1
- package/schema-manifest.json +30 -3
- package/src/tooling.test.mjs +6 -2
- package/tests/agent_board_atomic_fleet_onboarding.test.sql +13 -4
- package/tests/agent_board_consent_emission.test.sql +30 -11
- package/tests/agent_board_consent_gating.test.sql +16 -2
- package/tests/agent_board_delegate_role_class.test.sql +1 -1
- package/tests/agent_board_delegation_cap_ceiling.test.sql +26 -15
- package/tests/agent_board_delegation_enforcement.test.sql +1 -1
- package/tests/agent_board_enroll_resumption.test.sql +22 -4
- package/tests/agent_board_enroll_token_single_use.test.sql +18 -3
- package/tests/agent_board_federated_lock_order_class.test.sql +2 -2
- package/tests/agent_board_fk_lock_edges.test.sql +74 -14
- package/tests/agent_board_grant_target_role.test.sql +1118 -0
- package/tests/agent_board_invite_no_downgrade.test.sql +10 -8
- package/tests/agent_board_ledger_authority.test.sql +70 -12
- package/tests/agent_board_membership_current_row_class.test.sql +9 -1
- package/tests/agent_board_mint_fleet_agent_session.test.sql +2 -2
- package/tests/agent_board_mint_harden.test.sql +38 -27
- package/tests/agent_board_rolereset.test.sql +8 -2
- package/tests/agent_board_roomdeleg_lane_b.test.sql +6 -6
- package/tests/agent_board_rowid.test.sql +3 -1
- package/tests/agent_board_session_identity_approval_revocation.test.sql +334 -0
- package/tests/agent_board_session_identity_backfill.test.sql +82 -0
- package/tests/agent_board_session_identity_backfill_refusal.test.sql +14 -0
- package/tests/agent_board_session_identity_behavior_classes.test.sql +176 -0
- package/tests/agent_board_session_identity_class.test.sql +118 -0
- package/tests/agent_board_session_identity_fingerprint.test.sql +271 -0
- package/tests/agent_board_session_identity_labels_limits.test.sql +205 -0
- package/tests/agent_board_session_identity_lease.test.sql +235 -0
- package/tests/agent_board_session_identity_lifetime.test.sql +230 -0
- package/tests/agent_board_session_identity_limits.test.sql +208 -0
- package/tests/agent_board_session_identity_lineage.test.sql +64 -0
- package/tests/agent_board_session_identity_link.test.sql +201 -0
- package/tests/agent_board_session_identity_mint.test.sql +233 -0
- package/tests/agent_board_session_identity_panel_r1.test.sql +194 -0
- package/tests/agent_board_session_identity_panel_r2.test.sql +174 -0
- package/tests/agent_board_session_identity_protected_actions.test.sql +156 -0
- package/tests/agent_board_session_identity_revoke_closure.test.sql +131 -0
- package/tests/agent_board_sidowner_leases.test.sql +107 -0
- package/tests/agent_board_sidowner_owner_required.test.sql +97 -0
- package/tests/agent_board_sidowner_read_class.test.sql +171 -0
- package/tests/agent_board_sidowner_reads.test.sql +136 -0
- package/tests/agent_board_signer_lifecycle.test.sql +26 -4
- package/tests/agent_board_signing_challenge_pending_cap.test.sql +1 -1
- package/tests/agent_board_write_enforcement_class.test.sql +74 -15
- package/tests/catalog/function_execute_privileges.json +218 -2
- package/tests/catalog/p_metadata_parameters.json +98 -2
- package/tests/isolation/expected/grant_target_role_race.out +348 -0
- package/tests/isolation/expected/session_identity_limits.out +165 -0
- package/tests/isolation/expected/session_identity_links.out +235 -0
- package/tests/isolation/expected/session_identity_reclaim.out +253 -0
- package/tests/isolation/expected/session_identity_renew_revoke.out +115 -0
- package/tests/isolation/expected/session_identity_renew_revoke_key_gate.out +138 -0
- package/tests/isolation/expected/session_identity_tombstone_onboarding.out +247 -0
- package/tests/isolation/specs/grant_target_role_race.spec +207 -0
- package/tests/isolation/specs/session_identity_limits.spec +81 -0
- package/tests/isolation/specs/session_identity_links.spec +80 -0
- package/tests/isolation/specs/session_identity_reclaim.spec +125 -0
- package/tests/isolation/specs/session_identity_renew_revoke.spec +84 -0
- package/tests/isolation/specs/session_identity_renew_revoke_key_gate.spec +94 -0
- package/tests/isolation/specs/session_identity_tombstone_onboarding.spec +108 -0
- package/tests/seeds/20261011000100_agent_board_session_identities.sql.pre.sql +47 -0
|
@@ -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
|
+
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
Parsed test spec with 3 sessions
|
|
2
|
+
|
|
3
|
+
starting permutation: renew_begin renew revoke_begin revoke renew_commit revoke_commit check
|
|
4
|
+
step renew_begin:
|
|
5
|
+
BEGIN;
|
|
6
|
+
select set_config('request.jwt.claim.sub', (select auth_user_id::text from agent_board.agents where handle = 'sid-renew-child'), true) is not null as holder_forwarded;
|
|
7
|
+
SET LOCAL ROLE service_role;
|
|
8
|
+
SET LOCAL "request.jwt.claim.role" = 'service_role';
|
|
9
|
+
SET LOCAL "request.jwt.claim.identity_lease_epoch" = '0';
|
|
10
|
+
|
|
11
|
+
holder_forwarded
|
|
12
|
+
----------------
|
|
13
|
+
t
|
|
14
|
+
(1 row)
|
|
15
|
+
|
|
16
|
+
step renew:
|
|
17
|
+
select agent_board.renew_session_identity((select id from agent_board.agents where handle = 'sid-renew-child'), 'approved');
|
|
18
|
+
|
|
19
|
+
renew_session_identity
|
|
20
|
+
----------------------
|
|
21
|
+
|
|
22
|
+
(1 row)
|
|
23
|
+
|
|
24
|
+
step revoke_begin:
|
|
25
|
+
BEGIN;
|
|
26
|
+
SET LOCAL ROLE authenticated;
|
|
27
|
+
SET LOCAL "request.jwt.claim.role" = 'authenticated';
|
|
28
|
+
SET LOCAL "request.jwt.claim.sub" = '81000000-0000-4000-8000-000000000001';
|
|
29
|
+
|
|
30
|
+
step revoke:
|
|
31
|
+
select agent_board.revoke_session_identity((select id from agent_board.agents where handle = 'sid-renew-child'));
|
|
32
|
+
<waiting ...>
|
|
33
|
+
step renew_commit: COMMIT;
|
|
34
|
+
step revoke: <... completed>
|
|
35
|
+
revoke_session_identity
|
|
36
|
+
-----------------------
|
|
37
|
+
|
|
38
|
+
(1 row)
|
|
39
|
+
|
|
40
|
+
step revoke_commit: COMMIT;
|
|
41
|
+
step check:
|
|
42
|
+
select si.tombstone_reason, si.credential_epoch, a.status, g.revoked_at is not null as grant_revoked,
|
|
43
|
+
g.last_renewed_at is not null as renewal_preceded_revoke,
|
|
44
|
+
(select count(*) from agent_board.fleet_revocation_events e where e.subject_id = a.id) as permanent_revocations,
|
|
45
|
+
(select count(*) from agent_board.agent_signing_keys k where k.agent_id = a.id and k.status <> 'revoked') as active_keys
|
|
46
|
+
from agent_board.agents a join agent_board.session_identities si on si.agent_id = a.id
|
|
47
|
+
join agent_board.delegation_grants g on g.child_agent_id = a.id where a.handle = 'sid-renew-child';
|
|
48
|
+
select bool_and(expires_at <= issued_at + interval '900 seconds') as bounded_pre_revoke_tokens
|
|
49
|
+
from agent_board.nonfleet_sessions where agent_id = (select id from agent_board.agents where handle = 'sid-renew-child');
|
|
50
|
+
|
|
51
|
+
tombstone_reason|credential_epoch|status |grant_revoked|renewal_preceded_revoke|permanent_revocations|active_keys
|
|
52
|
+
----------------+----------------+-------+-------------+-----------------------+---------------------+-----------
|
|
53
|
+
revoked | 1|revoked|t |t | 1| 0
|
|
54
|
+
(1 row)
|
|
55
|
+
|
|
56
|
+
bounded_pre_revoke_tokens
|
|
57
|
+
-------------------------
|
|
58
|
+
t
|
|
59
|
+
(1 row)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
starting permutation: revoke_begin revoke renew_begin renew revoke_commit renew_commit check
|
|
63
|
+
step revoke_begin:
|
|
64
|
+
BEGIN;
|
|
65
|
+
SET LOCAL ROLE authenticated;
|
|
66
|
+
SET LOCAL "request.jwt.claim.role" = 'authenticated';
|
|
67
|
+
SET LOCAL "request.jwt.claim.sub" = '81000000-0000-4000-8000-000000000001';
|
|
68
|
+
|
|
69
|
+
step revoke:
|
|
70
|
+
select agent_board.revoke_session_identity((select id from agent_board.agents where handle = 'sid-renew-child'));
|
|
71
|
+
|
|
72
|
+
revoke_session_identity
|
|
73
|
+
-----------------------
|
|
74
|
+
|
|
75
|
+
(1 row)
|
|
76
|
+
|
|
77
|
+
step renew_begin:
|
|
78
|
+
BEGIN;
|
|
79
|
+
select set_config('request.jwt.claim.sub', (select auth_user_id::text from agent_board.agents where handle = 'sid-renew-child'), true) is not null as holder_forwarded;
|
|
80
|
+
SET LOCAL ROLE service_role;
|
|
81
|
+
SET LOCAL "request.jwt.claim.role" = 'service_role';
|
|
82
|
+
SET LOCAL "request.jwt.claim.identity_lease_epoch" = '0';
|
|
83
|
+
|
|
84
|
+
holder_forwarded
|
|
85
|
+
----------------
|
|
86
|
+
t
|
|
87
|
+
(1 row)
|
|
88
|
+
|
|
89
|
+
step renew:
|
|
90
|
+
select agent_board.renew_session_identity((select id from agent_board.agents where handle = 'sid-renew-child'), 'approved');
|
|
91
|
+
<waiting ...>
|
|
92
|
+
step revoke_commit: COMMIT;
|
|
93
|
+
step renew: <... completed>
|
|
94
|
+
ERROR: identity_tombstoned
|
|
95
|
+
step renew_commit: COMMIT;
|
|
96
|
+
step check:
|
|
97
|
+
select si.tombstone_reason, si.credential_epoch, a.status, g.revoked_at is not null as grant_revoked,
|
|
98
|
+
g.last_renewed_at is not null as renewal_preceded_revoke,
|
|
99
|
+
(select count(*) from agent_board.fleet_revocation_events e where e.subject_id = a.id) as permanent_revocations,
|
|
100
|
+
(select count(*) from agent_board.agent_signing_keys k where k.agent_id = a.id and k.status <> 'revoked') as active_keys
|
|
101
|
+
from agent_board.agents a join agent_board.session_identities si on si.agent_id = a.id
|
|
102
|
+
join agent_board.delegation_grants g on g.child_agent_id = a.id where a.handle = 'sid-renew-child';
|
|
103
|
+
select bool_and(expires_at <= issued_at + interval '900 seconds') as bounded_pre_revoke_tokens
|
|
104
|
+
from agent_board.nonfleet_sessions where agent_id = (select id from agent_board.agents where handle = 'sid-renew-child');
|
|
105
|
+
|
|
106
|
+
tombstone_reason|credential_epoch|status |grant_revoked|renewal_preceded_revoke|permanent_revocations|active_keys
|
|
107
|
+
----------------+----------------+-------+-------------+-----------------------+---------------------+-----------
|
|
108
|
+
revoked | 1|revoked|t |f | 1| 0
|
|
109
|
+
(1 row)
|
|
110
|
+
|
|
111
|
+
bounded_pre_revoke_tokens
|
|
112
|
+
-------------------------
|
|
113
|
+
t
|
|
114
|
+
(1 row)
|
|
115
|
+
|