@consiliency/agent-board-schema 1.64.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/README.md +19 -0
- package/fixtures/already-applied.json +44 -4
- package/migrations/20261015000100_agent_board_session_provenance.sql +367 -0
- package/migrations/20261015000200_agent_board_request_preserve_removed.sql +87 -0
- package/migrations/20261015000300_agent_board_rls_correlation.sql +132 -0
- package/migrations/20261015000400_agent_board_resolution_authority.sql +146 -0
- 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 +93 -3
- package/src/deployment-drift-main.test.mjs +156 -0
- package/src/deployment-drift-script.test.mjs +14 -1
- package/src/policy-comment.test.mjs +17 -0
- package/src/tooling.test.mjs +12 -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_consent_gating.test.sql +4 -4
- 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_gatenull_membstate.test.sql +7 -4
- 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_policy_correlation.test.sql +189 -0
- package/tests/agent_board_request_removed.test.sql +96 -0
- package/tests/agent_board_resolution_authority.test.sql +190 -0
- 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_session_provenance.test.sql +106 -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 +43 -7
- 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/consent_approval_lock.out +1 -1
- 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/consent_approval_lock.spec +13 -7
- 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,100 @@
|
|
|
1
|
+
-- Only the exact present native sender overloads execute. Missing platform
|
|
2
|
+
-- objects earn no native effect credit. Void return alone never proves a send.
|
|
3
|
+
create extension if not exists pgtap with schema extensions;
|
|
4
|
+
set search_path=extensions,public,agent_board;
|
|
5
|
+
begin;
|
|
6
|
+
\ir fixtures/agent_board_667_conversion_guard.sql
|
|
7
|
+
\ir fixtures/agent_board_667_sender_guard.sql
|
|
8
|
+
select set_config('request.jwt.claim.role','service_role',true);
|
|
9
|
+
insert into agent_board.agents(id,agent_type,handle,display_name,status)
|
|
10
|
+
values('667d0000-0000-4000-8000-000000000001','agent','sender-effects','Sender effects','active');
|
|
11
|
+
insert into agent_board.threads(id,thread_type,created_by_agent_id,subject)
|
|
12
|
+
values('667d0000-0000-4000-8000-000000000010','coordination','667d0000-0000-4000-8000-000000000001','Topic is literal data');
|
|
13
|
+
create temp table xb_sf_cases(fn text,label text,expression text,topic text,expected jsonb,binary_value bytea,private boolean,generated_payload_id boolean) on commit drop;
|
|
14
|
+
insert into xb_sf_cases values
|
|
15
|
+
('realtime.send(jsonb,text,text,boolean)','JSON generated ID',
|
|
16
|
+
$$realtime.send('{"value":1}','sf667-event','sf667-json-generated')$$,'sf667-json-generated','{"value":1}',null,true,true),
|
|
17
|
+
('realtime.send(jsonb,text,text,boolean)','JSON supplied ID',
|
|
18
|
+
$$realtime.send('{"id":"caller-id","value":2}','sf667-event','sf667-json-supplied',false)$$,'sf667-json-supplied','{"id":"caller-id","value":2}',null,false,false),
|
|
19
|
+
('realtime.send(jsonb,text,text,boolean)','JSON null payload',
|
|
20
|
+
$$realtime.send(null::jsonb,'sf667-event','sf667-json-null',true)$$,'sf667-json-null',null,null,true,false),
|
|
21
|
+
('realtime.send_binary(bytea,text,text,boolean)','binary default private',
|
|
22
|
+
$$realtime.send_binary(decode('0041ff','hex'),'sf667-event','sf667-binary-private')$$,'sf667-binary-private',null,decode('0041ff','hex'),true,false),
|
|
23
|
+
('realtime.send_binary(bytea,text,text,boolean)','binary explicit public',
|
|
24
|
+
$$realtime.send_binary(decode('00','hex'),'sf667-event','sf667-binary-public',false)$$,'sf667-binary-public',null,decode('00','hex'),false,false);
|
|
25
|
+
-- Unquoting the native SET template must execute a valid own history write,
|
|
26
|
+
-- rather than earning a kill from a syntax error swallowed by the native body.
|
|
27
|
+
insert into xb_sf_cases
|
|
28
|
+
select fn,label,format('%s(%s,''sf667-event'',%L,true)',callee,payload,topic),topic,expected,binary_value,true,generated
|
|
29
|
+
from(values
|
|
30
|
+
('realtime.send(jsonb,text,text,boolean)','JSON expression-looking topic','realtime.send',$q$'{"value":3}'::jsonb$q$,'{"value":3}'::jsonb,null::bytea,true),
|
|
31
|
+
('realtime.send_binary(bytea,text,text,boolean)','binary expression-looking topic','realtime.send_binary',$q$decode('41','hex')$q$,null::jsonb,decode('41','hex'),false)
|
|
32
|
+
) v(fn,label,callee,payload,expected,binary_value,generated)
|
|
33
|
+
cross join(values($q$'sf667-literal'; select agent_board.create_task('667d0000-0000-4000-8000-000000000010','667d0000-0000-4000-8000-000000000001','sf667-topic-side-effect'); --$q$)) x(raw_topic)
|
|
34
|
+
cross join lateral(select replace(raw_topic,'sf667-literal','sf667-literal-'||callee) as topic) unique_topic;
|
|
35
|
+
create function pg_temp.xb_sf_call(p_label text,p_expression text,p_topic text,p_expected jsonb,p_binary bytea,p_private boolean,p_generated boolean) returns setof text
|
|
36
|
+
language plpgsql volatile as $$
|
|
37
|
+
declare n bigint; correct boolean;
|
|
38
|
+
begin
|
|
39
|
+
return next lives_ok('select '||p_expression,'SN '||p_label||' native call returns');
|
|
40
|
+
select count(*),bool_and(m.id is not null and m.binary_payload is not distinct from p_binary
|
|
41
|
+
and m.payload is not distinct from case when p_generated then p_expected||jsonb_build_object('id',m.id) else p_expected end
|
|
42
|
+
and m.private is not distinct from p_private and m.extension='broadcast'
|
|
43
|
+
and m.updated_at is not null and m.inserted_at is not null and m.skip_broadcast=false
|
|
44
|
+
and (p_expected->>'id' is distinct from 'caller-id' or m.id::text<>'caller-id'))
|
|
45
|
+
into n,correct from realtime.messages m where m.topic=p_topic and m.event='sf667-event';
|
|
46
|
+
return next ok(n=1 and coalesce(correct,false),'SN '||p_label||' wrote the exact own row');
|
|
47
|
+
end$$;
|
|
48
|
+
create function pg_temp.xb_sf_refusal_state(p_identity text) returns text
|
|
49
|
+
language plpgsql volatile as $$
|
|
50
|
+
begin
|
|
51
|
+
return is((select count(*) from realtime.messages where event='sf667-denied' and topic=
|
|
52
|
+
case when p_identity like 'realtime.send_binary%' then 'sf667-denied-binary' else 'sf667-denied-json' end),
|
|
53
|
+
0::bigint,'SN '||p_identity||' RLS refusal wrote no own row');
|
|
54
|
+
end$$;
|
|
55
|
+
grant select on xb_sf_cases,xb_sf_reference to service_role,authenticated;
|
|
56
|
+
select plan(9+2*(select count(*)::integer from xb_sf_cases where to_regprocedure(fn) is not null)
|
|
57
|
+
+2*(select count(*)::integer from pg_temp.xb_sf_reference where kind='wrapper' and to_regprocedure(identity) is not null));
|
|
58
|
+
select is((select array_agg(identity order by identity collate "C") from pg_temp.xb_sf_reference where kind='wrapper'),
|
|
59
|
+
array['realtime.send(jsonb,text,text,boolean)','realtime.send_binary(bytea,text,text,boolean)']::text[],
|
|
60
|
+
'SN scope is exactly the two sender overloads');
|
|
61
|
+
select is((select count(*) from pg_temp.xb_sf_reference where kind='shape'),2::bigint,'SN explicit parent and leaf effect classes exist');
|
|
62
|
+
select is((select string_agg(identity||': '||problem,', ' order by identity,problem) from pg_temp.xb_sf_problems()),null::text,
|
|
63
|
+
'SN native sender effect profile is completely classified')
|
|
64
|
+
where exists(select 1 from pg_temp.xb_sf_reference where kind='wrapper' and to_regprocedure(identity) is not null);
|
|
65
|
+
select * from skip('native senders absent; no target or primitive admission credit',1)
|
|
66
|
+
where not exists(select 1 from pg_temp.xb_sf_reference where kind='wrapper' and to_regprocedure(identity) is not null);
|
|
67
|
+
select is((select count(*) from pg_temp.xb_sf_admitted()),
|
|
68
|
+
(select count(*) from pg_temp.xb_sf_reference where kind='wrapper' and to_regprocedure(identity) is not null),'SN only the verified present senders are admitted');
|
|
69
|
+
select is((select count(*) from agent_board.tasks where thread_id='667d0000-0000-4000-8000-000000000010'),0::bigint,'SN own fixture starts without history');
|
|
70
|
+
select is((with actual as (select rel from pg_temp.xb_sf_targets()),
|
|
71
|
+
canonical as (select relid::oid as rel from pg_partition_tree(to_regclass('realtime.messages')))
|
|
72
|
+
select count(*) from ((select rel from actual except select rel from canonical)
|
|
73
|
+
union all (select rel from canonical except select rel from actual)) d),0::bigint,
|
|
74
|
+
'SN independently derived partition tree has no omitted target') where to_regclass('realtime.messages') is not null;
|
|
75
|
+
select * from skip('native destination absent; no target coverage credit',1) where to_regclass('realtime.messages') is null;
|
|
76
|
+
select ok((select count(*)>=2 and bool_and(pg_temp.xb_sf_profile(t.rel)=r.payload) from pg_temp.xb_sf_targets() t
|
|
77
|
+
join pg_temp.xb_sf_reference r on r.kind='shape' and r.identity=case when t.rel=to_regclass('realtime.messages') then 'root' else 'leaf' end),
|
|
78
|
+
'SN every live destination positively matches its effect class') where to_regclass('realtime.messages') is not null;
|
|
79
|
+
select * from skip('native destination absent; no positive effect class credit',1) where to_regclass('realtime.messages') is null;
|
|
80
|
+
set local role service_role;
|
|
81
|
+
select r.* from (select * from xb_sf_cases where to_regprocedure(fn) is not null order by label) c
|
|
82
|
+
cross join lateral pg_temp.xb_sf_call(c.label,c.expression,c.topic,c.expected,c.binary_value,c.private,c.generated_payload_id) r;
|
|
83
|
+
reset role;
|
|
84
|
+
select is((select count(*) from agent_board.tasks where thread_id='667d0000-0000-4000-8000-000000000010'),0::bigint,
|
|
85
|
+
'SN quoted topics created no own history') where exists(select 1 from xb_sf_cases where to_regprocedure(fn) is not null);
|
|
86
|
+
select * from skip('native calls absent; no literal-effect credit',1) where not exists(select 1 from xb_sf_cases where to_regprocedure(fn) is not null);
|
|
87
|
+
-- RLS denial is intentionally caught by native code. Both the warning and the
|
|
88
|
+
-- separate no-row assertion matter; lives_ok alone is never refusal evidence.
|
|
89
|
+
set local role authenticated;
|
|
90
|
+
select lives_ok('select '||case when identity like 'realtime.send_binary%' then
|
|
91
|
+
$$realtime.send_binary(decode('42','hex'),'sf667-denied','sf667-denied-binary',true)$$ else
|
|
92
|
+
$$realtime.send('{"denied":true}','sf667-denied','sf667-denied-json',true)$$ end,
|
|
93
|
+
'SN '||identity||' caught RLS refusal returns')
|
|
94
|
+
from pg_temp.xb_sf_reference where kind='wrapper' and to_regprocedure(identity) is not null order by identity;
|
|
95
|
+
reset role;
|
|
96
|
+
select pg_temp.xb_sf_refusal_state(identity)
|
|
97
|
+
from pg_temp.xb_sf_reference where kind='wrapper' and to_regprocedure(identity) is not null order by identity;
|
|
98
|
+
select is((select count(distinct fn) from xb_sf_cases),2::bigint,'SN fixtures include both concrete payload types');
|
|
99
|
+
select * from finish();
|
|
100
|
+
rollback;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
-- Classifier controls execute even when the native platform is absent. They
|
|
2
|
+
-- prove recognition/restoration, not native calls or native effect admission.
|
|
3
|
+
create extension if not exists pgtap with schema extensions;
|
|
4
|
+
set search_path=extensions,public,agent_board;
|
|
5
|
+
begin;
|
|
6
|
+
\ir fixtures/agent_board_667_conversion_guard.sql
|
|
7
|
+
\ir fixtures/agent_board_667_sender_guard.sql
|
|
8
|
+
select plan(10);
|
|
9
|
+
create temp table xb_sf_prior_profile on commit drop as select * from pg_temp.xb_sf_problems();
|
|
10
|
+
select ok((select count(*)>0 from pg_temp.xb_sf_reference where kind='primitive'),'SP fixed-call reference is nonempty');
|
|
11
|
+
select is((select count(*) from pg_temp.xb_sf_reference where kind='wrapper'),2::bigint,'SP only two sender identities are candidates');
|
|
12
|
+
select lives_ok($q$create function pg_temp.clock_timestamp() returns timestamptz language sql as $b$select now()$b$$q$,
|
|
13
|
+
'SP valid clock shadow is registered');
|
|
14
|
+
select ok(exists(select 1 from pg_temp.xb_sf_problems() where identity like 'pg_temp_%.clock_timestamp()' and problem='unreviewed fixed-call shadow'),
|
|
15
|
+
'SP clock shadow names its full identity');
|
|
16
|
+
select is((select count(*) from pg_temp.xb_sf_admitted()),0::bigint,'SP clock shadow prevents sender admission');
|
|
17
|
+
drop function pg_temp.clock_timestamp();
|
|
18
|
+
select is((select jsonb_agg(to_jsonb(p) order by identity,problem) from pg_temp.xb_sf_problems() p),
|
|
19
|
+
(select jsonb_agg(to_jsonb(p) order by identity,problem) from xb_sf_prior_profile p),'SP clock removal restores the prior profile');
|
|
20
|
+
select lives_ok($q$create function pg_temp.jsonb_set(jsonb,text[],jsonb,boolean) returns jsonb language sql as $b$select $1$b$$q$,
|
|
21
|
+
'SP valid JSON shadow is registered');
|
|
22
|
+
select ok(exists(select 1 from pg_temp.xb_sf_problems() where identity like 'pg_temp_%.jsonb_set(jsonb,text[],jsonb,boolean)' and problem='unreviewed fixed-call shadow'),
|
|
23
|
+
'SP JSON shadow names its full overload');
|
|
24
|
+
select is((select count(*) from pg_temp.xb_sf_admitted()),0::bigint,'SP JSON shadow prevents sender admission');
|
|
25
|
+
drop function pg_temp.jsonb_set(jsonb,text[],jsonb,boolean);
|
|
26
|
+
select is((select jsonb_agg(to_jsonb(p) order by identity,problem) from pg_temp.xb_sf_problems() p),
|
|
27
|
+
(select jsonb_agg(to_jsonb(p) order by identity,problem) from xb_sf_prior_profile p),'SP JSON removal restores the prior profile');
|
|
28
|
+
select * from finish();
|
|
29
|
+
rollback;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
-- Native own-row and cursor witnesses, distinct from effect-class disposition.
|
|
2
|
+
create extension if not exists pgtap with schema extensions;set search_path=extensions,public,agent_board;begin;
|
|
3
|
+
select to_regprocedure('storage.list_objects_with_delimiter(text,text,text,integer,text,text,text,text,text,timestamp with time zone,text)') is not null as native_present \gset
|
|
4
|
+
\if :native_present
|
|
5
|
+
select plan(41);
|
|
6
|
+
insert into storage.buckets(id,name) values('667-delimiter-own','667-delimiter-own'),('667-delimiter-decoy','667-delimiter-decoy');
|
|
7
|
+
insert into storage.objects(id,bucket_id,name,created_at,updated_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned,metadata) values
|
|
8
|
+
('66700000-0000-4000-8000-000000000201','667-delimiter-own','alpha','2020-01-01 UTC','2020-01-02 UTC','2020-01-03 UTC','new',null,false,true,'{"n":1}'),
|
|
9
|
+
('66700000-0000-4000-8000-000000000202','667-delimiter-own','alpha','2019-12-30 UTC','2019-12-31 UTC','2020-01-01 UTC','a','2020-02-01 00:00:00.123456 UTC',false,true,'{"n":2}'),
|
|
10
|
+
('66700000-0000-4000-8000-000000000203','667-delimiter-own','alpha!','2020-01-02 UTC','2020-01-03 UTC','2020-01-04 UTC','one',null,false,true,'{"n":3}'),
|
|
11
|
+
('66700000-0000-4000-8000-000000000204','667-delimiter-own','beta','2020-01-03 UTC','2020-01-04 UTC','2020-01-05 UTC','one',null,false,true,'{"n":4}'),
|
|
12
|
+
('66700000-0000-4000-8000-000000000205','667-delimiter-own','folder/one','2020-01-04 UTC','2020-01-05 UTC','2020-01-06 UTC','one',null,false,true,'{"n":5}'),
|
|
13
|
+
('66700000-0000-4000-8000-000000000206','667-delimiter-own','folder/two','2020-01-05 UTC','2020-01-06 UTC','2020-01-07 UTC','one',null,false,true,'{"n":6}'),
|
|
14
|
+
('66700000-0000-4000-8000-000000000207','667-delimiter-own','alpha-marker','2020-01-06 UTC','2020-01-07 UTC','2020-01-08 UTC','one',null,true,true,'{"n":7}'),
|
|
15
|
+
('66700000-0000-4000-8000-000000000208','667-delimiter-decoy','decoy','2020-01-07 UTC','2020-01-08 UTC','2020-01-09 UTC','one',null,false,true,'{"n":8}');
|
|
16
|
+
insert into storage.objects(id,bucket_id,name,created_at,updated_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned,metadata) values('66700000-0000-4000-8000-000000000209','667-delimiter-own','alpha','2019-12-30 UTC','2019-12-31 UTC','2020-01-01 UTC','b','2020-02-01 00:00:00.123789 UTC',false,true,'{"n":9}');
|
|
17
|
+
create temp table sd_rows(ordinal bigint generated always as identity,name text,id uuid,metadata jsonb,updated_at timestamptz,created_at timestamptz,last_accessed_at timestamptz,version text,archived_at timestamptz,is_delete_marker boolean,is_versioned boolean) on commit drop;
|
|
18
|
+
truncate sd_rows;
|
|
19
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','/',100,'','','asc','exclude','exclude',null::timestamptz,'')$call$,'SD default ascending native call lives');
|
|
20
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['alpha','alpha!','beta','folder/']::text[],'SD default ascending returns exact own names');
|
|
21
|
+
select ok((select count(*)=1 and bool_and(id='66700000-0000-4000-8000-000000000201'::uuid and metadata='{"n":1}'::jsonb and version='new' and created_at='2020-01-01 UTC'::timestamptz and updated_at='2020-01-02 UTC'::timestamptz and last_accessed_at='2020-01-03 UTC'::timestamptz and archived_at is null and not is_delete_marker and is_versioned) from sd_rows where name='alpha'),'SD exact own leaf fields are preserved');
|
|
22
|
+
select ok((select count(*)=1 and bool_and(id is null and metadata is null and version is null and created_at is null and updated_at is null and last_accessed_at is null and archived_at is null) from sd_rows where name='folder/'),'SD folder fields are distinct from a leaf');
|
|
23
|
+
truncate sd_rows;
|
|
24
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','/',100,'','','desc','exclude','exclude',null::timestamptz,'')$call$,'SD default descending native call lives');
|
|
25
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['folder/','beta','alpha!','alpha']::text[],'SD default descending returns exact own names');
|
|
26
|
+
truncate sd_rows;
|
|
27
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','',100,'','','asc','exclude','exclude',null::timestamptz,'')$call$,'SD empty delimiter native call lives');
|
|
28
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['alpha','alpha!','beta','folder/one','folder/two']::text[],'SD empty delimiter returns exact own names');
|
|
29
|
+
truncate sd_rows;
|
|
30
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','folder/','/',100,'','','asc','exclude','exclude',null::timestamptz,'')$call$,'SD nested prefix native call lives');
|
|
31
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['folder/one','folder/two']::text[],'SD nested prefix returns exact own names');
|
|
32
|
+
truncate sd_rows;
|
|
33
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','/',100,'alpha','','asc','exclude','exclude',null::timestamptz,'')$call$,'SD start after native call lives');
|
|
34
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['alpha!','beta','folder/']::text[],'SD start after returns exact own names');
|
|
35
|
+
truncate sd_rows;
|
|
36
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','/',100,'alpha','beta','asc','exclude','exclude',null::timestamptz,'')$call$,'SD next token takes priority native call lives');
|
|
37
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['folder/']::text[],'SD next token takes priority returns exact own names');
|
|
38
|
+
truncate sd_rows;
|
|
39
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','/',1,'','','asc','exclude','exclude',null::timestamptz,'')$call$,'SD one key limit native call lives');
|
|
40
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['alpha']::text[],'SD one key limit returns exact own names');
|
|
41
|
+
truncate sd_rows;
|
|
42
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','/',100,'','','asc','only','exclude',null::timestamptz,'')$call$,'SD archived only native call lives');
|
|
43
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['alpha','alpha']::text[],'SD archived only returns exact own names');
|
|
44
|
+
select is((select array_agg(version order by ordinal) from sd_rows),array['a','b']::text[],'SD archived versions use millisecond and version order');
|
|
45
|
+
truncate sd_rows;
|
|
46
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','/',100,'','','asc','include','exclude',null::timestamptz,'')$call$,'SD versions included native call lives');
|
|
47
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['alpha','alpha','alpha','alpha!','beta','folder/']::text[],'SD versions included returns exact own names');
|
|
48
|
+
select is((select array_agg(version order by ordinal) from sd_rows where name='alpha'),array['new','a','b']::text[],'SD current and archived versions keep their own order');
|
|
49
|
+
truncate sd_rows;
|
|
50
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','/',100,'','','asc','exclude','only',null::timestamptz,'')$call$,'SD markers ascending native call lives');
|
|
51
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['alpha-marker']::text[],'SD markers ascending returns exact own names');
|
|
52
|
+
truncate sd_rows;
|
|
53
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','/',100,'','','desc','exclude','only',null::timestamptz,'')$call$,'SD markers descending native call lives');
|
|
54
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['alpha-marker']::text[],'SD markers descending returns exact own names');
|
|
55
|
+
truncate sd_rows;
|
|
56
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','/',100,'','','asc','include','only',null::timestamptz,'')$call$,'SD multiversion markers native call lives');
|
|
57
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['alpha-marker']::text[],'SD multiversion markers returns exact own names');
|
|
58
|
+
truncate sd_rows;
|
|
59
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','/',1,'','alpha','asc','include','exclude','2020-02-01 00:00:00.123900 UTC'::timestamptz,'a')$call$,'SD version cursor millisecond boundary native call lives');
|
|
60
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['alpha']::text[],'SD version cursor millisecond boundary returns exact own names');
|
|
61
|
+
select is((select array_agg(version order by ordinal) from sd_rows),array['b']::text[],'SD version cursor resumes at the exact millisecond tie');
|
|
62
|
+
truncate sd_rows;
|
|
63
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','/',1,'beta','','asc','exclude','exclude',null::timestamptz,'')$call$,'SD folder cursor native call lives');
|
|
64
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['folder/']::text[],'SD folder cursor returns exact own names');
|
|
65
|
+
insert into storage.objects(bucket_id,name,version,is_versioned) values('667-delimiter-own','quote''; SELECT 1; --','one',true);
|
|
66
|
+
truncate sd_rows;
|
|
67
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','quote''; SELECT 1; --','/',100,'','','asc','exclude','exclude',null::timestamptz,'')$call$,'SD SQL looking prefix native call lives');
|
|
68
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['quote''; SELECT 1; --']::text[],'SD SQL looking prefix returns exact own names');
|
|
69
|
+
truncate sd_rows;
|
|
70
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','quote''; SELECT 1; --','''; SELECT 1; --',100,'','','asc','exclude','exclude',null::timestamptz,'')$call$,'SD SQL looking delimiter native call lives');
|
|
71
|
+
select is((select array_agg(name order by ordinal) from sd_rows),array['quote''; SELECT 1; --']::text[],'SD SQL looking delimiter returns exact own names');
|
|
72
|
+
grant insert,select on sd_rows to service_role,authenticated;grant usage,select on sequence sd_rows_ordinal_seq to service_role,authenticated;
|
|
73
|
+
truncate sd_rows;set local role service_role;
|
|
74
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','/')$call$,'SD service_role native call lives');
|
|
75
|
+
reset role;
|
|
76
|
+
select is((select count(*) from sd_rows),5::bigint,'SD service_role row visibility');
|
|
77
|
+
truncate sd_rows;set local role authenticated;
|
|
78
|
+
select lives_ok($call$insert into sd_rows(name,id,metadata,updated_at,created_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned) select * from storage.list_objects_with_delimiter('667-delimiter-own','','/')$call$,'SD authenticated native call lives');
|
|
79
|
+
reset role;
|
|
80
|
+
select is((select count(*) from sd_rows),0::bigint,'SD authenticated row visibility');
|
|
81
|
+
\else
|
|
82
|
+
select plan(1);select ok(to_regprocedure('storage.list_objects_with_delimiter(text,text,text,integer,text,text,text,text,text,timestamp with time zone,text)') is null,'SD native delimiter absent; no native behavior credit');
|
|
83
|
+
\endif
|
|
84
|
+
select * from finish();rollback;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
create extension if not exists pgtap with schema extensions;
|
|
2
|
+
set search_path=extensions,public,agent_board;
|
|
3
|
+
begin;
|
|
4
|
+
\ir fixtures/agent_board_667_conversion_guard.sql
|
|
5
|
+
\ir fixtures/agent_board_667_sender_guard.sql
|
|
6
|
+
\ir fixtures/agent_board_667_timestamp_guard.sql
|
|
7
|
+
\ir fixtures/agent_board_667_search_guard.sql
|
|
8
|
+
\ir fixtures/agent_board_667_delimiter_guard.sql
|
|
9
|
+
select plan(4);
|
|
10
|
+
create temp table ss_prior on commit drop as select * from pg_temp.xb_sd_prerequisite_problems();
|
|
11
|
+
create function pg_temp.date_trunc(text,timestamptz) returns timestamptz language sql as $f$select null::timestamptz$f$;
|
|
12
|
+
select ok(exists(select 1 from pg_proc where oid='pg_temp.date_trunc(text,timestamptz)'::regprocedure),
|
|
13
|
+
'SD own resolution control is installed in the catalog');
|
|
14
|
+
select ok(exists(select 1 from pg_temp.xb_sd_prerequisite_problems()
|
|
15
|
+
where identity=pg_temp.xb_cf_fn('pg_temp.date_trunc(text,timestamptz)'::regprocedure) and problem='unreviewed delimiter overload or shadow'),
|
|
16
|
+
'SD resolution census names the injected overload identity');
|
|
17
|
+
select is((select count(*) from pg_temp.xb_sd_admitted()),0::bigint,'SD unreviewed overload closes admission');
|
|
18
|
+
drop function pg_temp.date_trunc(text,timestamptz);
|
|
19
|
+
select is((select jsonb_agg(jsonb_build_array(identity,problem) order by identity,problem) from pg_temp.xb_sd_prerequisite_problems()),
|
|
20
|
+
(select jsonb_agg(jsonb_build_array(identity,problem) order by identity,problem) from ss_prior),
|
|
21
|
+
'SD own overload removal restores the prior prerequisite findings');
|
|
22
|
+
select * from finish();
|
|
23
|
+
rollback;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
create extension if not exists pgtap with schema extensions;
|
|
2
|
+
create extension if not exists plpgsql_check with schema extensions;
|
|
3
|
+
set search_path=extensions,public,agent_board;
|
|
4
|
+
begin;
|
|
5
|
+
\ir fixtures/agent_board_667_conversion_guard.sql
|
|
6
|
+
\ir fixtures/agent_board_667_sender_guard.sql
|
|
7
|
+
\ir fixtures/agent_board_667_timestamp_guard.sql
|
|
8
|
+
\ir fixtures/agent_board_667_search_guard.sql
|
|
9
|
+
\ir fixtures/agent_board_667_delimiter_guard.sql
|
|
10
|
+
select to_regprocedure('storage.list_objects_with_delimiter(text,text,text,integer,text,text,text,text,text,timestamp with time zone,text)') is not null as native_present \gset
|
|
11
|
+
\if :native_present
|
|
12
|
+
select plan(18);
|
|
13
|
+
select is((select string_agg(identity||': '||problem,', ' order by identity,problem) from pg_temp.xb_sd_problems()),null::text,
|
|
14
|
+
'SD complete source, relation, resolution and callback profile matches');
|
|
15
|
+
select is((select array_agg(fn order by fn) from pg_temp.xb_sd_admitted()),
|
|
16
|
+
array['storage.list_objects_with_delimiter(text,text,text,integer,text,text,text,text,text,timestamp with time zone,text)'::regprocedure::oid],
|
|
17
|
+
'SD exactly the native delimiter OID is admitted');
|
|
18
|
+
select is((select count(*) from pg_temp.xb_sd_views),842::bigint,'SD all source-bound query and expression views parsed');
|
|
19
|
+
select is((select array_agg(category||':'||n order by category) from (select category,count(*) n from pg_temp.xb_sd_views group by category) q),
|
|
20
|
+
array['dynamic:666','expression:166','static:10']::text[],'SD every inventory category is present');
|
|
21
|
+
select is((select payload->>'prosrc_md5' from pg_temp.xb_sd_reference where kind='coverage'),
|
|
22
|
+
(select md5(prosrc) from pg_proc where oid='storage.list_objects_with_delimiter(text,text,text,integer,text,text,text,text,text,timestamp with time zone,text)'::regprocedure),
|
|
23
|
+
'SD constructor coverage is bound to the actual native body');
|
|
24
|
+
select is((select jsonb_array_length(payload->'execute_sites') from pg_temp.xb_sd_reference where kind='coverage'),3,
|
|
25
|
+
'SD lexical coverage includes every EXECUTE site');
|
|
26
|
+
select ok(exists(select 1 from pg_temp.xb_sd_reach() where fn='pg_catalog.date_trunc(text,timestamptz)'::regprocedure),
|
|
27
|
+
'SD timestamp normalization primitive is reached');
|
|
28
|
+
select ok(exists(select 1 from pg_temp.xb_sd_roots() where fn='pg_catalog.format(text,"any")'::regprocedure),
|
|
29
|
+
'SD SQL constructors themselves are in the executable graph');
|
|
30
|
+
select ok(exists(select 1 from pg_temp.xb_sd_roots() where fn='storage.get_common_prefix(text,text,text)'::regprocedure),
|
|
31
|
+
'SD source expressions reach the separately reviewed SQL prefix helper');
|
|
32
|
+
select ok((select count(*) from pg_temp.xb_sd_views v join pg_temp.xb_sd_reference q on q.kind='query' and q.identity=v.identity where q.payload->>'role'='record')=
|
|
33
|
+
(select sum((e->>'variants')::integer) from pg_temp.xb_sd_reference r cross join lateral jsonb_array_elements(r.payload->'execute_sites') e where r.kind='coverage' and e->>'role'='record')
|
|
34
|
+
and (select jsonb_array_length(payload->'record_fields')>0 from pg_temp.xb_sd_reference where kind='coverage'),
|
|
35
|
+
'SD every record batch has a nonempty source-derived field-type check');
|
|
36
|
+
select is((select array_agg(distinct d.refobjid::regclass::text order by d.refobjid::regclass::text) from pg_temp.xb_sd_views v
|
|
37
|
+
join pg_rewrite w on w.ev_class=v.rel join pg_depend d on d.classid='pg_rewrite'::regclass and d.objid=w.oid
|
|
38
|
+
where d.refclassid='pg_class'::regclass and d.refobjid<>v.rel),array['storage.objects']::text[],
|
|
39
|
+
'SD parsed inventory selects only the reviewed persistent target');
|
|
40
|
+
create function pg_temp.xb_sd_null_execute() returns void language plpgsql as $f$begin execute null::text;end$f$;
|
|
41
|
+
select throws_ok('select pg_temp.xb_sd_null_execute()','22004','query string argument of EXECUTE is null',
|
|
42
|
+
'SD nullable constructor path is a refusal, not executable caller text');
|
|
43
|
+
select ok((select bool_and(payload->>'group' in('dynamic','static','expression')) from pg_temp.xb_sd_reference where kind='query'),
|
|
44
|
+
'SD reference rows have classified source origins');
|
|
45
|
+
create temp table xb_sd_effect(note text) on commit drop;
|
|
46
|
+
create function pg_temp.xb_sd_dml() returns trigger language plpgsql as $f$
|
|
47
|
+
begin insert into pg_temp.xb_sd_effect values('called');return new;end$f$;
|
|
48
|
+
create trigger xb_sd_dml_control before insert on storage.objects for each row execute function pg_temp.xb_sd_dml();
|
|
49
|
+
insert into storage.buckets(id,name) values('667-delimiter-dml','667-delimiter-dml');
|
|
50
|
+
select lives_ok($call$select * from storage.list_objects_with_delimiter('667-delimiter-dml','','/')$call$,'SD SELECT with a live DML callback lives');
|
|
51
|
+
select is((select count(*) from pg_temp.xb_sd_effect),0::bigint,'SD native SELECT does not invoke the DML callback');
|
|
52
|
+
select lives_ok($call$insert into storage.objects(bucket_id,name) values('667-delimiter-dml','own-dml-control')$call$,'SD own DML callback control lives');
|
|
53
|
+
select is((select count(*) from pg_temp.xb_sd_effect),1::bigint,'SD own DML positively invokes the same callback');
|
|
54
|
+
select is((select count(*) from pg_temp.xb_sd_admitted()),1::bigint,'SD DML-only callback preserves SELECT admission');
|
|
55
|
+
\else
|
|
56
|
+
select plan(1);
|
|
57
|
+
select ok(to_regprocedure('storage.list_objects_with_delimiter(text,text,text,integer,text,text,text,text,text,timestamp with time zone,text)') is null
|
|
58
|
+
and not exists(select 1 from pg_temp.xb_sd_admitted()),'SD absent native delimiter has no admission or native credit');
|
|
59
|
+
\endif
|
|
60
|
+
select * from finish();
|
|
61
|
+
rollback;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
-- Native own-row witnesses, separate from the finite effect/dispatch guard.
|
|
2
|
+
create extension if not exists pgtap with schema extensions;
|
|
3
|
+
set search_path=extensions,public,agent_board;
|
|
4
|
+
begin;
|
|
5
|
+
select to_regprocedure('storage.search(text,text,integer,integer,integer,text,text,text,text,text)') is not null as native_present \gset
|
|
6
|
+
\if :native_present
|
|
7
|
+
select plan(42);
|
|
8
|
+
insert into storage.buckets(id,name) values('667-search-own','667-search-own'),('667-search-decoy','667-search-decoy');
|
|
9
|
+
insert into storage.objects(id,bucket_id,name,created_at,updated_at,last_accessed_at,version,archived_at,is_delete_marker,is_versioned,metadata) values
|
|
10
|
+
('66700000-0000-4000-8000-000000000201','667-search-own','alpha','2020-01-01 UTC','2020-01-02 UTC','2020-01-03 UTC','new',null,false,true,'{"n":1}'),
|
|
11
|
+
('66700000-0000-4000-8000-000000000202','667-search-own','alpha','2019-12-30 UTC','2019-12-31 UTC','2020-01-01 UTC','old','2020-02-01 UTC',false,true,'{"n":2}'),
|
|
12
|
+
('66700000-0000-4000-8000-000000000203','667-search-own','alpha!','2020-01-02 UTC','2020-01-03 UTC','2020-01-04 UTC','one',null,false,true,'{"n":3}'),
|
|
13
|
+
('66700000-0000-4000-8000-000000000204','667-search-own','beta','2020-01-03 UTC','2020-01-04 UTC','2020-01-05 UTC','one',null,false,true,'{"n":4}'),
|
|
14
|
+
('66700000-0000-4000-8000-000000000205','667-search-own','folder/one','2020-01-04 UTC','2020-01-05 UTC','2020-01-06 UTC','one',null,false,true,'{"n":5}'),
|
|
15
|
+
('66700000-0000-4000-8000-000000000206','667-search-own','folder/two','2020-01-05 UTC','2020-01-06 UTC','2020-01-07 UTC','one',null,false,true,'{"n":6}'),
|
|
16
|
+
('66700000-0000-4000-8000-000000000207','667-search-own','alpha-marker','2020-01-06 UTC','2020-01-07 UTC','2020-01-08 UTC','one',null,true,true,'{"n":7}'),
|
|
17
|
+
('66700000-0000-4000-8000-000000000208','667-search-decoy','decoy','2020-01-07 UTC','2020-01-08 UTC','2020-01-09 UTC','one',null,false,true,'{"n":8}');
|
|
18
|
+
create temp table ss_rows(ordinal bigint generated always as identity,name text,id uuid,updated_at timestamptz,created_at timestamptz,last_accessed_at timestamptz,metadata jsonb,version text,archived_at timestamptz,is_delete_marker boolean,is_versioned boolean) on commit drop;
|
|
19
|
+
truncate ss_rows;
|
|
20
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'','name','asc','exclude','exclude')$call$,'SS default ascending native call lives');
|
|
21
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['alpha','alpha!','beta','folder']::text[],'SS default ascending returns exact own names');
|
|
22
|
+
select ok((select count(*)=1 and bool_and(id='66700000-0000-4000-8000-000000000201'::uuid and metadata='{"n":1}'::jsonb and version='new' and created_at='2020-01-01 UTC'::timestamptz and updated_at='2020-01-02 UTC'::timestamptz and archived_at is null and not is_delete_marker and is_versioned) from ss_rows where name='alpha'),'SS exact own leaf fields are preserved');
|
|
23
|
+
select ok((select count(*)=1 and bool_and(id is null and metadata is null and version is null and created_at is null and updated_at is null) from ss_rows where name='folder'),'SS folder fields are distinct from a leaf');
|
|
24
|
+
truncate ss_rows;
|
|
25
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'','name','desc','exclude','exclude')$call$,'SS default descending native call lives');
|
|
26
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['folder','beta','alpha!','alpha']::text[],'SS default descending returns exact own names');
|
|
27
|
+
truncate ss_rows;
|
|
28
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',1,1,1,'','name','asc','exclude','exclude')$call$,'SS offset and limit native call lives');
|
|
29
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['alpha!']::text[],'SS offset and limit returns exact own names');
|
|
30
|
+
truncate ss_rows;
|
|
31
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('folder/','667-search-own',100,1,0,'','name','asc','exclude','exclude')$call$,'SS nested prefix native call lives');
|
|
32
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['one','two']::text[],'SS nested prefix returns exact own names');
|
|
33
|
+
truncate ss_rows;
|
|
34
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'alp','name','asc','exclude','exclude')$call$,'SS search term native call lives');
|
|
35
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['alpha','alpha!']::text[],'SS search term returns exact own names');
|
|
36
|
+
truncate ss_rows;
|
|
37
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'','name','asc','only','exclude')$call$,'SS archived only native call lives');
|
|
38
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['alpha']::text[],'SS archived only returns exact own names');
|
|
39
|
+
truncate ss_rows;
|
|
40
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'','name','asc','include','exclude')$call$,'SS versions included native call lives');
|
|
41
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['alpha','alpha','alpha!','beta','folder']::text[],'SS versions included returns exact own names');
|
|
42
|
+
truncate ss_rows;
|
|
43
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'','name','asc','exclude','only')$call$,'SS markers ascending native call lives');
|
|
44
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['alpha-marker']::text[],'SS markers ascending returns exact own names');
|
|
45
|
+
truncate ss_rows;
|
|
46
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'','name','desc','exclude','only')$call$,'SS markers descending native call lives');
|
|
47
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['alpha-marker']::text[],'SS markers descending returns exact own names');
|
|
48
|
+
truncate ss_rows;
|
|
49
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'','name','asc','include','only')$call$,'SS multiversion markers native call lives');
|
|
50
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['alpha-marker']::text[],'SS multiversion markers returns exact own names');
|
|
51
|
+
truncate ss_rows;
|
|
52
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'alp','name','desc','exclude','exclude')$call$,'SS bounded descending prefix native call lives');
|
|
53
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['alpha!','alpha']::text[],'SS bounded descending prefix returns exact own names');
|
|
54
|
+
truncate ss_rows;
|
|
55
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'','created_at','asc','exclude','exclude')$call$,'SS non-name created_at asc native call lives');
|
|
56
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['folder','alpha','alpha!','beta']::text[],'SS non-name created_at asc returns exact own names');
|
|
57
|
+
truncate ss_rows;
|
|
58
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'','created_at','desc','exclude','exclude')$call$,'SS non-name created_at desc native call lives');
|
|
59
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['folder','beta','alpha!','alpha']::text[],'SS non-name created_at desc returns exact own names');
|
|
60
|
+
truncate ss_rows;
|
|
61
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'','updated_at','asc','exclude','exclude')$call$,'SS non-name updated_at asc native call lives');
|
|
62
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['folder','alpha','alpha!','beta']::text[],'SS non-name updated_at asc returns exact own names');
|
|
63
|
+
truncate ss_rows;
|
|
64
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'','updated_at','desc','exclude','exclude')$call$,'SS non-name updated_at desc native call lives');
|
|
65
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['folder','beta','alpha!','alpha']::text[],'SS non-name updated_at desc returns exact own names');
|
|
66
|
+
truncate ss_rows;
|
|
67
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'','last_accessed_at','asc','exclude','exclude')$call$,'SS non-name last_accessed_at asc native call lives');
|
|
68
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['folder','alpha','alpha!','beta']::text[],'SS non-name last_accessed_at asc returns exact own names');
|
|
69
|
+
truncate ss_rows;
|
|
70
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,'','last_accessed_at','desc','exclude','exclude')$call$,'SS non-name last_accessed_at desc native call lives');
|
|
71
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array['folder','beta','alpha!','alpha']::text[],'SS non-name last_accessed_at desc returns exact own names');
|
|
72
|
+
insert into storage.objects(bucket_id,name,version,is_versioned) values('667-search-own',$data$quote'; SELECT 1; --$data$,'one',true);
|
|
73
|
+
truncate ss_rows;
|
|
74
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own',100,1,0,$data$quote'; SELECT 1; --$data$,'name','asc')$call$,'SS SQL-looking search data call lives');
|
|
75
|
+
select is((select array_agg(name order by ordinal) from ss_rows),array[$data$quote'; SELECT 1; --$data$]::text[],'SS SQL-looking search value remains bound data');
|
|
76
|
+
grant insert,select on ss_rows to service_role,authenticated;
|
|
77
|
+
grant usage,select on sequence ss_rows_ordinal_seq to service_role,authenticated;
|
|
78
|
+
truncate ss_rows;
|
|
79
|
+
set local role service_role;
|
|
80
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own')$call$,'SS service role native call lives');
|
|
81
|
+
reset role;
|
|
82
|
+
select is((select count(*) from ss_rows),5::bigint,'SS service role sees own default rows');
|
|
83
|
+
truncate ss_rows;
|
|
84
|
+
set local role authenticated;
|
|
85
|
+
select lives_ok($call$insert into ss_rows(name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search('','667-search-own')$call$,'SS authenticated native call lives');
|
|
86
|
+
reset role;
|
|
87
|
+
select is((select count(*) from ss_rows),0::bigint,'SS native empty policy set refuses authenticated rows');
|
|
88
|
+
\else
|
|
89
|
+
select plan(1);
|
|
90
|
+
select ok(to_regprocedure('storage.search(text,text,integer,integer,integer,text,text,text,text,text)') is null,'SS native search absent; no native behavior credit');
|
|
91
|
+
\endif
|
|
92
|
+
select * from finish();
|
|
93
|
+
rollback;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
create extension if not exists pgtap with schema extensions;
|
|
2
|
+
set search_path=extensions,public,agent_board;
|
|
3
|
+
begin;
|
|
4
|
+
\ir fixtures/agent_board_667_conversion_guard.sql
|
|
5
|
+
\ir fixtures/agent_board_667_sender_guard.sql
|
|
6
|
+
\ir fixtures/agent_board_667_timestamp_guard.sql
|
|
7
|
+
\ir fixtures/agent_board_667_search_guard.sql
|
|
8
|
+
select plan(4);
|
|
9
|
+
create temp table ss_prior on commit drop as select * from pg_temp.xb_ss_prerequisite_problems();
|
|
10
|
+
create function pg_temp.array_to_string(text[],text) returns text language sql as $f$select 'own-shadow'$f$;
|
|
11
|
+
select ok(exists(select 1 from pg_proc where oid='pg_temp.array_to_string(text[],text)'::regprocedure),
|
|
12
|
+
'SS own resolution control is installed in the catalog');
|
|
13
|
+
select ok(exists(select 1 from pg_temp.xb_ss_prerequisite_problems()
|
|
14
|
+
where identity=pg_temp.xb_cf_fn('pg_temp.array_to_string(text[],text)'::regprocedure) and problem='unreviewed search overload or shadow'),
|
|
15
|
+
'SS resolution census names the injected overload identity');
|
|
16
|
+
select is((select count(*) from pg_temp.xb_ss_admitted()),0::bigint,'SS unreviewed overload closes admission');
|
|
17
|
+
drop function pg_temp.array_to_string(text[],text);
|
|
18
|
+
select is((select jsonb_agg(jsonb_build_array(identity,problem) order by identity,problem) from pg_temp.xb_ss_prerequisite_problems()),
|
|
19
|
+
(select jsonb_agg(jsonb_build_array(identity,problem) order by identity,problem) from ss_prior),
|
|
20
|
+
'SS own overload removal restores the prior prerequisite findings');
|
|
21
|
+
select * from finish();
|
|
22
|
+
rollback;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
create extension if not exists pgtap with schema extensions;
|
|
2
|
+
create extension if not exists plpgsql_check with schema extensions;
|
|
3
|
+
set search_path=extensions,public,agent_board;
|
|
4
|
+
begin;
|
|
5
|
+
\ir fixtures/agent_board_667_conversion_guard.sql
|
|
6
|
+
\ir fixtures/agent_board_667_sender_guard.sql
|
|
7
|
+
\ir fixtures/agent_board_667_timestamp_guard.sql
|
|
8
|
+
\ir fixtures/agent_board_667_search_guard.sql
|
|
9
|
+
select to_regprocedure('storage.search(text,text,integer,integer,integer,text,text,text,text,text)') is not null as native_present \gset
|
|
10
|
+
\if :native_present
|
|
11
|
+
select plan(18);
|
|
12
|
+
select is((select string_agg(identity||': '||problem,', ' order by identity,problem) from pg_temp.xb_ss_problems()),null::text,
|
|
13
|
+
'SS complete source, relation, resolution and callback profile matches');
|
|
14
|
+
select is((select array_agg(fn order by fn) from pg_temp.xb_ss_admitted()),
|
|
15
|
+
array['storage.search(text,text,integer,integer,integer,text,text,text,text,text)'::regprocedure::oid],
|
|
16
|
+
'SS exactly the native search OID is admitted');
|
|
17
|
+
select is((select count(*) from pg_temp.xb_ss_views),341::bigint,'SS all source-bound query and expression views parsed');
|
|
18
|
+
select is((select array_agg(category||':'||n order by category) from (select category,count(*) n from pg_temp.xb_ss_views group by category) q),
|
|
19
|
+
array['dynamic:152','expression:176','static:13']::text[],'SS every inventory category is present');
|
|
20
|
+
select is((select payload->>'prosrc_md5' from pg_temp.xb_ss_reference where kind='coverage'),
|
|
21
|
+
(select md5(prosrc) from pg_proc where oid='storage.search(text,text,integer,integer,integer,text,text,text,text,text)'::regprocedure),
|
|
22
|
+
'SS constructor coverage is bound to the actual native body');
|
|
23
|
+
select is((select jsonb_array_length(payload->'execute_sites') from pg_temp.xb_ss_reference where kind='coverage'),4,
|
|
24
|
+
'SS lexical coverage includes every EXECUTE site');
|
|
25
|
+
select ok(exists(select 1 from pg_temp.xb_ss_reach() where fn='pg_catalog.texticlike_support(internal)'::regprocedure),
|
|
26
|
+
'SS ILIKE planner support callback is reached');
|
|
27
|
+
select ok(exists(select 1 from pg_temp.xb_ss_roots() where fn='pg_catalog.format(text,"any")'::regprocedure),
|
|
28
|
+
'SS SQL constructors themselves are in the executable graph');
|
|
29
|
+
select ok(exists(select 1 from pg_temp.xb_ss_roots() where fn='storage.get_common_prefix(text,text,text)'::regprocedure),
|
|
30
|
+
'SS source expressions reach the separately reviewed SQL prefix helper');
|
|
31
|
+
select ok((select count(*) from pg_temp.xb_ss_views v join pg_temp.xb_ss_reference q on q.kind='query' and q.identity=v.identity where q.payload->>'role'='record')=
|
|
32
|
+
(select sum((e->>'variants')::integer) from pg_temp.xb_ss_reference r cross join lateral jsonb_array_elements(r.payload->'execute_sites') e where r.kind='coverage' and e->>'role'='record')
|
|
33
|
+
and (select jsonb_array_length(payload->'record_fields')>0 from pg_temp.xb_ss_reference where kind='coverage'),
|
|
34
|
+
'SS every record batch has a nonempty source-derived field-type check');
|
|
35
|
+
select is((select array_agg(distinct d.refobjid::regclass::text order by d.refobjid::regclass::text) from pg_temp.xb_ss_views v
|
|
36
|
+
join pg_rewrite w on w.ev_class=v.rel join pg_depend d on d.classid='pg_rewrite'::regclass and d.objid=w.oid
|
|
37
|
+
where d.refclassid='pg_class'::regclass and d.refobjid<>v.rel),array['storage.objects']::text[],
|
|
38
|
+
'SS parsed inventory selects only the reviewed persistent target');
|
|
39
|
+
create function pg_temp.xb_ss_null_execute() returns void language plpgsql as $f$begin execute null::text;end$f$;
|
|
40
|
+
select throws_ok('select pg_temp.xb_ss_null_execute()','22004','query string argument of EXECUTE is null',
|
|
41
|
+
'SS nullable constructor path is a refusal, not executable caller text');
|
|
42
|
+
select ok((select bool_and(payload->>'group' in('dynamic','static','expression')) from pg_temp.xb_ss_reference where kind='query'),
|
|
43
|
+
'SS reference rows have classified source origins');
|
|
44
|
+
create temp table xb_ss_effect(note text) on commit drop;
|
|
45
|
+
create function pg_temp.xb_ss_dml() returns trigger language plpgsql as $f$
|
|
46
|
+
begin insert into pg_temp.xb_ss_effect values('called');return new;end$f$;
|
|
47
|
+
create trigger xb_ss_dml_control before insert on storage.objects for each row execute function pg_temp.xb_ss_dml();
|
|
48
|
+
insert into storage.buckets(id,name) values('667-search-dml','667-search-dml');
|
|
49
|
+
select lives_ok($call$select * from storage.search('','667-search-dml')$call$,'SS SELECT with a live DML callback lives');
|
|
50
|
+
select is((select count(*) from pg_temp.xb_ss_effect),0::bigint,'SS native SELECT does not invoke the DML callback');
|
|
51
|
+
select lives_ok($call$insert into storage.objects(bucket_id,name) values('667-search-dml','own-dml-control')$call$,'SS own DML callback control lives');
|
|
52
|
+
select is((select count(*) from pg_temp.xb_ss_effect),1::bigint,'SS own DML positively invokes the same callback');
|
|
53
|
+
select is((select count(*) from pg_temp.xb_ss_admitted()),1::bigint,'SS DML-only callback preserves SELECT admission');
|
|
54
|
+
\else
|
|
55
|
+
select plan(1);
|
|
56
|
+
select ok(to_regprocedure('storage.search(text,text,integer,integer,integer,text,text,text,text,text)') is null
|
|
57
|
+
and not exists(select 1 from pg_temp.xb_ss_admitted()),'SS absent native search has no admission or native credit');
|
|
58
|
+
\endif
|
|
59
|
+
select * from finish();
|
|
60
|
+
rollback;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
-- Native behavior is separate from the catalog effect/admission proof.
|
|
2
|
+
create extension if not exists pgtap with schema extensions;
|
|
3
|
+
set search_path=extensions,public,agent_board;
|
|
4
|
+
begin;
|
|
5
|
+
select (to_regprocedure('storage.search_by_timestamp(text,text,integer,integer,text,text,text,text,text,text,text)') is not null and to_regclass('storage.objects') is not null and to_regclass('storage.buckets') is not null) as native_present \gset
|
|
6
|
+
\if :native_present
|
|
7
|
+
select plan(19);
|
|
8
|
+
insert into storage.buckets(id,name) values ('667-timestamp-probe','667-timestamp-probe');
|
|
9
|
+
insert into storage.objects(id,bucket_id,name,created_at,updated_at,version,archived_at,is_delete_marker,is_versioned,metadata) values
|
|
10
|
+
('66700000-0000-4000-8000-000000000001','667-timestamp-probe','alpha','2020-01-01 UTC','2020-01-02 UTC','v1',null,false,true,'{"n":1}'),
|
|
11
|
+
('66700000-0000-4000-8000-000000000002','667-timestamp-probe','folder/child','2020-01-03 UTC','2020-01-04 UTC','v2',null,false,true,'{"n":2}'),
|
|
12
|
+
('66700000-0000-4000-8000-000000000003','667-timestamp-probe','alpha','2020-01-01 UTC','2020-01-02 UTC','old','2020-02-01 UTC',false,true,'{"n":3}'),
|
|
13
|
+
('66700000-0000-4000-8000-000000000004','667-timestamp-probe','deleted','2020-01-05 UTC','2020-01-06 UTC','v4',null,true,true,'{"n":4}'),
|
|
14
|
+
('66700000-0000-4000-8000-000000000005','667-timestamp-probe','percent%literal','2020-01-07 UTC','2020-01-08 UTC','v5',null,false,true,'{"n":5}'),
|
|
15
|
+
('66700000-0000-4000-8000-000000000006','667-timestamp-probe','percentXdecoy','2020-01-09 UTC','2020-01-10 UTC','v6',null,false,true,'{"n":6}'),
|
|
16
|
+
('66700000-0000-4000-8000-000000000008','667-timestamp-probe','folder/another','2020-01-04 UTC','2020-01-05 UTC','v8',null,false,true,'{"n":8}');
|
|
17
|
+
create temp table xb_timestamp_rows (ordinal bigint generated always as identity, key text,name text,id uuid,updated_at timestamptz,created_at timestamptz,last_accessed_at timestamptz,metadata jsonb,version text,archived_at timestamptz,is_delete_marker boolean,is_versioned boolean) on commit drop;
|
|
18
|
+
select lives_ok($q$insert into xb_timestamp_rows (key,name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search_by_timestamp('','667-timestamp-probe',100,1,'','asc','updated_at','')$q$,'ST native default call lives');
|
|
19
|
+
select is((select array_agg(name order by ordinal) from xb_timestamp_rows),array['alpha','folder/','percent%literal','percentXdecoy']::text[],'ST default filters and folder aggregation');
|
|
20
|
+
select ok((select count(*)=1 and bool_and(id='66700000-0000-4000-8000-000000000001'::uuid and key='alpha' and metadata='{"n":1}'::jsonb and version='v1' and not is_delete_marker and is_versioned) from xb_timestamp_rows where name='alpha'),'ST leaf fields preserved');
|
|
21
|
+
select is((select jsonb_agg(jsonb_build_array(key,name,id,updated_at,created_at,metadata,version,archived_at,is_delete_marker,is_versioned) order by ordinal) from xb_timestamp_rows where name='alpha'),jsonb_build_array(jsonb_build_array('alpha','alpha','66700000-0000-4000-8000-000000000001'::uuid,'2020-01-02 UTC'::timestamptz,'2020-01-01 UTC'::timestamptz,'{"n":1}'::jsonb,'v1',null,false,true)),'ST exact stable leaf projection');
|
|
22
|
+
select ok((select count(*)=1 and bool_and(id is null and key='folder' and created_at='2020-01-03 UTC'::timestamptz and updated_at=created_at and metadata is null and version is null) from xb_timestamp_rows where name='folder/'),'ST folder fields and timestamp');
|
|
23
|
+
truncate xb_timestamp_rows;
|
|
24
|
+
select lives_ok($q$insert into xb_timestamp_rows (key,name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search_by_timestamp('','667-timestamp-probe',1,1,'alpha','asc','updated_at','2020-01-02 UTC')$q$,'ST cursor call lives');
|
|
25
|
+
select is((select array_agg(name) from xb_timestamp_rows),array['folder/']::text[],'ST cursor and limit');
|
|
26
|
+
truncate xb_timestamp_rows;
|
|
27
|
+
select lives_ok($q$insert into xb_timestamp_rows (key,name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search_by_timestamp('','667-timestamp-probe',100,1,'','desc','created_at','','include','include')$q$,'ST inclusive call lives');
|
|
28
|
+
select is((select array_agg(name||':'||coalesce(version,'') order by ordinal) from xb_timestamp_rows),array['percentXdecoy:v6','percent%literal:v5','deleted:v4','folder/:','alpha:v1','alpha:old']::text[],'ST inclusive version and marker rows');
|
|
29
|
+
truncate xb_timestamp_rows;
|
|
30
|
+
select lives_ok($q$insert into xb_timestamp_rows (key,name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search_by_timestamp('percent%','667-timestamp-probe',100,1,'','asc','updated_at','','bogus','bogus')$q$,'ST literal percent and invalid filters call lives');
|
|
31
|
+
select is((select array_agg(name) from xb_timestamp_rows),array['percent%literal']::text[],'ST LIKE metacharacter is literal');
|
|
32
|
+
truncate xb_timestamp_rows;
|
|
33
|
+
select lives_ok($q$insert into xb_timestamp_rows (key,name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search_by_timestamp('','667-timestamp-probe',100,1,'','desc; select 1','created_at; select 1','','invalid','invalid')$q$,'ST invalid sort text falls back');
|
|
34
|
+
select is((select array_agg(name order by ordinal) from xb_timestamp_rows),array['alpha','folder/','percent%literal','percentXdecoy']::text[],'ST invalid options use default filters');
|
|
35
|
+
insert into storage.objects(id,bucket_id,name,created_at,updated_at,version,is_delete_marker,is_versioned)
|
|
36
|
+
values ('66700000-0000-4000-8000-000000000007','667-timestamp-probe',$v$quote'; SELECT 1; --$v$,'2020-01-11 UTC','2020-01-12 UTC','v7',false,true);
|
|
37
|
+
truncate xb_timestamp_rows;
|
|
38
|
+
select lives_ok($q$insert into xb_timestamp_rows (key,name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search_by_timestamp($v$quote'; SELECT 1; --$v$,'667-timestamp-probe',100,1,'','asc','updated_at','')$q$,'ST SQL-looking prefix call lives');
|
|
39
|
+
select is((select array_agg(name order by ordinal) from xb_timestamp_rows),array[$v$quote'; SELECT 1; --$v$]::text[],'ST SQL-looking prefix is data');
|
|
40
|
+
truncate xb_timestamp_rows;
|
|
41
|
+
grant insert,select on xb_timestamp_rows to service_role,authenticated;
|
|
42
|
+
grant usage,select on sequence xb_timestamp_rows_ordinal_seq to service_role,authenticated;
|
|
43
|
+
set local role service_role;
|
|
44
|
+
select lives_ok($q$insert into xb_timestamp_rows (key,name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search_by_timestamp('','667-timestamp-probe',100,1,'','asc','updated_at','')$q$,'ST service role call lives');
|
|
45
|
+
reset role;
|
|
46
|
+
select is((select count(*) from xb_timestamp_rows),5::bigint,'ST service role sees own current non-marker rows');
|
|
47
|
+
truncate xb_timestamp_rows;
|
|
48
|
+
set local role authenticated;
|
|
49
|
+
select lives_ok($q$insert into xb_timestamp_rows (key,name,id,updated_at,created_at,last_accessed_at,metadata,version,archived_at,is_delete_marker,is_versioned) select * from storage.search_by_timestamp('','667-timestamp-probe',100,1,'','asc','updated_at','')$q$,'ST authenticated role call lives');
|
|
50
|
+
reset role;
|
|
51
|
+
select is((select count(*) from xb_timestamp_rows),0::bigint,'ST authenticated role sees no rows under native empty policy set');
|
|
52
|
+
\else
|
|
53
|
+
select plan(1);
|
|
54
|
+
select ok(to_regprocedure('storage.search_by_timestamp(text,text,integer,integer,text,text,text,text,text,text,text)') is null,
|
|
55
|
+
'ST native reader is absent; no native behavior credit');
|
|
56
|
+
\endif
|
|
57
|
+
select * from finish();
|
|
58
|
+
rollback;
|