"""Opt-in persistence checks for the isolated generated demo dataset.""" import os import subprocess import sys from uuid import uuid4 import psycopg import pytest from psycopg.rows import dict_row from psycopg.types.json import Jsonb from app.core.config import settings from app.services.content_digest import digest from samples.peripheral.auth import Identity from samples.peripheral.config import SampleSettings from samples.peripheral.demo_data import build_demo_content from samples.peripheral.errors import SampleFailure from samples.peripheral.store import PostgresStore pytestmark = pytest.mark.skipif( os.getenv("PERIPHERAL_SAMPLE_LIVE_TEST") != "1", reason="set PERIPHERAL_SAMPLE_LIVE_TEST=1 to use provisioned peripheral_sample storage", ) def connection(): return psycopg.connect( host=settings.DB_HOST, port=settings.DB_PORT, user=settings.DB_USER, password=settings.DB_PASSWORD, dbname="tjwater_v2", connect_timeout=3, options="-c statement_timeout=10000", row_factory=dict_row, ) @pytest.fixture def live_demo_project(): project_id = uuid4() content = build_demo_content("live-" + str(project_id)) revision = digest(content) with connection() as conn: conn.execute( """INSERT INTO peripheral_sample.demo_datasets (project_id,dataset_id,digest,document) VALUES (%s,'water-demo-v1',%s,%s)""", (project_id, revision, Jsonb(content)), ) try: yield project_id, content, revision finally: with connection() as conn: conn.execute("DELETE FROM peripheral_sample.demo_datasets WHERE project_id=%s", (project_id,)) conn.execute("DELETE FROM peripheral_sample.scenarios WHERE project_id=%s", (project_id,)) def test_persisted_demo_is_read_from_fresh_connection_and_process(live_demo_project): project_id, content, revision = live_demo_project store = PostgresStore(SampleSettings(db_name="tjwater_v2")) result = store.demo_data(Identity(str(project_id), str(uuid4()), False)) assert result["source_revision"] == revision assert result["observations"] == content["observations"] script = """ import sys from samples.peripheral.auth import Identity from samples.peripheral.config import SampleSettings from samples.peripheral.store import PostgresStore result = PostgresStore(SampleSettings(db_name='tjwater_v2')).demo_data(Identity(sys.argv[1], sys.argv[2], False)) assert result['source_revision'] == sys.argv[3] and len(result['observations']) == 240 print('ok') """ child = subprocess.run( [sys.executable, "-c", script, str(project_id), str(uuid4()), revision], check=True, capture_output=True, text=True, ) assert child.stdout.strip() == "ok" def test_demo_read_is_project_isolated_and_never_calls_generator(live_demo_project, monkeypatch): project_id, _, _ = live_demo_project monkeypatch.setattr( "samples.peripheral.demo_data.build_demo_content", lambda *args, **kwargs: pytest.fail("persisted reads must not invoke the generator"), ) store = PostgresStore(SampleSettings(db_name="tjwater_v2")) assert store.demo_data(Identity(str(project_id), str(uuid4()), False))["project_id"] == str(project_id) with pytest.raises(SampleFailure) as missing: store.demo_data(Identity(str(uuid4()), str(uuid4()), False)) assert missing.value.code == "SOURCE_NOT_CONFIGURED" def test_tampered_document_is_rejected_and_cleanup_remains_scoped(live_demo_project): project_id, _, _ = live_demo_project with connection() as conn: conn.execute( """UPDATE peripheral_sample.demo_datasets SET document=jsonb_set(document,'{seed}',to_jsonb(%s::text)) WHERE project_id=%s AND dataset_id='water-demo-v1'""", ("tampered", project_id), ) store = PostgresStore(SampleSettings(db_name="tjwater_v2")) with pytest.raises(SampleFailure) as rejected: store.demo_data(Identity(str(project_id), str(uuid4()), False)) assert rejected.value.code == "INTEGRITY_MISMATCH"