@consiliency/agent-board-schema 1.54.0 → 1.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fixtures/already-applied.json +8 -0
- package/migrations/20261005000100_agent_board_enroll_token_single_use.sql +886 -0
- package/migrations/20261006000100_agent_board_room_roster_active_first.sql +118 -0
- package/package.json +1 -1
- package/schema-manifest.json +21 -3
- package/src/tooling.test.mjs +7 -2
- package/tests/agent_board_atomic_fleet_onboarding.test.sql +35 -35
- package/tests/agent_board_atomic_fleet_onboarding_backfill.test.sql +5 -5
- package/tests/agent_board_atomic_fleet_onboarding_runtime.test.sql +32 -32
- package/tests/agent_board_enroll_federated_identity.test.sql +11 -10
- package/tests/agent_board_enroll_pop_binding.test.sql +12 -12
- package/tests/agent_board_enroll_resumption.test.sql +1 -1
- package/tests/agent_board_enroll_token_single_use.test.sql +538 -0
- package/tests/agent_board_enrollment_audit_content.test.sql +3 -3
- package/tests/agent_board_federated_lock_order_class.test.sql +5 -5
- package/tests/agent_board_fedsession.test.sql +1 -1
- package/tests/agent_board_fk_lock_edges.test.sql +23 -0
- package/tests/agent_board_identity_providers.test.sql +3 -2
- package/tests/agent_board_membership_current_row_class.test.sql +460 -0
- package/tests/agent_board_portal_offline_invariant.test.sql +1 -1
- package/tests/agent_board_room_roster.test.sql +262 -24
- package/tests/agent_board_roomlink.test.sql +2 -2
- package/tests/agent_board_rowid.test.sql +15 -2
- package/tests/agent_board_write_enforcement_class.test.sql +5 -2
- package/tests/catalog/function_execute_privileges.json +12 -3
- package/tests/catalog/p_metadata_parameters.json +6 -2
- package/tests/isolation/expected/atomic_fedsession_fleet_lock_order.out +1 -1
- package/tests/isolation/expected/atomic_fleet_authority_races.out +8 -8
- package/tests/isolation/expected/atomic_fleet_binding_revoke.out +2 -2
- package/tests/isolation/expected/atomic_fleet_board_archive.out +2 -2
- package/tests/isolation/expected/atomic_fleet_human_fresh_revoke.out +2 -2
- package/tests/isolation/expected/atomic_fleet_identity_disposition.out +2 -2
- package/tests/isolation/expected/atomic_fleet_lifecycle_races.out +22 -22
- package/tests/isolation/expected/atomic_fleet_onboarding.out +2 -2
- package/tests/isolation/expected/atomic_fleet_subtree_lock_order.out +1 -1
- package/tests/isolation/expected/enroll_identity_board_owner_lock_order.out +1 -1
- package/tests/isolation/expected/enroll_token_fleet_abort.out +81 -0
- package/tests/isolation/expected/enroll_token_pk_backstop.out +36 -0
- package/tests/isolation/expected/enroll_token_placement.out +86 -0
- package/tests/isolation/expected/enroll_token_rollback_unstrands.out +59 -0
- package/tests/isolation/expected/enroll_token_route_race_fleet_first.out +72 -0
- package/tests/isolation/expected/enroll_token_route_race_identity_first.out +72 -0
- package/tests/isolation/expected/enroll_token_same_key_fleet_then_identity.out +73 -0
- package/tests/isolation/expected/enroll_token_same_key_identity_then_fleet.out +73 -0
- package/tests/isolation/expected/enroll_token_same_key_resume.out +59 -0
- package/tests/isolation/expected/enroll_token_same_token_race.out +58 -0
- package/tests/isolation/expected/onboarding_ceiling_lock_order.out +2 -2
- package/tests/isolation/specs/atomic_fedsession_fleet_lock_order.spec +1 -1
- package/tests/isolation/specs/atomic_fleet_authority_races.spec +2 -2
- package/tests/isolation/specs/atomic_fleet_binding_revoke.spec +2 -2
- package/tests/isolation/specs/atomic_fleet_board_archive.spec +2 -2
- package/tests/isolation/specs/atomic_fleet_human_fresh_revoke.spec +2 -2
- package/tests/isolation/specs/atomic_fleet_identity_disposition.spec +2 -2
- package/tests/isolation/specs/atomic_fleet_lifecycle_races.spec +2 -2
- package/tests/isolation/specs/atomic_fleet_onboarding.spec +2 -2
- package/tests/isolation/specs/atomic_fleet_subtree_lock_order.spec +2 -2
- package/tests/isolation/specs/enroll_identity_board_owner_lock_order.spec +1 -1
- package/tests/isolation/specs/enroll_token_fleet_abort.spec +138 -0
- package/tests/isolation/specs/enroll_token_pk_backstop.spec +37 -0
- package/tests/isolation/specs/enroll_token_placement.spec +136 -0
- package/tests/isolation/specs/enroll_token_rollback_unstrands.spec +71 -0
- package/tests/isolation/specs/enroll_token_route_race_fleet_first.spec +119 -0
- package/tests/isolation/specs/enroll_token_route_race_identity_first.spec +120 -0
- package/tests/isolation/specs/enroll_token_same_key_fleet_then_identity.spec +112 -0
- package/tests/isolation/specs/enroll_token_same_key_identity_then_fleet.spec +113 -0
- package/tests/isolation/specs/enroll_token_same_key_resume.spec +70 -0
- package/tests/isolation/specs/enroll_token_same_token_race.spec +80 -0
- package/tests/isolation/specs/onboarding_ceiling_lock_order.spec +1 -1
|
@@ -2,19 +2,49 @@
|
|
|
2
2
|
--
|
|
3
3
|
-- Mutation controls (the assertion names are part of the evidence contract):
|
|
4
4
|
-- * removing the owner/admin gate fails RC-32 (member denial);
|
|
5
|
-
-- * filtering active state before latest-row selection fails RC-38 (stale row);
|
|
6
|
-
-- * removing the id DESC tiebreak fails RC-39 (equal timestamp);
|
|
7
5
|
-- * omitting role from v_board_memberships fails RC-12 (catalog ordinal);
|
|
8
|
-
-- * removing the roster board predicate fails RC-37 (cross-board isolation)
|
|
6
|
+
-- * removing the roster board predicate fails RC-37 (cross-board isolation);
|
|
7
|
+
-- * dropping the MBROWID 3a active-first key from the AUTHORIZATION site fails
|
|
8
|
+
-- RC-45/RC-47/RC-49 (an active owner/admin with a newer removed/left/requested
|
|
9
|
+
-- row is refused), message-board#542 -- and, since those callers then capture
|
|
10
|
+
-- nothing, every board-C state check after them;
|
|
11
|
+
-- * dropping it from the PROJECTION site fails RC-38/RC-39 and RC-46/RC-48/
|
|
12
|
+
-- RC-50/RC-51 (that member is omitted) while RC-45/RC-47/RC-49 still pass;
|
|
13
|
+
-- * splitting authorization into "has an active row" AND "has an owner/admin
|
|
14
|
+
-- row in any state" fails RC-55/RC-56 (a member/observer with a newer
|
|
15
|
+
-- non-active owner/admin row is admitted);
|
|
16
|
+
-- * dropping the projection's active-state filter fails RC-25/RC-28/RC-51/RC-52
|
|
17
|
+
-- (non-active agents listed); dropping the authorization's active-state check
|
|
18
|
+
-- fails RC-53 (an owner with no active row admitted).
|
|
9
19
|
--
|
|
10
|
-
--
|
|
20
|
+
-- CURRENT STANDING IS ACTIVE-FIRST (message-board#542, migration 20261006000100).
|
|
21
|
+
-- Each agent's current row is chosen `case when membership_state in
|
|
22
|
+
-- ('joined','subscribed') then 0 else 1 end, created_at desc, id desc`, as every
|
|
23
|
+
-- other acting membership reader does (MBROWID 3a). The partial active unique
|
|
24
|
+
-- index allows at most ONE active row per (board, agent), so the result is "the
|
|
25
|
+
-- agent's active row, if any". Two consequences for this file:
|
|
26
|
+
-- * RC-38/RC-39 used to assert that a newer left/removed row HID an older
|
|
27
|
+
-- joined row. That was the #542 defect written down as a requirement; they
|
|
28
|
+
-- now assert the opposite, on board C.
|
|
29
|
+
-- * the id DESC tiebreak is no longer observable through this function: with
|
|
30
|
+
-- at most one active row it only orders non-active rows, which are never
|
|
31
|
+
-- listed and never authorize. It is pinned structurally by assertion 99 of
|
|
32
|
+
-- agent_board_rowid.test.sql (both list_board_members sites carry
|
|
33
|
+
-- `created_at desc, id desc`); the key itself is a class property in
|
|
34
|
+
-- agent_board_membership_current_row_class.test.sql.
|
|
35
|
+
--
|
|
36
|
+
-- EMISSION ORDER differs from label order: in the #542 section the captures
|
|
37
|
+
-- RC-45/47/49 run first, then RC-46/48/50/51, RC-38, RC-39, RC-52, RC-57,
|
|
38
|
+
-- RC-55, RC-56, RC-53, RC-54. Cite assertions by LABEL, not by TAP number.
|
|
39
|
+
--
|
|
40
|
+
-- HAND-COUNTED plan: RC-01..RC-57 = 57 assertions. The runner independently
|
|
11
41
|
-- verifies the plan and emitted assertion counts, so a truncated file cannot pass.
|
|
12
42
|
create extension if not exists pgtap with schema extensions;
|
|
13
43
|
set search_path = extensions, public, agent_board;
|
|
14
44
|
|
|
15
45
|
begin;
|
|
16
46
|
|
|
17
|
-
select plan(
|
|
47
|
+
select plan(57);
|
|
18
48
|
|
|
19
49
|
-- ---------------------------------------------------------------------------
|
|
20
50
|
-- Catalog contract: exact signature, projection, posture, privileges, and view.
|
|
@@ -158,6 +188,20 @@ create temp table _roomcontract_fixture (
|
|
|
158
188
|
stale_agent uuid,
|
|
159
189
|
tie_agent uuid,
|
|
160
190
|
board_b_agent uuid,
|
|
191
|
+
board_c uuid,
|
|
192
|
+
c_owner_removed uuid,
|
|
193
|
+
c_admin_left uuid,
|
|
194
|
+
c_owner_requested uuid,
|
|
195
|
+
c_inactive_only uuid,
|
|
196
|
+
c_removed_owner uuid,
|
|
197
|
+
c_member_was_owner uuid,
|
|
198
|
+
c_observer_was_admin uuid,
|
|
199
|
+
c_member_was_owner_user uuid,
|
|
200
|
+
c_observer_was_admin_user uuid,
|
|
201
|
+
c_owner_removed_user uuid,
|
|
202
|
+
c_admin_left_user uuid,
|
|
203
|
+
c_owner_requested_user uuid,
|
|
204
|
+
c_removed_owner_user uuid,
|
|
161
205
|
creator_user uuid,
|
|
162
206
|
owner_user uuid,
|
|
163
207
|
admin_user uuid,
|
|
@@ -177,6 +221,12 @@ declare
|
|
|
177
221
|
v_observer_user uuid;
|
|
178
222
|
v_nonmember_user uuid;
|
|
179
223
|
v_suspended_user uuid;
|
|
224
|
+
v_c_owner_removed_user uuid;
|
|
225
|
+
v_c_admin_left_user uuid;
|
|
226
|
+
v_c_owner_requested_user uuid;
|
|
227
|
+
v_c_removed_owner_user uuid;
|
|
228
|
+
v_c_member_was_owner_user uuid;
|
|
229
|
+
v_c_observer_was_admin_user uuid;
|
|
180
230
|
begin
|
|
181
231
|
v_creator_user := public.ensure_github_user('rc-creator', 'rc-creator@example.test', 'rc-creator', 'RC Creator');
|
|
182
232
|
v_owner_user := public.ensure_github_user('rc-owner', 'rc-owner@example.test', 'rc-owner', 'RC Owner');
|
|
@@ -185,6 +235,12 @@ begin
|
|
|
185
235
|
v_observer_user := public.ensure_github_user('rc-observer', 'rc-observer@example.test', 'rc-observer', 'RC Observer');
|
|
186
236
|
v_nonmember_user := public.ensure_github_user('rc-nonmember', 'rc-nonmember@example.test', 'rc-nonmember', 'RC Nonmember');
|
|
187
237
|
v_suspended_user := public.ensure_github_user('rc-suspended', 'rc-suspended@example.test', 'rc-suspended', 'RC Suspended');
|
|
238
|
+
v_c_owner_removed_user := public.ensure_github_user('rc-c-owner-removed', 'rc-c-owner-removed@example.test', 'rc-c-owner-removed', 'RC C Owner Removed');
|
|
239
|
+
v_c_admin_left_user := public.ensure_github_user('rc-c-admin-left', 'rc-c-admin-left@example.test', 'rc-c-admin-left', 'RC C Admin Left');
|
|
240
|
+
v_c_owner_requested_user := public.ensure_github_user('rc-c-owner-requested', 'rc-c-owner-requested@example.test', 'rc-c-owner-requested', 'RC C Owner Requested');
|
|
241
|
+
v_c_removed_owner_user := public.ensure_github_user('rc-c-removed-owner', 'rc-c-removed-owner@example.test', 'rc-c-removed-owner', 'RC C Removed Owner');
|
|
242
|
+
v_c_member_was_owner_user := public.ensure_github_user('rc-c-member-was-owner', 'rc-c-member-was-owner@example.test', 'rc-c-member-was-owner', 'RC C Member Was Owner');
|
|
243
|
+
v_c_observer_was_admin_user := public.ensure_github_user('rc-c-observer-was-admin', 'rc-c-observer-was-admin@example.test', 'rc-c-observer-was-admin', 'RC C Observer Was Admin');
|
|
188
244
|
|
|
189
245
|
insert into agent_board.agents(
|
|
190
246
|
id, agent_type, handle, display_name, status, auth_user_id, owner_user_id
|
|
@@ -201,12 +257,20 @@ begin
|
|
|
201
257
|
('73000000-0000-4000-8000-00000000000a', 'agent', 'rc-suspended', 'RC Suspended', 'suspended', v_suspended_user, v_suspended_user),
|
|
202
258
|
('73000000-0000-4000-8000-00000000000b', 'agent', 'rc-stale', 'RC Stale', 'active', null, null),
|
|
203
259
|
('73000000-0000-4000-8000-00000000000c', 'agent', 'rc-tie', 'RC Tie', 'active', null, null),
|
|
204
|
-
('73000000-0000-4000-8000-00000000000d', 'agent', 'rc-board-b', 'RC Board B', 'active', null, null)
|
|
260
|
+
('73000000-0000-4000-8000-00000000000d', 'agent', 'rc-board-b', 'RC Board B', 'active', null, null),
|
|
261
|
+
('73000000-0000-4000-8000-00000000000e', 'human', 'rc-c-owner-removed', 'RC C Owner Removed', 'active', v_c_owner_removed_user, v_c_owner_removed_user),
|
|
262
|
+
('73000000-0000-4000-8000-00000000000f', 'human', 'rc-c-admin-left', 'RC C Admin Left', 'active', v_c_admin_left_user, v_c_admin_left_user),
|
|
263
|
+
('73000000-0000-4000-8000-000000000010', 'human', 'rc-c-owner-requested', 'RC C Owner Requested', 'active', v_c_owner_requested_user, v_c_owner_requested_user),
|
|
264
|
+
('73000000-0000-4000-8000-000000000011', 'agent', 'rc-c-inactive-only', 'RC C Inactive Only', 'active', null, null),
|
|
265
|
+
('73000000-0000-4000-8000-000000000012', 'human', 'rc-c-removed-owner', 'RC C Removed Owner', 'active', v_c_removed_owner_user, v_c_removed_owner_user),
|
|
266
|
+
('73000000-0000-4000-8000-000000000013', 'human', 'rc-c-member-was-owner', 'RC C Member Was Owner', 'active', v_c_member_was_owner_user, v_c_member_was_owner_user),
|
|
267
|
+
('73000000-0000-4000-8000-000000000014', 'human', 'rc-c-observer-was-admin', 'RC C Observer Was Admin', 'active', v_c_observer_was_admin_user, v_c_observer_was_admin_user);
|
|
205
268
|
|
|
206
269
|
insert into agent_board.boards(id, slug, name, created_by_agent_id, status)
|
|
207
270
|
values
|
|
208
271
|
('73010000-0000-4000-8000-000000000001', 'roomcontract-a', 'ROOMCONTRACT A', '73000000-0000-4000-8000-000000000001', 'active'),
|
|
209
|
-
('73010000-0000-4000-8000-000000000002', 'roomcontract-b', 'ROOMCONTRACT B', '73000000-0000-4000-8000-000000000001', 'active')
|
|
272
|
+
('73010000-0000-4000-8000-000000000002', 'roomcontract-b', 'ROOMCONTRACT B', '73000000-0000-4000-8000-000000000001', 'active'),
|
|
273
|
+
('73010000-0000-4000-8000-000000000003', 'roomcontract-c', 'ROOMCONTRACT C', '73000000-0000-4000-8000-000000000001', 'active');
|
|
210
274
|
|
|
211
275
|
-- Board A current active roster: owner, admin, four members, observer.
|
|
212
276
|
insert into agent_board.board_memberships(board_id, agent_id, membership_state, role, created_by_agent_id)
|
|
@@ -219,26 +283,59 @@ begin
|
|
|
219
283
|
('73010000-0000-4000-8000-000000000001', '73000000-0000-4000-8000-000000000007', 'joined', 'member', '73000000-0000-4000-8000-000000000002'),
|
|
220
284
|
('73010000-0000-4000-8000-000000000001', '73000000-0000-4000-8000-000000000008', 'joined', 'observer', '73000000-0000-4000-8000-000000000002');
|
|
221
285
|
|
|
222
|
-
-- The board creator
|
|
286
|
+
-- The board creator once held owner standing and has NO active row now: a
|
|
287
|
+
-- removed owner row and a newer left row. Creator identity is not authority.
|
|
223
288
|
insert into agent_board.board_memberships(
|
|
224
289
|
id, board_id, agent_id, membership_state, role, created_by_agent_id, left_at, created_at, updated_at
|
|
225
290
|
) values
|
|
226
|
-
('73020000-0000-4000-8000-000000000001', '73010000-0000-4000-8000-000000000001', '73000000-0000-4000-8000-000000000001', '
|
|
291
|
+
('73020000-0000-4000-8000-000000000001', '73010000-0000-4000-8000-000000000001', '73000000-0000-4000-8000-000000000001', 'removed', 'owner', '73000000-0000-4000-8000-000000000001', '2026-09-01 00:00:00+00', '2026-09-01 00:00:00+00', '2026-09-01 00:00:00+00'),
|
|
227
292
|
('73020000-0000-4000-8000-000000000002', '73010000-0000-4000-8000-000000000001', '73000000-0000-4000-8000-000000000001', 'left', 'member', '73000000-0000-4000-8000-000000000001', '2026-09-02 00:00:00+00', '2026-09-02 00:00:00+00', '2026-09-02 00:00:00+00');
|
|
228
293
|
|
|
229
|
-
--
|
|
294
|
+
-- Board C (message-board#542): an active row coexisting with NEWER non-active
|
|
295
|
+
-- rows. The partial active unique index admits every pair below.
|
|
296
|
+
--
|
|
297
|
+
-- Stale-row control: an older joined row next to a newer left row is CURRENT.
|
|
230
298
|
insert into agent_board.board_memberships(
|
|
231
299
|
id, board_id, agent_id, membership_state, role, created_by_agent_id, left_at, created_at, updated_at
|
|
232
300
|
) values
|
|
233
|
-
('73020000-0000-4000-8000-000000000003', '73010000-0000-4000-8000-
|
|
234
|
-
('73020000-0000-4000-8000-000000000004', '73010000-0000-4000-8000-
|
|
301
|
+
('73020000-0000-4000-8000-000000000003', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-00000000000b', 'joined', 'member', '73000000-0000-4000-8000-000000000002', null, '2026-09-03 00:00:00+00', '2026-09-03 00:00:00+00'),
|
|
302
|
+
('73020000-0000-4000-8000-000000000004', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-00000000000b', 'left', 'member', '73000000-0000-4000-8000-000000000002', '2026-09-04 00:00:00+00', '2026-09-04 00:00:00+00', '2026-09-04 00:00:00+00');
|
|
235
303
|
|
|
236
|
-
--
|
|
304
|
+
-- Equal-timestamp control: the removed row has the LARGER id, so a bare
|
|
305
|
+
-- `created_at desc, id desc` would pick it; active-first picks the joined row.
|
|
237
306
|
insert into agent_board.board_memberships(
|
|
238
307
|
id, board_id, agent_id, membership_state, role, created_by_agent_id, left_at, created_at, updated_at
|
|
239
308
|
) values
|
|
240
|
-
('73020000-0000-4000-8000-000000000010', '73010000-0000-4000-8000-
|
|
241
|
-
('73020000-0000-4000-8000-000000000011', '73010000-0000-4000-8000-
|
|
309
|
+
('73020000-0000-4000-8000-000000000010', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-00000000000c', 'joined', 'member', '73000000-0000-4000-8000-000000000002', null, '2026-09-05 00:00:00+00', '2026-09-05 00:00:00+00'),
|
|
310
|
+
('73020000-0000-4000-8000-000000000011', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-00000000000c', 'removed', 'member', '73000000-0000-4000-8000-000000000002', '2026-09-05 00:00:00+00', '2026-09-05 00:00:00+00', '2026-09-05 00:00:00+00');
|
|
311
|
+
|
|
312
|
+
-- The three callers #542 names: an active owner with a newer REMOVED row, an
|
|
313
|
+
-- active admin with a newer LEFT row, an active owner with a newer REQUESTED row.
|
|
314
|
+
-- Then an agent whose ONLY rows are non-active, and an owner with no active row.
|
|
315
|
+
insert into agent_board.board_memberships(
|
|
316
|
+
id, board_id, agent_id, membership_state, role, created_by_agent_id, left_at, created_at, updated_at
|
|
317
|
+
) values
|
|
318
|
+
('73020000-0000-4000-8000-000000000020', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-00000000000e', 'joined', 'owner', '73000000-0000-4000-8000-000000000001', null, '2026-09-10 00:00:00+00', '2026-09-10 00:00:00+00'),
|
|
319
|
+
('73020000-0000-4000-8000-000000000021', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-00000000000e', 'removed', 'owner', '73000000-0000-4000-8000-000000000001', '2026-09-11 00:00:00+00', '2026-09-11 00:00:00+00', '2026-09-11 00:00:00+00'),
|
|
320
|
+
('73020000-0000-4000-8000-000000000022', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-00000000000f', 'subscribed', 'admin', '73000000-0000-4000-8000-000000000001', null, '2026-09-10 00:00:00+00', '2026-09-10 00:00:00+00'),
|
|
321
|
+
('73020000-0000-4000-8000-000000000023', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-00000000000f', 'left', 'admin', '73000000-0000-4000-8000-000000000001', '2026-09-12 00:00:00+00', '2026-09-12 00:00:00+00', '2026-09-12 00:00:00+00'),
|
|
322
|
+
('73020000-0000-4000-8000-000000000024', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-000000000010', 'joined', 'owner', '73000000-0000-4000-8000-000000000001', null, '2026-09-10 00:00:00+00', '2026-09-10 00:00:00+00'),
|
|
323
|
+
('73020000-0000-4000-8000-000000000025', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-000000000010', 'requested', 'member', '73000000-0000-4000-8000-000000000001', null, '2026-09-13 00:00:00+00', '2026-09-13 00:00:00+00'),
|
|
324
|
+
('73020000-0000-4000-8000-000000000026', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-000000000011', 'left', 'member', '73000000-0000-4000-8000-000000000001', '2026-09-10 00:00:00+00', '2026-09-10 00:00:00+00', '2026-09-10 00:00:00+00'),
|
|
325
|
+
('73020000-0000-4000-8000-000000000027', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-000000000011', 'removed', 'member', '73000000-0000-4000-8000-000000000001', '2026-09-11 00:00:00+00', '2026-09-11 00:00:00+00', '2026-09-11 00:00:00+00'),
|
|
326
|
+
('73020000-0000-4000-8000-000000000028', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-000000000012', 'left', 'owner', '73000000-0000-4000-8000-000000000001', '2026-09-10 00:00:00+00', '2026-09-10 00:00:00+00', '2026-09-10 00:00:00+00'),
|
|
327
|
+
('73020000-0000-4000-8000-000000000029', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-000000000012', 'removed', 'owner', '73000000-0000-4000-8000-000000000001', '2026-09-11 00:00:00+00', '2026-09-11 00:00:00+00', '2026-09-11 00:00:00+00');
|
|
328
|
+
|
|
329
|
+
-- The NARROWING direction (round-1 review): an ACTIVE member/observer row
|
|
330
|
+
-- next to a NEWER non-active OWNER/ADMIN row. Standing comes from the active
|
|
331
|
+
-- row, so the historical owner/admin role confers nothing.
|
|
332
|
+
insert into agent_board.board_memberships(
|
|
333
|
+
id, board_id, agent_id, membership_state, role, created_by_agent_id, left_at, created_at, updated_at
|
|
334
|
+
) values
|
|
335
|
+
('73020000-0000-4000-8000-000000000030', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-000000000013', 'joined', 'member', '73000000-0000-4000-8000-000000000001', null, '2026-09-10 00:00:00+00', '2026-09-10 00:00:00+00'),
|
|
336
|
+
('73020000-0000-4000-8000-000000000031', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-000000000013', 'removed', 'owner', '73000000-0000-4000-8000-000000000001', '2026-09-14 00:00:00+00', '2026-09-14 00:00:00+00', '2026-09-14 00:00:00+00'),
|
|
337
|
+
('73020000-0000-4000-8000-000000000032', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-000000000014', 'subscribed', 'observer', '73000000-0000-4000-8000-000000000001', null, '2026-09-10 00:00:00+00', '2026-09-10 00:00:00+00'),
|
|
338
|
+
('73020000-0000-4000-8000-000000000033', '73010000-0000-4000-8000-000000000003', '73000000-0000-4000-8000-000000000014', 'left', 'admin', '73000000-0000-4000-8000-000000000001', '2026-09-14 00:00:00+00', '2026-09-14 00:00:00+00', '2026-09-14 00:00:00+00');
|
|
242
339
|
|
|
243
340
|
insert into agent_board.board_memberships(board_id, agent_id, membership_state, role, created_by_agent_id)
|
|
244
341
|
values
|
|
@@ -255,6 +352,16 @@ begin
|
|
|
255
352
|
'73000000-0000-4000-8000-00000000000b',
|
|
256
353
|
'73000000-0000-4000-8000-00000000000c',
|
|
257
354
|
'73000000-0000-4000-8000-00000000000d',
|
|
355
|
+
'73010000-0000-4000-8000-000000000003',
|
|
356
|
+
'73000000-0000-4000-8000-00000000000e',
|
|
357
|
+
'73000000-0000-4000-8000-00000000000f',
|
|
358
|
+
'73000000-0000-4000-8000-000000000010',
|
|
359
|
+
'73000000-0000-4000-8000-000000000011',
|
|
360
|
+
'73000000-0000-4000-8000-000000000012',
|
|
361
|
+
'73000000-0000-4000-8000-000000000013',
|
|
362
|
+
'73000000-0000-4000-8000-000000000014',
|
|
363
|
+
v_c_member_was_owner_user, v_c_observer_was_admin_user,
|
|
364
|
+
v_c_owner_removed_user, v_c_admin_left_user, v_c_owner_requested_user, v_c_removed_owner_user,
|
|
258
365
|
v_creator_user, v_owner_user, v_admin_user, v_member_user, v_observer_user,
|
|
259
366
|
v_nonmember_user, v_suspended_user
|
|
260
367
|
);
|
|
@@ -401,7 +508,7 @@ set local role authenticated;
|
|
|
401
508
|
select throws_ok(
|
|
402
509
|
(select format($q$select agent_board.list_board_members(%L::uuid)$q$, board_a) from _roomcontract_fixture),
|
|
403
510
|
'42501', 'only a board owner or admin may list board members',
|
|
404
|
-
'RC-36: board creator identity is not authority
|
|
511
|
+
'RC-36: board creator identity is not authority when no membership row of its own is active');
|
|
405
512
|
|
|
406
513
|
reset role;
|
|
407
514
|
|
|
@@ -416,18 +523,149 @@ select is(
|
|
|
416
523
|
where agent_id = (select board_b_agent from _roomcontract_fixture)),
|
|
417
524
|
0,
|
|
418
525
|
'RC-37: board B membership is absent from board A roster (cross-board isolation)');
|
|
526
|
+
reset role;
|
|
527
|
+
|
|
528
|
+
-- ---------------------------------------------------------------------------
|
|
529
|
+
-- message-board#542: current standing is ACTIVE-FIRST (MBROWID 3a), on board C.
|
|
530
|
+
-- Each allow is lives_ok over a CAPTURE (`create temp table … as select * from
|
|
531
|
+
-- list_board_members(…)`), then SEPARATE state checks read the captured rows
|
|
532
|
+
-- (AGENTS.md rule 3, #113). A bare `is((select … from list_board_members(…)))`
|
|
533
|
+
-- would ABORT the file on a 42501 instead of failing one named assertion:
|
|
534
|
+
-- measured while writing this section — with the authorization key mutated
|
|
535
|
+
-- away, the first bare form killed the transaction and only 38 of 54 ran.
|
|
536
|
+
-- ---------------------------------------------------------------------------
|
|
537
|
+
select set_config('request.jwt.claim.sub', (select c_owner_removed_user::text from _roomcontract_fixture), true);
|
|
538
|
+
set local role authenticated;
|
|
539
|
+
select lives_ok(
|
|
540
|
+
(select format($q$create temp table _rc542_owner_removed on commit drop as select * from agent_board.list_board_members(%L::uuid)$q$, board_c) from _roomcontract_fixture),
|
|
541
|
+
'RC-45: an active owner with a NEWER removed row may list the roster (#542)');
|
|
542
|
+
reset role;
|
|
543
|
+
select set_config('request.jwt.claim.sub', (select c_admin_left_user::text from _roomcontract_fixture), true);
|
|
544
|
+
set local role authenticated;
|
|
545
|
+
select lives_ok(
|
|
546
|
+
(select format($q$create temp table _rc542_admin_left on commit drop as select * from agent_board.list_board_members(%L::uuid)$q$, board_c) from _roomcontract_fixture),
|
|
547
|
+
'RC-47: an active admin with a NEWER left row may list the roster (#542)');
|
|
548
|
+
reset role;
|
|
549
|
+
select set_config('request.jwt.claim.sub', (select c_owner_requested_user::text from _roomcontract_fixture), true);
|
|
550
|
+
set local role authenticated;
|
|
551
|
+
select lives_ok(
|
|
552
|
+
(select format($q$create temp table _rc542_owner_requested on commit drop as select * from agent_board.list_board_members(%L::uuid)$q$, board_c) from _roomcontract_fixture),
|
|
553
|
+
'RC-49: an active owner with a NEWER requested row may list the roster (#542)');
|
|
554
|
+
reset role;
|
|
555
|
+
|
|
556
|
+
-- A capture that never ran leaves no table; to_regclass keeps each state check
|
|
557
|
+
-- a named `not ok` (have NULL) instead of a missing-relation abort.
|
|
558
|
+
create temp table _rc542_rows (
|
|
559
|
+
caller text,
|
|
560
|
+
membership_id uuid,
|
|
561
|
+
board_id uuid,
|
|
562
|
+
agent_id uuid,
|
|
563
|
+
handle text,
|
|
564
|
+
display_name text,
|
|
565
|
+
agent_type text,
|
|
566
|
+
membership_state text,
|
|
567
|
+
role text,
|
|
568
|
+
created_by_agent_id uuid,
|
|
569
|
+
membership_created_at timestamptz,
|
|
570
|
+
membership_updated_at timestamptz
|
|
571
|
+
) on commit drop;
|
|
572
|
+
do $$
|
|
573
|
+
begin
|
|
574
|
+
if to_regclass('pg_temp._rc542_owner_removed') is not null then
|
|
575
|
+
insert into _rc542_rows select 'owner_removed', r.* from _rc542_owner_removed r;
|
|
576
|
+
end if;
|
|
577
|
+
if to_regclass('pg_temp._rc542_admin_left') is not null then
|
|
578
|
+
insert into _rc542_rows select 'admin_left', r.* from _rc542_admin_left r;
|
|
579
|
+
end if;
|
|
580
|
+
if to_regclass('pg_temp._rc542_owner_requested') is not null then
|
|
581
|
+
insert into _rc542_rows select 'owner_requested', r.* from _rc542_owner_requested r;
|
|
582
|
+
end if;
|
|
583
|
+
end
|
|
584
|
+
$$;
|
|
585
|
+
|
|
586
|
+
select is(
|
|
587
|
+
(select string_agg(r.membership_state || '/' || r.role, ',')
|
|
588
|
+
from _rc542_rows r, _roomcontract_fixture f
|
|
589
|
+
where r.caller = 'owner_removed' and r.agent_id = f.c_owner_removed and r.board_id = f.board_c),
|
|
590
|
+
'joined/owner',
|
|
591
|
+
'RC-46: that owner is listed once, by its ACTIVE owner row, not the newer removed row');
|
|
592
|
+
select is(
|
|
593
|
+
(select string_agg(r.membership_state || '/' || r.role, ',')
|
|
594
|
+
from _rc542_rows r, _roomcontract_fixture f
|
|
595
|
+
where r.caller = 'admin_left' and r.agent_id = f.c_admin_left and r.board_id = f.board_c),
|
|
596
|
+
'subscribed/admin',
|
|
597
|
+
'RC-48: that admin is listed once, by its ACTIVE admin row, not the newer left row');
|
|
598
|
+
select is(
|
|
599
|
+
(select string_agg(r.membership_state || '/' || r.role, ',')
|
|
600
|
+
from _rc542_rows r, _roomcontract_fixture f
|
|
601
|
+
where r.caller = 'owner_requested' and r.agent_id = f.c_owner_requested and r.board_id = f.board_c),
|
|
602
|
+
'joined/owner',
|
|
603
|
+
'RC-50: that owner is listed once, by its ACTIVE owner row, not the newer requested row');
|
|
604
|
+
select is(
|
|
605
|
+
(select array_agg(r.handle order by r.handle collate "C")
|
|
606
|
+
from _rc542_rows r, _roomcontract_fixture f
|
|
607
|
+
where r.caller = 'owner_removed' and r.board_id = f.board_c),
|
|
608
|
+
array['rc-c-admin-left', 'rc-c-member-was-owner', 'rc-c-observer-was-admin', 'rc-c-owner-removed', 'rc-c-owner-requested', 'rc-stale', 'rc-tie']::text[],
|
|
609
|
+
'RC-51: board C roster is exactly the seven agents holding an active row, whatever newer rows they have');
|
|
419
610
|
select is(
|
|
420
611
|
(select count(*)::int
|
|
421
|
-
from
|
|
422
|
-
where agent_id =
|
|
423
|
-
|
|
424
|
-
|
|
612
|
+
from _rc542_rows r, _roomcontract_fixture f
|
|
613
|
+
where r.caller = 'owner_removed' and r.agent_id = f.stale_agent and r.board_id = f.board_c
|
|
614
|
+
and r.membership_state = 'joined'),
|
|
615
|
+
1,
|
|
616
|
+
'RC-38: an older joined row outranks a newer LEFT row (active-first before recency)');
|
|
425
617
|
select is(
|
|
426
618
|
(select count(*)::int
|
|
427
|
-
from
|
|
428
|
-
where agent_id =
|
|
619
|
+
from _rc542_rows r, _roomcontract_fixture f
|
|
620
|
+
where r.caller = 'owner_removed' and r.agent_id = f.tie_agent and r.board_id = f.board_c
|
|
621
|
+
and r.membership_id = '73020000-0000-4000-8000-000000000010'::uuid),
|
|
622
|
+
1,
|
|
623
|
+
'RC-39: at an equal created_at the joined row outranks the larger-id removed row');
|
|
624
|
+
select is(
|
|
625
|
+
(select count(*)::int
|
|
626
|
+
from _rc542_rows r, _roomcontract_fixture f
|
|
627
|
+
where r.caller = 'owner_removed' and r.agent_id = f.c_inactive_only and r.board_id = f.board_c),
|
|
429
628
|
0,
|
|
430
|
-
'RC-
|
|
629
|
+
'RC-52: an agent whose only rows are left/removed is not listed');
|
|
630
|
+
|
|
631
|
+
select is(
|
|
632
|
+
(select string_agg(r.handle || '=' || r.membership_state || '/' || r.role, ',' order by r.handle collate "C")
|
|
633
|
+
from _rc542_rows r, _roomcontract_fixture f
|
|
634
|
+
where r.caller = 'owner_removed' and r.board_id = f.board_c
|
|
635
|
+
and r.agent_id in (f.c_member_was_owner, f.c_observer_was_admin)),
|
|
636
|
+
'rc-c-member-was-owner=joined/member,rc-c-observer-was-admin=subscribed/observer',
|
|
637
|
+
'RC-57: a member/observer with a NEWER non-active owner/admin row is listed with its ACTIVE role');
|
|
638
|
+
|
|
639
|
+
select set_config('request.jwt.claim.sub', (select c_member_was_owner_user::text from _roomcontract_fixture), true);
|
|
640
|
+
set local role authenticated;
|
|
641
|
+
select throws_ok(
|
|
642
|
+
(select format($q$select agent_board.list_board_members(%L::uuid)$q$, board_c) from _roomcontract_fixture),
|
|
643
|
+
'42501', 'only a board owner or admin may list board members',
|
|
644
|
+
'RC-55: an active MEMBER with a newer removed OWNER row is refused (the old role confers nothing)');
|
|
645
|
+
reset role;
|
|
646
|
+
|
|
647
|
+
select set_config('request.jwt.claim.sub', (select c_observer_was_admin_user::text from _roomcontract_fixture), true);
|
|
648
|
+
set local role authenticated;
|
|
649
|
+
select throws_ok(
|
|
650
|
+
(select format($q$select agent_board.list_board_members(%L::uuid)$q$, board_c) from _roomcontract_fixture),
|
|
651
|
+
'42501', 'only a board owner or admin may list board members',
|
|
652
|
+
'RC-56: an active OBSERVER with a newer left ADMIN row is refused');
|
|
653
|
+
reset role;
|
|
654
|
+
|
|
655
|
+
select set_config('request.jwt.claim.sub', (select c_removed_owner_user::text from _roomcontract_fixture), true);
|
|
656
|
+
set local role authenticated;
|
|
657
|
+
select throws_ok(
|
|
658
|
+
(select format($q$select agent_board.list_board_members(%L::uuid)$q$, board_c) from _roomcontract_fixture),
|
|
659
|
+
'42501', 'only a board owner or admin may list board members',
|
|
660
|
+
'RC-53: an owner whose rows are all left/removed (no active row) is refused');
|
|
661
|
+
reset role;
|
|
662
|
+
|
|
663
|
+
select set_config('request.jwt.claim.sub', (select owner_user::text from _roomcontract_fixture), true);
|
|
664
|
+
set local role authenticated;
|
|
665
|
+
select throws_ok(
|
|
666
|
+
(select format($q$select agent_board.list_board_members(%L::uuid)$q$, board_c) from _roomcontract_fixture),
|
|
667
|
+
'42501', 'only a board owner or admin may list board members',
|
|
668
|
+
'RC-54: board A''s owner holds no row on board C and is refused there (standing is board-scoped)');
|
|
431
669
|
reset role;
|
|
432
670
|
|
|
433
671
|
-- ---------------------------------------------------------------------------
|
|
@@ -456,7 +694,7 @@ select set_config('request.jwt.claim.sub', '', true);
|
|
|
456
694
|
\else
|
|
457
695
|
|
|
458
696
|
select * from skip(
|
|
459
|
-
|
|
697
|
+
41,
|
|
460
698
|
'ROOMCONTRACT runtime checks require list_board_members and v_board_memberships.role'
|
|
461
699
|
);
|
|
462
700
|
|
|
@@ -343,7 +343,7 @@ begin
|
|
|
343
343
|
from _lf f, agent_board.enroll_federated_identity(
|
|
344
344
|
f.prov_iss, 'message-board', f.prov_sub,
|
|
345
345
|
jsonb_build_object('iss',f.prov_iss,'aud','message-board','sub', f.prov_sub), f.prov_slug,
|
|
346
|
-
f.pub1, 'raw_ed25519_base64url', f.fp1, true, null, 'agent', '{}', '{}', f.code_enroll) e;
|
|
346
|
+
f.pub1, 'raw_ed25519_base64url', f.fp1, true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1), null, 'agent', '{}', '{}', f.code_enroll) e;
|
|
347
347
|
insert into _er values ('X', v_aid, v_red);
|
|
348
348
|
|
|
349
349
|
-- Bad code: enrollment still succeeds, invite_redeemed=false, no membership.
|
|
@@ -351,7 +351,7 @@ begin
|
|
|
351
351
|
from _lf f, agent_board.enroll_federated_identity(
|
|
352
352
|
f.prov_iss, 'message-board', f.prov_sub || '-2',
|
|
353
353
|
jsonb_build_object('iss',f.prov_iss,'aud','message-board','sub', f.prov_sub || '-2'), f.prov_slug || '-2',
|
|
354
|
-
f.pub2, 'raw_ed25519_base64url', f.fp2, true, null, 'agent', '{}', '{}', 'bogus-code-nonexistent') e;
|
|
354
|
+
f.pub2, 'raw_ed25519_base64url', f.fp2, true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1), null, 'agent', '{}', '{}', 'bogus-code-nonexistent') e;
|
|
355
355
|
insert into _er values ('Y', v_aid, v_red);
|
|
356
356
|
end
|
|
357
357
|
$$;
|
|
@@ -19,7 +19,7 @@ set search_path = extensions, public, agent_board;
|
|
|
19
19
|
|
|
20
20
|
begin;
|
|
21
21
|
|
|
22
|
-
select plan(
|
|
22
|
+
select plan(99);
|
|
23
23
|
|
|
24
24
|
create temp view _rowid_order_sites as
|
|
25
25
|
with defs as (
|
|
@@ -29,7 +29,7 @@ with defs as (
|
|
|
29
29
|
-- LITERALS STRIPPED, and re-derived rather than assumed. The first version of
|
|
30
30
|
-- this line kept literals "because some ORDER BY operands are literals"; that
|
|
31
31
|
-- was measured and is false for THIS view -- the derived checks over it match
|
|
32
|
-
-- `created_at desc` / `id desc`, which are code, and the whole file
|
|
32
|
+
-- `created_at desc` / `id desc`, which are code, and the whole file was 98/98 when measured
|
|
33
33
|
-- with literals stripped. Keeping them left a real, if narrow, hole: the site
|
|
34
34
|
-- set is built by splitting `def` on `;`, so a literal containing a semicolon
|
|
35
35
|
-- re-splits a statement and can drop it out of the set.
|
|
@@ -1300,6 +1300,19 @@ select is(
|
|
|
1300
1300
|
select set_config('request.jwt.claim.role', '', true);
|
|
1301
1301
|
select set_config('request.jwt.claim.sub', '', true);
|
|
1302
1302
|
|
|
1303
|
+
-- 99. list_board_members (ROOMCONTRACT, re-created active-first by #542) was in
|
|
1304
|
+
-- the assertion-2 inventory but had no count-equality row of its own, so a
|
|
1305
|
+
-- dropped `bm.id desc` at either site went unnoticed here; through the roster
|
|
1306
|
+
-- itself the tiebreak is unobservable (it only orders non-active rows). Pinned as
|
|
1307
|
+
-- the exact pair (created_at DESC sites, of them with id DESC) so a site that
|
|
1308
|
+
-- disappears is not read as agreement 0 = 0.
|
|
1309
|
+
select is(
|
|
1310
|
+
(select array[created_at_desc_count, total_order_count]
|
|
1311
|
+
from _rowid_function_order_counts
|
|
1312
|
+
where proname = 'list_board_members'),
|
|
1313
|
+
array[2, 2],
|
|
1314
|
+
'list_board_members: BOTH created_at DESC sites (authorization + projection) have the id DESC tiebreak');
|
|
1315
|
+
|
|
1303
1316
|
select finish();
|
|
1304
1317
|
|
|
1305
1318
|
rollback;
|
|
@@ -424,10 +424,13 @@ select distinct p.oid,
|
|
|
424
424
|
|
|
425
425
|
-- WEC-1. The universe canary. Without it, a write-target set that had gone empty would empty the
|
|
426
426
|
-- writer population too. Base tables only — see limit 4 on why the 26 views are not pinned.
|
|
427
|
+
-- 59 -> 60 with #521's agent_board.enroll_token_uses. Its only writer, _enroll_token_bind, is
|
|
428
|
+
-- EXECUTE-able by no API role and is reached only from the service_role-only
|
|
429
|
+
-- enroll_federated_identity, so it adds no member to the `authenticated` writer population.
|
|
427
430
|
select is(
|
|
428
431
|
(select count(*)::text from _wec_target where relkind = 'r'),
|
|
429
|
-
'
|
|
430
|
-
'#325 canary: agent_board has
|
|
432
|
+
'60',
|
|
433
|
+
'#325 canary: agent_board has 60 base tables — the universe the write scan runs over, pinned so an empty violating set below cannot mean an empty universe');
|
|
431
434
|
|
|
432
435
|
-- WEC-2. The relations the class writes, as an EXACT SET. A new one names itself.
|
|
433
436
|
select is(
|
|
@@ -366,7 +366,16 @@
|
|
|
366
366
|
"signature": "_enroll_federated_identity_once(p_issuer text, p_audience text, p_subject text, p_human_identity_claim jsonb, p_slug text, p_agent_public_key text, p_agent_public_key_format text, p_agent_public_key_fingerprint text, p_pop_verified boolean, p_actor_sub text, p_agent_kind text, p_requested_scopes text[], p_requested_board_scopes text[], p_invite_code text)",
|
|
367
367
|
"executable_by": {
|
|
368
368
|
"anon": false,
|
|
369
|
-
"service_role":
|
|
369
|
+
"service_role": false,
|
|
370
|
+
"authenticated": false
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
"name": "_enroll_token_bind",
|
|
375
|
+
"signature": "_enroll_token_bind(p_token_sha256 text, p_token_expires_at timestamp with time zone, p_fingerprint text)",
|
|
376
|
+
"executable_by": {
|
|
377
|
+
"anon": false,
|
|
378
|
+
"service_role": false,
|
|
370
379
|
"authenticated": false
|
|
371
380
|
}
|
|
372
381
|
},
|
|
@@ -957,7 +966,7 @@
|
|
|
957
966
|
},
|
|
958
967
|
{
|
|
959
968
|
"name": "enroll_federated_identity",
|
|
960
|
-
"signature": "enroll_federated_identity(p_issuer text, p_audience text, p_subject text, p_human_identity_claim jsonb, p_slug text, p_agent_public_key text, p_agent_public_key_format text, p_agent_public_key_fingerprint text, p_pop_verified boolean, p_actor_sub text, p_agent_kind text, p_requested_scopes text[], p_requested_board_scopes text[], p_invite_code text)",
|
|
969
|
+
"signature": "enroll_federated_identity(p_issuer text, p_audience text, p_subject text, p_human_identity_claim jsonb, p_slug text, p_agent_public_key text, p_agent_public_key_format text, p_agent_public_key_fingerprint text, p_pop_verified boolean, p_token_sha256 text, p_token_expires_at timestamp with time zone, p_actor_sub text, p_agent_kind text, p_requested_scopes text[], p_requested_board_scopes text[], p_invite_code text)",
|
|
961
970
|
"executable_by": {
|
|
962
971
|
"anon": false,
|
|
963
972
|
"service_role": true,
|
|
@@ -1119,7 +1128,7 @@
|
|
|
1119
1128
|
},
|
|
1120
1129
|
{
|
|
1121
1130
|
"name": "onboard_federated_fleet_agent",
|
|
1122
|
-
"signature": "onboard_federated_fleet_agent(p_issuer text, p_audience text, p_subject text, p_human_identity_claim jsonb, p_slug text, p_agent_public_key text, p_agent_public_key_format text, p_agent_public_key_fingerprint text, p_pop_verified boolean, p_actor_sub text, p_agent_kind text, p_requested_scopes text[], p_requested_board_scopes text[], p_invite_code text, p_board_id uuid, p_machine_id uuid, p_harness_kind text, p_harness_label text, p_repo_slug text, p_repo_fingerprint text, p_repo_scope_role text, p_agent_role text, p_expected_agent_handle text)",
|
|
1131
|
+
"signature": "onboard_federated_fleet_agent(p_issuer text, p_audience text, p_subject text, p_human_identity_claim jsonb, p_slug text, p_agent_public_key text, p_agent_public_key_format text, p_agent_public_key_fingerprint text, p_pop_verified boolean, p_token_sha256 text, p_token_expires_at timestamp with time zone, p_actor_sub text, p_agent_kind text, p_requested_scopes text[], p_requested_board_scopes text[], p_invite_code text, p_board_id uuid, p_machine_id uuid, p_harness_kind text, p_harness_label text, p_repo_slug text, p_repo_fingerprint text, p_repo_scope_role text, p_agent_role text, p_expected_agent_handle text)",
|
|
1123
1132
|
"executable_by": {
|
|
1124
1133
|
"anon": false,
|
|
1125
1134
|
"service_role": true,
|
|
@@ -165,6 +165,10 @@
|
|
|
165
165
|
"signature": "_enroll_federated_identity_once(p_issuer text, p_audience text, p_subject text, p_human_identity_claim jsonb, p_slug text, p_agent_public_key text, p_agent_public_key_format text, p_agent_public_key_fingerprint text, p_pop_verified boolean, p_actor_sub text, p_agent_kind text, p_requested_scopes text[], p_requested_board_scopes text[], p_invite_code text)",
|
|
166
166
|
"declares_p_metadata": false
|
|
167
167
|
},
|
|
168
|
+
{
|
|
169
|
+
"signature": "_enroll_token_bind(p_token_sha256 text, p_token_expires_at timestamp with time zone, p_fingerprint text)",
|
|
170
|
+
"declares_p_metadata": false
|
|
171
|
+
},
|
|
168
172
|
{
|
|
169
173
|
"signature": "_ensure_agent_auth_user(p_slug text)",
|
|
170
174
|
"declares_p_metadata": false
|
|
@@ -426,7 +430,7 @@
|
|
|
426
430
|
"declares_p_metadata": false
|
|
427
431
|
},
|
|
428
432
|
{
|
|
429
|
-
"signature": "enroll_federated_identity(p_issuer text, p_audience text, p_subject text, p_human_identity_claim jsonb, p_slug text, p_agent_public_key text, p_agent_public_key_format text, p_agent_public_key_fingerprint text, p_pop_verified boolean, p_actor_sub text, p_agent_kind text, p_requested_scopes text[], p_requested_board_scopes text[], p_invite_code text)",
|
|
433
|
+
"signature": "enroll_federated_identity(p_issuer text, p_audience text, p_subject text, p_human_identity_claim jsonb, p_slug text, p_agent_public_key text, p_agent_public_key_format text, p_agent_public_key_fingerprint text, p_pop_verified boolean, p_token_sha256 text, p_token_expires_at timestamp with time zone, p_actor_sub text, p_agent_kind text, p_requested_scopes text[], p_requested_board_scopes text[], p_invite_code text)",
|
|
430
434
|
"declares_p_metadata": false
|
|
431
435
|
},
|
|
432
436
|
{
|
|
@@ -498,7 +502,7 @@
|
|
|
498
502
|
"declares_p_metadata": false
|
|
499
503
|
},
|
|
500
504
|
{
|
|
501
|
-
"signature": "onboard_federated_fleet_agent(p_issuer text, p_audience text, p_subject text, p_human_identity_claim jsonb, p_slug text, p_agent_public_key text, p_agent_public_key_format text, p_agent_public_key_fingerprint text, p_pop_verified boolean, p_actor_sub text, p_agent_kind text, p_requested_scopes text[], p_requested_board_scopes text[], p_invite_code text, p_board_id uuid, p_machine_id uuid, p_harness_kind text, p_harness_label text, p_repo_slug text, p_repo_fingerprint text, p_repo_scope_role text, p_agent_role text, p_expected_agent_handle text)",
|
|
505
|
+
"signature": "onboard_federated_fleet_agent(p_issuer text, p_audience text, p_subject text, p_human_identity_claim jsonb, p_slug text, p_agent_public_key text, p_agent_public_key_format text, p_agent_public_key_fingerprint text, p_pop_verified boolean, p_token_sha256 text, p_token_expires_at timestamp with time zone, p_actor_sub text, p_agent_kind text, p_requested_scopes text[], p_requested_board_scopes text[], p_invite_code text, p_board_id uuid, p_machine_id uuid, p_harness_kind text, p_harness_label text, p_repo_slug text, p_repo_fingerprint text, p_repo_scope_role text, p_agent_role text, p_expected_agent_handle text)",
|
|
502
506
|
"declares_p_metadata": false
|
|
503
507
|
},
|
|
504
508
|
{
|
|
@@ -26,7 +26,7 @@ step fleet_onboard:
|
|
|
26
26
|
'eRHZmllEy_TZHAG2zB-Qe_a5BFLkaavMTazWWfaE3f0',
|
|
27
27
|
'raw_ed25519_base64url',
|
|
28
28
|
'sha256:z8d5LQPfBMYnfZfvu8wVz684_jkp578-SPDU2OMObS8',
|
|
29
|
-
true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
29
|
+
true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1), null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
30
30
|
(select code from agent_board.board_invite_tokens where created_by_agent_id='162a0000-0000-0000-0000-000000000001'),
|
|
31
31
|
(select id from agent_board.boards where slug='atomic-cross-board'),
|
|
32
32
|
'162a0000-0000-0000-0000-000000000003',
|
|
@@ -11,7 +11,7 @@ step retry_onboard:
|
|
|
11
11
|
'yd_DIFGWGusVg3SbktDJQ1bE5UWvtR33xln4b05JIhk',
|
|
12
12
|
'raw_ed25519_base64url',
|
|
13
13
|
'sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA',
|
|
14
|
-
true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
14
|
+
true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1), null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
15
15
|
(select code from agent_board.board_invite_tokens where created_by_agent_id='16250000-0000-0000-0000-000000000001'),
|
|
16
16
|
(select id from agent_board.boards where slug='atomic-authority-board'),
|
|
17
17
|
'16250000-0000-0000-0000-000000000003', 'codex', 'phase-loop',
|
|
@@ -71,7 +71,7 @@ step retry_onboard:
|
|
|
71
71
|
'yd_DIFGWGusVg3SbktDJQ1bE5UWvtR33xln4b05JIhk',
|
|
72
72
|
'raw_ed25519_base64url',
|
|
73
73
|
'sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA',
|
|
74
|
-
true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
74
|
+
true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1), null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
75
75
|
(select code from agent_board.board_invite_tokens where created_by_agent_id='16250000-0000-0000-0000-000000000001'),
|
|
76
76
|
(select id from agent_board.boards where slug='atomic-authority-board'),
|
|
77
77
|
'16250000-0000-0000-0000-000000000003', 'codex', 'phase-loop',
|
|
@@ -129,7 +129,7 @@ step retry_onboard:
|
|
|
129
129
|
'yd_DIFGWGusVg3SbktDJQ1bE5UWvtR33xln4b05JIhk',
|
|
130
130
|
'raw_ed25519_base64url',
|
|
131
131
|
'sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA',
|
|
132
|
-
true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
132
|
+
true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1), null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
133
133
|
(select code from agent_board.board_invite_tokens where created_by_agent_id='16250000-0000-0000-0000-000000000001'),
|
|
134
134
|
(select id from agent_board.boards where slug='atomic-authority-board'),
|
|
135
135
|
'16250000-0000-0000-0000-000000000003', 'codex', 'phase-loop',
|
|
@@ -202,7 +202,7 @@ step retry_onboard:
|
|
|
202
202
|
'yd_DIFGWGusVg3SbktDJQ1bE5UWvtR33xln4b05JIhk',
|
|
203
203
|
'raw_ed25519_base64url',
|
|
204
204
|
'sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA',
|
|
205
|
-
true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
205
|
+
true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1), null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
206
206
|
(select code from agent_board.board_invite_tokens where created_by_agent_id='16250000-0000-0000-0000-000000000001'),
|
|
207
207
|
(select id from agent_board.boards where slug='atomic-authority-board'),
|
|
208
208
|
'16250000-0000-0000-0000-000000000003', 'codex', 'phase-loop',
|
|
@@ -256,7 +256,7 @@ step retry_onboard:
|
|
|
256
256
|
'yd_DIFGWGusVg3SbktDJQ1bE5UWvtR33xln4b05JIhk',
|
|
257
257
|
'raw_ed25519_base64url',
|
|
258
258
|
'sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA',
|
|
259
|
-
true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
259
|
+
true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1), null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
260
260
|
(select code from agent_board.board_invite_tokens where created_by_agent_id='16250000-0000-0000-0000-000000000001'),
|
|
261
261
|
(select id from agent_board.boards where slug='atomic-authority-board'),
|
|
262
262
|
'16250000-0000-0000-0000-000000000003', 'codex', 'phase-loop',
|
|
@@ -312,7 +312,7 @@ step retry_onboard:
|
|
|
312
312
|
'yd_DIFGWGusVg3SbktDJQ1bE5UWvtR33xln4b05JIhk',
|
|
313
313
|
'raw_ed25519_base64url',
|
|
314
314
|
'sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA',
|
|
315
|
-
true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
315
|
+
true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1), null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
316
316
|
(select code from agent_board.board_invite_tokens where created_by_agent_id='16250000-0000-0000-0000-000000000001'),
|
|
317
317
|
(select id from agent_board.boards where slug='atomic-authority-board'),
|
|
318
318
|
'16250000-0000-0000-0000-000000000003', 'codex', 'phase-loop',
|
|
@@ -355,7 +355,7 @@ step retry_onboard:
|
|
|
355
355
|
'yd_DIFGWGusVg3SbktDJQ1bE5UWvtR33xln4b05JIhk',
|
|
356
356
|
'raw_ed25519_base64url',
|
|
357
357
|
'sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA',
|
|
358
|
-
true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
358
|
+
true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1), null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
359
359
|
(select code from agent_board.board_invite_tokens where created_by_agent_id='16250000-0000-0000-0000-000000000001'),
|
|
360
360
|
(select id from agent_board.boards where slug='atomic-authority-board'),
|
|
361
361
|
'16250000-0000-0000-0000-000000000003', 'codex', 'phase-loop',
|
|
@@ -436,7 +436,7 @@ step retry_onboard:
|
|
|
436
436
|
'yd_DIFGWGusVg3SbktDJQ1bE5UWvtR33xln4b05JIhk',
|
|
437
437
|
'raw_ed25519_base64url',
|
|
438
438
|
'sha256:NeVC2vx1MbTY56jUwJcLLr6YwB4IKCERsXWbUwhf5pA',
|
|
439
|
-
true, null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
439
|
+
true, md5(random()::text) || md5(random()::text), now() + make_interval(hours => 1), null, 'agent', ARRAY['board:send'], ARRAY[]::text[],
|
|
440
440
|
(select code from agent_board.board_invite_tokens where created_by_agent_id='16250000-0000-0000-0000-000000000001'),
|
|
441
441
|
(select id from agent_board.boards where slug='atomic-authority-board'),
|
|
442
442
|
'16250000-0000-0000-0000-000000000003', 'codex', 'phase-loop',
|