@consiliency/agent-board-schema 1.57.0 → 1.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/fixtures/already-applied.json +8 -0
  2. package/migrations/20261008000100_agent_board_hosted_delegates.sql +3152 -0
  3. package/migrations/20261009000100_agent_board_hosted_followups.sql +665 -0
  4. package/package.json +1 -1
  5. package/schema-manifest.json +21 -3
  6. package/src/tooling.test.mjs +9 -2
  7. package/tests/agent_board_atomic_fleet_onboarding.test.sql +13 -0
  8. package/tests/agent_board_consent_emission.test.sql +4 -2
  9. package/tests/agent_board_delegate_role_class.test.sql +736 -0
  10. package/tests/agent_board_federated_identity_injective_slug.test.sql +5 -2
  11. package/tests/agent_board_fedsession_stored_identity_gate.test.sql +71 -14
  12. package/tests/agent_board_fk_lock_edges.test.sql +9 -0
  13. package/tests/agent_board_hosted_delegates.test.sql +1278 -0
  14. package/tests/agent_board_ledger_authority.test.sql +34 -5
  15. package/tests/agent_board_signer_lifecycle.test.sql +3 -0
  16. package/tests/agent_board_write_enforcement_class.test.sql +8 -3
  17. package/tests/catalog/function_execute_privileges.json +269 -2
  18. package/tests/catalog/p_metadata_parameters.json +44 -0
  19. package/tests/isolation/expected/hosted_delegate_add_tombstone_race.out +105 -0
  20. package/tests/isolation/expected/hosted_delegate_exchange_agent_revoke_race.out +66 -0
  21. package/tests/isolation/expected/hosted_delegate_exchange_race.out +93 -0
  22. package/tests/isolation/expected/hosted_delegate_first_exchange_race.out +129 -0
  23. package/tests/isolation/expected/hosted_delegate_owner_provisioning_race.out +91 -0
  24. package/tests/isolation/expected/hosted_delegate_owner_revoke_race.out +137 -0
  25. package/tests/isolation/expected/hosted_delegate_revoke_race.out +87 -0
  26. package/tests/isolation/expected/hosted_delegate_tombstone_revoke_race.out +170 -0
  27. package/tests/isolation/expected/hosted_delegate_withdraw_evict_race.out +235 -0
  28. package/tests/isolation/specs/hosted_delegate_add_tombstone_race.spec +102 -0
  29. package/tests/isolation/specs/hosted_delegate_exchange_agent_revoke_race.spec +92 -0
  30. package/tests/isolation/specs/hosted_delegate_exchange_race.spec +64 -0
  31. package/tests/isolation/specs/hosted_delegate_first_exchange_race.spec +72 -0
  32. package/tests/isolation/specs/hosted_delegate_owner_provisioning_race.spec +73 -0
  33. package/tests/isolation/specs/hosted_delegate_owner_revoke_race.spec +93 -0
  34. package/tests/isolation/specs/hosted_delegate_revoke_race.spec +59 -0
  35. package/tests/isolation/specs/hosted_delegate_tombstone_revoke_race.spec +158 -0
  36. package/tests/isolation/specs/hosted_delegate_withdraw_evict_race.spec +145 -0
@@ -0,0 +1,736 @@
1
+ -- HOSTED (v11) SL-2 pgTAP: the agent_board_delegate role, as CLASSES derived from the catalog
2
+ -- (specs/agent-client-contract.md, HOSTED, "Class assertions SL-2 must write" and "What stays
3
+ -- refused for a delegate"). Nothing here is a hand list of the population: each class is read
4
+ -- from pg_proc / pg_class / pg_policy / pg_depend or from agent_board.delegate_allowed_operations,
5
+ -- so a new function, relation, grant or policy fails AND NAMES ITSELF.
6
+ --
7
+ -- Where an expected value is written here, it is the frozen contract value (the policy
8
+ -- predicates, the eight agents columns, a derived population named positively so a new member
9
+ -- shows up as a diff), never the population an assertion iterates over.
10
+ --
11
+ -- The zero-rows matrix (section 9) SWITCHES ROLE to agent_board_delegate. Every negative case
12
+ -- is paired with the same kind of row on a board where the delegate is active, so a predicate
13
+ -- that returns false everywhere fails too.
14
+ create extension if not exists pgtap with schema extensions;
15
+ set search_path = extensions, public, agent_board;
16
+
17
+ begin;
18
+
19
+ select plan(43);
20
+
21
+ -- ===========================================================================
22
+ -- 1. The role itself
23
+ -- ===========================================================================
24
+ -- 1
25
+ select is(
26
+ (select rolcanlogin::text || '/' || rolsuper::text || '/' || rolbypassrls::text || '/' || rolinherit::text
27
+ || '/' || rolcreaterole::text || '/' || rolcreatedb::text
28
+ from pg_roles where rolname = 'agent_board_delegate'),
29
+ 'false/false/false/false/false/false',
30
+ 'agent_board_delegate: NOLOGIN, not a superuser, no BYPASSRLS, NOINHERIT, no CREATEROLE/CREATEDB');
31
+ -- 2
32
+ select is(
33
+ (select count(*)::int from pg_auth_members where member = 'agent_board_delegate'::regrole),
34
+ 0,
35
+ 'agent_board_delegate is a member of NO role (never authenticated, which would inherit every authenticated grant)');
36
+ -- 3 -- who can BECOME it: only authenticator (where it exists). The PostgreSQL 16+ creator
37
+ -- grant (ADMIN only, no SET and no INHERIT) cannot switch to it and is not counted.
38
+ select is(
39
+ (select coalesce(string_agg(m.rolname, ',' order by m.rolname), '(none)')
40
+ from pg_auth_members am join pg_roles m on m.oid = am.member
41
+ where am.roleid = 'agent_board_delegate'::regrole and (am.set_option or am.inherit_option)),
42
+ case when exists (select 1 from pg_roles where rolname = 'authenticator') then 'authenticator' else '(none)' end,
43
+ 'only authenticator can switch to agent_board_delegate');
44
+ -- 4
45
+ select ok(has_schema_privilege('agent_board_delegate', 'agent_board', 'USAGE'),
46
+ 'agent_board_delegate has USAGE on schema agent_board');
47
+
48
+ -- ===========================================================================
49
+ -- 2. Function deny-by-default, over SECURITY DEFINER functions (IF-0-HOSTED-5)
50
+ -- ===========================================================================
51
+ create temp view _fn as
52
+ select p.oid, p.proname::text as name, p.proname || '(' || oidvectortypes(p.proargtypes) || ')' as signature, p.prosecdef
53
+ from pg_proc p join pg_namespace n on n.oid = p.pronamespace
54
+ where n.nspname = 'agent_board';
55
+ -- 5 -- every listed function names exactly one function
56
+ select is(
57
+ (select coalesce(string_agg(o.kind || ':' || o.signature, ', ' order by o.signature), '(none)')
58
+ from agent_board.delegate_allowed_operations o
59
+ where o.kind in ('rpc', 'ambient_rpc', 'predicate')
60
+ and (select count(*) from _fn f where f.signature = o.signature) <> 1),
61
+ '(none)',
62
+ 'every rpc/ambient_rpc/predicate entry of the allow set names exactly one agent_board function');
63
+ -- 6 -- THE CLASS: has_function_privilege iff listed, over every definer
64
+ select is(
65
+ (select coalesce(string_agg(f.signature || ' => ' ||
66
+ case when has_function_privilege('agent_board_delegate', f.oid, 'EXECUTE') then 'GRANTED, NOT LISTED' else 'LISTED, NOT GRANTED' end,
67
+ '; ' order by f.signature), '')
68
+ from _fn f
69
+ where f.prosecdef
70
+ and has_function_privilege('agent_board_delegate', f.oid, 'EXECUTE')
71
+ <> exists (select 1 from agent_board.delegate_allowed_operations o
72
+ where o.kind in ('rpc', 'ambient_rpc', 'predicate') and o.signature = f.signature)),
73
+ '',
74
+ 'CLASS: agent_board_delegate can EXECUTE a SECURITY DEFINER function iff it is in delegate_allowed_operations');
75
+ -- 7 -- every listed function is a definer (a non-definer runs with the caller's rights and
76
+ -- needs no grant; listing one would hide what the role can really reach)
77
+ select is(
78
+ (select coalesce(string_agg(f.signature, ', ' order by f.signature), '(none)')
79
+ from _fn f join agent_board.delegate_allowed_operations o on o.signature = f.signature
80
+ where o.kind in ('rpc', 'ambient_rpc', 'predicate') and not f.prosecdef),
81
+ '(none)',
82
+ 'every function in the allow set is SECURITY DEFINER');
83
+ -- 8 -- the allow set's function membership, named: the contract's first membership with the
84
+ -- three per-row board predicates replaced by _delegate_visible_board_ids() (InitPlan form,
85
+ -- authorised by the team lead; SL-8 amends the contract)
86
+ select is(
87
+ (select string_agg(kind || ':' || signature, ' | ' order by kind, signature)
88
+ from agent_board.delegate_allowed_operations where kind in ('rpc', 'ambient_rpc', 'predicate')),
89
+ 'ambient_rpc:get_schema_version() | predicate:_delegate_visible_agent(uuid) | predicate:_delegate_visible_board_ids() | predicate:current_agent_id() | rpc:create_or_find_thread(uuid, text, text, text, jsonb) | rpc:post_board_message(uuid, uuid, text, text, text, text, text, text, text, jsonb) | rpc:post_board_message(uuid, uuid, uuid, text, text, text, text, text, jsonb) | rpc:post_message(uuid, uuid, text, text, uuid, jsonb)',
90
+ 'the allow set''s functions are exactly the contract''s first membership (D4): read and post, nothing else');
91
+
92
+ -- ===========================================================================
93
+ -- 3. Read-grant completeness
94
+ -- ===========================================================================
95
+ create temp view _rel as
96
+ select c.oid, c.relname::text as name, c.relkind, c.reloptions
97
+ from pg_class c join pg_namespace n on n.oid = c.relnamespace
98
+ where n.nspname = 'agent_board' and c.relkind in ('r', 'v', 'm', 'p', 'f');
99
+ -- 9 -- SELECT iff listed as read_view / read_table (has_any_column_privilege for column grants)
100
+ select is(
101
+ (select coalesce(string_agg(r.name || ' => ' ||
102
+ case when has_any_column_privilege('agent_board_delegate', r.oid, 'SELECT') then 'GRANTED, NOT LISTED' else 'LISTED, NOT GRANTED' end,
103
+ '; ' order by r.name), '')
104
+ from _rel r
105
+ where has_any_column_privilege('agent_board_delegate', r.oid, 'SELECT')
106
+ <> exists (select 1 from agent_board.delegate_allowed_operations o
107
+ where o.kind in ('read_view', 'read_table') and o.name = r.name
108
+ and o.kind = case when r.relkind in ('v', 'm') then 'read_view' else 'read_table' end)),
109
+ '',
110
+ 'CLASS: agent_board_delegate can SELECT a relation iff it is listed as read_view or read_table, of its own relkind');
111
+ -- 10 -- the read closure, named: 5 views and 13 tables
112
+ select is(
113
+ (select string_agg(kind || ':' || name, ' ' order by kind, name)
114
+ from agent_board.delegate_allowed_operations where kind in ('read_view', 'read_table')),
115
+ 'read_table:agent_signing_keys read_table:agents read_table:board_memberships read_table:boards read_table:claims read_table:delivery_recipients read_table:escalations read_table:inbox_items read_table:messages read_table:presence read_table:signature_evidence read_table:task_events read_table:tasks read_view:v_agent_dashboard read_view:v_agent_inbox read_view:v_board_feed read_view:v_board_memberships read_view:v_thread_feed',
116
+ 'the read closure is the five views and the thirteen tables the contract freezes');
117
+ -- 11 -- the closure is CLOSED: every relation a granted view reads is itself granted
118
+ select is(
119
+ (select coalesce(string_agg(distinct v.relname || ' -> ' || t.relname, ', '), '(none)')
120
+ from pg_rewrite rw
121
+ join pg_class v on v.oid = rw.ev_class
122
+ join pg_depend d on d.classid = 'pg_rewrite'::regclass and d.objid = rw.oid and d.refclassid = 'pg_class'::regclass
123
+ join pg_class t on t.oid = d.refobjid and t.oid <> v.oid
124
+ where has_table_privilege('agent_board_delegate', v.oid, 'SELECT')
125
+ and v.relkind = 'v' and v.relnamespace = 'agent_board'::regnamespace
126
+ and not has_any_column_privilege('agent_board_delegate', t.oid, 'SELECT')),
127
+ '(none)',
128
+ 'the read closure is closed: every relation a granted view reads is granted too (else the view raises)');
129
+ -- 12 -- every granted view is security_invoker
130
+ select is(
131
+ (select coalesce(string_agg(r.name, ', ' order by r.name), '(none)')
132
+ from _rel r
133
+ where r.relkind in ('v', 'm')
134
+ and has_table_privilege('agent_board_delegate', r.oid, 'SELECT')
135
+ and not coalesce('security_invoker=true' = any(r.reloptions), false)),
136
+ '(none)',
137
+ 'every view agent_board_delegate can SELECT is security_invoker = true');
138
+ -- 13 -- agents: exactly the eight columns authenticated holds, never auth_user_id or owner_user_id
139
+ select is(
140
+ (select string_agg(a.attname, ',' order by a.attname)
141
+ from pg_attribute a
142
+ where a.attrelid = 'agent_board.agents'::regclass and a.attnum > 0 and not a.attisdropped
143
+ and has_column_privilege('agent_board_delegate', a.attrelid, a.attnum, 'SELECT')),
144
+ 'agent_type,created_at,display_name,handle,id,kind,status,updated_at',
145
+ 'agents: SELECT on exactly the eight authenticated columns (never auth_user_id, owner_user_id or is_delegate)');
146
+ -- 14 -- no write privilege anywhere, no sequence privilege
147
+ select is(
148
+ (select coalesce(string_agg(x, ', ' order by x), '(none)') from (
149
+ select r.name || ':' || p as x
150
+ from _rel r cross join unnest(array['INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER']) p
151
+ where has_table_privilege('agent_board_delegate', r.oid, p)
152
+ union all
153
+ select c.relname || ':' || p
154
+ from pg_class c join pg_namespace n on n.oid = c.relnamespace
155
+ cross join unnest(array['USAGE', 'SELECT', 'UPDATE']) p
156
+ where n.nspname = 'agent_board' and c.relkind = 'S'
157
+ and has_sequence_privilege('agent_board_delegate', c.oid, p)) z),
158
+ '(none)',
159
+ 'agent_board_delegate holds no INSERT/UPDATE/DELETE/TRUNCATE/REFERENCES/TRIGGER and no sequence privilege');
160
+
161
+ -- ===========================================================================
162
+ -- 4. Policy completeness
163
+ -- ===========================================================================
164
+ create temp view _pol as
165
+ select c.relname::text as relname, p.polname::text as polname, p.polcmd, p.polpermissive,
166
+ array(select r.rolname::text from pg_roles r where r.oid = any(p.polroles) order by 1) as roles,
167
+ 0 = any(p.polroles) as is_public, p.oid as poloid, p.polrelid,
168
+ -- newlines and indentation in the deparse collapsed to single spaces
169
+ replace(replace(replace(replace(pg_get_expr(p.polqual, p.polrelid), E'\n', ' '), ' ', ' '), ' ', ' '), ' ', ' ') as qual,
170
+ pg_get_expr(p.polwithcheck, p.polrelid) as withcheck
171
+ from pg_policy p join pg_class c on c.oid = p.polrelid join pg_namespace n on n.oid = c.relnamespace
172
+ where n.nspname = 'agent_board'
173
+ and ((select r.oid from pg_roles r where r.rolname = 'agent_board_delegate') = any(p.polroles) or 0 = any(p.polroles));
174
+ -- 15 -- a PUBLIC policy applies to the role too; allowed only where the role has no SELECT
175
+ select is(
176
+ (select coalesce(string_agg(relname || ':' || polname || ':' ||
177
+ case when has_table_privilege('agent_board_delegate', polrelid, 'SELECT') then 'ROLE HAS SELECT' else 'inert' end,
178
+ ', ' order by relname, polname), '(none)')
179
+ from _pol where is_public),
180
+ 'schema_version:agent_board_select_schema_version:inert',
181
+ 'the one PUBLIC policy (schema_version) is on a relation the role cannot SELECT, so it grants the role nothing');
182
+ -- 16 -- exactly one delegate policy per read_table: SELECT, permissive, the role only
183
+ select is(
184
+ (select coalesce(string_agg(x, '; ' order by x), '(none)') from (
185
+ select o.name || ' => ' || count(p.polname)::text || ' policies' as x
186
+ from agent_board.delegate_allowed_operations o
187
+ left join _pol p on p.relname = o.name and not p.is_public
188
+ where o.kind = 'read_table'
189
+ group by o.name having count(p.polname) <> 1
190
+ union all
191
+ select relname || ':' || polname || ' is not a permissive SELECT policy for the role alone'
192
+ from _pol
193
+ where not is_public and (polcmd <> 'r' or not polpermissive or roles <> array['agent_board_delegate'] or withcheck is not null)
194
+ union all
195
+ select relname || ':' || polname || ' is on a relation outside the read closure'
196
+ from _pol
197
+ where not is_public and relname not in (select name from agent_board.delegate_allowed_operations where kind = 'read_table')) z),
198
+ '(none)',
199
+ 'policy completeness: one permissive SELECT policy TO agent_board_delegate on each read_table, and none elsewhere');
200
+ -- 17 -- each predicate is the one the contract freezes (deparsed, whitespace-normalised). The
201
+ -- deparse qualifies names by the search_path, so agent_board is taken off it for this read.
202
+ set local search_path = extensions, public;
203
+ select is(
204
+ (select string_agg(relname || ' :: ' || qual, E'\n' order by relname) from _pol where not is_public),
205
+ 'agent_signing_keys :: false' || E'\n' ||
206
+ 'agents :: agent_board._delegate_visible_agent(id)' || E'\n' ||
207
+ 'board_memberships :: ((agent_id = ( SELECT agent_board.current_agent_id() AS current_agent_id)) AND (membership_state = ANY (ARRAY[''joined''::text, ''subscribed''::text])))' || E'\n' ||
208
+ 'boards :: (id = ANY (COALESCE(( SELECT agent_board._delegate_visible_board_ids() AS _delegate_visible_board_ids), ''{}''::uuid[])))' || E'\n' ||
209
+ 'claims :: ((task_id IS NOT NULL) AND (EXISTS ( SELECT 1 FROM agent_board.delivery_recipients dr WHERE ((dr.source_task_id = claims.task_id) AND (dr.board_id = ANY (COALESCE(( SELECT agent_board._delegate_visible_board_ids() AS _delegate_visible_board_ids), ''{}''::uuid[])))))))' || E'\n' ||
210
+ 'delivery_recipients :: (board_id = ANY (COALESCE(( SELECT agent_board._delegate_visible_board_ids() AS _delegate_visible_board_ids), ''{}''::uuid[])))' || E'\n' ||
211
+ 'escalations :: ((task_id IS NOT NULL) AND (EXISTS ( SELECT 1 FROM agent_board.delivery_recipients dr WHERE ((dr.source_task_id = escalations.task_id) AND (dr.board_id = ANY (COALESCE(( SELECT agent_board._delegate_visible_board_ids() AS _delegate_visible_board_ids), ''{}''::uuid[])))))))' || E'\n' ||
212
+ 'inbox_items :: ((board_id = ANY (COALESCE(( SELECT agent_board._delegate_visible_board_ids() AS _delegate_visible_board_ids), ''{}''::uuid[]))) AND ((recipient_agent_id = ( SELECT agent_board.current_agent_id() AS current_agent_id)) OR visible_in_board_feed))' || E'\n' ||
213
+ 'messages :: (EXISTS ( SELECT 1 FROM agent_board.delivery_recipients dr WHERE ((dr.source_message_id = messages.id) AND (dr.board_id = ANY (COALESCE(( SELECT agent_board._delegate_visible_board_ids() AS _delegate_visible_board_ids), ''{}''::uuid[]))))))' || E'\n' ||
214
+ 'presence :: false' || E'\n' ||
215
+ 'signature_evidence :: (((source_message_id IS NOT NULL) OR (source_task_event_id IS NOT NULL) OR (source_delivery_recipient_id IS NOT NULL)) AND (source_artifact_id IS NULL) AND ((source_message_id IS NULL) OR (EXISTS ( SELECT 1 FROM agent_board.delivery_recipients dr WHERE ((dr.source_message_id = signature_evidence.source_message_id) AND (dr.board_id = ANY (COALESCE(( SELECT agent_board._delegate_visible_board_ids() AS _delegate_visible_board_ids), ''{}''::uuid[]))))))) AND ((source_task_event_id IS NULL) OR (EXISTS ( SELECT 1 FROM agent_board.task_events te WHERE (te.id = signature_evidence.source_task_event_id)))) AND ((source_delivery_recipient_id IS NULL) OR (EXISTS ( SELECT 1 FROM agent_board.delivery_recipients dr WHERE (dr.id = signature_evidence.source_delivery_recipient_id)))))' || E'\n' ||
216
+ 'task_events :: (EXISTS ( SELECT 1 FROM agent_board.delivery_recipients dr WHERE ((dr.source_task_id = task_events.task_id) AND (dr.board_id = ANY (COALESCE(( SELECT agent_board._delegate_visible_board_ids() AS _delegate_visible_board_ids), ''{}''::uuid[]))))))' || E'\n' ||
217
+ 'tasks :: (EXISTS ( SELECT 1 FROM agent_board.delivery_recipients dr WHERE ((dr.source_task_id = tasks.id) AND (dr.board_id = ANY (COALESCE(( SELECT agent_board._delegate_visible_board_ids() AS _delegate_visible_board_ids), ''{}''::uuid[]))))))',
218
+ 'each delegate policy''s USING is exactly the D14 predicate stated once in the migration (InitPlan form)');
219
+ set local search_path = extensions, public, agent_board;
220
+
221
+ -- ===========================================================================
222
+ -- 5. Predicates are IN the set, not exempt
223
+ -- ===========================================================================
224
+ -- 18 -- every function a delegate-applicable policy or a granted view invokes is listed as a predicate
225
+ select is(
226
+ (select coalesce(string_agg(distinct f.signature, ', '), '(none)')
227
+ from (
228
+ select d.refobjid as fn
229
+ from pg_depend d join _pol p on d.classid = 'pg_policy'::regclass and d.objid = p.poloid
230
+ where d.refclassid = 'pg_proc'::regclass
231
+ and has_table_privilege('agent_board_delegate', p.polrelid, 'SELECT')
232
+ union
233
+ select d.refobjid
234
+ from pg_rewrite rw
235
+ join pg_depend d on d.classid = 'pg_rewrite'::regclass and d.objid = rw.oid
236
+ where d.refclassid = 'pg_proc'::regclass
237
+ and has_table_privilege('agent_board_delegate', rw.ev_class, 'SELECT')
238
+ ) used
239
+ join _fn f on f.oid = used.fn -- agent_board functions; builtins are not predicates
240
+ where not exists (select 1 from agent_board.delegate_allowed_operations o
241
+ where o.kind = 'predicate' and o.signature = f.signature)),
242
+ '(none)',
243
+ 'every function a delegate policy or granted view invokes is in the allow set as a predicate (no exemption list)');
244
+ -- 19 -- ...and every listed predicate IS invoked by one (a predicate nothing reaches is a stray grant)
245
+ select is(
246
+ (select coalesce(string_agg(o.signature, ', ' order by o.signature), '(none)')
247
+ from agent_board.delegate_allowed_operations o
248
+ join _fn f on f.signature = o.signature
249
+ where o.kind = 'predicate'
250
+ and not exists (
251
+ select 1 from pg_depend d join _pol p on d.classid = 'pg_policy'::regclass and d.objid = p.poloid
252
+ where d.refclassid = 'pg_proc'::regclass and d.refobjid = f.oid)),
253
+ '(none)',
254
+ 'every listed predicate is invoked by a delegate policy');
255
+ -- 20 -- no granted view invokes an agent_board function (the views add no predicate)
256
+ select is(
257
+ (select count(*)::int
258
+ from pg_rewrite rw join pg_depend d on d.classid = 'pg_rewrite'::regclass and d.objid = rw.oid
259
+ join _fn f on f.oid = d.refobjid
260
+ where d.refclassid = 'pg_proc'::regclass and has_table_privilege('agent_board_delegate', rw.ev_class, 'SELECT')),
261
+ 0,
262
+ 'none of the granted views calls an agent_board function');
263
+
264
+ -- ===========================================================================
265
+ -- 6. D15 -- the admission flag has one setter; the sink reads it
266
+ -- ===========================================================================
267
+ -- 21 -- every function that names the flag at all, derived (a second setter -- or any new
268
+ -- reader -- names itself here)
269
+ select is(
270
+ (select coalesce(string_agg(f.name, ',' order by f.name), '(none)')
271
+ from _fn f
272
+ where strpos(agent_board_test.stripped_body(f.oid, true), 'agent_board.delegate_admission') > 0),
273
+ '_upsert_board_membership_state,add_delegate_to_board',
274
+ 'D15: exactly two functions name agent_board.delegate_admission: its setter and the sink that reads it');
275
+ -- 22 -- the setter sets it to the target, and clears it
276
+ -- source-scan: loud-literal one body, named by regprocedure; a miss fails
277
+ select ok(
278
+ agent_board_test.stripped_body('agent_board.add_delegate_to_board(uuid,uuid)'::regprocedure, true)
279
+ ~ 'set_config\(''agent_board\.delegate_admission'', p_agent_id::text, true\).*set_config\(''agent_board\.delegate_admission'', '''', true\)',
280
+ 'D15: add_delegate_to_board sets the flag to the target and clears it again');
281
+ -- 23 -- the sink only reads it
282
+ -- source-scan: loud-literal one body, named by regprocedure; a miss fails
283
+ select ok(
284
+ agent_board_test.stripped_body('agent_board._upsert_board_membership_state(uuid,uuid,text,uuid,jsonb,uuid,text)'::regprocedure, true)
285
+ ~ 'current_setting\(''agent_board\.delegate_admission'', true\)',
286
+ 'D15: the sink reads the flag with current_setting');
287
+
288
+ -- ===========================================================================
289
+ -- 7. Placement and role-writer classes (§What stays refused for a delegate)
290
+ -- ===========================================================================
291
+ -- Every direct writer of board_memberships (any INSERT, UPDATE, MERGE or DELETE on it, the
292
+ -- ledger_authority role-writer derivation widened to every column) other than the sink must
293
+ -- call the shared refusal, schema-qualified. The sink carries the D15 rule instead.
294
+ create temp view _bm_writers as
295
+ select f.oid, f.name,
296
+ agent_board_test.stripped_body(f.oid) ~ agent_board_test.call_re('_refuse_delegate_membership_target', false) as refuses,
297
+ agent_board_test.stripped_body(f.oid) ~ agent_board_test.col_write_re('board_memberships', 'role') as writes_role
298
+ from _fn f
299
+ where f.name <> '_upsert_board_membership_state'
300
+ and agent_board_test.stripped_body(f.oid) ~ agent_board_test.write_re('board_memberships');
301
+ -- 24
302
+ select is(
303
+ (select string_agg(name || case when writes_role then '[role]' else '' end, ',' order by name) from _bm_writers),
304
+ '_fedsession_autojoin_default_board[role],_redeem_unbounded_invite_for_agent[role],bootstrap_board_owner_memberships[role],create_board[role],grant_board_role[role]',
305
+ 'the direct board_memberships writers outside the sink, derived (a new one names itself)');
306
+ -- 25
307
+ select is(
308
+ (select coalesce(string_agg(name, ',' order by name), '') from _bm_writers where not refuses),
309
+ '',
310
+ 'CLASS: every direct board_memberships writer outside the sink refuses a delegate target (grant_board_role included)');
311
+ -- 26 -- and every entrypoint that reaches board_memberships at all reaches it through one of
312
+ -- them or the sink: a function that writes it directly is in the set above by construction, so
313
+ -- this pins the sink's own rule is present
314
+ select ok(
315
+ agent_board_test.stripped_body('agent_board._upsert_board_membership_state(uuid,uuid,text,uuid,jsonb,uuid,text)'::regprocedure)
316
+ ~ agent_board_test.call_re('_delegate_principal_agent_id', false)
317
+ and agent_board_test.stripped_body('agent_board._upsert_board_membership_state(uuid,uuid,text,uuid,jsonb,uuid,text)'::regprocedure, true)
318
+ ~* 'is\s+distinct\s+from\s+''member''',
319
+ 'D15: the sink compares the session with the delegate''s principal and asserts member after the write');
320
+
321
+ -- ===========================================================================
322
+ -- 8. D16 -- the addressing class
323
+ -- ===========================================================================
324
+ create temp view _addr as
325
+ select distinct f.oid, f.name,
326
+ agent_board_test.stripped_body(f.oid) ~ agent_board_test.call_re('_refuse_delegate_addressee', false) as refuses
327
+ from _fn f
328
+ cross join (values ('tasks', 'assigned_agent_id'), ('escalations', 'assigned_agent_id'),
329
+ ('delegations', 'delegated_to_agent_id'), ('delivery_recipients', 'recipient_agent_id'),
330
+ ('inbox_items', 'recipient_agent_id')) x(rel, col)
331
+ where agent_board_test.stripped_body(f.oid) ~ agent_board_test.col_write_re(x.rel, x.col);
332
+ -- 27
333
+ select is(
334
+ (select string_agg(name, ',' order by name) from _addr),
335
+ '_append_task_event,_upsert_delivery_recipient,_upsert_inbox_item,create_task,delegate_task,raise_escalation',
336
+ 'the writers of an addressee column, derived (a new one names itself)');
337
+ -- 28
338
+ select is(
339
+ (select coalesce(string_agg(name, ',' order by name), '') from _addr where not refuses),
340
+ '',
341
+ 'CLASS (D16): every writer of an addressee column calls the delegate-addressee refusal');
342
+ -- 29 -- update_inbox_item_state changes state and never the recipient (asserted positively)
343
+ select is(
344
+ (agent_board_test.stripped_body('agent_board.update_inbox_item_state(uuid,uuid,text,jsonb)'::regprocedure)
345
+ ~ agent_board_test.re(agent_board_test.col_assign_frag('inbox_items', 'action_state', true)))::text
346
+ || '/' ||
347
+ (agent_board_test.stripped_body('agent_board.update_inbox_item_state(uuid,uuid,text,jsonb)'::regprocedure)
348
+ ~ agent_board_test.re(agent_board_test.col_assign_frag('inbox_items', 'recipient_agent_id', true)))::text,
349
+ 'true/false',
350
+ 'update_inbox_item_state assigns action_state and never recipient_agent_id');
351
+
352
+ -- ===========================================================================
353
+ -- 9. The provenance vocabulary readers (§principal-authored, exactly)
354
+ -- ===========================================================================
355
+ -- Every function naming a provenance value in its source, derived, each given a POSITIVE
356
+ -- disposition for principal-authored. An undisposed reader names itself.
357
+ -- 30
358
+ select is(
359
+ (select string_agg(f.name || ':' || case
360
+ when f.name = '_emit_membership_event'
361
+ and agent_board_test.stripped_body(f.oid, true) ~ 'v_prov\s*:=\s*''principal-authored''' then 'derives it'
362
+ when f.name = '_board_membership_events_provenance_guard'
363
+ and agent_board_test.stripped_body(f.oid, true) ~ 'provenance\s*=\s*''principal-authored''' then 'guards it'
364
+ when f.name in ('_membership_consent_present', '_membership_consent_kind')
365
+ and (select count(*) from regexp_matches(agent_board_test.stripped_body(f.oid, true), 'provenance\s*=\s*''principal-authored''', 'g')) = 2
366
+ then 'reads it in case and filter'
367
+ when f.name = '_upsert_board_membership_state'
368
+ and agent_board_test.stripped_body(f.oid) ~ agent_board_test.call_re('_emit_membership_event', false) then 'emits only through the emitter'
369
+ when f.name in ('create_board', 'bootstrap_board_owner_memberships', '_redeem_unbounded_invite_for_agent')
370
+ and agent_board_test.stripped_body(f.oid) ~ agent_board_test.call_re('_refuse_delegate_membership_target', false) then 'never a delegate target'
371
+ when f.name = 'resolve_board_request'
372
+ and exists (select 1 from agent_board_test.fn_call_closure() c
373
+ where c.root_oid = f.oid and c.reached_name = '_upsert_board_membership_state') then 'admits only through the sink (D15)'
374
+ when f.name = 'list_my_board_requests'
375
+ and not has_function_privilege('agent_board_delegate', f.oid, 'EXECUTE') then 'not callable by a delegate'
376
+ else 'UNDISPOSED' end, ', ' order by f.name)
377
+ from _fn f
378
+ where f.name in (select p.proname from pg_proc p join pg_namespace n on n.oid = p.pronamespace
379
+ where n.nspname = 'agent_board'
380
+ -- source-scan: raw-subject the contract derives this set from prosrc on purpose: a comment naming a value widens the set and only adds a disposition
381
+ and p.prosrc ~* '(operator-designated|target-authored|board-authored)')),
382
+ '_board_membership_events_provenance_guard:guards it, _emit_membership_event:derives it, _membership_consent_kind:reads it in case and filter, _membership_consent_present:reads it in case and filter, _redeem_unbounded_invite_for_agent:never a delegate target, _upsert_board_membership_state:emits only through the emitter, bootstrap_board_owner_memberships:never a delegate target, create_board:never a delegate target, list_my_board_requests:not callable by a delegate, resolve_board_request:admits only through the sink (D15)',
383
+ 'every reader of the provenance vocabulary has a positive disposition for principal-authored');
384
+ -- 31 -- post_message is the only function that inserts into messages (the attribution mark is complete)
385
+ select is(
386
+ (select string_agg(f.name, ',' order by f.name) from _fn f
387
+ where agent_board_test.stripped_body(f.oid) ~ agent_board_test.stmt_re('insert into', 'messages')),
388
+ 'post_message',
389
+ 'post_message is the only writer of messages, so its delegate mark covers every message');
390
+ -- 32 -- the delegate fact is written only by the exchange's first-use insert
391
+ select is(
392
+ (select string_agg(f.name, ',' order by f.name) from _fn f
393
+ where agent_board_test.stripped_body(f.oid) ~ agent_board_test.col_write_re('agents', 'is_delegate')),
394
+ 'exchange_delegate_credential',
395
+ 'agents.is_delegate is written by exchange_delegate_credential alone');
396
+
397
+ -- ===========================================================================
398
+ -- 10. Zero rows elsewhere (D14) -- AS the delegate, over every listed relation
399
+ -- ===========================================================================
400
+ do $$
401
+ begin
402
+ if not (select rolsuper from pg_roles where rolname = current_user) then
403
+ execute format('grant agent_board_delegate to %I with set true', current_user);
404
+ end if;
405
+ end $$;
406
+
407
+ create temp table _z(k text primary key, v text);
408
+ create function pg_temp.v(p_k text) returns text language sql as $$ select v from _z where k = p_k $$;
409
+ create function pg_temp.u(p_k text) returns uuid language sql as $$ select v::uuid from _z where k = p_k $$;
410
+ create function pg_temp.put(p_k text, p_v text) returns void language sql as $$
411
+ insert into _z values (p_k, p_v) on conflict (k) do update set v = excluded.v $$;
412
+ create function pg_temp.svc() returns void language plpgsql as $$
413
+ begin perform set_config('request.jwt.claims', '', true); end $$;
414
+ create function pg_temp.authn(p_sub uuid) returns void language plpgsql as $$
415
+ begin perform set_config('request.jwt.claims', json_build_object('role', 'authenticated', 'sub', p_sub)::text, true); end $$;
416
+ create function pg_temp.as_d_val(p_sql text) returns text language plpgsql as $$
417
+ declare v text;
418
+ begin
419
+ perform set_config('request.jwt.claims',
420
+ json_build_object('role', 'agent_board_delegate', 'sub', pg_temp.v('D.auth'), 'agent_credential_id', pg_temp.v('D.cred'))::text, true);
421
+ set local role agent_board_delegate;
422
+ begin
423
+ execute p_sql into v;
424
+ exception when others then
425
+ v := 'ERR ' || sqlstate || ':' || sqlerrm;
426
+ end;
427
+ reset role;
428
+ return v;
429
+ end $$;
430
+
431
+ -- Fixtures: an owner (real enrollment), keyed agents, four boards, and an exclusive member per
432
+ -- board so `agents` has a row that belongs to exactly one board.
433
+ insert into agent_board.identity_providers
434
+ (issuer, audience, supported, policy_approved, allowed_scopes, allowed_board_scopes, allowed_agent_kinds)
435
+ values ('https://portal.zrows.test', 'message-board', true, true, '{}', '{}', '{agent,human}');
436
+ do $$
437
+ declare r record;
438
+ begin
439
+ perform set_config('request.jwt.claims', '', true);
440
+ select * into r from agent_board.enroll_federated_human('https://portal.zrows.test', 'message-board', 'zrows-owner',
441
+ '{"sub": "zrows-owner", "email": "zrows@t.test", "email_verified": true}'::jsonb, 'Z Owner');
442
+ perform pg_temp.put('O', r.agent_id::text);
443
+ perform pg_temp.put('O.auth', r.auth_user_id::text);
444
+ select * into r from agent_board.exchange_delegate_credential(jsonb_build_object(
445
+ 'iss', 'https://portal.zrows.test', 'sub', 'zrows-owner', 'slot_resource', null,
446
+ 'agent_board_delegate_instance', jsonb_build_object('instance_id', 'zrows_instance_000001', 'grant_id', 'zrows_grant_00000001',
447
+ 'generation', 1, 'owner_sub', 'zrows-owner', 'client_id', 'zrows-client', 'status', 'active', 'client_change', null)));
448
+ perform pg_temp.put('D', r.agent_id::text);
449
+ perform pg_temp.put('D.auth', r.auth_user_id::text);
450
+ perform pg_temp.put('D.cred', r.credential_id::text);
451
+ end $$;
452
+
453
+ insert into auth.users(id, instance_id, aud, role, email)
454
+ select ('7a000000-0000-4000-8000-' || lpad(n::text, 12, '0'))::uuid, '00000000-0000-0000-0000-000000000000',
455
+ 'authenticated', 'authenticated', 'zrows' || n || '@t.test'
456
+ from generate_series(1, 6) n;
457
+ insert into agent_board.agents(id, agent_type, kind, handle, display_name, status, auth_user_id)
458
+ select ('7a100000-0000-4000-8000-' || lpad(n::text, 12, '0'))::uuid, 'agent', 'agent', 'zrows-keyed-' || n, 'Z ' || n, 'active',
459
+ ('7a000000-0000-4000-8000-' || lpad(n::text, 12, '0'))::uuid
460
+ from generate_series(1, 6) n;
461
+ -- K = 1 (owner of every board), K2 = 2 (member of BA and BN), exclusive members 3..6 of BA, BN, BR, BL.
462
+ select pg_temp.put('K', '7a100000-0000-4000-8000-000000000001'), pg_temp.put('K.auth', '7a000000-0000-4000-8000-000000000001'),
463
+ pg_temp.put('K2', '7a100000-0000-4000-8000-000000000002'), pg_temp.put('K2.auth', '7a000000-0000-4000-8000-000000000002');
464
+ insert into agent_board.boards(id, slug, name, created_by_agent_id, visibility, status)
465
+ select ('7a200000-0000-4000-8000-' || lpad(n::text, 12, '0'))::uuid, 'zrows-' || b, 'Z ' || b, pg_temp.u('K'), 'private', 'active'
466
+ from unnest(array['ba', 'bn', 'br', 'bl']) with ordinality as t(b, n);
467
+ select pg_temp.put('B' || upper(b), ('7a200000-0000-4000-8000-' || lpad(n::text, 12, '0')))
468
+ from unnest(array['a', 'n', 'r', 'l']) with ordinality as t(b, n);
469
+ select pg_temp.put('X' || upper(b), ('7a100000-0000-4000-8000-' || lpad((n + 2)::text, 12, '0')))
470
+ from unnest(array['a', 'n', 'r', 'l']) with ordinality as t(b, n);
471
+ insert into agent_board.board_memberships(board_id, agent_id, role, membership_state, created_by_agent_id)
472
+ select pg_temp.u('B' || b), pg_temp.u('K'), 'owner', 'joined', pg_temp.u('K') from unnest(array['A', 'N', 'R', 'L']) b
473
+ union all
474
+ select pg_temp.u('B' || b), pg_temp.u('X' || b), 'member', 'joined', pg_temp.u('K') from unnest(array['A', 'N', 'R', 'L']) b
475
+ union all
476
+ select pg_temp.u('B' || b), pg_temp.u('O'), 'member', 'joined', pg_temp.u('K') from unnest(array['A', 'R', 'L']) b
477
+ union all
478
+ select pg_temp.u('B' || b), pg_temp.u('K2'), 'member', 'joined', pg_temp.u('K') from unnest(array['A', 'N']) b;
479
+
480
+ -- The owner places its delegate on BA, BR and BL (not BN).
481
+ select pg_temp.authn(pg_temp.u('O.auth'));
482
+ select agent_board.add_delegate_to_board(pg_temp.u('D'), pg_temp.u('B' || b)) from unnest(array['A', 'R', 'L']) b;
483
+
484
+ -- On each board: a keyed post (thread T<b>), the delegate's own post (BA/BR/BL), a task
485
+ -- ASSIGNED TO THE DELEGATE with its event, a claim and an escalation, a tasking delivery to
486
+ -- the board, signature evidence over the keyed post, and a co-member's per-recipient inbox item.
487
+ do $$
488
+ declare b text; v_thread uuid; v_msg uuid; v_task uuid; v_dr uuid; v_ev uuid;
489
+ begin
490
+ foreach b in array array['A', 'N', 'R', 'L'] loop
491
+ perform pg_temp.authn(pg_temp.u('K.auth'));
492
+ select thread_id into v_thread from agent_board.create_or_find_thread(pg_temp.u('K'), 'zrows ' || b, 'zrows-' || b);
493
+ perform pg_temp.put('T' || b, v_thread::text);
494
+ select message_id into v_msg from agent_board.post_board_message(v_thread, pg_temp.u('K'), pg_temp.u('B' || b), 's', 'keyed on ' || b);
495
+ perform pg_temp.put('M' || b, v_msg::text);
496
+ if b <> 'N' then
497
+ perform set_config('request.jwt.claims', json_build_object('role', 'agent_board_delegate', 'sub', pg_temp.v('D.auth'),
498
+ 'agent_credential_id', pg_temp.v('D.cred'))::text, true);
499
+ perform agent_board.post_board_message(v_thread, null, pg_temp.u('B' || b), 's', 'delegate on ' || b);
500
+ end if;
501
+ -- seeded as the table owner, so the row exists whatever the writers refuse
502
+ insert into agent_board.tasks(thread_id, created_by_agent_id, assigned_agent_id, title, metadata)
503
+ values (v_thread, pg_temp.u('K'), pg_temp.u('D'), 'task on ' || b, jsonb_build_object('zrowsBoard', b))
504
+ returning id into v_task;
505
+ perform pg_temp.put('TK' || b, v_task::text);
506
+ insert into agent_board.task_events(task_id, thread_id, actor_agent_id, event_sequence, event_type, origin_posture)
507
+ values (v_task, v_thread, pg_temp.u('K'), 1, 'created', 'unattested:preexisting') returning id into v_ev;
508
+ insert into agent_board.claims(task_id, thread_id, agent_id, resource_kind, resource_key, lease_expires_at)
509
+ values (v_task, v_thread, pg_temp.u('K2'), 'task', 'zrows-' || b, now() + interval '1 hour');
510
+ insert into agent_board.escalations(thread_id, task_id, raised_by_agent_id, assigned_agent_id, summary)
511
+ values (v_thread, v_task, pg_temp.u('K'), pg_temp.u('D'), 'esc on ' || b);
512
+ insert into agent_board.delivery_recipients(delivery_mode, recipient_agent_id, source_kind, source_task_id, board_id, board_membership_id)
513
+ values ('tasking', pg_temp.u('K'), 'task', v_task, pg_temp.u('B' || b),
514
+ (select bm.id from agent_board.board_memberships bm
515
+ where bm.board_id = pg_temp.u('B' || b) and bm.agent_id = pg_temp.u('K') and bm.membership_state = 'joined'))
516
+ returning id into v_dr;
517
+ -- the co-member's (K's) per-recipient tasking row: a board, but NOT feed-visible
518
+ insert into agent_board.inbox_items(delivery_recipient_id, recipient_agent_id, board_id, delivery_mode, source_kind,
519
+ source_task_id, subject, visible_in_inbox, visible_in_board_feed)
520
+ values (v_dr, pg_temp.u('K'), pg_temp.u('B' || b), 'tasking', 'task', v_task, 'tasking on ' || b, true, false);
521
+ perform pg_temp.put('II' || b, (select id::text from agent_board.inbox_items where delivery_recipient_id = v_dr));
522
+ insert into agent_board.signature_evidence(agent_id, source_kind, source_message_id, operation, payload_digest, verification_status)
523
+ values (pg_temp.u('K'), 'message', v_msg, 'post_board_message', 'sha256:zrows', 'unsigned');
524
+ insert into agent_board.signature_evidence(agent_id, source_kind, source_task_event_id, operation, payload_digest, verification_status)
525
+ values (pg_temp.u('K'), 'task_event', v_ev, 'append_task_event', 'sha256:zrows', 'unsigned');
526
+ end loop;
527
+ end $$;
528
+
529
+ -- Then the delegate is REMOVED from BR (an admin) and LEFT on BL (its owner withdraws it).
530
+ select pg_temp.authn(pg_temp.u('K.auth'));
531
+ select agent_board.update_board_membership(pg_temp.u('BR'), pg_temp.u('D'), 'removed');
532
+ select pg_temp.authn(pg_temp.u('O.auth'));
533
+ select agent_board.update_board_membership(pg_temp.u('BL'), pg_temp.u('D'), 'left');
534
+
535
+ -- The count of rows of `rel` that belong to board `b`, AS the delegate. Each relation's notion
536
+ -- of "belongs to a board" is stated here; the SET of relations comes from the allow set, and a
537
+ -- relation with no statement is reported UNMAPPED (it fails, naming itself).
538
+ create function pg_temp.rows_of(p_rel text, p_b text) returns text language plpgsql as $$
539
+ declare q text;
540
+ begin
541
+ q := case p_rel
542
+ when 'boards' then format('select count(*) from agent_board.boards where id = %L', pg_temp.v('B' || p_b))
543
+ when 'board_memberships' then format('select count(*) from agent_board.board_memberships where board_id = %L', pg_temp.v('B' || p_b))
544
+ when 'agents' then format('select count(*) from agent_board.agents where id = %L', pg_temp.v('X' || p_b))
545
+ when 'messages' then format('select count(*) from agent_board.messages where thread_id = %L', pg_temp.v('T' || p_b))
546
+ when 'delivery_recipients' then format('select count(*) from agent_board.delivery_recipients where board_id = %L', pg_temp.v('B' || p_b))
547
+ when 'inbox_items' then format('select count(*) from agent_board.inbox_items where board_id = %L', pg_temp.v('B' || p_b))
548
+ when 'tasks' then format('select count(*) from agent_board.tasks where id = %L', pg_temp.v('TK' || p_b))
549
+ when 'task_events' then format('select count(*) from agent_board.task_events where task_id = %L', pg_temp.v('TK' || p_b))
550
+ when 'claims' then format('select count(*) from agent_board.claims where task_id = %L', pg_temp.v('TK' || p_b))
551
+ when 'escalations' then format('select count(*) from agent_board.escalations where task_id = %L', pg_temp.v('TK' || p_b))
552
+ when 'signature_evidence' then format('select count(*) from agent_board.signature_evidence se where se.source_message_id = %L
553
+ or se.source_task_event_id in (select te.id from agent_board.task_events te where te.task_id = %L)',
554
+ pg_temp.v('M' || p_b), pg_temp.v('TK' || p_b))
555
+ when 'presence' then 'select count(*) from agent_board.presence'
556
+ when 'agent_signing_keys' then 'select count(*) from agent_board.agent_signing_keys'
557
+ when 'v_board_feed' then format('select count(*) from agent_board.v_board_feed where board_id = %L', pg_temp.v('B' || p_b))
558
+ when 'v_thread_feed' then format('select count(*) from agent_board.v_thread_feed where thread_id = %L', pg_temp.v('T' || p_b))
559
+ when 'v_agent_inbox' then format('select count(*) from agent_board.v_agent_inbox where board_id = %L', pg_temp.v('B' || p_b))
560
+ when 'v_board_memberships' then format('select count(*) from agent_board.v_board_memberships where board_id = %L', pg_temp.v('B' || p_b))
561
+ when 'v_agent_dashboard' then format('select count(*) from agent_board.v_agent_dashboard where agent_id = %L', pg_temp.v('X' || p_b))
562
+ else null end;
563
+ if q is null then
564
+ return 'UNMAPPED';
565
+ end if;
566
+ return pg_temp.as_d_val(q);
567
+ end $$;
568
+
569
+ -- presence and agent_signing_keys have the frozen predicate `false`: a board-scoped positive
570
+ -- pair cannot exist for them, which assertion 17 pins (their qual IS `false`). Every other
571
+ -- relation must show the row on the active board.
572
+ create temp view _matrix as
573
+ select o.name,
574
+ pg_temp.rows_of(o.name, 'A') as on_active,
575
+ pg_temp.rows_of(o.name, 'N') as on_never,
576
+ pg_temp.rows_of(o.name, 'R') as on_removed,
577
+ pg_temp.rows_of(o.name, 'L') as on_left,
578
+ o.name in ('presence', 'agent_signing_keys') as no_positive
579
+ from agent_board.delegate_allowed_operations o
580
+ where o.kind in ('read_view', 'read_table');
581
+ create temp table _m as select * from _matrix;
582
+ -- The matrix, printed, so a reader sees the counts the four assertions below judge.
583
+ select diag('matrix (active/never/removed/left): ' || string_agg(name || '=' || on_active || '/' || on_never || '/' || on_removed || '/' || on_left, ' ' order by name)) from _m;
584
+ -- 33 -- the positive pair: every relation shows its row on the board the delegate is active on
585
+ select is(
586
+ (select coalesce(string_agg(name || '=' || on_active, ', ' order by name), '(none)')
587
+ from _m where not no_positive and not (on_active ~ '^[0-9]+$' and on_active::int > 0)),
588
+ '(none)',
589
+ 'D14 positive pair: every read relation shows the row on a board where the delegate is active');
590
+ -- 34
591
+ select is(
592
+ (select coalesce(string_agg(name || '=' || on_never, ', ' order by name), '(none)') from _m where on_never <> '0'),
593
+ '(none)',
594
+ 'D14: on a board the delegate was never on, every read relation shows ZERO rows (incl. a task ASSIGNED to it)');
595
+ -- 35
596
+ select is(
597
+ (select coalesce(string_agg(name || '=' || on_removed, ', ' order by name), '(none)') from _m where on_removed <> '0'),
598
+ '(none)',
599
+ 'D14: after its REMOVAL from a board, zero rows of that board -- even what it authored, received or was assigned');
600
+ -- 36
601
+ select is(
602
+ (select coalesce(string_agg(name || '=' || on_left, ', ' order by name), '(none)') from _m where on_left <> '0'),
603
+ '(none)',
604
+ 'D14: after it moves to LEFT on a board, zero rows of that board');
605
+
606
+ -- 37 -- boardless rows addressed to / authored by the delegate (seeded directly) are invisible
607
+ do $$
608
+ declare v_thread uuid; v_msg uuid; v_dr uuid;
609
+ begin
610
+ insert into agent_board.threads(thread_type, created_by_agent_id, subject) values ('coordination', pg_temp.u('D'), 'boardless')
611
+ returning id into v_thread;
612
+ insert into agent_board.messages(thread_id, author_agent_id, message_sequence, body)
613
+ values (v_thread, pg_temp.u('D'), 1, 'boardless by the delegate') returning id into v_msg;
614
+ insert into agent_board.delivery_recipients(delivery_mode, recipient_agent_id, source_kind, source_message_id, board_id)
615
+ values ('direct', pg_temp.u('D'), 'message', v_msg, null) returning id into v_dr;
616
+ insert into agent_board.inbox_items(delivery_recipient_id, recipient_agent_id, board_id, delivery_mode, source_kind, source_message_id, subject)
617
+ values (v_dr, pg_temp.u('D'), null, 'direct', 'message', v_msg, 'boardless');
618
+ insert into agent_board.presence(agent_id, availability) values (pg_temp.u('D'), 'ready');
619
+ perform pg_temp.put('BLM', v_msg::text);
620
+ end $$;
621
+ select is(
622
+ pg_temp.as_d_val(format($$ select concat_ws('/',
623
+ (select count(*) from agent_board.messages where id = %L),
624
+ (select count(*) from agent_board.delivery_recipients where source_message_id = %L),
625
+ (select count(*) from agent_board.inbox_items where source_message_id = %L),
626
+ (select count(*) from agent_board.presence)) $$, pg_temp.v('BLM'), pg_temp.v('BLM'), pg_temp.v('BLM'))),
627
+ '0/0/0/0',
628
+ 'D14: a boardless message it AUTHORED, a boardless delivery and inbox item ADDRESSED to it, and its own presence: invisible');
629
+
630
+ -- 38, 39 -- CROSS-BOARD POST: a message delivered only to BN, in a thread stamped BA
631
+ select pg_temp.authn(pg_temp.u('K.auth'));
632
+ select pg_temp.put('XB', (select message_id::text from agent_board.post_board_message(pg_temp.u('TA'), pg_temp.u('K'), pg_temp.u('BN'), 's', 'cross-board to BN')));
633
+ select is(
634
+ (select board_id::text from agent_board.threads where id = pg_temp.u('TA')) || ' ' ||
635
+ pg_temp.as_d_val(format($$ select count(*) from agent_board.messages where id = %L $$, pg_temp.v('XB'))),
636
+ pg_temp.v('BA') || ' 0',
637
+ 'D14 cross-board post: in a thread stamped BA, a message delivered only to BN is invisible to a delegate on BA');
638
+ select is(
639
+ pg_temp.as_d_val(format($$ select count(*) from agent_board.messages where id = %L $$, pg_temp.v('MA'))),
640
+ '1',
641
+ 'D14 cross-board post, paired: the BA post in the same thread is visible');
642
+
643
+ -- 40 -- REUSED DM THREAD: boardless DMs in a thread later stamped BA by a board post
644
+ do $$
645
+ declare v_thread uuid;
646
+ begin
647
+ perform pg_temp.authn(pg_temp.u('K.auth'));
648
+ select thread_id into v_thread from agent_board.create_or_find_thread(pg_temp.u('K'), 'dm then board', 'zrows-dm');
649
+ perform agent_board.send_direct_message(v_thread, pg_temp.u('K'), pg_temp.u('K2'), 's', 'the dm before');
650
+ perform pg_temp.put('DMT', v_thread::text);
651
+ perform agent_board.post_board_message(v_thread, pg_temp.u('K'), pg_temp.u('BA'), 's', 'the board post after');
652
+ end $$;
653
+ select is(
654
+ pg_temp.as_d_val(format($$ select string_agg(body, ',' order by body) from agent_board.messages where thread_id = %L $$, pg_temp.v('DMT'))),
655
+ 'the board post after',
656
+ 'D14 reused DM thread: the boardless DM in a thread later stamped BA is invisible; the board post is visible');
657
+
658
+ -- 41 -- A CO-MEMBER'S INBOX: K2's per-recipient item on BA is invisible; v_agent_inbox shows
659
+ -- only the delegate's own rows or feed-visible ones, and shows some
660
+ select is(
661
+ pg_temp.as_d_val(format($$ select concat_ws('/',
662
+ (select count(*) from agent_board.inbox_items where id = %L),
663
+ (select count(*) from agent_board.v_agent_inbox where not (recipient_agent_id = %L or visible_in_board_feed)),
664
+ (select (count(*) > 0)::text from agent_board.v_agent_inbox)) $$, pg_temp.v('IIA'), pg_temp.v('D'))),
665
+ '0/0/true',
666
+ 'D14 co-member inbox: a co-member''s (non-feed) per-recipient item is invisible; v_agent_inbox returns only own or feed-visible rows (and some)');
667
+
668
+ -- ===========================================================================
669
+ -- 11. DIFFERENTIAL: the shipped (InitPlan) policies show EXACTLY the contract's rows
670
+ -- ===========================================================================
671
+ -- The contract froze the D14 read rule as per-row predicates; the migration ships the same
672
+ -- rule with the caller's board set computed once per query. This compares, for every
673
+ -- read_table in the allow set (the list is read from the table, not written here), the row
674
+ -- ids the delegate SEES with the row ids the contract's predicates ADMIT, computed here as
675
+ -- the table owner from the rule itself. The fixture above holds every case the contract
676
+ -- names: active, never-member, removed and left boards; boardless rows addressed to and
677
+ -- authored by the delegate; a task assigned to it off-board; a cross-board post; a DM thread
678
+ -- later stamped by a board post; and a co-member's non-feed inbox row. A relation with no
679
+ -- reference rule here is reported UNMAPPED and fails.
680
+ create function pg_temp.oracle(p_rel text, p_d uuid) returns text language plpgsql as $$
681
+ declare q text; v text;
682
+ a text := format('(select bm.board_id from agent_board.board_memberships bm where bm.agent_id = %L and bm.membership_state in (''joined'', ''subscribed''))', p_d);
683
+ msg_vis text; task_vis text;
684
+ begin
685
+ msg_vis := 'exists (select 1 from agent_board.delivery_recipients d2 where d2.source_message_id = %s and d2.board_id is not null and d2.board_id in ' || a || ')';
686
+ task_vis := 'exists (select 1 from agent_board.delivery_recipients d3 where d3.source_task_id = %s and d3.board_id is not null and d3.board_id in ' || a || ')';
687
+ q := case p_rel
688
+ when 'boards' then 'select id from agent_board.boards where id in ' || a
689
+ when 'board_memberships' then format('select id from agent_board.board_memberships where agent_id = %L and membership_state in (''joined'', ''subscribed'')', p_d)
690
+ when 'agents' then format('select x.id from agent_board.agents x where x.id = %L
691
+ or exists (select 1 from agent_board.board_memberships o where o.agent_id = x.id and o.membership_state in (''joined'', ''subscribed'') and o.board_id in %s)
692
+ or exists (select 1 from agent_board.messages m where m.author_agent_id = x.id and %s)', p_d, a, format(msg_vis, 'm.id'))
693
+ when 'messages' then 'select m.id from agent_board.messages m where ' || format(msg_vis, 'm.id')
694
+ when 'delivery_recipients' then 'select id from agent_board.delivery_recipients where board_id is not null and board_id in ' || a
695
+ when 'inbox_items' then format('select id from agent_board.inbox_items where board_id is not null and board_id in %s and (recipient_agent_id = %L or visible_in_board_feed)', a, p_d)
696
+ when 'tasks' then 'select t.id from agent_board.tasks t where ' || format(task_vis, 't.id')
697
+ when 'task_events' then 'select te.id from agent_board.task_events te where ' || format(task_vis, 'te.task_id')
698
+ when 'claims' then 'select c.id from agent_board.claims c where c.task_id is not null and ' || format(task_vis, 'c.task_id')
699
+ when 'escalations' then 'select e.id from agent_board.escalations e where e.task_id is not null and ' || format(task_vis, 'e.task_id')
700
+ when 'signature_evidence' then 'select se.id from agent_board.signature_evidence se
701
+ where (se.source_message_id is not null or se.source_task_event_id is not null or se.source_delivery_recipient_id is not null)
702
+ and se.source_artifact_id is null
703
+ and (se.source_message_id is null or ' || format(msg_vis, 'se.source_message_id') || ')
704
+ and (se.source_task_event_id is null or exists (select 1 from agent_board.task_events te where te.id = se.source_task_event_id and ' || format(task_vis, 'te.task_id') || '))
705
+ and (se.source_delivery_recipient_id is null or exists (select 1 from agent_board.delivery_recipients dr where dr.id = se.source_delivery_recipient_id and dr.board_id is not null and dr.board_id in ' || a || '))'
706
+ when 'presence' then 'select agent_id from agent_board.presence where false'
707
+ when 'agent_signing_keys' then 'select id from agent_board.agent_signing_keys where false'
708
+ else null end;
709
+ if q is null then return 'UNMAPPED'; end if;
710
+ execute 'select coalesce(string_agg(z::text, '','' order by z::text), '''') from (' || q || ') s(z)' into v;
711
+ return v;
712
+ end $$;
713
+ create function pg_temp.seen(p_rel text) returns text language plpgsql as $$
714
+ begin
715
+ return coalesce(pg_temp.as_d_val(format('select coalesce(string_agg(%s::text, '','' order by %s::text), '''') from agent_board.%I',
716
+ case p_rel when 'presence' then 'agent_id' else 'id' end, case p_rel when 'presence' then 'agent_id' else 'id' end, p_rel)), '');
717
+ end $$;
718
+ create temp table _eq as
719
+ select o.name, pg_temp.oracle(o.name, pg_temp.u('D')) as contract_rows, pg_temp.seen(o.name) as seen_rows
720
+ from agent_board.delegate_allowed_operations o where o.kind = 'read_table';
721
+ select diag('differential (rows admitted by the contract rule / rows seen): ' || string_agg(name || '=' ||
722
+ (case when contract_rows = '' then 0 else array_length(string_to_array(contract_rows, ','), 1) end)::text || '/' ||
723
+ (case when seen_rows = '' then 0 else array_length(string_to_array(seen_rows, ','), 1) end)::text, ' ' order by name)) from _eq;
724
+ -- 42
725
+ select is(
726
+ (select coalesce(string_agg(name, ', ' order by name), '(none)') from _eq where contract_rows is distinct from seen_rows),
727
+ '(none)',
728
+ 'DIFFERENTIAL: for every read_table the delegate sees exactly the rows the contract''s per-row rule admits');
729
+ -- 43 -- not vacuous: the rule admits rows in every relation whose predicate is not `false`
730
+ select is(
731
+ (select count(*)::int from _eq where contract_rows <> '' and contract_rows <> 'UNMAPPED'),
732
+ 11,
733
+ 'DIFFERENTIAL is not vacuous: 11 of the 13 tables have admitted rows (presence and agent_signing_keys are `false` by contract)');
734
+
735
+ select * from finish();
736
+ rollback;