Commit graph

98 Commits

Autor SHA1 Nachricht Datum
claude-dev
a27fe44b0b Revert "feat(sources): X-Account-Verwaltung im Verwaltungsportal"
This reverts commit bd476edb13.
2026-05-22 11:12:28 +00:00
6c623a8ae5 Promote develop → main (2026-05-22 11:09 UTC) 2026-05-22 13:09:25 +02:00
240222cb2a Release-Notes: X-Konten direkt im Verwaltungsportal verwalten 2026-05-22 13:09:23 +02:00
claude-dev
bd476edb13 feat(sources): X-Account-Verwaltung im Verwaltungsportal
Neuer Sub-Tab "X-Accounts" unter Quellen: die als Recherchequelle
eingebundenen X-Accounts anzeigen, hinzufuegen, bearbeiten und entfernen.
Schreibt source_type=x_account in die geteilte sources-Tabelle, von wo
der Monitor sie pro Lage nutzt.

- x_account im source_type-Pattern von GlobalSourceCreate/Update
- primary_language in Create/Update plus INSERT (Keyword-Matching)
- x_account-Typ und x-Kategorie in source_meta.py
- Sub-Tab, Tabelle und Modal in dashboard.html, Logik in sources.js

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 11:06:07 +00:00
ed38d68db7 Promote develop → main (2026-05-22 09:37 UTC) 2026-05-22 11:37:54 +02:00
c7d6d2eedf Release-Notes: Neue Übersetzungsfunktion im Dashboard 2026-05-22 11:37:47 +02:00
031bd9e114 feat(translation): manueller Übersetzungs-Button im Dashboard
Fremdsprachige Artikel ohne deutsche Fassung lassen sich jetzt manuell
über das Verwaltungs-Dashboard übersetzen. Hintergrund: die automatische
Übersetzung im Monitor wurde deaktiviert (TRANSLATOR_ENABLED=false),
nachdem ein sehr großer Lauf den Refresh-Worker blockiert hatte.

- translation_agent.py: Verwaltungs-Adaption des Monitor-Translators
  (Haiku-Batches), Imports auf shared.agents.claude_client umgestellt
- routers/translation.py: Endpoints /api/translation/status, /run und
  /cancel. Der Lauf läuft als entkoppelter Hintergrund-Task, blockiert
  keinen Request und ist jederzeit abbrechbar
- Dashboard-Karte mit Fortschrittsbalken, Aufwandsschätzung vorab und
  Abbrechen-Button
- test_imports.py: neuen Router in den Smoke-Test aufgenommen

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 10:07:37 +02:00
c316c67294 Kategorie stimmungsbild (#9) 2026-05-22 00:29:02 +02:00
430641b128 feat(sources): neue Kategorie 'stimmungsbild' fuer Forum-Quellen
Single Source of Truth (source_meta.SOURCE_CATEGORIES) um den Eintrag
"Forum / Stimmungsbild" erweitert. Wird vom Frontend ueber /api/sources/meta
geladen und in den Filter-Dropdowns angezeigt.

Hintergrund: jp_demo nutzt 5ch (Phase 2), Hatena Bookmark und Note Trending
als anonyme Foren-Quellen fuer eine eigene Stimmungs-Kachel im Monitor.
Diese Quellen bekommen in der DB category='stimmungsbild' + media_type='forum',
sodass sie aus dem Faktencheck rausfallen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 00:28:04 +02:00
7c558b7cb4 Promote develop → main (2026-05-21 15:49 UTC) 2026-05-21 17:49:35 +02:00
Claude Code
c62be998d5 fix(config): CLAUDE_PATH-Default auf /usr/local/bin/claude
Bisheriger Default /home/claude-dev/.claude/local/claude existiert auf dem
Live-Server nicht. Folge: jeder call_claude im verwaltungsportal stirbt mit
FileNotFoundError [Errno 2]. Konkret betroffen: bulk_classify (alle Quellen-
Klassifizierungen schlugen still fehl bzw. brachen nach der ersten Quelle ab).

Live wurde uebergangsweise per CLAUDE_PATH-Env in /home/claude-dev/AegisSight
-Monitor-Verwaltung/.env ueberschrieben. Dieser Commit zieht den Fix in den
Code, damit der Default auch ohne .env-Override funktioniert (bzw. die .env-
Zeile spaeter wieder entfernt werden kann).

Monitor-config.py:30 hat einen abweichenden Default (/usr/bin/claude) —
nicht in diesem Commit angefasst, da Monitor heute funktioniert; getrennt
nachhalten falls auch dort Drift auftritt.
2026-05-20 19:53:03 +00:00
5d1d72bf3d Promote develop → main (2026-05-17 19:19 UTC) 2026-05-17 21:19:44 +02:00
d0b71d82e4 Release-Notes: 83 neue Quellen für Militär, Polizei-Technik & Waffen 2026-05-17 21:19:42 +02:00
claude-dev
c64675b266 feat(scripts): Bulk-Seed fuer 83 Militaer-, Polizei-Technik und Waffen-Quellen
Neues idempotentes Skript scripts/seed_military_sources.{json,py} legt 85
internationale Defense-Quellen an (RSS/Web/Telegram), kategorisiert mit
Topic-Tags im notes-Feld: [militaertechnik], [waffen-international],
[polizei-technik]. Sprachen EN/DE/FR/RU/FA/PL, country_code manuell gesetzt.

Erstlauf auf Staging-DB: 83 neu (IDs 384-466), 2 Duplikate (rybar,
osintdefender bereits vorhanden). URL-Check verhindert Duplikate, das
gleiche Skript laeuft ohne Aenderung gegen Live-DB:

  venv/bin/python scripts/seed_military_sources.py \
    --db /home/claude-dev/osint-data/osint.db

Sektionen: 31 internationale Equipment-Fachredaktionen (Janes, TWZ, Defense
News, Naval News, Army Recognition, Aviation Week ...), 8 deutsche
(ESuT, Soldat & Technik, hartpunkt, Augen geradeaus ...), 5 franzoesische
(Opex360, Mer et Marine ...), 5 russische (Topwar, TASS, RIA, bmpd, Zvezda),
4 ukrainisch/polnische (Defense Express, Militarnyi, Defence24), 2
israelische, 3 iranische, 3 chinesisch/asiatische, 8 OSINT-Tracker (ORYX,
WarSpotting, CIT, 5 Telegram), 5 Polizei-Technik (Behoerden-Spiegel, pvt,
Police Magazine ...) und 11 Waffen-Spezialisten (Small Arms Survey, SIPRI,
Conflict Armament Research, ARES, Calibre Obscura, ICRC ...).

Plan: ~/.claude/plans/gleaming-inventing-fern.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 11:18:07 +00:00
1d9ce20b68 Promote develop → main (2026-05-17 00:40 UTC) 2026-05-17 02:40:40 +02:00
claude-dev
9843ff0015 fix(pdf-upload): closeModal-Aufrufe ohne Quotes -> Abbrechen ging nicht
Die Anfuehrungszeichen waren beim Einfuegen verloren gegangen
(onclick="closeModal(modalPdfUpload)" statt closeModal())
-> Browser warf ReferenceError und der Klick blieb wirkungslos.
Mit &#39; (HTML-Entity-Apostroph) im Attribut-Wert eindeutig.
2026-05-16 23:43:41 +00:00
claude-dev
27afce7c9e feat(sources): PDF-Upload als neuer Quellentyp pdf_document
- POST /api/sources/global/upload-pdf: multipart File-Upload,
  50 MB Limit, SHA256-Dedup, speichert PDF unter <dirname(DB)>/pdfs/{sha}.pdf,
  legt Source mit processed_at=NULL an (Monitor verarbeitet asynchron)
- pattern in GlobalSourceUpdate um pdf_document erweitert (2x)
- dashboard.html: Button + Modal im Grundquellen-Sub-Tab
- sources.js: openPdfUploadModal + setupPdfUploadForm + FormData-Submit
- app.js: API.upload(path, formData) Helper fuer multipart
- requirements.txt: pypdf (Validierung optional)
2026-05-16 23:21:56 +00:00
claude-dev
d3e5fa7079 feat(orgs): Pipeline-Sprache als Org-Setting im Verwaltungsportal
- OrgCreate / OrgUpdate / OrgResponse um output_language (de | en).
- routers/organizations.py persistiert die Sprache nach create/update
  via shared.services.org_settings.set_org_setting.
- _enrich_org liest output_language aus organization_settings (Default de).
- Frontend: Dropdown im Modal Neue Organisation und im Org-Edit-Formular,
  Auto-Befuellung aus org.output_language. Cache-Buster auf app.js gebumpt.

Phase 7 von 8 (eng_demo / Org-Sprache).
2026-05-13 21:18:07 +00:00
claude-dev
521633bde9 feat(shared): org_settings Helper (Kopie aus Monitor)
Helper aus AegisSight-Monitor/src/services/org_settings.py uebernommen.
Wird in Phase 7 vom Verwaltungs-Org-Router verwendet, um output_language
beim Org-Anlegen/Bearbeiten zu setzen.

Phase 1 von 8 (eng_demo / Org-Sprache).
2026-05-13 20:46:10 +00:00
claude-dev
015255237a feat(klassifikation): Quellen-Klassifikation aus Monitor in Verwaltung verschoben
Service-Module (source_classifier, external_reputation) liegen jetzt in shared/services/, Endpoints unter /api/sources/classification/* sind hier statt im Monitor:
- classification/{stats,queue,bulk-classify,bulk-approve}
- {id}/classification/{approve,reject,reclassify}
- external-reputation/sync

modalSource erweitert um Klassifikations-Section (Politik, Medientyp, Reliability, state-affiliated, Land, 12 Alignment-Chips). Neuer Sub-Tab Klassifikation mit Review-Queue, Pending-Counter, Bulk-Actions. Auth via get_current_admin, Audit-Logging.

Begleit-Refactor: Monitor verliert die Klassifikations-UI/-Endpoints separat.
2026-05-09 21:27:55 +00:00
b56b7eeda2 Merge pull request 'Promote: sync Strategie/Karteileichen-Reihenfolge' (#5) from develop into main 2026-05-09 17:44:30 +02:00
Claude
2f7d967ce2 sync(shared): Reihenfolge Strategie-Eskalation/Karteileichen aus Monitor 5f053a3 2026-05-09 15:43:44 +00:00
1d9751ef1a Promote develop -> main 2026-05-09 17:27:03 +02:00
Claude
5e08d06784 feat(quellen-health): Strategie-Eskalation, Loesung-suchen bei Warnings, Trend-Delta
Drei zusammenhaengende Verbesserungen am Quellen-Health-Bereich:

1. shared/services/source_suggester.py:
   - sync mit Monitor commit 49c5572.
   - Neue Funktion generate_strategy_escalation_suggestions: erzeugt
     deactivate-Vorschlaege fuer Quellen mit fetch_strategy=googlebot|
     paywall, deren Reachability-Check trotzdem error meldet.

2. source-health.js: Loesung-suchen-Button erweitert.
   Bisher nur bei status=error AND check_type=reachability. Jetzt auch
   bei status=warning AND check_type=feed_validity (z.B. "Feed
   erreichbar aber leer"). Backend-Endpoint /api/sources/health/
   search-fix wird in beiden Faellen aufgerufen, Claude sucht eine
   bessere URL fuer die Quelle.

3. source-health.js: Trend-Delta im Counter.
   Liest healthHistoryCache[1] (vorletzter Run) und vergleicht mit
   aktuellen errors/warnings/ok. Zeigt z.B. "3 Fehler (+2)" rot oder
   "143 Warnungen (-15)" gruen. Bei steigenden ok-Counts ist Plus
   gruen, bei steigenden Fehlern ist Plus rot. Wenn der vorletzte
   Run nicht verfuegbar (Initial-Lauf): kein Delta.

Cache-Buster source-health.js auf 20260509l gebumpt.
2026-05-09 15:26:24 +00:00
6a02e06887 Promote develop -> main 2026-05-09 17:21:07 +02:00
Claude
719c67df3e sync(shared): Karteileichen-Heuristik aus Monitor-Repo uebernommen
Spiegelung von AegisSight-Monitor commit d973dc7. Identische Datei
(Pre-Commit-Hook prueft Drift gegen Monitor-Master = 0).

Neue Funktion generate_stale_deactivation_suggestions wird beim
manuellen Health-Check-Run ueber das Verwaltungsportal-UI aufgerufen
(/api/sources/health/run-stream am Ende). Karteileichen-Quellen
landen damit im Vorschlaege-Tab als deactivate_source-Vorschlaege
und koennen per Klick angenommen werden.
2026-05-09 15:09:45 +00:00
42a0647cd7 Promote develop → main (2026-05-09 15:05 UTC) 2026-05-09 17:05:22 +02:00
Claude (cleanup)
38a13c0b64 ux(quellen-health): Run-Verlauf-Tabelle kompakter
- Total-Spalte raus (= errors+warnings+ok, redundant).
- Spalten-Widths explizit per colgroup gesetzt: 200/160/110/130/110px,
  damit die Werte nicht in einer leeren Flaeche rechts kleben.
- Header-Bezeichnungen + Werte fuer Counter-Spalten zentriert
  (statt rechtsbuendig auf gleichmaessig verteilten Spalten).
- Run-ID gekuerzt auf 12 Zeichen, kleinerer font-size, voller
  Wert im title-Tooltip.
- Spaltenbeschriftung von "Zeitpunkt (Run-Ende)" -> "Zeitpunkt"
  (Klammer-Erklaerung war Footnote-Material).

Cache-Buster source-health.js auf 20260509k gebumpt.
2026-05-09 14:44:20 +00:00
Claude (cleanup)
3a838809c6 fix(navigation): #healthSubTabs aus globalem Top-Tab-Handler ausnehmen
Der globale setupNavTabs in app.js fing nav-tab-Clicks aus ALLEN
nav-tabs ab, ausser #orgDetailTabs und #sourceSubTabs. Das neue
#healthSubTabs (aus dem letzten Commit) war nicht in der :not()-
Liste und triggerte daher den Top-Level-Handler, der getElementById("sec-suggestions")
suchte und null bekam -> Crash beim classList.add("active").

Fix: :not(#healthSubTabs) ergaenzt an allen drei Stellen
(setupNavTabs, setupNavTabs Click-Handler, openSection-Helfer in Z. 408).
Cache-Buster fuer app.js gebumpt 20260509d -> 20260509j.
2026-05-09 14:38:36 +00:00
Claude (cleanup)
f1680c9f4f ux(quellen-health): Sub-Tabs Vorschläge / Health-Status / Verlauf, Lucide-Icons statt Emojis
Splittet die Quellen-Health-Section in drei eigene Sub-Tabs auf, damit
der User je nach Aufgabe nur den relevanten Bereich sieht und nicht
durch die ganze Seite scrollen muss.

dashboard.html:
- Innerhalb von <div id=sub-source-health>: neue nav-tabs healthSubTabs
  mit drei Buttons (Vorschläge / Health-Status / Verlauf).
- Drei Pane-Container ht-suggestions / ht-checks / ht-verlauf,
  jeweils per inline-style display kontrolliert.

source-health.js:
- setupHealthSubTabs(): Click-Handler fuer den Tab-Wechsel
  (toggle .active auf den Buttons + display none/block auf den Panes).
- renderHealthDashboard splittet jetzt in drei innerHTML-Calls,
  einen pro Pane:
    paneSuggestions <- Vorschlaege offen
    paneChecks      <- Counter + Filter + Tabelle + Mehr-laden
    paneVerlauf     <- erledigte Vorschlaege + Run-Verlauf
- Tab-Label "Vorschlaege" wird mit Counter angereichert (z.B.
  "Vorschlaege (24 offen)"), wenn welche offen sind.
- LUCIDE_ICONS-Konstante mit Inline-SVG fuer check, x, search,
  refresh. Emojis und HTML-Entities (&check; &times; ) ersetzt.
  Inline-SVG statt CDN-Library, damit keine externe Abhaengigkeit.

Cache-Buster fuer source-health.js auf 20260509i gebumpt.
2026-05-09 14:26:10 +00:00
Claude (cleanup)
5191962ce0 ux(quellen-health): Verschlankung - Beschreibung gekürzt, Verlauf eingeklappt, schmalere Health-Tabelle, Icon-Buttons
Vier UX-Hebel zusammengelegt, alle reines Frontend:

1. Vorschlaege-Tabelle: Beschreibung als Einzeiler mit Ellipsis;
   voller Text im title-Tooltip. Spart bei 24 offenen Vorschlaegen
   ~25 Bildschirmhoehen.

2. Verlauf-Card: standardmaessig eingeklappt via <details>-Element.
   Header zeigt nur "Verlauf (N erledigte Vorschlaege - klick zum
   Aufklappen)". Klick expandiert die Tabelle.

3. Health-Tabelle: Spalten Domain und Sprache aus der Tabelle raus,
   beide als Tooltip auf dem Quellen-Namen. Tabelle hat statt 8
   Spalten nur noch 6, ist schmaler und besser lesbar.

4. Aktionen-Spalten: Text-Buttons ("Annehmen", "Ablehnen", "Lösung
   suchen") durch kompakte Icon-Buttons ersetzt (✓ ✗ 🔍).
   Funktion identisch, Tooltip via title-Attribut.

Cache-Buster fuer source-health.js auf 20260509h gebumpt.
2026-05-09 14:18:04 +00:00
Claude (cleanup)
b6926df84d cleanup(sources): redundanten /health/run Endpoint entfernen
Frontend ruft ausschliesslich /health/run-stream auf. Der Legacy-Endpoint
/health/run war ein simples synchrones Pendant ohne Fortschrittsanzeige
und wurde nirgends mehr aufgerufen (verifiziert via grep -r im Repo).

Schritt 2 der Quellen-Health-Aufraeumung. Reine Code-Saeuberung,
keine UX- oder Backend-Verhaltensaenderung.
2026-05-09 14:03:51 +00:00
2594b0339f Promote develop -> main 2026-05-09 15:47:23 +02:00
claude-dev
e8bb2495ee ux(quellen-health): Default "Nur Probleme", Counter feiner gegliedert, Filter-Hint bei Pagination
Schritt 1 der Quellen-Health-Aufraeumung. Drei UX-Verbesserungen, kein Daten-Eingriff:

1. Default-Filter "Nur Probleme" (errors + warnings, ohne OK).
   - Neuer Status-Filter-Wert "issues" als virtuelles Frontend-Konstrukt.
   - applyHealthFilter behandelt "issues" als status != ok.
   - Default in healthFilters ist jetzt "issues". User sieht beim
     Tab-Klick sofort die kritischen 146 Eintraege statt der 281
     gruenen OK-Zeilen.

2. Counter aufgegliedert nach check_type.
   - Backend (/api/sources/health): zusaetzliches Feld "breakdown"
     mit der GROUP-BY (check_type, status) Aggregation.
   - Frontend rendert pro Status-Zeile die feine Aufschluesselung,
     z.B. "143 Warnungen (112 Aktualität, 27 Feed-Validität, 3 Duplikat,
     1 Erreichbarkeit)".
   - Hilft dem Admin, sofort zu sehen wo das Problem liegt.

3. Filter-Hint bei Pagination + leeren Treffern.
   - Wenn der aktuelle Filter ueber die geladenen 100 Items keinen
     Treffer findet UND has_more=true, zeigt das Frontend einen
     Hinweis-Link "Alle X Health-Checks laden und Filter erneut
     anwenden".
   - Loest das Edge-Problem, dass z.B. Filter "Nur OK" auf den
     Default-100 (errors first) leer schien.

Cache-Buster fuer source-health.js auf 20260509g gebumpt.
2026-05-09 13:24:44 +00:00
claude-dev
50749323f8 fix(quellen-health): fehlende Sub-Section + Render-Container
Tab-Button "Quellen-Health" verlinkte auf eine Sub-Section, die
es im DOM gar nicht gab:

- <button data-subtab="source-health"> existierte bereits
- <div id="sub-source-health"> fehlte komplett
- <div id="healthContent"> (Render-Anker für source-health.js) fehlte
  ebenfalls

Folge:
1. sources.js Click-Handler crashte mit
   "Cannot read properties of null (reading classList)" beim Versuch,
   die Sub-Section auf .active zu setzen
2. loadHealthData() lief zwar (über separaten Listener in
   source-health.js) und der Backend-Call ging durch, aber
   renderHealthDashboard fand kein #healthContent und brach still ab
   (if (!container) return). Nutzer sah niemals Inhalt.

Fix: Sub-Section <div id="sub-source-health"><div id="healthContent">
zwischen sub-tenant-sources und der Audit-Section eingefügt. Außerdem
das ohnehin fehlende </div> für sec-sources sauber geschlossen.

Damit löst sich das gefühlte "Quellen Health lädt minutenlang":
beim Klick wird der Tab korrekt aktiviert, der Render landet in
#healthContent und ist dank der Pagination + Cache aus den letzten
zwei Commits sofort sichtbar.
2026-05-09 13:15:16 +00:00
claude-dev
657683d491 perf(sources): Quellen-Health Pagination (default 100, plus mehr/alle laden)
Echter Bottleneck war der DOM-Render von 519 Tabellen-Zeilen, nicht
das Backend (45ms). Backend-Slim und Cache aus dem letzten Commit
haben Bandbreite und wiederholte Klicks beschleunigt, aber der erste
Klick blieb langsam, weil weiterhin alle 519 Items in einem
innerHTML-Schub gerendert wurden.

Lösung: Server-Side-Pagination.

Backend (/api/sources/health):
- Neue Query-Param: limit (default 100, max 5000), offset (default 0)
- Counters errors/warnings/ok/total_checks aus separater GROUP-BY-
  Aggregat-Query über den GESAMTEN Bestand, nicht über die Page.
- Neues Feld all_orgs in der Antwort: alle Tenants mit Health-Checks,
  damit das Filter-Dropdown auch im Pagination-Modus die volle
  Org-Liste hat.
- Neue Felder limit, offset, has_more.

Frontend (source-health.js):
- healthLoadLimit (default 100), wird durch loadMoreHealth() um 200
  hochgesetzt oder durch loadAllHealth() auf alles gesetzt.
- Cache-Key beinhaltet jetzt auch das aktuelle Limit, damit beim
  Mehr-laden nicht aus altem Cache bedient wird.
- Org-Liste kommt aus healthData.all_orgs statt aus den geladenen
  Page-Items, sonst wäre sie nach Pagination unvollständig.
- Footer mit zwei Buttons ("+200 laden", "Alle N weiteren laden")
  unter der Tabelle, nur sichtbar bei has_more=true.
- Counter-Anzeige: "X / Y angezeigt (von Z insgesamt)".

Cache-Buster für source-health.js auf 20260509f gebumpt.
2026-05-09 12:54:35 +00:00
claude-dev
f6af21e6cb perf(sources): Quellen-Health Tab schneller (Payload-Slim + 60s-Cache)
Tab "Quellen Health" lädt deutlich schneller:

1. /api/sources/health: SELECT reduziert auf nur die im Frontend wirklich
   gerenderten Felder. Weg sind: h.id, s.url, s.source_type, s.category,
   s.bias, h.details, h.checked_at. Response-Größe sinkt damit von ~198 KB
   auf grob die Hälfte (bei 519 Health-Checks) ohne UI-Verlust.

2. source-health.js: 60-Sekunden In-Memory-Cache fürs loadHealthData.
   Tab hin und her klicken ist damit instant statt jedes Mal voller
   Reload + Render der 519 Tabellen-Zeilen.
   Bei Mutationen (Vorschlag annehmen/ablehnen, run-stream beendet,
   search-fix) wird mit loadHealthData(true) der Cache umgangen,
   damit frische Daten gezeigt werden.

3. dashboard.html: Cache-Buster für source-health.js auf 20260509e gebumpt.
2026-05-09 12:33:30 +00:00
claude-dev
1b25d8ba12 sync: paywall-Strategie ohne removepaywall fuer Feed-URL 2026-05-09 05:02:22 +00:00
claude-dev
d8f4e0d303 sync: removepaywall.com Korrektur aus Monitor (singular) 2026-05-09 05:00:14 +00:00
claude-dev
7f729443cb Phase 18 (Verwaltung): fetch_strategy in CRUD + Edit-Modal
- migrations/2026-05-09e_fetch_strategy.py NEU: ALTER TABLE sources ADD COLUMN
  fetch_strategy. Pre-flagging fuer FT/WSJ/NZZ etc. (paywall) und Rheinische
  Post/Verfassungsschutz (googlebot).
- shared/services/source_health.py: gesynct vom Monitor (Phase-18-Code mit
  Retry-Logik + Strategien default/googlebot/paywall/skip).
- routers/sources.py: GlobalSourceCreate/Update um fetch_strategy
  (Pattern-Validation), SOURCE_UPDATE_COLUMNS + INSERT erweitert.
- dashboard.html: Edit-Modal hat jetzt Dropdown sourceFetchStrategy.
- sources.js: laedt + sendet fetch_strategy mit.

Cache-Buster 20260509c -> 20260509d.
2026-05-09 04:57:01 +00:00
claude-dev
bff934d673 Phase 17: Health-Tab Filter + Org-Spalte + History-View + URL-Schema-Fix
Backend:
- shared/services/source_health.py: URL ohne https://-Prefix wird normalisiert
  bevor httpx.get() aufgerufen wird (Bug-Fix: t.me/kanal liess httpx mit
  ValueError crashen, Synchron mit Monitor-Fix 1ee6c4d).
- routers/sources.py /health: Query erweitert um tenant_id, category,
  language, bias, org_name (LEFT JOIN organizations) - Frontend kann jetzt
  pro Issue Tenant-Info anzeigen.
- routers/sources.py /health/history NEU: letzte N Runs aus
  source_health_history aggregiert (run_id, archived_at, errors/warnings/ok).

Frontend (source-health.js):
- healthFilters State: status / check_type / org.
- applyHealthFilter() reduziert die Anzeige.
- Filter-Bar mit 3 Dropdowns + Counter "X / Y Ergebnisse".
- Tabelle erweitert: Org-Spalte ("global" oder Org-Name), Sprache-Spalte.
- History-View neu: letzte 10 Runs als Tabelle (Zeitpunkt, Run-ID, Counts).

Cache-Buster auf 20260509c gebumpt.
2026-05-09 04:47:05 +00:00
claude-dev
07a426561c sync_shared: LOCKED_FILES-Eintrag entfernt nach Phase 16
Nach Phase 16 (Monitor-source_health.py auf Phase-2-Stand) sind alle
4 shared/-Dateien wieder identisch zwischen Monitor und Verwaltung.
Der Lock auf source_health.py war nur fuer den Zeitraum noetig, in dem
die Verwaltung die History-Logik schon hatte und der Monitor noch nicht.
2026-05-09 04:43:20 +00:00
claude-dev
b5bb27785a cache-buster: 20260509 -> 20260509b (Phase 15 sichtbar machen) 2026-05-09 04:35:33 +00:00
claude-dev
c86b2a0056 Phase 15: language + bias als Spalten, Filter, Edit-Form
Bisher waren die DB-Felder sources.language und sources.bias zwar gepflegt
(254/275 Quellen mit bias, 254 mit language), aber in der Verwaltung nicht
sichtbar. Der Admin konnte nicht filtern oder editieren.

Backend (routers/sources.py)
- GlobalSourceCreate + GlobalSourceUpdate Pydantic-Modelle: language +
  bias als Optional[str] erweitert (max 100 / 500 Zeichen).
- SOURCE_UPDATE_COLUMNS: language + bias hinzu.
- INSERT in create_global_source: schreibt language + bias mit.
- Neuer Endpoint GET /api/sources/global/languages: distinct language-Werte
  fuer Frontend-Filter-Dropdown.

Frontend HTML (dashboard.html)
- Grundquellen-Filter-Bar: Sprachen-Dropdown ergaenzt.
- Grundquellen-Tabellenkopf: 2 neue Spalten Sprache (sortable) + Bias.
- modalSource: 2 neue Felder language (mit datalist Vorschlaegen) + bias.
- Kundenquellen-Filter-Bar: Sprachen-Dropdown.
- Kundenquellen-Tabellenkopf: Sprache (sortable) + Bias.

Frontend JS (sources.js)
- loadGlobalSources lädt /languages parallel zu /global + /global/stats,
  populiert beide Sprache-Dropdowns + datalist im Edit-Modal.
- renderGlobalSources: cols 11 -> 13, language+bias-Zellen
  (Bias mit Tooltip fuer Lang-Texte).
- filterGlobalSources: Sprache-Filter, Bias in Suche.
- editGlobalSource: language + bias laden.
- Form-Submit: language + bias mitgesendet.
- renderTenantSources: cols 8 -> 10, language+bias-Zellen.
- tenantFilters um language erweitert, applyTenantFilterAndSort prueft.

Cache-Buster ?v=20260509 (heute) bleibt - Tag wechselt erst morgen.
2026-05-09 04:35:08 +00:00
claude-dev
ff83f64aa6 Phase 14a: Integration-Tests (FastAPI TestClient, ohne DB)
tests/test_api_smoke.py:
  - 43 parametrisierte Auth-Coverage-Tests: jeder geschuetzte Endpoint
    muss ohne Authorization-Header 401 oder 403 liefern (nicht 200, nicht 500).
    Verhindert, dass jemand versehentlich einen Endpoint ohne
    get_current_admin schreibt.
  - 2 Tests fuer oeffentliche Auth-Endpoints (/magic-link, /verify):
    pruefen nur, dass NICHT 401/403 zurueckkommt.
  - 2 Static-Route-Tests (/, /dashboard) muessen 200 liefern.
  - TestClient(raise_server_exceptions=False) damit DB-Probleme nicht zu
    Test-Aborts werden.

tests/test_api_meta.py:
  - Integration-Tests fuer /api/sources/meta mit dependency_overrides
    (Mock get_current_admin). DB-frei, deshalb echte Endpoint-Logik
    vollstaendig durchgetestet.
  - 5 Tests: Schema vorhanden, Pflichtfelder, spezielle Lagen-Themen,
    alle 5 source-types.

Insgesamt: 80 Tests, 0.63s. Aufruf:
  PYTHONPATH=src ./venv/bin/python -m pytest tests/ -v

Phase 14b (echtes DB-Schema-Setup mit aiosqlite-In-Memory) folgt separat,
braucht Schema-Bootstrap - viel groesserer Aufwand fuer CRUD-Tests.
2026-05-09 04:25:39 +00:00
claude-dev
9d16aba5f9 CLAUDE.md: Cache-Buster-Regel dokumentiert (bei JS/CSS-Aenderungen ?v= bumpen) 2026-05-09 04:13:36 +00:00
claude-dev
4bebe9168a Cache-Buster ?v=20260509 an JS+CSS - Browser-Reload nach jeder JS-Aenderung erzwingen
Live-Symptom: User sah leere Audit-Tabelle obwohl Backend 22 Eintraege
lieferte. Ursache: Browser hatte alte audit.js gecached (von vor Phase 5/8b),
in der die Audit-Render-Logik anders war oder fehlte.

Aktuell ohne Cache-Buster cacht der Browser die JS aggressiv. Mit ?v=YYYYMMDD
laedt der Browser bei jedem Bump die neue Version.

Beim naechsten Frontend-Patch in dieser Verwaltung: Cache-Buster auf neues
Datum bumpen, damit alle Browser wieder neu laden.
2026-05-09 04:10:12 +00:00
claude-dev
00cd81f177 Phase 12: Test-Suite (30 pytest-Tests) + CLAUDE.md aktualisiert
tests/:
  conftest.py        - minimale Env-Vars + sys.path-Setup
  test_auth.py       - Magic-Token + JWT Round-Trip (4 Tests)
  test_audit.py      - diff() + _to_json() Helper (8 Tests)
  test_models.py     - Pydantic-Validierung (7 Tests)
  test_source_meta.py - Single Source of Truth Konsistenz (7 Tests)
  test_imports.py    - alle Backend-Module importierbar (4 Tests)

requirements-dev.txt: pytest, ftfy, pyflakes

Tests sind reine Unit-Tests (kein DB-Zugriff, kein HTTP-Server),
laufen in <0.5s, geben sofortiges Catch-Net fuer Syntax/Import-Bugs.

Aufruf: PYTHONPATH=src ./venv/bin/python -m pytest tests/ -v

CLAUDE.md erweitert um:
- Sektion Tests (Framework, Pfad, Ausfuehrung)
- Sektion Phasen-Historie (alle 12 Phasen der Aufraeum-Aktion 2026-05-09
  mit kurzer Erklaerung)
2026-05-09 03:55:30 +00:00
claude-dev
9000750df2 Phase 9: Code-Hygiene - alle pyflakes-Issues fixen
15 pyflakes-Warnings entfernt:
- src/audit.py: HTTPException (in router import statt helper, war hier ungenutzt)
- src/routers/auth.py: status (FastAPI-status ungenutzt)
- src/routers/audit.py: HTTPException (ungenutzt)
- src/routers/users.py: MAGIC_LINK_EXPIRE_MINUTES (ungenutzt)
- src/routers/sources.py: row_to_dict, _extract_domain, _detect_category,
  urlparse, status (alle ungenutzt - status.HTTP_* wird nirgendwo aufgerufen)
- src/routers/sources.py: 2x f-string ohne Placeholder (URL aktualisiert,
  Verbindung fehlgeschlagen) zu normalen Strings
- src/routers/sources.py: except httpx.ConnectError as e -> e ungenutzt, weg
- src/database.py: os ungenutzt
- src/models.py: EmailStr ungenutzt

Audit-Coverage geprueft: alle write-Endpoints in users.py rufen
_toggle_field() auf, das die log_action-Aufrufe macht. Keine Audit-Luecken.
Alle anderen Routers (organizations/licenses/dashboard/token_usage)
hatten bereits saubere Audit-Coverage.

Mojibake-Diagnose ueber alle src/*.py: 0 Treffer.
2026-05-09 03:49:53 +00:00
claude-dev
52a18fd9ec Phase 8a+8b: Pre-Commit-Hook fuer shared/-Drift + Audit-UI resource_id-Filter
Phase 8a (Hook):
- scripts/git-hooks/pre-commit: prueft bei Commits mit src/shared/-Aenderungen
  den Drift-Stand via sync_shared.py --check und gibt eine Warnung aus
  (blockiert NICHT - User entscheidet selbst, ob er zurueck will).
- scripts/install-hooks.sh: kopiert Hooks aus scripts/git-hooks/ nach
  .git/hooks/ (idempotent, ueberspringt user-eigene Hooks).

Phase 8b (Audit-UI):
- dashboard.html: Resource-ID Eingabefeld neben den anderen Audit-Filtern.
- audit.js: Filter-Listen erweitern, params um resource_id ergaenzt
  (Backend hatte den Filter seit Phase 5 schon).
- Damit ist die Audit-Spur einer einzelnen Ressource auch im Audit-Log-Tab
  filterbar (vorher nur per Direkt-URL bzw. per Quellen-Audit-Modal).
2026-05-09 03:40:00 +00:00