Sources: "Check source" read-only spot-check action

Per Codex — a per-row Check button that previews a LIVE source on demand,
intentionally read-only and ephemeral.

* POST /api/admin/sources/{id}/preview — admin-gated, safe-fetch + heuristic
  preview (reuses the candidate preview path), returns the result. Mutates
  NOTHING: no DB write, no poll attempt, no health/state change. 404 on missing.
* UI: per-row Check button with a Checking… state; results in an inline row
  under the source (sampled, would-pass %, recent-7d, example accept/skip
  headlines) with dismiss; inline error on failure. "Checked just now" is
  local UI state only. Heuristic v1 — model deep-check left for later.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jay
2026-06-09 15:11:08 -04:00
parent eacf91225a
commit ee00d8e89b
3 changed files with 61 additions and 0 deletions
+12
View File
@@ -933,6 +933,18 @@ def create_app() -> FastAPI:
conn.commit()
return {"ok": True, "visible": body.visible}
@app.post("/api/admin/sources/{sid}/preview")
def admin_source_preview(sid: int, request: Request) -> dict:
# Read-only spot-check of a LIVE source: safe-fetch + heuristic preview.
# Mutates nothing — no DB write, no poll attempt, no health/state change.
with get_conn() as conn:
_require_admin(conn, request)
src = conn.execute("SELECT feed_url FROM sources WHERE id = ?", (sid,)).fetchone()
if not src:
raise HTTPException(status_code=404, detail="source not found")
url = src["feed_url"]
return _preview_or_502(url) # safe fetch, no DB connection held
# --- Source candidates (supervised add-a-source pipeline) ----------------
def _candidate_dict(row) -> dict: