import os import sqlite3 import stat from pathlib import Path import pytest from src.available_issue_snapshot_store import AvailableIssueSnapshotStore from src.completed_filed_review_store import CompletedFiledReviewStore from src.idempotency import IdempotencyLedger from src.later_store import LaterStore from src.live_snapshot_store import LiveSnapshotStore from src.login_attempt_store import LoginAttemptStore from src.passkey_store import PasskeyStore from src.private_state import connect_private_sqlite from src.push_subscription_store import PushSubscriptionStore from src.saved_search_store import SavedSearchStore from src.security_event_store import SecurityEventStore from src.session_store import SessionStore from src.today_store import TodayStore from src.unfiled_draft_store import UnfiledDraftStore def mode(path: Path) -> int: return stat.S_IMODE(path.stat().st_mode) def test_private_sqlite_connection_enforces_directory_database_and_sidecar_modes(tmp_path): state = tmp_path / "state" old_umask = os.umask(0o022) try: connection = connect_private_sqlite(state / "private.sqlite3") connection.execute("PRAGMA journal_mode=WAL") connection.execute("CREATE TABLE secrets (value TEXT)") connection.execute("INSERT INTO secrets VALUES ('operator data')") connection.commit() assert mode(state) == 0o700 assert mode(state / "private.sqlite3") == 0o600 assert mode(state / "private.sqlite3-wal") == 0o600 assert mode(state / "private.sqlite3-shm") == 0o600 finally: connection.close() os.umask(old_umask) def test_private_sqlite_connection_repairs_existing_permissive_modes_without_losing_rows(tmp_path): state = tmp_path / "state" state.mkdir(mode=0o755) database = state / "private.sqlite3" with sqlite3.connect(database) as connection: connection.execute("CREATE TABLE secrets (value TEXT)") connection.execute("INSERT INTO secrets VALUES ('keep me')") state.chmod(0o755) database.chmod(0o644) with connect_private_sqlite(database) as connection: value = connection.execute("SELECT value FROM secrets").fetchone()[0] assert value == "keep me" assert mode(state) == 0o700 assert mode(database) == 0o600 def test_private_sqlite_connection_rejects_a_symlink_before_opening_target(tmp_path): target = tmp_path / "target.sqlite3" with sqlite3.connect(target) as connection: connection.execute("CREATE TABLE sentinel (value TEXT)") connection.execute("INSERT INTO sentinel VALUES ('unchanged')") link = tmp_path / "state" / "private.sqlite3" link.parent.mkdir() link.symlink_to(target) with pytest.raises(ValueError, match="symlink"): connect_private_sqlite(link) with sqlite3.connect(target) as connection: assert connection.execute("SELECT value FROM sentinel").fetchone()[0] == "unchanged" @pytest.mark.parametrize( "build", [ TodayStore, LaterStore, SavedSearchStore, lambda path: UnfiledDraftStore(path, encryption_key=b"d" * 32), CompletedFiledReviewStore, PushSubscriptionStore, LiveSnapshotStore, AvailableIssueSnapshotStore, lambda path: IdempotencyLedger(path, ttl_seconds=60, max_entries=10), ], ) def test_eager_private_stores_share_the_private_filesystem_boundary(tmp_path, build): state = tmp_path / "state" old_umask = os.umask(0o022) try: build(state / "store.sqlite3") finally: os.umask(old_umask) assert mode(state) == 0o700 assert mode(state / "store.sqlite3") == 0o600 @pytest.mark.parametrize( "exercise", [ lambda path: SecurityEventStore(path, clock=lambda: 1).record("sign_in"), lambda path: LoginAttemptStore( path, clock=lambda: 1, max_failures=3, window_seconds=60 ).record_failure("203.0.113.10"), lambda path: PasskeyStore(path, clock=lambda: 1).issue_challenge( b"challenge", session_id=None, purpose="authentication", action="sign_in", target="dashboard", source="browser", ttl_seconds=60, ), lambda path: SessionStore(path, clock=lambda: 1).activate("session", 60), ], ) def test_on_demand_private_stores_share_the_private_filesystem_boundary(tmp_path, exercise): state = tmp_path / "state" old_umask = os.umask(0o022) try: exercise(state / "store.sqlite3") finally: os.umask(old_umask) assert mode(state) == 0o700 assert mode(state / "store.sqlite3") == 0o600