@consiliency/agent-board-schema 1.68.0 → 1.74.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 +28 -4
- package/migrations/20261026000100_agent_board_thread_association.sql +1287 -0
- package/migrations/20261101000100_agent_board_session_measured_mint.sql +145 -0
- package/migrations/20261104065658_agent_board_reply_delivery.sql +659 -0
- package/migrations/20261104170000_agent_board_tasking_replay_scope.sql +320 -0
- package/migrations/20261104180000_agent_board_delivery_writer_execute.sql +51 -0
- package/migrations/20261104190000_agent_board_message_replay_scope.sql +373 -0
- package/package.json +1 -1
- package/schema-manifest.json +57 -3
- package/src/tooling.test.mjs +8 -2
- package/tests/agent_board_661_reply_delivery.test.sql +185 -0
- package/tests/agent_board_667_boundary.test.sql +162 -0
- package/tests/agent_board_667_conversion_branches.test.sql +91 -0
- package/tests/agent_board_667_conversion_profile.test.sql +112 -0
- package/tests/agent_board_667_history_class.test.sql +785 -0
- package/tests/agent_board_667_native_cast_effect.test.sql +88 -0
- package/tests/agent_board_667_realtime_apply_behavior.test.sql +117 -0
- package/tests/agent_board_667_realtime_apply_controls.test.sql +143 -0
- package/tests/agent_board_667_realtime_apply_profile.test.sql +61 -0
- package/tests/agent_board_667_retention.test.sql +201 -0
- package/tests/agent_board_667_routing.test.sql +294 -0
- package/tests/agent_board_667_sender_effects.test.sql +100 -0
- package/tests/agent_board_667_sender_profile_controls.test.sql +29 -0
- package/tests/agent_board_667_storage_delimiter_behavior.test.sql +84 -0
- package/tests/agent_board_667_storage_delimiter_controls.test.sql +23 -0
- package/tests/agent_board_667_storage_delimiter_profile.test.sql +61 -0
- package/tests/agent_board_667_storage_search_behavior.test.sql +93 -0
- package/tests/agent_board_667_storage_search_controls.test.sql +22 -0
- package/tests/agent_board_667_storage_search_profile.test.sql +60 -0
- package/tests/agent_board_667_storage_timestamp_behavior.test.sql +58 -0
- package/tests/agent_board_667_storage_timestamp_controls.test.sql +22 -0
- package/tests/agent_board_667_storage_timestamp_profile.test.sql +54 -0
- package/tests/agent_board_667_writers.test.sql +281 -0
- package/tests/agent_board_717_message_replay_scope.test.sql +828 -0
- package/tests/agent_board_717_tasking_replay_scope.test.sql +661 -0
- package/tests/agent_board_addressing.test.sql +8 -5
- package/tests/agent_board_claim_subject_gate.test.sql +7 -3
- package/tests/agent_board_claimpolicy_race.test.sql +39 -11
- package/tests/agent_board_delegate_role_class.test.sql +33 -15
- package/tests/agent_board_delivery_writer_execute.test.sql +371 -0
- package/tests/agent_board_fk_lock_edges.test.sql +3 -0
- package/tests/agent_board_hosted_delegates.test.sql +5 -2
- package/tests/agent_board_inbox_rpcs.test.sql +5 -3
- package/tests/agent_board_obsgate.test.sql +8 -4
- package/tests/agent_board_obsgate4.test.sql +2 -2
- package/tests/agent_board_outbox_wake_ordering.test.sql +25 -2
- package/tests/agent_board_own_post_not_delivered.test.sql +11 -9
- package/tests/agent_board_session_identity_behavior_classes.test.sql +2 -2
- package/tests/agent_board_session_identity_limits.test.sql +1 -1
- package/tests/agent_board_session_identity_measured_mint.test.sql +342 -0
- package/tests/agent_board_session_identity_predicate_isolation.test.sql +146 -0
- package/tests/agent_board_sidserver_authority.test.sql +69 -0
- package/tests/agent_board_sidserver_catalog.test.sql +47 -0
- package/tests/agent_board_signed_write_gateway.test.sql +4 -2
- package/tests/agent_board_task_thread_lock_order.test.sql +67 -42
- package/tests/agent_board_v2_invariants.test.sql +5 -2
- package/tests/agent_board_write_enforcement_class.test.sql +3 -3
- package/tests/catalog/function_execute_privileges.json +41 -5
- package/tests/catalog/p_metadata_parameters.json +16 -0
- package/tests/fixtures/agent_board_667_apply_rls_guard.sql +195 -0
- package/tests/fixtures/agent_board_667_apply_rls_provenance.md +125 -0
- package/tests/fixtures/agent_board_667_apply_rls_reference.sql +1903 -0
- package/tests/fixtures/agent_board_667_conversion_guard.sql +162 -0
- package/tests/fixtures/agent_board_667_conversion_reference.md +23 -0
- package/tests/fixtures/agent_board_667_conversion_reference.sql +5325 -0
- package/tests/fixtures/agent_board_667_delimiter_guard.sql +92 -0
- package/tests/fixtures/agent_board_667_delimiter_provenance.md +116 -0
- package/tests/fixtures/agent_board_667_delimiter_reference.sql +10150 -0
- package/tests/fixtures/agent_board_667_search_guard.sql +92 -0
- package/tests/fixtures/agent_board_667_search_provenance.md +141 -0
- package/tests/fixtures/agent_board_667_search_reference.sql +4779 -0
- package/tests/fixtures/agent_board_667_sender_guard.sql +102 -0
- package/tests/fixtures/agent_board_667_sender_reference.md +20 -0
- package/tests/fixtures/agent_board_667_sender_reference.sql +875 -0
- package/tests/fixtures/agent_board_667_timestamp_graph.sql +84 -0
- package/tests/fixtures/agent_board_667_timestamp_guard.sql +94 -0
- package/tests/fixtures/agent_board_667_timestamp_provenance.md +99 -0
- package/tests/fixtures/agent_board_667_timestamp_reference.sql +2938 -0
- package/tests/isolation/expected/association_artifact_anchor_order.out +108 -0
- package/tests/isolation/expected/association_board_vs_board.out +71 -0
- package/tests/isolation/expected/association_post_wait_authority.out +77 -0
- package/tests/isolation/expected/association_strong_history_writers.out +203 -0
- package/tests/isolation/expected/association_strong_isolation.out +185 -0
- package/tests/isolation/expected/association_vs_artifact_claim_escalation.out +199 -0
- package/tests/isolation/expected/association_vs_heartbeat.out +78 -0
- package/tests/isolation/expected/association_vs_multi_anchor_artifact.out +67 -0
- package/tests/isolation/expected/association_vs_private_message.out +67 -0
- package/tests/isolation/expected/association_vs_task_and_conflict.out +133 -0
- package/tests/isolation/expected/association_vs_taskful_cross_thread.out +133 -0
- package/tests/isolation/expected/message_replay_scope.out +209 -0
- package/tests/isolation/expected/tasking_replay_scope.out +125 -0
- package/tests/isolation/specs/association_artifact_anchor_order.spec +46 -0
- package/tests/isolation/specs/association_board_vs_board.spec +37 -0
- package/tests/isolation/specs/association_post_wait_authority.spec +48 -0
- package/tests/isolation/specs/association_strong_history_writers.spec +61 -0
- package/tests/isolation/specs/association_strong_isolation.spec +50 -0
- package/tests/isolation/specs/association_vs_artifact_claim_escalation.spec +41 -0
- package/tests/isolation/specs/association_vs_heartbeat.spec +47 -0
- package/tests/isolation/specs/association_vs_multi_anchor_artifact.spec +38 -0
- package/tests/isolation/specs/association_vs_private_message.spec +33 -0
- package/tests/isolation/specs/association_vs_task_and_conflict.spec +38 -0
- package/tests/isolation/specs/association_vs_taskful_cross_thread.spec +42 -0
- package/tests/isolation/specs/message_replay_scope.spec +77 -0
- package/tests/isolation/specs/tasking_replay_scope.spec +72 -0
- package/tests/mutations/717-f1/M0_prefix_main_acl_and_comments.sql +11 -0
- package/tests/mutations/717-f1/M10_wrapper_stops_delegating.sql +7 -0
- package/tests/mutations/717-f1/M11_transitive_recipient_content.sql +8 -0
- package/tests/mutations/717-f1/M12_transitive_recipient_visibility.sql +8 -0
- package/tests/mutations/717-f1/M13_transitive_worker_content.sql +15 -0
- package/tests/mutations/717-f1/M1a_regrant_upsert_delivery_recipient.sql +1 -0
- package/tests/mutations/717-f1/M1b_regrant_upsert_inbox_item.sql +1 -0
- package/tests/mutations/717-f1/M1c_regrant_queue_inbox_callbacks.sql +1 -0
- package/tests/mutations/717-f1/M1d_regrant_queue_board_post_callbacks.sql +1 -0
- package/tests/mutations/717-f1/M1e_regrant_next_thread_message_sequence.sql +1 -0
- package/tests/mutations/717-f1/M2_blanket_schema_grant.sql +1 -0
- package/tests/mutations/717-f1/M3_new_overload_of_sink.sql +10 -0
- package/tests/mutations/717-f1/M4_new_route_calling_sink.sql +7 -0
- package/tests/mutations/717-f1/M5_actor_trusts_supplied_id.sql +5 -0
- package/tests/mutations/717-f1/M6_signed_route_granted_to_authenticated.sql +1 -0
- package/tests/mutations/717-f1/M7_worker_granted_to_authenticated.sql +1 -0
- package/tests/mutations/717-f1/M8_recipient_state_rewrites_visibility.sql +5 -0
- package/tests/mutations/717-f1/M9_public_route_revoked_from_service_role.sql +1 -0
- package/tests/mutations/717-f1/outbox_wake_ordering/W1_regrant_queue_inbox_callbacks.sql +1 -0
- package/tests/mutations/717-f1/outbox_wake_ordering/W2_revoke_worker_from_service_role.sql +1 -0
- package/tests/mutations/717-f1/outbox_wake_ordering/W3_invoker_caller_of_sink.sql +1 -0
- package/tests/mutations/717-f1/outbox_wake_ordering/W4_public_regrant_board_post_sink.sql +1 -0
- package/tests/mutations/717-f1/run.sh +17 -0
- package/tests/mutations/717-f2b/C1_new_delivery_route.sql +4 -0
- package/tests/mutations/717-f2b/C2_new_replay_lookup.sql +3 -0
- package/tests/mutations/717-f2b/C3_internal_regranted.sql +2 -0
- package/tests/mutations/717-f2b/C4_wrapper_writes_delivery.sql +9 -0
- package/tests/mutations/717-f2b/C5_class_member_dynamic_sql.sql +9 -0
- package/tests/mutations/717-f2b/C6_drop_board_scope_constraint.sql +2 -0
- package/tests/mutations/717-f2b/C7_state_private_helper_content.sql +14 -0
- package/tests/mutations/717-f2b/L1_dm_lock_split_by_recipient.sql +8 -0
- package/tests/mutations/717-f2b/L2_dm_lock_removed.sql +12 -0
- package/tests/mutations/717-f2b/L3_mc_lock_split_by_recipients.sql +8 -0
- package/tests/mutations/717-f2b/L4_mc_lock_removed.sql +12 -0
- package/tests/mutations/717-f2b/M0_prefix_definitions.sql +17 -0
- package/tests/mutations/717-f2b/M10_mc_lookup_any_author.sql +15 -0
- package/tests/mutations/717-f2b/M11_dm_swallow_refusal.sql +8 -0
- package/tests/mutations/717-f2b/M12_mc_swallow_refusal.sql +8 -0
- package/tests/mutations/717-f2b/M13_signed_dm_swallows_refusal.sql +32 -0
- package/tests/mutations/717-f2b/M14_signed_mc_swallows_refusal.sql +20 -0
- package/tests/mutations/717-f2b/M15_mc_any_source.sql +7 -0
- package/tests/mutations/717-f2b/M1_dm_drop_recipient_proof.sql +16 -0
- package/tests/mutations/717-f2b/M2_mc_drop_recipient_proof.sql +16 -0
- package/tests/mutations/717-f2b/M3_dm_metadata_as_proof.sql +12 -0
- package/tests/mutations/717-f2b/M4_mc_metadata_as_proof.sql +16 -0
- package/tests/mutations/717-f2b/M5_dm_any_mode.sql +11 -0
- package/tests/mutations/717-f2b/M6_dm_board_delivery_counts.sql +11 -0
- package/tests/mutations/717-f2b/M7_mc_any_mode.sql +11 -0
- package/tests/mutations/717-f2b/M8_dm_thread_stamp_as_proof.sql +12 -0
- package/tests/mutations/717-f2b/M9_dm_lookup_any_author.sql +15 -0
- package/tests/mutations/717-f2b/run.sh +82 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
-- #667: exercise every admitted retention branch against real rows. This is a
|
|
2
|
+
-- behavioral state check, not a proof about arbitrary dynamic SQL or concurrency.
|
|
3
|
+
create extension if not exists pgtap with schema extensions;
|
|
4
|
+
set search_path = extensions, public, agent_board;
|
|
5
|
+
begin;
|
|
6
|
+
select plan(62);
|
|
7
|
+
create temp table xb_retention_ids(kind text primary key,id uuid not null) on commit drop;
|
|
8
|
+
create temp table xb_retention_before(kind text primary key,row_data jsonb not null,row_count bigint not null) on commit drop;
|
|
9
|
+
select lives_ok($q$
|
|
10
|
+
do $setup$
|
|
11
|
+
declare a uuid:=gen_random_uuid(); th uuid:=gen_random_uuid(); other_th uuid:=gen_random_uuid(); tk uuid:=gen_random_uuid(); msg uuid:=gen_random_uuid(); other_msg uuid:=gen_random_uuid();
|
|
12
|
+
ev uuid:=gen_random_uuid(); board uuid:=gen_random_uuid(); bm uuid:=gen_random_uuid(); dr uuid:=gen_random_uuid();
|
|
13
|
+
ib uuid:=gen_random_uuid(); ep uuid:=gen_random_uuid(); sub uuid:=gen_random_uuid(); ob uuid:=gen_random_uuid(); att uuid:=gen_random_uuid();
|
|
14
|
+
suffix text:=substr(replace(gen_random_uuid()::text,'-',''),1,12);
|
|
15
|
+
begin
|
|
16
|
+
perform set_config('request.jwt.claim.role','service_role',true);
|
|
17
|
+
insert into agent_board.agents(id,agent_type,handle,display_name,status) values (a,'agent','xb-ret-'||suffix,'XB retention','active');
|
|
18
|
+
insert into agent_board.threads(id,thread_type,created_by_agent_id,subject) values (th,'coordination',a,'private retention'),(other_th,'coordination',a,'other retention anchor');
|
|
19
|
+
insert into agent_board.tasks(id,thread_id,created_by_agent_id,title) values (tk,th,a,'private task');
|
|
20
|
+
insert into agent_board.messages(id,thread_id,author_agent_id,message_sequence,body,metadata) values (msg,th,a,1,'private message',jsonb_build_object('note','keep')),(other_msg,other_th,a,1,'other retention message',jsonb_build_object('note','other'));
|
|
21
|
+
insert into agent_board.task_events(id,task_id,thread_id,actor_agent_id,event_sequence,event_type,payload,origin_posture) values (ev,tk,th,a,1,'created',jsonb_build_object('note','keep'),'unattested:signed-metadata-rpc');
|
|
22
|
+
insert into agent_board.presence(agent_id,thread_id,availability,activity_summary,expires_at,metadata) values (a,th,'ready','private activity',now()-interval '1 hour',jsonb_build_object('note','keep'));
|
|
23
|
+
insert into agent_board.boards(id,slug,name,created_by_agent_id,visibility,status) values (board,'xb-ret-'||suffix,'XB retention',a,'private','active');
|
|
24
|
+
insert into agent_board.board_memberships(id,board_id,agent_id,membership_state,created_by_agent_id,left_at,metadata) values (bm,board,a,'left',a,now()-interval '1 hour',jsonb_build_object('note','keep'));
|
|
25
|
+
insert into agent_board.delivery_recipients(id,delivery_mode,recipient_agent_id,source_kind,source_message_id,metadata) values (dr,'direct',a,'message',msg,jsonb_build_object('note','keep'));
|
|
26
|
+
insert into agent_board.inbox_items(id,delivery_recipient_id,recipient_agent_id,delivery_mode,source_kind,source_message_id,subject,metadata) values (ib,dr,a,'direct','message',msg,'private inbox',jsonb_build_object('note','keep'));
|
|
27
|
+
insert into agent_board.callback_endpoints(id,owner_agent_id,endpoint_url) values (ep,a,'https://example.test/'||suffix);
|
|
28
|
+
insert into agent_board.callback_subscriptions(id,endpoint_id,agent_id,subscription_scope,event_category) values (sub,ep,a,'own_inbox','inbox.item.delivered');
|
|
29
|
+
insert into agent_board.callback_outbox_events(id,endpoint_id,subscription_id,recipient_agent_id,inbox_item_id,event_category,delivery_mode,source_kind,source_message_id,idempotency_key,metadata) values (ob,ep,sub,a,ib,'inbox.item.delivered','direct','message',msg,'xb-ret-'||suffix,jsonb_build_object('note','keep'));
|
|
30
|
+
insert into agent_board.callback_delivery_attempts(id,outbox_event_id,endpoint_id,attempt_number,attempt_outcome,metadata) values (att,ob,ep,1,'delivered',jsonb_build_object('note','keep'));
|
|
31
|
+
insert into xb_retention_ids values ('messages',msg),('task_events',ev),('presence',a),('board_memberships',bm),('delivery_recipients',dr),('inbox_items',ib),('callback_outbox_events',ob),('callback_delivery_attempts',att),('thread',th),('other_thread',other_th),('other_message',other_msg),('board',board),('actor',a);
|
|
32
|
+
end $setup$;
|
|
33
|
+
$q$, 'XB retention fixtures are created');
|
|
34
|
+
-- Capture every row-level write across the application schema while each
|
|
35
|
+
-- retention branch runs. The fixture is already seeded; these are test-only
|
|
36
|
+
-- triggers inside this rolled-back transaction, never product triggers.
|
|
37
|
+
create temp table xb_retention_changes(table_name text, operation text, old_row jsonb, new_row jsonb) on commit drop;
|
|
38
|
+
create function pg_temp.xb_retention_capture() returns trigger language plpgsql as $body$
|
|
39
|
+
begin
|
|
40
|
+
insert into xb_retention_changes values (tg_table_schema || '.' || tg_table_name,tg_op,
|
|
41
|
+
case when tg_op='INSERT' then null else to_jsonb(old) end,
|
|
42
|
+
case when tg_op='DELETE' then null else to_jsonb(new) end);
|
|
43
|
+
if tg_op='DELETE' then return old; end if;
|
|
44
|
+
return new;
|
|
45
|
+
end $body$;
|
|
46
|
+
do $body$
|
|
47
|
+
declare r record;
|
|
48
|
+
begin
|
|
49
|
+
for r in select n.nspname,c.relname from pg_class c join pg_namespace n on n.oid=c.relnamespace
|
|
50
|
+
where n.nspname='agent_board' and c.relkind in ('r','p') and not c.relispartition order by c.oid
|
|
51
|
+
loop
|
|
52
|
+
execute format('create trigger xb_retention_capture after insert or update or delete on %I.%I for each row execute function pg_temp.xb_retention_capture()',r.nspname,r.relname);
|
|
53
|
+
end loop;
|
|
54
|
+
end $body$;
|
|
55
|
+
insert into xb_retention_before select 'messages',to_jsonb(x),(select count(*) from agent_board.messages) from agent_board.messages x where x.id=(select id from xb_retention_ids where kind='messages');
|
|
56
|
+
truncate xb_retention_changes;
|
|
57
|
+
select lives_ok($$select agent_board.mark_retention_metadata('messages',now()+interval '1 day',gen_random_uuid(),'xb-retention')$$,'XB retention messages executes');
|
|
58
|
+
select ok((select x.metadata ? 'ops_retained_at' from agent_board.messages x where x.id=(select id from xb_retention_ids where kind='messages')),'XB retention messages actually updates its row');
|
|
59
|
+
select is((select to_jsonb(x)-'metadata' from agent_board.messages x where x.id=(select id from xb_retention_ids where kind='messages')),
|
|
60
|
+
(select row_data-'metadata' from xb_retention_before where kind='messages'),'XB retention messages preserves every other column and anchor');
|
|
61
|
+
select is((select x.metadata-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason' from agent_board.messages x where x.id=(select id from xb_retention_ids where kind='messages')),
|
|
62
|
+
(select row_data->'metadata' from xb_retention_before where kind='messages'),'XB retention messages preserves existing content');
|
|
63
|
+
select is((select count(*) from agent_board.messages),(select row_count from xb_retention_before where kind='messages'),'XB retention messages inserts or deletes no row');
|
|
64
|
+
select is((select string_agg(distinct table_name || ':' || operation, ', ' order by table_name || ':' || operation) from xb_retention_changes),
|
|
65
|
+
'agent_board.messages:UPDATE', 'XB retention messages writes only its target with UPDATE');
|
|
66
|
+
select is((select count(*) from xb_retention_changes where table_name='agent_board.messages' and operation='UPDATE'
|
|
67
|
+
and ((old_row-'metadata') is distinct from (new_row-'metadata')
|
|
68
|
+
or (old_row->'metadata') is distinct from ((new_row->'metadata')-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason'))),
|
|
69
|
+
0::bigint, 'XB retention messages changes only allowed columns on every updated row');
|
|
70
|
+
insert into xb_retention_before select 'task_events',to_jsonb(x),(select count(*) from agent_board.task_events) from agent_board.task_events x where x.id=(select id from xb_retention_ids where kind='task_events');
|
|
71
|
+
truncate xb_retention_changes;
|
|
72
|
+
select lives_ok($$select agent_board.mark_retention_metadata('task_events',now()+interval '1 day',gen_random_uuid(),'xb-retention')$$,'XB retention task_events executes');
|
|
73
|
+
select ok((select x.payload ? 'ops_retained_at' from agent_board.task_events x where x.id=(select id from xb_retention_ids where kind='task_events')),'XB retention task_events actually updates its row');
|
|
74
|
+
select is((select to_jsonb(x)-'payload' from agent_board.task_events x where x.id=(select id from xb_retention_ids where kind='task_events')),
|
|
75
|
+
(select row_data-'payload' from xb_retention_before where kind='task_events'),'XB retention task_events preserves every other column and anchor');
|
|
76
|
+
select is((select x.payload-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason' from agent_board.task_events x where x.id=(select id from xb_retention_ids where kind='task_events')),
|
|
77
|
+
(select row_data->'payload' from xb_retention_before where kind='task_events'),'XB retention task_events preserves existing content');
|
|
78
|
+
select is((select count(*) from agent_board.task_events),(select row_count from xb_retention_before where kind='task_events'),'XB retention task_events inserts or deletes no row');
|
|
79
|
+
select is((select string_agg(distinct table_name || ':' || operation, ', ' order by table_name || ':' || operation) from xb_retention_changes),
|
|
80
|
+
'agent_board.task_events:UPDATE', 'XB retention task_events writes only its target with UPDATE');
|
|
81
|
+
select is((select count(*) from xb_retention_changes where table_name='agent_board.task_events' and operation='UPDATE'
|
|
82
|
+
and ((old_row-'payload') is distinct from (new_row-'payload')
|
|
83
|
+
or (old_row->'payload') is distinct from ((new_row->'payload')-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason'))),
|
|
84
|
+
0::bigint, 'XB retention task_events changes only allowed columns on every updated row');
|
|
85
|
+
insert into xb_retention_before select 'presence',to_jsonb(x),(select count(*) from agent_board.presence) from agent_board.presence x where x.agent_id=(select id from xb_retention_ids where kind='presence');
|
|
86
|
+
truncate xb_retention_changes;
|
|
87
|
+
select lives_ok($$select agent_board.mark_retention_metadata('presence',now()+interval '1 day',gen_random_uuid(),'xb-retention')$$,'XB retention presence executes');
|
|
88
|
+
select ok((select x.metadata ? 'ops_retained_at' from agent_board.presence x where x.agent_id=(select id from xb_retention_ids where kind='presence')),'XB retention presence actually updates its row');
|
|
89
|
+
select is((select to_jsonb(x)-'metadata'-'updated_at' from agent_board.presence x where x.agent_id=(select id from xb_retention_ids where kind='presence')),
|
|
90
|
+
(select row_data-'metadata'-'updated_at' from xb_retention_before where kind='presence'),'XB retention presence preserves every other column and anchor');
|
|
91
|
+
select is((select x.metadata-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason' from agent_board.presence x where x.agent_id=(select id from xb_retention_ids where kind='presence')),
|
|
92
|
+
(select row_data->'metadata' from xb_retention_before where kind='presence'),'XB retention presence preserves existing content');
|
|
93
|
+
select is((select count(*) from agent_board.presence),(select row_count from xb_retention_before where kind='presence'),'XB retention presence inserts or deletes no row');
|
|
94
|
+
select is((select string_agg(distinct table_name || ':' || operation, ', ' order by table_name || ':' || operation) from xb_retention_changes),
|
|
95
|
+
'agent_board.presence:UPDATE', 'XB retention presence writes only its target with UPDATE');
|
|
96
|
+
select is((select count(*) from xb_retention_changes where table_name='agent_board.presence' and operation='UPDATE'
|
|
97
|
+
and ((old_row-'metadata'-'updated_at') is distinct from (new_row-'metadata'-'updated_at')
|
|
98
|
+
or (old_row->'metadata') is distinct from ((new_row->'metadata')-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason'))),
|
|
99
|
+
0::bigint, 'XB retention presence changes only allowed columns on every updated row');
|
|
100
|
+
insert into xb_retention_before select 'callback_outbox_events',to_jsonb(x),(select count(*) from agent_board.callback_outbox_events) from agent_board.callback_outbox_events x where x.id=(select id from xb_retention_ids where kind='callback_outbox_events');
|
|
101
|
+
truncate xb_retention_changes;
|
|
102
|
+
select lives_ok($$select agent_board.mark_retention_metadata('callback_outbox_events',now()+interval '1 day',gen_random_uuid(),'xb-retention')$$,'XB retention callback_outbox_events executes');
|
|
103
|
+
select ok((select x.metadata ? 'ops_retained_at' from agent_board.callback_outbox_events x where x.id=(select id from xb_retention_ids where kind='callback_outbox_events')),'XB retention callback_outbox_events actually updates its row');
|
|
104
|
+
select is((select to_jsonb(x)-'metadata' from agent_board.callback_outbox_events x where x.id=(select id from xb_retention_ids where kind='callback_outbox_events')),
|
|
105
|
+
(select row_data-'metadata' from xb_retention_before where kind='callback_outbox_events'),'XB retention callback_outbox_events preserves every other column and anchor');
|
|
106
|
+
select is((select x.metadata-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason' from agent_board.callback_outbox_events x where x.id=(select id from xb_retention_ids where kind='callback_outbox_events')),
|
|
107
|
+
(select row_data->'metadata' from xb_retention_before where kind='callback_outbox_events'),'XB retention callback_outbox_events preserves existing content');
|
|
108
|
+
select is((select count(*) from agent_board.callback_outbox_events),(select row_count from xb_retention_before where kind='callback_outbox_events'),'XB retention callback_outbox_events inserts or deletes no row');
|
|
109
|
+
select is((select string_agg(distinct table_name || ':' || operation, ', ' order by table_name || ':' || operation) from xb_retention_changes),
|
|
110
|
+
'agent_board.callback_outbox_events:UPDATE', 'XB retention callback_outbox_events writes only its target with UPDATE');
|
|
111
|
+
select is((select count(*) from xb_retention_changes where table_name='agent_board.callback_outbox_events' and operation='UPDATE'
|
|
112
|
+
and ((old_row-'metadata') is distinct from (new_row-'metadata')
|
|
113
|
+
or (old_row->'metadata') is distinct from ((new_row->'metadata')-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason'))),
|
|
114
|
+
0::bigint, 'XB retention callback_outbox_events changes only allowed columns on every updated row');
|
|
115
|
+
insert into xb_retention_before select 'callback_delivery_attempts',to_jsonb(x),(select count(*) from agent_board.callback_delivery_attempts) from agent_board.callback_delivery_attempts x where x.id=(select id from xb_retention_ids where kind='callback_delivery_attempts');
|
|
116
|
+
truncate xb_retention_changes;
|
|
117
|
+
select lives_ok($$select agent_board.mark_retention_metadata('callback_delivery_attempts',now()+interval '1 day',gen_random_uuid(),'xb-retention')$$,'XB retention callback_delivery_attempts executes');
|
|
118
|
+
select ok((select x.metadata ? 'ops_retained_at' from agent_board.callback_delivery_attempts x where x.id=(select id from xb_retention_ids where kind='callback_delivery_attempts')),'XB retention callback_delivery_attempts actually updates its row');
|
|
119
|
+
select is((select to_jsonb(x)-'metadata' from agent_board.callback_delivery_attempts x where x.id=(select id from xb_retention_ids where kind='callback_delivery_attempts')),
|
|
120
|
+
(select row_data-'metadata' from xb_retention_before where kind='callback_delivery_attempts'),'XB retention callback_delivery_attempts preserves every other column and anchor');
|
|
121
|
+
select is((select x.metadata-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason' from agent_board.callback_delivery_attempts x where x.id=(select id from xb_retention_ids where kind='callback_delivery_attempts')),
|
|
122
|
+
(select row_data->'metadata' from xb_retention_before where kind='callback_delivery_attempts'),'XB retention callback_delivery_attempts preserves existing content');
|
|
123
|
+
select is((select count(*) from agent_board.callback_delivery_attempts),(select row_count from xb_retention_before where kind='callback_delivery_attempts'),'XB retention callback_delivery_attempts inserts or deletes no row');
|
|
124
|
+
select is((select string_agg(distinct table_name || ':' || operation, ', ' order by table_name || ':' || operation) from xb_retention_changes),
|
|
125
|
+
'agent_board.callback_delivery_attempts:UPDATE', 'XB retention callback_delivery_attempts writes only its target with UPDATE');
|
|
126
|
+
select is((select count(*) from xb_retention_changes where table_name='agent_board.callback_delivery_attempts' and operation='UPDATE'
|
|
127
|
+
and ((old_row-'metadata') is distinct from (new_row-'metadata')
|
|
128
|
+
or (old_row->'metadata') is distinct from ((new_row->'metadata')-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason'))),
|
|
129
|
+
0::bigint, 'XB retention callback_delivery_attempts changes only allowed columns on every updated row');
|
|
130
|
+
insert into xb_retention_before select 'inbox_items',to_jsonb(x),(select count(*) from agent_board.inbox_items) from agent_board.inbox_items x where x.id=(select id from xb_retention_ids where kind='inbox_items');
|
|
131
|
+
truncate xb_retention_changes;
|
|
132
|
+
select lives_ok($$select agent_board.mark_retention_metadata('inbox_items',now()+interval '1 day',gen_random_uuid(),'xb-retention')$$,'XB retention inbox_items executes');
|
|
133
|
+
select ok((select x.metadata ? 'ops_retained_at' from agent_board.inbox_items x where x.id=(select id from xb_retention_ids where kind='inbox_items')),'XB retention inbox_items actually updates its row');
|
|
134
|
+
select is((select to_jsonb(x)-'metadata' from agent_board.inbox_items x where x.id=(select id from xb_retention_ids where kind='inbox_items')),
|
|
135
|
+
(select row_data-'metadata' from xb_retention_before where kind='inbox_items'),'XB retention inbox_items preserves every other column and anchor');
|
|
136
|
+
select is((select x.metadata-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason' from agent_board.inbox_items x where x.id=(select id from xb_retention_ids where kind='inbox_items')),
|
|
137
|
+
(select row_data->'metadata' from xb_retention_before where kind='inbox_items'),'XB retention inbox_items preserves existing content');
|
|
138
|
+
select is((select count(*) from agent_board.inbox_items),(select row_count from xb_retention_before where kind='inbox_items'),'XB retention inbox_items inserts or deletes no row');
|
|
139
|
+
select is((select string_agg(distinct table_name || ':' || operation, ', ' order by table_name || ':' || operation) from xb_retention_changes),
|
|
140
|
+
'agent_board.inbox_items:UPDATE', 'XB retention inbox_items writes only its target with UPDATE');
|
|
141
|
+
select is((select count(*) from xb_retention_changes where table_name='agent_board.inbox_items' and operation='UPDATE'
|
|
142
|
+
and ((old_row-'metadata') is distinct from (new_row-'metadata')
|
|
143
|
+
or (old_row->'metadata') is distinct from ((new_row->'metadata')-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason'))),
|
|
144
|
+
0::bigint, 'XB retention inbox_items changes only allowed columns on every updated row');
|
|
145
|
+
insert into xb_retention_before select 'delivery_recipients',to_jsonb(x),(select count(*) from agent_board.delivery_recipients) from agent_board.delivery_recipients x where x.id=(select id from xb_retention_ids where kind='delivery_recipients');
|
|
146
|
+
truncate xb_retention_changes;
|
|
147
|
+
select lives_ok($$select agent_board.mark_retention_metadata('delivery_recipients',now()+interval '1 day',gen_random_uuid(),'xb-retention')$$,'XB retention delivery_recipients executes');
|
|
148
|
+
select ok((select x.metadata ? 'ops_retained_at' from agent_board.delivery_recipients x where x.id=(select id from xb_retention_ids where kind='delivery_recipients')),'XB retention delivery_recipients actually updates its row');
|
|
149
|
+
select is((select to_jsonb(x)-'metadata' from agent_board.delivery_recipients x where x.id=(select id from xb_retention_ids where kind='delivery_recipients')),
|
|
150
|
+
(select row_data-'metadata' from xb_retention_before where kind='delivery_recipients'),'XB retention delivery_recipients preserves every other column and anchor');
|
|
151
|
+
select is((select x.metadata-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason' from agent_board.delivery_recipients x where x.id=(select id from xb_retention_ids where kind='delivery_recipients')),
|
|
152
|
+
(select row_data->'metadata' from xb_retention_before where kind='delivery_recipients'),'XB retention delivery_recipients preserves existing content');
|
|
153
|
+
select is((select count(*) from agent_board.delivery_recipients),(select row_count from xb_retention_before where kind='delivery_recipients'),'XB retention delivery_recipients inserts or deletes no row');
|
|
154
|
+
select is((select string_agg(distinct table_name || ':' || operation, ', ' order by table_name || ':' || operation) from xb_retention_changes),
|
|
155
|
+
'agent_board.delivery_recipients:UPDATE', 'XB retention delivery_recipients writes only its target with UPDATE');
|
|
156
|
+
select is((select count(*) from xb_retention_changes where table_name='agent_board.delivery_recipients' and operation='UPDATE'
|
|
157
|
+
and ((old_row-'metadata') is distinct from (new_row-'metadata')
|
|
158
|
+
or (old_row->'metadata') is distinct from ((new_row->'metadata')-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason'))),
|
|
159
|
+
0::bigint, 'XB retention delivery_recipients changes only allowed columns on every updated row');
|
|
160
|
+
insert into xb_retention_before select 'board_memberships',to_jsonb(x),(select count(*) from agent_board.board_memberships) from agent_board.board_memberships x where x.id=(select id from xb_retention_ids where kind='board_memberships');
|
|
161
|
+
truncate xb_retention_changes;
|
|
162
|
+
select lives_ok($$select agent_board.mark_retention_metadata('board_memberships',now()+interval '1 day',gen_random_uuid(),'xb-retention')$$,'XB retention board_memberships executes');
|
|
163
|
+
select ok((select x.metadata ? 'ops_retained_at' from agent_board.board_memberships x where x.id=(select id from xb_retention_ids where kind='board_memberships')),'XB retention board_memberships actually updates its row');
|
|
164
|
+
select is((select to_jsonb(x)-'metadata'-'updated_at' from agent_board.board_memberships x where x.id=(select id from xb_retention_ids where kind='board_memberships')),
|
|
165
|
+
(select row_data-'metadata'-'updated_at' from xb_retention_before where kind='board_memberships'),'XB retention board_memberships preserves every other column and anchor');
|
|
166
|
+
select is((select x.metadata-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason' from agent_board.board_memberships x where x.id=(select id from xb_retention_ids where kind='board_memberships')),
|
|
167
|
+
(select row_data->'metadata' from xb_retention_before where kind='board_memberships'),'XB retention board_memberships preserves existing content');
|
|
168
|
+
select is((select count(*) from agent_board.board_memberships),(select row_count from xb_retention_before where kind='board_memberships'),'XB retention board_memberships inserts or deletes no row');
|
|
169
|
+
select is((select string_agg(distinct table_name || ':' || operation, ', ' order by table_name || ':' || operation) from xb_retention_changes),
|
|
170
|
+
'agent_board.board_memberships:UPDATE', 'XB retention board_memberships writes only its target with UPDATE');
|
|
171
|
+
select is((select count(*) from xb_retention_changes where table_name='agent_board.board_memberships' and operation='UPDATE'
|
|
172
|
+
and ((old_row-'metadata'-'updated_at') is distinct from (new_row-'metadata'-'updated_at')
|
|
173
|
+
or (old_row->'metadata') is distinct from ((new_row->'metadata')-'ops_retained_at'-'ops_retention_run_id'-'ops_retention_reason'))),
|
|
174
|
+
0::bigint, 'XB retention board_memberships changes only allowed columns on every updated row');
|
|
175
|
+
-- Enumerate candidate table names from the catalog, and actually invoke the
|
|
176
|
+
-- validator with a cutoff that cannot select a row. This is a finite catalog
|
|
177
|
+
-- check; the injected table additionally proves a new valid target is refused.
|
|
178
|
+
create table agent_board.xb_retention_candidate(id uuid primary key default gen_random_uuid(), metadata jsonb not null default '{}'::jsonb, created_at timestamptz not null default now());
|
|
179
|
+
insert into agent_board.xb_retention_candidate(metadata) values (jsonb_build_object('note','unrelated'));
|
|
180
|
+
create function pg_temp.xb_retention_probe(p_target text) returns text language plpgsql as $body$
|
|
181
|
+
begin
|
|
182
|
+
perform agent_board.mark_retention_metadata(p_target,'-infinity'::timestamptz,gen_random_uuid(),'probe');
|
|
183
|
+
return 'accepted';
|
|
184
|
+
exception when sqlstate '22023' then return 'rejected';
|
|
185
|
+
when others then return 'ERROR:' || sqlstate;
|
|
186
|
+
end $body$;
|
|
187
|
+
select is((with tested as materialized (
|
|
188
|
+
select c.relname::text as name, pg_temp.xb_retention_probe(c.relname::text) as outcome
|
|
189
|
+
from pg_class c join pg_namespace n on n.oid=c.relnamespace
|
|
190
|
+
where n.nspname='agent_board' and c.relkind in ('r','p'))
|
|
191
|
+
select string_agg(name || '=' || outcome, ', ' order by name) from tested where outcome<>'rejected'),
|
|
192
|
+
'board_memberships=accepted, callback_delivery_attempts=accepted, callback_outbox_events=accepted, delivery_recipients=accepted, inbox_items=accepted, messages=accepted, presence=accepted, task_events=accepted',
|
|
193
|
+
'XB retention validator accepts exactly the eight catalog tables');
|
|
194
|
+
select throws_ok($$select agent_board.mark_retention_metadata('xb_retention_candidate',now()+interval '1 day',gen_random_uuid(),'xb')$$,
|
|
195
|
+
'22023','unsupported retention table xb_retention_candidate','XB retention rejects an injected unrelated table');
|
|
196
|
+
select is((select metadata from agent_board.xb_retention_candidate),jsonb_build_object('note','unrelated'),
|
|
197
|
+
'XB rejected unrelated table remains unchanged');
|
|
198
|
+
select throws_ok($$select agent_board.mark_retention_metadata('tasks',now()+interval '1 day',gen_random_uuid(),'xb')$$,'22023','unsupported retention table tasks','XB retention rejects a non-admitted target');
|
|
199
|
+
select throws_ok($$select * from agent_board.post_board_message((select id from xb_retention_ids where kind='thread'),(select id from xb_retention_ids where kind='actor'),(select id from xb_retention_ids where kind='board'),'s','b')$$,'42501','thread has private history','XB retained private history still refuses association');
|
|
200
|
+
select * from finish();
|
|
201
|
+
rollback;
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
-- #667: descriptor and signed caller routes retain their resolved targets and
|
|
2
|
+
-- private delivery scope. All RPCs are caught before state is asserted.
|
|
3
|
+
create extension if not exists pgtap with schema extensions;
|
|
4
|
+
set search_path = extensions, public, agent_board;
|
|
5
|
+
begin;
|
|
6
|
+
select plan(39);
|
|
7
|
+
create temp table xb_route(actor uuid,r1 uuid,r2 uuid,board1 uuid,board2 uuid,slug1 text,slug2 text) on commit drop;
|
|
8
|
+
create temp table xb_route_thread(kind text primary key,id uuid not null) on commit drop;
|
|
9
|
+
select lives_ok($q$
|
|
10
|
+
do $setup$
|
|
11
|
+
declare a uuid:=gen_random_uuid(); r1 uuid:=gen_random_uuid(); r2 uuid:=gen_random_uuid(); b1 uuid:=gen_random_uuid(); b2 uuid:=gen_random_uuid();
|
|
12
|
+
suffix text:=replace(gen_random_uuid()::text,'-',''); endpoint uuid:=gen_random_uuid(); membership uuid; t record;
|
|
13
|
+
begin
|
|
14
|
+
perform set_config('request.jwt.claim.role','service_role',true);
|
|
15
|
+
insert into agent_board.agents(id,agent_type,handle,display_name,status) values
|
|
16
|
+
(a,'agent','xb-route-a-'||suffix,'XB route actor','active'),
|
|
17
|
+
(r1,'agent','xb-route-r1-'||suffix,'XB recipient one','active'),
|
|
18
|
+
(r2,'agent','xb-route-r2-'||suffix,'XB recipient two','active');
|
|
19
|
+
insert into agent_board.boards(id,slug,name,created_by_agent_id,visibility,status) values
|
|
20
|
+
(b1,'xb-route-one-'||suffix,'XB route one',a,'private','active'),
|
|
21
|
+
(b2,'xb-route-two-'||suffix,'XB route two',a,'private','active');
|
|
22
|
+
insert into agent_board.board_memberships(board_id,agent_id,membership_state,created_by_agent_id,role)
|
|
23
|
+
values(b1,a,'joined',a,'member'),(b1,r1,'joined',a,'member'),(b2,a,'joined',a,'member'),(b2,r2,'joined',a,'member');
|
|
24
|
+
select id into membership from agent_board.board_memberships where board_id=b1 and agent_id=r1;
|
|
25
|
+
insert into agent_board.callback_endpoints(id,owner_agent_id,endpoint_url,endpoint_status)
|
|
26
|
+
values(endpoint,r1,'https://example.test/xb-'||suffix,'verified');
|
|
27
|
+
insert into agent_board.callback_subscriptions(endpoint_id,agent_id,subscription_scope,event_category,board_id,board_membership_id)
|
|
28
|
+
values(endpoint,r1,'own_inbox','inbox.item.delivered',null,null),
|
|
29
|
+
(endpoint,r1,'board','board.post.delivered',b1,membership);
|
|
30
|
+
insert into xb_route values(a,r1,r2,b1,b2,'xb-route-one-'||suffix,'xb-route-two-'||suffix);
|
|
31
|
+
insert into xb_route_thread select kind,gen_random_uuid() from unnest(array['post','task','direct','multi','signed_direct','signed_multi','alternate','fail_desc_post','fail_desc_task','fail_signed_post','fail_signed_task','signed_task_positive','signed_multi_desc','signed_task_desc']) kind;
|
|
32
|
+
insert into agent_board.threads(id,thread_type,created_by_agent_id,subject)
|
|
33
|
+
select id,'coordination',a,kind from xb_route_thread;
|
|
34
|
+
insert into agent_board.messages(thread_id,author_agent_id,message_sequence,body)
|
|
35
|
+
values((select id from xb_route_thread where kind='alternate'),a,1,'XB alternate source');
|
|
36
|
+
insert into agent_board.tasks(thread_id,created_by_agent_id,title)
|
|
37
|
+
values((select id from xb_route_thread where kind='alternate'),a,'XB alternate task');
|
|
38
|
+
insert into agent_board.task_events(task_id,thread_id,actor_agent_id,event_sequence,event_type,payload,origin_posture)
|
|
39
|
+
select id,thread_id,a,1,'created','{}'::jsonb,'unattested:signed-metadata-rpc'
|
|
40
|
+
from agent_board.tasks where thread_id=(select id from xb_route_thread where kind='alternate');
|
|
41
|
+
for t in select id from xb_route_thread where kind in ('direct','multi','signed_direct','signed_multi','signed_multi_desc') loop
|
|
42
|
+
perform agent_board._associate_empty_thread(t.id,b1);
|
|
43
|
+
end loop;
|
|
44
|
+
end $setup$;
|
|
45
|
+
$q$, 'XB routing fixtures and already-associated private routes are created');
|
|
46
|
+
select lives_ok($$select * from agent_board.post_board_message((select id from xb_route_thread where kind='post'),(select actor from xb_route),
|
|
47
|
+
(select slug1 from xb_route),'addressing_v1','descriptor post','descriptor post body','comment','medium',null,'{}'::jsonb)$$,
|
|
48
|
+
'XB board slug post succeeds');
|
|
49
|
+
select ok(exists(select 1 from agent_board.messages m join agent_board.threads t on t.id=m.thread_id
|
|
50
|
+
where t.id=(select id from xb_route_thread where kind='post') and t.board_id=(select board1 from xb_route) and m.body='descriptor post body'),
|
|
51
|
+
'XB board slug post uses its resolved board and thread');
|
|
52
|
+
select lives_ok($$select * from agent_board.create_tasking_delivery((select id from xb_route_thread where kind='task'),(select actor from xb_route),
|
|
53
|
+
'descriptor task',null,jsonb_build_array(jsonb_build_object('kind','agent_id','agentId',(select r1::text from xb_route))),
|
|
54
|
+
(select slug1 from xb_route),'addressing_v1','medium','distributed',null,'{}'::jsonb)$$,
|
|
55
|
+
'XB descriptor board task succeeds');
|
|
56
|
+
select ok(exists(select 1 from agent_board.tasks t join agent_board.threads th on th.id=t.thread_id
|
|
57
|
+
join agent_board.delivery_recipients d on d.source_task_id=t.id where th.id=(select id from xb_route_thread where kind='task')
|
|
58
|
+
and th.board_id=(select board1 from xb_route) and d.recipient_agent_id=(select r1 from xb_route) and d.board_id is null),
|
|
59
|
+
'XB descriptor task resolves board and preserves explicit private recipient');
|
|
60
|
+
select lives_ok($$select * from agent_board.send_direct_message((select id from xb_route_thread where kind='direct'),(select actor from xb_route),
|
|
61
|
+
jsonb_build_object('kind','agent_id','agentId',(select r1::text from xb_route)),'addressing_v1','direct','descriptor direct body','comment','medium',null,'{}'::jsonb)$$,
|
|
62
|
+
'XB descriptor direct message succeeds');
|
|
63
|
+
select ok(exists(select 1 from agent_board.messages m join agent_board.delivery_recipients d on d.source_message_id=m.id
|
|
64
|
+
where m.thread_id=(select id from xb_route_thread where kind='direct') and m.body='descriptor direct body'
|
|
65
|
+
and d.recipient_agent_id=(select r1 from xb_route) and d.board_id is null)
|
|
66
|
+
and not exists(select 1 from agent_board.messages m join agent_board.delivery_recipients d on d.source_message_id=m.id
|
|
67
|
+
where m.thread_id=(select id from xb_route_thread where kind='direct') and d.recipient_agent_id=(select r2 from xb_route)),
|
|
68
|
+
'XB descriptor direct message reaches only the requested private recipient');
|
|
69
|
+
select lives_ok($$select * from agent_board.send_multicast_message((select id from xb_route_thread where kind='multi'),(select actor from xb_route),
|
|
70
|
+
jsonb_build_array(jsonb_build_object('kind','agent_id','agentId',(select r1::text from xb_route))),
|
|
71
|
+
'addressing_v1','multi','descriptor multi body','comment','medium',null,'{}'::jsonb)$$,
|
|
72
|
+
'XB descriptor multicast succeeds');
|
|
73
|
+
select ok(exists(select 1 from agent_board.messages m join agent_board.delivery_recipients d on d.source_message_id=m.id
|
|
74
|
+
where m.thread_id=(select id from xb_route_thread where kind='multi') and m.body='descriptor multi body'
|
|
75
|
+
and d.recipient_agent_id=(select r1 from xb_route) and d.board_id is null)
|
|
76
|
+
and not exists(select 1 from agent_board.messages m join agent_board.delivery_recipients d on d.source_message_id=m.id
|
|
77
|
+
where m.thread_id=(select id from xb_route_thread where kind='multi') and d.recipient_agent_id=(select r2 from xb_route)),
|
|
78
|
+
'XB descriptor multicast reaches only the requested private recipient');
|
|
79
|
+
select lives_ok($$select * from agent_board.signed_send_direct_message(jsonb_build_object('p_thread_id',(select id from xb_route_thread where kind='signed_direct'),
|
|
80
|
+
'p_author_agent_id',(select actor from xb_route),'p_recipient_agent_id',(select r1 from xb_route),'p_subject','signed direct','p_body','signed direct body'),
|
|
81
|
+
jsonb_build_object('agent_id',(select actor from xb_route),'verification_status','warn','payload_digest','sha256:'||repeat('c',64),'enforcement_mode','warn'))$$,
|
|
82
|
+
'XB signed direct message succeeds');
|
|
83
|
+
select ok(exists(select 1 from agent_board.messages m join agent_board.delivery_recipients d on d.source_message_id=m.id
|
|
84
|
+
join agent_board.signature_evidence e on e.source_message_id=m.id where m.thread_id=(select id from xb_route_thread where kind='signed_direct')
|
|
85
|
+
and m.body='signed direct body' and d.recipient_agent_id=(select r1 from xb_route) and d.board_id is null
|
|
86
|
+
and e.agent_id=(select actor from xb_route) and e.operation='send_direct_message' and e.verification_status='warn'),
|
|
87
|
+
'XB signed direct retains private recipient, actor and linked evidence');
|
|
88
|
+
select lives_ok($$select * from agent_board.signed_send_multicast_message(jsonb_build_object('p_thread_id',(select id from xb_route_thread where kind='signed_multi'),
|
|
89
|
+
'p_author_agent_id',(select actor from xb_route),'p_recipient_agent_ids',jsonb_build_array((select r1 from xb_route)),'p_subject','signed multi','p_body','signed multi body'),
|
|
90
|
+
jsonb_build_object('agent_id',(select actor from xb_route),'verification_status','warn','payload_digest','sha256:'||repeat('d',64),'enforcement_mode','warn'))$$,
|
|
91
|
+
'XB signed multicast succeeds');
|
|
92
|
+
select ok(exists(select 1 from agent_board.messages m join agent_board.delivery_recipients d on d.source_message_id=m.id
|
|
93
|
+
join agent_board.signature_evidence e on e.source_message_id=m.id where m.thread_id=(select id from xb_route_thread where kind='signed_multi')
|
|
94
|
+
and m.body='signed multi body' and d.recipient_agent_id=(select r1 from xb_route) and d.board_id is null
|
|
95
|
+
and e.agent_id=(select actor from xb_route) and e.operation='send_multicast_message' and e.verification_status='warn'),
|
|
96
|
+
'XB signed multicast retains private recipient, actor and linked evidence');
|
|
97
|
+
-- Positively bind the common inbox/callback descendants to their actual
|
|
98
|
+
-- message/task parents, rather than relying only on validated foreign keys.
|
|
99
|
+
select ok(exists(select 1 from agent_board.messages m join agent_board.delivery_recipients d on d.source_message_id=m.id
|
|
100
|
+
join agent_board.inbox_items i on i.delivery_recipient_id=d.id and i.source_message_id=m.id
|
|
101
|
+
join agent_board.callback_outbox_events o on o.inbox_item_id=i.id and o.source_message_id=m.id
|
|
102
|
+
where m.thread_id=(select id from xb_route_thread where kind='direct') and d.recipient_agent_id=(select r1 from xb_route)),
|
|
103
|
+
'XB direct inbox and callback retain their actual message parent');
|
|
104
|
+
select ok(exists(select 1 from agent_board.tasks t join agent_board.delivery_recipients d on d.source_task_id=t.id
|
|
105
|
+
join agent_board.inbox_items i on i.delivery_recipient_id=d.id and i.source_task_id=t.id
|
|
106
|
+
join agent_board.callback_outbox_events o on o.inbox_item_id=i.id and o.source_task_id=t.id
|
|
107
|
+
where t.thread_id=(select id from xb_route_thread where kind='task') and d.recipient_agent_id=(select r1 from xb_route)),
|
|
108
|
+
'XB task inbox and callback retain their actual task parent');
|
|
109
|
+
select ok(exists(select 1 from agent_board.messages m join agent_board.callback_outbox_events o on o.source_message_id=m.id
|
|
110
|
+
where m.thread_id=(select id from xb_route_thread where kind='post') and o.board_id=(select board1 from xb_route)
|
|
111
|
+
and o.event_category='board.post.delivered' and o.recipient_agent_id=(select r1 from xb_route)),
|
|
112
|
+
'XB board callback retains its actual message and board parent');
|
|
113
|
+
-- Fail only after observing the relevant stamp, source and delivery. This
|
|
114
|
+
-- makes a rollback witness distinguish a late failure from a setup refusal.
|
|
115
|
+
create function pg_temp.xb_fail_descriptor_inbox() returns trigger language plpgsql as $body$
|
|
116
|
+
begin
|
|
117
|
+
if new.subject='XB fail descriptor post' then
|
|
118
|
+
if not exists(select 1 from agent_board.messages m join agent_board.threads th on th.id=m.thread_id
|
|
119
|
+
join agent_board.delivery_recipients d on d.source_message_id=m.id
|
|
120
|
+
where m.id=new.source_message_id and th.board_id=(select board1 from xb_route) and d.id=new.delivery_recipient_id) then
|
|
121
|
+
raise exception 'XB descriptor post did not reach stamped delivery' using errcode='P0001';
|
|
122
|
+
end if;
|
|
123
|
+
raise exception 'XB descriptor post late failure' using errcode='P0001';
|
|
124
|
+
elsif new.subject='XB fail descriptor task' then
|
|
125
|
+
if not exists(select 1 from agent_board.tasks t join agent_board.threads th on th.id=t.thread_id
|
|
126
|
+
join agent_board.delivery_recipients d on d.source_task_id=t.id
|
|
127
|
+
where t.id=new.source_task_id and th.board_id=(select board1 from xb_route) and d.id=new.delivery_recipient_id) then
|
|
128
|
+
raise exception 'XB descriptor task did not reach stamped delivery' using errcode='P0001';
|
|
129
|
+
end if;
|
|
130
|
+
raise exception 'XB descriptor task late failure' using errcode='P0001';
|
|
131
|
+
end if;
|
|
132
|
+
return new;
|
|
133
|
+
end $body$;
|
|
134
|
+
create trigger xb_fail_descriptor_inbox before insert on agent_board.inbox_items for each row execute function pg_temp.xb_fail_descriptor_inbox();
|
|
135
|
+
create function pg_temp.xb_fail_signed_evidence() returns trigger language plpgsql as $body$
|
|
136
|
+
begin
|
|
137
|
+
if new.operation='post_board_message' and exists(select 1 from agent_board.messages where id=new.source_message_id and body='XB fail signed post') then
|
|
138
|
+
if not exists(select 1 from agent_board.messages m join agent_board.threads th on th.id=m.thread_id
|
|
139
|
+
join agent_board.delivery_recipients d on d.source_message_id=m.id join agent_board.inbox_items i on i.delivery_recipient_id=d.id
|
|
140
|
+
where m.id=new.source_message_id and th.board_id=(select board1 from xb_route)) then
|
|
141
|
+
raise exception 'XB signed post did not reach stamped inbox' using errcode='P0001';
|
|
142
|
+
end if;
|
|
143
|
+
raise exception 'XB signed post late failure' using errcode='P0001';
|
|
144
|
+
elsif new.operation='create_tasking_delivery' and exists(select 1 from agent_board.task_events ev join agent_board.tasks t on t.id=ev.task_id
|
|
145
|
+
where ev.id=new.source_task_event_id and t.title='XB fail signed task') then
|
|
146
|
+
if not exists(select 1 from agent_board.task_events ev join agent_board.tasks t on t.id=ev.task_id
|
|
147
|
+
join agent_board.threads th on th.id=t.thread_id join agent_board.delivery_recipients d on d.source_task_id=t.id
|
|
148
|
+
join agent_board.inbox_items i on i.delivery_recipient_id=d.id where ev.id=new.source_task_event_id
|
|
149
|
+
and th.board_id=(select board1 from xb_route)) then
|
|
150
|
+
raise exception 'XB signed task did not reach stamped inbox' using errcode='P0001';
|
|
151
|
+
end if;
|
|
152
|
+
raise exception 'XB signed task late failure' using errcode='P0001';
|
|
153
|
+
end if;
|
|
154
|
+
return new;
|
|
155
|
+
end $body$;
|
|
156
|
+
create trigger xb_fail_signed_evidence before insert on agent_board.signature_evidence for each row execute function pg_temp.xb_fail_signed_evidence();
|
|
157
|
+
create temp table xb_route_before on commit drop as select
|
|
158
|
+
(select count(*) from agent_board.delivery_recipients where board_id=(select board1 from xb_route)) as deliveries,
|
|
159
|
+
(select count(*) from agent_board.inbox_items where board_id=(select board1 from xb_route)) as inbox,
|
|
160
|
+
(select count(*) from agent_board.signature_evidence where agent_id=(select actor from xb_route)) as evidence;
|
|
161
|
+
select throws_ok($$select * from agent_board.post_board_message((select id from xb_route_thread where kind='fail_desc_post'),(select actor from xb_route),
|
|
162
|
+
(select slug1 from xb_route),'addressing_v1','XB fail descriptor post','body','comment','medium',null,'{}'::jsonb)$$,
|
|
163
|
+
'P0001','XB descriptor post late failure','XB descriptor post reaches its late failure');
|
|
164
|
+
select ok((select board_id is null from agent_board.threads where id=(select id from xb_route_thread where kind='fail_desc_post'))
|
|
165
|
+
and not exists(select 1 from agent_board.messages where thread_id=(select id from xb_route_thread where kind='fail_desc_post'))
|
|
166
|
+
and (select deliveries=(select count(*) from agent_board.delivery_recipients where board_id=(select board1 from xb_route))
|
|
167
|
+
and inbox=(select count(*) from agent_board.inbox_items where board_id=(select board1 from xb_route))
|
|
168
|
+
and evidence=(select count(*) from agent_board.signature_evidence where agent_id=(select actor from xb_route)) from xb_route_before),
|
|
169
|
+
'XB descriptor post late failure rolls back stamp, message, delivery, inbox and evidence');
|
|
170
|
+
select throws_ok($$select * from agent_board.create_tasking_delivery((select id from xb_route_thread where kind='fail_desc_task'),(select actor from xb_route),
|
|
171
|
+
'XB fail descriptor task',null,null::jsonb,(select slug1 from xb_route),'addressing_v1','medium','distributed',null,'{}'::jsonb)$$,
|
|
172
|
+
'P0001','XB descriptor task late failure','XB descriptor task reaches its late failure');
|
|
173
|
+
select ok((select board_id is null from agent_board.threads where id=(select id from xb_route_thread where kind='fail_desc_task'))
|
|
174
|
+
and not exists(select 1 from agent_board.tasks where thread_id=(select id from xb_route_thread where kind='fail_desc_task'))
|
|
175
|
+
and not exists(select 1 from agent_board.task_events where thread_id=(select id from xb_route_thread where kind='fail_desc_task'))
|
|
176
|
+
and (select deliveries=(select count(*) from agent_board.delivery_recipients where board_id=(select board1 from xb_route))
|
|
177
|
+
and inbox=(select count(*) from agent_board.inbox_items where board_id=(select board1 from xb_route))
|
|
178
|
+
and evidence=(select count(*) from agent_board.signature_evidence where agent_id=(select actor from xb_route)) from xb_route_before),
|
|
179
|
+
'XB descriptor task late failure rolls back stamp, task, event, delivery, inbox and evidence');
|
|
180
|
+
select throws_ok($$select * from agent_board.signed_post_board_message(jsonb_build_object('p_thread_id',(select id from xb_route_thread where kind='fail_signed_post'),
|
|
181
|
+
'p_author_agent_id',(select actor from xb_route),'p_board_id',(select board1 from xb_route),'p_subject','signed failure','p_body','XB fail signed post'),
|
|
182
|
+
jsonb_build_object('agent_id',(select actor from xb_route),'verification_status','warn','payload_digest','sha256:'||repeat('e',64),'enforcement_mode','warn'))$$,
|
|
183
|
+
'P0001','XB signed post late failure','XB signed post reaches its evidence failure');
|
|
184
|
+
select ok((select board_id is null from agent_board.threads where id=(select id from xb_route_thread where kind='fail_signed_post'))
|
|
185
|
+
and not exists(select 1 from agent_board.messages where thread_id=(select id from xb_route_thread where kind='fail_signed_post'))
|
|
186
|
+
and (select deliveries=(select count(*) from agent_board.delivery_recipients where board_id=(select board1 from xb_route))
|
|
187
|
+
and inbox=(select count(*) from agent_board.inbox_items where board_id=(select board1 from xb_route))
|
|
188
|
+
and evidence=(select count(*) from agent_board.signature_evidence where agent_id=(select actor from xb_route)) from xb_route_before),
|
|
189
|
+
'XB signed post evidence failure rolls back stamp, message, delivery, inbox and evidence');
|
|
190
|
+
select throws_ok($$select * from agent_board.signed_create_tasking_delivery(jsonb_build_object('p_thread_id',(select id from xb_route_thread where kind='fail_signed_task'),
|
|
191
|
+
'p_created_by_agent_id',(select actor from xb_route),'p_board_id',(select board1 from xb_route),'p_title','XB fail signed task'),
|
|
192
|
+
jsonb_build_object('agent_id',(select actor from xb_route),'verification_status','warn','payload_digest','sha256:'||repeat('f',64),'enforcement_mode','warn'))$$,
|
|
193
|
+
'P0001','XB signed task late failure','XB signed task reaches its evidence failure');
|
|
194
|
+
select ok((select board_id is null from agent_board.threads where id=(select id from xb_route_thread where kind='fail_signed_task'))
|
|
195
|
+
and not exists(select 1 from agent_board.tasks where thread_id=(select id from xb_route_thread where kind='fail_signed_task'))
|
|
196
|
+
and not exists(select 1 from agent_board.task_events where thread_id=(select id from xb_route_thread where kind='fail_signed_task'))
|
|
197
|
+
and (select deliveries=(select count(*) from agent_board.delivery_recipients where board_id=(select board1 from xb_route))
|
|
198
|
+
and inbox=(select count(*) from agent_board.inbox_items where board_id=(select board1 from xb_route))
|
|
199
|
+
and evidence=(select count(*) from agent_board.signature_evidence where agent_id=(select actor from xb_route)) from xb_route_before),
|
|
200
|
+
'XB signed task evidence failure rolls back stamp, task, event, delivery, inbox and evidence');
|
|
201
|
+
-- The fleet-policy preflight one-hop inserter uses external evidence, not a
|
|
202
|
+
-- message/task/artifact parent. Exercise its real fleet branch and then prove
|
|
203
|
+
-- that such evidence alone does not turn an empty thread into history.
|
|
204
|
+
create temp table xb_external_evidence_fixture(actor uuid,thread_id uuid) on commit drop;
|
|
205
|
+
select lives_ok($q$
|
|
206
|
+
do $fleet$
|
|
207
|
+
declare a uuid:=gen_random_uuid(); t uuid:=gen_random_uuid(); d uuid:=gen_random_uuid(); m uuid:=gen_random_uuid();
|
|
208
|
+
suffix text:=replace(gen_random_uuid()::text,'-','');
|
|
209
|
+
begin
|
|
210
|
+
insert into agent_board.agents(id,agent_type,handle,display_name,status) values(a,'agent','xb-external-'||suffix,'XB external actor','active');
|
|
211
|
+
insert into agent_board.board_memberships(board_id,agent_id,membership_state,created_by_agent_id,role)
|
|
212
|
+
values((select board1 from xb_route),a,'joined',(select actor from xb_route),'member');
|
|
213
|
+
insert into agent_board.threads(id,thread_type,created_by_agent_id,subject) values(t,'coordination',a,'XB external evidence');
|
|
214
|
+
insert into agent_board.fleet_trust_domains(id,slug,display_name,domain_kind,owner_agent_id,lifecycle_state)
|
|
215
|
+
values(d,'xb-external-'||suffix,'XB external domain','tailnet',a,'active');
|
|
216
|
+
insert into agent_board.fleet_machines(id,trust_domain_id,owner_agent_id,machine_label,machine_fingerprint,lifecycle_state)
|
|
217
|
+
values(m,d,a,'XB external machine','sha256:'||suffix,'active');
|
|
218
|
+
insert into agent_board.fleet_machine_agents(machine_id,agent_id,lifecycle_state) values(m,a,'active');
|
|
219
|
+
insert into xb_external_evidence_fixture values(a,t);
|
|
220
|
+
end $fleet$;
|
|
221
|
+
$q$, 'XB external-evidence fleet fixture is created');
|
|
222
|
+
select lives_ok($$select * from agent_board.evaluate_signed_write_fleet_policy('send_direct_message',
|
|
223
|
+
jsonb_build_object('p_recipient_agent_id',(select r1 from xb_route)),
|
|
224
|
+
jsonb_build_object('agent_id',(select actor from xb_external_evidence_fixture),'verification_status','warn',
|
|
225
|
+
'payload_digest','sha256:'||repeat('9',64),'enforcement_mode','warn'))$$,
|
|
226
|
+
'XB fleet policy writes external preflight evidence');
|
|
227
|
+
select ok(exists(select 1 from agent_board.signature_evidence e where e.agent_id=(select actor from xb_external_evidence_fixture)
|
|
228
|
+
and e.operation='send_direct_message' and e.source_kind='external' and e.external_evidence_ref is not null
|
|
229
|
+
and e.source_message_id is null and e.source_task_event_id is null and e.source_artifact_id is null and e.source_delivery_recipient_id is null),
|
|
230
|
+
'XB fleet preflight evidence has no message, task-event, artifact or delivery parent');
|
|
231
|
+
select lives_ok($$select * from agent_board.post_board_message((select thread_id from xb_external_evidence_fixture),
|
|
232
|
+
(select actor from xb_external_evidence_fixture),(select board1 from xb_route),'external evidence','body')$$,
|
|
233
|
+
'XB external preflight evidence permits empty-thread association');
|
|
234
|
+
select is((select board_id from agent_board.threads where id=(select thread_id from xb_external_evidence_fixture)),
|
|
235
|
+
(select board1 from xb_route),'XB external-evidence control actually stamps the board');
|
|
236
|
+
select lives_ok($$select * from agent_board.signed_create_tasking_delivery(jsonb_build_object(
|
|
237
|
+
'p_thread_id',(select id from xb_route_thread where kind='signed_task_positive'),
|
|
238
|
+
'p_created_by_agent_id',(select actor from xb_route),'p_board_id',(select board1 from xb_route),'p_title','XB routed signed task'),
|
|
239
|
+
jsonb_build_object('agent_id',(select actor from xb_route),'verification_status','warn',
|
|
240
|
+
'payload_digest','sha256:'||repeat('8',64),'enforcement_mode','warn'))$$,
|
|
241
|
+
'XB signed task with evidence succeeds');
|
|
242
|
+
select ok(exists(select 1 from agent_board.tasks t join agent_board.task_events ev on ev.task_id=t.id
|
|
243
|
+
join agent_board.signature_evidence e on e.source_task_event_id=ev.id join agent_board.threads th on th.id=t.thread_id
|
|
244
|
+
where t.thread_id=(select id from xb_route_thread where kind='signed_task_positive') and t.title='XB routed signed task'
|
|
245
|
+
and th.board_id=(select board1 from xb_route) and e.agent_id=(select actor from xb_route)
|
|
246
|
+
and e.operation='create_tasking_delivery'),
|
|
247
|
+
'XB signed task evidence retains its actual task-event parent');
|
|
248
|
+
-- The two delivery upserts have ON CONFLICT update branches. Retry against
|
|
249
|
+
-- an existing row while presenting a different valid source to the inbox
|
|
250
|
+
-- updater; the persisted canonical parent must remain the original one.
|
|
251
|
+
select lives_ok($$select agent_board._upsert_inbox_item(d.id,(select r1 from xb_route),null,'direct','message',
|
|
252
|
+
(select id from agent_board.messages where thread_id=(select id from xb_route_thread where kind='alternate')),null,null,
|
|
253
|
+
'XB inbox retry','retry','medium',true,false,'{}'::jsonb,'{}'::jsonb)
|
|
254
|
+
from agent_board.messages m join agent_board.delivery_recipients d on d.source_message_id=m.id
|
|
255
|
+
where m.thread_id=(select id from xb_route_thread where kind='direct') and d.recipient_agent_id=(select r1 from xb_route)$$,
|
|
256
|
+
'XB existing inbox update succeeds with a different offered source');
|
|
257
|
+
select ok(exists(select 1 from agent_board.messages m join agent_board.delivery_recipients d on d.source_message_id=m.id
|
|
258
|
+
join agent_board.inbox_items i on i.delivery_recipient_id=d.id and i.source_message_id=m.id
|
|
259
|
+
where m.thread_id=(select id from xb_route_thread where kind='direct') and d.recipient_agent_id=(select r1 from xb_route)
|
|
260
|
+
and i.subject='XB inbox retry'), 'XB existing inbox update retains the original message anchor');
|
|
261
|
+
select lives_ok($$select agent_board._upsert_delivery_recipient('direct',(select r1 from xb_route),'message',m.id,null,null,null,null,
|
|
262
|
+
'{"retry":true}'::jsonb) from agent_board.messages m where m.thread_id=(select id from xb_route_thread where kind='direct')$$,
|
|
263
|
+
'XB existing delivery metadata update succeeds');
|
|
264
|
+
select ok(exists(select 1 from agent_board.messages m join agent_board.delivery_recipients d on d.source_message_id=m.id
|
|
265
|
+
where m.thread_id=(select id from xb_route_thread where kind='direct') and d.recipient_agent_id=(select r1 from xb_route)
|
|
266
|
+
and d.board_id is null and d.metadata->>'retry'='true'),
|
|
267
|
+
'XB existing delivery metadata update retains original source and private scope');
|
|
268
|
+
-- Signed wrappers also expose descriptor branches; they must retain the same
|
|
269
|
+
-- resolved targets, private scope and source-linked evidence.
|
|
270
|
+
select lives_ok($$select * from agent_board.signed_send_multicast_message(jsonb_build_object(
|
|
271
|
+
'p_thread_id',(select id from xb_route_thread where kind='signed_multi_desc'),'p_author_agent_id',(select actor from xb_route),
|
|
272
|
+
'p_recipient_descriptors',jsonb_build_array(jsonb_build_object('kind','agent_id','agentId',(select r1::text from xb_route))),
|
|
273
|
+
'p_addressing_mode','addressing_v1','p_subject','signed descriptor multi','p_body','signed descriptor multi body'),
|
|
274
|
+
jsonb_build_object('agent_id',(select actor from xb_route),'verification_status','warn','payload_digest','sha256:'||repeat('6',64),'enforcement_mode','warn'))$$,
|
|
275
|
+
'XB signed descriptor multicast succeeds');
|
|
276
|
+
select ok(exists(select 1 from agent_board.messages m join agent_board.delivery_recipients d on d.source_message_id=m.id
|
|
277
|
+
join agent_board.signature_evidence e on e.source_message_id=m.id where m.thread_id=(select id from xb_route_thread where kind='signed_multi_desc')
|
|
278
|
+
and d.recipient_agent_id=(select r1 from xb_route) and d.board_id is null and e.agent_id=(select actor from xb_route)
|
|
279
|
+
and e.operation='send_multicast_message'), 'XB signed descriptor multicast retains recipient, privacy and evidence');
|
|
280
|
+
select lives_ok($$select * from agent_board.signed_create_tasking_delivery(jsonb_build_object(
|
|
281
|
+
'p_thread_id',(select id from xb_route_thread where kind='signed_task_desc'),'p_created_by_agent_id',(select actor from xb_route),
|
|
282
|
+
'p_title','XB signed descriptor task','p_board_slug',(select slug1 from xb_route),
|
|
283
|
+
'p_recipient_descriptors',jsonb_build_array(jsonb_build_object('kind','agent_id','agentId',(select r1::text from xb_route))),
|
|
284
|
+
'p_addressing_mode','addressing_v1'),
|
|
285
|
+
jsonb_build_object('agent_id',(select actor from xb_route),'verification_status','warn','payload_digest','sha256:'||repeat('7',64),'enforcement_mode','warn'))$$,
|
|
286
|
+
'XB signed descriptor board task succeeds');
|
|
287
|
+
select ok(exists(select 1 from agent_board.tasks t join agent_board.threads th on th.id=t.thread_id
|
|
288
|
+
join agent_board.delivery_recipients d on d.source_task_id=t.id join agent_board.task_events ev on ev.task_id=t.id
|
|
289
|
+
join agent_board.signature_evidence e on e.source_task_event_id=ev.id where t.thread_id=(select id from xb_route_thread where kind='signed_task_desc')
|
|
290
|
+
and th.board_id=(select board1 from xb_route) and d.recipient_agent_id=(select r1 from xb_route) and d.board_id is null
|
|
291
|
+
and e.agent_id=(select actor from xb_route) and e.operation='create_tasking_delivery'),
|
|
292
|
+
'XB signed descriptor task retains board, private recipient and evidence');
|
|
293
|
+
select * from finish();
|
|
294
|
+
rollback;
|