"description":"Desktop → Hetzner → OpenAI erfolgreich in der echten App getestet. basis14.py lokal gegen Live-Backend gestartet. Kein lokaler OpenAI-Key noetig. Chat-/Textpfad funktioniert ueber Hetzner-Backend. Variante B produktiv nachgewiesen."
"description":"Lizenz aktiv solange Subscription bezahlt ist. Rueckfall auf Testmodus / eingeschraenkten Modus bei Kuendigung/Nichtzahlung. App-/Lizenzstatus sauber pruefen. /license/status-Struktur NICHT kaputtmachen. Keine vorschnellen Auth-/API-Contract-Aenderungen."
"description":"Echter Live-Testkauf durchgefuehrt und sauber neutralisiert. Subscription initial active, danach storniert + Zahlung refundiert. license_debug zeigt korrekt canceled. Drei Bugs in stripe_routes.py gepatcht: (A) _upsert_license COALESCE-Fix gegen customer_email-Verlust, (B) cancel_at_period_end-Erkennung in Webhook, (C) sync_subscription robuster (optional subscription_id, nicht nur active). DB-Backup: stripe_webhook.sqlite.before_email_fix. Stripe-/Webhook-/Live-Pfad technisch bewiesen."
"title":"ERLEDIGT: Desktop-Lizenzpfad gegen Live-Backend validiert (2026-03-30)",
"status":"erledigt",
"description":"Desktop respektiert canceled-Status korrekt und faellt auf Testmodus zurueck. Kompletter Lizenz-Lifecycle nachgewiesen: Kauf → active → Storno/Refund → canceled → Desktop-Testmodus. check_license_status() in basis14.py, compute_license_decision() in aza_license_logic.py funktionieren korrekt."
},
{
"id":"LIVE-KAUF-01",
"priority":"ERLEDIGT",
"group":"Lizenz-/Subscription-Lifecycle",
"area":"Billing / Desktop / Lizenz",
"title":"ERLEDIGT: Echter Live-Kauf CHF 59 + Desktop Vollmodus (2026-03-30)",
"status":"erledigt",
"description":"Echter Live-Kauf Basic Monthly (CHF 59) erfolgreich. Backend-Lizenz active fuer admin@aza-medwork.ch. Desktop startet ohne Testfenster und im Vollmodus. current_period_end korrekt gesetzt (1777652509)."
"description":"Root Cause: Lokales Aktivierungs-Gate (_show_activation_gate) pruefte Aktivierungsschluessel/Trial vor Backend-Lizenzcheck. Fix: _has_remote_backend() erkennt nicht-localhost Backend. Bei Remote-Backend wird lokales Gate komplett uebersprungen. Backend-Lizenzstatus allein fuehrend. Datei: basis14.py."
},
{
"id":"LIVE-KAUF-03",
"priority":"ERLEDIGT",
"group":"Lizenz-/Subscription-Lifecycle",
"area":"Backend / Webhook",
"title":"ERLEDIGT: current_period_end-Fallback in Webhook (2026-03-30)",
"status":"erledigt",
"description":"Root Cause: checkout.session.completed und subscription.updated/deleted Webhook-Handler hatten keinen Fallback auf items.data[0].current_period_end. Fix: Fallback-Extraktion ergaenzt. Bestehende null-Daten via sync_subscription repariert. current_period_end jetzt 1777652509. Datei: stripe_routes.py."
},
{
"id":"BETREIBER-01",
"priority":"ERLEDIGT",
"group":"Ops / Admin-Monitor",
"area":"Backend / Ops",
"title":"ERLEDIGT: Betreiber-Kontrolle mit Einzelposten (2026-03-31)",
"status":"erledigt",
"description":"Root Cause 16: revenue_overview zeigte nur Summen, keine Einzelposten. Fix: recent_charges und recent_refunds Listen in revenue_overview ergaenzt. Bewiesen: recent_charges zeigt 59.0 CHF fuer admin@aza-medwork.ch, recent_refunds zeigt 59.0 CHF. Datei: admin_routes.py."
},
{
"id":"SEC-TOKEN-01",
"priority":"HOCH",
"group":"Sicherheit",
"area":"Ops / Security",
"title":"Admin-Token-Rotation (Token im Chat offengelegt)",
"description":"AZA_ADMIN_TOKEN wurde in einem Chat-Verlauf sichtbar. Chat loeschen rotiert den Token NICHT. Vor produktivem Kundenbetrieb rotieren: (1) Neuen Token generieren, (2) In /root/aza-app/deploy/.env setzen, (3) docker compose up -d --build --force-recreate aza-api. Mini-Block, kein Code noetig."
},
{
"id":"ADMIN-V1",
"priority":"ERLEDIGT",
"group":"Ops / Admin-Monitor",
"area":"Backend / Ops",
"title":"ERLEDIGT: Admin Monitor v1 live (2026-03-30)",
"status":"erledigt",
"description":"Interne Admin-Endpunkte live und durch X-Admin-Token / AZA_ADMIN_TOKEN geschuetzt. Endpunkte: GET /admin/system_status, GET /admin/licenses_overview, GET /admin/backup_status, GET /admin/billing_overview. Datei: admin_routes.py, eingebunden in backend_main.py mit prefix=/admin."
},
{
"id":"ADMIN-V2",
"priority":"ERLEDIGT",
"group":"Ops / Admin-Monitor",
"area":"Backend / Ops",
"title":"ERLEDIGT: Control Panel v2 live (2026-03-30)",
"status":"erledigt",
"description":"Erweiterte Admin-Endpunkte: GET /admin/license_customer_map (Lizenznehmer-Uebersicht), GET /admin/revenue_overview (Umsatz/Refunds), GET /admin/alerts (Warn-/Ampelliste), GET /admin/dashboard_summary (Sammel-Endpunkt). Nachweislich funktionierend: revenue_overview zeigt 59 CHF gross / 59 CHF refund / 0 CHF net fuer 2026-03. alerts und dashboard_summary funktional."
},
{
"id":"BACKUP-MON",
"priority":"ERLEDIGT",
"group":"Ops / Backup",
"area":"Ops / Hetzner",
"title":"ERLEDIGT: Backup/Storage-Monitor aktiv (2026-03-30)",
"status":"erledigt",
"description":"Taegliches Backup-Skript eingerichtet (/root/aza-backups/backup_aza.sh, Cronjob). /host_backups read-only in Container gemountet. backup_status erkennt Backups korrekt. Ca. 137 GB frei, ca. 4-5% belegt. Kein akuter Speicherdruck."
"description":"Kritischer Bruch behoben: Gueltiger AZA-Aktivierungsschluessel setzt jetzt license_mode=active (Vollmodus), nicht nur Start-Erlaubnis. Damit ist der manuelle erste Kundenweg praktikabel: Entwickler generiert Key, sendet per E-Mail, Kunde gibt ein, App laeuft voll. Datei: basis14.py."
},
{
"id":"FB-B",
"priority":"HOCH",
"group":"Fokusblock B – Kritische Restfehler",
"area":"Desktop / Bugfix",
"title":"Kritische Desktop-Restfehler nur gezielt und einzeln behandeln",
"status":"offen",
"description":"Keine neuen Monsterpatches. Root-cause-first. Installierten Build hoeher gewichten als Code-Behauptungen. Nur Blocker fuer den Kundenweg."
"description":"Update-Komfort / separater Updater ist NICHT aktuelle Prioritaet. Kein aktueller Hauptblock. Erst nach stabilem Kauf-/Download-/Installationspfad."
},
{
"id":"A-01",
"priority":"SOFORT",
"group":"A – Go-Live extern",
"area":"Ops",
"title":"Hostpoint-Website stabil lassen",
"status":"in_progress",
"description":"Keine riskanten Domain-/DNS-Experimente. Bestehende WordPress/Kadence-Seite bleibt Haupt-Website auf Hostpoint."
"description":"Installer herunterladen, installieren, Aktivierung, Lizenzpruefung, Backend-Anbindung – alles End-to-End."
},
{
"id":"BRAND-01",
"priority":"HOCH",
"group":"Branding / Produktname",
"area":"Product / Marketing",
"title":"Produktname AZA Office final entscheiden (vor Go-Live)",
"status":"in_arbeit",
"description":"AKTUELLE RICHTUNG: AZA Office. Favorit-Langform: 'AZA Office – Ihr medizinischer KI-Arbeitsplatz fuer die Praxis'. Zweite gute Variante: 'AZA Office – Die KI-Assistenz fuer medizinische Dokumentation'. Noch nicht zwingend final juristisch/brand-strategisch entschieden, aber bevorzugte Naming-Richtung fuer WooCommerce/Website/Download/Go-Live. Fruehere Shortlist (AZA Desktop) bleibt dokumentiert in project_roadmap.json und project_plan.json."
},
{
"id":"B-01",
"priority":"HOCH",
"group":"B – Verkauf / Subscription",
"area":"Product",
"title":"Subscription in Website/Checkout konsistent abbilden",
"description":"Signing-Readiness vorbereitet: sign_release.ps1 erstellt, Release-Pipeline mit optionalem Signing-Schritt (build_and_test_release.ps1), Artefakt-Report mit Signatur-Status (build_release_artifacts.ps1), SIGNING_READINESS.md mit Checkliste. OFFEN: Echtes EV Code-Signing-Zertifikat beschaffen, signtool.exe auf Build-Rechner installieren, produktiver Signierlauf durchfuehren, Publisher-Name im Zertifikat mit AppPublisher in aza_installer.iss abstimmen."
},
{
"id":"C-04",
"priority":"HOCH",
"group":"C – Download-Produkt",
"area":"Release / Security",
"title":"Code-Signing vor Kundenauslieferung aktivieren",
"status":"offen",
"description":"VOR erster Kundenauslieferung verpflichtend: (1) Offiziellen Firmennamen im Handelsregister pruefen (EV-Validierung prueft HR-Eintrag). (2) EV Code-Signing-Zertifikat beschaffen (DigiCert/Sectigo empfohlen, alternativ Azure Trusted Signing). (3) signtool.exe installieren (Windows SDK). (4) AppPublisher in aza_installer.iss auf exakten Zertifikats-Subject abstimmen (aktuell 'AZA MedWork'). (5) Falls HR-Name abweicht: auch legal/privacy_policy.md, legal/ai_consent.md, deploy/WOOCOMMERCE_PRODUCT.md (Absendername), deploy/WORDPRESS_GOLIVE.md gemeinsam anpassen. (6) sign_release.ps1 produktiv ausfuehren. (7) Signierte Artefakte auf Windows-PC mit Smart App Control testen. (8) Publisher-Name nach Festlegung NICHT mehr aendern (Reputation). Grund: Windows Smart App Control blockiert unsignierte/unbekannte Apps bei Kunden."
},
{
"id":"C-05",
"priority":"HOCH",
"group":"C – Download-Produkt",
"area":"Release / Legal",
"title":"Publisher-/Firmenname final festlegen (vor Zertifikatskauf)",
"status":"offen",
"description":"Vor Zertifikatskauf: (1) Offiziellen Firmennamen im Handelsregister pruefen. (2) Entscheiden ob Signing-Publisher 'AZA MedWork', 'AZA MedWork GmbH' oder anders lauten soll. (3) AppPublisher in aza_installer.iss anpassen falls noetig. (4) Alle signing-relevanten Stellen gemeinsam aktualisieren: aza_installer.iss, legal/privacy_policy.md, legal/ai_consent.md, deploy/WOOCOMMERCE_PRODUCT.md, deploy/WORDPRESS_GOLIVE.md. (5) Nicht-signing-relevante Stellen (project_status.json 'AZA Medical AI Assistant', billing/invoice_template.json) koennen unabhaengig bleiben. Analyse: Aktuell 3 Namensformen im Projekt – 'AZA MedWork' (Firma/Publisher), 'AZA Desktop' (Produkt), 'AZA Medical AI Assistant' (interner Projektname). Nur 'AZA MedWork' ist signing-kritisch."
"title":"ERLEDIGT: Admin Control Panel v2 live (2026-03-30)",
"status":"erledigt",
"description":"Admin Monitor v1 + Control Panel v2 in admin_routes.py. 8 Endpunkte. Geschuetzt via X-Admin-Token / AZA_ADMIN_TOKEN. Weitere Support-Workflows und Nutzer-Management spaeter bei Bedarf."
"title":"ERLEDIGT: Serverseitige OpenAI-Architektur Variante B produktiv (2026-03-26)",
"status":"erledigt",
"description":"VERBINDLICHE ENTSCHEIDUNG (2026-03-25) UMGESETZT: OpenAI-Key AUSSCHLIESSLICH serverseitig auf Hetzner. Hetzner-Backend live unter api.aza-medwork.ch. POST /v1/chat, Caddy/HTTPS, serverseitiger OpenAI-Zugriff nachgewiesen. Verbleibend: Desktop-Client auf Live-Backend umstellen."
"title":"ERLEDIGT: Migrationspfad umgesetzt – Key-Dialog bei Remote-Backend unterdrueckt",
"status":"erledigt",
"description":"UMGESETZT (2026-03-27): Key-Setup-Dialog wird bei konfiguriertem Remote-Backend unterdrueckt. ensure_ready() akzeptiert Remote-Backend als ready. Lokaler Key bleibt als Dev-Fallback. Produktivauslieferung hat keinen Key-Setup-Dialog wenn backend_url.txt auf Live-Backend zeigt."
"group":"Architektur – OpenAI-Key (VARIANTE B VERBINDLICH)",
"area":"Security",
"title":"GESPERRT: Keine Keys hardcoden, keinen Shared-Key, keine halben Loesungen",
"status":"gesperrt",
"description":"VERBINDLICHE SPERRUNG: NIEMALS OpenAI-Key hardcoded in die App. NIEMALS Shared-Key ausliefern. KEINE halben Uebergangsloesung fuer Kunden. KEINE Shared-Key-Bastelei in der App. Secrets NIEMALS loggen. /license/status nicht leichtfertig kaputtpatchen."
},
{
"id":"LOCK-01",
"priority":"GESPERRT",
"group":"Gesperrte Entscheidungen",
"area":"Audio / Aufnahme",
"title":"Audioaufnahme IMMER als M4A – NICHT AENDERN",
"status":"gesperrt",
"description":"ENDGUELTIGE ENTSCHEIDUNG: Audioaufnahme erfolgt direkt als M4A (AAC 64kbps via ffmpeg stdin-Pipe). KEIN WAV-Zwischenschritt. WAV nur als Fallback wenn ffmpeg fehlt. Diese Regel wurde bereits einmal faelschlich gebrochen und darf NIEMALS wieder geaendert werden. Jede Aenderung an aza_audio.py muss diese Regel respektieren."
"title":"Pruefen: Schweizer Hosting / Datenstandort",
"status":"offen",
"description":"Sicherstellen, dass Gesundheitsdaten in der Schweiz oder einem aequivalent geschuetzten Rechtsraum gehostet werden. Hetzner-Standort pruefen."
"title":"Keine ueberzogenen Aussenbehauptungen ohne Zertifizierung",
"status":"offen",
"description":"REGEL: Keine Marketing- oder Produktbehauptungen zu HIN-Zertifizierung, ISO-Zertifizierung oder EPD-Integration, solange diese nicht tatsaechlich vorliegen. Intern als Zielbild fuehren, extern nur als Orientierung kommunizieren."
},
{
"id":"DX-01",
"priority":"ERLEDIGT",
"group":"Desktop UX / Persistence",
"area":"Desktop / Installer",
"title":"Benutzerdaten bei Deinstallation erhalten",
"status":"erledigt",
"description":"Inno Setup fragt bei Deinstallation ob Benutzerdaten (%APPDATA%\\AZA Desktop) geloescht werden sollen. Standard: Nein. Daten bleiben bei Neuinstallation erhalten."
},
{
"id":"DX-02",
"priority":"ERLEDIGT",
"group":"Desktop UX / Persistence",
"area":"Desktop / UX",
"title":"Signaturlogik: Profilname als Fallback",
"status":"erledigt",
"description":"load_signature_name() faellt automatisch auf den Profilnamen zurueck wenn kein expliziter Signaturname gesetzt ist. Wirkt in Briefen, Rezepten, KoGu, OP-Berichten."
},
{
"id":"DX-03",
"priority":"ERLEDIGT",
"group":"Desktop UX / Persistence",
"area":"Desktop / UX",
"title":"Rechtsklick-Haekchen im Minifenster",
"status":"erledigt",
"description":"Im minimierten Hauptfenster dieselbe Option 'Rechtsklick = Einfuegen' wie im Vollbild. Gleiche Variable, synchronisiert, sofort wirksam."
},
{
"id":"DX-04",
"priority":"ERLEDIGT",
"group":"Desktop UX / Persistence",
"area":"Desktop / UX / KI",
"title":"Kommentare-Fenster (fertiggestellt)",
"status":"erledigt",
"description":"Vollstaendig umgesetzt: Button 'Kommentare' in Toolbar, separates Fenster, KI-Kurzkommentare via GPT, manuelles Aktualisieren, Live-Aktualisierung bei KG-Aenderung, automatisches Oeffnen nach KG-Erstellung wenn Haekchen aktiv, klickbare Diagnose-Kommentare mit Detailfenster, Tag-basiertes Highlighting."
},
{
"id":"DX-05",
"priority":"ERLEDIGT",
"group":"Desktop UX / Persistence",
"area":"Desktop / Bugfix",
"title":"Autotext Root-Cause-Fix",
"status":"erledigt",
"description":"Root Cause: _is_admin NameError verhinderte Oeffnen des Autotext-Dialogs im installierten Build. Listener-Architektur auf bewaehrten Stand (Kopie 13) zurueckgesetzt. Prozess-basierter Fokus-Check entfernt zugunsten des einfacheren FocusIn/FocusOut-Mechanismus."
},
{
"id":"DX-06",
"priority":"ERLEDIGT",
"group":"Desktop UX / Persistence",
"area":"Desktop / UX",
"title":"Signatur-UI: Haekchen + abweichender Signaturname in Einstellungen",
"status":"erledigt",
"description":"Einstellungsdialog: Haekchen 'Profilname verwenden' + Feld fuer abweichenden Signaturnamen. Wenn Haekchen aktiv: Profilname. Wenn Haekchen aus + Name: diesen verwenden. Persistenz via kg_diktat_signature.txt."
"title":"Briefstil-Lernen: Integration in Briefgenerierung",
"status":"erledigt",
"description":"Aktives Stilprofil wird VOR der Briefgenerierung als Stil-Anweisung in den System-Prompt injiziert. Klare Abgrenzung: nur Stil/Struktur, KEINE Patientendaten/Altinhalte. Reihenfolge: Stilprofil → Briefvorlage → Generierung."
"description":"OFFEN: (a) Erweiterte Stilanalyse mit strukturiertem JSON statt Freitext, (b) Mehrere Profile gleichzeitig vergleichen, (c) Stilprofil-Vorschau/Zusammenfassung im Dialog, (d) Weitere Dateiformate (PDF, RTF), (e) Anonymisierungs-Pipeline fuer Trainingsinput."
},
{
"id":"PCP-01",
"priority":"ERLEDIGT",
"group":"Persistenz / Consent / Profil",
"area":"Desktop / UX / Consent",
"title":"KI-Einwilligung beim Erststart (nicht erst bei Start-Klick)",
"status":"erledigt",
"description":"Consent-Dialog wird direkt nach Fachgebiet-Auswahl im Init-Flow angezeigt, bevor die App normal weiterlaueft. Wenn bereits erteilt, wird nicht erneut gefragt."
},
{
"id":"PCP-02",
"priority":"ERLEDIGT",
"group":"Persistenz / Consent / Profil",
"area":"Desktop / Profil",
"title":"Benutzerprofil um Code (ZSR/GLN) erweitert",
"status":"erledigt",
"description":"Registrierungs- und Profil-Bearbeiten-Dialog enthalten Feld 'Code (ZSR/GLN, optional)'. Persistent in kg_diktat_user_profile.json in %APPDATA%."
},
{
"id":"PCP-03",
"priority":"ERLEDIGT",
"group":"Persistenz / Consent / Profil",
"area":"Desktop / Installer",
"title":"Deinstallations-Frage listet alle Benutzerdaten einzeln auf",
"description":"Einstellung 'kommentare_auto_open' in autotext_data. Haekchen in Einstellungen (LabelFrame 'Startverhalten/Fenster'). Auto-open nach 1000ms wenn aktiv. Persistent."
},
{
"id":"PCP-05",
"priority":"ERLEDIGT",
"group":"Persistenz / Consent / Profil",
"area":"Desktop / UX",
"title":"Einstellungsdialog logisch gruppiert",
"status":"erledigt",
"description":"Startverhalten/Fenster als eigener LabelFrame (Diktat, Audionotiz, Kommentare). Sichtbarkeit, Add-ons, Statusanzeige, Autotext, Signatur, Datenschutz als klare Abschnitte."
"description":"Root Cause: translate.main() wurde im frozen Build in einem Hintergrund-Thread gestartet und erzeugte tk.Tk() – Tkinter ist nicht threadsafe. Fix: translate.py akzeptiert parent-Parameter und erstellt Toplevel statt Tk(). basis14.py ruft translate.main(parent=self) direkt auf dem Main-Thread auf. Kein eigener mainloop() im Embedded-Modus."
},
{
"id":"BRP-01",
"priority":"ERLEDIGT",
"group":"Briefprofile",
"area":"Desktop / KI / Brief",
"title":"KISIM Bericht als vordefiniertes Briefprofil",
"status":"erledigt",
"description":"Festes Briefstrukturprofil: Einleitung mit vidit-Zeile, Abschnitte Diagnose/Allergien/Therapie/Anamnese/Beurteilung/Diagnostik/Procedere, nummerierte Diagnosen mit ICD-10, Schlussformel mit Signatur."
},
{
"id":"BRP-02",
"priority":"ERLEDIGT",
"group":"Briefprofile",
"area":"Desktop / KI / Brief",
"title":"Klinischer Bericht als vordefiniertes Briefprofil",
"status":"erledigt",
"description":"Festes Briefstrukturprofil: Einleitung mit vidit-Zeile, pro Diagnose Untergliederung KLINIK/DIAGNOSTIK/THERAPIE/Aktuell, danach Allergien/Beurteilung/Procedere, Schlussformel mit Signatur."
},
{
"id":"BRP-03",
"priority":"ERLEDIGT",
"group":"Briefprofile",
"area":"Desktop / UX",
"title":"Berichtsprofil-Auswahl im Brief-Fenster",
"status":"erledigt",
"description":"Combobox 'Berichtsprofil' im Brief-Fenster: Standard / KISIM Bericht / Klinischer Bericht. Persistent via active_brief_profile in autotext_data. Bei Auswahl wird das Profil direkt als System-Prompt verwendet, nicht nachtraeglich umgeformt."
"description":"VERBINDLICHE PRODUKTREGEL: 1 aktive Lizenz = 2 gleichzeitig aktive Computer. Dieselbe Kaeufer-Email darf mehrere Lizenzen kaufen. Die erlaubten Geraete addieren sich: 1 Lizenz = 2, 2 Lizenzen = 4, 3 Lizenzen = 6. Backend entscheidet fuehrend. Desktop sendet email + device_id an Backend. Backend liefert mindestens: license_active, allowed_devices, used_devices, device_allowed, reason. Diese Regel in allen kuenftigen Handovern wiederverwenden."
},
{
"id":"UX-DEINSTALL",
"priority":"HOCH",
"group":"Desktop UX / Installer",
"area":"Desktop / Installer / UX",
"title":"Deinstallation: Kein Zwangs-Neustart, Option jetzt/spaeter",
"status":"offen",
"description":"Nach Deinstallation darf AZA keinen sofortigen Zwangs-Neustart ausloesen. Es muss die Option geben: jetzt neu starten / spaeter neu starten. Benutzer entscheidet selbst. Datei: installer/aza_installer.iss oder Inno-Setup-Konfiguration."
"title":"Internationalisierung / Laender- und Quellenprofile",
"status":"geparkt",
"description":"NICHT FUER JETZT. Erst nach DACH-Stabilitaet (CH/DE/AT) und Produkterfolg. Zielbild: (1) UI-Sprache je nach Markt anpassbar (app_language). (2) Medikamentenquellen je nach Land (med_source_profile). (3) Diagnose-/Therapiequellen je nach Land (dx_source_profile, therapy_source_profile). (4) market_region als uebergreifendes Profil. (5) Manueller Override durch Benutzer/Praxis. Nicht hart nach Herkunftsland schalten, sondern saubere Profil-Logik. Handelsnamen, Zulassungen, Fachinfos und Verfuegbarkeit sind laenderspezifisch – deshalb spaeter Quellenprofile pro Markt. Beispiel: DACH zuerst, spaeter franzoesische UI + franzoesische med. Quellen/Links. Relevant erst nach Go-Live und DACH-Erfolg."