"""Endpoints that reported success without doing anything. Sweep findings #8, #9 and #10. All three share a shape: a write path that answers 200 while the thing the caller asked for did not happen. """ from __future__ import annotations import sqlite3 from pathlib import Path import pytest import yaml from fastapi import FastAPI from starlette.testclient import TestClient import admin from config import load_config ROOT = Path(__file__).resolve().parent.parent SCHEMA_SQL = (ROOT / "config" / "schema.sql").read_text() @pytest.fixture def client(tmp_path): """Rooted at a throwaway config dir so no write touches the real overlay.""" cfg_dir = tmp_path / "config" cfg_dir.mkdir() doc = yaml.safe_load((ROOT / "config" / "config.yaml").read_text()) (cfg_dir / "config.yaml").write_text(yaml.safe_dump(doc, sort_keys=False)) db_path = tmp_path / "t.db" conn = sqlite3.connect(db_path) conn.executescript(SCHEMA_SQL) admin.ensure_admin_tables(conn) conn.commit() conn.close() def _db(): c = sqlite3.connect(db_path) c.row_factory = sqlite3.Row return c cfg = load_config(cfg_dir / "config.yaml") app = FastAPI() app.include_router(admin.build_router(cfg, _db, str(tmp_path)), prefix="/admin") return TestClient(app), cfg_dir ALLOWLISTED = "openrouter" # --- #9: NOT a defect -- the idempotent delete is deliberate --------------- # # The sweep flagged DELETE returning 200 for an absent entry as a silent # false confirmation. It is not an oversight: test_allowlist_delete_idempotent # in test_admin_allowlist.py pins exactly that behaviour, docstring and all. # The inconsistency with profile delete and model-override delete (both 404) # is real and is recorded as an open question in the sweep plan; resolving it # is a decision, not a bug fix, so nothing here changes it. def test_deleting_an_absent_entry_is_a_deliberate_200(client): c, _ = client resp = c.delete(f"/admin/api/providers/{ALLOWLISTED}/allowlist/nope/nope") assert resp.status_code == 200, resp.text def test_deleting_a_real_entry_removes_it(client): c, _ = client c.post(f"/admin/api/providers/{ALLOWLISTED}/allowlist", json={"model_id": "vendor/m", "note": "n"}) resp = c.delete(f"/admin/api/providers/{ALLOWLISTED}/allowlist/vendor/m") assert resp.status_code == 200, resp.text ids = [e["model_id"] for e in c.get(f"/admin/api/providers/{ALLOWLISTED}/allowlist").json()] assert "vendor/m" not in ids # --- #10: re-adding could not correct a note ------------------------------- def test_re_adding_updates_the_note(client): c, _ = client c.post(f"/admin/api/providers/{ALLOWLISTED}/allowlist", json={"model_id": "vendor/m", "note": "first"}) resp = c.post(f"/admin/api/providers/{ALLOWLISTED}/allowlist", json={"model_id": "vendor/m", "note": "corrected"}) assert resp.status_code == 200, resp.text assert resp.json()["note"] == "corrected" entry = [e for e in c.get(f"/admin/api/providers/{ALLOWLISTED}/allowlist").json() if e["model_id"] == "vendor/m"][0] assert entry["note"] == "corrected" def test_re_adding_does_not_duplicate_the_row(client): c, _ = client for note in ("a", "b", "c"): c.post(f"/admin/api/providers/{ALLOWLISTED}/allowlist", json={"model_id": "vendor/m", "note": note}) rows = [e for e in c.get(f"/admin/api/providers/{ALLOWLISTED}/allowlist").json() if e["model_id"] == "vendor/m"] assert len(rows) == 1 def test_re_adding_keeps_the_original_added_at(client): """Correcting a note is not a re-admission.""" c, _ = client first = c.post(f"/admin/api/providers/{ALLOWLISTED}/allowlist", json={"model_id": "vendor/m", "note": "first"}).json() second = c.post(f"/admin/api/providers/{ALLOWLISTED}/allowlist", json={"model_id": "vendor/m", "note": "second"}).json() assert second["added_at"] == first["added_at"] # --- #8: an unusable base_url persisted ------------------------------------ def test_cloud_fallback_rejects_a_non_url(client): c, cfg_dir = client resp = c.post("/admin/api/cloud-fallback-config", json={"cloud_fallback": {"base_url": "notaurl", "model": "m", "api_key_env": "K"}}) assert resp.status_code == 422, resp.text assert "http(s)" in resp.text overlay = cfg_dir / "config.local.yaml" if overlay.exists(): assert "notaurl" not in overlay.read_text() def test_cloud_fallback_accepts_a_real_url(client): c, cfg_dir = client resp = c.post("/admin/api/cloud-fallback-config", json={"cloud_fallback": {"base_url": "https://api.example.com/v1", "model": "m", "api_key_env": "K"}}) assert resp.status_code == 200, resp.text assert "api.example.com" in (cfg_dir / "config.local.yaml").read_text() def test_cloud_primary_rejects_a_non_url(client): """The classifier card had the same gap as the fallback card.""" c, _ = client resp = c.post("/admin/api/classifier-config", json={"mode": "cloud_llm", "cloud_primary_auto": False, "cloud_primary": {"base_url": "ftp://nope", "model": "m"}}) assert resp.status_code == 422, resp.text assert "http(s)" in resp.text def test_clearing_the_fallback_still_works(client): """The None path is the documented remove signal and must stay reachable.""" c, cfg_dir = client c.post("/admin/api/cloud-fallback-config", json={"cloud_fallback": {"base_url": "https://api.example.com/v1", "model": "m", "api_key_env": "K"}}) resp = c.post("/admin/api/cloud-fallback-config", json={"cloud_fallback": None}) assert resp.status_code == 200, resp.text assert "api.example.com" not in (cfg_dir / "config.local.yaml").read_text()