Spaces:
Sleeping
Sleeping
| """Durable decision store on Postgres (Neon), used only when DATABASE_URL is set. | |
| Kept deliberately tiny and schema-light: a moderator decision is a flat dict, stored verbatim as a | |
| JSONB row, so its shape can evolve without migrations. This is the durable seam behind | |
| `src/audit.py` — the deployed Hugging Face Space has an ephemeral filesystem, so the audit log lives | |
| here instead of in a local file. | |
| A fresh connection is opened per operation (and closed via the context manager). Traffic is low and | |
| Neon's pooled endpoint handles this cheaply; it avoids the stale-idle-connection failures a cached | |
| long-lived connection would hit on a demo that sits quiet for hours. | |
| """ | |
| from __future__ import annotations | |
| from .config import CONFIG | |
| _schema_ready = False | |
| def _connect(): | |
| import psycopg # lazy: only imported when a database is actually configured | |
| return psycopg.connect(CONFIG.database_url, autocommit=True) | |
| def _ensure_schema(conn) -> None: | |
| global _schema_ready | |
| if _schema_ready: | |
| return | |
| with conn.cursor() as cur: | |
| cur.execute( | |
| "CREATE TABLE IF NOT EXISTS audit_log (" | |
| " id BIGSERIAL PRIMARY KEY," | |
| " ts TIMESTAMPTZ NOT NULL DEFAULT now()," | |
| " record JSONB NOT NULL" | |
| ")" | |
| ) | |
| _schema_ready = True | |
| def insert_decision(record: dict) -> None: | |
| """Append one decision record (stored as a JSONB row).""" | |
| from psycopg.types.json import Json | |
| with _connect() as conn: | |
| _ensure_schema(conn) | |
| with conn.cursor() as cur: | |
| cur.execute("INSERT INTO audit_log (record) VALUES (%s)", (Json(record),)) | |
| def fetch_decisions() -> list[dict]: | |
| """All decision records in write order (oldest first). psycopg adapts JSONB to dict.""" | |
| with _connect() as conn: | |
| _ensure_schema(conn) | |
| with conn.cursor() as cur: | |
| cur.execute("SELECT record FROM audit_log ORDER BY id") | |
| return [row[0] for row in cur.fetchall()] | |