431 lines
18 KiB
Markdown
431 lines
18 KiB
Markdown
|
|
# AZA – Detaillierte Projektuebergabe / Handover
|
|||
|
|
|
|||
|
|
**Stand: 2026-04-06**
|
|||
|
|
**Zweck:** Diese Datei ist die verbindliche Referenz fuer jeden neuen Chat. Zuerst lesen, dann arbeiten.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. Projektziel / Aktueller Fokus
|
|||
|
|
|
|||
|
|
**AZA** (AZA Medical AI Assistant / AZA Desktop) ist eine medizinische KI-Desktop-Anwendung fuer Windows. Sie unterstuetzt Aerzte bei Diktat, Textverarbeitung, medizinischer Recherche und Dokumentation.
|
|||
|
|
|
|||
|
|
**Architektur (Variante B – verbindlich seit 2026-03-25):**
|
|||
|
|
- Desktop-App (Python/Tkinter) kommuniziert mit eigenem AZA-Backend auf Hetzner
|
|||
|
|
- Backend leitet KI-Anfragen serverseitig an OpenAI weiter
|
|||
|
|
- Kein OpenAI-Key beim Kunden noetig
|
|||
|
|
- Kein OpenAI-Key in der Desktop-App
|
|||
|
|
|
|||
|
|
**Aktueller Schwerpunkt:**
|
|||
|
|
Produktiver Kundenfluss mit Lizenzschluessel. Die klare Zielsequenz ist:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Kauf → Lizenzschluessel per E-Mail → Download → Installation → Aktivierung → Nutzung
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. Aktueller stabiler technischer Stand
|
|||
|
|
|
|||
|
|
### 2.1 Lizenzschluessel-Flow (PRODUKTIV, Stand 2026-04-06)
|
|||
|
|
|
|||
|
|
| Aspekt | Status |
|
|||
|
|
|---|---|
|
|||
|
|
| `/license/activate` | Funktioniert produktiv auf Hetzner |
|
|||
|
|
| `/license/status` | Funktioniert produktiv auf Hetzner |
|
|||
|
|
| Lizenzschluessel-Erzeugung | Automatisch beim Kauf (Format: `AZA-XXXX-XXXX-XXXX-XXXX`) |
|
|||
|
|
| Lizenzschluessel in DB | Gespeichert in `licenses`-Tabelle, Spalte `license_key` |
|
|||
|
|
| Desktop-Aktivierung | Lizenzschluessel kann in der Desktop-App eingegeben und aktiviert werden |
|
|||
|
|
| `/license/status?license_key=...` | Liefert `valid: true` fuer aktive Lizenzen |
|
|||
|
|
| Device-Enforcement | Aktiv und funktioniert korrekt |
|
|||
|
|
| Success-Seite `/billing/success` | Zeigt dem Kunden den Lizenzschluessel nach Kauf an |
|
|||
|
|
| Produktiver Test | Erfolgreich mit aktivem Lizenzschluessel |
|
|||
|
|
|
|||
|
|
**Wichtig:** Device-Bindings waren zeitweise ein Blocker. Fuer den Testdatensatz (`admin@aza-medwork.ch`) wurden bestehende Device-Bindings aus der DB geloescht, damit der erneute Aktivierungstest funktionierte. Bei neuen Kunden tritt dieses Problem nicht auf.
|
|||
|
|
|
|||
|
|
### 2.2 Mailversand (PRODUKTIV ueber Resend, Stand 2026-04-06)
|
|||
|
|
|
|||
|
|
| Aspekt | Status |
|
|||
|
|
|---|---|
|
|||
|
|
| Produktiver Versandkanal | **Resend HTTP API** |
|
|||
|
|
| Resend-Domain | `mail.aza-medwork.ch` (DNS bei Hostpoint verifiziert) |
|
|||
|
|
| Absender / MAIL_FROM | `AZA MedWork <noreply@mail.aza-medwork.ch>` |
|
|||
|
|
| Test-Endpunkt | `POST /stripe/test_license_email?email=...` (Admin-geschuetzt) |
|
|||
|
|
| Letzter erfolgreicher Test | `{"sent": true, "to": "admin@aza-medwork.ch"}` |
|
|||
|
|
| E-Mail Zustellung | Produktiv bestaetigt – Mail kommt an |
|
|||
|
|
|
|||
|
|
### 2.3 Stripe / Billing (PRODUKTIV)
|
|||
|
|
|
|||
|
|
| Aspekt | Status |
|
|||
|
|
|---|---|
|
|||
|
|
| Stripe-Modus | Live (sk_live_) |
|
|||
|
|
| Webhook-Endpunkt | `https://api.aza-medwork.ch/stripe/webhook` |
|
|||
|
|
| Echter Live-Kauf | CHF 59 Basic Monthly erfolgreich durchgefuehrt |
|
|||
|
|
| Lizenz-Lifecycle | Kauf → active → Storno/Refund → canceled → Desktop Testmodus (bewiesen) |
|
|||
|
|
| Webhook-Events | `checkout.session.completed`, `customer.subscription.updated`, `customer.subscription.deleted` |
|
|||
|
|
|
|||
|
|
### 2.4 Desktop-App
|
|||
|
|
|
|||
|
|
| Aspekt | Status |
|
|||
|
|
|---|---|
|
|||
|
|
| Lizenzpruefung | Ueber Backend (`/license/status`) mit Lizenzschluessel |
|
|||
|
|
| Vollmodus | Wenn Backend `valid: true` liefert |
|
|||
|
|
| Testmodus | Wenn keine gueltige Lizenz oder Backend nicht erreichbar |
|
|||
|
|
| Lokales Aktivierungs-Gate | Bei Remote-Backend uebersprungen (Root Cause 14 behoben) |
|
|||
|
|
| Update-Checker | Prueft `https://api.aza-medwork.ch/download/version.json` beim Start |
|
|||
|
|
| Aktuelle Version | `APP_VERSION = "1.0.0"`, `APP_CHANNEL = "stable"` |
|
|||
|
|
|
|||
|
|
### 2.5 Admin Control Panel (PRODUKTIV)
|
|||
|
|
|
|||
|
|
8 interne Admin-Endpunkte, geschuetzt via `X-Admin-Token` / `AZA_ADMIN_TOKEN`:
|
|||
|
|
|
|||
|
|
**v1:**
|
|||
|
|
- `GET /admin/system_status` – App-Health, Uptime, Disk, Stripe-Config, DB-Info
|
|||
|
|
- `GET /admin/licenses_overview` – Lizenzen nach Status, letzte 20, `?email=` Filter
|
|||
|
|
- `GET /admin/backup_status` – Backup-Pfade, Groesse, neustes Backup, Log-Tail
|
|||
|
|
- `GET /admin/billing_overview` – Stripe-Health, Lizenz-Summary, Event-Log
|
|||
|
|
|
|||
|
|
**v2:**
|
|||
|
|
- `GET /admin/license_customer_map` – Detaillierte Lizenznehmer-Uebersicht, `?email=` und `?status=` Filter
|
|||
|
|
- `GET /admin/revenue_overview` – MRR, Stripe-Live-Daten (gross/refunds/net), recent_charges, recent_refunds
|
|||
|
|
- `GET /admin/alerts` – Strukturierte Warnliste (info/warning/critical)
|
|||
|
|
- `GET /admin/dashboard_summary` – Sammel-Endpunkt fuer alle Kennzahlen
|
|||
|
|
|
|||
|
|
### 2.6 Backup / Storage
|
|||
|
|
|
|||
|
|
- Taegliches Backup-Skript: `/root/aza-backups/backup_aza.sh` (Cronjob)
|
|||
|
|
- Backup-Pfad: `/root/aza-backups/daily/`
|
|||
|
|
- In Container gemountet als `/host_backups` (read-only)
|
|||
|
|
- Ca. 137 GB frei, ca. 4-5% belegt – kein Speicherdruck
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. Mailversand-Historie / Root Causes / Finaler Weg
|
|||
|
|
|
|||
|
|
### Chronologie
|
|||
|
|
|
|||
|
|
1. **Erster Versuch: Hostpoint-SMTP**
|
|||
|
|
- Hostpoint-Mailbox `noreply@aza-medwork.ch` wurde angelegt
|
|||
|
|
- SMTP-Server: `asmtp.mail.hostpoint.ch`
|
|||
|
|
- Port 465 (SSL) und 587 (STARTTLS) getestet
|
|||
|
|
- SMTP-Daten wurden mehrfach geprueft und waren korrekt
|
|||
|
|
|
|||
|
|
2. **Beobachtete Fehler (SMTP von Hetzner/Container):**
|
|||
|
|
- Erste Tests: Auth-Fehler (falscher Host `mail.hostpoint.ch` statt `asmtp.mail.hostpoint.ch`)
|
|||
|
|
- Nach Host-Korrektur: `OSError: [Errno 101] Network is unreachable`
|
|||
|
|
- Port 465 → Timeout / Network unreachable
|
|||
|
|
- Port 587 → Timeout / Network unreachable
|
|||
|
|
- Ursache: Hetzner-Container kann Hostpoint-SMTP-Server nicht erreichen (Netzwerk-/Firewallsperre)
|
|||
|
|
|
|||
|
|
3. **Schlussfolgerung:**
|
|||
|
|
- Hostpoint-SMTP ist von Hetzner aus nicht nutzbar
|
|||
|
|
- Das ist ein Infrastruktur-/Netzwerkproblem, kein Code-Problem
|
|||
|
|
- Hostpoint-SMTP ist **nicht** der produktive Versandweg
|
|||
|
|
|
|||
|
|
4. **Loesung: Umstellung auf Resend HTTP API**
|
|||
|
|
- Resend-Account erstellt
|
|||
|
|
- Domain `mail.aza-medwork.ch` bei Resend registriert und via DNS bei Hostpoint verifiziert
|
|||
|
|
- `MAIL_FROM` gesetzt auf `AZA MedWork <noreply@mail.aza-medwork.ch>`
|
|||
|
|
- Code in `stripe_routes.py` umgebaut: `_send_via_resend()` als primaerer Kanal
|
|||
|
|
- **Wichtiger Fix:** Resend-HTTP-API erfordert `User-Agent` Header (ohne → Error 1010/403)
|
|||
|
|
- Fix angewandt: `"User-Agent": "AZA-MedWork/1.0"` im Request
|
|||
|
|
|
|||
|
|
5. **Finaler erfolgreicher Test:**
|
|||
|
|
```
|
|||
|
|
POST /stripe/test_license_email?email=admin@aza-medwork.ch
|
|||
|
|
→ {"sent": true, "to": "admin@aza-medwork.ch"}
|
|||
|
|
```
|
|||
|
|
E-Mail kam produktiv an.
|
|||
|
|
|
|||
|
|
### Aktueller Zustand der Mailfunktion in `stripe_routes.py`
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
send_license_email(to_email, license_key)
|
|||
|
|
├── RESEND_API_KEY gesetzt? → _send_via_resend() [PRODUKTIVER WEG]
|
|||
|
|
└── sonst → _send_via_smtp() [INAKTIVER FALLBACK]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- SMTP-Code ist noch vorhanden als Fallback
|
|||
|
|
- SMTP-Variablen in `.env` sind Altlast, nicht produktiv aktiv
|
|||
|
|
- Wenn `RESEND_API_KEY` gesetzt ist (und das ist es), wird immer Resend benutzt
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. Wichtige Pfade / Betriebsorte / Operator-Wissen
|
|||
|
|
|
|||
|
|
### Lokaler Windows-Rechner
|
|||
|
|
|
|||
|
|
| Was | Pfad |
|
|||
|
|
|---|---|
|
|||
|
|
| Projektordner | `C:\Users\surov\Documents\AZA_GIT\aza\AzA march 2026` |
|
|||
|
|
| Desktop-App direkt starten | `python basis14.py` (im Projektordner) |
|
|||
|
|
| Build-EXE | `.\build_exe.ps1` |
|
|||
|
|
| Build-Installer | `.\build_installer.ps1` |
|
|||
|
|
| Kompletter Release | `.\ship_release.ps1` |
|
|||
|
|
| Nur Upload | `.\publish_update.ps1` |
|
|||
|
|
| Installer-Artefakt | `dist\installer\aza_desktop_setup.exe` |
|
|||
|
|
| Release-Manifest | `release\version.json` |
|
|||
|
|
| Versionsquelle | `aza_version.py` (`APP_VERSION`, `APP_CHANNEL`) |
|
|||
|
|
|
|||
|
|
**Wichtig:** NICHT ueber lokale Starter starten (`start_all.bat`, `RUN_AZA_ONECLICK.bat`, `START_AZA.bat`, `start_backend_autoport.bat`) – diese setzen Env-Variablen auf localhost und ueberschreiben die Live-Backend-URL.
|
|||
|
|
|
|||
|
|
### Hetzner-Server (SSH)
|
|||
|
|
|
|||
|
|
| Was | Pfad / Befehl |
|
|||
|
|
|---|---|
|
|||
|
|
| SSH-Zugang | `ssh root@178.104.51.177` |
|
|||
|
|
| Repo-Root | `/root/aza-app` |
|
|||
|
|
| Docker-Compose-Ordner | `/root/aza-app/deploy` |
|
|||
|
|
| `.env`-Datei | `/root/aza-app/deploy/.env` |
|
|||
|
|
| Rebuild (immer im deploy-Ordner!) | `cd /root/aza-app/deploy && docker compose down && docker compose up -d --build` |
|
|||
|
|
| Container-Logs | `docker logs aza-api --tail 100` |
|
|||
|
|
| ENV im Container pruefen | `docker exec aza-api env \| grep VARIABLE` |
|
|||
|
|
| Backup-Ordner | `/root/aza-backups/daily/` |
|
|||
|
|
|
|||
|
|
**WICHTIG:** `docker compose` Befehle muessen IMMER im Ordner `/root/aza-app/deploy` ausgefuehrt werden, nicht im Repo-Root `/root/aza-app`.
|
|||
|
|
|
|||
|
|
### Hostpoint (Website / DNS)
|
|||
|
|
|
|||
|
|
| Was | Detail |
|
|||
|
|
|---|---|
|
|||
|
|
| Haupt-Website | Hostpoint bleibt fuer Website, Marketing, WooCommerce |
|
|||
|
|
| DNS-Verwaltung | Bei Hostpoint (fuer `aza-medwork.ch` und Subdomains) |
|
|||
|
|
| Mailboxen | Hostpoint verwaltet Mailboxen (z.B. `noreply@aza-medwork.ch`) |
|
|||
|
|
| Resend-DNS | `mail.aza-medwork.ch` DNS-Records fuer Resend bei Hostpoint gesetzt |
|
|||
|
|
|
|||
|
|
### Produktive URLs
|
|||
|
|
|
|||
|
|
| URL | Zweck |
|
|||
|
|
|---|---|
|
|||
|
|
| `https://api.aza-medwork.ch` | Backend-API |
|
|||
|
|
| `https://api.aza-medwork.ch/health` | Health-Check |
|
|||
|
|
| `https://api.aza-medwork.ch/stripe/webhook` | Stripe-Webhook |
|
|||
|
|
| `https://api.aza-medwork.ch/download/version.json` | Update-Manifest |
|
|||
|
|
| `https://api.aza-medwork.ch/download/aza_desktop_setup.exe` | Installer-Download |
|
|||
|
|
| `https://api.aza-medwork.ch/billing/success` | Kauf-Erfolgsseite |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. Wichtige ENV / Konfiguration
|
|||
|
|
|
|||
|
|
### Aktive produktive ENV-Variablen (auf Hetzner in `/root/aza-app/deploy/.env`)
|
|||
|
|
|
|||
|
|
| Variable | Rolle | Status |
|
|||
|
|
|---|---|---|
|
|||
|
|
| `RESEND_API_KEY` | Resend API Credential fuer Mailversand | **AKTIV PRODUKTIV** |
|
|||
|
|
| `MAIL_FROM` | Absender fuer Lizenzschluessel-Mail | **AKTIV PRODUKTIV** |
|
|||
|
|
| `STRIPE_SECRET_KEY` | Stripe Live API Key (sk_live_...) | **AKTIV PRODUKTIV** |
|
|||
|
|
| `STRIPE_WEBHOOK_SECRET` | Stripe Webhook Signing Secret | **AKTIV PRODUKTIV** |
|
|||
|
|
| `AZA_ADMIN_TOKEN` | Token fuer Admin-Endpunkte | **AKTIV PRODUKTIV** |
|
|||
|
|
| `MEDWORK_API_TOKENS` | API-Token fuer Desktop-Backend-Kommunikation | **AKTIV PRODUKTIV** |
|
|||
|
|
| `OPENAI_API_KEY` | OpenAI API Key (serverseitig) | **AKTIV PRODUKTIV** |
|
|||
|
|
| `AZA_DOMAIN` | `api.aza-medwork.ch` | **AKTIV PRODUKTIV** |
|
|||
|
|
| `ACME_EMAIL` | `info@aza-medwork.ch` (fuer Caddy/HTTPS) | **AKTIV PRODUKTIV** |
|
|||
|
|
|
|||
|
|
### Inaktive / historische ENV-Variablen
|
|||
|
|
|
|||
|
|
| Variable | Rolle | Status |
|
|||
|
|
|---|---|---|
|
|||
|
|
| `SMTP_HOST` | Hostpoint SMTP Server | **INAKTIV** – Fallback, wird nicht genutzt |
|
|||
|
|
| `SMTP_PORT` | Hostpoint SMTP Port | **INAKTIV** – Fallback |
|
|||
|
|
| `SMTP_USER` | Hostpoint SMTP User | **INAKTIV** – Fallback |
|
|||
|
|
| `SMTP_PASS` | Hostpoint SMTP Passwort | **INAKTIV** – Fallback |
|
|||
|
|
| `SMTP_FROM` | Hostpoint SMTP Absender | **INAKTIV** – Fallback |
|
|||
|
|
|
|||
|
|
**Keine Rueckkehr zu Hostpoint-SMTP noetig, solange Resend stabil laeuft.**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. Naechster Hauptblock: End-to-End-Kundentest
|
|||
|
|
|
|||
|
|
**Ziel:** Den kompletten Kundenfluss ohne Basteln, ohne manuelle DB-Eingriffe und ohne Operator-Hilfe beweisen.
|
|||
|
|
|
|||
|
|
### Zielbild fuer den Kundenfluss
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. Kunde kauft ueber Stripe Payment Link / Checkout
|
|||
|
|
2. Stripe Webhook verarbeitet den Kauf
|
|||
|
|
3. Backend erzeugt Lizenzschluessel und speichert ihn in der DB
|
|||
|
|
4. Resend sendet automatisch E-Mail mit Lizenzschluessel an den Kunden
|
|||
|
|
5. Success-Seite zeigt dem Kunden ebenfalls den Lizenzschluessel
|
|||
|
|
6. Kunde laedt AZA ueber offiziellen Download-Link herunter
|
|||
|
|
7. Kunde installiert AZA
|
|||
|
|
8. Kunde gibt Lizenzschluessel in der Desktop-App ein
|
|||
|
|
9. Desktop aktiviert gegen Backend (/license/activate)
|
|||
|
|
10. Desktop startet im Vollmodus
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Was dabei noch geprueft / sichergestellt werden muss
|
|||
|
|
|
|||
|
|
- [ ] E-Mail mit Lizenzschluessel kommt automatisch beim Kauf an (nicht nur via Test-Endpunkt)
|
|||
|
|
- [ ] Download-Link in der E-Mail ist korrekt und funktioniert
|
|||
|
|
- [ ] Installer laesst sich sauber installieren
|
|||
|
|
- [ ] Erststart ohne vorherige Konfiguration funktioniert
|
|||
|
|
- [ ] Lizenzschluessel-Eingabe in der App funktioniert auf Anhieb
|
|||
|
|
- [ ] Vollmodus wird sofort nach Aktivierung erreicht
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. Download-/Installer-Entscheidung
|
|||
|
|
|
|||
|
|
**Fuer den naechsten Kundenfluss-Test:**
|
|||
|
|
- Download soll ueber die offizielle Website / Download-Seite priorisiert werden
|
|||
|
|
- Nicht zuerst einen rohen Direktlink als Hauptweg verwenden
|
|||
|
|
- Die E-Mail soll idealerweise einen klaren Download-Link enthalten
|
|||
|
|
- Der Kundentest soll moeglichst realistisch am echten Kundenablauf orientiert sein
|
|||
|
|
|
|||
|
|
**Zielbild:**
|
|||
|
|
Mail mit Lizenzschluessel + klarem Download-Link → Download → Installation → Aktivierung
|
|||
|
|
|
|||
|
|
**Aktuell verfuegbarer Direktlink:**
|
|||
|
|
`https://api.aza-medwork.ch/download/aza_desktop_setup.exe`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. Offene Restpunkte
|
|||
|
|
|
|||
|
|
| Punkt | Prioritaet | Blocker? |
|
|||
|
|
|---|---|---|
|
|||
|
|
| Mailtext und Success-Seite inhaltlich polieren | Niedrig | Nein |
|
|||
|
|
| Admin-Token rotieren (wurde im Chat offengelegt) | Mittel | Nein, aber vor echtem Kundenbetrieb empfohlen |
|
|||
|
|
| SMTP-Reste in `.env` aufraeumen | Niedrig | Nein (inaktiv) |
|
|||
|
|
| Resend-Setup / Domain-Policy weiter polieren | Niedrig | Nein |
|
|||
|
|
| Device-Bindings-Management fuer Mehrgeraete klarer machen | Mittel | Nein |
|
|||
|
|
| translate.py, aza_email.py, diktat_app.py auf Backend-Chat migrieren | Niedrig | Nein (Nebenpfade) |
|
|||
|
|
| WooCommerce / Website-Kaufpfad professionalisieren | Mittel | Spaeterer Block |
|
|||
|
|
| Browser-AZA / Web-App | Niedrig | Spaeterer Block |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. Arbeitsstil / Nutzerpraeferenzen
|
|||
|
|
|
|||
|
|
**Diese Regeln gelten fuer ALLE zukuenftigen Chats:**
|
|||
|
|
|
|||
|
|
### Allgemeine Regeln
|
|||
|
|
|
|||
|
|
- Nutzer bastelt nicht – alle Aenderungen kommen als fertige, vollstaendige Dateien (ready-to-paste)
|
|||
|
|
- Nutzer fuehrt nur vorgegebene Commands aus, keine manuellen Edits
|
|||
|
|
- Jede Aenderung in 1 Patch, kein schrittweises Anleiten
|
|||
|
|
- Keine risky Refactors – immer minimal und sicher
|
|||
|
|
- Root-cause-first bei jedem Problem
|
|||
|
|
- Keine Monsterpatches
|
|||
|
|
- Keine Rueckfragen-Orgien
|
|||
|
|
- Keine Variantenflut – genau 1 Weg, der beste
|
|||
|
|
|
|||
|
|
### Operator-Schritte
|
|||
|
|
|
|||
|
|
- **Immer** explizit angeben, WO ein Schritt auszufuehren ist:
|
|||
|
|
- `[Windows PowerShell]` – lokaler Rechner, Projektordner
|
|||
|
|
- `[Hetzner SSH]` – `ssh root@178.104.51.177`
|
|||
|
|
- `[Browser]` – URL angeben
|
|||
|
|
- `[Composer/IDE]` – Cursor Editor
|
|||
|
|
- **Immer** exakte Copy-Paste-Befehle liefern
|
|||
|
|
- **Immer** mit Pfad oder Ort starten
|
|||
|
|
- Nicht schreiben, was der Nutzer NICHT tun soll, sondern nur den naechsten exakten Schritt
|
|||
|
|
- Keine vagen Formulierungen wie "send this" oder "do something like"
|
|||
|
|
- Nutzer will moeglichst wenig manuelle Improvisation
|
|||
|
|
|
|||
|
|
### Uebergaben
|
|||
|
|
|
|||
|
|
- Uebergaben fuer naechste Chats sollen ausfuehrlich sein, nicht minimal
|
|||
|
|
- Wichtige Root Causes immer dokumentieren
|
|||
|
|
- Geloeste Probleme klar als geloest markieren
|
|||
|
|
- Nicht bei alten Problemen wieder anfangen
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 10. Empfohlener Chat-Start fuer den naechsten Chat
|
|||
|
|
|
|||
|
|
### Sinnvolle naechste Hauptbloecke (nach Prioritaet)
|
|||
|
|
|
|||
|
|
1. **End-to-End-Kundentest** (EMPFOHLEN als naechstes)
|
|||
|
|
- Kontrollierter Kauf → automatische E-Mail → Download → Installation → Aktivierung → Vollmodus
|
|||
|
|
- Beweisen, dass der gesamte Fluss ohne Basteln funktioniert
|
|||
|
|
|
|||
|
|
2. **Download-Seite / Website-Kaufpfad**
|
|||
|
|
- Offizielle Download-Seite auf der Website einrichten
|
|||
|
|
- Klaren Kundenweg von Website → Kauf → Download definieren
|
|||
|
|
|
|||
|
|
3. **Admin-Token-Rotation + Secrets-Hygiene**
|
|||
|
|
- Offengelegten Admin-Token rotieren
|
|||
|
|
- Sicherstellen, dass keine Secrets im Repo liegen
|
|||
|
|
|
|||
|
|
### Beste Empfehlung
|
|||
|
|
|
|||
|
|
**Starte mit Block 1: End-to-End-Kundentest.**
|
|||
|
|
|
|||
|
|
### Erster konkreter Operator-Schritt
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
[Browser]
|
|||
|
|
Stripe Payment Link oeffnen und kontrollierten Testkauf mit einer
|
|||
|
|
frischen E-Mail-Adresse durchfuehren (NICHT admin@aza-medwork.ch,
|
|||
|
|
sondern eine neue Adresse, um den Neukundenfall zu simulieren).
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Danach pruefen:
|
|||
|
|
1. `[Hetzner SSH]` – `/stripe/license_debug?email=NEUE_EMAIL` → aktive Lizenz?
|
|||
|
|
2. `[E-Mail-Postfach]` – Lizenzschluessel-Mail angekommen?
|
|||
|
|
3. `[Browser]` – Installer herunterladen ueber Link aus der Mail
|
|||
|
|
4. `[Windows]` – Installer ausfuehren, App starten, Lizenzschluessel eingeben
|
|||
|
|
5. `[Desktop-App]` – Vollmodus bestaetigen
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 11. Geloeste Root Causes (Referenz)
|
|||
|
|
|
|||
|
|
| RC | Problem | Loesung | Datei | Datum |
|
|||
|
|
|---|---|---|---|---|
|
|||
|
|
| RC14 | Desktop zeigte Testversion trotz aktiver Remote-Lizenz | `_has_remote_backend()` Bypass fuer lokales Aktivierungs-Gate | `basis14.py` | 2026-03-30 |
|
|||
|
|
| RC15 | `current_period_end` war null fuer aktive Lizenz | Fallback auf `items.data[0].current_period_end` im Webhook | `stripe_routes.py` | 2026-03-30 |
|
|||
|
|
| RC16 | revenue_overview zu grob fuer Betreiber | `recent_charges` und `recent_refunds` ergaenzt | `admin_routes.py` | 2026-03-31 |
|
|||
|
|
| RC17 | SMTP von Hetzner → Hostpoint nicht erreichbar | Umstellung auf Resend HTTP API | `stripe_routes.py` | 2026-04-06 |
|
|||
|
|
| RC18 | Resend-API lehnte Request ab (Error 1010/403) | `User-Agent: AZA-MedWork/1.0` Header ergaenzt | `stripe_routes.py` | 2026-04-06 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 12. Wichtige Dateien im Projekt
|
|||
|
|
|
|||
|
|
### Backend (auf Hetzner unter `/root/aza-app/`)
|
|||
|
|
|
|||
|
|
| Datei | Rolle |
|
|||
|
|
|---|---|
|
|||
|
|
| `backend_main.py` | FastAPI-Hauptanwendung, mountet alle Router |
|
|||
|
|
| `stripe_routes.py` | Stripe-Webhook, Lizenz-DB, Mailversand, Lizenzschluessel-Erzeugung |
|
|||
|
|
| `admin_routes.py` | Admin Control Panel v1+v2 Endpunkte |
|
|||
|
|
| `aza_license_logic.py` | `compute_license_decision()` – Lizenzgueltigkeit berechnen |
|
|||
|
|
| `aza_device_enforcement.py` | Device-Bindings verwalten |
|
|||
|
|
| `aza_security.py` | `require_api_token`, `require_admin_token` |
|
|||
|
|
|
|||
|
|
### Desktop (lokal)
|
|||
|
|
|
|||
|
|
| Datei | Rolle |
|
|||
|
|
|---|---|
|
|||
|
|
| `basis14.py` | Haupt-Desktop-App (8900+ Zeilen), UI, Lizenzcheck, Aktivierung |
|
|||
|
|
| `aza_version.py` | `APP_VERSION`, `APP_CHANNEL` – zentrale Versionsquelle |
|
|||
|
|
| `aza_style.py` | UI-Styling-Konstanten |
|
|||
|
|
| `desktop_update_check.py` | Update-Checker beim App-Start |
|
|||
|
|
| `aza_desktop.spec` | PyInstaller-Spezifikation |
|
|||
|
|
|
|||
|
|
### Build / Release (lokal)
|
|||
|
|
|
|||
|
|
| Datei | Rolle |
|
|||
|
|
|---|---|
|
|||
|
|
| `build_exe.ps1` | Baut EXE mit PyInstaller |
|
|||
|
|
| `build_installer.ps1` | Baut Installer mit Inno Setup |
|
|||
|
|
| `build_release_manifest.ps1` | Erzeugt `release/version.json` |
|
|||
|
|
| `release.ps1` | Lokaler Release-Prozess (Build + Verify) |
|
|||
|
|
| `publish_update.ps1` | Upload nach Hetzner |
|
|||
|
|
| `ship_release.ps1` | **Verbindlicher Ein-Knopf-Release** (Build + Upload) |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Abschluss
|
|||
|
|
|
|||
|
|
**Wenn der naechste Chat startet:**
|
|||
|
|
1. Zuerst diese Datei lesen
|
|||
|
|
2. Nicht wieder bei alten SMTP-/Deploy-/Pfadfehlern beginnen
|
|||
|
|
3. Hostpoint-SMTP ist nicht der produktive Weg – Resend funktioniert
|
|||
|
|
4. Lizenzschluessel-Flow ist produktiv – nicht neu bauen
|
|||
|
|
5. Admin-Endpunkte sind produktiv – nicht neu bauen
|
|||
|
|
6. Direkt beim naechsten sinnvollen Block weitermachen (siehe Abschnitt 10)
|