"""Citable figures: a permalink for any number we publish — source URL, exact pull time, hash of our copy, and that figure's own accuracy-check history. Plus the source-moved feed.""" import hashlib import json import re from urllib.parse import quote from datetime import datetime, timezone from html import escape as e from fastapi import APIRouter, HTTPException, Request from fastapi.responses import HTMLResponse from deps import db router = APIRouter() CSS = "body{font-family:Georgia,serif;max-width:760px;margin:0 auto;padding:28px 18px;color:#1a1a1a;line-height:1.5}h1{font-size:1.4rem;border-bottom:2px solid #1a1a1a;padding-bottom:8px}th{text-align:left;width:32%;vertical-align:top;padding:5px 8px 5px 0}td{padding:5px 0;vertical-align:top}tr{border-bottom:1px solid #e5e5e5}table{border-collapse:collapse;width:100%}code{font-size:.85em;word-break:break-all}.muted{color:#666;font-size:.92em}" def figure_id(source: str, subject: str, field: str) -> str: return hashlib.sha256(f"{source}|{subject}|{field}".encode()).hexdigest()[:16] def value_hash(v) -> str: return hashlib.sha256(json.dumps(v, sort_keys=True, default=str).encode()).hexdigest() async def _history(source: str, subject: str, field: str) -> dict: runs = await db.accuracy_runs.find({"checks": {"$elemMatch": {"source": source, "subject": subject, "field": field}}}, {"_id": 0, "at": 1, "checks.$": 1}).sort("at", -1).to_list(500) counts = {"match": 0, "source_moved": 0, "stale": 0, "unavailable": 0} last = None for r in runs: c = r["checks"][0] counts[c["result"]] = counts.get(c["result"], 0) + 1 if last is None: last = {"at": r["at"], "result": c["result"], "ours": c.get("ours"), "source_now": c.get("source_now")} tickets = await db.corrections.find({"opened_by": "accuracy_audit", "figure": {"$regex": re.escape(subject)}}, {"_id": 0, "ticket_id": 1, "created_at": 1, "resolved_at": 1, "outcome": 1}).to_list(50) days = [(datetime.fromisoformat(t["resolved_at"]) - datetime.fromisoformat(t["created_at"])).total_seconds() / 86400 for t in tickets if t.get("resolved_at")] return {"checks": len(runs), **counts, "last_check": last, "tickets_opened": len(tickets), "tickets_resolved": len(days), "median_days_to_correct": round(sorted(days)[len(days) // 2], 2) if days else None, "sentence": (f"checked {len(runs)} time{'s' if len(runs) != 1 else ''} against the source · stale {counts['stale']}× · source moved {counts['source_moved']}×" + (f" · corrected in {round(sorted(days)[len(days) // 2], 2)} days (median)" if days else "")) if runs else "not yet sampled by the daily accuracy check"} async def receipt(source: str, subject: str, field: str, value, source_url: str, pulled_at: str | None, origin: str) -> dict: fid = figure_id(source, subject, field) return {"figure_id": fid, "permalink": f"{origin}/api/cite/{fid}?source={quote(source)}&subject={quote(subject)}&field={quote(field)}", "source": source, "subject": subject, "field": field, "value": value, "value_sha256": value_hash(value), "source_url": source_url, "our_pull_at": pulled_at, "accuracy_history": await _history(source, subject, field), "generated_at": datetime.now(timezone.utc).isoformat(), "how_to_cite": f"Alpha Covenant Holdings, \"{field}\" for {subject}, from {source}, copy pulled {pulled_at or 'n/a'}, retrieved {datetime.now(timezone.utc).date()}, {origin}/api/cite/{fid}?source={quote(source)}&subject={quote(subject)}&field={quote(field)}"} async def _lookup(source: str, subject: str, field: str): """Find the current published value for a sampled figure. Returns (value, source_url, pulled_at) or None.""" if source == "CFPB Consumer Complaint Database": d = await db.covenant_scores.find_one({"company": subject, "cached_at": {"$gt": "1971"}}, {"_id": 0, "reproduce": 1, "cached_at": 1}, sort=[("cached_at", -1)]) if d: st = ((d.get("reproduce") or {}).get("steps") or [{}])[0] return st.get("value"), st.get("url"), d.get("cached_at") latest = await db.accuracy_runs.find_one({"checks": {"$elemMatch": {"source": source, "subject": subject, "field": field}}}, {"_id": 0, "checks.$": 1}, sort=[("at", -1)]) if latest: c = latest["checks"][0] return c.get("ours"), c.get("source_url"), c.get("our_pull_at") return None def _origin(request: Request) -> str: host = request.headers.get("x-forwarded-host") or request.headers.get("host") or "alphacovenantholdings.com" return f"https://{host.split(',')[0].strip()}" @router.get("/api/cite/{fid}") async def cite(fid: str, request: Request, source: str, subject: str, field: str, format: str = "html"): if figure_id(source, subject, field) != fid: raise HTTPException(status_code=404, detail="Figure id does not match source/subject/field.") found = await _lookup(source, subject, field) if not found: raise HTTPException(status_code=404, detail="No published figure found for that source/subject/field.") value, url, pulled = found r = await receipt(source, subject, field, value, url, pulled, _origin(request)) if format == "json": return r h = r["accuracy_history"] rows = [("Figure", f"{e(field)} for {e(subject)}"), ("Published value", f"{e(json.dumps(value, default=str))}"), ("Source", f'{e(source)}'), ("Our copy pulled", e(pulled or "not stated")), ("SHA-256 of our copy", f"{r['value_sha256']}"), ("Accuracy-check history", e(h["sentence"])), ("Last check", e(f"{h['last_check']['at'][:16].replace('T', ' ')} UTC → {h['last_check']['result']}") if h["last_check"] else "—"), ("Corrections tickets on this figure", f"{h['tickets_opened']} opened · {h['tickets_resolved']} resolved"), ("How to cite", e(r["how_to_cite"])), ("Machine-readable", f'JSON · all daily checks · checker code')] body = "".join(f"{e(k)}{v}" for k, v in rows) return HTMLResponse(f"""Citable figure {e(fid)} — Alpha Covenant Holdings

Citable figure {e(fid)}

A permanent receipt for one number we publish: where it came from, when we pulled it, the hash of our copy, and how often the daily accuracy check has found it faithful. No script required.

{body}

Receipts are generated live; the history grows every day the figure is sampled. This is our own check against the source, not an independent audit.

""") @router.get("/api/public/source-moved") async def source_moved(days: int = 30): """What the government itself revised: checks where the source's current value differs from our copy while our copy was still inside its refresh window.""" since = (datetime.now(timezone.utc) - __import__("datetime").timedelta(days=days)).isoformat() runs = await db.accuracy_runs.find({"at": {"$gte": since}}, {"_id": 0, "at": 1, "checks": 1}).sort("at", -1).to_list(200) items = [] for r in runs: for c in r["checks"]: if c["result"] == "source_moved": items.append({"observed_at": r["at"], "source": c["source"], "subject": c["subject"], "field": c["field"], "was": c.get("ours"), "now": c.get("source_now"), "source_url": c.get("source_url"), "figure_id": figure_id(c["source"], c["subject"], c["field"])}) return {"window_days": days, "count": len(items), "items": items, "meaning": "The agency's published number changed after we copied it, within our refresh window. This is the source moving, not our error; the copy is re-pulled on the next refresh.", "generated_at": datetime.now(timezone.utc).isoformat()}