Files
aza/AzA march 2026/project_handover.md
2026-04-16 13:32:32 +02:00

28 KiB
Raw Blame History

AZA - Master Handover / Operational Runbook

Working Mode Rules

  • User does not tinker or manually edit files.
  • Always provide 1:1 Composer patches (usually Opus).
  • One step at a time.

CURRENT PROJECT PHASE (2026-03-30)

Phase: Stripe/License Live Path PROVEN + Admin Control Panel v2 LIVE Next Block: WooCommerce/Production Sales Path

STATUS: TECHNICAL FOUNDATION FULLY ESTABLISHED (2026-03-30)

1. Stripe/License Live Path PROVEN:

  • Complete license lifecycle technically proven: Purchase → License active → Cancel/Refund → License canceled → Desktop test mode
  • Real live test purchase executed and cleanly neutralized
  • Desktop correctly respects canceled status and falls back to test mode
  • B1-W1 through B1-W5 all successfully completed
  • Three bugs patched in stripe_routes.py (COALESCE fix, cancel_at_period_end, sync_subscription)

2. Admin Monitor v1 + Control Panel v2 LIVE:

  • 8 internal admin endpoints, protected via X-Admin-Token / AZA_ADMIN_TOKEN
  • v1: system_status, licenses_overview, backup_status, billing_overview
  • v2: license_customer_map, revenue_overview, alerts, dashboard_summary
  • Verified: without token → 401, wrong token → 401, correct token → data

3. Backup/Storage Monitor ACTIVE:

  • Daily backup script configured (/root/aza-backups/backup_aza.sh, cron)
  • /host_backups read-only mounted in container
  • backup_status correctly detects backups
  • ~137 GB free, ~4-5% used no acute storage pressure

4. Solved Root Causes / Lessons Learned (2026-03-27 2026-03-30):

  • Sandbox and live must be strictly separated
  • missing_lookup_key resolved with _lookup_key_from_price fallback
  • Live context in container verified with sk_live_
  • license_debug initially wrong due to old active sandbox row + new canceled live row without customer_email
  • Operative hotfix: DB backup created, canceled row linked with customer_email, old incorrect active record removed

Hetzner Backend is LIVE (2026-03-26)

  • Production API path: https://api.aza-medwork.ch
  • DNS: api.aza-medwork.ch178.104.51.177
  • Repo on Hetzner: /root/aza-app
  • Deploy directory: /root/aza-app/deploy
  • Running services: aza-api + aza-caddy
  • Variant B technically proven end-to-end

ARCHITECTURE DECISION VARIANT B (mandatory, 2026-03-25):

  • NO OpenAI key in the desktop app
  • NO per-customer OpenAI key requirement
  • NO shared OpenAI key client-side
  • Instead: AZA Office talks ONLY to own AZA backend
  • Only the AZA backend talks to OpenAI
  • The OpenAI key resides EXCLUSIVELY server-side
  • NO half-measures, NO shared-key hacks

Successful Proofs (2026-03-26):

  • curl https://api.aza-medwork.ch/health → successful
  • curl -X POST https://api.aza-medwork.ch/v1/chat with valid X-API-Token → success:true, content:OK
  • Proven: Hetzner backend runs, Caddy/HTTPS runs, server-side OpenAI access works, Variant B works end-to-end

Root Causes Solved During Deploy:

  1. Wrong git remote (naswinterthur) was unsuitable
  2. Uploading only deploy/ was wrong docker-compose.yml expects repo root context (context: .., dockerfile: deploy/Dockerfile)
  3. Host nginx blocked port 80
  4. Caddy DNS/ACME issues due to resolver 127.0.0.53 → Fix: explicit DNS 1.1.1.1 + 8.8.8.8 in caddy service

Final Hetzner State:

  • Services: aza-api + aza-caddy
  • Compose runs from /root/aza-app/deploy
  • .env is production-relevant there
  • AZA_DOMAIN=api.aza-medwork.ch
  • ACME_EMAIL=info@aza-medwork.ch
  • MEDWORK_API_TOKENS is set productively
  • OPENAI_API_KEY is set server-side

B1 BACKEND SPRINT (4 Weeks)

Week Approx. Dates Focus
1 Mar 25 Apr 01 Backend Chat Proxy Endpoint (POST /v1/chat) + Auth + Rate Limiting
2 Apr 02 Apr 08 Desktop app: all OpenAI calls via backend instead of direct
3 Apr 09 Apr 15 Hetzner Deploy: Docker/Caddy/HTTPS + Production Env + Smoke Tests
4 Apr 16 Apr 22 E2E Test Desktop→Backend→OpenAI + Customer journey without OpenAI key + Go-Live

CURRENT PRIORITY ORDER (B1 Backend Sprint)

  1. Backend Chat Proxy POST /v1/chat (Week 1) Foundation of architecture
  2. Desktop app migration to backend (Week 2) Migrate all OpenAI calls
  3. Hetzner Deploy (Week 3) Set up production server
  4. E2E Test + Go-Live backend path (Week 4) Customer journey without OpenAI key
  5. WooCommerce/Stripe purchase path runs IN PARALLEL (Hostpoint)

EXPLICITLY DEFERRED / NOT NOW:

  • Update comfort / separate auto-updater
  • Browser-AZA web app (after backend architecture)
  • Large refactors not serving Variant B

HOSTPOINT vs. HETZNER:

  • Hostpoint remains for website/marketing/WooCommerce/Stripe
  • Hetzner is NOW the backend path for OpenAI proxy/API
  • Both run in parallel, not against each other

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

POST /v1/chat IMPLEMENTED AND VERIFIED.

Aspect Detail
Auth require_api_token (X-API-Token header, existing pattern)
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
Model 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 chars/message
OpenAI Call _get_openai().chat.completions.create(**params) server-side
Response Schema {success, content, finish_reason, model, usage, request_id, duration_ms, error}
Secret Scrubbing sk-, sk-proj-, org- in error texts are replaced
Tests 7/7 green (auth, model, validation, OpenAI proxy, /license/status, schema)

File: backend_main.py (~100 lines added)

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

Desktop app: Chat completions now routed through backend POST /v1/chat.

Migrated:

  1. call_chat_completion() in basis14.py central wrapper -> _backend_chat_completion()
  2. News search direct self.client call -> _backend_chat_completion()
  3. Comments own OpenAI() client -> _backend_chat_completion()
  4. Med detail short info own OpenAI() client -> _backend_chat_completion()
  5. Letter style analysis in aza_text_windows_mixin.py -> _backend_chat_completion()

New architecture in basis14.py:

  • _BackendChatResponse wrapper class, OpenAI-interface compatible (.choices[0].message.content, .usage)
  • _backend_chat_completion(**kwargs) POST /v1/chat using existing token mechanism (get_backend_url/get_backend_token)
  • call_chat_completion(**kwargs) consent/capacity check, then _backend_chat_completion()
  • Timeout: 5s connect, 120s read
  • Errors: RuntimeError with readable message, no secrets

Remaining for later blocks: translate.py, congress_window.py, aza_email.py (standalone modules)

7/7 tests green: Health, Auth, Model validation, E2E Desktop->Backend->OpenAI, Response schema, /license/status OK.

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

Hetzner backend is LIVE.

Aspect Detail
Domain https://api.aza-medwork.ch
DNS api.aza-medwork.ch178.104.51.177 (A record)
Repo on Hetzner /root/aza-app
Deploy directory /root/aza-app/deploy
Running services aza-api + aza-caddy
Compose runs from /root/aza-app/deploy
.env production AZA_DOMAIN=api.aza-medwork.ch, ACME_EMAIL=info@aza-medwork.ch, MEDWORK_API_TOKENS set, OPENAI_API_KEY set server-side

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

Server-side Variant B proven end-to-end:

  • curl https://api.aza-medwork.ch/health → successful
  • curl -X POST /v1/chat with valid X-API-Token → success:true, content:OK

DONE: B1 Desktop Finalization (Code Patches, 2026-03-27)

All code patches for Variant B in the desktop app are verified and correct:

Patch Status Detail
ensure_ready() CORRECT Remote backend counts as ready (no local OpenAI key needed)
OpenAI key setup dialog CORRECT Dialog suppressed when remote backend configured
backend_url.txt CORRECT Points to https://api.aza-medwork.ch
backend_token.txt CORRECT Primary local token source, prioritized by app
start_all.bat guard CORRECT Variant B protection: does not overwrite URL for live backend
start_backend_autoport.bat guard CORRECT Variant B protection: does not overwrite URL for live backend
Chat/text path CORRECT Routes through POST {backend_url}/v1/chat

Token priority (confirmed): backend_token.txt > Env MEDWORK_API_TOKENS > Env MEDWORK_API_TOKEN

Backend URL priority (confirmed): Env MEDWORK_BACKEND_URL > backend_url.txt

Unchanged side paths (do NOT block main test):

  • translate.py, aza_email.py, apps/diktat/diktat_app.py still have local OpenAI clients → side paths only
  • kongress2_window.py has hardcoded URL → congress feature is parked

DONE: B1-W5 Local Desktop Live Test (2026-03-27)

Desktop → Hetzner → OpenAI successfully tested in the real app.

  • backend_url.txt points to https://api.aza-medwork.ch
  • backend_token.txt locally present, accepted by live backend
  • basis14.py started locally and successfully tested against live backend
  • No local OpenAI key needed
  • No OpenAI key dialog appears
  • Chat/text path routes through Hetzner backend

Desktop-specific notes (for future chats):

  • ensure_ready() is correctly patched for remote backend
  • OpenAI key dialog suppressed when remote backend configured
  • Do NOT use local starters for live test (start_all.bat, RUN_AZA_ONECLICK.bat, START_AZA.bat, start_backend_autoport.bat) they set env to localhost
  • Preferred start method: python basis14.py directly

DONE: Desktop License Path Against Live Backend (2026-03-30)

Desktop app correctly interprets backend license status:

  • canceled / inactive → test mode / DEMO
  • active → full mode
  • Relevant code: check_license_status() in basis14.py, compute_license_decision() in aza_license_logic.py
  • Activation key fallback only applies when no remote backend configured

DONE: Admin Monitor v1 + Control Panel v2 (2026-03-30)

File: admin_routes.py (mounted in backend_main.py with prefix="/admin")

Security: X-Admin-Token / AZA_ADMIN_TOKEN (require_admin_token from aza_security.py)

v1 endpoints: system_status, licenses_overview, backup_status, billing_overview v2 endpoints: license_customer_map, revenue_overview, alerts, dashboard_summary

Key files on Hetzner:

  • /root/aza-app/admin_routes.py
  • /root/aza-app/stripe_routes.py
  • /root/aza-app/backend_main.py
  • /root/aza-app/deploy/docker-compose.yml
  • /root/aza-app/deploy/.env
  • /root/aza-backups/backup_aza.sh + /root/aza-backups/daily/ (cron)

CURRENT MAIN BLOCK: WooCommerce / Production Sales Path

Goal: Make AZA Office production-ready for sale via aza-medwork.ch (Hostpoint WordPress + WooCommerce + Stripe).

Option 1 (preferred): WooCommerce / Shop Admin

  1. Create products in WooCommerce
  2. Checkout / My Account / Download / Email
  3. Billing/Legal/Invoices (CHF, VAT, Terms)
  4. End-to-end test purchase
  5. Verify bank payouts

Option 2 (technical): License/Customer Logic

  1. Clean customer/license lifecycle
  2. Later team/practice logic
  3. Better local persistence / status consistency

Stripe/Webhook/Admin Monitor foundation is ESTABLISHED. Focus moves forward.

CURRENT SUBSCRIPTION PRICES (2026-03-27)

Plan Monthly Yearly
1 User (Basic) CHF 59 CHF 590
2 Users (Team) CHF 89 CHF 890

Stripe Lookup Keys and Price IDs:

Lookup Key Price ID Amount
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

OPEN REQUIRED DOCUMENTATION Stripe Account:

  • Active Stripe account (login / email): NOT YET DOCUMENTED
  • Test mode or live mode currently active: NOT YET DOCUMENTED
  • Bank account for payouts configured: NOT YET DOCUMENTED
  • Webhook active and URL: NOT YET DOCUMENTED
  • Leading success/cancel URLs: NOT YET DOCUMENTED These items must be documented before the first real customer purchase.

DONE: Stripe Webhook + Live Test COMPLETE (2026-03-30)

Status: Webhook functional. Sandbox AND live purchase processed. Live test purchase successfully neutralized (canceled + refunded). license_debug shows status=canceled.

Solved problems (chronological):

  1. StripeObject vs dict: .get(...) on raw Stripe objects → Fix: event = json.loads(body)
  2. .to_dict_recursive() does not exist → Never use it
  3. Double prefix 404: → Fix: @router.post("/webhook") only
  4. Email lookup: customer_email null → Cascade: customer_emailcustomer_details.emailCustomer.retrieve(id)
  5. Container env trap: restart not enough → up -d --build --force-recreate
  6. Decimal serialization: str(StripeObject) fails with Decimal → Fix: _stripe_to_dict() + _decimal_default()
  7. Idempotency bug: _mark_processed() ran after error → Fix: only after success inside try block
  8. Silent exits: Missing data → 200 OK without log → Fix: comprehensive logging
  9. Sandbox API key mix: Sandbox webhook + live secret key → Fix: BOTH sk_test_ + whsec_ for sandbox
  10. missing_lookup_key: Sandbox omits price.lookup_key → Fix: _lookup_key_from_price() fallback
  11. customer_email loss on updates (Bug A, 2026-03-30): _upsert_license overwrote customer_email with NULL → Fix: COALESCE in SQL
  12. cancel_at_period_end ignored (Bug B, 2026-03-30): Webhook wrote status=active despite cancellation intent → Fix: explicit check
  13. sync_subscription too restrictive (Bug C, 2026-03-30): Only searched WHERE status='active' → Fix: search most recent regardless of status

NEVER AGAIN Stripe Webhook Rules:

  • Never use .to_dict_recursive()
  • Never use .get(...) on raw StripeObjects
  • After signature verification: event = json.loads(body)
  • Use _stripe_to_dict() for Subscription/Customer objects (not json.loads(str(...)))
  • Prefix routing: with prefix="/stripe", decorator must be @router.post("/webhook")
  • For .env changes: docker compose up -d --build --force-recreate aza-api
  • Sandbox and live strictly separated: BOTH sk_test_ + whsec_ for sandbox
  • After sandbox tests: restore live keys in deploy/.env
  • license_debug is suitable for operational quick check
  • After license anomalies: always check DB assignment first (licenses table, customer_email, subscription_id, status)

Operational reference Hetzner:

  • Current file: /root/aza-app/stripe_routes.py
  • Working backup: /root/aza-app/stripe_routes.py.working_lookup_fallback_ok
  • SQLite DB: /root/aza-app/data/stripe_webhook.sqlite
  • DB backup (after sandbox): /root/aza-app/data/stripe_webhook.sqlite.backup_after_sandbox_success
  • DB backup (before email fix): /app/data/stripe_webhook.sqlite.before_email_fix_1774895539
  • 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
  • Sync: curl -X POST https://api.aza-medwork.ch/stripe/sync_subscription
  • Live Stripe currently set in /root/aza-app/deploy/.env

EXPLICITLY DEFERRED (Polish Phase)

  • Autotext fix
  • Window sizes adjustment
  • Button sizes / layout for online presentation
  • General UI polish
  • Clean up direct OpenAI side paths in secondary modules (translate.py, aza_email.py, diktat_app.py)

Blocker Rule: One clear block at a time.

CUSTOMER JOURNEY ANALYSIS (2026-03-25)

Step Status Detail
Purchase (WooCommerce) NEXT MAIN BLOCK WooCommerce product setup, checkout, download, email, billing/legal
Download PARTIAL Mechanism exists, WooCommerce upload missing
Installer FUNCTIONALLY COMPLETE No code signing (SmartScreen warning)
Activation STRIPE LIVE PATH PROVEN (2026-03-30) Complete lifecycle: purchase → active → cancel/refund → canceled → test mode
First Start VARIANT B LIVE (2026-03-27) Desktop → Hetzner → OpenAI works. Desktop respects canceled status correctly.
Admin/Ops CONTROL PANEL V2 LIVE (2026-03-30) 8 endpoints, backup/storage/revenue/alerts/dashboard. X-Admin-Token protected.

FOCUS BLOCKS

Priority Block Description
DONE B1-W1: Backend /v1/chat Chat Proxy Endpoint foundation of Variant B
DONE B1-W2: Desktop migration All OpenAI calls in basis14.py + mixin via backend
DONE B1-W3: Hetzner Deploy Backend LIVE on api.aza-medwork.ch
DONE B1-W4: Server E2E /health + /v1/chat successful, Variant B server-side proven
DONE B1-W5: Desktop Live Test basis14.py locally tested against live backend (2026-03-27)
DONE Stripe Live Webhook Webhook 200 OK, license entry in DB, StripeObject/routing/env traps solved (2026-03-27)
DONE STRIPE-W2-LIVE: Live Test Purchase Real live purchase + cancel + refund, license_debug=canceled, 3 bugs patched (2026-03-30)
DONE Desktop License Path canceled → test mode, active → full mode correctly (2026-03-30)
DONE Admin Monitor v1 system_status, licenses_overview, backup_status, billing_overview (2026-03-30)
DONE Control Panel v2 license_customer_map, revenue_overview, alerts, dashboard_summary (2026-03-30)
DONE Backup/Storage Monitor Daily backup, /host_backups mounted, ~137 GB free (2026-03-30)
CURRENT WooCommerce / Production Sales Path Products, checkout, download, email, billing/legal
NEXT License/Customer Logic Clean lifecycle, team/practice logic
DEFERRED UI Polish Autotext fix, window sizes, buttons, layout
DEFERRED FB-C: Signing Signing readiness prepared
DEFERRED FB-D: Update Comfort Only after stable customer journey

PRODUCT NAME CURRENT DIRECTION

Current favorite: AZA Office

Preferred long form:

  • AZA Office Ihr medizinischer KI-Arbeitsplatz fuer die Praxis

Second good variant:

  • AZA Office Die KI-Assistenz fuer medizinische Dokumentation

Status: Current preferred naming direction. Not yet legally/brand-strategically finalized. Use for WooCommerce/website/download/Go-Live/product presentation.

Earlier shortlist (AZA Desktop): Documented in project_roadmap.json and project_plan.json. Superseded by AZA Office.

WORKING PRINCIPLES FOR NEXT CHATS

  • Root-cause-first instead of blind patching
  • One clear block at a time
  • No 10 construction sites simultaneously
  • Weight real installed builds higher than code assertions
  • Don't declare "done" too early
  • Distinguish Desktop into:
    1. Dev code
    2. Newly built installer
    3. Real behavior in installed build

COMMUNICATION NOTE (2026-03-30):

Do NOT reopen / consider ESTABLISHED:

  • Hetzner deploy live and working
  • DNS/Caddy/nginx/TLS completed
  • Variant A/B debate Variant B is mandatory and productive
  • Stripe webhook stabilization all root causes solved
  • Stripe live test completed and neutralized (purchase + cancel + refund)
  • Desktop license path validated, canceled/active correct
  • Admin Monitor v1 + Control Panel v2 LIVE and functional
  • Backup/Storage Monitor ACTIVE
  • Stripe/Webhook/License/Admin foundation is TECHNICALLY PROVEN do not restart from basics

Current focus:

  1. WooCommerce / Production sales path (products, checkout, download, email, billing/legal)
  2. End-to-end test purchase validation
  3. Then: License/customer logic professionalization or UI polish

Continuity that MUST NOT be lost:

  • User does not tinker only exact commands or complete Composer prompts
  • Root-cause-first, no monster patches
  • Hostpoint remains main website, Hetzner is backend/API
  • Desktop talks to backend, OpenAI key stays server-side
  • Backend license status is authoritative (not activation key)
  • Admin Control Panel is foundation for operator view
  • Backup/Storage monitor is active

Current Local Workspace

CURRENT PATH (from 2026-03-27):

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

OLD PATH (HISTORICAL, do not use):

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

Key Commands

Preferred start method for live test against Hetzner backend:

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

DO NOT use for live test (set env to localhost):

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

Local dev start (only for local development with own backend):

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

Tests:

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

Desktop UX Block (2026-03-18)

  • Benutzerdaten bei Deinstallation erhalten (Inno Setup, Standard: Nein)
  • Signatur-UI: Haekchen "Profilname verwenden" + abweichender Signaturname in Einstellungen
  • Rechtsklick-Haekchen im Minifenster (synchronisiert)
  • Kommentare-Fenster (TEILWEISE: Grundstruktur, Detailmodus + Live-Update offen)
  • Briefstil-Lernen (DOCX-Upload, Stilprofil-Analyse, Profilauswahl, Integration)
  • Briefstil-Profile Fix: KISIM/Klinisch als feste Systemprofile, vereinheitlichtes Stilprofil-UI im Brief-Bereich
  • Autotext Root-Cause-Fix (_is_admin NameError, Listener-Revert)
  • Persistenz-Patch: Erststart-Consent, Profil+Code, Kommentare-Toggle, Einstellungs-Gruppierung
  • Uebersetzer-Stabilitaetsfix: Toplevel-Embedded statt Tkinter-in-Thread
  • Briefprofile: KISIM Bericht + Klinischer Bericht als vordefinierte Profile

AZA Clean Uninstall / Reset Tool

Per Doppelklick: AZA_Deinstallieren.bat

Per PowerShell:

powershell -ExecutionPolicy Bypass -File .\tools\aza_clean_uninstall.ps1
  • Modus 1: Nur App entfernen, Benutzerdaten behalten
  • Modus 2: Vollstaendig zuruecksetzen (App + Benutzerdaten)
  • Kein Neustart noetig (Standardfall)
  • Danach direkt Neuinstallation moeglich

Do-Not-Break Rules

  1. Do not change existing API response formats (especially /license/status).
  2. Do not modify auth/security mechanisms.
  3. Do not log or print secrets/tokens/keys.
  4. Signature fallback: profile name used when no explicit signature set.
  5. User data in %APPDATA%\AZA Desktop NOT deleted on uninstall by default.
  6. Style learning from old letters: only style/structure, NEVER copy patient data or old content.

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

  1. Translator label: "Fachuebersetzer" renamed to "Uebersetzer" everywhere
  2. Comments window: auto-open checkbox (persistent), live-update on KG change, clickable diagnosis headings with detail popups
  3. Correction window: scrollbar for saved corrections list
  4. Style profile live application: brief regenerated immediately on profile change/toggle
  5. "Profil anwenden" button in style profile management dialog
  6. KG creation writes directly to main window (no popup)
  7. Persistence: dokumente_collapsed now properly saved/loaded
  8. Main window centering: robust delayed centering after widget build via self.after()

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

  1. Style profile dialog: now management-only (status display, learn, delete). Active selection exclusively in brief window.
  2. Comments window: auto-opens after KG creation when checkbox is active (not just refreshes existing window).
  3. Logo separation: Wassertropfen (logo.ico) for EXE/desktop/installer/title bar icon. Original logo (logo.png) for internal branding (bottom-left).

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

Root Cause (FIX-09): LLM generated medication info purely from model knowledge. Root Cause (FIX-10): PharmaWiki regex wrong (used h2/h3 instead of span#subtitle). Compendium.ch is SPA (not scrapable). Root Cause (FIX-11): Content source and external link were mixed in one dropdown/dict.

Fix (FIX-11): Clean separation of content source and external link:

CONTENT SOURCE (what is shown in detail window):

  • _fetch_doccheck_info(med_name): DocCheck Flexikon (default) server-rendered, h2/h3 headings
  • _fetch_pharmawiki_info(med_name): PharmaWiki (fallback) span#subtitle headings
  • User-selectable via "Inhaltsquelle:" dropdown, persistent in med_content_quelle
  • New dict _MED_CONTENT_QUELLEN (DocCheck, PharmaWiki)
  • Curated _MEDICATION_FACTS as offline fallback

EXTERNAL LINK ("Originalquelle oeffnen" button):

  • CH = Compendium, AT = BASG, DE = BfArM UNCHANGED
  • Still via _MED_QUELLEN / medikament_quelle NOT modified

Therapies/procedures: separate handling via DocCheck/PharmaWiki (unchanged). Candidate logic (Dermowarte→Dermovate etc.): untouched.

Files: basis14.py

ARCH-MED: Medication Source Architecture (2026-03-22)

Architecture (implemented):

  1. Detect medication in KG text (existing tagging + validation)
  2. Fetch content from DocCheck Flexikon (default) or PharmaWiki (user choice/fallback)
  3. Inject source text into LLM prompt (strict: only use provided data)
  4. Curated facts list as offline fallback
  5. External link always country-based (CH/AT/DE)
  6. Omit anything not from the source

Coverage: All medications available on DocCheck Flexikon + PharmaWiki.

Next steps:

  1. Caching strategy (cache fetched content locally)
  2. Robustness against HTML structure changes
  3. Long-term: Compendium API / HCI Solutions data license evaluation

Later market profiles (DE: BfArM, AT: BASG) separately.

Zukunftsblock Internationalisierung / Laender- und Quellenprofile (GEPARKT)

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

Voraussetzung: DACH (CH/DE/AT) stabil, Go-Live gesichert, Produkt erfolgreich.

Zielbild:

  • UI/Sprache, Medikamenten-/Diagnose-/Therapiequellen pro Markt anpassbar
  • Profil-Felder: app_language, market_region, med_source_profile, dx_source_profile, therapy_source_profile
  • Manueller Override durch Benutzer/Praxis
  • Nicht hart nach Herkunftsland schalten saubere Profil-Logik
  • Handelsnamen/Zulassungen/Fachinfos sind laenderspezifisch → Quellenprofile pro Markt

Kein aktueller Implementierungsblock. Erst nach Go-Live und DACH-Erfolg relevant.

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

Problem: Windows Smart App Control blockiert unsignierte Apps bei Kunden.

Status: Signing-Readiness vorbereitet, noch NICHT produktiv aktiviert.

Vorbereitet:

  • sign_release.ps1 signiert EXE + DLLs/PYDs + Installer (DryRun-Modus verfuegbar)
  • build_and_test_release.ps1 Signing-Schritt integriert (optional, graceful skip)
  • build_release_artifacts.ps1 Artefakt-Report mit Signatur-Status
  • SIGNING_READINESS.md Vollstaendige Dokumentation

Signing-Reihenfolge: DLLs/PYDs → EXE → Installer-Build → Installer signieren → Artefakt-Report

Vor Kundenauslieferung noch offen:

  1. EV Code-Signing-Zertifikat beschaffen
  2. signtool.exe installieren (Windows SDK)
  3. Publisher-Name abstimmen (Zertifikat ↔ AppPublisher ↔ Handelsregister)
  4. Produktiver Signierlauf + Test auf Windows-PC mit Smart App Control

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

3 Namensformen im Projekt beabsichtigt, keine Inkonsistenz:

  • AZA MedWork = Firma/Publisher → SIGNING-KRITISCH (Installer, Legal, Consent, E-Mail-Absender)
  • AZA Desktop = Produktname → konsistent, kein Handlungsbedarf
  • AZA Medical AI Assistant = interner Projektname → nicht signing-relevant

Vor Zertifikatskauf: HR-Name pruefen, AppPublisher auf Zertifikats-Subject abstimmen. Falls HR-Name abweicht: alle signing-relevanten Stellen gemeinsam anpassen (Liste in handover.md). Nach Festlegung: Publisher-Name NICHT mehr wechseln (SmartScreen-Reputation).