fix: KI-Analyse deckt standardmäßig ALLE Inhalte ab (kein Limit-Risiko)
Das per-Scan-Limit (max_pages/images_per_scan) war ein Sicherheitsrisiko: Inhalte jenseits des Fensters blieben über viele Scans ungeprüft. Eine KI-Bildanalyse ist aber nur sinnvoll, wenn ALLE Bilder geprüft werden. Neu, sauber getrennt: - Geänderte/neue/geflaggte Inhalte werden IMMER sofort geprüft (Echtzeit- Schutz), ungeachtet jeder Drossel — auch wenn das Limit klein ist. - Die Limits drosseln NUR den historischen Altbestand und sind per Default 0 = unbegrenzt → der erste Scan deckt den kompletten Bestand ab. Dank Hash-Cache eine einmalige Ausgabe; Folge-Scans prüfen nur noch Neues. - Positiver Wert bleibt als optionale Drossel nur für sehr große Sites. Tests: 257 grün (+2: geänderte Seite trotz Drossel=1 geprüft; image-Bestand backlog=0 deckt alle Bilder in einem Scan ab). Default-Werte 20/15 → 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
6c7e69e635
commit
369a3b8774
5 changed files with 83 additions and 31 deletions
|
|
@ -230,6 +230,22 @@ class TestImages:
|
|||
if e.get("kind") == "image"}
|
||||
assert len(analysed) == 5 # nach 3 Scans sind alle 5 Bilder abgedeckt
|
||||
|
||||
def test_image_backlog_unlimited_covers_all_in_one_scan(self, tmp_path, monkeypatch):
|
||||
"""max_images_per_scan=0 → voller Bildbestand in EINEM Scan (Default)."""
|
||||
monkeypatch.setenv("OPENROUTER_API_KEY", "test")
|
||||
bm = BaselineManager(tmp_path)
|
||||
cfg = self._cfg_img()
|
||||
cfg["ai_analysis"]["image"]["max_images_per_scan"] = 0 # unbegrenzt
|
||||
imgs = [{"url": f"https://x.de/img{i}.jpg", "class": "internal"} for i in range(7)]
|
||||
hashes = {f"https://x.de/img{i}.jpg": {"sha256": f"h{i}", "size": 1, "error": None}
|
||||
for i in range(7)}
|
||||
with patch("scanner.ai_analyzer.fetch_asset_hashes", return_value=hashes), \
|
||||
patch("scanner.ai_analyzer._openrouter_chat", return_value=_verdict()):
|
||||
run_ai_analysis(cfg, bm, _snap("kurz", img=imgs), {})
|
||||
imgcount = sum(1 for e in bm.load_ai_ledger()["entries"].values()
|
||||
if e.get("kind") == "image")
|
||||
assert imgcount == 7
|
||||
|
||||
def test_image_cache_hit_second_scan(self, tmp_path, monkeypatch):
|
||||
monkeypatch.setenv("OPENROUTER_API_KEY", "test")
|
||||
bm = BaselineManager(tmp_path)
|
||||
|
|
@ -421,6 +437,21 @@ class TestParallel:
|
|||
assert len(res["findings"]) == 2 # aber Fund für beide URLs
|
||||
assert {f["url"] for f in res["findings"]} == {"https://x.de/a", "https://x.de/b"}
|
||||
|
||||
def test_changed_page_always_analyzed_despite_backlog_limit(self, tmp_path, monkeypatch):
|
||||
"""Geänderte Seiten werden IMMER geprüft — die Bestands-Drossel gilt nicht für sie."""
|
||||
monkeypatch.setenv("OPENROUTER_API_KEY", "test")
|
||||
bm = BaselineManager(tmp_path)
|
||||
cfg = _cfg()
|
||||
cfg["ai_analysis"]["text"]["max_pages_per_scan"] = 1 # strenge Bestands-Drossel
|
||||
pages = {f"https://x.de/p{i}": {"url": f"https://x.de/p{i}", "status": 200,
|
||||
"text": _LONG + str(i), "links": {"img": []}}
|
||||
for i in range(5)}
|
||||
diff = {"new_internal_urls": ["https://x.de/p3"], "page_diffs": []}
|
||||
with patch("scanner.ai_analyzer._openrouter_chat", return_value=_verdict()):
|
||||
run_ai_analysis(cfg, bm, {"pages": pages}, diff)
|
||||
urls = {e["url"] for e in bm.load_ai_ledger()["entries"].values()}
|
||||
assert "https://x.de/p3" in urls # geänderte Seite trotz Drossel=1 geprüft
|
||||
|
||||
def test_findings_sorted_deterministically(self, tmp_path, monkeypatch):
|
||||
monkeypatch.setenv("OPENROUTER_API_KEY", "test")
|
||||
bm = BaselineManager(tmp_path)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue