@consiliency/agent-board-schema 1.48.0 → 1.51.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 +16 -0
- package/migrations/20260929000100_agent_board_advisory_revert_cap_reset.sql +371 -0
- package/migrations/20260930000100_agent_board_claim_policy_race.sql +922 -0
- package/migrations/20261001000100_agent_board_claimpolicy_lock_grant_revoke.sql +158 -0
- package/migrations/20261002000100_agent_board_session_challenge_supersede.sql +383 -0
- package/package.json +1 -1
- package/schema-manifest.json +39 -3
- package/src/tooling.test.mjs +33 -2
- package/tests/agent_board_board_claim_policy.test.sql +261 -1
- package/tests/agent_board_claim_subject_gate.test.sql +11 -2
- package/tests/agent_board_claimkey.test.sql +17 -2
- package/tests/agent_board_claimpolicy_race.test.sql +1374 -0
- package/tests/agent_board_fk_lock_edges.test.sql +20 -0
- package/tests/agent_board_ownerless_quota_census.test.sql +6 -0
- package/tests/agent_board_ownerless_renew_quota.test.sql +37 -8
- package/tests/agent_board_signing_challenge_pending_cap.test.sql +391 -36
- package/tests/catalog/p_metadata_parameters.json +16 -0
- package/tests/fixtures/test-prereqs.sql +186 -0
- package/tests/isolation/expected/challenge_supersede_lock_order.out +213 -0
- package/tests/isolation/expected/claimpolicy_acquire_revert_race.out +66 -0
- package/tests/isolation/expected/claimpolicy_board_scope.out +73 -0
- package/tests/isolation/expected/claimpolicy_claimrow_lock_order.out +80 -0
- package/tests/isolation/expected/claimpolicy_isolation_refusal.out +114 -0
- package/tests/isolation/expected/claimpolicy_renew_revert_race.out +66 -0
- package/tests/isolation/expected/claimpolicy_writer_keyshare.out +49 -0
- package/tests/isolation/specs/challenge_supersede_lock_order.spec +183 -0
- package/tests/isolation/specs/claimpolicy_acquire_revert_race.spec +118 -0
- package/tests/isolation/specs/claimpolicy_board_scope.spec +115 -0
- package/tests/isolation/specs/claimpolicy_claimrow_lock_order.spec +200 -0
- package/tests/isolation/specs/claimpolicy_isolation_refusal.spec +162 -0
- package/tests/isolation/specs/claimpolicy_renew_revert_race.spec +150 -0
- package/tests/isolation/specs/claimpolicy_writer_keyshare.spec +107 -0
- package/tests/seeds/20261001000100_agent_board_claimpolicy_lock_grant_revoke.sql.pre.sql +99 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
-- Consiliency/message-board#405 — the ADVERSARIAL PRE-STATE for 20261001000100.
|
|
2
|
+
--
|
|
3
|
+
-- WHAT THIS GATES, and why an assertion could not. CPR-22 checks the lock helper's final ACL in the
|
|
4
|
+
-- ordinary fixture — where there is no delegated grant — so it stays GREEN if the migration's
|
|
5
|
+
-- `CASCADE` were removed or its sweep narrowed back to a list of known roles. The migration's
|
|
6
|
+
-- claimed behaviour is about a state the fixture never contains, so the fixture has to contain it.
|
|
7
|
+
--
|
|
8
|
+
-- THE STATE: `service_role` holds EXECUTE **WITH GRANT OPTION** and has granted it onward to
|
|
9
|
+
-- `anon`. That is the adopter shape the migration exists to survive: a plain `REVOKE` defaults to
|
|
10
|
+
-- RESTRICT and fails `dependent privileges exist` against it, which on an adopter database is a
|
|
11
|
+
-- FAILED UPGRADE rather than a tidier ACL. Measured against this bundle: the plain form errors, the
|
|
12
|
+
-- shipped form exits 0 and leaves `{postgres=X/postgres}`.
|
|
13
|
+
--
|
|
14
|
+
-- HOW THE GATE READS. This runs BEFORE 20261001000100 (the runner's tests/seeds/<migration>.pre.sql
|
|
15
|
+
-- hook, #103). Afterwards, either
|
|
16
|
+
-- * the migration swept the chain and CPR-22 reports an empty ACL — the claim holds; or
|
|
17
|
+
-- * the migration RAISED, and the whole bundle replay fails loudly at this migration.
|
|
18
|
+
-- There is no third outcome in which a narrowed sweep passes quietly.
|
|
19
|
+
--
|
|
20
|
+
-- ONLY PRE-EXISTING ROLES ARE USED — no CREATE ROLE. Roles are cluster-global, so a seed that
|
|
21
|
+
-- created them would leak them into a shared cluster and could collide with a concurrent run;
|
|
22
|
+
-- service_role and anon are part of the adopter base this bundle already assumes.
|
|
23
|
+
--
|
|
24
|
+
-- WHAT THIS FIXTURE GATES, precisely — and the second clause is NARROWER than an earlier version of
|
|
25
|
+
-- this paragraph claimed. It gates that the sweep CASCADEs, and that it reaches a grantee OUTSIDE
|
|
26
|
+
-- THE HISTORICAL HAND LIST (public/anon/authenticated/service_role). It does NOT gate that the
|
|
27
|
+
-- sweep is catalog-DERIVED: a migration hard-coded to those four PLUS `authenticator` clears this
|
|
28
|
+
-- fixture and its guard below. A fixture names specific roles by construction, so only a randomly
|
|
29
|
+
-- generated grantee defeats any hand list.
|
|
30
|
+
--
|
|
31
|
+
-- A DISPOSABLE RANDOM GRANTEE WAS CONSIDERED AND REJECTED, checked rather than reasoned about. The
|
|
32
|
+
-- runner has a `.pre.sql` hook and no post hook, so a role created here is never dropped; a seed
|
|
33
|
+
-- that swept `mb_seed405_%` at its start to compensate would be dropping roles belonging to any
|
|
34
|
+
-- CONCURRENT run on the same cluster, and this cluster is shared. Trading a stated gap for
|
|
35
|
+
-- cross-run interference is the worse deal. Derivation itself stays mutation-verified: narrowing
|
|
36
|
+
-- the sweep to known roles was injected and CPR-22 named the survivor.
|
|
37
|
+
--
|
|
38
|
+
-- WHAT IT DOES NOT GATE: that the sweep derives its SIGNATURES. That needs a pre-existing overload,
|
|
39
|
+
-- and a seeded overload PERSISTS — the runner has a `.pre.sql` hook and no post hook, so nothing
|
|
40
|
+
-- drops it, and tests/catalog/p_metadata_parameters.json enumerates every agent_board signature and
|
|
41
|
+
-- would go red. Checked rather than assumed. So a migration narrowed back to the `(uuid)` signature
|
|
42
|
+
-- stays green here; that half is mutation-verified only, and this paragraph is the record of it
|
|
43
|
+
-- rather than a silence someone has to rediscover.
|
|
44
|
+
|
|
45
|
+
do $$
|
|
46
|
+
begin
|
|
47
|
+
-- Idempotent: a re-replay onto a database that already carries the chain must not fail here, or
|
|
48
|
+
-- the seed becomes a worse failure mode than the one it tests for.
|
|
49
|
+
if not exists (select 1 from pg_roles where rolname = 'service_role')
|
|
50
|
+
or not exists (select 1 from pg_roles where rolname = 'anon') then
|
|
51
|
+
raise exception
|
|
52
|
+
'claimpolicy lock-grant seed: service_role/anon absent — the adopter base this bundle assumes is not present'
|
|
53
|
+
using errcode = '42704';
|
|
54
|
+
end if;
|
|
55
|
+
|
|
56
|
+
-- A GRANTEE OUTSIDE THE FOUR NAMES THE OLD HAND LIST USED. Without this the fixture gates only
|
|
57
|
+
-- "CASCADE is present": a migration hard-coded to revoke public/anon/authenticated/service_role
|
|
58
|
+
-- with CASCADE would sweep the chain below, pass, and still abandon every arbitrary adopter
|
|
59
|
+
-- grantee — which is the entire reason the sweep was made catalog-derived. `authenticator` is
|
|
60
|
+
-- outside that list and is part of the Supabase adopter base, so nothing has to be created:
|
|
61
|
+
-- a role invented here would linger cluster-wide, since a seed has no post hook to drop it.
|
|
62
|
+
execute 'grant execute on function agent_board._claimgate_lock_board_policy(uuid) to authenticator';
|
|
63
|
+
|
|
64
|
+
execute 'grant execute on function agent_board._claimgate_lock_board_policy(uuid) to service_role with grant option';
|
|
65
|
+
end $$;
|
|
66
|
+
|
|
67
|
+
-- The onward grant must be made BY service_role, so the dependency really exists.
|
|
68
|
+
--
|
|
69
|
+
-- `SET ROLE`, NOT `SET LOCAL ROLE`, and that distinction is the whole gate. The runner applies this
|
|
70
|
+
-- file with `psql -f` in AUTOCOMMIT, so every statement is its own implicit transaction and a
|
|
71
|
+
-- `SET LOCAL` is discarded before the next one runs. The first version used SET LOCAL: the grant was
|
|
72
|
+
-- then made by `postgres`, recorded as `anon=X/postgres` with no dependency on service_role's grant,
|
|
73
|
+
-- and a plain RESTRICT revoke would have swept it happily — a gate that passed whether or not the
|
|
74
|
+
-- migration cascaded. The check below caught exactly that, which is why it is here.
|
|
75
|
+
set role service_role;
|
|
76
|
+
grant execute on function agent_board._claimgate_lock_board_policy(uuid) to anon;
|
|
77
|
+
reset role;
|
|
78
|
+
|
|
79
|
+
-- Proof the pre-state is what this file claims, checked rather than assumed: if the chain did not
|
|
80
|
+
-- form, the migration would sweep a state no harder than the ordinary one and the gate would be
|
|
81
|
+
-- vacuous — green for the wrong reason, which is the failure mode this whole effort keeps finding.
|
|
82
|
+
do $$
|
|
83
|
+
declare v_acl text;
|
|
84
|
+
begin
|
|
85
|
+
select coalesce(proacl::text, '<null>') into v_acl
|
|
86
|
+
from pg_proc where oid = to_regprocedure('agent_board._claimgate_lock_board_policy(uuid)');
|
|
87
|
+
if v_acl not like '%anon=X/service_role%' then
|
|
88
|
+
raise exception
|
|
89
|
+
'claimpolicy lock-grant seed: the delegated grant did not form (acl=%) — refusing to leave a VACUOUS gate that would pass whether or not the migration cascades',
|
|
90
|
+
v_acl
|
|
91
|
+
using errcode = '55000';
|
|
92
|
+
end if;
|
|
93
|
+
if v_acl not like '%authenticator=%' then
|
|
94
|
+
raise exception
|
|
95
|
+
'claimpolicy lock-grant seed: the out-of-list grantee did not take (acl=%) — without it this fixture gates only CASCADE, and a migration narrowed to the four historical role names would pass',
|
|
96
|
+
v_acl
|
|
97
|
+
using errcode = '55000';
|
|
98
|
+
end if;
|
|
99
|
+
end $$;
|