@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,1250 @@
1
+ create extension if not exists pgtap with schema extensions;
2
+ set search_path = extensions, public, agent_board;
3
+
4
+ begin;
5
+ select plan(103);
6
+
7
+ create temp table _atomic_cfg(
8
+ owner_id uuid,
9
+ board_id uuid,
10
+ machine_id uuid,
11
+ invite_id uuid,
12
+ invite_code text
13
+ ) on commit drop;
14
+
15
+ create temp table _atomic_result(
16
+ attempt text,
17
+ agent_id uuid,
18
+ signing_key_id uuid,
19
+ board_id uuid,
20
+ harness_registration_id uuid,
21
+ repo_scope_id uuid,
22
+ fleet_machine_agent_id uuid,
23
+ binding_signing_key_id uuid,
24
+ identity_disposition text,
25
+ membership_disposition text,
26
+ harness_disposition text,
27
+ repo_scope_disposition text,
28
+ binding_disposition text
29
+ ) on commit drop;
30
+
31
+ create temp table _recovery_cfg(
32
+ legacy_agent_id uuid,
33
+ legacy_signing_key_id uuid,
34
+ invite_id uuid,
35
+ invite_code text
36
+ ) on commit drop;
37
+
38
+ create temp table _recovery_result(
39
+ agent_id uuid,
40
+ signing_key_id uuid,
41
+ identity_disposition text,
42
+ membership_disposition text,
43
+ harness_disposition text,
44
+ repo_scope_disposition text,
45
+ binding_disposition text
46
+ ) on commit drop;
47
+
48
+ create temp table _collision_cfg(invite_id uuid, invite_code text) on commit drop;
49
+ create temp table _human_revocation_cfg(owner_user_id uuid) on commit drop;
50
+
51
+ do $$
52
+ declare
53
+ v_owner uuid := '16210000-0000-0000-0000-000000000001';
54
+ v_board uuid;
55
+ v_domain uuid;
56
+ v_machine uuid;
57
+ v_invite uuid;
58
+ v_code text;
59
+ begin
60
+ insert into agent_board.agents(id, agent_type, handle, display_name, status)
61
+ values (v_owner, 'agent', 'atomic-runtime-owner', 'Atomic Runtime Owner', 'active');
62
+
63
+ select board_id
64
+ into v_board
65
+ from agent_board.create_board(
66
+ v_owner, 'atomic-runtime-board', 'Atomic Runtime Board',
67
+ 'Consiliency/message-board#162 runtime proof', '{}'::jsonb, 'private'
68
+ );
69
+
70
+ insert into agent_board.fleet_trust_domains(
71
+ slug, display_name, domain_kind, owner_agent_id, lifecycle_state, approved_at
72
+ ) values (
73
+ 'atomic-runtime-domain', 'Atomic Runtime Domain', 'tailnet', v_owner, 'active', now()
74
+ ) returning id into v_domain;
75
+
76
+ insert into agent_board.fleet_machines(
77
+ trust_domain_id, owner_agent_id, machine_label, machine_fingerprint,
78
+ lifecycle_state, enrollment_source, enrolled_at
79
+ ) values (
80
+ v_domain, v_owner, 'claw', 'sha256:atomic-runtime-machine',
81
+ 'active', 'portal', now()
82
+ ) returning id into v_machine;
83
+
84
+ insert into agent_board.identity_providers(
85
+ issuer, audience, supported, policy_approved,
86
+ allowed_scopes, allowed_board_scopes, allowed_agent_kinds
87
+ ) values (
88
+ 'https://atomic-runtime.test', 'message-board', true, true,
89
+ '{board:send}', '{}', '{agent}'
90
+ );
91
+
92
+ select invite_id, code
93
+ into v_invite, v_code
94
+ from agent_board.create_fleet_onboarding_invite(
95
+ v_board, v_machine, 'codex', 'phase-loop', 'message-board',
96
+ 'sha256:atomic-runtime-repo', 'worker', 'phase_worker',
97
+ 'atomic-runtime-agent', 1, now() + interval '1 hour', v_owner, '{}'::jsonb
98
+ );
99
+
100
+ insert into _atomic_cfg values (v_owner, v_board, v_machine, v_invite, v_code);
101
+
102
+ insert into _atomic_result
103
+ select 'first', r.agent_id, r.signing_key_id, r.board_id,
104
+ r.harness_registration_id, r.repo_scope_id, r.fleet_machine_agent_id,
105
+ r.binding_signing_key_id,
106
+ r.identity_disposition, r.membership_disposition,
107
+ r.harness_disposition, r.repo_scope_disposition, r.binding_disposition
108
+ from agent_board.onboard_federated_fleet_agent(
109
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
110
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":100}'::jsonb,
111
+ 'atomic-runtime-agent',
112
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0',
113
+ 'raw_ed25519_base64url',
114
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8',
115
+ true, null, 'agent', '{board:send}', '{}', v_code, v_board, v_machine,
116
+ 'codex', 'phase-loop', 'message-board', 'sha256:atomic-runtime-repo',
117
+ 'worker', 'phase_worker', 'atomic-runtime-agent'
118
+ ) r;
119
+
120
+ insert into _atomic_result
121
+ select 'replay', r.agent_id, r.signing_key_id, r.board_id,
122
+ r.harness_registration_id, r.repo_scope_id, r.fleet_machine_agent_id,
123
+ r.binding_signing_key_id,
124
+ r.identity_disposition, r.membership_disposition,
125
+ r.harness_disposition, r.repo_scope_disposition, r.binding_disposition
126
+ from agent_board.onboard_federated_fleet_agent(
127
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
128
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":200,"jti":"rotated"}'::jsonb,
129
+ 'atomic-runtime-agent',
130
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0',
131
+ 'raw_ed25519_base64url',
132
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8',
133
+ true, null, 'agent', '{board:send}', '{}', v_code, v_board, v_machine,
134
+ 'codex', 'phase-loop', 'message-board', 'sha256:atomic-runtime-repo',
135
+ 'worker', 'phase_worker', 'atomic-runtime-agent'
136
+ ) r;
137
+ end
138
+ $$;
139
+
140
+ select is((select count(*)::int from _atomic_result where attempt='first'), 1,
141
+ 'first atomic onboarding returns one complete receipt');
142
+ select is((select count(*)::int from _atomic_result where attempt='replay'), 1,
143
+ 'exact replay returns one complete receipt');
144
+ select is((select agent_id from _atomic_result where attempt='replay'),
145
+ (select agent_id from _atomic_result where attempt='first'),
146
+ 'exact replay returns the same agent');
147
+ select is((select signing_key_id from _atomic_result where attempt='replay'),
148
+ (select signing_key_id from _atomic_result where attempt='first'),
149
+ 'exact replay returns the same proven key');
150
+ select is((select fleet_machine_agent_id from _atomic_result where attempt='replay'),
151
+ (select fleet_machine_agent_id from _atomic_result where attempt='first'),
152
+ 'exact replay returns the same fleet binding');
153
+ select is((select identity_disposition from _atomic_result where attempt='first'), 'created',
154
+ 'first identity disposition is created');
155
+ select is((select identity_disposition from _atomic_result where attempt='replay'), 'reused',
156
+ 'replay identity disposition is reused');
157
+ select is((select uses_count from agent_board.board_invite_tokens
158
+ where id=(select invite_id from _atomic_cfg)), 1,
159
+ 'exact replay consumes no second invite use');
160
+ select is((select count(*)::int from agent_board.board_invite_redemptions
161
+ where invite_id=(select invite_id from _atomic_cfg)), 1,
162
+ 'exact replay keeps one redemption ledger row');
163
+ select is((select count(*)::int from agent_board.agents where handle='atomic-runtime-agent'), 1,
164
+ 'atomic onboarding creates exactly one agent');
165
+ select is((select count(*)::int from agent_board.agent_signing_keys
166
+ where id=(select signing_key_id from _atomic_result where attempt='first')), 1,
167
+ 'atomic onboarding creates exactly one proven key');
168
+ select is((select role || '/' || membership_state from agent_board.board_memberships
169
+ where board_id=(select board_id from _atomic_cfg)
170
+ and agent_id=(select agent_id from _atomic_result where attempt='first')),
171
+ 'member/joined',
172
+ 'atomic onboarding creates the bounded member membership');
173
+ select is((select count(*)::int from agent_board.fleet_harness_registrations
174
+ where id=(select harness_registration_id from _atomic_result where attempt='first')), 1,
175
+ 'atomic onboarding creates one harness registration');
176
+ select is((select count(*)::int from agent_board.fleet_repo_scopes
177
+ where id=(select repo_scope_id from _atomic_result where attempt='first')), 1,
178
+ 'atomic onboarding creates one repo scope');
179
+ select is((select fma.signing_key_id from agent_board.fleet_machine_agents fma
180
+ where fma.id=(select fleet_machine_agent_id from _atomic_result where attempt='first')),
181
+ (select signing_key_id from _atomic_result where attempt='first'),
182
+ 'fleet binding pins the exact proven signing key');
183
+ select is((select binding_signing_key_id from _atomic_result where attempt='first'),
184
+ (select signing_key_id from _atomic_result where attempt='first'),
185
+ 'receipt independently returns the signing key pinned by the fleet binding');
186
+
187
+ create function pg_temp._atomic_history_attempt(p_iat integer)
188
+ returns text
189
+ language plpgsql
190
+ as $$
191
+ begin
192
+ perform * from agent_board.onboard_federated_fleet_agent(
193
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
194
+ jsonb_build_object('iss','https://atomic-runtime.test','aud','message-board','sub','human-runtime','iat',p_iat),
195
+ 'atomic-runtime-agent',
196
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
197
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
198
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
199
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
200
+ 'codex', 'phase-loop', 'message-board', 'sha256:atomic-runtime-repo',
201
+ 'worker', 'phase_worker', 'atomic-runtime-agent'
202
+ );
203
+ return 'lived';
204
+ exception when others then
205
+ return sqlstate;
206
+ end
207
+ $$;
208
+
209
+ insert into agent_board.fleet_harness_registrations(
210
+ id, machine_id, harness_kind, harness_label, lifecycle_state, revoked_at
211
+ ) values (
212
+ 'ffffffff-ffff-ffff-ffff-fffffffffff1', (select machine_id from _atomic_cfg),
213
+ 'codex', 'phase-loop', 'revoked', now()
214
+ );
215
+ select is(pg_temp._atomic_history_attempt(210), '42501',
216
+ 'a later-sorting revoked harness tombstone blocks active-row replay');
217
+ delete from agent_board.fleet_harness_registrations where id='ffffffff-ffff-ffff-ffff-fffffffffff1';
218
+ insert into agent_board.fleet_harness_registrations(
219
+ id, machine_id, harness_kind, harness_label, lifecycle_state, revoked_at
220
+ ) values (
221
+ '00000000-0000-0000-0000-000000000001', (select machine_id from _atomic_cfg),
222
+ 'codex', 'phase-loop', 'revoked', now()
223
+ );
224
+ select is(pg_temp._atomic_history_attempt(211), '42501',
225
+ 'an earlier-sorting revoked harness tombstone blocks active-row replay');
226
+ delete from agent_board.fleet_harness_registrations where id='00000000-0000-0000-0000-000000000001';
227
+
228
+ insert into agent_board.fleet_repo_scopes(
229
+ id, harness_registration_id, repo_slug, repo_fingerprint, scope_role,
230
+ lifecycle_state, revoked_at
231
+ ) values (
232
+ 'ffffffff-ffff-ffff-ffff-fffffffffff2',
233
+ (select harness_registration_id from _atomic_result where attempt='first'),
234
+ 'message-board', 'sha256:atomic-runtime-repo', 'worker', 'revoked', now()
235
+ );
236
+ select is(pg_temp._atomic_history_attempt(212), '42501',
237
+ 'a later-sorting revoked repo tombstone blocks active-row replay');
238
+ delete from agent_board.fleet_repo_scopes where id='ffffffff-ffff-ffff-ffff-fffffffffff2';
239
+ insert into agent_board.fleet_repo_scopes(
240
+ id, harness_registration_id, repo_slug, repo_fingerprint, scope_role,
241
+ lifecycle_state, revoked_at
242
+ ) values (
243
+ '00000000-0000-0000-0000-000000000002',
244
+ (select harness_registration_id from _atomic_result where attempt='first'),
245
+ 'message-board', 'sha256:atomic-runtime-repo', 'worker', 'revoked', now()
246
+ );
247
+ select is(pg_temp._atomic_history_attempt(213), '42501',
248
+ 'an earlier-sorting revoked repo tombstone blocks active-row replay');
249
+ delete from agent_board.fleet_repo_scopes where id='00000000-0000-0000-0000-000000000002';
250
+
251
+ insert into agent_board.fleet_machine_agents(
252
+ id, machine_id, agent_id, repo_scope_id, signing_key_id, agent_role,
253
+ lifecycle_state, revoked_at
254
+ ) values (
255
+ 'ffffffff-ffff-ffff-ffff-fffffffffff3', (select machine_id from _atomic_cfg),
256
+ (select agent_id from _atomic_result where attempt='first'),
257
+ (select repo_scope_id from _atomic_result where attempt='first'),
258
+ (select signing_key_id from _atomic_result where attempt='first'),
259
+ 'phase_worker', 'revoked', now()
260
+ );
261
+ select is(pg_temp._atomic_history_attempt(214), '42501',
262
+ 'a later-sorting revoked binding tombstone blocks active-row replay');
263
+ delete from agent_board.fleet_machine_agents where id='ffffffff-ffff-ffff-ffff-fffffffffff3';
264
+ insert into agent_board.fleet_machine_agents(
265
+ id, machine_id, agent_id, repo_scope_id, signing_key_id, agent_role,
266
+ lifecycle_state, revoked_at
267
+ ) values (
268
+ '00000000-0000-0000-0000-000000000003', (select machine_id from _atomic_cfg),
269
+ (select agent_id from _atomic_result where attempt='first'),
270
+ (select repo_scope_id from _atomic_result where attempt='first'),
271
+ (select signing_key_id from _atomic_result where attempt='first'),
272
+ 'phase_worker', 'revoked', now()
273
+ );
274
+ select is(pg_temp._atomic_history_attempt(215), '42501',
275
+ 'an earlier-sorting revoked binding tombstone blocks active-row replay');
276
+ delete from agent_board.fleet_machine_agents where id='00000000-0000-0000-0000-000000000003';
277
+
278
+ update agent_board.board_invite_tokens
279
+ set expires_at = now() - interval '1 minute'
280
+ where id = (select invite_id from _atomic_cfg);
281
+ select lives_ok(
282
+ $$insert into _atomic_result
283
+ select 'expired-complete-replay', r.agent_id, r.signing_key_id, r.board_id,
284
+ r.harness_registration_id, r.repo_scope_id, r.fleet_machine_agent_id,
285
+ r.binding_signing_key_id,
286
+ r.identity_disposition, r.membership_disposition,
287
+ r.harness_disposition, r.repo_scope_disposition, r.binding_disposition
288
+ from agent_board.onboard_federated_fleet_agent(
289
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
290
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":250}'::jsonb,
291
+ 'atomic-runtime-agent',
292
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
293
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
294
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
295
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
296
+ 'codex', 'phase-loop', 'message-board', 'sha256:atomic-runtime-repo',
297
+ 'worker', 'phase_worker', 'atomic-runtime-agent') r$$,
298
+ 'a fully complete active replay may bypass only expiry and its consumed use cap'
299
+ );
300
+ select is((select count(*)::int from _atomic_result where attempt='expired-complete-replay'), 1,
301
+ 'expired complete replay returns the exact receipt');
302
+ select is((select uses_count from agent_board.board_invite_tokens
303
+ where id=(select invite_id from _atomic_cfg)), 1,
304
+ 'expired complete replay consumes no additional use');
305
+ update agent_board.board_invite_tokens
306
+ set expires_at = now() + interval '1 hour'
307
+ where id = (select invite_id from _atomic_cfg);
308
+
309
+ select throws_ok(
310
+ $$select * from agent_board._redeem_invite_for_agent(
311
+ (select invite_code from _atomic_cfg),
312
+ (select agent_id from _atomic_result where attempt='first'))$$,
313
+ '42501', null,
314
+ 'generic redemption rejects the bounded invite'
315
+ );
316
+ select throws_ok(
317
+ $$select * from agent_board.enroll_federated_identity(
318
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
319
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":300}'::jsonb, 'atomic-runtime-agent',
320
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
321
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
322
+ '{board:send}', '{}', (select invite_code from _atomic_cfg))$$,
323
+ '42501', null,
324
+ 'legacy enrollment rejects the bounded invite before replay'
325
+ );
326
+ select throws_ok(
327
+ $$select * from agent_board.onboard_federated_fleet_agent(
328
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
329
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":300}'::jsonb, 'atomic-runtime-agent',
330
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
331
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
332
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
333
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg), 'codex', 'substituted-label',
334
+ 'message-board', 'sha256:atomic-runtime-repo', 'worker', 'phase_worker',
335
+ 'atomic-runtime-agent')$$,
336
+ '42501', null,
337
+ 'altered bound tuple is rejected before replay writes'
338
+ );
339
+ select throws_ok(
340
+ $$select * from agent_board.onboard_federated_fleet_agent(
341
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
342
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":350}'::jsonb, 'atomic-runtime-agent',
343
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
344
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
345
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
346
+ gen_random_uuid(), (select machine_id from _atomic_cfg), 'codex', 'phase-loop',
347
+ 'message-board', 'sha256:atomic-runtime-repo', 'worker', 'phase_worker',
348
+ 'atomic-runtime-agent')$$,
349
+ '42501', null,
350
+ 'wrong board id is rejected against the locked invite before replay writes'
351
+ );
352
+ select throws_ok(
353
+ $$select * from agent_board.onboard_federated_fleet_agent(
354
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
355
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":351}'::jsonb, 'atomic-runtime-agent',
356
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
357
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
358
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
359
+ (select board_id from _atomic_cfg), gen_random_uuid(), 'codex', 'phase-loop',
360
+ 'message-board', 'sha256:atomic-runtime-repo', 'worker', 'phase_worker',
361
+ 'atomic-runtime-agent')$$,
362
+ '42501', null, 'altered machine bound is rejected before replay writes'
363
+ );
364
+ select throws_ok(
365
+ $$select * from agent_board.onboard_federated_fleet_agent(
366
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
367
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":352}'::jsonb, 'atomic-runtime-agent',
368
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
369
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
370
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
371
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg), 'claude', 'phase-loop',
372
+ 'message-board', 'sha256:atomic-runtime-repo', 'worker', 'phase_worker',
373
+ 'atomic-runtime-agent')$$,
374
+ '42501', null, 'altered harness-kind bound is rejected before replay writes'
375
+ );
376
+ select throws_ok(
377
+ $$select * from agent_board.onboard_federated_fleet_agent(
378
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
379
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":353}'::jsonb, 'atomic-runtime-agent',
380
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
381
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
382
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
383
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg), 'codex', 'phase-loop',
384
+ 'other-repo', 'sha256:atomic-runtime-repo', 'worker', 'phase_worker',
385
+ 'atomic-runtime-agent')$$,
386
+ '42501', null, 'altered repo-slug bound is rejected before replay writes'
387
+ );
388
+ select throws_ok(
389
+ $$select * from agent_board.onboard_federated_fleet_agent(
390
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
391
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":354}'::jsonb, 'atomic-runtime-agent',
392
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
393
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
394
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
395
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg), 'codex', 'phase-loop',
396
+ 'message-board', 'sha256:substituted-repo', 'worker', 'phase_worker',
397
+ 'atomic-runtime-agent')$$,
398
+ '42501', null, 'altered repo-fingerprint bound is rejected before replay writes'
399
+ );
400
+ select throws_ok(
401
+ $$select * from agent_board.onboard_federated_fleet_agent(
402
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
403
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":355}'::jsonb, 'atomic-runtime-agent',
404
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
405
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
406
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
407
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg), 'codex', 'phase-loop',
408
+ 'message-board', 'sha256:atomic-runtime-repo', 'reviewer', 'reviewer',
409
+ 'atomic-runtime-agent')$$,
410
+ '42501', null, 'altered role-pair bound is rejected before replay writes'
411
+ );
412
+ select throws_ok(
413
+ $$select * from agent_board.onboard_federated_fleet_agent(
414
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
415
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":356}'::jsonb, 'atomic-runtime-agent',
416
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
417
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
418
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
419
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg), 'codex', 'phase-loop',
420
+ 'message-board', 'sha256:atomic-runtime-repo', 'worker', 'phase_worker',
421
+ 'substituted-handle')$$,
422
+ '42501', null, 'altered expected-handle bound is rejected before replay writes'
423
+ );
424
+ select throws_ok(
425
+ $$select * from agent_board.onboard_federated_fleet_agent(
426
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
427
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":357}'::jsonb, 'atomic-runtime-agent',
428
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
429
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
430
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
431
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg), 'codex', 'phase-loop',
432
+ 'message-board', 'sha256:atomic-runtime-repo', 'worker', 'reviewer',
433
+ 'atomic-runtime-agent')$$,
434
+ '42501', null, 'altered agent-role bound is rejected before replay writes'
435
+ );
436
+ select is(
437
+ (select count(*)::text from agent_board.agents where handle='atomic-runtime-agent') || '/' ||
438
+ (select count(*)::text from agent_board.board_invite_redemptions where invite_id=(select invite_id from _atomic_cfg)) || '/' ||
439
+ (select count(*)::text from agent_board.fleet_machine_agents where agent_id=(select agent_id from _atomic_result where attempt='first')),
440
+ '1/1/1',
441
+ 'wrong-board rejection leaves identity, redemption, and fleet counts unchanged'
442
+ );
443
+ select is((select count(*)::int from agent_board.fleet_machine_agents
444
+ where agent_id=(select agent_id from _atomic_result where attempt='first')), 1,
445
+ 'rejected legacy and altered-bound paths leave one fleet binding');
446
+ select throws_ok(
447
+ $$update agent_board.fleet_onboarding_invite_bounds
448
+ set harness_label='mutated'
449
+ where invite_id=(select invite_id from _atomic_cfg)$$,
450
+ '55000', null,
451
+ 'creator-authorized bounds remain immutable'
452
+ );
453
+
454
+ create temp table _cascade_invite as
455
+ select invite_id
456
+ from agent_board.create_fleet_onboarding_invite(
457
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
458
+ 'codex', 'cascade-proof', 'message-board', 'sha256:cascade-proof',
459
+ 'worker', 'phase_worker', 'agent-board/cascade-proof/codex',
460
+ 1, now() + interval '1 hour', (select owner_id from _atomic_cfg), '{}'::jsonb
461
+ );
462
+ delete from agent_board.board_invite_tokens where id=(select invite_id from _cascade_invite);
463
+ select is(
464
+ (select count(*)::int from agent_board.fleet_onboarding_invite_bounds
465
+ where invite_id=(select invite_id from _cascade_invite)),
466
+ 0,
467
+ 'deleting an unused invite reaches the declared bounds cascade'
468
+ );
469
+
470
+ update agent_board.board_invite_tokens
471
+ set revoked_at = now()
472
+ where id = (select invite_id from _atomic_cfg);
473
+ select throws_ok(
474
+ $$select * from agent_board.onboard_federated_fleet_agent(
475
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
476
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":360}'::jsonb, 'atomic-runtime-agent',
477
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
478
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
479
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
480
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg), 'codex', 'phase-loop',
481
+ 'message-board', 'sha256:atomic-runtime-repo', 'worker', 'phase_worker',
482
+ 'atomic-runtime-agent')$$,
483
+ '42501', null,
484
+ 'even a complete replay cannot bypass explicit invite revocation'
485
+ );
486
+
487
+ delete from agent_board.fleet_machine_agents
488
+ where id = (select fleet_machine_agent_id from _atomic_result where attempt='first');
489
+ select throws_ok(
490
+ $$select * from agent_board.onboard_federated_fleet_agent(
491
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
492
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":361}'::jsonb, 'atomic-runtime-agent',
493
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
494
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
495
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
496
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg), 'codex', 'phase-loop',
497
+ 'message-board', 'sha256:atomic-runtime-repo', 'worker', 'phase_worker',
498
+ 'atomic-runtime-agent')$$,
499
+ '42501', null,
500
+ 'a revoked invite cannot repair a partial fleet suffix'
501
+ );
502
+ select is((select count(*)::int from agent_board.fleet_machine_agents
503
+ where agent_id=(select agent_id from _atomic_result where attempt='first')), 0,
504
+ 'revoked partial recovery rolls back without a replacement binding');
505
+
506
+ update agent_board.board_invite_tokens
507
+ set revoked_at = null
508
+ where id = (select invite_id from _atomic_cfg);
509
+ select throws_ok(
510
+ $$select * from agent_board.onboard_federated_fleet_agent(
511
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
512
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":362}'::jsonb, 'atomic-runtime-agent',
513
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
514
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
515
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
516
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg), 'codex', 'phase-loop',
517
+ 'message-board', 'sha256:atomic-runtime-repo', 'worker', 'phase_worker',
518
+ 'atomic-runtime-agent')$$,
519
+ '42501', null,
520
+ 'an exhausted invite cannot repair a partial fleet suffix'
521
+ );
522
+
523
+ update agent_board.board_invite_tokens
524
+ set max_uses = 2, expires_at = now() - interval '1 minute'
525
+ where id = (select invite_id from _atomic_cfg);
526
+ select throws_ok(
527
+ $$select * from agent_board.onboard_federated_fleet_agent(
528
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
529
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":363}'::jsonb, 'atomic-runtime-agent',
530
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
531
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
532
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
533
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg), 'codex', 'phase-loop',
534
+ 'message-board', 'sha256:atomic-runtime-repo', 'worker', 'phase_worker',
535
+ 'atomic-runtime-agent')$$,
536
+ '42501', null,
537
+ 'an expired invite cannot repair a partial fleet suffix'
538
+ );
539
+
540
+ update agent_board.board_invite_tokens
541
+ set expires_at = now() + interval '1 hour'
542
+ where id = (select invite_id from _atomic_cfg);
543
+ update agent_board.agents set status = 'suspended'
544
+ where id = (select owner_id from _atomic_cfg);
545
+ select throws_ok(
546
+ $$select * from agent_board.onboard_federated_fleet_agent(
547
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
548
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":364}'::jsonb, 'atomic-runtime-agent',
549
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
550
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
551
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
552
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg), 'codex', 'phase-loop',
553
+ 'message-board', 'sha256:atomic-runtime-repo', 'worker', 'phase_worker',
554
+ 'atomic-runtime-agent')$$,
555
+ '42501', null,
556
+ 'an inactive invite creator cannot repair a partial fleet suffix'
557
+ );
558
+
559
+ update agent_board.agents set status = 'active'
560
+ where id = (select owner_id from _atomic_cfg);
561
+ select lives_ok(
562
+ $$insert into _atomic_result
563
+ select 'partial-recovery', r.agent_id, r.signing_key_id, r.board_id,
564
+ r.harness_registration_id, r.repo_scope_id, r.fleet_machine_agent_id,
565
+ r.binding_signing_key_id,
566
+ r.identity_disposition, r.membership_disposition,
567
+ r.harness_disposition, r.repo_scope_disposition, r.binding_disposition
568
+ from agent_board.onboard_federated_fleet_agent(
569
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
570
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":365}'::jsonb,
571
+ 'atomic-runtime-agent',
572
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
573
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
574
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
575
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
576
+ 'codex', 'phase-loop', 'message-board', 'sha256:atomic-runtime-repo',
577
+ 'worker', 'phase_worker', 'atomic-runtime-agent') r$$,
578
+ 'a current authorized invite repairs an exact partial suffix'
579
+ );
580
+ select is((select count(*)::int from agent_board.fleet_machine_agents
581
+ where agent_id=(select agent_id from _atomic_result where attempt='first')), 1,
582
+ 'authorized partial recovery creates exactly one replacement binding');
583
+ select is((select binding_disposition from _atomic_result where attempt='partial-recovery'), 'recovered',
584
+ 'authorized partial recovery reports recovered disposition');
585
+ select is(
586
+ (select count(*)::text from agent_board.board_invite_redemptions
587
+ where invite_id=(select invite_id from _atomic_cfg)) || '/' ||
588
+ (select count(*)::text from agent_board.board_memberships
589
+ where board_id=(select board_id from _atomic_cfg)
590
+ and agent_id=(select agent_id from _atomic_result where attempt='first')
591
+ and membership_state in ('joined','subscribed')),
592
+ '1/1',
593
+ 'partial recovery preserves one redemption and one active membership'
594
+ );
595
+ update _atomic_result
596
+ set fleet_machine_agent_id = (
597
+ select fleet_machine_agent_id from _atomic_result where attempt='partial-recovery'
598
+ )
599
+ where attempt in ('first', 'replay', 'expired-complete-replay');
600
+
601
+ select lives_ok(
602
+ format(
603
+ 'select * from agent_board.revoke_fleet_machine_agent_binding(%L::uuid,%L::uuid,%L,%L::jsonb)',
604
+ (select fleet_machine_agent_id from _atomic_result where attempt='first'),
605
+ (select owner_id from _atomic_cfg), 'runtime test', '{}'
606
+ ),
607
+ 'the exact-binding sole writer permanently revokes the binding'
608
+ );
609
+ select is((select lifecycle_state from agent_board.fleet_machine_agents
610
+ where id=(select fleet_machine_agent_id from _atomic_result where attempt='first')),
611
+ 'revoked',
612
+ 'the exact binding remains a revoked tombstone');
613
+ select throws_ok(
614
+ $$select * from agent_board.onboard_federated_fleet_agent(
615
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
616
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":400}'::jsonb, 'atomic-runtime-agent',
617
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
618
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
619
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
620
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg), 'codex', 'phase-loop',
621
+ 'message-board', 'sha256:atomic-runtime-repo', 'worker', 'phase_worker',
622
+ 'atomic-runtime-agent')$$,
623
+ '42501', null,
624
+ 'post-revocation exact replay cannot create replacement authority'
625
+ );
626
+ select is((select count(*)::int from agent_board.fleet_machine_agents
627
+ where agent_id=(select agent_id from _atomic_result where attempt='first')), 1,
628
+ 'post-revocation replay leaves only the original tombstone');
629
+
630
+ do $$
631
+ declare
632
+ v_agent uuid;
633
+ v_key uuid;
634
+ v_invite uuid;
635
+ v_code text;
636
+ begin
637
+ select e.agent_id, e.signing_key_id
638
+ into v_agent, v_key
639
+ from agent_board.enroll_federated_identity(
640
+ 'https://atomic-runtime.test', 'message-board', 'human-recovery',
641
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-recovery","iat":500}'::jsonb,
642
+ 'atomic-recovery-agent',
643
+ 'yd_DIFGWGusVg3SbktDJQ1bE5UWvtR33xln4b05JIhk',
644
+ 'raw_ed25519_base64url',
645
+ 'sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA',
646
+ true, null, 'agent', '{board:send}', '{}', null
647
+ ) e;
648
+
649
+ select invite_id, code into v_invite, v_code
650
+ from agent_board.create_fleet_onboarding_invite(
651
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
652
+ 'codex', 'recovery-harness', 'message-board', 'sha256:recovery-repo',
653
+ 'worker', 'phase_worker', 'atomic-recovery-agent', 1,
654
+ now() + interval '1 hour', (select owner_id from _atomic_cfg), '{}'::jsonb
655
+ );
656
+ insert into _recovery_cfg values (v_agent, v_key, v_invite, v_code);
657
+ end
658
+ $$;
659
+
660
+ select lives_ok(
661
+ $$insert into _recovery_result
662
+ select r.agent_id, r.signing_key_id, r.identity_disposition,
663
+ r.membership_disposition, r.harness_disposition,
664
+ r.repo_scope_disposition, r.binding_disposition
665
+ from agent_board.onboard_federated_fleet_agent(
666
+ 'https://atomic-runtime.test', 'message-board', 'human-recovery',
667
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-recovery","iat":501,"jti":"rotated"}'::jsonb,
668
+ 'atomic-recovery-agent',
669
+ 'yd_DIFGWGusVg3SbktDJQ1bE5UWvtR33xln4b05JIhk', 'raw_ed25519_base64url',
670
+ 'sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA', true, null, 'agent',
671
+ '{board:send}', '{}', (select invite_code from _recovery_cfg),
672
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
673
+ 'codex', 'recovery-harness', 'message-board', 'sha256:recovery-repo',
674
+ 'worker', 'phase_worker', 'atomic-recovery-agent') r$$,
675
+ 'an exact legacy identity recovers its missing membership and fleet suffix'
676
+ );
677
+ select is((select agent_id from _recovery_result),
678
+ (select legacy_agent_id from _recovery_cfg),
679
+ 'legacy recovery reuses the exact principal');
680
+ select is((select signing_key_id from _recovery_result),
681
+ (select legacy_signing_key_id from _recovery_cfg),
682
+ 'legacy recovery reuses the exact proven signing key');
683
+ select is(
684
+ (select identity_disposition || '/' || membership_disposition || '/' ||
685
+ harness_disposition || '/' || repo_scope_disposition || '/' || binding_disposition
686
+ from _recovery_result),
687
+ 'reused/created/recovered/recovered/recovered',
688
+ 'legacy recovery reports the created and recovered suffix components');
689
+ select is(
690
+ (select count(*)::text from agent_board.board_invite_redemptions
691
+ where invite_id=(select invite_id from _recovery_cfg)) || '/' ||
692
+ (select count(*)::text from agent_board.board_memberships
693
+ where board_id=(select board_id from _atomic_cfg)
694
+ and agent_id=(select legacy_agent_id from _recovery_cfg)
695
+ and membership_state in ('joined','subscribed')) || '/' ||
696
+ (select count(*)::text from agent_board.fleet_machine_agents
697
+ where agent_id=(select legacy_agent_id from _recovery_cfg)),
698
+ '1/1/1',
699
+ 'legacy recovery creates exactly one redemption, membership, and binding');
700
+
701
+ insert into agent_board.agents(
702
+ id, agent_type, handle, display_name, status
703
+ ) values (
704
+ '16210000-0000-0000-0000-000000000099', 'agent',
705
+ 'atomic-collision-agent', 'Atomic Collision Occupant', 'active'
706
+ );
707
+ insert into _collision_cfg
708
+ select invite_id, code
709
+ from agent_board.create_fleet_onboarding_invite(
710
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
711
+ 'codex', 'collision-harness', 'message-board', 'sha256:collision-repo',
712
+ 'worker', 'phase_worker', 'atomic-collision-agent', 1,
713
+ now() + interval '1 hour', (select owner_id from _atomic_cfg), '{}'::jsonb
714
+ );
715
+ select throws_ok(
716
+ $$select * from agent_board.onboard_federated_fleet_agent(
717
+ 'https://atomic-runtime.test', 'message-board', 'human-collision',
718
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-collision","iat":600}'::jsonb,
719
+ 'atomic-collision-agent',
720
+ '4KAcBIlVxExOCkFemWSjOREACgi90CE_2-EFbmRYAzM', 'raw_ed25519_base64url',
721
+ 'sha256:M-L7uu74kuf1rPVyZcW9Ar-LD1ZULN3E36HKqy93O3Q', true, null, 'agent',
722
+ '{board:send}', '{}', (select invite_code from _collision_cfg),
723
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
724
+ 'codex', 'collision-harness', 'message-board', 'sha256:collision-repo',
725
+ 'worker', 'phase_worker', 'atomic-collision-agent')$$,
726
+ '23505', null,
727
+ 'server handle disambiguation is a late failure, not committed substitution'
728
+ );
729
+ select is((select count(*)::int from agent_board.agent_signing_keys
730
+ where fingerprint='sha256:M-L7uu74kuf1rPVyZcW9Ar-LD1ZULN3E36HKqy93O3Q'), 0,
731
+ 'late handle collision rolls back the newly proven key');
732
+ select is((select count(*)::int from agent_board.enrollment_federation_audit
733
+ where issuer='https://atomic-runtime.test' and subject='human-collision'), 0,
734
+ 'late handle collision rolls back enrollment audit evidence');
735
+ select is(
736
+ (select uses_count::text from agent_board.board_invite_tokens
737
+ where id=(select invite_id from _collision_cfg)) || '/' ||
738
+ (select count(*)::text from agent_board.board_invite_redemptions
739
+ where invite_id=(select invite_id from _collision_cfg)) || '/' ||
740
+ (select count(*)::text from agent_board.fleet_harness_registrations
741
+ where harness_label='collision-harness'),
742
+ '0/0/0',
743
+ 'late handle collision rolls back invite, redemption, and fleet writes');
744
+
745
+ insert into agent_board.agents(id, agent_type, handle, display_name, status)
746
+ values ('16210000-0000-0000-0000-000000000098', 'agent',
747
+ 'atomic-wrong-creator', 'Atomic Wrong Creator', 'active');
748
+ select throws_ok(
749
+ $$select * from agent_board.create_fleet_onboarding_invite(
750
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
751
+ 'codex', 'wrong-creator', 'message-board', 'sha256:wrong-creator',
752
+ 'worker', 'phase_worker', 'wrong-creator-agent', 1,
753
+ now() + interval '1 hour',
754
+ '16210000-0000-0000-0000-000000000098'::uuid, '{}'::jsonb)$$,
755
+ '42501', null,
756
+ 'an agent that does not own the machine cannot mint its bounded invite'
757
+ );
758
+
759
+ update agent_board.fleet_machines
760
+ set lifecycle_state='revoked', revoked_at=now()
761
+ where id=(select machine_id from _atomic_cfg);
762
+ select is(pg_temp._atomic_history_attempt(650), '42501',
763
+ 'composed fleet replay rejects a revoked machine');
764
+ select throws_ok(
765
+ $$select * from agent_board.create_fleet_onboarding_invite(
766
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
767
+ 'codex', 'inactive-machine', 'message-board', 'sha256:inactive-machine',
768
+ 'worker', 'phase_worker', 'inactive-machine-agent', 1,
769
+ now() + interval '1 hour', (select owner_id from _atomic_cfg), '{}'::jsonb)$$,
770
+ '42501', null,
771
+ 'a revoked machine cannot mint a bounded fleet invite'
772
+ );
773
+ update agent_board.fleet_machines
774
+ set lifecycle_state='active', revoked_at=null
775
+ where id=(select machine_id from _atomic_cfg);
776
+
777
+ update agent_board.fleet_trust_domains
778
+ set lifecycle_state='revoked', revoked_at=now()
779
+ where id=(select trust_domain_id from agent_board.fleet_machines
780
+ where id=(select machine_id from _atomic_cfg));
781
+ select is(pg_temp._atomic_history_attempt(651), '42501',
782
+ 'composed fleet replay rejects a revoked trust domain');
783
+ select throws_ok(
784
+ $$select * from agent_board.create_fleet_onboarding_invite(
785
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
786
+ 'codex', 'inactive-domain', 'message-board', 'sha256:inactive-domain',
787
+ 'worker', 'phase_worker', 'inactive-domain-agent', 1,
788
+ now() + interval '1 hour', (select owner_id from _atomic_cfg), '{}'::jsonb)$$,
789
+ '42501', null,
790
+ 'an inactive trust domain cannot mint a bounded fleet invite'
791
+ );
792
+ update agent_board.fleet_trust_domains
793
+ set lifecycle_state='active', revoked_at=null
794
+ where id=(select trust_domain_id from agent_board.fleet_machines
795
+ where id=(select machine_id from _atomic_cfg));
796
+
797
+ select throws_ok(
798
+ $$select * from agent_board.create_fleet_onboarding_invite(
799
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
800
+ '../bad-kind', 'malformed', 'message-board', 'sha256:malformed',
801
+ 'worker', 'phase_worker', 'malformed-agent', 1,
802
+ now() + interval '1 hour', (select owner_id from _atomic_cfg), '{}'::jsonb)$$,
803
+ '22023', null,
804
+ 'malformed fleet descriptors are rejected before invite creation'
805
+ );
806
+
807
+ create temp table _matrix_invites(
808
+ case_name text primary key,
809
+ invite_id uuid not null,
810
+ invite_code text not null
811
+ );
812
+
813
+ insert into _matrix_invites
814
+ select 'generic', invite_id, code
815
+ from agent_board.create_invite_link(
816
+ (select board_id from _atomic_cfg), 'member', 'joined', 1,
817
+ now() + interval '1 hour', (select owner_id from _atomic_cfg), '{}'::jsonb
818
+ );
819
+ select throws_ok(
820
+ $$select * from agent_board.onboard_federated_fleet_agent(
821
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
822
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":700}'::jsonb,
823
+ 'atomic-runtime-agent',
824
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
825
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
826
+ '{board:send}', '{}', (select invite_code from _matrix_invites where case_name='generic'),
827
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
828
+ 'codex', 'phase-loop', 'message-board', 'sha256:atomic-runtime-repo',
829
+ 'worker', 'phase_worker', 'atomic-runtime-agent')$$,
830
+ '42501', null, 'a generic invite cannot enter the composed fleet path'
831
+ );
832
+ select is(
833
+ (select uses_count::text from agent_board.board_invite_tokens
834
+ where id=(select invite_id from _matrix_invites where case_name='generic')) || '/' ||
835
+ (select count(*)::text from agent_board.board_invite_redemptions
836
+ where invite_id=(select invite_id from _matrix_invites where case_name='generic')),
837
+ '0/0', 'generic-invite rejection leaves uses and redemption counts unchanged'
838
+ );
839
+
840
+ update agent_board.board_memberships
841
+ set membership_state='removed', left_at=now(), updated_at=now()
842
+ where board_id=(select board_id from _atomic_cfg)
843
+ and agent_id=(select owner_id from _atomic_cfg)
844
+ and membership_state in ('joined','subscribed');
845
+ select throws_ok(
846
+ $$select * from agent_board.onboard_federated_fleet_agent(
847
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
848
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":701}'::jsonb,
849
+ 'atomic-runtime-agent',
850
+ 'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0', 'raw_ed25519_base64url',
851
+ 'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8', true, null, 'agent',
852
+ '{board:send}', '{}', (select invite_code from _atomic_cfg),
853
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
854
+ 'codex', 'phase-loop', 'message-board', 'sha256:atomic-runtime-repo',
855
+ 'worker', 'phase_worker', 'atomic-runtime-agent')$$,
856
+ '42501', null, 'an invite whose creator is no longer a board member fails closed'
857
+ );
858
+ select is((select uses_count from agent_board.board_invite_tokens where id=(select invite_id from _atomic_cfg)), 1,
859
+ 'non-member creator rejection does not consume another invite use');
860
+ update agent_board.board_memberships
861
+ set membership_state='joined', role='owner', left_at=null, updated_at=now()
862
+ where board_id=(select board_id from _atomic_cfg)
863
+ and agent_id=(select owner_id from _atomic_cfg)
864
+ and membership_state='removed';
865
+
866
+ select throws_ok(
867
+ $$select * from agent_board.create_fleet_onboarding_invite(
868
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
869
+ 'codex', 'elevated-role', 'message-board', 'sha256:elevated-role',
870
+ 'worker', 'reviewer', 'elevated-role-agent', 1,
871
+ now() + interval '1 hour', (select owner_id from _atomic_cfg), '{}'::jsonb)$$,
872
+ '22023', null, 'an elevated or mismatched role pair cannot mint a fleet invite'
873
+ );
874
+
875
+ insert into _matrix_invites
876
+ select 'conflict', invite_id, code
877
+ from agent_board.create_fleet_onboarding_invite(
878
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
879
+ 'codex', 'conflict-harness', 'message-board', 'sha256:conflict-repo',
880
+ 'worker', 'phase_worker', 'atomic-conflict-agent', 1,
881
+ now() + interval '1 hour', (select owner_id from _atomic_cfg), '{}'::jsonb
882
+ );
883
+ insert into agent_board.fleet_harness_registrations(machine_id, harness_kind, harness_label)
884
+ values ((select machine_id from _atomic_cfg), 'codex', 'conflict-harness');
885
+ insert into agent_board.fleet_repo_scopes(
886
+ harness_registration_id, repo_slug, repo_fingerprint, scope_role
887
+ ) select id, 'other-repo', 'sha256:conflict-repo', 'worker'
888
+ from agent_board.fleet_harness_registrations
889
+ where machine_id=(select machine_id from _atomic_cfg)
890
+ and harness_kind='codex' and harness_label='conflict-harness';
891
+ select throws_ok(
892
+ $$select * from agent_board.onboard_federated_fleet_agent(
893
+ 'https://atomic-runtime.test', 'message-board', 'human-conflict',
894
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-conflict","iat":702}'::jsonb,
895
+ 'atomic-conflict-agent',
896
+ '5TG73fnNhqeYkoSvPf9QwmWkvKWe0yA7B8YinAWQ8m4', 'raw_ed25519_base64url',
897
+ 'sha256:qhjEQe9R_x26TBZyBsd-LrpR1fh7Mvnz86rbsCKtjz8', true, null, 'agent',
898
+ '{board:send}', '{}', (select invite_code from _matrix_invites where case_name='conflict'),
899
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
900
+ 'codex', 'conflict-harness', 'message-board', 'sha256:conflict-repo',
901
+ 'worker', 'phase_worker', 'atomic-conflict-agent')$$,
902
+ '42501', null, 'a conflicting active repo registration rejects atomic onboarding'
903
+ );
904
+ select is(
905
+ (select count(*)::text from agent_board.agent_signing_keys
906
+ where fingerprint='sha256:qhjEQe9R_x26TBZyBsd-LrpR1fh7Mvnz86rbsCKtjz8') || '/' ||
907
+ (select count(*)::text from agent_board.board_invite_redemptions
908
+ where invite_id=(select invite_id from _matrix_invites where case_name='conflict')),
909
+ '0/0', 'conflicting active registration rolls back identity and redemption writes'
910
+ );
911
+
912
+ do $$
913
+ declare
914
+ v_agent uuid;
915
+ v_invite uuid;
916
+ v_code text;
917
+ begin
918
+ select agent_id into v_agent from agent_board.enroll_federated_identity(
919
+ 'https://atomic-runtime.test', 'message-board', 'human-blocked',
920
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-blocked","iat":703}'::jsonb,
921
+ 'atomic-blocked-agent',
922
+ 'HdUqLbj-jcUwvwE4rf9WXeDQrjrAtYUT6YmnsGMKcNQ', 'raw_ed25519_base64url',
923
+ 'sha256:d115bUBikhOk-QFOCc-lItU2nRZMKf79kAHmvgLsKng', true, null, 'agent',
924
+ '{board:send}', '{}', null
925
+ );
926
+ insert into agent_board.board_memberships(
927
+ board_id, agent_id, membership_state, role, left_at, created_by_agent_id
928
+ ) values (
929
+ (select board_id from _atomic_cfg), v_agent, 'removed', 'member', now(),
930
+ (select owner_id from _atomic_cfg)
931
+ );
932
+ select invite_id, code into v_invite, v_code
933
+ from agent_board.create_fleet_onboarding_invite(
934
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
935
+ 'codex', 'blocked-harness', 'message-board', 'sha256:blocked-repo',
936
+ 'worker', 'phase_worker', 'atomic-blocked-agent', 1,
937
+ now() + interval '1 hour', (select owner_id from _atomic_cfg), '{}'::jsonb
938
+ );
939
+ insert into _matrix_invites values ('blocked', v_invite, v_code);
940
+ end
941
+ $$;
942
+ select throws_ok(
943
+ $$select * from agent_board.onboard_federated_fleet_agent(
944
+ 'https://atomic-runtime.test', 'message-board', 'human-blocked',
945
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-blocked","iat":704}'::jsonb,
946
+ 'atomic-blocked-agent',
947
+ 'HdUqLbj-jcUwvwE4rf9WXeDQrjrAtYUT6YmnsGMKcNQ', 'raw_ed25519_base64url',
948
+ 'sha256:d115bUBikhOk-QFOCc-lItU2nRZMKf79kAHmvgLsKng', true, null, 'agent',
949
+ '{board:send}', '{}', (select invite_code from _matrix_invites where case_name='blocked'),
950
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
951
+ 'codex', 'blocked-harness', 'message-board', 'sha256:blocked-repo',
952
+ 'worker', 'phase_worker', 'atomic-blocked-agent')$$,
953
+ '42501', null, 'a removed target membership blocks fleet invite redemption'
954
+ );
955
+ select is(
956
+ (select uses_count::text from agent_board.board_invite_tokens
957
+ where id=(select invite_id from _matrix_invites where case_name='blocked')) || '/' ||
958
+ (select count(*)::text from agent_board.fleet_harness_registrations where harness_label='blocked-harness'),
959
+ '0/0', 'blocked invite leaves invite and fleet counts unchanged'
960
+ );
961
+
962
+ insert into _matrix_invites
963
+ select 'late-failure', invite_id, code
964
+ from agent_board.create_fleet_onboarding_invite(
965
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
966
+ 'codex', 'late-failure-harness', 'message-board', 'sha256:late-failure-repo',
967
+ 'worker', 'phase_worker', 'atomic-late-failure-agent', 1,
968
+ now() + interval '1 hour', (select owner_id from _atomic_cfg), '{}'::jsonb
969
+ );
970
+ create function pg_temp._atomic_late_binding_failure() returns trigger
971
+ language plpgsql as $$
972
+ begin
973
+ if new.agent_role = 'phase_worker' then
974
+ raise exception 'injected late fleet constraint failure' using errcode = '23514';
975
+ end if;
976
+ return new;
977
+ end
978
+ $$;
979
+ create trigger atomic_late_binding_failure
980
+ before insert on agent_board.fleet_machine_agents
981
+ for each row execute function pg_temp._atomic_late_binding_failure();
982
+ select throws_ok(
983
+ $$select * from agent_board.onboard_federated_fleet_agent(
984
+ 'https://atomic-runtime.test', 'message-board', 'human-late-failure',
985
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-late-failure","iat":705}'::jsonb,
986
+ 'atomic-late-failure-agent',
987
+ 'TDyof3w0SMg4SDYuj-qenolHC_n05cZbrLSckKVGtMo', 'raw_ed25519_base64url',
988
+ 'sha256:lSBZnHvmPvQONy8aoygp-fmTg26iZenrZC-L5LN9m7M', true, null, 'agent',
989
+ '{board:send}', '{}', (select invite_code from _matrix_invites where case_name='late-failure'),
990
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
991
+ 'codex', 'late-failure-harness', 'message-board', 'sha256:late-failure-repo',
992
+ 'worker', 'phase_worker', 'atomic-late-failure-agent')$$,
993
+ '23514', null, 'an injected late binding constraint aborts the composed transaction'
994
+ );
995
+ drop trigger atomic_late_binding_failure on agent_board.fleet_machine_agents;
996
+ select is(
997
+ (select count(*)::text from agent_board.agent_signing_keys
998
+ where fingerprint='sha256:lSBZnHvmPvQONy8aoygp-fmTg26iZenrZC-L5LN9m7M') || '/' ||
999
+ (select count(*)::text from agent_board.enrollment_federation_audit
1000
+ where subject='human-late-failure') || '/' ||
1001
+ (select count(*)::text from agent_board.board_invite_redemptions
1002
+ where invite_id=(select invite_id from _matrix_invites where case_name='late-failure')) || '/' ||
1003
+ (select count(*)::text from agent_board.fleet_harness_registrations where harness_label='late-failure-harness'),
1004
+ '0/0/0/0', 'late fleet failure rolls back identity, audit, redemption, and fleet writes'
1005
+ );
1006
+ select is(
1007
+ (select uses_count::text from agent_board.board_invite_tokens
1008
+ where id=(select invite_id from _matrix_invites where case_name='late-failure')) || '/' ||
1009
+ (select count(*)::text from agent_board.board_memberships
1010
+ where agent_id in (select id from agent_board.agents where handle='atomic-late-failure-agent')),
1011
+ '0/0', 'late fleet failure preserves invite use and membership counts'
1012
+ );
1013
+
1014
+ update agent_board.boards set status='archived'
1015
+ where id=(select board_id from _atomic_cfg);
1016
+ select throws_ok(
1017
+ $$select * from agent_board.create_fleet_onboarding_invite(
1018
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
1019
+ 'codex', 'archived-board', 'message-board', 'sha256:archived-board',
1020
+ 'worker', 'phase_worker', 'archived-board-agent', 1,
1021
+ now() + interval '1 hour', (select owner_id from _atomic_cfg), '{}'::jsonb)$$,
1022
+ '42501', null, 'an archived board cannot mint a bounded fleet invite'
1023
+ );
1024
+ select is(pg_temp._atomic_history_attempt(800), '42501',
1025
+ 'an archived board cannot redeem an existing bounded fleet invite');
1026
+ select is((select uses_count from agent_board.board_invite_tokens
1027
+ where id=(select invite_id from _atomic_cfg)), 1,
1028
+ 'archived-board rejection consumes no invite use');
1029
+ update agent_board.boards set status='active'
1030
+ where id=(select board_id from _atomic_cfg);
1031
+
1032
+ select set_config('request.jwt.claim.role', 'authenticated', true);
1033
+ select set_config(
1034
+ 'request.jwt.claim.sub',
1035
+ (select auth_user_id::text from agent_board.agents
1036
+ where id=(select agent_id from _atomic_result where attempt='first')),
1037
+ true
1038
+ );
1039
+ select throws_ok(
1040
+ $$select * from agent_board.register_agent(
1041
+ 'agent', 'atomic-runtime-agent', 'Atomic Runtime Agent', 'active',
1042
+ '{"federation":{"replay":{"subject":"forged"}}}'::jsonb)$$,
1043
+ '42501', null, 'authenticated register_agent cannot rewrite frozen federation metadata'
1044
+ );
1045
+ select throws_ok(
1046
+ $$select * from agent_board.register_agent(
1047
+ 'agent', 'atomic-runtime-agent-renamed', 'Atomic Runtime Agent', 'active', '{}'::jsonb)$$,
1048
+ '42501', null, 'authenticated register_agent cannot rename a frozen replay principal'
1049
+ );
1050
+ select set_config('request.jwt.claim.role', 'service_role', true);
1051
+ select set_config('request.jwt.claim.sub', '', true);
1052
+ select is(
1053
+ (select handle || '/' || (metadata #>> '{federation,replay,subject}')
1054
+ from agent_board.agents
1055
+ where id=(select agent_id from _atomic_result where attempt='first')),
1056
+ 'atomic-runtime-agent/human-runtime',
1057
+ 'rejected authenticated mutations leave the frozen replay projection unchanged'
1058
+ );
1059
+
1060
+ insert into _matrix_invites
1061
+ select 'human-revoked', invite_id, code
1062
+ from agent_board.create_fleet_onboarding_invite(
1063
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
1064
+ 'codex', 'human-revoked', 'message-board', 'sha256:human-revoked',
1065
+ 'worker', 'phase_worker', 'atomic-revoked-future', 1,
1066
+ now() + interval '1 hour', (select owner_id from _atomic_cfg), '{}'::jsonb
1067
+ );
1068
+ select lives_ok(
1069
+ format(
1070
+ 'select * from agent_board.revoke_human_subtree(%L::uuid,%L::uuid,%L)',
1071
+ (select owner_user_id from agent_board.agents
1072
+ where id=(select agent_id from _atomic_result where attempt='first')),
1073
+ (select owner_id from _atomic_cfg), 'runtime total human revoke'
1074
+ ),
1075
+ 'total human revocation durably marks and revokes the existing subtree'
1076
+ );
1077
+ insert into _human_revocation_cfg
1078
+ select owner_user_id from agent_board.agents
1079
+ where id=(select agent_id from _atomic_result where attempt='first');
1080
+ select is(
1081
+ (select count(*)::int from agent_board.fleet_human_revocations
1082
+ where owner_user_id=(select owner_user_id from agent_board.agents
1083
+ where id=(select agent_id from _atomic_result where attempt='first'))),
1084
+ 1, 'total human revocation stores one durable owner marker'
1085
+ );
1086
+ select throws_ok(
1087
+ $$select * from agent_board.onboard_federated_fleet_agent(
1088
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
1089
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":801}'::jsonb,
1090
+ 'atomic-revoked-future',
1091
+ 'TDyof3w0SMg4SDYuj-qenolHC_n05cZbrLSckKVGtMo', 'raw_ed25519_base64url',
1092
+ 'sha256:lSBZnHvmPvQONy8aoygp-fmTg26iZenrZC-L5LN9m7M', true, null, 'agent',
1093
+ '{board:send}', '{}', (select invite_code from _matrix_invites where case_name='human-revoked'),
1094
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
1095
+ 'codex', 'human-revoked', 'message-board', 'sha256:human-revoked',
1096
+ 'worker', 'phase_worker', 'atomic-revoked-future')$$,
1097
+ '42501', null, 'a durably revoked human cannot onboard a fresh key'
1098
+ );
1099
+ select is(
1100
+ (select count(*)::int from agent_board.agent_signing_keys
1101
+ where fingerprint='sha256:lSBZnHvmPvQONy8aoygp-fmTg26iZenrZC-L5LN9m7M'),
1102
+ 0, 'revoked-human fresh onboarding creates no signing key'
1103
+ );
1104
+
1105
+ insert into auth.users(id, instance_id, aud, role, email, created_at, updated_at)
1106
+ values (
1107
+ '16200000-0000-0000-0000-000000000098',
1108
+ '00000000-0000-0000-0000-000000000000',
1109
+ 'authenticated', 'authenticated', 'atomic-audit-owner@example.test', now(), now()
1110
+ );
1111
+ insert into agent_board.agents(
1112
+ id, agent_type, kind, handle, display_name, status, auth_user_id, owner_user_id, metadata
1113
+ ) values (
1114
+ '16200000-0000-0000-0000-000000000198', 'agent', 'agent',
1115
+ 'atomic-audit-owner', 'Atomic Audit Owner', 'active',
1116
+ '16200000-0000-0000-0000-000000000098',
1117
+ '16200000-0000-0000-0000-000000000098',
1118
+ '{"federation":{"issuer":"https://forged-metadata.test","subject":"forged-metadata-subject"}}'::jsonb
1119
+ );
1120
+ insert into agent_board.enrollment_federation_audit(
1121
+ issuer, audience, subject, human_identity_claim, provider_id,
1122
+ agent_id, auth_user_id, requested_scopes, granted_scopes
1123
+ ) values (
1124
+ 'https://immutable-audit.test', 'message-board', 'immutable-audit-subject',
1125
+ '{"iss":"https://immutable-audit.test","aud":"message-board","sub":"immutable-audit-subject"}'::jsonb,
1126
+ null, '16200000-0000-0000-0000-000000000198',
1127
+ '16200000-0000-0000-0000-000000000098', '{}', '{}'
1128
+ );
1129
+ select lives_ok(
1130
+ $$select * from agent_board.revoke_human_subtree(
1131
+ '16200000-0000-0000-0000-000000000098',
1132
+ (select owner_id from _atomic_cfg), 'immutable evidence runtime')$$,
1133
+ 'total human revocation accepts stable audit evidence even when metadata is forged'
1134
+ );
1135
+ select is(
1136
+ (select count(*)::int from agent_board.fleet_human_revocations
1137
+ where issuer='https://immutable-audit.test' and subject='immutable-audit-subject'),
1138
+ 1, 'human revocation marker is derived from append-only audit evidence'
1139
+ );
1140
+ select is(
1141
+ (select count(*)::int from agent_board.fleet_human_revocations
1142
+ where issuer='https://forged-metadata.test' or subject='forged-metadata-subject'),
1143
+ 0, 'historically mutable federation metadata cannot choose the revocation marker'
1144
+ );
1145
+
1146
+ insert into auth.users(id, instance_id, aud, role, email, created_at, updated_at)
1147
+ values (
1148
+ '16200000-0000-0000-0000-000000000097',
1149
+ '00000000-0000-0000-0000-000000000000',
1150
+ 'authenticated', 'authenticated', 'atomic-missing-audit@example.test', now(), now()
1151
+ );
1152
+ insert into agent_board.agents(
1153
+ id, agent_type, kind, handle, display_name, status, auth_user_id, owner_user_id, metadata
1154
+ ) values (
1155
+ '16200000-0000-0000-0000-000000000197', 'agent', 'agent',
1156
+ 'atomic-missing-audit', 'Atomic Missing Audit', 'active',
1157
+ '16200000-0000-0000-0000-000000000097',
1158
+ '16200000-0000-0000-0000-000000000097',
1159
+ '{"federation":{"issuer":"https://missing-audit.test","subject":"missing-audit-subject"}}'::jsonb
1160
+ );
1161
+ select throws_ok(
1162
+ $$select * from agent_board.revoke_human_subtree(
1163
+ '16200000-0000-0000-0000-000000000097',
1164
+ (select owner_id from _atomic_cfg), 'missing evidence runtime')$$,
1165
+ 'P0002', null, 'federation-linked human revocation fails closed without stable audit evidence'
1166
+ );
1167
+ select is(
1168
+ (select status from agent_board.agents where id='16200000-0000-0000-0000-000000000197'),
1169
+ 'active', 'missing-evidence failure commits no partial subtree revocation'
1170
+ );
1171
+
1172
+ insert into auth.users(id, instance_id, aud, role, email, created_at, updated_at)
1173
+ values (
1174
+ '16200000-0000-0000-0000-000000000096',
1175
+ '00000000-0000-0000-0000-000000000000',
1176
+ 'authenticated', 'authenticated', 'atomic-mixed-audit@example.test', now(), now()
1177
+ );
1178
+ insert into agent_board.agents(
1179
+ id, agent_type, kind, handle, display_name, status, auth_user_id, owner_user_id, metadata
1180
+ ) values
1181
+ (
1182
+ '16200000-0000-0000-0000-000000000196', 'agent', 'agent',
1183
+ 'atomic-mixed-audited', 'Atomic Mixed Audited', 'active',
1184
+ '16200000-0000-0000-0000-000000000096',
1185
+ '16200000-0000-0000-0000-000000000096',
1186
+ '{"federation":{"issuer":"https://mixed-audit.test","subject":"mixed-audited"}}'::jsonb
1187
+ ),
1188
+ (
1189
+ '16200000-0000-0000-0000-000000000296', 'agent', 'agent',
1190
+ 'atomic-mixed-unaudited', 'Atomic Mixed Unaudited', 'active',
1191
+ null, '16200000-0000-0000-0000-000000000096',
1192
+ '{"federation":{"issuer":"https://mixed-audit.test","subject":"mixed-unaudited"}}'::jsonb
1193
+ );
1194
+ insert into agent_board.enrollment_federation_audit(
1195
+ issuer, audience, subject, human_identity_claim, provider_id,
1196
+ agent_id, auth_user_id, requested_scopes, granted_scopes
1197
+ ) values (
1198
+ 'https://mixed-audit.test', 'message-board', 'mixed-audited',
1199
+ '{"iss":"https://mixed-audit.test","aud":"message-board","sub":"mixed-audited"}'::jsonb,
1200
+ null, '16200000-0000-0000-0000-000000000196',
1201
+ '16200000-0000-0000-0000-000000000096', '{}', '{}'
1202
+ );
1203
+ select throws_ok(
1204
+ $$select * from agent_board.revoke_human_subtree(
1205
+ '16200000-0000-0000-0000-000000000096',
1206
+ (select owner_id from _atomic_cfg), 'mixed evidence runtime')$$,
1207
+ 'P0002', null, 'mixed federation owner fails closed when any linked agent lacks stable audit evidence'
1208
+ );
1209
+ select is(
1210
+ (select count(*)::int from agent_board.agents
1211
+ where owner_user_id='16200000-0000-0000-0000-000000000096' and status='active'),
1212
+ 2, 'mixed-evidence failure commits no partial subtree revocation'
1213
+ );
1214
+ select is(
1215
+ (select count(*)::int from agent_board.fleet_human_revocations
1216
+ where issuer='https://mixed-audit.test'),
1217
+ 0, 'mixed-evidence failure commits no partial durable marker'
1218
+ );
1219
+
1220
+ select lives_ok(
1221
+ $$delete from auth.users where id=(select owner_user_id from _human_revocation_cfg)$$,
1222
+ 'auth-user cleanup does not erase the stable federation revocation marker'
1223
+ );
1224
+ select is(
1225
+ (select count(*)::int from agent_board.fleet_human_revocations
1226
+ where issuer='https://atomic-runtime.test' and subject='human-runtime'
1227
+ and owner_user_id is null),
1228
+ 1, 'stable federation revocation survives owner UUID deletion'
1229
+ );
1230
+ select throws_ok(
1231
+ $$select * from agent_board.onboard_federated_fleet_agent(
1232
+ 'https://atomic-runtime.test', 'message-board', 'human-runtime',
1233
+ '{"iss":"https://atomic-runtime.test","aud":"message-board","sub":"human-runtime","iat":802}'::jsonb,
1234
+ 'atomic-revoked-future',
1235
+ '8lbFi0KooZCbgv7LYQzJ455CsFFnoeOK9qkcsEwUBZg', 'raw_ed25519_base64url',
1236
+ 'sha256:SiF8ib634OSMsAhUlMQk44VFekSV1EcRHzkdhv-R8vc', true, null, 'agent',
1237
+ '{board:send}', '{}', (select invite_code from _matrix_invites where case_name='human-revoked'),
1238
+ (select board_id from _atomic_cfg), (select machine_id from _atomic_cfg),
1239
+ 'codex', 'human-revoked', 'message-board', 'sha256:human-revoked',
1240
+ 'worker', 'phase_worker', 'atomic-revoked-future')$$,
1241
+ '42501', null, 'deleted-owner identity remains durably barred from fresh-key onboarding'
1242
+ );
1243
+ select is(
1244
+ (select count(*)::int from agent_board.agent_signing_keys
1245
+ where fingerprint='sha256:SiF8ib634OSMsAhUlMQk44VFekSV1EcRHzkdhv-R8vc'),
1246
+ 0, 'deleted-owner rejection creates no fresh signing key'
1247
+ );
1248
+
1249
+ select * from finish();
1250
+ rollback;