16 Commits

Autor SHA1 Nachricht Datum
claude-dev
4532086e0e feat(orgs): KI-Verarbeitung organisationsweit einstellbar
Der Monitor löst den KI-Weg als Lage vor Organisation vor Servervorgabe auf
und liest dafür das Org-Setting ai_backend. Geschrieben werden konnte es
bisher nur direkt in der Datenbank, eine Oberfläche gab es nicht. Für einen
Kunden, der die DSGVO-Fassung will, ist das der praktisch wichtigste Weg,
denn der stellt einmal zentral um und nicht Lage für Lage.

Das Feld steht jetzt dort, wo die Pipeline-Sprache schon steht, also als
eigene Spalte in der Lizenztabelle der aktiven Lizenz, und zusätzlich im
Anlege-Dialog für neue Organisationen.

Drei Werte. Leer bedeutet Servervorgabe, cli den heutigen Weg über Anthropic,
bedrock die EU-Fassung über AWS Bedrock in Frankfurt mit Recherche über den
europäischen Suchindex staan.

Der Leerstring ist dabei ein gültiger Wert und keine fehlende Angabe. Der
Router prüft deshalb auf None statt auf Wahrheit, sonst ließe sich eine
gesetzte Vorgabe nie wieder auf die Servervorgabe zurücknehmen.

26 Prüfungen, ohne Datenbank und ohne Netz.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 18:31:06 +00:00
claude-dev
9bf3adbacb feat(abrechnung): Credits-Uebertrag komplett entfernt
Produktentscheidung 07/2026: ungenutzte Credits verfallen zum
Periodenende. Uebertrag-Checkbox aus allen drei Formularen
(Kontingent bearbeiten, Lizenz anlegen, Org anlegen) samt
Ausgrau-Logik raus, credits_rollover/credits_carried aus Modellen,
Endpoints (overview/current/PUT budget) und insert_license_row raus,
Anzeige inkl. Uebertrag im Org-Detail raus. Migrationsskript legt die
beiden Spalten nicht mehr an. Gegenstueck zum Monitor-Commit f8499c4,
Promote-Reihenfolge wie immer Monitor VOR Portal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 21:51:02 +00:00
claude-dev
16250cd8f5 feat(zugaenge): Telegram-Session-Status im Reiter Recherche-Zugaenge
Der Reiter X-Recherche-Konten heisst jetzt Recherche-Zugaenge und zeigt
oben eine Telegram-Karte: Session gueltig/Problem, verbunden als, Stand.
Die Daten meldet der Monitor (Commit 7dae63e) in die geteilte Tabelle
system_status, das Portal liest nur an (GET /api/x-scraper/telegram-status,
tolerant wenn Tabelle/Eintrag fehlt). Migration fuer die
Portal-Staging-DB liegt bei. Promote-Reihenfolge: Monitor VOR Portal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 19:07:01 +00:00
claude-dev
ae4fb106ad feat(sources): Sammel-Bearbeitung fuer Vorschlaege im Aufgaben-Reiter
Die Vorschlags-Tabelle hat jetzt eine Checkbox-Spalte mit Alle-auswaehlen
(wirkt auf die gefilterten Zeilen) und zwei Knoepfe Ausgewaehlte annehmen /
Ausgewaehlte ablehnen. Noetig geworden, weil ein Pruefaluf hunderte
Vorschlaege erzeugen kann und Einzelklicks mit Dialog dann nicht praktikabel
sind. Neuer Endpoint PUT /suggestions/bulk nutzt exakt dieselbe
Entscheidungslogik wie der Einzel-Endpoint (gemeinsamer Helper
_apply_suggestion_decision, inkl. Auto-Reject und Duplikat-Schutz),
bereits erledigte IDs werden uebersprungen statt als Fehler gewertet.
Ein Audit-Eintrag pro Sammelaktion mit Zaehlern.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 18:54:43 +00:00
claude-dev
c5f63b1d14 fix(sources): Feinschliff nach Konsistenz-Pruefung + UI-Rueckmeldungen
Echte Fehler:
- esc() maskiert jetzt auch Anfuehrungszeichen. Quellennamen mit
  Apostroph (z.B. LExpress) brachen sonst die Zeilen-Knoepfe.
- formatDateTime parst SQLite-UTC-Zeitstempel jetzt als UTC statt
  Lokalzeit (Zeiten waren um den Zeitzonen-Offset verschoben).
- Audit-Filter Bis-Datum schliesst den gewaehlten Tag jetzt komplett ein.

UI-Rueckmeldungen:
- Beschreibung in der Vorschlags-Tabelle bricht mehrzeilig um statt
  abgeschnitten zu werden.
- Bestaetigen-Knopf im Dialog ist standardmaessig Gold, Rot nur noch bei
  destruktiven Aktionen (Org/Nutzer/Quelle loeschen, X-Konto entfernen).
- Alle >= 0.85 genehmigen ist ausgegraut, solange keine Klassifikationen
  ausstehen.

Konsistenz:
- GET /suggestions deckelt pending nicht mehr auf 50 (Badge und Tabelle
  liefen auseinander), bearbeitete weiterhin letzte 50.
- /stats zaehlt jetzt alle Quellen wie die Liste (nicht nur aktive),
  Grundquellen/Kundenquellen-Aufteilung wird immer angezeigt.
- Health-Spalte sortiert nach Schweregrad statt alphabetisch.
- Aufgaben-Badge laedt schon beim Seitenstart, nicht erst beim Reiterklick.
- Loesung-suchen-Knopf stellt nach Fehler das Icon wieder her, native
  confirm()-Dialoge durch showConfirm ersetzt.
- Tote Endpoints GET /health (Alt-Liste) und GET /classification/stats
  entfernt, tote CSS-Bloecke (activity-*, badge-health-*,
  review-conf-filter) geloescht.
- Smoke-Test deckt jetzt alle Klassifikations-/Upload-/Sync-Endpoints ab.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 18:48:16 +00:00
claude-dev
14e766173c feat(sources): Knopf Jetzt pruefen startet den Health-Check aus dem Portal
- POST /api/sources/health/run (202, bei laufendem Run 409) stoesst den
  Lauf als BackgroundTask an: eigene DB-Connection, run_health_checks +
  generate_suggestions aus den geteilten Diensten, exakt nach dem Vorbild
  des Monitor-Nachtjobs daily_source_health_check. Kein Code-Duplikat.
- GET /api/sources/health/run-status liefert den In-Memory-Status
  (health_run.py, pure Funktionen mit Doppelstart-Sperre, unit-getestet).
  Nach einem Neustart ist der Status idle, ein partieller Stand wird vom
  naechsten Lauf archiviert und ueberschrieben (wie beim Nachtjob).
- Frontend: Knopf Jetzt pruefen + Zuletzt geprueft in der Stats-Leiste
  der Quellenliste, Polling alle 4 s, Abschluss-Toast mit geprueft/
  Probleme/neue Vorschlaege, danach Liste + Aufgaben-Badge neu laden.
  Beim Oeffnen des Reiters wird ein laufender Run aus anderer Session
  erkannt und weiterverfolgt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 18:14:14 +00:00
claude-dev
bcfdac158e feat(sources): Aufgaben-Posteingang ersetzt Quellen-Health und Klassifikation
- Neuer Unterreiter Aufgaben buendelt Health-Vorschlaege (Tabelle inkl.
  Loesung-suchen), Klassifikations-Review-Karten und den eingeklappten
  Verlauf (erledigte Vorschlaege + letzte Prueflaeufe). Die dritte
  Navigationsebene (healthSubTabs) entfaellt komplett.
- Badge zeigt die Summe aus offenen Vorschlaegen und ausstehenden
  Klassifikationen, gespeist vom neuen billigen GET /api/sources/tasks/summary
  (gleiche Bedingung wie /classification/stats, laeuft nie auseinander).
  Badge laedt jetzt schon beim Klick auf den Quellen-Hauptreiter.
- aufgaben.js NEU (uebernimmt Vorschlags-/Verlauf-Rendering aus
  source-health.js und den kompletten Klassifikations-Block aus sources.js),
  source-health.js GELOESCHT (60s-Cache, Checks-Tabelle mit eigener
  Pagination und Filtern entfaellt, die Details stecken jetzt als
  Ausklapp-Zeile in der Quellenliste).
- Quellen hat damit 3 statt 5 Unterreiter: Quellenliste, Aufgaben,
  X-Recherche-Konten.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 18:11:19 +00:00
claude-dev
bbbcc51fc2 feat(sources): vereinte Quellenliste (Grund- + Kundenquellen in einer Tabelle)
- GET /api/sources mit scope=all|global|tenant ersetzt GET /global und
  GET /tenant. Liefert org_name (LEFT JOIN organizations) und wie bisher
  health_status + Artikel-Aktivitaet fuer ALLE Quellen.
- GET /global/stats wird GET /stats (zaehlt jetzt beide Herkuenfte,
  neu by_origin und last_check), GET /global/languages wird GET /languages.
- PUT /global/{id} akzeptiert jetzt auch Kundenquellen (Guard ohne
  tenant_id-Filter), damit der Deaktivieren-Knopf fuer beide funktioniert.
  DELETE bleibt bewusst global-only.
- Neu GET /{source_id}/health fuer die Ausklapp-Details je Quelle.
- Frontend: EIN Render-/Filter-/Sortier-Pfad statt zwei (Tenant-Kette
  komplett entfernt, ~200 Zeilen). Herkunfts-Filter, Organisations-Spalte,
  Checkbox-Spalte + Bulk-Promote nur bei Herkunft Kundenquellen.
- Health-Badge ist klickbar und klappt eine gemeinsame Detailzeile aus
  (Notizen + Checks mit Meldung und Zeitpunkt) mit Deaktivieren-Knopf.
  Klickweg kaputte Quelle finden und deaktivieren: 3 statt 8 bis 10 Klicks.
- Unterreiter Kundenquellen entfaellt, erster Reiter heisst Quellenliste.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 18:06:35 +00:00
claude-dev
1a08facb64 fix(sources): Meta-Reparatur (telegram/x/x_account/pdf_document) + toten Code entfernt
- source_meta.py kennt jetzt den echten Bestand: Kategorien telegram (107 Quellen)
  und x (40), Typen x_account und pdf_document. Die 10 nie belegten
  Lagen-Kategorien und der ungenutzte Typ excluded sind raus.
- Pydantic-Pattern source_type um x_account ergaenzt, excluded raus.
  Behebt 422 beim Speichern von 40 X-Account-Quellen.
- Modal-Selects (Typ, Kategorie, PDF-Kategorie) werden aus /api/sources/meta
  befuellt statt hartkodiert. Submit sendet category/source_type nur noch,
  wenn nicht leer. Behebt stilles Loeschen der Kategorie bei Telegram-Quellen.
- source_suggester: Import auf shared.agents.claude_client angepasst
  (war im Portal seit jeher kaputt, Konvention wie source_classifier).
- Toter Code raus: POST /health/run-stream (147 Z. SSE-Duplikat),
  runHealthCheck() im Frontend, excluded_counts-CTE + Sperren-Spalte
  (immer 0), Trend-Delta (braucht 2 Runs, es gibt 1), Alignment-Chips
  (source_alignments ist leer), doppeltes formatDateTime, redundanter
  setupHealthTab-Listener, toter healthContent-Zugriff.
- Tests: Kategorien-/Typen-Sets neu gepinnt, Smoke-Karteileichen entfernt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 17:58:08 +00:00
claude-dev
83af0d6897 feat(org-detail): Widerrufen-Knopf entfernt, Warnschwelle 0 = aus
Zwei Rückmeldungen des Nutzers.

- Der Widerrufen-Knopf in der Lizenz-Tabelle ist raus. Eine neue Lizenz
  widerruft die alte automatisch, und einen Kunden abschalten erledigt
  der prominente Org-Status-Umschalter. Der API-Endpoint /revoke bleibt.
- Die Warnschwelle lässt sich jetzt abschalten, 0 = aus, in allen drei
  Formularen (Budget, Neue Lizenz, Org-Anlage) samt Modell- und
  Endpoint-Validierung. Gegenstück im Monitor ist Commit 17b1886
  (bisher fiel eine 0 dort still auf die Voreinstellung 80 zurück).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 15:52:40 +00:00
claude-dev
25ec80c8e4 feat(statistik): Hauptreiter Statistik mit kompletter Betriebsstatistik
Neuer Reiter zwischen Audit-Log und Verbrauchsrechner, Anlass war die
Dashboard-Kachel API-Kosten gesamt, die nirgendwo hinführte (sie springt
jetzt hierher). Kennzahlen-Set nach Betreiber-Best-Practices für
nutzungsbasierte KI-Produkte (Kostenverlauf, Marge je Kunde, Betrieb).

- GET /api/statistik?months=N liefert alles in einem JSON. Kosten und
  Läufe je Monat und Lagentyp (führende Quelle refresh_log mit
  lückenlosem incidents-Join), Quellen-Split aus token_usage_monthly,
  Erfolgsquote, normalisiertes Fehler-Ranking, Dauer je Typ, Wachstum,
  MAU/DAU aus user_activity_days und je Organisation Ist-Kosten plus
  Margen-Schätzung zu heutigen Sätzen (Recherche-Anlage zählt dreifach,
  weil der Multi-Pass nur eine Log-Zeile erzeugt). Aggregation als pure,
  unit-getestete Funktionen, Monatsachse lückenlos gefüllt, Mediane nur
  über Läufe mit Kosten (Erfassung begann erst 03/2026).
- statistik.js injiziert sich selbst nach dem rechner.js-Muster,
  Platzierung doppelt gesichert (Ladereihenfolge mit async=false plus
  insertBefore). Charts als Inline-SVG ohne Bibliothek, eine Achse je
  Chart, Hover-Titel mit großen Trefferflächen, Legenden, Serienfarben
  je Theme mit dem dataviz-Palette-Validator geprüft (alle Checks PASS).
  Zeitraum 6/12/Alles, Datenstand-Hinweis, ehrliche Fußnote unter der
  Margen-Tabelle, Leerzustand für die junge Aktivitäts-Erfassung.
- Migration user_activity_days für die Portal-Staging-DB (auf Live legt
  sie der Monitor an, dort läuft die Erfassung in get_current_user).
- 10 neue Unit-Tests plus Auth-Smoke für den Endpoint, 96 Tests grün
  (die zwei bekannten shared-Import-Fehlschläge bestehen unverändert).

Gegenstück im Monitor: Commit d367c60 (Aktivitäts-Erfassung).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 15:09:34 +00:00
claude-dev
eeb74c74c1 fix(kontingent): Übertrag in den Folgemonat standardmäßig aus
Auf Nutzerwunsch findet ohne bewusste Entscheidung kein Übertrag statt.
Modell-Default, beide Checkboxen (Lizenz-Modal, Org-Modal) und der
Modell-Test stehen jetzt auf aus, der Übertrag bleibt pro Kunde
zuschaltbar. Der DB-Spalten-Default stand ohnehin schon auf 0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 13:22:54 +00:00
claude-dev
e0c39de21f feat(kontingent): Credits-Stellwerte je Lizenz + Lizenz beim Org-Anlegen
Bedienseite für das Credits-Monatskontingent des Monitors. Das Portal
setzt jetzt alle Stellwerte, der Monitor bleibt Herr der Laufzeitfelder.

- Lizenz-Modal und Budget-Formular um Abrechnungszeitraum (monthly/total),
  Übertrag-Checkbox und Warnschwelle erweitert, Vorbelegungen auf das
  beschlossene Modell (10.000 Credits, monatlich, Übertrag an, 0,20 USD).
- Neue Organisation kann direkt eine Lizenz mit Kontingent anlegen
  (OrgCreate.license, verschachtelt). Org- und Lizenz-Insert laufen in
  EINER Transaktion, schlägt der Lizenz-Teil fehl, entsteht keine
  halbe Organisation. Gemeinsamer Helper insert_license_row statt
  Duplikation der Widerruf- und Audit-Logik.
- PUT /api/token-usage/budget validiert credits_period (monthly|total)
  und budget_warning_percent (1 bis 100), credits_rollover wird wie
  unlimited_budget normalisiert. Laufzeitfelder bleiben bewusst
  außerhalb der Whitelist.
- Overview und Org-Detail rechnen den Rest jetzt gegen verfügbar =
  Kontingent + Übertrag, dieselbe Bezugsgröße wie der Hard-Stop im
  Monitor. Neuer read-only Block Laufzeitwerte im Token-Subtab.
- Startup-Check loggt einen deutlichen Fehler, wenn die licenses-Tabelle
  die Credits-Spalten noch nicht hat (falsche Deploy-Reihenfolge).
- Migration migrations/2026-07-25_credits_period.py (idempotent,
  wortgleich mit der Monitor-Migration) für die Portal-Staging-DB,
  auf Live gilt: Monitor VOR Portal promoten.
- 13 neue Modell-Tests, pytest grün (die zwei bekannten
  shared-Import-Fehlschläge bestehen unverändert seit vorher).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 13:11:02 +00: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
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
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