Files
2026-04-16 13:32:32 +02:00

48 KiB
Raw Permalink Blame History

AZA Master Handover / Operational Runbook

Arbeitsmodus / Regeln

User bastelt nicht; nur Composer-Patches (meist Opus) oder 1 exakter Command mit Pfad.

  • Alle Aenderungen kommen als fertige, vollstaendige Dateien (ready-to-paste).
  • User fuehrt nur vorgegebene Commands aus, keine manuellen Edits.
  • Jede Aenderung in 1 Patch, kein schrittweises Anleiten.
  • Keine risky Refactors immer minimal und sicher.

AKTUELLE PROJEKTPHASE (Stand 2026-03-28)

Phase: Stripe/Lizenz-Block ABGESCHLOSSEN Desktop-Lizenzpfad-Validierung ist naechster Block

STATUS: Stripe/Lizenz-Webhook-Block ERFOLGREICH ABGESCHLOSSEN (2026-03-28)

  • B1-W1 bis B1-W5 alle erfolgreich abgeschlossen
  • Stripe-Webhook funktional: Sandbox-Kauf verarbeitet, Lizenz in DB
  • Desktop → Hetzner → OpenAI funktioniert in der echten App
  • Kein lokaler OpenAI-Key noetig fuer den Hauptpfad
  • basis14.py wurde lokal erfolgreich gegen das Live-Backend getestet

Hetzner-Backend ist LIVE (2026-03-26)

  • Produktiver API-Pfad: https://api.aza-medwork.ch
  • DNS: api.aza-medwork.ch178.104.51.177
  • Repo auf Hetzner: /root/aza-app
  • Deploy-Verzeichnis: /root/aza-app/deploy
  • Laufende Services: aza-api + aza-caddy
  • Variante B technisch Ende-zu-Ende nachgewiesen

ARCHITEKTURENTSCHEIDUNG VARIANTE B (verbindlich, 2026-03-25):

  • KEIN OpenAI-Key in der Desktop-App
  • KEIN eigener OpenAI-Key pro Kunde als Pflicht
  • KEIN gemeinsamer OpenAI-Key clientseitig
  • Stattdessen: AZA Office spricht NUR mit eigenem AZA-Backend
  • Nur das AZA-Backend spricht mit OpenAI
  • Der OpenAI-Key liegt AUSSCHLIESSLICH serverseitig
  • KEINE halben Uebergangsloesung, KEINE Shared-Key-Bastelei

Erfolgreiche Nachweise (2026-03-26):

  • curl https://api.aza-medwork.ch/health → erfolgreich
  • curl -X POST https://api.aza-medwork.ch/v1/chat mit gueltigem X-API-Token → success:true, content:OK
  • Damit nachgewiesen: Hetzner-Backend laeuft, Caddy/HTTPS laeuft, serverseitiger OpenAI-Zugriff laeuft, Variante B funktioniert technisch Ende-zu-Ende

B1 BACKEND-SPRINT (4 Wochen)

Woche Zeitraum ca. Fokus
1 25.03 01.04 Backend Chat Proxy Endpoint (POST /v1/chat) + Auth + Rate Limiting
2 02.04 08.04 Desktop-App: alle OpenAI-Calls ueber Backend statt direkt
3 09.04 15.04 Hetzner Deploy: Docker/Caddy/HTTPS + Production-Env + Smoke-Tests
4 16.04 22.04 E2E-Test Desktop→Backend→OpenAI + Kundenweg ohne OpenAI-Key + Go-Live

AKTUELLE PRIORITAETSREIHENFOLGE (B1 Backend-Sprint)

  1. Backend Chat Proxy POST /v1/chat (Woche 1) Grundstein der Architektur
  2. Desktop-App auf Backend umstellen (Woche 2) Alle OpenAI-Calls migrieren
  3. Hetzner Deploy (Woche 3) Produktionsserver aufsetzen
  4. E2E-Test + Go-Live Backend-Pfad (Woche 4) Kundenweg ohne OpenAI-Key
  5. WooCommerce/Stripe/Kauf-Weg laeuft PARALLEL weiter (Hostpoint)

EXPLIZIT NACHRANGIG / NICHT JETZT:

  • Update-Komfort / separater Auto-Updater
  • Browser-AZA Web-App (nach Backend-Architektur)
  • Grosse Refactors die nicht Variante B dienen

HOSTPOINT vs. HETZNER:

  • Hostpoint bleibt fuer Website/Marketing/WooCommerce/Stripe
  • Hetzner ist JETZT der Backend-Pfad fuer OpenAI-Proxy/API
  • Beides laeuft parallel, nicht gegeneinander

ERLEDIGT: B1-W1 Backend Chat Proxy Endpoint (2026-03-26)

POST /v1/chat IMPLEMENTIERT UND VERIFIZIERT.

Aspekt Detail
Auth require_api_token (X-API-Token Header, bestehendes Muster)
Rate Limiting default_ip_limiter + default_token_limiter
Request-Schema ChatRequest: model, messages[], temperature?, max_tokens?, top_p?
Message-Schema ChatMessage: role (system/user/assistant), content
Modell-Whitelist gpt-5.2, gpt-5-mini, gpt-5-nano, gpt-4o, gpt-4o-mini, gpt-4o-mini-search-preview
Input-Limits Max 64 Messages, max 100k Zeichen/Nachricht
OpenAI-Call _get_openai().chat.completions.create(**params) serverseitig
Response-Schema {success, content, finish_reason, model, usage, request_id, duration_ms, error}
Secret-Scrubbing sk-, sk-proj-, org- in Fehlertexten werden ersetzt
Tests 7/7 gruen (Auth, Modell, Validierung, OpenAI-Proxy, /license/status, Schema)

Datei: backend_main.py (~100 Zeilen)

ERLEDIGT: B1-W2 Desktop Chat Migration (2026-03-26)

Desktop-App: Chat-Completions laufen jetzt ueber Backend POST /v1/chat.

Migriert:

  1. call_chat_completion() in basis14.py zentraler Wrapper -> _backend_chat_completion()
  2. News-Suche direkter self.client Call -> _backend_chat_completion()
  3. Kommentare eigener OpenAI() Client -> _backend_chat_completion()
  4. Med-Detail Kurzinfo eigener OpenAI() Client -> _backend_chat_completion()
  5. Briefstil-Analyse in aza_text_windows_mixin.py -> _backend_chat_completion()

Neue Architektur in basis14.py:

  • _BackendChatResponse Wrapper-Klasse, OpenAI-Interface-kompatibel (.choices[0].message.content, .usage)
  • _backend_chat_completion(**kwargs) POST /v1/chat mit bestehender Token-Mechanik (get_backend_url/get_backend_token)
  • call_chat_completion(**kwargs) Consent/Capacity Check, dann _backend_chat_completion()
  • Timeout: 5s connect, 120s read
  • Fehler: RuntimeError mit lesbarer Meldung, keine Secrets

Verbleibend fuer spaetere Bloecke: translate.py, congress_window.py, aza_email.py (eigenstaendige Module)

7/7 Tests gruen: Health, Auth, Model-Validation, E2E Desktop->Backend->OpenAI, Response-Schema, /license/status OK.

ERLEDIGT: B1-W3 Hetzner Deploy (2026-03-26)

Hetzner-Backend ist LIVE.

Aspekt Detail
Domain https://api.aza-medwork.ch
DNS api.aza-medwork.ch178.104.51.177 (A-Record)
Repo auf Hetzner /root/aza-app
Deploy-Verzeichnis /root/aza-app/deploy
Laufende Services aza-api + aza-caddy
Compose laeuft aus /root/aza-app/deploy
.env produktiv AZA_DOMAIN=api.aza-medwork.ch, ACME_EMAIL=info@aza-medwork.ch, MEDWORK_API_TOKENS gesetzt, OPENAI_API_KEY serverseitig gesetzt

Geloeste Root Causes beim Deploy:

  1. Falsches Git-Remote (naswinterthur) war nicht geeignet → korrektes Remote verwendet
  2. Nur deploy/ hochladen war falsch → docker-compose.yml erwartet Repo-Root-Kontext (context: .., dockerfile: deploy/Dockerfile)
  3. Host-nginx blockierte Port 80 → nginx gestoppt
  4. Caddy DNS/ACME-Probleme wegen Resolver 127.0.0.53 → Fix: im caddy-Service in docker-compose.yml explizit DNS gesetzt (1.1.1.1, 8.8.8.8)

ERLEDIGT: B1-W4 Server-E2E-Test (2026-03-26)

Serverseitige Variante B Ende-zu-Ende nachgewiesen:

  • curl https://api.aza-medwork.ch/health → erfolgreich
  • curl -X POST https://api.aza-medwork.ch/v1/chat mit gueltigem X-API-Token → success:true, content:OK
  • Hetzner-Backend laeuft, Caddy/HTTPS laeuft, serverseitiger OpenAI-Zugriff laeuft

ERLEDIGT: B1 Desktop-Finalisierung (Code-Patches, 2026-03-27)

Alle Code-Patches fuer Variante B im Desktop sind verifiziert und korrekt:

Patch Status Detail
ensure_ready() KORREKT Remote-Backend gilt als ready (kein lokaler OpenAI-Key noetig)
OpenAI-Key-Setup-Dialog KORREKT Dialog wird bei konfiguriertem Remote-Backend unterdrueckt
backend_url.txt KORREKT Zeigt auf https://api.aza-medwork.ch
backend_token.txt KORREKT Zentrale lokale Token-Quelle, wird von App priorisiert
start_all.bat Guard KORREKT Variante-B-Schutz: ueberschreibt URL nicht bei Live-Backend
start_backend_autoport.bat Guard KORREKT Variante-B-Schutz: ueberschreibt URL nicht bei Live-Backend
Chat-/Textpfad KORREKT Laeuft ueber POST {backend_url}/v1/chat

Token-Prioritaet (bestaetigt):

  1. backend_token.txt (hoechste Prioritaet)
  2. Env MEDWORK_API_TOKENS
  3. Env MEDWORK_API_TOKEN

Backend-URL-Prioritaet (bestaetigt):

  1. Env MEDWORK_BACKEND_URL
  2. backend_url.txt

Nicht geaenderte Restpfade (blockieren Haupttest NICHT):

  • translate.py, aza_email.py, apps/diktat/diktat_app.py haben noch lokale OpenAI-Clients → betreffen Nebenpfade
  • kongress2_window.py hat hardcoded URL → Kongress ist geparkt
  • self.client = OpenAI(...) Init bleibt als Dev-Fallback → blockiert nichts bei Variante B

ERLEDIGT: B1-W5 Lokaler Desktop-Live-Test (2026-03-27)

Desktop → Hetzner → OpenAI erfolgreich in der echten App getestet.

  • backend_url.txt zeigt auf https://api.aza-medwork.ch
  • backend_token.txt lokal vorhanden, vom Live-Backend akzeptiert
  • basis14.py lokal gestartet und erfolgreich gegen Live-Backend getestet
  • Kein lokaler OpenAI-Key noetig
  • Kein OpenAI-Key-Dialog erscheint
  • Chat-/Textpfad laeuft ueber Hetzner-Backend

Desktop-spezifische Hinweise (fuer kuenftige Chats):

  • ensure_ready() ist korrekt fuer Remote-Backend gepatcht
  • OpenAI-Key-Dialog wird bei Remote-Backend unterdrueckt
  • Fuer Live-Test NICHT ueber lokale Starter gehen (start_all.bat, RUN_AZA_ONECLICK.bat, START_AZA.bat, start_backend_autoport.bat) diese setzen Env auf localhost
  • Bevorzugte Startmethode: python basis14.py direkt

AKTUELLER HAUPTBLOCK: Desktop-Lizenzpfad validieren (ab 2026-03-28)

Ziel: Desktop-App soll ueber /stripe/license_debug bzw. /license/status den aktiven Lizenzstatus aus der Stripe-DB lesen und korrekt zwischen Vollmodus und Testmodus schalten.

Konkret:

  1. Desktop-Lizenzcheck gegen funktionierenden /stripe/license_debug?email={EMAIL} pruefen
  2. Validieren: aktive Subscription → Vollmodus, keine/abgelaufene → Testmodus
  3. Aktivierungsschluessel-Fallback greift nur bei fehlendem Remote-Backend (bereits implementiert)
  4. Bestehende /license/status-Struktur NICHT kaputtmachen
  5. KEIN unkontrollierter Live-Kauf als Testschritt
  6. Nur minimale gezielte Patches

DANACH: Lizenz-/Subscription-Lifecycle

Ziel: Lizenzstatus zuverlaessig an Subscription-Zahlung koppeln.

Konkret:

  1. Lizenz aktiv solange Subscription bezahlt ist
  2. Rueckfall auf Testmodus bei Kuendigung/Nichtzahlung
  3. App-/Lizenzstatus sauber pruefen
  4. /license/status-Struktur NICHT kaputtmachen

PARALLELER PFLICHTBLOCK: WooCommerce / Stripe Live-Setup (ab 2026-03-27)

Ziel: Zahlungsfluss produktiv machen inkl. Auszahlung auf Bankkonto.

Konkret:

  1. WooCommerce-/Stripe-Konfiguration fertigstellen
  2. Live-Zahlungsfluss vorbereiten
  3. Sicherstellen, dass Auszahlungen auf das Bankkonto des Nutzers gehen
  4. Testkauf / Zahlungsfluss validieren

FUEHRENDE SUBSCRIPTION-PREISE (Stand 2026-03-27)

Plan Monatlich Jaehrlich
1 Benutzer (Basic) CHF 59 CHF 590
2 Benutzer (Team) CHF 89 CHF 890

Stripe Lookup-Keys und Price-IDs:

Lookup-Key Price-ID Betrag
aza_basic_monthly price_1T53xHL5lREAW68VbuK43lmz CHF 59
aza_basic_yearly price_1T542BL5lREAW68VNLQGCKWZ CHF 590
aza_team_monthly price_1T544tL5lREAW68VkmnmZ21Q CHF 89
aza_team_yearly price_1T545RL5lREAW68VLbIh73AN CHF 890

Stripe Live-Status (Stand 2026-03-27):

  • Stripe Live-Konto existiert und ist eingerichtet
  • Produkt AzA Office mit 4 Preisen angelegt (Basic monatlich/jaehrlich, Team monatlich/jaehrlich)
  • Payment Links erstellt
  • Live-Webhook eingerichtet: https://api.aza-medwork.ch/stripe/webhook → 200 OK
  • STRIPE_SECRET_KEY und STRIPE_WEBHOOK_SECRET korrekt in Hetzner .env
  • Aktivierungsschluessel-Fallback im Desktop bei Remote-Backend auf Dev-only begrenzt

OFFENE PFLICHT-DOKUMENTATION Stripe-Konto:

  • Fuehrendes Stripe-Konto (Login / E-Mail): NOCH NICHT DOKUMENTIERT
  • Testmodus oder Livemodus aktuell fuehrend: NOCH NICHT DOKUMENTIERT
  • Bankkonto fuer Auszahlungen hinterlegt: NOCH NICHT DOKUMENTIERT
  • Success-/Cancel-URLs fuehrend: NOCH NICHT DOKUMENTIERT Diese Punkte muessen vor dem ersten echten Kundenkauf dokumentiert sein.

ERLEDIGT: Stripe-/Lizenz-Nacharbeiten (2026-03-28):

  1. Frisches Stripe-Event senden und pruefen ob admin@aza-medwork.ch sauber in DB landet → ERLEDIGT: Sandbox-Kauf erfolgreich verarbeitet
  2. test@example.com aus SQLite bereinigen → ERLEDIGT: geloescht
  3. Desktop-Lizenzcheck auf /stripe/license_debug?email={EMAIL} abstimmen → NAECHSTER HAUPTBLOCK
  4. Nach stabilem Abschluss Stripe-Secrets rotieren → OFFEN (spaeter)
  5. Stripe-Konto Ownership dokumentieren → OFFEN (Admin-Block)
  6. Bankkonto fuer Stripe-Auszahlungen pruefen → OFFEN (Admin-Block)

ERLEDIGT: Stripe/Lizenz-Webhook-Block ABGESCHLOSSEN (2026-03-28)

Status: Webhook funktional. Sandbox-Kauf erfolgreich verarbeitet. Lizenz in SQLite. license_debug funktioniert intern und extern.

Erfolgreicher Sandbox-Kauf (2026-03-28):

  • Email: admin@aza-medwork.ch
  • Subscription: sub_1TG4fSRGaRoJio7WyM2KwN53
  • Status: active
  • Lookup-Key: aza_basic_monthly
  • SQLite bereinigt: nur relevanter Datensatz, test@example.com geloescht

Geloeste Root Causes (chronologisch):

  1. StripeObject vs. dict: .get(...) auf rohen Stripe-Objekten → Fix: event = json.loads(body)
  2. .to_dict_recursive() existiert nicht: Niemals verwenden
  3. Doppel-Prefix 404: prefix="/stripe" in main.py + /stripe/webhook in Router → Fix: nur @router.post("/webhook")
  4. Email-Lookup: Kaskade: customer_emailcustomer_details.emailCustomer.retrieve(id)
  5. Container-Env-Falle: docker compose restart reicht nicht → up -d --build --force-recreate
  6. Decimal-Serialisierung: str(StripeObject) scheitert bei Decimal-Werten → Fix: _stripe_to_dict() + _decimal_default()
  7. Idempotenz-Bug: _mark_processed() lief auch nach Fehler → Fix: nur nach Erfolg innerhalb try-Block
  8. Stille Exits: Fehlende Daten fuehrten zu 200 OK ohne Log → Fix: lueckenloses Logging (webhook_received, checkout_entered, license_skip, license_upsert, license_error)
  9. Sandbox API-Key-Mix: Sandbox-Webhook mit Live-Secret-Key → No such subscription → Fix: BOTH sk_test_ + whsec_ fuer Sandbox
  10. missing_lookup_key: Sandbox setzt price.lookup_key nicht → Fix: _lookup_key_from_price() Fallback ueber recurring.interval + unit_amount

NEVER AGAIN Stripe-Webhook-Regeln:

  • Niemals .to_dict_recursive() verwenden
  • Niemals rohe StripeObjects mit .get(...) behandeln
  • Niemals json.loads(str(stripe_obj)) bricht bei Decimal. Immer _stripe_to_dict() verwenden
  • Webhook nach Signaturpruefung immer als plain JSON: event = json.loads(body)
  • _mark_processed() NUR nach erfolgreicher Verarbeitung (innerhalb try)
  • Prefix-Routing: bei prefix="/stripe" muss Decorator @router.post("/webhook") lauten
  • Bei .env-Aenderungen: docker compose up -d --build --force-recreate aza-api
  • Sandbox und Live strikt trennen: BOTH STRIPE_SECRET_KEY=sk_test_... + STRIPE_WEBHOOK_SECRET=whsec_... fuer Sandbox
  • Nach Sandbox-Tests wieder Live in deploy/.env setzen

Operative Referenz Hetzner:

  • Aktuelle Datei: /root/aza-app/stripe_routes.py
  • Working Backup (nach lookup-Fallback): /root/aza-app/stripe_routes.py.working_lookup_fallback_ok
  • Aelteres Backup: /root/aza-app/stripe_routes.py.working_backup
  • SQLite DB: /root/aza-app/data/stripe_webhook.sqlite
  • DB-Backup (nach Sandbox-Erfolg): /root/aza-app/data/stripe_webhook.sqlite.backup_after_sandbox_success
  • Repo: /root/aza-app
  • Compose: /root/aza-app/deploy
  • Logs: docker logs -f --tail 20 aza-api
  • Event-Log: tail -n 20 /root/aza-app/data/stripe_events.log.jsonl
  • Debug: curl https://api.aza-medwork.ch/stripe/license_debug?email=admin@aza-medwork.ch
  • Live-Stripe ist aktuell wieder in /root/aza-app/deploy/.env gesetzt

BEWUSST NACHGELAGERT (Polish-Phase)

  • Autotext-Fix
  • Fenstergroessen anpassen
  • Button-Groessen / Layout fuer Online-Praesentation
  • Allgemeiner UI-Feinschliff
  • Direkte OpenAI-Restpfade in Nebenmodulen bereinigen (translate.py, aza_email.py, diktat_app.py)

Blocker-Regel: Ein klarer Block nach dem anderen.

KUNDENWEG-ANALYSE (2026-03-25)

Strecke Status Detail
Kauf (WooCommerce) IN ARBEIT (parallel) Doku fertig, 7 Admin-Schritte in WordPress-Admin (Hostpoint)
Download TEILWEISE Mechanik da, WooCommerce-Upload fehlt
Installer FUNKTIONAL FERTIG Kein Code-Signing (SmartScreen-Warnung)
Aktivierung BRIDGE IMPLEMENTIERT AZA-Key setzt Vollmodus, Trial-Dialog zeigt Status
Erster Start VARIANTE B LIVE (2026-03-27) Desktop → Hetzner → OpenAI funktioniert. Kein lokaler OpenAI-Key noetig.

FOKUSBLOECKE

Prio Block Beschreibung
ERLEDIGT B1-W1: Backend /v1/chat Chat Proxy Endpoint Grundstein Variante B
ERLEDIGT B1-W2: Desktop umstellen Alle OpenAI-Calls in basis14.py + Mixin ueber Backend
ERLEDIGT B1-W3: Hetzner Deploy Backend LIVE auf api.aza-medwork.ch
ERLEDIGT B1-W4: Server-E2E /health + /v1/chat erfolgreich, Variante B serverseitig nachgewiesen
ERLEDIGT B1-W5: Desktop Live-Test basis14.py lokal gegen Live-Backend erfolgreich getestet (2026-03-27)
ERLEDIGT Stripe Live-Webhook Webhook 200 OK, Lizenzeintrag in DB, StripeObject/Routing/Env-Fallen geloest (2026-03-27)
ERLEDIGT Stripe Live-Konto/Produkt/Preise Produkt AzA Office, 4 Preise, Payment Links, Webhook eingerichtet (2026-03-27)
ERLEDIGT STRIPE-W1: Webhook-Nacharbeiten Sandbox-Kauf erfolgreich, lookup_key-Fallback, SQLite bereinigt, license_debug funktional (2026-03-28)
AKTUELL Desktop-Lizenzpfad validieren Desktop gegen /stripe/license_debug bzw. /license/status, Vollmodus/Testmodus korrekt
DANACH Lizenz-/Subscription-Lifecycle Lizenz an Subscription koppeln, Rueckfall bei Kuendigung
PARALLEL (Admin) WooCommerce-Grundkonfiguration Zahlungsfluss + Auszahlung auf Bankkonto (getrennter Admin-Block)
NACHGELAGERT UI-Polish Autotext-Fix, Fenstergroessen, Buttons, Layout
NACHGELAGERT FB-C: Signing Signing-Readiness vorbereitet
NACHGELAGERT FB-D: Update-Komfort Erst nach stabilem Kundenweg

PRODUKTNAME AKTUELLE RICHTUNG

Aktueller Favorit: AZA Office

Bevorzugte Langform:

  • AZA Office Ihr medizinischer KI-Arbeitsplatz fuer die Praxis

Zweite gute Variante:

  • AZA Office Die KI-Assistenz fuer medizinische Dokumentation

Status: Aktuelle bevorzugte Naming-Richtung. Noch nicht zwingend final juristisch/brand-strategisch entschieden. Soll fuer WooCommerce/Website/Download/Go-Live/Produktdarstellung wiederverwendet werden.

Fruehere Shortlist (AZA Desktop): Dokumentiert in project_roadmap.json und project_plan.json. Durch AZA Office abgeloest.

VARIANTE B BESTANDSANALYSE (2026-03-25)

Was fuer serverseitigen OpenAI-Zugriff BEREITS existiert:

Baustein Status Detail
POST /v1/transcribe FUNKTIONIERT Backend→OpenAI fuer Transkription. Muster fuer /v1/chat.
Auth-Contract FUNKTIONIERT X-API-Token + X-Device-Id. Etabliert.
License /license/status FUNKTIONIERT Lizenzpruefung ueber Backend.
Stripe Billing Portal FUNKTIONIERT Desktop holt URL vom Backend.
Docker/Caddy/Compose VORBEREITET deploy/ Ordner komplett. Lokal verifiziert.
OpenAI-Client in backend_main.py VORHANDEN from openai import OpenAI importiert.
Rate Limiting VORHANDEN aza_rate_limit.py (IP + Token Limiter).

Was die Desktop-App DIREKT zu OpenAI ruft (zu migrieren):

Feature Datei Zeile ca. API
Chat (zentral) basis14.py ~5458 chat.completions.create
News-Suche basis14.py ~3417 chat.completions.create
Kommentare basis14.py ~7058 chat.completions.create
Med-Detail Kurzinfo basis14.py ~7453 chat.completions.create
Usage/Budget aza_persistence.py ~500 /v1/usage (REST)
Briefgenerierung aza_text_windows_mixin.py diverse chat.completions.create
Uebersetzer translate.py diverse chat.completions.create
Diktat-App apps/diktat/diktat_app.py diverse transcriptions/chat

Was BEREITS ueber Backend laeuft:

  • Transkription: transcribe_file_via_backend_with_fallback() → POST /v1/transcribe
  • Lizenzpruefung: GET /license/status
  • Billing Portal: GET /stripe/billing_portal_url

Luecken fuer Variante B (aktualisiert 2026-03-27):

  1. KEIN /v1/chat Endpoint → ERLEDIGT (2026-03-26)
  2. Kein kundenbezogenes Usage-Tracking auf dem Server (spaeter)
  3. Backend NICHT auf Hetzner deployed → ERLEDIGT: api.aza-medwork.ch LIVE (2026-03-26)
  4. Desktop zeigt noch auf lokales Backend → ERLEDIGT (2026-03-27): Desktop → Hetzner → OpenAI funktioniert in der echten App
  5. Kein Kunden-Quota/Budget-Management serverseitig (spaeter)
  6. Lizenz-/Subscription-Lifecycle Lizenz an Zahlung koppeln, Rueckfall bei Kuendigung (NAECHSTER HAUPTBLOCK)

ARBEITSWEISE FUER NAECHSTE CHATS

  • Root-cause-first statt blindem Nachpatchen
  • Ein klarer Block nach dem anderen
  • Keine 10 Baustellen gleichzeitig
  • Reale installierte Builds staerker gewichten als Code-Behauptungen
  • Nicht zu frueh "fertig" sagen
  • Desktop unterscheiden in:
    1. Dev-Code
    2. Neu gebauter Installer
    3. Reales Verhalten im installierten Build

KOMMUNIKATIONSHINWEIS (2026-03-28):

Aktuell NICHT wieder aufmachen:

  • Hetzner-Grunddeploy ist live und funktioniert
  • DNS/Caddy/nginx-Diskussion ist abgeschlossen
  • Basis-Backend-Migration B1-W1 bis B1-W5 erledigt
  • Variante A/B-Diskussion Variante B ist verbindlich und produktiv
  • Stripe-Webhook-Stabilisierung ABGESCHLOSSEN, alle Root Causes geloest, Sandbox-Kauf erfolgreich
  • .to_dict_recursive(), Routing, Decimal, lookup_key debuggen alles geloest und dokumentiert
  • Keine unkontrollierten Live-Kaeufe zuerst Desktop-Lizenzpfad sauber validieren

Aktuelle Hauptfokusse:

  1. Desktop-Lizenzpfad gegen funktionierenden Stripe-Endpunkt validieren (STRIPE-W2)
  2. Billing-/Lizenz-Lifecycle sauber finalisieren (LIC-01 nach Desktop-Validierung)
  3. WooCommerce-Grundkonfiguration als getrennter Admin-Block (LIC-02/LIC-04)
  4. Danach: UI-/Autotext-/Praesentation-Polish

Aktueller lokaler Arbeitsordner

FUEHRENDER PFAD (ab 2026-03-27):

C:\Users\surov\Documents\AZA_GIT\aza\AzA march 2026

ALTER PFAD (HISTORISCH, nicht mehr verwenden):

C:\Users\surov\Documents\AZA\backup 24.2.26

Lokaler Start (Variante B Live-Test)

Bevorzugte Startmethode fuer Live-Test gegen Hetzner-Backend:

cd "C:\Users\surov\Documents\AZA_GIT\aza\AzA march 2026"
python basis14.py

NICHT verwenden fuer Live-Test (setzen Env auf localhost):

  • start_all.bat
  • RUN_AZA_ONECLICK.bat
  • START_AZA.bat
  • start_backend_autoport.bat

Alter lokaler Dev-Start (nur fuer lokale Entwicklung mit eigenem Backend):

cd "C:\Users\surov\Documents\AZA_GIT\aza\AzA march 2026"
powershell -ExecutionPolicy Bypass -File .\deploy\local_reset_and_start.ps1

Tests (Lokal)

cd "C:\Users\surov\Documents\AZA_GIT\aza\AzA march 2026"
powershell -ExecutionPolicy Bypass -File .\deploy\authorized_test.ps1
powershell -ExecutionPolicy Bypass -File .\deploy\smoke_suite.ps1

Step 14 Docker/Compose Smoke-Test

Ziel: Container bauen, starten, smoke_suite PASS gegen Docker.

1 Command:

cd "C:\Users\surov\Documents\AZA_GIT\aza\AzA march 2026"
powershell -ExecutionPolicy Bypass -File .\deploy\docker_smoke.ps1

Was das Script macht:

  • docker compose up -d --build (baut und startet Container)
  • Wartet bis /health HTTP 200 liefert (max 60s)
  • Fuehrt smoke_suite.ps1 gegen den Container aus
  • Gibt [RESULT] PASS oder [RESULT] FAIL aus
  • Bei FAIL bleiben Container laufen (Logs inspizierbar)

Erwartete Checks (smoke_suite):

  • GET /health -> 200
  • GET /version -> 200 mit {name, build}
  • GET /license/status ohne Token -> 401/403
  • GET /license/status mit Token -> 200 mit {valid, valid_until}
  • GET /stripe/health -> 200 oder 404 (WARN)
  • GET /openapi.json -> 200

Bei Fehler:

docker compose -f .\deploy\docker-compose.yml logs --follow
docker compose -f .\deploy\docker-compose.yml down

Step 15 Caddy/HTTPS Reverse Proxy

Ziel: HTTPS live mit ACME-Zertifikat, Reverse Proxy auf :8000.

  • Caddyfile finalisieren (Domain, TLS)
  • ACME-Challenge testen
  • Reverse Proxy pruefen (curl https://DOMAIN/health)

Step 16 Go-Live Runbook

Ziel: Production-Deployment auf VPS oder Buero-PC.

  • Webhook erreichbar (Stripe)
  • Stripe Signatur ok (STRIPE_WEBHOOK_SECRET)
  • Billing Portal Return URL korrekt
  • Log-Hygiene: keine Secrets in Logs

Desktop UX / Persistence Block (2026-03-18)

Benutzerdaten bei Deinstallation:

  • Inno Setup CurUninstallStepChanged fragt ob %APPDATA%\AZA Desktop geloescht werden soll
  • Standard: Nein (Daten bleiben erhalten, Neuinstallation nutzt vorhandene Daten)
  • Dateien: installer/aza_installer.iss

Signatur-/Benutzername-Logik:

  • load_signature_name() faellt auf Profilname zurueck wenn kein expliziter Signaturname gesetzt
  • Einstellungsdialog: Haekchen "Profilname verwenden" + Feld fuer abweichenden Signaturnamen
  • Wenn Haekchen aktiv → Profilname. Wenn aus + Name eingetragen → diesen verwenden
  • Dateien: aza_persistence.py, aza_settings_mixin.py

Rechtsklick im Minifenster:

  • Gleiche Checkbox wie im Hauptfenster, teilt _rclick_paste_var, synchronisiert
  • Datei: basis14.py

Kommentare-Fenster (TEILWEISE):

  • Grundstruktur: Button "Kommentare" in Toolbar, separates Fenster, KI-Kurzkommentare via GPT
  • OFFEN: Live-Aktualisierung bei KG-Aenderung, Detailfenster bei Klick auf Kommentar
  • Datei: basis14.py

Briefstil-Lernen aus frueheren Word-Briefen (TEILWEISE):

  • DOCX-Upload (Mehrfach), Stilprofil-Analyse via GPT, persistente Stilprofile
  • Profilauswahl im Brief-Fenster, Integration in Briefgenerierung als System-Prompt
  • OFFEN: Detailmodus-Erweiterung der Stilanalyse, erweiterte Formatunterstuetzung
  • Dateien: aza_persistence.py, aza_text_windows_mixin.py, basis14.py

Autotext Root-Cause-Fix:

  • Root Cause: _is_admin NameError verhinderte Autotext-Dialog im installierten Build
  • Listener auf bewaehrten Stand (Kopie 13) zurueckgesetzt
  • Datei: basis14.py

Uebersetzer-Stabilitaetsfix (2026-03-19):

  • Root Cause: translate.main() erzeugte tk.Tk() in Hintergrund-Thread (frozen Build) Tkinter nicht threadsafe
  • Fix: translate.py akzeptiert parent-Parameter, erstellt Toplevel statt Tk(), kein eigener mainloop()
  • basis14.py ruft translate.main(parent=self) direkt auf dem Main-Thread auf
  • Zusaetzlich: API-Key-Fallback ueber openai_runtime_config
  • Dateien: translate.py, basis14.py

Briefstil-Profile (2026-03-19, nachgeschaerft):

  • KISIM Bericht + Klinischer Bericht als feste Systemprofile (immer sichtbar, nicht loeschbar)
  • KISIM = klassischer Gesamtbericht: Diagnose/Allergien/Therapie/Anamnese/Beurteilung/Diagnostik/Procedere
  • Klinisch = diagnosezentriert: pro Diagnose KLINIK/DIAGNOSTIK/THERAPIE/Aktuell, dann Allergien/Beurteilung/Procedere
  • Praezise medizinische Regeln: keine Ueberinterpretation, keine Halluzination, konservativ kodieren
  • Vereinheitlichtes Stilprofil-System im Brief-Fenster:
    • Haekchen "Stilprofil anwenden" + Dropdown (keins / Klinischer Bericht / KISIM Bericht / Benutzerprofile)
    • Haekchen "Standard fuer Arztbriefe" (persistent)
  • Reihenfolge Dropdown: (keins) -> Systemprofile -> gelernte Benutzerprofile
  • Stilprofil-Dialog: System-Profile als feste nicht-loeschbare Eintraege, Benutzerprofile per Word-Upload
  • Persistenz: stilprofil_enabled, stilprofil_name, stilprofil_default_brief in autotext_data
  • Dateien: aza_prompts.py, aza_text_windows_mixin.py, aza_persistence.py

Persistenz- und Consent-Patch:

  • KI-Einwilligung direkt beim Erststart (nach Fachgebiet-Dialog, vor normalem App-Betrieb)
  • Benutzerprofil um Code (ZSR/GLN) erweitert (Registrierung + Profil-Bearbeiten)
  • Deinstallations-Frage listet alle Benutzerdaten einzeln auf (Profil, Transkripte, Vorlagen, Consent, Signatur etc.)
  • Kommentare-Fenster: Toggle "beim Start automatisch oeffnen" + persistent
  • Einstellungen logisch gruppiert: LabelFrame "Startverhalten / Fenster"
  • Alle Benutzerdaten liegen in %APPDATA%\AZA Desktop und ueberleben Reinstall (Standard: behalten)
  • Dateien: basis14.py, aza_settings_mixin.py, aza_persistence.py, installer/aza_installer.iss

AZA Clean Uninstall / Reset Tool (2026-03-19)

Zweck: Saubere Deinstallation und Reset von AZA Desktop ohne Neustart. Fuer Installer-Abnahme und Reinstall-Tests.

Starten (Doppelklick):

AZA_Deinstallieren.bat

Oder direkt in PowerShell:

cd "C:\Users\surov\Documents\AZA_GIT\aza\AzA march 2026"
powershell -ExecutionPolicy Bypass -File .\tools\aza_clean_uninstall.ps1

Modi:

  • Modus 1: Nur App entfernen, Benutzerdaten behalten (Standard fuer Reinstall-Tests)
  • Modus 2: Vollstaendig zuruecksetzen inkl. aller Benutzerdaten

Was das Tool macht:

  1. AZA-Prozesse sauber beenden (erst freundlich, dann forciert)
  2. Inno-Setup-Uninstaller silent ausfuehren
  3. Installationsreste bereinigen (Verzeichnis, Shortcuts)
  4. Firewall-Regel entfernen
  5. Benutzerdaten je nach Modus behalten oder loeschen
  6. Registry-Reste bereinigen (falls Inno-Uninstaller nicht verfuegbar)
  7. Abschlussmeldung: Neustart noetig? Neuinstallation moeglich?

Benutzerdaten-Pfade:

  • AppData: %APPDATA%\AZA Desktop (Profil, Einstellungen, Lizenz, Consent, Autotext, Stilprofile)
  • Dokumente: %USERPROFILE%\Documents\KG_Diktat_Ablage (Transkripte, Briefe, Rezepte, Kostengutsprachen)

Dateien: tools/aza_clean_uninstall.ps1, AZA_Deinstallieren.bat

Do-Not-Break Regeln

  1. Keine bestehenden API-Response-Formate aendern (besonders /license/status)
  2. Auth/Security nicht modifizieren (Token-Rotation, _check_token)
  3. Keine Secrets loggen/printen (Tokens, Keys, Passwoerter)
  4. backend_token.txt nie committen (steht in .gitignore)
  5. deploy/.env nie committen (enthaelt Produktions-Secrets)
  6. Immer try/except um History-Logging (darf Response nie blockieren)
  7. Windows PowerShell 5.1 kompatibel bleiben
  8. Signatur-/Profilname-Fallback: Wenn kein expliziter Signaturname gesetzt, wird Profilname verwendet
  9. Benutzerdaten in %APPDATA%\AZA Desktop bei Deinstallation standardmaessig NICHT loeschen
  10. Aus frueheren Briefen wird nur Stil/Struktur gelernt, KEINE Patientendaten/Altinhalte uebernehmen

Korrektur-Patch (FIX-01) 2026-03-19

Sammel-Korrektur-Patch mit folgenden Aenderungen:

  1. Uebersetzer-Label: "Fachuebersetzer" ueberall zu "Uebersetzer" umbenannt (aza_config.py, version.json, CHANGELOG.md, web/index.html, deploy-Docs)
  2. Kommentare-Fenster fertiggestellt: Haekchen "beim Start automatisch oeffnen" (persistent), Live-Update bei KG-Aenderung (auto-refresh nach KG-Erstellung), klickbare Diagnose-Ueberschriften mit Detailfenster
  3. Korrektur-Fenster: Scrollbar fuer Liste der gespeicherten Korrekturen (height=8 statt 4), Korrekturen bleiben bei Benutzerdaten-Behalten erhalten
  4. Stilprofil Live-Anwendung: Bei Profilwechsel/Toggle im Brief-Fenster wird der aktuelle Brief sofort neu generiert (nicht erst beim naechsten Brief). Extrahierte Methode _build_brief_prompt_for_profile() und _regenerate_brief_live()
  5. Profil-anwenden-Button: Im Stilprofil-Verwaltungsdialog neuer gruener Button "Profil anwenden" wendet das gewaehlte Profil sofort auf den aktuellen Brief an
  6. KG direkt im Hauptfenster: make_kg_from_text() schreibt jetzt direkt ins txt_output (via _fill_kg_and_finish), kein separates Popup-Fenster mehr
  7. Persistenz: dokumente_collapsed wird jetzt korrekt geladen/gespeichert in autotext_data
  8. Hauptfenster-Zentrierung: Robuste verzoegerte Zentrierung nach vollstaendigem Widget-Aufbau via self.after(50, _ensure_centered), statt zu fruehem center_window() im init

Nachschaerfungs-Patch (FIX-02) 2026-03-19

  1. Stilprofil-Dialog nur Verwaltung: Im Dialog _open_brief_stilprofil_dialog() wurde die aktive Profilauswahl (Dropdown+Combobox+on_profile_change) entfernt. Dialog zeigt jetzt nur: aktuell aktives Profil als Status, verfuegbare System-/Benutzerprofile als Liste, Lernfunktion fuer neue Profile, Loeschen von Benutzerprofilen. Aktive Auswahl NUR im Arztbrief-Fenster (Haekchen+Dropdown).
  2. Kommentare-Fenster auto-open: _auto_refresh_kommentare() oeffnet jetzt das Kommentare-Fenster automatisch nach KG-Erstellung, wenn kommentare_auto_open=True und das Fenster noch nicht offen ist. Checkbox-Text geaendert zu "Kommentare-Fenster standardmaessig oeffnen (nach KG-Erstellung)".
  3. Logo-Trennung: Wassertropfen-Bild (assets/wassertropfen aza medwork.png) wird zu logo.ico konvertiert fuer EXE-Icon, Desktop-Shortcut, Installer-Icon und Titelleisten-Icon. Originales Logo (assets/logo.png) wird als logo.png im Root fuer internes Branding unten links verwendet. logo.ico in aza_desktop.spec datas aufgenommen fuer Runtime-Zugriff.

Dateien: basis14.py, aza_text_windows_mixin.py, aza_desktop.spec, logo.png, logo.ico

Medikamenten-Detailfenster (FIX-03) 2026-03-20

  1. Klick auf Medikament/Diagnose im Kommentare-Fenster: Oeffnet strukturiertes Detailfenster (zentriert) mit KI-generierter Kurzinfo (Indikation, Nebenwirkungen, Anwendung, Schwangerschaft/Stillzeit, Hinweise).
  2. Quellenauswahl: Dropdown im Detailfenster: compendium.ch (Standard), BASG All-in-One Register, BfArM AMIce. Auswahl persistent in medikament_quelle (autotext_data).
  3. Originalquelle oeffnen: Button "Originalquelle oeffnen" im Detailfenster oeffnet passende Suchseite zur aktiven Quelle im Browser.
  4. Persistenz: medikament_quelle in aza_persistence.py (load/save/default).

Dateien: basis14.py, aza_persistence.py

Diagnose-Detailfenster (FIX-04) 2026-03-20

  1. Getrennte Detail-Logik: Medikamente ([MED]) und Diagnosen ([DX]) haben eigene Detailfenster mit eigenen Prompts, Quellen und Persistenz-Keys.
  2. Diagnose-Quellen: DocCheck Flexikon (Standard bei Deutsch), MSD Manual Patienten (Standard bei anderer Sprache). Persistent in diagnose_quelle.
  3. Medikament-Quellen: compendium.ch / BASG / BfArM (wie bisher). Persistent in medikament_quelle.
  4. KI-Kommentare: Prompt erzeugt [DX]/[MED]-Tags pro Ueberschrift. _apply_kommentare erkennt Tags und leitet an _show_dx_detail bzw _show_med_detail weiter.
  5. Visuelle Trennung: Medikamente gruen mit Pillen-Icon, Diagnosen blau mit Krankenhaus-Icon.

Dateien: basis14.py, aza_persistence.py

Detailfenster-Nachschaerfung (FIX-05) 2026-03-20

  1. Medikamenten-Prompt: Dosierung jetzt mit konkreter Standarddosierung fuer Erwachsene (z.B. "100 mg s.c. Woche 0 und 4, dann alle 8 Wochen"). Explizite Anweisung, nicht "gemaess aerztlicher Anweisung" zu schreiben. Zielgruppe: Fachpersonal.
  2. Diagnose-Prompt: Ebenfalls fuer Fachpersonal optimiert, konsistente Abschnittsueberschriften.
  3. Klickbare Abschnitte: Abschnittsueberschriften in Med- und Dx-Detailfenstern sind blau, fett, unterstrichen und klickbar. Klick oeffnet die aktuell gewaehlte Originalquelle (compendium.ch/BASG/BfArM bzw. DocCheck/MSD).
  4. Erkennungslogik: Ueberschriften werden anhand bekannter Headings-Liste erkannt (_DETAIL_SECTION_HEADINGS_MED / _DX), mit Umlaut-Normalisierung.
  5. Hint-Label: Kleiner Hinweistext unter dem Quellen-Dropdown informiert ueber Klickbarkeit.

Dateien: basis14.py

Qualitaets- und Sicherheits-Fixblock (FIX-06) 2026-03-20

1. Keine Fantasie-Medikamente

  • Kommentar-Generator-Prompt verschaerft: NUR real existierende Medikamente als [MED] taggen.
  • Medikamenten-Detail-Prompt: Obligatorische Sicherheitspruefung VOR Fachinfo-Generierung. Falls kein reales Medikament erkannt: "KEIN MEDIKAMENT ERKANNT" statt halluzinierter Fachinfos. Bei Tippfehlern: "NICHT EINDEUTIG Meinten Sie evtl. [Name]?" ohne Fachinfos.

2. Korrektur-Fenster UX

  • Hint-Label: "Doppelklick auf Wort im Text = Feld Falsch wird befuellt"
  • Felder mit groesserer Schrift und fetter Beschriftung
  • Gruener "Uebernehmen"-Button

3. Audionotiz-Stabilitaetsfix

  • Root Cause: DiktatApp(tk.Tk) erzeugte zweite Tk-Instanz in Daemon-Thread → Crashes.
  • Fix: Toplevel statt Tk im eingebetteten Modus (_as_toplevel_of parameter).
  • Recorder-Referenz Race-Condition behoben. Fehlerbehandlung abgesichert.

4. Resize-Griff fuer alle Toplevel-Fenster

add_resize_grip() zu: Kommentare, News, Fachgebiet, Arztzeugnis, KI-Einwilligung, KG-Vorlage, Med/Dx-Detail, Registrierung.

Dateien: basis14.py, apps/diktat/diktat_app.py

Status: Code umgesetzt, Build erstellt. Verifikation im installierten Build steht noch aus.

Nachschaerfungs-Fixblock (FIX-07) 2026-03-20

1. Resize-Grip Root Cause Fix

  • Root Cause: grip.place() wurde von pack/grid-Inhalten ueberdeckt (Z-Order-Problem).
  • Fix: grip.lift() + wiederholte after()-Aufrufe, um den Grip garantiert ueber allen Inhalten anzuzeigen. Cursor auf size_nw_se geaendert.
  • Datei: aza_ui_helpers.py → add_resize_grip()

2. Korrekturfenster Sichtbare Falsch/Richtig-Felder

  • Neuer korr_frame (blauer Rahmen) direkt OBERHALB der gespeicherten Korrekturen-Liste.
  • Enthalt: "Falsch:" (rot) + Eingabefeld, "Richtig:" (gruen) + Eingabefeld, "Uebernehmen"-Button.
  • Hint-Text: "Doppelklick auf ein Wort oben befuellt 'Falsch' automatisch."
  • Alter doppelter bottom_add-Block mit Feldern entfernt.
  • Datei: basis14.py
  • Root Cause: DocCheck Flexikon URL verwendete ?q= (falscher Parameter). DocCheck basiert auf MediaWiki → korrekter Parameter ist ?search=.
  • Fix: URL geaendert zu Spezial:Suche?search={q}&go=Seite (versucht zuerst Direktartikel, dann Suchergebnis).
  • Datei: basis14.py → _DX_QUELLEN

4. Medikamenten-Kurzvorschau Zentrale Validierung VOR Anzeige (FIX-08)

  • Root Cause: Die Kommentar-Generierung lief als EINZELNER AI-Call:
    1. GPT-4o-mini erzeugte [MED] Dermowartecreme MIT halluziniertem Kurztext
    2. _apply_kommentare() zeigte diesen Text 1:1 an
    3. Validierung existierte NUR im ZWEITEN AI-Call des Detailfensters
    4. Ergebnis: Kurzansicht halluzinierte, Detailfenster sagte "KEIN MEDIKAMENT ERKANNT"
  • Loesung (deterministisch, nicht prompt-basiert):
    • Neue Datei aza_med_validator.py mit ~300 realen Medikamenten/Wirkstoffen (DACH-Raum)
    • validate_medication_name(name) prueft gegen diese Liste (exakt + difflib.get_close_matches())
    • Wird in _apply_kommentare() fuer JEDEN [MED]-Eintrag VORHER aufgerufen
    • Ergebnis:
      • Sicher erkannt → normale Anzeige + echte Fachinfo
      • Nicht erkannt, aber Kandidat gefunden → ⚠ grau + "Meinten Sie evtl. X?" + klickbarer [Uebernehmen]-Link
      • Nicht erkannt, kein Kandidat → ⚠ grau + "Kein sicher erkanntes Medikament."
    • AI-generierte Kurzinfo wird bei nicht-erkannten Medikamenten komplett unterdrueckt (skip_until_next_heading)
    • _accept_med_candidate() ersetzt den Namen im AI-Text und re-rendert
  • Dateien: aza_med_validator.py (NEU), basis14.py, aza_desktop.spec

Status: Code nachgeschaerft, Build + Installer erstellt (2026-03-20 17:52). Manuelle Verifikation im installierten Build erforderlich. SHA256: 27EB38F60965F23C4C2526D47BB4418306AB5ED4F2CB01910CA18D770D2EF2AB

  • Root Cause (FIX-09): LLM generierte Medikamenten-Infos rein aus Modellwissen.
  • Root Cause (FIX-10): System blieb auf Wirkstoff-Ebene haengen. PharmaWiki-Regex falsch, Compendium SPA nicht scrapbar.
  • Root Cause (FIX-11): Inhaltsquelle und Originallink waren im Code vermischt. Ein Dropdown steuerte beides.
  • Loesung (FIX-11, 2026-03-22) Saubere Trennung:
    • INHALTSQUELLE (was im Detailfenster angezeigt wird):
      • _fetch_doccheck_info(med_name): DocCheck Flexikon (Standard)
      • _fetch_pharmawiki_info(med_name): PharmaWiki (Fallback)
      • Benutzerwaehlbar ueber Dropdown "Inhaltsquelle:" im Detailfenster
      • Persistent gespeichert als med_content_quelle in _autotext_data
      • Neues Dict _MED_CONTENT_QUELLEN (DocCheck, PharmaWiki)
    • ORIGINALQUELLE (externer Link / "Originalquelle oeffnen"):
      • CH = Compendium, AT = BASG, DE = BfArM UNVERAENDERT
      • Weiterhin ueber _MED_QUELLEN / medikament_quelle
    • Kuratierte Fakten _MEDICATION_FACTS als Offline-Fallback
  • Therapien/Prozeduren weiterhin getrennt mit DocCheck/PharmaWiki
  • Kandidatenlogik (Dermowarte→Dermovate, Vilastin→Bilastin) unberuehrt
  • Dateien: basis14.py

Medikamenten-Quellenlogik Schweiz Zielarchitektur (ARCH-MED)

Status: Erste Stufe umgesetzt (2026-03-22). Compendium Produkt-Aufloesung + PharmaWiki Quelltext-Extraktion live.

Aktueller Stand (teilweise umgesetzt):

  • Compendium.ch Produkt-Aufloesung: Wirkstoff → konkreter Praeparat-Name + Darreichungsform
  • PharmaWiki Quelltext-Extraktion: Strukturierte Sektionen fuer Prompt-Injektion
  • Kuratierte Faktenliste _MEDICATION_FACTS (~18 Medikamente) als Offline-Fallback

Endziel fuer Schweizer Modus: AZA soll Medikamenteninformationen fuer die Schweiz grundsaetzlich ueber Compendium.ch nachschlagen koennen nicht nur ueber eine kleine interne Faktenliste, nicht nur Link-Weiterleitung, nicht nur LLM-Wissen.

Zielarchitektur:

  1. Medikament im KG-Text erkennen (bestehendes Tagging + Validierung)
  2. In Compendium.ch suchen (echte Suche, nicht nur Link) UMGESETZT
  3. Konkreten Produkt-/Praeparattreffer bestimmen UMGESETZT (Name + Darreichungsform)
  4. Relevante Fach-/Produktinfo strukturiert auswerten UMGESETZT via PharmaWiki, Compendium-Detailseite noch offen
  5. Kommentarinfo NUR aus diesen quellenbasierten Daten bauen UMGESETZT
  6. Was nicht aus der Quelle kommt → weglassen, nicht erfinden UMGESETZT

Abdeckung:

  • PharmaWiki-Fetch deckt grundsaetzlich alle dort verfuegbaren Medikamente ab
  • Compendium Produkt-Aufloesung liefert konkreten Praeparat-Namen (abhaengig von Compendium-HTML-Struktur)
  • Lokale Faktenliste bleibt als Offline-Fallback

Naechste Schritte (ARCH-MED-01/02):

  1. Compendium-Detailseiten-Extraktion evaluieren (zusaetzlich zu Produkt-Aufloesung)
  2. Caching-Strategie festlegen (PharmaWiki-/Compendium-Antworten lokal cachen)
  3. Robustheit gegen HTML-Strukturaenderungen absichern
  4. Langfristig: HCI Solutions Datenlizenz / Compendium-API evaluieren

Spaetere Marktprofile:

  • DE: BfArM / Gelbe Liste separat
  • AT: BASG separat
  • Jeweils eigenstaendig, nicht mit CH vermischen

Zukunftsblock Internationalisierung / Laender- und Quellenprofile (GEPARKT)

Status: Zukunftsthema NICHT fuer jetzt. Erst nach DACH-Stabilitaet und Produkterfolg.

Voraussetzung: DACH-Markt (Schweiz / Deutschland / Oesterreich) sauber stabilisiert, Go-Live gesichert, Produkt erfolgreich.

Zielbild:

  • UI je nach Markt/Sprache anpassbar
  • Medikamentenquellen je nach Land/Sprache anpassbar
  • Diagnose-/Therapiequellen je nach Land/Sprache anpassbar
  • Beispiel: DACH zuerst, spaeter franzoesische UI + franzoesische medizinische Quellen/Links

Profil-Architektur (spaeter umsetzen):

  • app_language UI-Sprache
  • market_region Zielmarkt/Land
  • med_source_profile Medikamentenquellen (Compendium, BASG, BfArM, …)
  • dx_source_profile Diagnosequellen (DocCheck, MSD, …)
  • therapy_source_profile Therapiequellen
  • Manueller Override durch Benutzer/Praxis

Wichtig:

  • Nicht hart nach Herkunftsland des Users schalten, sondern saubere Profil-Logik
  • Handelsnamen, Zulassungen, Fachinfos und Verfuegbarkeit sind laenderspezifisch
  • Deshalb spaeter Quellenprofile pro Markt statt Einheitslogik
  • Kein aktueller Implementierungsblock reines Roadmap-Thema

Status: Build + Installer erstellt (2026-03-22 22:14). Manuelle Verifikation im installierten Build empfohlen. SHA256: ABC12791E0DB8472C78E673EC57D416A796E4B5534FF39D2B7A76B8E94B10C0E

Aktivierungsschluessel → Lizenzmodus Bridge (2026-03-24)

Root Cause: Zwei unabhaengige Gating-Systeme im Desktop-Build:

  1. Aktivierungsschluessel (aza_activation.py): Kontrolliert ob App STARTET (Trial oder AZA-Key)
  2. Subscription-Lizenz (check_license_status): Kontrolliert ob DEMO- oder VOLL-Modus

Diese waren NICHT verbunden. Ein zahlender Kunde mit gueltigem AZA-Key lief trotzdem im DEMO-Modus, weil die Subscription-Lizenzpruefung mangels MEDWORK_BACKEND_URL immer fehlschlug.

Fix: In KGDesktopApp.init (basis14.py): Nach check_license_status() wird geprueft, ob ein gueltiger Aktivierungsschluessel vorhanden ist. Falls ja und license_mode noch "demo" → auf "active" setzen.

Auswirkung: ~10 Zeilen, kein Monsterpatch. /license/status unberuehrt. Keine Auth-Aenderung. Erster Kundenweg damit praktikabel: Entwickler generiert Key, sendet per E-Mail, Kunde gibt ein → Vollmodus.

Entschaerfender Faktor: DEMO_MAX_DICTATIONS=9999 (Demo-Modus ist de facto unbeschraenkt). Die Bridge ist trotzdem korrekt, weil DEMO_MAX_DICTATIONS spaeter gesenkt werden soll.

Datei: basis14.py (KGDesktopApp.init, nach self.check_license_status())

Windows Code-Signing / Smart App Control Readiness (2026-03-23)

Problem: Windows Smart App Control (ab Windows 11 22H2) blockiert unsignierte und unbekannte Anwendungen automatisch. Auch ohne Smart App Control zeigt SmartScreen Warnungen bei unsignierten Downloads. Fuer Kundenauslieferung muessen alle ausfuehrbaren Artefakte signiert werden.

Status: Signing-Readiness vorbereitet, noch NICHT produktiv aktiviert (kein Zertifikat vorhanden).

Vorbereitete Dateien:

  • sign_release.ps1 Signing-Skript (signiert EXE, DLLs/PYDs, Installer; DryRun-Modus; Verifikation)
  • build_and_test_release.ps1 Release-Pipeline mit optionalem Signing-Schritt (graceful skip ohne Zertifikat)
  • build_release_artifacts.ps1 Artefakt-Report enthaelt jetzt signing_status und signing_subject
  • SIGNING_READINESS.md Vollstaendige Dokumentation mit Artefakt-Liste, Signing-Reihenfolge, Zertifikats-Optionen, Checkliste

Artefakte die signiert werden muessen:

Prioritaet Artefakt Pfad
Kritisch Haupt-EXE dist\aza_desktop\aza_desktop.exe
Kritisch Installer dist\installer\aza_desktop_setup.exe
Empfohlen DLLs dist\aza_desktop\_internal\*.dll
Empfohlen PYDs dist\aza_desktop\_internal\*.pyd

Signing-Reihenfolge in der Pipeline:

Desktop Build → DLLs/PYDs signieren → EXE signieren → Installer Build → Installer signieren → Artefakt-Report → Publish

Noch offen vor Kundenauslieferung:

  1. EV Code-Signing-Zertifikat beschaffen (empfohlen: DigiCert/Sectigo, ca. CHF 400600/Jahr; alternativ Azure Trusted Signing)
  2. signtool.exe installieren (Windows SDK)
  3. Publisher-Name im Zertifikat mit AppPublisher in aza_installer.iss abstimmen (aktuell: AZA MedWork)
  4. sign_release.ps1 produktiv ausfuehren
  5. Signierte Artefakte auf sauberem Windows-PC mit aktivem Smart App Control testen

Publisher-/Namenskonsistenz (Analyse 2026-03-23):

Im Projekt existieren 3 verschiedene Namensformen. Dies ist KEINE Inkonsistenz jede Form hat eine klare Rolle:

Namensform Rolle Signing-relevant Stellen
AZA MedWork Firma / Publisher JA signing-kritisch aza_installer.iss, legal/privacy_policy.md, legal/ai_consent.md, deploy/WOOCOMMERCE_PRODUCT.md, deploy/WORDPRESS_GOLIVE.md
AZA Desktop Produktname Nein aza_config.py, CHANGELOG.md, web/download.html, tools/aza_clean_uninstall.ps1, translate.py, build_exe.ps1, deploy/PRODUCT_V1.md
AZA Medical AI Assistant Interner Projektname Nein project_status.json, project_status_routes.py, web/index.html, billing/invoice_template.json, billing/BILLING_FLOW.md

Vor Zertifikatskauf zu klaeren:

  1. Offiziellen Firmennamen im Handelsregister pruefen
  2. EV-Zertifikats-Subject muss exakt mit HR-Name uebereinstimmen
  3. AppPublisher in aza_installer.iss auf Zertifikats-Subject abstimmen
  4. Falls HR-Name von "AZA MedWork" abweicht: alle signing-relevanten Stellen gemeinsam anpassen
  5. SmartScreen-Reputation baut auf Publisher-Namen auf nach Festlegung NICHT mehr aendern

Stellen die bei Namensaenderung gemeinsam angepasst werden muessen:

  • installer/aza_installer.issMyAppPublisher
  • legal/privacy_policy.md → Zeile 5 + Zeile 27
  • legal/ai_consent.md → Zeile 10, 12, 132
  • deploy/WOOCOMMERCE_PRODUCT.md → Absendername
  • deploy/WORDPRESS_GOLIVE.md → Absendername
  • SIGNING_READINESS.md → Beispielname
  • apps/diktat/diktat_app.py → Docstring
  • aza_consent.py → Docstring

Stellen die NICHT angepasst werden muessen (nicht signing-relevant):

  • project_status.json ("AZA Medical AI Assistant" ist interner Projektname)
  • project_status_routes.py (API-Response, intern)
  • billing/invoice_template.json (Rechnungsposition, kann abweichen)
  • web/index.html, web/download.html (Marketing-Langname)

Do-Not-Break:

  • Keine echten Zertifikate oder Secrets ins Repository committen
  • Signing-Schritt ist optional (Pipeline laeuft auch ohne Zertifikat durch)
  • Keine Pseudo-Signierung oder Fake-Zertifikate
  • Publisher-Name nach Festlegung NICHT mehr wechseln