@consiliency/agent-board-schema 1.53.0 → 1.55.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 (65) hide show
  1. package/fixtures/already-applied.json +615 -607
  2. package/migrations/20261004000100_agent_board_callback_consumer_intent.sql +52 -0
  3. package/migrations/20261005000100_agent_board_enroll_token_single_use.sql +886 -0
  4. package/package.json +1 -1
  5. package/schema-manifest.json +21 -3
  6. package/src/tooling.test.mjs +5 -2
  7. package/tests/agent_board_atomic_fleet_onboarding.test.sql +35 -35
  8. package/tests/agent_board_atomic_fleet_onboarding_backfill.test.sql +5 -5
  9. package/tests/agent_board_atomic_fleet_onboarding_runtime.test.sql +32 -32
  10. package/tests/agent_board_enroll_federated_identity.test.sql +11 -10
  11. package/tests/agent_board_enroll_pop_binding.test.sql +12 -12
  12. package/tests/agent_board_enroll_resumption.test.sql +1 -1
  13. package/tests/agent_board_enroll_token_single_use.test.sql +538 -0
  14. package/tests/agent_board_enrollment_audit_content.test.sql +3 -3
  15. package/tests/agent_board_federated_lock_order_class.test.sql +5 -5
  16. package/tests/agent_board_fedsession.test.sql +1 -1
  17. package/tests/agent_board_fk_lock_edges.test.sql +23 -0
  18. package/tests/agent_board_identity_providers.test.sql +3 -2
  19. package/tests/agent_board_portal_offline_invariant.test.sql +1 -1
  20. package/tests/agent_board_roomlink.test.sql +2 -2
  21. package/tests/agent_board_write_enforcement_class.test.sql +5 -2
  22. package/tests/catalog/function_execute_privileges.json +12 -3
  23. package/tests/catalog/p_metadata_parameters.json +6 -2
  24. package/tests/isolation/expected/atomic_fedsession_fleet_lock_order.out +1 -1
  25. package/tests/isolation/expected/atomic_fleet_authority_races.out +8 -8
  26. package/tests/isolation/expected/atomic_fleet_binding_revoke.out +2 -2
  27. package/tests/isolation/expected/atomic_fleet_board_archive.out +2 -2
  28. package/tests/isolation/expected/atomic_fleet_human_fresh_revoke.out +2 -2
  29. package/tests/isolation/expected/atomic_fleet_identity_disposition.out +2 -2
  30. package/tests/isolation/expected/atomic_fleet_lifecycle_races.out +22 -22
  31. package/tests/isolation/expected/atomic_fleet_onboarding.out +2 -2
  32. package/tests/isolation/expected/atomic_fleet_subtree_lock_order.out +1 -1
  33. package/tests/isolation/expected/enroll_identity_board_owner_lock_order.out +1 -1
  34. package/tests/isolation/expected/enroll_token_fleet_abort.out +81 -0
  35. package/tests/isolation/expected/enroll_token_pk_backstop.out +36 -0
  36. package/tests/isolation/expected/enroll_token_placement.out +86 -0
  37. package/tests/isolation/expected/enroll_token_rollback_unstrands.out +59 -0
  38. package/tests/isolation/expected/enroll_token_route_race_fleet_first.out +72 -0
  39. package/tests/isolation/expected/enroll_token_route_race_identity_first.out +72 -0
  40. package/tests/isolation/expected/enroll_token_same_key_fleet_then_identity.out +73 -0
  41. package/tests/isolation/expected/enroll_token_same_key_identity_then_fleet.out +73 -0
  42. package/tests/isolation/expected/enroll_token_same_key_resume.out +59 -0
  43. package/tests/isolation/expected/enroll_token_same_token_race.out +58 -0
  44. package/tests/isolation/expected/onboarding_ceiling_lock_order.out +2 -2
  45. package/tests/isolation/specs/atomic_fedsession_fleet_lock_order.spec +1 -1
  46. package/tests/isolation/specs/atomic_fleet_authority_races.spec +2 -2
  47. package/tests/isolation/specs/atomic_fleet_binding_revoke.spec +2 -2
  48. package/tests/isolation/specs/atomic_fleet_board_archive.spec +2 -2
  49. package/tests/isolation/specs/atomic_fleet_human_fresh_revoke.spec +2 -2
  50. package/tests/isolation/specs/atomic_fleet_identity_disposition.spec +2 -2
  51. package/tests/isolation/specs/atomic_fleet_lifecycle_races.spec +2 -2
  52. package/tests/isolation/specs/atomic_fleet_onboarding.spec +2 -2
  53. package/tests/isolation/specs/atomic_fleet_subtree_lock_order.spec +2 -2
  54. package/tests/isolation/specs/enroll_identity_board_owner_lock_order.spec +1 -1
  55. package/tests/isolation/specs/enroll_token_fleet_abort.spec +138 -0
  56. package/tests/isolation/specs/enroll_token_pk_backstop.spec +37 -0
  57. package/tests/isolation/specs/enroll_token_placement.spec +136 -0
  58. package/tests/isolation/specs/enroll_token_rollback_unstrands.spec +71 -0
  59. package/tests/isolation/specs/enroll_token_route_race_fleet_first.spec +119 -0
  60. package/tests/isolation/specs/enroll_token_route_race_identity_first.spec +120 -0
  61. package/tests/isolation/specs/enroll_token_same_key_fleet_then_identity.spec +112 -0
  62. package/tests/isolation/specs/enroll_token_same_key_identity_then_fleet.spec +113 -0
  63. package/tests/isolation/specs/enroll_token_same_key_resume.spec +70 -0
  64. package/tests/isolation/specs/enroll_token_same_token_race.spec +80 -0
  65. package/tests/isolation/specs/onboarding_ceiling_lock_order.spec +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@consiliency/agent-board-schema",
3
- "version": "1.53.0",
3
+ "version": "1.55.0",
4
4
  "description": "Canonical, immutable, exact-pinnable agent_board schema bundle: ordered SQL migrations, digest + compatibility manifest, and deterministic materialize/plan/check tooling for adopters.",
5
5
  "repository": "https://github.com/Consiliency/message-board.git",
6
6
  "type": "module",
@@ -2,7 +2,7 @@
2
2
  "schema": "agent_board_schema_manifest.v1",
3
3
  "interface": "IF-0-MBPLANE-BUNDLE-1",
4
4
  "package": "@consiliency/agent-board-schema",
5
- "packageVersion": "1.53.0",
5
+ "packageVersion": "1.55.0",
6
6
  "schemaVersion": 8,
7
7
  "minClientVersion": "1.1.0",
8
8
  "source": {
@@ -46,8 +46,8 @@
46
46
  "usage": "upsert (retention/monitoring defaults; on conflict do nothing)"
47
47
  }
48
48
  ],
49
- "migrationCount": 151,
50
- "aggregateSha256": "332c33f67f08d8bcdbf71ef2568ea03f6cd16ccdeaac4d1944259ab28012900c",
49
+ "migrationCount": 153,
50
+ "aggregateSha256": "90e7cdfd7208e11b31f1699482c22b96f2ad0d797eb9490c85098491881e95dc",
51
51
  "migrations": [
52
52
  {
53
53
  "order": 0,
@@ -1407,6 +1407,24 @@
1407
1407
  "sourceRef": "message-board",
1408
1408
  "bytes": 3993,
1409
1409
  "sha256": "7bcb993b9943cd7e6bd3777c90c32e9cb32e53415262f8c58a8d75678a449853"
1410
+ },
1411
+ {
1412
+ "order": 151,
1413
+ "id": "20261004000100_agent_board_callback_consumer_intent",
1414
+ "filename": "20261004000100_agent_board_callback_consumer_intent.sql",
1415
+ "origin": "message-board-forward",
1416
+ "sourceRef": "message-board",
1417
+ "bytes": 3403,
1418
+ "sha256": "cd1815a58978261be143426eaac2dfccb6bb86b003487e4d1866aba60e7a6eb6"
1419
+ },
1420
+ {
1421
+ "order": 152,
1422
+ "id": "20261005000100_agent_board_enroll_token_single_use",
1423
+ "filename": "20261005000100_agent_board_enroll_token_single_use.sql",
1424
+ "origin": "message-board-forward",
1425
+ "sourceRef": "message-board",
1426
+ "bytes": 55964,
1427
+ "sha256": "317d7b41432b36a2e38cc64940838e173e425014e3e256a96d832202b250e82d"
1410
1428
  }
1411
1429
  ],
1412
1430
  "excludedBridge": {
@@ -38,9 +38,9 @@ describe('manifest integrity', () => {
38
38
  expect(manifest.schemaVersion).toBe(8);
39
39
  expect(manifest.minClientVersion).toMatch(/^\d+\.\d+\.\d+$/);
40
40
  });
41
- it('registers the four MBAUTHZ + four MBSENDAUTHZ + four MBSESSION + four MBDELEG + three MBFED + three MBHARDEN + two MBPORTALGATE + two MBPORTAL-PR32 + two ROOMOWN + two ROOMLINK + one ROOMDELEG + one LOCALAUTH + one ROOMUIAPI + one FEDSESSION + one FEDSESSION-AUTOJOIN + one GATENULL + one MEMBSTATE + one AGENTSDIR + one LEAVEIDEM + one ROLERESET + one MBROWID + one MBHYGIENE + one MBCONSENT-A + one MBCONSENT-B(a) + one MBCONSENT-B(i) + one MBCONSENT-B(ii) + one MBCONSENT-B(iii) + one MBHARDEN-#97 + one MBHARDEN-#118 + one INVITEPOLICY + one OBSGATE + one OBSGATE-2 + one OBSGATE-3 + one OBSGATE-4 + one FLEETMACHINERLS + one RESOLVENOOP + one ROOMDELEG-LANEB + one CLAIMKEY + two MINTHARDEN + one FLEETMACHINEHIJACK + one CLAIMGATE-SHADOW + one CLAIMGATE-ENFORCE + one FLEETMACHINEREACTIVATION + one DELEGCAPCEILING + one FLEETMACHINERECLAIM + one DELEGSOLEWRITER + one FLEETDOMAINRECLAIM + five ATOMICFLEETONBOARDING (onboarding + ceiling-lock + revocation-evidence + fedsession-gate + fedsession-lock-order) + one OUTBOXWAKE + one ENROLLLOCKORDER + one FEDPROVIDERABSENCE + one WAKERECOVERY + one CONSENTRECONCILE + one ENROLLRESUMPTION + one SIGNEDAUTHORITY + one SIGNERLIFECYCLE + one LEDGERAUTHORITY + one CEILINGLOCKCOMMENT + one LEDGERBOARDCREATE + one RECEIPTSUBJECTGATE + one TASKTHREADLOCKORDER + one CLAIMSUBJECTGATE + one FEDSESSIONIDENTITYGATE + one FEDIDENTITYSLUG + one INVITENODOWNGRADE + one SIGNEDWRITEFLAG + one SIGNEDWRITEMODEL + one RTCREDCLAIM + one ORIGINPOSTURE + one BOARDCLAIMPOLICY + one HEARTBEATPRESERVE + one LIVENESSDENOM + one OWNERLESSRENEWTTL + one OWNERLESSQUOTACENSUS + one FLEETDOMAINNODOWNGRADE + one OWNERLESSQUOTACONVERGE + one ADVISORYREVERTRESET + one CLAIMPOLICYRACE + one CLAIMPOLICYLOCKGRANT + one SESSIONCHALLENGESUPERSEDE + one ROOMCONTRACT forward migrations (migrationCount = prior 113 + 5 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 = 151)', () => {
41
+ it('registers the four MBAUTHZ + four MBSENDAUTHZ + four MBSESSION + four MBDELEG + three MBFED + three MBHARDEN + two MBPORTALGATE + two MBPORTAL-PR32 + two ROOMOWN + two ROOMLINK + one ROOMDELEG + one LOCALAUTH + one ROOMUIAPI + one FEDSESSION + one FEDSESSION-AUTOJOIN + one GATENULL + one MEMBSTATE + one AGENTSDIR + one LEAVEIDEM + one ROLERESET + one MBROWID + one MBHYGIENE + one MBCONSENT-A + one MBCONSENT-B(a) + one MBCONSENT-B(i) + one MBCONSENT-B(ii) + one MBCONSENT-B(iii) + one MBHARDEN-#97 + one MBHARDEN-#118 + one INVITEPOLICY + one OBSGATE + one OBSGATE-2 + one OBSGATE-3 + one OBSGATE-4 + one FLEETMACHINERLS + one RESOLVENOOP + one ROOMDELEG-LANEB + one CLAIMKEY + two MINTHARDEN + one FLEETMACHINEHIJACK + one CLAIMGATE-SHADOW + one CLAIMGATE-ENFORCE + one FLEETMACHINEREACTIVATION + one DELEGCAPCEILING + one FLEETMACHINERECLAIM + one DELEGSOLEWRITER + one FLEETDOMAINRECLAIM + five ATOMICFLEETONBOARDING (onboarding + ceiling-lock + revocation-evidence + fedsession-gate + fedsession-lock-order) + one OUTBOXWAKE + one ENROLLLOCKORDER + one FEDPROVIDERABSENCE + one WAKERECOVERY + one CONSENTRECONCILE + one ENROLLRESUMPTION + one SIGNEDAUTHORITY + one SIGNERLIFECYCLE + one LEDGERAUTHORITY + one CEILINGLOCKCOMMENT + one LEDGERBOARDCREATE + one RECEIPTSUBJECTGATE + one TASKTHREADLOCKORDER + one CLAIMSUBJECTGATE + one FEDSESSIONIDENTITYGATE + one FEDIDENTITYSLUG + one INVITENODOWNGRADE + one SIGNEDWRITEFLAG + one SIGNEDWRITEMODEL + one RTCREDCLAIM + one ORIGINPOSTURE + one BOARDCLAIMPOLICY + one HEARTBEATPRESERVE + one LIVENESSDENOM + one OWNERLESSRENEWTTL + one OWNERLESSQUOTACENSUS + one FLEETDOMAINNODOWNGRADE + one OWNERLESSQUOTACONVERGE + one ADVISORYREVERTRESET + one CLAIMPOLICYRACE + one CLAIMPOLICYLOCKGRANT + one SESSIONCHALLENGESUPERSEDE + one ROOMCONTRACT + one CALLBACKCONSUMER + one ENROLLTOKENSINGLEUSE forward migrations (migrationCount = prior 113 + 5 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 = 153)', () => {
42
42
  expect(manifest.migrationCount).toBe(manifest.migrations.length);
43
- expect(manifest.migrationCount).toBe(151);
43
+ expect(manifest.migrationCount).toBe(153);
44
44
  // MBSESSION switched enforcement on (scoped-send re-grant): the client-visible
45
45
  // schema version bumped to 8. MBDELEG tightens delegation and MBFED adds only
46
46
  // enrollment-only additive surface (identity_providers registry, enrollment audit,
@@ -337,6 +337,9 @@ describe('manifest integrity', () => {
337
337
  '20261002000100_agent_board_session_challenge_supersede.sql',
338
338
  // ROOMCONTRACT: owner/admin active roster RPC plus self-membership role.
339
339
  '20261003000100_agent_board_room_roster.sql',
340
+ '20261004000100_agent_board_callback_consumer_intent.sql',
341
+ // ENROLLTOKENSINGLEUSE (#521): a verified Portal token binds to at most one key.
342
+ '20261005000100_agent_board_enroll_token_single_use.sql',
340
343
  ]) {
341
344
  expect(names.has(f)).toBe(true);
342
345
  }
@@ -156,7 +156,7 @@ select has_function(
156
156
  );
157
157
  select has_function(
158
158
  'agent_board', 'onboard_federated_fleet_agent',
159
- array['text','text','text','jsonb','text','text','text','text','boolean','text','text','text[]','text[]','text','uuid','uuid','text','text','text','text','text','text','text'],
159
+ array['text','text','text','jsonb','text','text','text','text','boolean','text','timestamp with time zone','text','text','text[]','text[]','text','uuid','uuid','text','text','text','text','text','text','text'],
160
160
  'atomic fleet onboarding RPC exists'
161
161
  );
162
162
  select has_function('agent_board', '_redeem_fleet_invite_for_agent', array['text','uuid'], 'fleet-only redemption helper exists');
@@ -168,7 +168,7 @@ select has_function(
168
168
  );
169
169
  select function_privs_are(
170
170
  'agent_board', 'onboard_federated_fleet_agent',
171
- array['text','text','text','jsonb','text','text','text','text','boolean','text','text','text[]','text[]','text','uuid','uuid','text','text','text','text','text','text','text'],
171
+ array['text','text','text','jsonb','text','text','text','text','boolean','text','timestamp with time zone','text','text','text[]','text[]','text','uuid','uuid','text','text','text','text','text','text','text'],
172
172
  'service_role', array['EXECUTE'],
173
173
  'only service_role can execute atomic onboarding'
174
174
  );
@@ -178,27 +178,27 @@ select function_privs_are(
178
178
  'fleet redemption helper is service-role-only'
179
179
  );
180
180
  select ok(
181
- agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
181
+ agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
182
182
  like '%fleet_onboarding.v1%',
183
183
  'atomic onboarding returns the frozen contract version'
184
184
  );
185
185
  select ok(
186
- agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
186
+ agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
187
187
  like '%for update%',
188
188
  'atomic onboarding catalog-pins row locking'
189
189
  );
190
190
  select ok(
191
- agent_board_test.stripped_body('agent_board.enroll_federated_identity(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text)'::regprocedure, true)
191
+ agent_board_test.stripped_body('agent_board.enroll_federated_identity(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text)'::regprocedure, true)
192
192
  like '%pg_advisory_xact_lock%',
193
193
  'exact-key create-or-reuse is serialized by fingerprint'
194
194
  );
195
195
  select ok(
196
- agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
196
+ agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
197
197
  like '%pg_advisory_xact_lock(hashtextextended(p_agent_public_key_fingerprint, 0))%',
198
198
  'composed onboarding serializes identity disposition by fingerprint'
199
199
  );
200
200
  select ok(
201
- agent_board_test.stripped_body('agent_board.enroll_federated_identity(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text)'::regprocedure, true)
201
+ agent_board_test.stripped_body('agent_board.enroll_federated_identity(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text)'::regprocedure, true)
202
202
  like '%fleet invite requires atomic fleet onboarding%',
203
203
  'legacy enrollment rejects bounded invites before writes'
204
204
  );
@@ -208,42 +208,42 @@ select ok(
208
208
  'generic ROOMLINK redemption rejects bounded invites'
209
209
  );
210
210
  select ok(
211
- agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
211
+ agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
212
212
  like '%phase_worker%worker%reviewer%reviewer%',
213
213
  'only bounded worker and reviewer role pairs are admitted'
214
214
  );
215
215
  select ok(
216
- agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
216
+ agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
217
217
  like '%signing_key_id is distinct from v_enroll.signing_key_id%',
218
218
  'binding replay pins the exact proven signing key'
219
219
  );
220
220
  select ok(
221
- agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
221
+ agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
222
222
  like '%v_inv.board_id is distinct from p_board_id%',
223
223
  'requested board is checked against the locked invite before writes'
224
224
  );
225
225
  select ok(
226
- agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
226
+ agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
227
227
  like '%not v_completed_replay%v_inv.expires_at <= now()%v_inv.uses_count >= v_inv.max_uses%',
228
228
  'only a complete active replay may bypass expiry and exhaustion'
229
229
  );
230
230
  select ok(
231
- agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
231
+ agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
232
232
  like '%v_inv.revoked_at is not null%a.status = ''active''%_grant_within_ceiling%',
233
233
  'revocation and current creator authority gate every fleet replay'
234
234
  );
235
235
  select ok(
236
- agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
236
+ agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
237
237
  like '%a.id = any(array[v_inv.created_by_agent_id, v_existing_agent_id])%order by a.id for update%bm.agent_id = v_inv.created_by_agent_id%order by bm.id for update%_grant_within_ceiling%',
238
238
  'creator and enrolled principals lock in UUID order before creator authority'
239
239
  );
240
240
  select ok(
241
- agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
241
+ agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
242
242
  like '%board_invite_redemptions red%order by red.id for update%bm.agent_id = v_enroll.agent_id%order by bm.id for update%select exists%',
243
243
  'complete-replay proof locks redemption and membership first'
244
244
  );
245
245
  select ok(
246
- agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
246
+ agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
247
247
  like '%perform 1 from agent_board.fleet_harness_registrations%perform 1 from agent_board.fleet_repo_scopes%perform 1 from agent_board.fleet_machine_agents%',
248
248
  'every matching harness, repo, and binding history row is locked before reuse'
249
249
  );
@@ -263,12 +263,12 @@ select ok(
263
263
  'exact binding revocation locks the machine before the binding [SOLE PIN: no isolation spec discriminates this ordering -- measured against all 20]'
264
264
  );
265
265
  select ok(
266
- strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'where fm.id = p_machine_id for update'
266
+ strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'where fm.id = p_machine_id for update'
267
267
  ) > 0
268
- and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.agents a where a.id = v_enroll.agent_id for update'
268
+ and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.agents a where a.id = v_enroll.agent_id for update'
269
269
  ) > 0
270
- and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'where fm.id = p_machine_id for update'
271
- ) < strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.agents a where a.id = v_enroll.agent_id for update'
270
+ and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'where fm.id = p_machine_id for update'
271
+ ) < strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.agents a where a.id = v_enroll.agent_id for update'
272
272
  ),
273
273
  'atomic onboarding locks the machine before its enrolled agent [CONFIRMATORY: atomic_fleet_binding_revoke.spec and atomic_fleet_lifecycle_races.spec both discriminate the inversion]'
274
274
  );
@@ -368,12 +368,12 @@ select ok(
368
368
  'bounded invite mint locks and requires an active board'
369
369
  );
370
370
  select ok(
371
- agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
371
+ agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure, true)
372
372
  like '%from agent_board.boards b%where b.id = v_inv.board_id%for update%v_board.status <> ''active''%',
373
373
  'atomic onboarding locks and requires the invite board to remain active'
374
374
  );
375
375
  select ok(
376
- agent_board_test.stripped_body('agent_board.enroll_federated_identity(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text)'::regprocedure, true)
376
+ agent_board_test.stripped_body('agent_board.enroll_federated_identity(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text)'::regprocedure, true)
377
377
  like '%from auth.users u where u.id = v_owner_user_id for update%fleet_human_revocations%r.issuer = p_issuer and r.subject = p_subject%',
378
378
  'identity enrollment locks the human owner and rejects durable total revocation'
379
379
  );
@@ -404,7 +404,7 @@ select ok(
404
404
  select ok(
405
405
  not has_function_privilege(
406
406
  'authenticated',
407
- 'agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure,
407
+ 'agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure,
408
408
  'EXECUTE'
409
409
  ),
410
410
  'authenticated CANNOT execute atomic onboarding'
@@ -412,7 +412,7 @@ select ok(
412
412
  select ok(
413
413
  not has_function_privilege(
414
414
  'anon',
415
- 'agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure,
415
+ 'agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure,
416
416
  'EXECUTE'
417
417
  ),
418
418
  'anon CANNOT execute atomic onboarding'
@@ -439,10 +439,10 @@ select ok(
439
439
  -- Ordering, not mere presence: the lock has to be held BEFORE the authorization
440
440
  -- decision reads the (possibly absent) ceiling, and BEFORE the writer upserts it.
441
441
  select ok(
442
- strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
442
+ strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
443
443
  ) > 0
444
- and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
445
- ) < strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'agent_board._grant_within_ceiling('
444
+ and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
445
+ ) < strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'agent_board._grant_within_ceiling('
446
446
  ),
447
447
  'atomic onboarding holds the board ceiling lock before evaluating creator authority [REDUNDANT: implied by the advisory-before-boards and boards-before-ceiling-read claims below; an advisory moved between those two points violates the real ordering and still passes THIS one]'
448
448
  );
@@ -454,10 +454,10 @@ select ok(
454
454
  -- that catches the inversion; it is deliberately separate from the "before the
455
455
  -- ceiling read" assertion below, because that one passes in BOTH orders.
456
456
  select ok(
457
- strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
457
+ strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
458
458
  ) > 0
459
- and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
460
- ) < strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.boards b
459
+ and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'perform agent_board._lock_board_authority_ceiling(v_inv.board_id)'
460
+ ) < strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.boards b
461
461
  where b.id = v_inv.board_id
462
462
  for update'
463
463
  ),
@@ -477,14 +477,14 @@ select ok(
477
477
  -- ordering nothing else states, because the boards lock is taken for board liveness,
478
478
  -- not for the ceiling. Pin the ordering so a refactor that moves it is not silent.
479
479
  select ok(
480
- strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.boards b
480
+ strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.boards b
481
481
  where b.id = v_inv.board_id
482
482
  for update'
483
483
  ) > 0
484
- and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.boards b
484
+ and strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'from agent_board.boards b
485
485
  where b.id = v_inv.board_id
486
486
  for update'
487
- ) < strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'agent_board._grant_within_ceiling('
487
+ ) < strpos(lower(agent_board_test.stripped_body('agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text)'::regprocedure)), 'agent_board._grant_within_ceiling('
488
488
  ),
489
489
  'atomic onboarding holds the boards row FOR UPDATE before it reads the ceiling [CONFIRMATORY FOR FLAT MASKS ONLY: agent_board_federated_lock_order_class.test.sql EC-3 fails by name on the comment/literal mutants, but it carries the SAME strip, so a NESTED block comment takes this assertion and EC-3 green together -- see #199 in the header; atomic_fleet_authority_races.spec pins the OUTCOME only when this lock and the advisory are BOTH gone, and atomic_fleet_board_archive.spec BLOCKS rather than failing by name]'
490
490
  );
@@ -553,7 +553,7 @@ select is( -- pgtap-allow-raise-checked: catalog read only; the RPC names below
553
553
  -- lock also closes this reader's exposure to the ceiling row's ABSENCE, one of the three
554
554
  -- 20260901000110 left explicitly undetermined.
555
555
  'agent_board.grant_board_role(uuid,uuid,text,uuid) => serialized',
556
- 'agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text) => serialized'
556
+ 'agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text) => serialized'
557
557
  ]::text[],
558
558
  'every ceiling-authorization reader in pg_proc is declared with its serialization state'
559
559
  );
@@ -698,14 +698,14 @@ select is( -- pgtap-allow-raise-checked: catalog read only; the RPC names below
698
698
  'agent_board._revoke_agent_principal(uuid,uuid,text) [definer] => service_role',
699
699
  'agent_board.create_fleet_onboarding_invite(uuid,uuid,text,text,text,text,text,text,text,integer,timestamp with time zone,uuid,jsonb) [definer] => authenticated,service_role',
700
700
  'agent_board.enroll_federated_human(text,text,text,jsonb,text) [definer] => service_role',
701
- 'agent_board.enroll_federated_identity(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text) [definer] => service_role',
701
+ 'agent_board.enroll_federated_identity(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text) [definer] => service_role',
702
702
  'agent_board.evaluate_fleet_sender_policy(uuid,uuid,uuid,uuid,text,uuid,boolean) [definer] => authenticated,service_role',
703
703
  -- Joined this class in #276: the live grant chokepoint now takes _lock_board_authority_ceiling
704
704
  -- (forced by the section-9 agents/board_memberships class in agent_board_signer_lifecycle.test.sql
705
705
  -- once the ledger gate made it lock both). Still authenticated,service_role — #276 removes
706
706
  -- authority from a revoked principal, it does not change who may call the RPC.
707
707
  'agent_board.grant_board_role(uuid,uuid,text,uuid) [definer] => authenticated,service_role',
708
- 'agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text) [definer] => service_role',
708
+ 'agent_board.onboard_federated_fleet_agent(text,text,text,jsonb,text,text,text,text,boolean,text,timestamp with time zone,text,text,text[],text[],text,uuid,uuid,text,text,text,text,text,text,text) [definer] => service_role',
709
709
  'agent_board.reactivate_fleet_machine(uuid,uuid,text) [definer] => service_role',
710
710
  'agent_board.revoke_fleet_subject(text,uuid,uuid,text,jsonb) [definer] => authenticated,service_role',
711
711
  'agent_board.revoke_human_subtree(uuid,uuid,text) [definer] => service_role',
@@ -83,7 +83,7 @@ select * from agent_board.enroll_federated_identity(
83
83
  'TauOMxwU-TW-deqQjil1DLDy_AvJrfoG_eXGwwvaRUk',
84
84
  'raw_ed25519_base64url',
85
85
  'sha256:QnDuPiA99wAIcCJlk4ZS_ZJV4gQPW8cX0LVmKQJNl0I',
86
- true, null, 'agent', ARRAY['board:read','board:send'], ARRAY[]::text[], null
86
+ true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1), null, 'agent', ARRAY['board:read','board:send'], ARRAY[]::text[], null
87
87
  );
88
88
  select is((select agent_id from _legacy_replay),
89
89
  '16200000-0000-0000-0000-000000000001'::uuid,
@@ -107,7 +107,7 @@ select throws_ok(
107
107
  '{"iss":"https://legacy.atomic.test","aud":["message-board","new-audience"],"uid":"legacy-complete"}'::jsonb,
108
108
  'atomic-backfill-complete','TauOMxwU-TW-deqQjil1DLDy_AvJrfoG_eXGwwvaRUk',
109
109
  'raw_ed25519_base64url','sha256:QnDuPiA99wAIcCJlk4ZS_ZJV4gQPW8cX0LVmKQJNl0I',
110
- true,null,'agent',ARRAY['board:read','board:send'],ARRAY[]::text[],null)$$,
110
+ true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1),null,'agent',ARRAY['board:read','board:send'],ARRAY[]::text[],null)$$,
111
111
  '23505', null, 'changed normalized audience projection conflicts'
112
112
  );
113
113
  select throws_ok(
@@ -116,7 +116,7 @@ select throws_ok(
116
116
  '{"iss":"https://legacy.atomic.test","aud":["message-board","secondary-audience"],"uid":"changed-subject"}'::jsonb,
117
117
  'atomic-backfill-complete','TauOMxwU-TW-deqQjil1DLDy_AvJrfoG_eXGwwvaRUk',
118
118
  'raw_ed25519_base64url','sha256:QnDuPiA99wAIcCJlk4ZS_ZJV4gQPW8cX0LVmKQJNl0I',
119
- true,null,'agent',ARRAY['board:read','board:send'],ARRAY[]::text[],null)$$,
119
+ true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1),null,'agent',ARRAY['board:read','board:send'],ARRAY[]::text[],null)$$,
120
120
  '23505', null, 'changed stable subject conflicts'
121
121
  );
122
122
  select throws_ok(
@@ -125,7 +125,7 @@ select throws_ok(
125
125
  '{"iss":"https://legacy.atomic.test","aud":["message-board","secondary-audience"],"uid":"legacy-complete"}'::jsonb,
126
126
  'changed-slug','TauOMxwU-TW-deqQjil1DLDy_AvJrfoG_eXGwwvaRUk',
127
127
  'raw_ed25519_base64url','sha256:QnDuPiA99wAIcCJlk4ZS_ZJV4gQPW8cX0LVmKQJNl0I',
128
- true,null,'agent',ARRAY['board:read','board:send'],ARRAY[]::text[],null)$$,
128
+ true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1),null,'agent',ARRAY['board:read','board:send'],ARRAY[]::text[],null)$$,
129
129
  '23505', null, 'changed requested slug conflicts'
130
130
  );
131
131
  select throws_ok(
@@ -134,7 +134,7 @@ select throws_ok(
134
134
  '{"iss":"https://legacy.atomic.test","aud":["message-board","secondary-audience"],"uid":"legacy-complete"}'::jsonb,
135
135
  'atomic-backfill-complete','TauOMxwU-TW-deqQjil1DLDy_AvJrfoG_eXGwwvaRUk',
136
136
  'raw_ed25519_base64url','sha256:QnDuPiA99wAIcCJlk4ZS_ZJV4gQPW8cX0LVmKQJNl0I',
137
- true,'new-actor','agent',ARRAY['board:read','board:send'],ARRAY[]::text[],null)$$,
137
+ true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1),'new-actor','agent',ARRAY['board:read','board:send'],ARRAY[]::text[],null)$$,
138
138
  '23505', null, 'changed independent actor subject conflicts'
139
139
  );
140
140