@@ -180,3 +180,91 @@ loaded = store.load("definer-search-path-a")
180180assert loaded is not None
181181assert loaded.evidence_id == "definer-search-path-a"
182182PY
183+
184+ docker exec -i " ${container} " psql -U postgres -d postgres -v ON_ERROR_STOP=1 << 'SQL '
185+ CREATE ROLE cwl_llm_batch_outbox_view_owner NOLOGIN
186+ NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION BYPASSRLS;
187+ GRANT USAGE, CREATE ON SCHEMA public TO cwl_llm_batch_outbox_view_owner;
188+ GRANT SELECT ON public.llm_context_lifecycle_outbox
189+ TO cwl_llm_batch_outbox_view_owner;
190+ SET ROLE cwl_llm_batch_outbox_view_owner;
191+ CREATE VIEW public.cwl_llm_batch_outbox_privileged_view AS
192+ SELECT tenant_scope, evidence_id
193+ FROM public.llm_context_lifecycle_outbox;
194+ RESET ROLE;
195+ REVOKE CREATE ON SCHEMA public FROM cwl_llm_batch_outbox_view_owner;
196+ REVOKE ALL ON public.cwl_llm_batch_outbox_privileged_view FROM PUBLIC;
197+ GRANT SELECT ON public.cwl_llm_batch_outbox_privileged_view
198+ TO cwl_llm_batch_outbox_definer_path_caller;
199+ SQL
200+
201+ view_counts=" $(
202+ docker exec -i " ${container} " psql -h 127.0.0.1 \
203+ -U cwl_llm_batch_outbox_definer_path_caller -d postgres -Atq \
204+ -v ON_ERROR_STOP=1 << 'SQL '
205+ BEGIN;
206+ SELECT pg_catalog.set_config('pg_llm_batch.tenant_scope', 'tenant-a', true);
207+ SELECT pg_catalog.count(*) FROM ONLY public.llm_context_lifecycle_outbox;
208+ SELECT pg_catalog.count(*) FROM public.cwl_llm_batch_outbox_privileged_view;
209+ ROLLBACK;
210+ SQL
211+ ) "
212+ if [[ " ${view_counts} " != $' tenant-a\n 1\n 2' ]]; then
213+ echo " privileged view specimen did not reproduce the forced-RLS bypass" >&2
214+ printf ' %s\n' " ${view_counts} " >&2
215+ exit 1
216+ fi
217+
218+ docker run --rm -i --network " container:${container} " " ${component_image} " python - << 'PY '
219+ from pg_llm_batch.context_lifecycle_outbox import PostgresContextLifecycleOutboxStore
220+ from pg_llm_batch.exceptions import ConfigError
221+
222+ store = PostgresContextLifecycleOutboxStore(
223+ "postgresql://cwl_llm_batch_outbox_definer_path_caller@127.0.0.1/postgres",
224+ tenant_scope="tenant-a",
225+ tenant_scope_sha256="a" * 64,
226+ )
227+ try:
228+ store.load("definer-search-path-a")
229+ except ConfigError as exc:
230+ assert "separated forced RLS authority" in str(exc)
231+ else:
232+ raise AssertionError(
233+ "runtime admitted a caller-selectable non-security-invoker view whose BYPASSRLS "
234+ "owner can read the lifecycle outbox across forced-RLS tenant boundaries"
235+ )
236+ PY
237+
238+ docker exec -i " ${container} " psql -U postgres -d postgres -v ON_ERROR_STOP=1 << 'SQL '
239+ ALTER VIEW public.cwl_llm_batch_outbox_privileged_view
240+ SET (security_invoker = true);
241+ SQL
242+
243+ safe_view_count=" $(
244+ docker exec -i " ${container} " psql -h 127.0.0.1 \
245+ -U cwl_llm_batch_outbox_definer_path_caller -d postgres -Atq \
246+ -v ON_ERROR_STOP=1 << 'SQL '
247+ BEGIN;
248+ SELECT pg_catalog.set_config('pg_llm_batch.tenant_scope', 'tenant-a', true);
249+ SELECT pg_catalog.count(*) FROM public.cwl_llm_batch_outbox_privileged_view;
250+ ROLLBACK;
251+ SQL
252+ ) "
253+ if [[ " ${safe_view_count} " != $' tenant-a\n 1' ]]; then
254+ echo " security-invoker view positive control did not preserve tenant RLS" >&2
255+ printf ' %s\n' " ${safe_view_count} " >&2
256+ exit 1
257+ fi
258+
259+ docker run --rm -i --network " container:${container} " " ${component_image} " python - << 'PY '
260+ from pg_llm_batch.context_lifecycle_outbox import PostgresContextLifecycleOutboxStore
261+
262+ store = PostgresContextLifecycleOutboxStore(
263+ "postgresql://cwl_llm_batch_outbox_definer_path_caller@127.0.0.1/postgres",
264+ tenant_scope="tenant-a",
265+ tenant_scope_sha256="a" * 64,
266+ )
267+ loaded = store.load("definer-search-path-a")
268+ assert loaded is not None
269+ assert loaded.evidence_id == "definer-search-path-a"
270+ PY
0 commit comments