@consiliency/agent-board-schema 1.59.0 → 1.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -0
- package/fixtures/already-applied.json +16 -0
- package/migrations/20261010000100_agent_board_own_post_not_delivered.sql +637 -0
- package/migrations/20261011000100_agent_board_session_identities.sql +1964 -0
- package/migrations/20261012000100_agent_board_sidowner.sql +209 -0
- package/migrations/20261014000100_agent_board_grant_target_role.sql +218 -0
- package/package.json +1 -1
- package/schema-manifest.json +39 -3
- package/src/tooling.test.mjs +9 -2
- package/tests/agent_board_addressing.test.sql +3 -1
- package/tests/agent_board_atomic_fleet_onboarding.test.sql +13 -4
- package/tests/agent_board_consent_emission.test.sql +30 -11
- package/tests/agent_board_consent_gating.test.sql +16 -2
- package/tests/agent_board_delegate_role_class.test.sql +1 -1
- package/tests/agent_board_delegation_cap_ceiling.test.sql +26 -15
- package/tests/agent_board_delegation_enforcement.test.sql +1 -1
- package/tests/agent_board_enroll_resumption.test.sql +22 -4
- package/tests/agent_board_enroll_token_single_use.test.sql +18 -3
- package/tests/agent_board_federated_lock_order_class.test.sql +2 -2
- package/tests/agent_board_fk_lock_edges.test.sql +74 -14
- package/tests/agent_board_grant_target_role.test.sql +1118 -0
- package/tests/agent_board_inbox_rpcs.test.sql +5 -2
- package/tests/agent_board_invite_no_downgrade.test.sql +10 -8
- package/tests/agent_board_ledger_authority.test.sql +70 -12
- package/tests/agent_board_membership_current_row_class.test.sql +9 -1
- package/tests/agent_board_mint_fleet_agent_session.test.sql +2 -2
- package/tests/agent_board_mint_harden.test.sql +38 -27
- package/tests/agent_board_own_post_not_delivered.test.sql +490 -0
- package/tests/agent_board_rolereset.test.sql +8 -2
- package/tests/agent_board_roomdeleg_lane_b.test.sql +6 -6
- package/tests/agent_board_rowid.test.sql +3 -1
- package/tests/agent_board_session_identity_approval_revocation.test.sql +334 -0
- package/tests/agent_board_session_identity_backfill.test.sql +82 -0
- package/tests/agent_board_session_identity_backfill_refusal.test.sql +14 -0
- package/tests/agent_board_session_identity_behavior_classes.test.sql +176 -0
- package/tests/agent_board_session_identity_class.test.sql +118 -0
- package/tests/agent_board_session_identity_fingerprint.test.sql +271 -0
- package/tests/agent_board_session_identity_labels_limits.test.sql +205 -0
- package/tests/agent_board_session_identity_lease.test.sql +235 -0
- package/tests/agent_board_session_identity_lifetime.test.sql +230 -0
- package/tests/agent_board_session_identity_limits.test.sql +208 -0
- package/tests/agent_board_session_identity_lineage.test.sql +64 -0
- package/tests/agent_board_session_identity_link.test.sql +201 -0
- package/tests/agent_board_session_identity_mint.test.sql +233 -0
- package/tests/agent_board_session_identity_panel_r1.test.sql +194 -0
- package/tests/agent_board_session_identity_panel_r2.test.sql +174 -0
- package/tests/agent_board_session_identity_protected_actions.test.sql +156 -0
- package/tests/agent_board_session_identity_revoke_closure.test.sql +131 -0
- package/tests/agent_board_sidowner_leases.test.sql +107 -0
- package/tests/agent_board_sidowner_owner_required.test.sql +97 -0
- package/tests/agent_board_sidowner_read_class.test.sql +171 -0
- package/tests/agent_board_sidowner_reads.test.sql +136 -0
- package/tests/agent_board_signer_lifecycle.test.sql +26 -4
- package/tests/agent_board_signing_challenge_pending_cap.test.sql +1 -1
- package/tests/agent_board_v2_invariants.test.sql +4 -4
- package/tests/agent_board_write_enforcement_class.test.sql +74 -15
- package/tests/catalog/function_execute_privileges.json +218 -2
- package/tests/catalog/p_metadata_parameters.json +98 -2
- package/tests/isolation/expected/grant_target_role_race.out +348 -0
- package/tests/isolation/expected/session_identity_limits.out +165 -0
- package/tests/isolation/expected/session_identity_links.out +235 -0
- package/tests/isolation/expected/session_identity_reclaim.out +253 -0
- package/tests/isolation/expected/session_identity_renew_revoke.out +115 -0
- package/tests/isolation/expected/session_identity_renew_revoke_key_gate.out +138 -0
- package/tests/isolation/expected/session_identity_tombstone_onboarding.out +247 -0
- package/tests/isolation/specs/grant_target_role_race.spec +207 -0
- package/tests/isolation/specs/session_identity_limits.spec +81 -0
- package/tests/isolation/specs/session_identity_links.spec +80 -0
- package/tests/isolation/specs/session_identity_reclaim.spec +125 -0
- package/tests/isolation/specs/session_identity_renew_revoke.spec +84 -0
- package/tests/isolation/specs/session_identity_renew_revoke_key_gate.spec +94 -0
- package/tests/isolation/specs/session_identity_tombstone_onboarding.spec +108 -0
- package/tests/seeds/20261011000100_agent_board_session_identities.sql.pre.sql +47 -0
|
@@ -332,7 +332,7 @@ set search_path = extensions, public, agent_board;
|
|
|
332
332
|
|
|
333
333
|
begin;
|
|
334
334
|
|
|
335
|
-
select plan(
|
|
335
|
+
select plan(30);
|
|
336
336
|
|
|
337
337
|
-- ===========================================================================================
|
|
338
338
|
-- THE CLASS, derived from pg_catalog. Nothing below is a list of names.
|
|
@@ -430,10 +430,12 @@ select distinct p.oid,
|
|
|
430
430
|
-- 60 -> 62 with HOSTED's delegate_instances and delegate_allowed_operations (20261008000100).
|
|
431
431
|
-- Both are written only by service_role-only definers or the migration itself, so neither joins
|
|
432
432
|
-- the `authenticated` writer population below.
|
|
433
|
+
-- SIDSCHEMA adds identities and aliases. Human-owner readmission writes them and
|
|
434
|
+
-- delegation_grants; these remain in the derived class, not an exemption list.
|
|
433
435
|
select is(
|
|
434
436
|
(select count(*)::text from _wec_target where relkind = 'r'),
|
|
435
|
-
'
|
|
436
|
-
'#325 canary: agent_board has
|
|
437
|
+
'64',
|
|
438
|
+
'#325 canary: agent_board has 64 base tables — the universe the write scan runs over, pinned so an empty violating set below cannot mean an empty universe');
|
|
437
439
|
|
|
438
440
|
-- WEC-2. The relations the class writes, as an EXACT SET. A new one names itself.
|
|
439
441
|
select is(
|
|
@@ -459,6 +461,7 @@ select is(
|
|
|
459
461
|
'callback_subscriptions',
|
|
460
462
|
'claims',
|
|
461
463
|
'conflicts',
|
|
464
|
+
'delegation_grants',
|
|
462
465
|
'delegation_policies',
|
|
463
466
|
'delegations',
|
|
464
467
|
'delivery_recipients',
|
|
@@ -476,11 +479,13 @@ select is(
|
|
|
476
479
|
'presence',
|
|
477
480
|
'read_receipts',
|
|
478
481
|
'send_authz_telemetry',
|
|
482
|
+
'session_id_aliases',
|
|
483
|
+
'session_identities',
|
|
479
484
|
'task_events',
|
|
480
485
|
'tasks',
|
|
481
486
|
'threads'
|
|
482
487
|
]::text[],
|
|
483
|
-
'#325: these
|
|
488
|
+
'#325: these 40 agent_board relations are written by an authenticated-executable function, directly or through a callee — SIDSCHEMA readmission adds grants, identities and aliases without excluding their writers');
|
|
484
489
|
|
|
485
490
|
-- WEC-3. The class itself, as an EXACT SET of SIGNATURES, and it is signatures rather than
|
|
486
491
|
-- `count(*) = 59` for two reasons. The routine response to a red count is to bump the count,
|
|
@@ -495,6 +500,8 @@ select is( -- pgtap-allow-raise-checked
|
|
|
495
500
|
-- HOSTED (20261008000100): the owner places its hosted delegate through the sink.
|
|
496
501
|
'agent_board.add_delegate_to_board(uuid,uuid)',
|
|
497
502
|
'agent_board.append_task_event(uuid,uuid,text,jsonb,text,uuid,timestamp with time zone)',
|
|
503
|
+
-- Approval's measured fingerprint is service-only until SIDSERVER binds it.
|
|
504
|
+
-- Its ACL and real human/ancestor actors are pinned in the fingerprint suite.
|
|
498
505
|
'agent_board.block_board_inviter(uuid,uuid,uuid,jsonb)',
|
|
499
506
|
'agent_board.create_board(uuid,text,text,text,jsonb,text)',
|
|
500
507
|
'agent_board.create_fleet_onboarding_invite(uuid,uuid,text,text,text,text,text,text,text,integer,timestamp with time zone,uuid,jsonb)',
|
|
@@ -509,6 +516,7 @@ select is( -- pgtap-allow-raise-checked
|
|
|
509
516
|
'agent_board.disable_callback_endpoint(uuid,uuid,text,jsonb)',
|
|
510
517
|
'agent_board.grant_board_role(uuid,uuid,text,uuid)',
|
|
511
518
|
'agent_board.heartbeat(uuid,uuid,text,text,interval,jsonb)',
|
|
519
|
+
'agent_board.heartbeat_session_identity(uuid)',
|
|
512
520
|
'agent_board.invite_board_member(uuid,uuid,uuid,jsonb)',
|
|
513
521
|
'agent_board.issue_signing_key_challenge(uuid,text,interval)',
|
|
514
522
|
'agent_board.join_board(uuid,uuid,text,uuid,jsonb)',
|
|
@@ -520,13 +528,17 @@ select is( -- pgtap-allow-raise-checked
|
|
|
520
528
|
'agent_board.provision_agent(text,text,jsonb,uuid)',
|
|
521
529
|
'agent_board.raise_conflict(uuid,uuid,text,text,text,uuid,jsonb)',
|
|
522
530
|
'agent_board.raise_escalation(uuid,uuid,text,text,text,uuid,uuid,jsonb)',
|
|
531
|
+
'agent_board.readmit_session_identity(uuid,text,text,jsonb,jsonb,interval)',
|
|
523
532
|
'agent_board.record_signing_key_proof_result(uuid,uuid,text,boolean,text,jsonb)',
|
|
524
533
|
'agent_board.redeem_invite_link(text,jsonb)',
|
|
525
534
|
'agent_board.register_agent(text,text,text,text,jsonb)',
|
|
526
535
|
'agent_board.register_callback_endpoint(uuid,text,jsonb)',
|
|
527
536
|
'agent_board.register_fleet_machine(uuid,uuid,text,text,text,jsonb)',
|
|
528
537
|
'agent_board.release_claim(uuid)',
|
|
538
|
+
'agent_board.rename_agent(uuid,text)',
|
|
529
539
|
'agent_board.renew_claim(uuid,timestamp with time zone)',
|
|
540
|
+
-- Fresh renewal attestation is service-role-only; lifetime's trust assertion
|
|
541
|
+
-- positively pins the ACL, rather than excluding a reachable writer here.
|
|
530
542
|
'agent_board.request_join_board(uuid,uuid,jsonb)',
|
|
531
543
|
'agent_board.resolve_board_request(uuid,uuid,text,uuid,jsonb)',
|
|
532
544
|
'agent_board.resolve_conflict(uuid,uuid,jsonb)',
|
|
@@ -535,6 +547,7 @@ select is( -- pgtap-allow-raise-checked
|
|
|
535
547
|
'agent_board.revoke_fleet_machine_agent_binding(uuid,uuid,text,jsonb)',
|
|
536
548
|
'agent_board.revoke_fleet_subject(text,uuid,uuid,text,jsonb)',
|
|
537
549
|
'agent_board.revoke_invite_link(text,jsonb)',
|
|
550
|
+
'agent_board.revoke_session_identity(uuid)',
|
|
538
551
|
'agent_board.rotate_callback_signing_key(uuid,uuid,jsonb)',
|
|
539
552
|
'agent_board.self_enroll_human(text)',
|
|
540
553
|
'agent_board.send_direct_message(uuid,uuid,jsonb,text,text,text,text,text,text,jsonb)',
|
|
@@ -543,6 +556,7 @@ select is( -- pgtap-allow-raise-checked
|
|
|
543
556
|
'agent_board.send_multicast_message(uuid,uuid,uuid[],text,text,text,text,text,jsonb)',
|
|
544
557
|
'agent_board.set_board_authority_ceiling(uuid,text,uuid)',
|
|
545
558
|
'agent_board.set_board_claim_policy(uuid,text)',
|
|
559
|
+
'agent_board.set_board_member_label(uuid,uuid,text)',
|
|
546
560
|
'agent_board.set_board_role_gate(uuid,boolean)',
|
|
547
561
|
'agent_board.set_fleet_receive_policy(uuid,text,text,boolean,uuid,uuid,jsonb)',
|
|
548
562
|
'agent_board.subscribe_callback_endpoint(uuid,uuid,text,text,uuid,jsonb)',
|
|
@@ -553,7 +567,7 @@ select is( -- pgtap-allow-raise-checked
|
|
|
553
567
|
'agent_board.upsert_delegation_policy(uuid,text,jsonb,integer,interval,boolean)',
|
|
554
568
|
'agent_board.verify_callback_endpoint(uuid,uuid,jsonb)'
|
|
555
569
|
]::text[],
|
|
556
|
-
'#325: the effect-derived class is exactly these
|
|
570
|
+
'#325: the effect-derived class is exactly these 66 authenticated-executable writer OVERLOADS — per-OID, and TRANSITIVE, so a delegating wrapper whose own body holds no DML is a member rather than a blind spot');
|
|
557
571
|
|
|
558
572
|
-- WEC-4. THE DELEGATION-CHAIN LIVENESS PIN, and the mitigation for the fail-open inversion the
|
|
559
573
|
-- header describes. Everything above depends on `fn_call_closure()` actually resolving edges; a
|
|
@@ -614,8 +628,8 @@ select is(
|
|
|
614
628
|
(select coalesce(array_agg(p.sig order by p.sig), array[]::text[])
|
|
615
629
|
from _wec_pop p
|
|
616
630
|
where agent_board_test.stripped_body(p.oid, true) ~ agent_board_test.call_re('auth.uid', false)),
|
|
617
|
-
array['agent_board.self_enroll_human(text)']::text[],
|
|
618
|
-
'#325: exactly
|
|
631
|
+
array['agent_board.rename_agent(uuid,text)', 'agent_board.self_enroll_human(text)']::text[],
|
|
632
|
+
'#325: exactly these writers derive from raw auth.uid() — self enrollment creates the human identity; rename requires its active human owner, positively exercised by WEC-26..29');
|
|
619
633
|
|
|
620
634
|
-- ===========================================================================================
|
|
621
635
|
-- HALF B — every writer REFUSES SOMEBODY. Labelled honestly: it pins that a refusal exists on the
|
|
@@ -673,7 +687,6 @@ select is( -- pgtap-allow-raise-checked
|
|
|
673
687
|
'agent_board.issue_signing_key_challenge(uuid,text,interval) -> _resolved_actor_agent_id',
|
|
674
688
|
'agent_board.provision_agent(text,text,jsonb,uuid) -> _require_platform_admin_user_id',
|
|
675
689
|
'agent_board.register_callback_endpoint(uuid,text,jsonb) -> _resolved_actor_agent_id',
|
|
676
|
-
'agent_board.revoke_agent(uuid,text) -> _require_platform_admin_user_id',
|
|
677
690
|
'agent_board.rotate_callback_signing_key(uuid,uuid,jsonb) -> _resolved_actor_agent_id',
|
|
678
691
|
'agent_board.subscribe_callback_endpoint(uuid,uuid,text,text,uuid,jsonb) -> _resolved_actor_agent_id',
|
|
679
692
|
'agent_board.unblock_board_inviter(uuid,uuid,uuid) -> _resolved_actor_agent_id',
|
|
@@ -682,7 +695,7 @@ select is( -- pgtap-allow-raise-checked
|
|
|
682
695
|
'agent_board.upsert_delegation_policy(uuid,text,jsonb,integer,interval,boolean) -> _resolved_actor_agent_id',
|
|
683
696
|
'agent_board.verify_callback_endpoint(uuid,uuid,jsonb) -> _resolved_actor_agent_id'
|
|
684
697
|
]::text[],
|
|
685
|
-
'#325 HALF B, part 1: exactly these
|
|
698
|
+
'#325 HALF B, part 1: exactly these 15 writers reach NO shared authz predicate and raise no 42501 of their own, and each NAMES the raising resolver it relies on — 14 the session resolver, 1 the platform-admin one; revoke_agent now refuses an unresolved actor in its own body; a new ungated writer joins this set, and a member that loses or switches its resolver reds here');
|
|
686
699
|
|
|
687
700
|
-- WEC-9. The union, and the only assertion here that is a claim about the WHOLE class rather than
|
|
688
701
|
-- about a category. Not spelled over the CLOSURE for 42501: that form is satisfied by 59 of 59
|
|
@@ -875,7 +888,7 @@ select is(
|
|
|
875
888
|
cross join unnest(array['INSERT', 'UPDATE', 'DELETE', 'TRUNCATE']) as pv
|
|
876
889
|
where has_table_privilege(r, t.reloid, pv)),
|
|
877
890
|
array[]::text[],
|
|
878
|
-
'#325: NEITHER authenticated NOR anon holds a direct write privilege on ANY of the
|
|
891
|
+
'#325: NEITHER authenticated NOR anon holds a direct write privilege on ANY of the 40 class relations — so for those two roles every write goes through some agent_board function; WEC-3 is what says which');
|
|
879
892
|
|
|
880
893
|
-- WEC-18. The arm that DOES NOT hold, pinned as an exact set rather than omitted. service_role
|
|
881
894
|
-- writes thirteen of these relations directly, with no function and no body — the structural
|
|
@@ -900,6 +913,7 @@ select is(
|
|
|
900
913
|
'INSERT:board_invite_redemptions',
|
|
901
914
|
'INSERT:board_invite_tokens',
|
|
902
915
|
'INSERT:board_membership_events',
|
|
916
|
+
'INSERT:delegation_grants',
|
|
903
917
|
'INSERT:fleet_harness_registrations',
|
|
904
918
|
'INSERT:fleet_machine_agents',
|
|
905
919
|
'INSERT:fleet_machines',
|
|
@@ -911,6 +925,7 @@ select is(
|
|
|
911
925
|
'UPDATE:board_authority_ceilings',
|
|
912
926
|
'UPDATE:board_invite_redemptions',
|
|
913
927
|
'UPDATE:board_invite_tokens',
|
|
928
|
+
'UPDATE:delegation_grants',
|
|
914
929
|
'UPDATE:fleet_harness_registrations',
|
|
915
930
|
'UPDATE:fleet_machine_agents',
|
|
916
931
|
'UPDATE:fleet_machines',
|
|
@@ -919,7 +934,7 @@ select is(
|
|
|
919
934
|
'UPDATE:fleet_revocation_events',
|
|
920
935
|
'UPDATE:fleet_trust_domains'
|
|
921
936
|
]::text[],
|
|
922
|
-
'#325: service_role holds direct DML on
|
|
937
|
+
'#325: service_role holds direct DML on FOURTEEN of the 40 class relations — grants newly enter this class through readmission, not through a new grant; the exact privilege set bounds the hole');
|
|
923
938
|
|
|
924
939
|
-- WEC-19. The rule-1-correct arm. WEC-17 and WEC-18 are hand lists of three role names between
|
|
925
940
|
-- them, so an INSERT granted to a brand-new role self-names in NEITHER. This reads the ACL itself.
|
|
@@ -952,7 +967,7 @@ select ok(
|
|
|
952
967
|
where c.relowner <> 'postgres'::regrole) = 0
|
|
953
968
|
and has_table_privilege('postgres', 'agent_board.threads', 'INSERT')
|
|
954
969
|
and has_table_privilege('postgres', 'agent_board.threads', 'DELETE'),
|
|
955
|
-
'#325: postgres OWNS every one of the
|
|
970
|
+
'#325: postgres OWNS every one of the 40 class relations (pg_class.relowner, not inferred from a privilege) and holds writes on them — so the WEC-19 exclusion is a fact about ownership, not a carve-out');
|
|
956
971
|
|
|
957
972
|
-- WEC-21. The over-revoke guard. A file that only ever asserts absence would call a schema with
|
|
958
973
|
-- every privilege revoked a success.
|
|
@@ -1006,12 +1021,13 @@ select is(
|
|
|
1006
1021
|
'agent_board.fleet_trust_domains',
|
|
1007
1022
|
'agent_board.inbox_items',
|
|
1008
1023
|
'agent_board.messages',
|
|
1024
|
+
'agent_board.session_identities',
|
|
1009
1025
|
'agent_board.task_events',
|
|
1010
1026
|
'agent_board.tasks',
|
|
1011
1027
|
'agent_board.threads',
|
|
1012
1028
|
'auth.users'
|
|
1013
1029
|
]::text[],
|
|
1014
|
-
'#325: deleting a row in one of these
|
|
1030
|
+
'#325: deleting a row in one of these 20 parents CASCADES or SET NULLs into a class relation — a write path with no privilege check and no function body; one parent is auth.users, i.e. outside agent_board entirely');
|
|
1015
1031
|
|
|
1016
1032
|
-- WEC-23. The edge count. This IS a bare count and the hazard is stated rather than left for a
|
|
1017
1033
|
-- reviewer: the routine response to a red count is to bump it, which absorbs a new cascade edge
|
|
@@ -1023,8 +1039,8 @@ select is(
|
|
|
1023
1039
|
from _wec_class_tables t
|
|
1024
1040
|
join pg_constraint con on con.conrelid = t.reloid
|
|
1025
1041
|
where con.contype = 'f' and con.confdeltype in ('c', 'n', 'd')),
|
|
1026
|
-
'
|
|
1027
|
-
'#325:
|
|
1042
|
+
'92',
|
|
1043
|
+
'#325: 92 writing referential actions (78 CASCADE + 14 SET NULL) reach the 40 class relations — the four SIDSCHEMA class additions are positively pinned in WEC-30');
|
|
1028
1044
|
|
|
1029
1045
|
-- ===========================================================================================
|
|
1030
1046
|
-- WEC-24/25 — THE CROSS-CHECK (Consiliency/message-board#416 / #417 / #424, plan change 9).
|
|
@@ -1138,6 +1154,49 @@ select is(
|
|
|
1138
1154
|
'mark_retention_metadata',
|
|
1139
1155
|
'WEC-25 (change 9): the plpgsql bodies WEC-24 skips for dynamic SQL are exactly these — mark_retention_metadata writes board_memberships through format(), which neither write_re nor the parser can see; a second dynamic writer fails here by name');
|
|
1140
1156
|
|
|
1157
|
+
-- WEC-26..29: raw auth.uid() for rename is a human-ownership check, not agent
|
|
1158
|
+
-- self-authentication or a service-role assertion. Exercise the real API role.
|
|
1159
|
+
create temp table _wec_owner(user_id uuid, original_handle text) on commit drop;
|
|
1160
|
+
do $$ declare u uuid; begin
|
|
1161
|
+
u := public.ensure_github_user('wec-owner-' || gen_random_uuid(), 'wec-owner@example.test',
|
|
1162
|
+
'wec-owner-' || gen_random_uuid(), 'WEC owner');
|
|
1163
|
+
insert into agent_board.agents(agent_type, handle, display_name, status, auth_user_id, owner_user_id)
|
|
1164
|
+
values ('human', 'wec-human-' || gen_random_uuid(), 'WEC owner', 'active', u, u);
|
|
1165
|
+
update agent_board.agents set owner_user_id = u
|
|
1166
|
+
where id = (select agent_id from _wec_agent where label = 'a');
|
|
1167
|
+
insert into _wec_owner select u, handle from agent_board.agents
|
|
1168
|
+
where id = (select agent_id from _wec_agent where label = 'a');
|
|
1169
|
+
end $$;
|
|
1170
|
+
grant select on _wec_owner, _wec_agent to authenticated;
|
|
1171
|
+
grant usage on schema extensions to authenticated;
|
|
1172
|
+
set local role authenticated;
|
|
1173
|
+
select set_config('request.jwt.claim.role', 'authenticated', true);
|
|
1174
|
+
select set_config('request.jwt.claim.sub', (select user_id from _wec_owner)::text, true);
|
|
1175
|
+
select lives_ok($$select agent_board.rename_agent((select agent_id from _wec_agent where label = 'a'), 'WEC renamed')$$,
|
|
1176
|
+
'WEC-26: active authenticated human owner can rename its agent');
|
|
1177
|
+
reset role;
|
|
1178
|
+
select is((select display_name || '/' || (handle = original_handle)::text
|
|
1179
|
+
from agent_board.agents cross join _wec_owner where id = (select agent_id from _wec_agent where label = 'a')),
|
|
1180
|
+
'WEC renamed/true', 'WEC-27: raw-human rename writes only the intended display name and preserves handle');
|
|
1181
|
+
-- The nearest invalid owner: ownership matches the agent's auth user, but that
|
|
1182
|
+
-- principal is not a human. A stranger would hide loss of the human predicate.
|
|
1183
|
+
update agent_board.agents set owner_user_id = (select user_id from _wec_agent where label = 'a')
|
|
1184
|
+
where id = (select agent_id from _wec_agent where label = 'a');
|
|
1185
|
+
set local role authenticated;
|
|
1186
|
+
select set_config('request.jwt.claim.sub', (select user_id from _wec_agent where label = 'a')::text, true);
|
|
1187
|
+
select throws_ok($$select agent_board.rename_agent((select agent_id from _wec_agent where label = 'a'), 'WEC agent renamed')$$,
|
|
1188
|
+
'42501', 'agent rename requires the human owner', 'WEC-28: the agent credential is not its human owner');
|
|
1189
|
+
reset role;
|
|
1190
|
+
select is((select display_name from agent_board.agents where id = (select agent_id from _wec_agent where label = 'a')),
|
|
1191
|
+
'WEC renamed', 'WEC-29: refused agent rename leaves the human-owned state unchanged');
|
|
1192
|
+
select is((select array_agg(c.conname::text || ':' || c.confdeltype::text order by c.conname::text)
|
|
1193
|
+
from _wec_class_tables t join pg_constraint c on c.conrelid = t.reloid
|
|
1194
|
+
where t.relname in ('delegation_grants', 'session_identities', 'session_id_aliases')
|
|
1195
|
+
and c.contype = 'f' and c.confdeltype in ('c', 'n', 'd')),
|
|
1196
|
+
array['delegation_grants_child_agent_id_fkey:c', 'delegation_grants_root_agent_id_fkey:c',
|
|
1197
|
+
'session_id_aliases_identity_agent_id_fkey:c', 'session_identities_agent_id_fkey:c']::text[],
|
|
1198
|
+
'WEC-30: all four newly class-visible referential writes are the intended principal/grant/identity/alias cascades');
|
|
1199
|
+
|
|
1141
1200
|
select * from finish();
|
|
1142
1201
|
|
|
1143
1202
|
rollback;
|
|
@@ -559,6 +559,15 @@
|
|
|
559
559
|
"authenticated": false
|
|
560
560
|
}
|
|
561
561
|
},
|
|
562
|
+
{
|
|
563
|
+
"name": "_mint_fleet_agent_session_legacy",
|
|
564
|
+
"signature": "_mint_fleet_agent_session_legacy(p_challenge_id uuid, p_nonce text, p_signing_key_id uuid, p_agent_id uuid, p_max_ttl_seconds integer)",
|
|
565
|
+
"executable_by": {
|
|
566
|
+
"anon": false,
|
|
567
|
+
"service_role": false,
|
|
568
|
+
"authenticated": false
|
|
569
|
+
}
|
|
570
|
+
},
|
|
562
571
|
{
|
|
563
572
|
"name": "_next_callback_attempt_number",
|
|
564
573
|
"signature": "_next_callback_attempt_number(p_outbox_event_id uuid)",
|
|
@@ -775,6 +784,15 @@
|
|
|
775
784
|
"authenticated": false
|
|
776
785
|
}
|
|
777
786
|
},
|
|
787
|
+
{
|
|
788
|
+
"name": "_revoke_session_identity_family",
|
|
789
|
+
"signature": "_revoke_session_identity_family(p_agent_id uuid, p_actor uuid, p_reason text)",
|
|
790
|
+
"executable_by": {
|
|
791
|
+
"anon": false,
|
|
792
|
+
"service_role": true,
|
|
793
|
+
"authenticated": false
|
|
794
|
+
}
|
|
795
|
+
},
|
|
778
796
|
{
|
|
779
797
|
"name": "_role_rank",
|
|
780
798
|
"signature": "_role_rank(p_role text)",
|
|
@@ -793,6 +811,105 @@
|
|
|
793
811
|
"authenticated": false
|
|
794
812
|
}
|
|
795
813
|
},
|
|
814
|
+
{
|
|
815
|
+
"name": "_session_identity_agent_lineage",
|
|
816
|
+
"signature": "_session_identity_agent_lineage()",
|
|
817
|
+
"executable_by": {
|
|
818
|
+
"anon": false,
|
|
819
|
+
"service_role": true,
|
|
820
|
+
"authenticated": false
|
|
821
|
+
}
|
|
822
|
+
},
|
|
823
|
+
{
|
|
824
|
+
"name": "_session_identity_ancestor_actor",
|
|
825
|
+
"signature": "_session_identity_ancestor_actor(p_identity_agent_id uuid)",
|
|
826
|
+
"executable_by": {
|
|
827
|
+
"anon": false,
|
|
828
|
+
"service_role": true,
|
|
829
|
+
"authenticated": false
|
|
830
|
+
}
|
|
831
|
+
},
|
|
832
|
+
{
|
|
833
|
+
"name": "_session_identity_ancestor_ceiling",
|
|
834
|
+
"signature": "_session_identity_ancestor_ceiling(p_agent_id uuid)",
|
|
835
|
+
"executable_by": {
|
|
836
|
+
"anon": false,
|
|
837
|
+
"service_role": false,
|
|
838
|
+
"authenticated": false
|
|
839
|
+
}
|
|
840
|
+
},
|
|
841
|
+
{
|
|
842
|
+
"name": "_session_identity_check_limits",
|
|
843
|
+
"signature": "_session_identity_check_limits(p_root uuid, p_parent uuid, p_reactivation uuid)",
|
|
844
|
+
"executable_by": {
|
|
845
|
+
"anon": false,
|
|
846
|
+
"service_role": false,
|
|
847
|
+
"authenticated": false
|
|
848
|
+
}
|
|
849
|
+
},
|
|
850
|
+
{
|
|
851
|
+
"name": "_session_identity_has_human_owner",
|
|
852
|
+
"signature": "_session_identity_has_human_owner(p_root_agent_id uuid)",
|
|
853
|
+
"executable_by": {
|
|
854
|
+
"anon": false,
|
|
855
|
+
"service_role": true,
|
|
856
|
+
"authenticated": false
|
|
857
|
+
}
|
|
858
|
+
},
|
|
859
|
+
{
|
|
860
|
+
"name": "_session_identity_kind_immutable",
|
|
861
|
+
"signature": "_session_identity_kind_immutable()",
|
|
862
|
+
"executable_by": {
|
|
863
|
+
"anon": false,
|
|
864
|
+
"service_role": true,
|
|
865
|
+
"authenticated": false
|
|
866
|
+
}
|
|
867
|
+
},
|
|
868
|
+
{
|
|
869
|
+
"name": "_session_identity_lease_live",
|
|
870
|
+
"signature": "_session_identity_lease_live(p_identity uuid)",
|
|
871
|
+
"executable_by": {
|
|
872
|
+
"anon": false,
|
|
873
|
+
"service_role": true,
|
|
874
|
+
"authenticated": false
|
|
875
|
+
}
|
|
876
|
+
},
|
|
877
|
+
{
|
|
878
|
+
"name": "_session_identity_lineage",
|
|
879
|
+
"signature": "_session_identity_lineage()",
|
|
880
|
+
"executable_by": {
|
|
881
|
+
"anon": false,
|
|
882
|
+
"service_role": true,
|
|
883
|
+
"authenticated": false
|
|
884
|
+
}
|
|
885
|
+
},
|
|
886
|
+
{
|
|
887
|
+
"name": "_session_identity_owner",
|
|
888
|
+
"signature": "_session_identity_owner(p_identity_agent_id uuid)",
|
|
889
|
+
"executable_by": {
|
|
890
|
+
"anon": false,
|
|
891
|
+
"service_role": true,
|
|
892
|
+
"authenticated": false
|
|
893
|
+
}
|
|
894
|
+
},
|
|
895
|
+
{
|
|
896
|
+
"name": "_session_identity_read_allowed",
|
|
897
|
+
"signature": "_session_identity_read_allowed(p_identity_agent_id uuid)",
|
|
898
|
+
"executable_by": {
|
|
899
|
+
"anon": false,
|
|
900
|
+
"service_role": true,
|
|
901
|
+
"authenticated": false
|
|
902
|
+
}
|
|
903
|
+
},
|
|
904
|
+
{
|
|
905
|
+
"name": "_session_identity_revocation_actor",
|
|
906
|
+
"signature": "_session_identity_revocation_actor(p_identity_agent_id uuid)",
|
|
907
|
+
"executable_by": {
|
|
908
|
+
"anon": false,
|
|
909
|
+
"service_role": false,
|
|
910
|
+
"authenticated": false
|
|
911
|
+
}
|
|
912
|
+
},
|
|
796
913
|
{
|
|
797
914
|
"name": "_signed_write_actor_id",
|
|
798
915
|
"signature": "_signed_write_actor_id(p_payload jsonb, p_gateway_decision jsonb, p_actor_field text)",
|
|
@@ -883,6 +1000,15 @@
|
|
|
883
1000
|
"authenticated": true
|
|
884
1001
|
}
|
|
885
1002
|
},
|
|
1003
|
+
{
|
|
1004
|
+
"name": "approve_identity_state",
|
|
1005
|
+
"signature": "approve_identity_state(p_identity_agent_id uuid, p_risky_digest text, p_recorded_fingerprint jsonb)",
|
|
1006
|
+
"executable_by": {
|
|
1007
|
+
"anon": false,
|
|
1008
|
+
"service_role": true,
|
|
1009
|
+
"authenticated": false
|
|
1010
|
+
}
|
|
1011
|
+
},
|
|
886
1012
|
{
|
|
887
1013
|
"name": "block_board_inviter",
|
|
888
1014
|
"signature": "block_board_inviter(p_board_id uuid, p_inviter_agent_id uuid, p_target_agent_id uuid, p_metadata jsonb)",
|
|
@@ -1108,6 +1234,15 @@
|
|
|
1108
1234
|
"authenticated": true
|
|
1109
1235
|
}
|
|
1110
1236
|
},
|
|
1237
|
+
{
|
|
1238
|
+
"name": "get_session_identity_state",
|
|
1239
|
+
"signature": "get_session_identity_state(p_identity_agent_id uuid)",
|
|
1240
|
+
"executable_by": {
|
|
1241
|
+
"anon": false,
|
|
1242
|
+
"service_role": true,
|
|
1243
|
+
"authenticated": true
|
|
1244
|
+
}
|
|
1245
|
+
},
|
|
1111
1246
|
{
|
|
1112
1247
|
"name": "grant_board_role",
|
|
1113
1248
|
"signature": "grant_board_role(p_board_id uuid, p_agent_id uuid, p_grantee_role text, p_grantor_agent_id uuid)",
|
|
@@ -1126,6 +1261,15 @@
|
|
|
1126
1261
|
"authenticated": true
|
|
1127
1262
|
}
|
|
1128
1263
|
},
|
|
1264
|
+
{
|
|
1265
|
+
"name": "heartbeat_session_identity",
|
|
1266
|
+
"signature": "heartbeat_session_identity(p_identity_agent_id uuid)",
|
|
1267
|
+
"executable_by": {
|
|
1268
|
+
"anon": false,
|
|
1269
|
+
"service_role": false,
|
|
1270
|
+
"authenticated": true
|
|
1271
|
+
}
|
|
1272
|
+
},
|
|
1129
1273
|
{
|
|
1130
1274
|
"name": "invite_board_for_display",
|
|
1131
1275
|
"signature": "invite_board_for_display(p_code_sha256 text)",
|
|
@@ -1171,6 +1315,15 @@
|
|
|
1171
1315
|
"authenticated": true
|
|
1172
1316
|
}
|
|
1173
1317
|
},
|
|
1318
|
+
{
|
|
1319
|
+
"name": "link_session_alias",
|
|
1320
|
+
"signature": "link_session_alias(p_identity_agent_id uuid, p_identity_lease_epoch text, p_session_id text)",
|
|
1321
|
+
"executable_by": {
|
|
1322
|
+
"anon": false,
|
|
1323
|
+
"service_role": true,
|
|
1324
|
+
"authenticated": false
|
|
1325
|
+
}
|
|
1326
|
+
},
|
|
1174
1327
|
{
|
|
1175
1328
|
"name": "list_board_members",
|
|
1176
1329
|
"signature": "list_board_members(p_board_id uuid)",
|
|
@@ -1198,6 +1351,15 @@
|
|
|
1198
1351
|
"authenticated": true
|
|
1199
1352
|
}
|
|
1200
1353
|
},
|
|
1354
|
+
{
|
|
1355
|
+
"name": "list_session_children",
|
|
1356
|
+
"signature": "list_session_children(p_parent_agent_id uuid)",
|
|
1357
|
+
"executable_by": {
|
|
1358
|
+
"anon": false,
|
|
1359
|
+
"service_role": true,
|
|
1360
|
+
"authenticated": true
|
|
1361
|
+
}
|
|
1362
|
+
},
|
|
1201
1363
|
{
|
|
1202
1364
|
"name": "mark_read",
|
|
1203
1365
|
"signature": "mark_read(p_thread_id uuid, p_agent_id uuid, p_last_read_message_sequence bigint)",
|
|
@@ -1218,7 +1380,7 @@
|
|
|
1218
1380
|
},
|
|
1219
1381
|
{
|
|
1220
1382
|
"name": "mint_delegated_child",
|
|
1221
|
-
"signature": "mint_delegated_child(p_root_agent_id uuid, p_child_slug text, p_requested_scopes jsonb, p_child_public_key text, p_ttl interval, p_self_service boolean)",
|
|
1383
|
+
"signature": "mint_delegated_child(p_root_agent_id uuid, p_child_slug text, p_requested_scopes jsonb, p_child_public_key text, p_ttl interval, p_self_service boolean, p_session_harness text, p_session_id text, p_minter_lease_epoch text, p_requested_rooms jsonb, p_fingerprint jsonb, p_forked_from uuid)",
|
|
1222
1384
|
"executable_by": {
|
|
1223
1385
|
"anon": false,
|
|
1224
1386
|
"service_role": true,
|
|
@@ -1227,7 +1389,7 @@
|
|
|
1227
1389
|
},
|
|
1228
1390
|
{
|
|
1229
1391
|
"name": "mint_fleet_agent_session",
|
|
1230
|
-
"signature": "mint_fleet_agent_session(p_challenge_id uuid, p_nonce text, p_signing_key_id uuid, p_agent_id uuid, p_max_ttl_seconds integer)",
|
|
1392
|
+
"signature": "mint_fleet_agent_session(p_challenge_id uuid, p_nonce text, p_signing_key_id uuid, p_agent_id uuid, p_max_ttl_seconds integer, p_holder_secret text, p_session_id text)",
|
|
1231
1393
|
"executable_by": {
|
|
1232
1394
|
"anon": false,
|
|
1233
1395
|
"service_role": true,
|
|
@@ -1315,6 +1477,15 @@
|
|
|
1315
1477
|
"authenticated": false
|
|
1316
1478
|
}
|
|
1317
1479
|
},
|
|
1480
|
+
{
|
|
1481
|
+
"name": "readmit_session_identity",
|
|
1482
|
+
"signature": "readmit_session_identity(p_identity_agent_id uuid, p_child_slug text, p_child_public_key text, p_requested_scopes jsonb, p_requested_rooms jsonb, p_ttl interval)",
|
|
1483
|
+
"executable_by": {
|
|
1484
|
+
"anon": false,
|
|
1485
|
+
"service_role": false,
|
|
1486
|
+
"authenticated": true
|
|
1487
|
+
}
|
|
1488
|
+
},
|
|
1318
1489
|
{
|
|
1319
1490
|
"name": "reap_expired_enroll_rate_events",
|
|
1320
1491
|
"signature": "reap_expired_enroll_rate_events(p_older_than interval)",
|
|
@@ -1396,6 +1567,15 @@
|
|
|
1396
1567
|
"authenticated": false
|
|
1397
1568
|
}
|
|
1398
1569
|
},
|
|
1570
|
+
{
|
|
1571
|
+
"name": "record_session_identity_state",
|
|
1572
|
+
"signature": "record_session_identity_state(p_identity_agent_id uuid, p_fingerprint jsonb)",
|
|
1573
|
+
"executable_by": {
|
|
1574
|
+
"anon": false,
|
|
1575
|
+
"service_role": true,
|
|
1576
|
+
"authenticated": false
|
|
1577
|
+
}
|
|
1578
|
+
},
|
|
1399
1579
|
{
|
|
1400
1580
|
"name": "record_signing_key_proof_result",
|
|
1401
1581
|
"signature": "record_signing_key_proof_result(p_challenge_id uuid, p_agent_id uuid, p_key_id text, p_verified boolean, p_failure_class text, p_metadata jsonb)",
|
|
@@ -1450,6 +1630,15 @@
|
|
|
1450
1630
|
"authenticated": true
|
|
1451
1631
|
}
|
|
1452
1632
|
},
|
|
1633
|
+
{
|
|
1634
|
+
"name": "rename_agent",
|
|
1635
|
+
"signature": "rename_agent(p_agent_id uuid, p_display_name text)",
|
|
1636
|
+
"executable_by": {
|
|
1637
|
+
"anon": false,
|
|
1638
|
+
"service_role": false,
|
|
1639
|
+
"authenticated": true
|
|
1640
|
+
}
|
|
1641
|
+
},
|
|
1453
1642
|
{
|
|
1454
1643
|
"name": "renew_claim",
|
|
1455
1644
|
"signature": "renew_claim(p_lease_token uuid, p_lease_expires_at timestamp with time zone)",
|
|
@@ -1468,6 +1657,15 @@
|
|
|
1468
1657
|
"authenticated": false
|
|
1469
1658
|
}
|
|
1470
1659
|
},
|
|
1660
|
+
{
|
|
1661
|
+
"name": "renew_session_identity",
|
|
1662
|
+
"signature": "renew_session_identity(p_identity_agent_id uuid, p_risky_digest text)",
|
|
1663
|
+
"executable_by": {
|
|
1664
|
+
"anon": false,
|
|
1665
|
+
"service_role": true,
|
|
1666
|
+
"authenticated": false
|
|
1667
|
+
}
|
|
1668
|
+
},
|
|
1471
1669
|
{
|
|
1472
1670
|
"name": "request_join_board",
|
|
1473
1671
|
"signature": "request_join_board(p_board_id uuid, p_agent_id uuid, p_metadata jsonb)",
|
|
@@ -1585,6 +1783,15 @@
|
|
|
1585
1783
|
"authenticated": true
|
|
1586
1784
|
}
|
|
1587
1785
|
},
|
|
1786
|
+
{
|
|
1787
|
+
"name": "revoke_session_identity",
|
|
1788
|
+
"signature": "revoke_session_identity(p_identity_agent_id uuid)",
|
|
1789
|
+
"executable_by": {
|
|
1790
|
+
"anon": false,
|
|
1791
|
+
"service_role": false,
|
|
1792
|
+
"authenticated": true
|
|
1793
|
+
}
|
|
1794
|
+
},
|
|
1588
1795
|
{
|
|
1589
1796
|
"name": "rotate_agent_token",
|
|
1590
1797
|
"signature": "rotate_agent_token(p_agent_id uuid)",
|
|
@@ -1666,6 +1873,15 @@
|
|
|
1666
1873
|
"authenticated": true
|
|
1667
1874
|
}
|
|
1668
1875
|
},
|
|
1876
|
+
{
|
|
1877
|
+
"name": "set_board_member_label",
|
|
1878
|
+
"signature": "set_board_member_label(p_board_id uuid, p_agent_id uuid, p_label text)",
|
|
1879
|
+
"executable_by": {
|
|
1880
|
+
"anon": false,
|
|
1881
|
+
"service_role": false,
|
|
1882
|
+
"authenticated": true
|
|
1883
|
+
}
|
|
1884
|
+
},
|
|
1669
1885
|
{
|
|
1670
1886
|
"name": "set_board_role_gate",
|
|
1671
1887
|
"signature": "set_board_role_gate(p_board_id uuid, p_enforced boolean)",
|