@consiliency/agent-board-schema 1.28.0 → 1.38.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 +40 -0
- package/migrations/20260910000100_agent_board_ceiling_lock_comment_truth.sql +89 -0
- package/migrations/20260911000100_agent_board_ledger_revoked_board_creation.sql +330 -0
- package/migrations/20260912000100_agent_board_receipt_subject_gate.sql +348 -0
- package/migrations/20260913000100_agent_board_task_thread_lock_order.sql +292 -0
- package/migrations/20260914000100_agent_board_claim_subject_gate.sql +500 -0
- package/migrations/20260915000100_agent_board_fedsession_stored_identity_gate.sql +353 -0
- package/migrations/20260916000100_agent_board_federated_identity_injective_slug.sql +1646 -0
- package/migrations/20260917000100_agent_board_invite_no_downgrade.sql +398 -0
- package/migrations/20260918000100_agent_board_signed_write_enforced_repoint.sql +139 -0
- package/migrations/20260919000100_agent_board_signed_write_model_key.sql +107 -0
- package/package.json +1 -1
- package/schema-manifest.json +93 -3
- package/src/deployment-drift-script.test.mjs +424 -0
- package/src/deployment-drift.test.mjs +301 -0
- package/src/tooling.test.mjs +83 -2
- package/tests/agent_board_atomic_fleet_onboarding.test.sql +144 -29
- package/tests/agent_board_bundle_endpoint_compat.test.sql +73 -18
- package/tests/agent_board_claim_subject_gate.test.sql +1025 -0
- package/tests/agent_board_consent_substrate.test.sql +8 -1
- package/tests/agent_board_enroll_resumption.test.sql +7 -1
- package/tests/agent_board_federated_identity_injective_slug.test.sql +388 -0
- package/tests/agent_board_fedsession.test.sql +17 -2
- package/tests/agent_board_fedsession_stored_identity_gate.test.sql +606 -0
- package/tests/agent_board_fk_lock_edges.test.sql +422 -0
- package/tests/agent_board_invite_no_downgrade.test.sql +689 -0
- package/tests/agent_board_ledger_authority.test.sql +142 -71
- package/tests/agent_board_receipt_subject_gate.test.sql +624 -0
- package/tests/agent_board_signed_write_enforced.test.sql +366 -0
- package/tests/agent_board_signer_lifecycle.test.sql +23 -6
- package/tests/agent_board_source_strip_helper.test.sql +256 -1
- package/tests/agent_board_task_thread_lock_order.test.sql +337 -0
- package/tests/agent_board_write_enforcement_class.test.sql +1016 -0
- package/tests/catalog/p_metadata_parameters.json +12 -0
- package/tests/fixtures/isolation-substrate.sql +1 -1
- package/tests/fixtures/test-prereqs.sql +442 -11
- package/tests/isolation/expected/ledger_authority_revoke.out +219 -1
- package/tests/isolation/expected/task_thread_lock_order.out +203 -0
- package/tests/isolation/specs/enroll_identity_board_owner_lock_order.spec +5 -4
- package/tests/isolation/specs/fedsession_provider_absent_owner_lock.spec +4 -4
- package/tests/isolation/specs/ledger_authority_revoke.spec +115 -0
- package/tests/isolation/specs/task_thread_lock_order.spec +197 -0
- package/tests/seeds/20260916000100_agent_board_federated_identity_injective_slug.sql.pre.sql +196 -0
|
@@ -28,15 +28,28 @@
|
|
|
28
28
|
-- is the failure mode throws_like alone cannot see.
|
|
29
29
|
-- * The class assertions in section 9 are catalog-derived (pg_proc + stripped_body), not a
|
|
30
30
|
-- list written here, so a NEW authority write that forgets the gate fails and NAMES ITSELF
|
|
31
|
-
-- (CLAUDE.md rule 1).
|
|
31
|
+
-- (CLAUDE.md rule 1). Each remaining exemption is asserted POSITIVELY — by properties it
|
|
32
32
|
-- actually has — never by the absence of a match.
|
|
33
|
+
--
|
|
34
|
+
-- #280 (20260911000100) AMENDS THIS FILE'S CLAIM. `create_board` was #276's ONE
|
|
35
|
+
-- authenticated-callable exemption, and its residual was asserted here as BEHAVIOUR — a
|
|
36
|
+
-- ledger-revoked agent COULD create a board and be seeded owner — precisely so that closing #280
|
|
37
|
+
-- would be a deliberate test change rather than a silent behaviour change. The owner ratified
|
|
38
|
+
-- "revoked means revoked", so those assertions are FLIPPED in section 11 and the EXEMPTION B
|
|
39
|
+
-- block that licensed them is DELETED rather than left standing: its three properties are still
|
|
40
|
+
-- true, but they exist to license an exemption that no longer exists, and a live assertion that
|
|
41
|
+
-- licenses nothing is this repo's recorded failure shape. The exemption list is now THREE and
|
|
42
|
+
-- the ledger-consult set is now SIX; both are derived from pg_catalog on every run, so those two
|
|
43
|
+
-- edits must agree with the shipped schema or the difference NAMES create_board.
|
|
33
44
|
|
|
34
45
|
create extension if not exists pgtap with schema extensions;
|
|
35
46
|
set search_path = extensions, public, agent_board;
|
|
36
47
|
|
|
37
48
|
begin;
|
|
38
49
|
|
|
39
|
-
|
|
50
|
+
-- 88 at #276; #280 deletes 7 (EXEMPTION B1/B2/B3, the three RESIDUAL assertions, and a fourth
|
|
51
|
+
-- residual companion in section 10 that named only the slug) and adds 10 in section 11.
|
|
52
|
+
select plan(91);
|
|
40
53
|
|
|
41
54
|
create function pg_temp.claims(p_sub text) returns void language plpgsql as $$
|
|
42
55
|
begin
|
|
@@ -544,13 +557,17 @@ select is(
|
|
|
544
557
|
where n.nspname = 'agent_board'
|
|
545
558
|
and p.proname not in ('_assert_actor_not_fleet_revoked', '_actor_fleet_revoked')
|
|
546
559
|
and agent_board_test.stripped_body(p.oid) ~ '\m(_assert_actor_not_fleet_revoked|_actor_fleet_revoked)\s*\('),
|
|
547
|
-
'_redeem_unbounded_invite_for_agent,create_invite_link,grant_board_role,'
|
|
560
|
+
'_redeem_unbounded_invite_for_agent,create_board,create_invite_link,grant_board_role,'
|
|
548
561
|
|| 'set_board_authority_ceiling,set_board_role_gate',
|
|
549
|
-
'the functions that consult the fleet revocation ledger are exactly these
|
|
562
|
+
'the functions that consult the fleet revocation ledger are exactly these six (#280 added '
|
|
563
|
+
'create_board)');
|
|
550
564
|
|
|
551
|
-
-- The gate proper: the two sets must differ by EXACTLY the
|
|
565
|
+
-- The gate proper: the two sets must differ by EXACTLY the three asserted exemptions, and any
|
|
552
566
|
-- other member of the difference is NAMED in the failure. Each excluded name is licensed by a
|
|
553
|
-
-- positive disposition below, never by the absence of a match.
|
|
567
|
+
-- positive disposition below, never by the absence of a match. create_board was the fourth
|
|
568
|
+
-- until #280 gated it; removing it from this list is what makes the migration's claim checkable
|
|
569
|
+
-- rather than asserted — if the gate were dropped from the function, create_board reappears in
|
|
570
|
+
-- the difference and this assertion prints its name.
|
|
554
571
|
select is(
|
|
555
572
|
(select string_agg(x.proname || ':' || x.why, '; ' order by x.proname)
|
|
556
573
|
from (
|
|
@@ -562,8 +579,8 @@ select is(
|
|
|
562
579
|
from pg_proc p join pg_namespace n on n.oid = p.pronamespace
|
|
563
580
|
where n.nspname = 'agent_board'
|
|
564
581
|
and p.proname not in (
|
|
565
|
-
-- the
|
|
566
|
-
'_upsert_board_membership_state',
|
|
582
|
+
-- the three asserted exemptions (create_board was the fourth until #280)...
|
|
583
|
+
'_upsert_board_membership_state',
|
|
567
584
|
'_fedsession_autojoin_default_board', 'bootstrap_board_owner_memberships',
|
|
568
585
|
-- ...and the two helpers, which ARE the gate rather than users of it
|
|
569
586
|
'_assert_actor_not_fleet_revoked', '_actor_fleet_revoked')
|
|
@@ -665,63 +682,12 @@ select is(
|
|
|
665
682
|
'EXEMPTION A4: EVERY caller of _upsert_board_membership_state takes EXACTLY these parameters '
|
|
666
683
|
'— not one declares a role, so "no caller can hand it one" is checked rather than argued');
|
|
667
684
|
|
|
668
|
-
-- ---------------------------------------------------------------------------
|
|
669
|
-
-- EXEMPTION B — create_board, the ONE authenticated-callable member of the class.
|
|
670
|
-
-- ---------------------------------------------------------------------------
|
|
671
|
-
select is(
|
|
672
|
-
(select string_agg(pg_get_function_identity_arguments(p.oid), ' | ' order by p.oid)
|
|
673
|
-
from pg_proc p join pg_namespace n on n.oid = p.pronamespace
|
|
674
|
-
where n.nspname = 'agent_board' and p.proname = 'create_board'),
|
|
675
|
-
'p_created_by_agent_id uuid, p_slug text, p_name text, p_description text, p_metadata jsonb, '
|
|
676
|
-
|| 'p_visibility text',
|
|
677
|
-
'EXEMPTION B1: create_board takes EXACTLY these parameters — no role among them, and no '
|
|
678
|
-
'overload carrying one, so the owner seat it writes is a literal and not a caller choice');
|
|
679
|
-
|
|
680
|
-
select ok(
|
|
681
|
-
agent_board_test.stripped_body('agent_board.create_board(uuid,text,text,text,jsonb,text)'::regprocedure, true)
|
|
682
|
-
like '%values (v_board.id, v_board.created_by_agent_id, ''joined'', ''owner'', v_board.created_by_agent_id)%',
|
|
683
|
-
'EXEMPTION B2: the seat it writes is the literal owner for the board OWN created_by_agent_id '
|
|
684
|
-
'— the resolved actor, seeding itself on a board it just inserted');
|
|
685
|
-
|
|
686
|
-
select ok(
|
|
687
|
-
agent_board_test.stripped_body('agent_board.create_board(uuid,text,text,text,jsonb,text)'::regprocedure, true)
|
|
688
|
-
like '%board slug already in use%'
|
|
689
|
-
and strpos(agent_board_test.stripped_body('agent_board.create_board(uuid,text,text,text,jsonb,text)'::regprocedure, true),
|
|
690
|
-
'update agent_board.boards as b')
|
|
691
|
-
< strpos(agent_board_test.stripped_body('agent_board.create_board(uuid,text,text,text,jsonb,text)'::regprocedure, true),
|
|
692
|
-
'insert into agent_board.board_memberships'),
|
|
693
|
-
'EXEMPTION B3: the slug-COLLISION branch refuses a non-owner and updates the boards row '
|
|
694
|
-
'BEFORE the else-branch membership insert — the seat is on the fresh-board path only, so it '
|
|
695
|
-
'cannot elevate a membership on a pre-existing board');
|
|
696
|
-
|
|
697
|
-
-- ...and the residual, asserted as BEHAVIOUR so #280 closing flips a test rather than a comment.
|
|
698
|
-
select pg_temp.claims('27600000-0000-0000-0000-000000000001');
|
|
699
|
-
|
|
700
|
-
select lives_ok(
|
|
701
|
-
$$create temp table _cb as select * from agent_board.create_board(
|
|
702
|
-
'27610000-0000-4000-8000-000000000001','k276-residual-board','K276 Residual Board')$$,
|
|
703
|
-
'RESIDUAL (#280): a ledger-revoked agent CAN still create a board and be seeded its owner');
|
|
704
|
-
|
|
705
|
-
select is(
|
|
706
|
-
(select bm.role from agent_board.board_memberships bm
|
|
707
|
-
join agent_board.boards b on b.id = bm.board_id
|
|
708
|
-
where b.slug = 'k276-residual-board'
|
|
709
|
-
and bm.agent_id = '27610000-0000-4000-8000-000000000001'),
|
|
710
|
-
'owner',
|
|
711
|
-
'RESIDUAL (#280): and the owner seat really landed — this is the manufacture-new-authority '
|
|
712
|
-
'gap #276 does NOT close, measured rather than described');
|
|
713
|
-
|
|
714
|
-
select throws_like(
|
|
715
|
-
$$select * from agent_board.grant_board_role(
|
|
716
|
-
(select id from agent_board.boards where slug = 'k276-residual-board'),
|
|
717
|
-
'27610000-0000-4000-8000-000000000002','admin')$$,
|
|
718
|
-
'%fleet_revoked:%',
|
|
719
|
-
'but the gate still holds on the board it just created: it cannot GRANT there either, even '
|
|
720
|
-
'as that board owner with no ceiling row');
|
|
721
|
-
|
|
722
685
|
-- ---------------------------------------------------------------------------
|
|
723
686
|
-- EXEMPTIONS C and D — the two remaining service_role-only seeders. (What used to be
|
|
724
|
-
-- exemption C, _redeem_unbounded_invite_for_agent, is now GATED — see section 10
|
|
687
|
+
-- exemption C, _redeem_unbounded_invite_for_agent, is now GATED — see section 10; what used to
|
|
688
|
+
-- be exemption B, create_board, is now GATED too — see section 11, which is where its old
|
|
689
|
+
-- RESIDUAL assertions were flipped. Its EXEMPTION B1/B2/B3 properties were deleted rather than
|
|
690
|
+
-- kept: they are still true, but they existed to license an exemption that no longer exists.)
|
|
725
691
|
-- ---------------------------------------------------------------------------
|
|
726
692
|
select is(
|
|
727
693
|
(select string_agg(p.proname || '=' ||
|
|
@@ -867,14 +833,14 @@ select is(
|
|
|
867
833
|
'joined',
|
|
868
834
|
'and that redemption really placed the revoked redeemer');
|
|
869
835
|
|
|
870
|
-
--
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
836
|
+
-- #280 DELETED a fourth residual assertion that stood here: "on the board it just created, a
|
|
837
|
+
-- revoked agent still cannot mint a link either". It was found by the SUITE, not by reading —
|
|
838
|
+
-- it names no function, only the slug `k276-residual-board`, so a grep for `create_board` missed
|
|
839
|
+
-- it and it went red as a null board id. Recorded because it is CLAUDE.md rule 1 in miniature:
|
|
840
|
+
-- the class of things to change came from a list written by hand, and the one member phrased
|
|
841
|
+
-- differently was the one that escaped. It is deleted rather than re-pointed: with the board it
|
|
842
|
+
-- referenced gone, the claim it made is exactly the G3 MINT assertion above (a ledger-revoked
|
|
843
|
+
-- owner cannot mint on a board it owns), driven there against board 1.
|
|
878
844
|
|
|
879
845
|
|
|
880
846
|
-- The RESIDUAL BOUND rests on a lock that is already in this function: the token FOR UPDATE is
|
|
@@ -1006,5 +972,110 @@ select ok(
|
|
|
1006
972
|
!~ '\m(effective_at|reactivated_at)\M',
|
|
1007
973
|
'the gate has no supersession clause, matching the send path''s agent-subject predicate');
|
|
1008
974
|
|
|
975
|
+
-- ===========================================================================
|
|
976
|
+
-- 11. #280 — create_board is GATED. These assertions are the FLIP of the RESIDUAL pair that
|
|
977
|
+
-- lived in what was EXEMPTION B: this file previously asserted, as behaviour, that a
|
|
978
|
+
-- ledger-revoked agent COULD create a board and be seeded its owner. #276's lane wrote it
|
|
979
|
+
-- that way deliberately so that closing #280 would be a visible test change. This is that
|
|
980
|
+
-- change.
|
|
981
|
+
--
|
|
982
|
+
-- THE ALLOW SIDE COMES FIRST AND MATTERS MORE THAN THE REFUSAL. create_board is the only
|
|
983
|
+
-- gated site every ordinary user reaches, on the CLI's default post-enroll intent among
|
|
984
|
+
-- other paths, so the expensive failure here is not "a revoked agent slipped through" but
|
|
985
|
+
-- "nobody can create a board any more". JUDGEMENT 2 of the #276 header — a principal that
|
|
986
|
+
-- was never in a fleet has no ledger row and passes by construction — is therefore asserted
|
|
987
|
+
-- POSITIVELY, on BOTH routes (authenticated and the service_role create-on-behalf-of the
|
|
988
|
+
-- gateway uses), by driving a real creation and reading the owner seat back. Never by the
|
|
989
|
+
-- absence of a refusal.
|
|
990
|
+
--
|
|
991
|
+
-- Every refusal probe is followed by a STATE check, because a gate that raises AND writes is
|
|
992
|
+
-- the failure throws_like alone cannot see. Here the state check is the operation's own
|
|
993
|
+
-- outcome: no boards row for the slug (which is also why no membership can exist).
|
|
994
|
+
-- ===========================================================================
|
|
995
|
+
|
|
996
|
+
-- ALLOW, ROUTE 1: the NON-FLEET agent (agent 3 has no fleet_machine_agents row at all).
|
|
997
|
+
select pg_temp.claims('27600000-0000-0000-0000-000000000003');
|
|
998
|
+
|
|
999
|
+
select lives_ok(
|
|
1000
|
+
$$create temp table _cb280a as select * from agent_board.create_board(
|
|
1001
|
+
'27610000-0000-4000-8000-000000000003','k280-allow-board','K280 Allow Board')$$,
|
|
1002
|
+
'ALLOW (#280): a NON-FLEET agent still creates a board — the capability this gate must not '
|
|
1003
|
+
'regress, driven rather than inferred from the absence of a refusal');
|
|
1004
|
+
|
|
1005
|
+
select is(
|
|
1006
|
+
(select bm.role from agent_board.board_memberships bm
|
|
1007
|
+
join agent_board.boards b on b.id = bm.board_id
|
|
1008
|
+
where b.slug = 'k280-allow-board'
|
|
1009
|
+
and bm.agent_id = '27610000-0000-4000-8000-000000000003'),
|
|
1010
|
+
'owner',
|
|
1011
|
+
'and its owner seat really landed, so the allow side is the whole operation and not just the '
|
|
1012
|
+
'absence of a raise');
|
|
1013
|
+
|
|
1014
|
+
-- ALLOW, ROUTE 2: service_role acting on behalf of a non-revoked principal — the gateway path.
|
|
1015
|
+
select pg_temp.service();
|
|
1016
|
+
|
|
1017
|
+
select lives_ok(
|
|
1018
|
+
$$create temp table _cb280b as select * from agent_board.create_board(
|
|
1019
|
+
'27610000-0000-4000-8000-000000000003','k280-allow-board-svc','K280 Allow Board Svc')$$,
|
|
1020
|
+
'ALLOW (#280): and service_role create-on-behalf-of a non-revoked agent still works');
|
|
1021
|
+
|
|
1022
|
+
select is(
|
|
1023
|
+
(select bm.role from agent_board.board_memberships bm
|
|
1024
|
+
join agent_board.boards b on b.id = bm.board_id
|
|
1025
|
+
where b.slug = 'k280-allow-board-svc'
|
|
1026
|
+
and bm.agent_id = '27610000-0000-4000-8000-000000000003'),
|
|
1027
|
+
'owner',
|
|
1028
|
+
'and that owner seat landed too — the gate binds the PRINCIPAL, so a clean principal is '
|
|
1029
|
+
'unaffected on either route');
|
|
1030
|
+
|
|
1031
|
+
-- REFUSED, ROUTE 1: the ledger-revoked agent 1 (revoked in section 4; agents.status still
|
|
1032
|
+
-- 'active', which is this migration's precondition and what makes the refusal the LEDGER's).
|
|
1033
|
+
select pg_temp.claims('27600000-0000-0000-0000-000000000001');
|
|
1034
|
+
|
|
1035
|
+
select throws_like(
|
|
1036
|
+
$$select * from agent_board.create_board(
|
|
1037
|
+
'27610000-0000-4000-8000-000000000001','k280-refused-board','K280 Refused Board')$$,
|
|
1038
|
+
'%fleet_revoked:%create_board%',
|
|
1039
|
+
'#280: a ledger-revoked agent can no longer create a board (this is the flipped RESIDUAL)');
|
|
1040
|
+
|
|
1041
|
+
select is(
|
|
1042
|
+
(select count(*)::int from agent_board.boards where slug = 'k280-refused-board'),
|
|
1043
|
+
0,
|
|
1044
|
+
'and the refused creation left NO board behind — the raise rolled back the boards insert, so '
|
|
1045
|
+
'the owner seat and the owner_seed event cannot exist either');
|
|
1046
|
+
|
|
1047
|
+
-- REFUSED, the SLUG-COLLISION branch. Agent 1 holds an ACTIVE owner membership on board 1, so
|
|
1048
|
+
-- it passes the owner check and would previously have renamed/reopened it. This is the scope
|
|
1049
|
+
-- consequence the migration header records explicitly: the gate covers BOTH branches.
|
|
1050
|
+
select throws_like(
|
|
1051
|
+
$$select * from agent_board.create_board(
|
|
1052
|
+
'27610000-0000-4000-8000-000000000001','k276-board-1','K276 Board 1 RENAMED')$$,
|
|
1053
|
+
'%fleet_revoked:%create_board%',
|
|
1054
|
+
'#280: and the slug-COLLISION branch is refused too — a revoked owner cannot reopen or '
|
|
1055
|
+
'rename an existing board it still owns');
|
|
1056
|
+
|
|
1057
|
+
select is(
|
|
1058
|
+
(select b.name from agent_board.boards b where b.slug = 'k276-board-1'),
|
|
1059
|
+
'K276 Board 1',
|
|
1060
|
+
'and that board is UNCHANGED: the raise rolled the collision-branch UPDATE back, which is a '
|
|
1061
|
+
'state check the message alone could not make');
|
|
1062
|
+
|
|
1063
|
+
-- REFUSED, ROUTE 2: service_role supplying a REVOKED p_created_by_agent_id. The check binds the
|
|
1064
|
+
-- principal the write is attributed to, not the connection role — a gateway acting for a
|
|
1065
|
+
-- revoked agent is the case #276 was filed about, restated here for the one function #276 left.
|
|
1066
|
+
select pg_temp.service();
|
|
1067
|
+
|
|
1068
|
+
select throws_like(
|
|
1069
|
+
$$select * from agent_board.create_board(
|
|
1070
|
+
'27610000-0000-4000-8000-000000000001','k280-refused-svc','K280 Refused Svc')$$,
|
|
1071
|
+
'%fleet_revoked:%create_board%',
|
|
1072
|
+
'#280: service_role create-on-behalf-of a REVOKED agent is refused — the gate binds the '
|
|
1073
|
+
'principal, never the connection role');
|
|
1074
|
+
|
|
1075
|
+
select is(
|
|
1076
|
+
(select count(*)::int from agent_board.boards where slug = 'k280-refused-svc'),
|
|
1077
|
+
0,
|
|
1078
|
+
'and that one left no board behind either');
|
|
1079
|
+
|
|
1009
1080
|
select finish();
|
|
1010
1081
|
rollback;
|