"""Report whether the database schema matches the code (STATE-WP-0083-T07). Central ran two revisions behind the code it was serving, and `review_contracts` did not exist there although its migration shipped inside the running image. Nothing surfaced that: the API starts happily against a schema it was not built for, and only fails when a request happens to touch the missing table. A hub that cannot say which schema it is running has the same problem as a projection that cannot name its source commit — it is asserting correctness it cannot demonstrate. """ from __future__ import annotations from functools import lru_cache from pathlib import Path from typing import Any from sqlalchemy import text from sqlalchemy.ext.asyncio import AsyncSession _MIGRATIONS = Path(__file__).resolve().parents[2] / "migrations" @lru_cache(maxsize=1) def code_head_revision() -> str | None: """The head revision the shipped migration scripts define. Read from the migration files rather than the database: this is what the code expects, and it must be knowable without a working connection. """ try: from alembic.config import Config from alembic.script import ScriptDirectory cfg = Config() cfg.set_main_option("script_location", str(_MIGRATIONS)) heads = ScriptDirectory.from_config(cfg).get_heads() return heads[0] if len(heads) == 1 else ",".join(sorted(heads)) or None except Exception: return None async def db_revision(session: AsyncSession) -> str | None: try: result = await session.execute(text("select version_num from alembic_version")) return result.scalar() except Exception: return None async def schema_state(session: AsyncSession) -> dict[str, Any]: applied = await db_revision(session) expected = code_head_revision() # "unknown" is deliberately not "ok": an instance that cannot determine its # own schema state must not report agreement it has not established. if applied is None or expected is None: status = "unknown" elif applied == expected: status = "ok" else: status = "behind" return {"status": status, "applied": applied, "expected": expected}