from __future__ import annotations from datetime import UTC, datetime import os from pathlib import Path from typing import Any from uuid import uuid4 import pytest from sqlalchemy import create_engine, text, update from app.database import Database from app.postgres_database import PostgresDatabase _INITIAL_TURN = { "role": "assistant", "content": None, "composer_mode": "ui_only", "blocks": [], } _TARGET_USER_ID = "2081575100391407617" def _profile( user_id: str | None = _TARGET_USER_ID, *, provider: str = "offerpai" ) -> dict[str, Any]: if user_id is None: return {} return { "external_account": { "provider": provider, "user_id": user_id, } } def _session_cases() -> list[tuple[str, dict[str, Any], datetime, datetime]]: first = datetime(2026, 1, 1, tzinfo=UTC) second = datetime(2026, 1, 2, tzinfo=UTC) latest = datetime(2026, 1, 3, tzinfo=UTC) excluded_latest = datetime(2026, 1, 4, tzinfo=UTC) return [ ("session-old", _profile(), first, first), # updated_at wins first; created_at then beats this lexically larger id. ("session-z-created-old", _profile(), first, latest), ("session-a", _profile(), second, latest), # Same timestamps as session-a: id is the final deterministic tie-breaker. ("session-c", _profile(), second, latest), ( "session-other-provider", _profile(provider="another-provider"), excluded_latest, excluded_latest, ), ( "session-other-user", _profile("another-user"), excluded_latest, excluded_latest, ), ("session-anonymous", _profile(None), excluded_latest, excluded_latest), ] def _create_sessions(database: Any) -> None: for session_id, profile, _created_at, _updated_at in _session_cases(): database.create_session( session_id, "PRIVACY_CONSENT", profile, _INITIAL_TURN, ) def test_sqlite_finds_latest_offerpai_session_with_deterministic_order( tmp_path: Path, ) -> None: database = Database(tmp_path / "identity-lookup.db") database.initialize() _create_sessions(database) with database.transaction(immediate=True) as connection: for session_id, _profile_value, created_at, updated_at in _session_cases(): connection.execute( "UPDATE sessions SET created_at = ?, updated_at = ? WHERE id = ?", (created_at.isoformat(), updated_at.isoformat(), session_id), ) found = database.find_latest_session_by_external_user_id( f" {_TARGET_USER_ID}\t" ) assert found is not None assert found["id"] == "session-c" assert database.find_latest_session_by_external_user_id("missing-user") is None def test_sqlite_ignores_blank_external_user_id(tmp_path: Path) -> None: database = Database(tmp_path / "identity-lookup-blank.db") database.initialize() for external_user_id in ("", " ", "\t\r\n"): assert database.find_latest_session_by_external_user_id(external_user_id) is None @pytest.fixture def postgres_database() -> Any: database_url = os.environ["RESUME_AGENT_TEST_DATABASE_URL"] schema = f"test_session_identity_{uuid4().hex}" database = PostgresDatabase(database_url, schema=schema) database.initialize() try: yield database finally: database.engine.dispose() cleanup_engine = create_engine(database_url) try: with cleanup_engine.begin() as connection: connection.execute(text(f'DROP SCHEMA IF EXISTS "{schema}" CASCADE')) finally: cleanup_engine.dispose() def test_postgres_finds_latest_offerpai_session_with_deterministic_order( postgres_database: PostgresDatabase, ) -> None: _create_sessions(postgres_database) sessions = postgres_database.tables["sessions"] with postgres_database.transaction() as connection: for session_id, _profile_value, created_at, updated_at in _session_cases(): connection.execute( update(sessions) .where(sessions.c.id == session_id) .values(created_at=created_at, updated_at=updated_at) ) found = postgres_database.find_latest_session_by_external_user_id( f" {_TARGET_USER_ID}\t" ) assert found is not None assert found["id"] == "session-c" assert ( postgres_database.find_latest_session_by_external_user_id("missing-user") is None ) def test_postgres_ignores_blank_external_user_id( postgres_database: PostgresDatabase, ) -> None: for external_user_id in ("", " ", "\t\r\n"): assert ( postgres_database.find_latest_session_by_external_user_id( external_user_id ) is None )