V5 komplett: Auth, Admin, Federation, Channels, Devices, Cockpit, Profil, Autotext-Fix, Uebersetzer-Fix
Made-with: Cursor
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# AZA – Master Handover / Operational Runbook
|
||||
|
||||
## Arbeitsmodus / Regeln
|
||||
## Arbeitsmodus / Regeln (VERBINDLICH)
|
||||
|
||||
User bastelt nicht; nur Composer-Patches (meist Opus) oder 1 exakter Command mit Pfad.
|
||||
|
||||
@@ -8,10 +8,76 @@ User bastelt nicht; nur Composer-Patches (meist Opus) oder 1 exakter Command mit
|
||||
- User fuehrt nur vorgegebene Commands aus, keine manuellen Edits.
|
||||
- Jede Aenderung in 1 Patch, kein schrittweises Anleiten.
|
||||
- Keine risky Refactors – immer minimal und sicher.
|
||||
- KEINE Bastelloesungen, KEINE Prototypisierung, KEINE Zwischenloesungen.
|
||||
- KEINE localStorage-Geschaeftsdaten als Zielbild.
|
||||
- KEINE vagen „spaeter besser"-Loesungen.
|
||||
- KEINE Diffs als Hauptlieferung – nur vollstaendige fertige Dateien.
|
||||
- Immer dazuschreiben WO etwas auszufuehren ist: Browser / Windows PowerShell / Hetzner SSH / Composer.
|
||||
- Root-cause-first bei jedem Problem.
|
||||
- Nur Schritte empfehlen, die zur Live-Architektur passen.
|
||||
|
||||
## AKTUELLE PROJEKTPHASE (Stand 2026-04-12)
|
||||
## Server-Deploy-Realitaet (VERBINDLICH)
|
||||
|
||||
**Phase:** Device-/Seat-Logik V1 implementiert. Backup-Konzept + Deinstallations-UX als naechste Hauptbloecke.
|
||||
Hetzner `/root/aza-app` ist KEIN Git-Repository.
|
||||
Server-Updates laufen real ueber:
|
||||
1. Lokal aendern (Composer/Max)
|
||||
2. Per `scp` auf Hetzner hochkopieren
|
||||
3. Auf Hetzner: `cd /root/aza-app/deploy && docker compose up --build -d`
|
||||
|
||||
NICHT `git pull` auf Hetzner annehmen. Das funktioniert dort nicht.
|
||||
|
||||
## AKTUELLE PROJEKTPHASE (Stand 2026-04-18)
|
||||
|
||||
**Phase:** Praxis-Chat V5 live (Auth + Sessions + Tasks + Admin + Devices + Channels + Federation).
|
||||
Admin-Panel im Browser eingebaut. Naechste Bloecke: Admin real pruefen, Empfangs-Huelle NaN-Bug, Uebersetzer-Bug.
|
||||
|
||||
## BEKANNTE REGRESSIONEN + KORREKTUREN
|
||||
|
||||
### Autotext-Regression April 2026 (GEFIXT + EINGEFROREN)
|
||||
|
||||
**Root Cause:** Race Condition zwischen zwei gleichzeitig aktiven Autotext-Systemen:
|
||||
1. In-App-Autotext (`on_keyrelease` auf Tkinter Text-Widgets, `_bind_autotext()`)
|
||||
2. Globaler Autotext-Listener (pynput `_run_global_autotext_listener()`)
|
||||
|
||||
Der Fokusstatus (`_autotext_focus_in_app`) wird per PID-Check alle 1000ms aktualisiert.
|
||||
In dem Zeitfenster konnten beide Systeme feuern → doppelte Einfuegung.
|
||||
|
||||
**Symptome:**
|
||||
- Doppelte Autotext-Einfuegung in AZA-Textfeldern
|
||||
- Teils unzuverlaessiges Verhalten in externen Programmen
|
||||
|
||||
**Funktionierende Korrektur (basis14.py, `_bind_autotext()`):**
|
||||
- `_autotext_injecting`-Check am Anfang von `on_keyrelease`: ueberspringt wenn der
|
||||
globale Listener gerade injiziert
|
||||
- Deduplizierung: wenn dasselbe Wort innerhalb von 1 Sekunde erneut expandiert werden
|
||||
soll, wird es uebersprungen (`_last_expansion` mit Zeitstempel + Wort)
|
||||
- Kein grosser Umbau, nur minimale Absicherung
|
||||
|
||||
**Do-Not-Break-Regeln (VERBINDLICH):**
|
||||
- `_run_global_autotext_listener()` NICHT aendern (Freeze seit Maerz 2026)
|
||||
- `_bind_autotext()` NICHT aendern ausser bei reproduzierbarem Bug
|
||||
- `_periodic_focus_check()` NICHT aendern
|
||||
- `_check_autotext_focus_out()` NICHT aendern
|
||||
- Die `_last_expansion`-Deduplizierung NICHT entfernen
|
||||
- Den `_autotext_injecting`-Check in `on_keyrelease` NICHT entfernen
|
||||
- KEINE Disk-I/O in on_press/on_release
|
||||
- KEINE Aenderung der Timing-Konstanten (REPLACE_DELAY, 0.04s/0.01s, etc.)
|
||||
- Bei kuenftigen Aenderungen an basis14.py: Autotext-Bereich (Zeilen ~8825-9082) explizit
|
||||
NICHT anfassen, ausser bei reproduzierbarem Bug mit klarer Root Cause
|
||||
|
||||
## OFFENE REALE BUGS (Stand 2026-04-18)
|
||||
|
||||
1. **Empfangs-Huelle: Schriftgroesse NaN** (GEFIXT, Deploy ausstehend)
|
||||
- Root Cause: Huelle laedt alte empfang.html. Neue Version hat robustes parseInt + kein uiScale.
|
||||
- Fix: neue empfang.html per scp deployen
|
||||
|
||||
2. **Uebersetzer: Zielsprache wird nicht eingehalten** (GEFIXT, Neustart noetig)
|
||||
- Root Cause: `get_lang_codes()` fiel bei fehlendem ` – ` im Combo-Wert auf `"en"` zurueck
|
||||
- Fix: 3 Stellen in translate.py gefixt, Fallback nutzt gespeicherte Sprache
|
||||
|
||||
3. **`An Empfang senden` (`basis14.py`): noch nicht professionell**
|
||||
- ~1100 Zeilen `_send_to_empfang()` – Hochrisikobereich
|
||||
- Offen: Auto-Integration medizinischer Inhalte, Bilder, Chatfluss, Aktionsleiste
|
||||
|
||||
## VERBINDLICHE PROJEKTKONTINUITAET (ab 2026-04-12)
|
||||
|
||||
@@ -218,40 +284,190 @@ kurze Antworten, kein voller Hauptclient).
|
||||
|
||||
Festlegung: Mobile spaeter lieber als echte App, nicht als dauerhafte Browser-Notloesung.
|
||||
|
||||
#### 6.11 Aktueller Stand vs. Zielarchitektur
|
||||
#### 6.11 Praxis-zu-Praxis-Kopplung (VERBINDLICH, 2026-04-18)
|
||||
|
||||
**Was schon da ist (V1):**
|
||||
- Benutzer-Sync via Backend (`empfang_users.json`)
|
||||
- Thread-basierter Chat (thread_id, reply_to)
|
||||
- Aufgaben-Panel (localStorage, user-scoped)
|
||||
- 3-Panel-Layout im Browser-Empfang
|
||||
- Ton-/Benachrichtigungssystem
|
||||
- Empfangs-Desktop-Huelle
|
||||
Interne Kurzbezeichnung: **AZA Praxis-Federation**
|
||||
|
||||
**Was noch fehlt fuer V2:**
|
||||
- practice_id in allen Entitaeten
|
||||
- Echte Authentifizierung (JWT/Session)
|
||||
- Serverseitige Kanalstruktur
|
||||
- Serverseitige Aufgaben (statt localStorage)
|
||||
- Geraeteverwaltung fuer Praxis-Admin
|
||||
- QR-Code-Kopplung fuer Mobile
|
||||
**Grundprinzip:** Praxen sind standardmaessig vollstaendig getrennt.
|
||||
Eine Verbindung entsteht NUR durch explizite beidseitige Zustimmung.
|
||||
|
||||
**Ablauf:**
|
||||
1. Admin Praxis A erzeugt Verbindungseinladung (Einmal-Code, 48h gueltig)
|
||||
2. Admin Praxis B gibt Code ein und bestaetigt
|
||||
3. Serverseitig: `PracticeConnection`-Objekt wird angelegt
|
||||
4. Definierte externe Kommunikationsraeume werden freigeschaltet
|
||||
5. Jeder Admin kann die Verbindung jederzeit trennen
|
||||
|
||||
**Datenmodell `PracticeConnection`:**
|
||||
|
||||
| Feld | Typ | Beschreibung |
|
||||
|---|---|---|
|
||||
| `connection_id` | UUID | Eindeutige Verbindung |
|
||||
| `practice_a_id` | UUID | Initiierende Praxis |
|
||||
| `practice_b_id` | UUID | Annehmende Praxis |
|
||||
| `status` | enum | pending / active / revoked |
|
||||
| `created_by` | user_id | Admin der die Einladung erstellt hat |
|
||||
| `accepted_by` | user_id | Admin der angenommen hat |
|
||||
| `created_at` | timestamp | Erstellzeitpunkt |
|
||||
| `accepted_at` | timestamp | Annahmezeitpunkt |
|
||||
| `revoked_at` | timestamp | Trennzeitpunkt (optional) |
|
||||
| `shared_channels` | list | Freigegebene Kanaltypen |
|
||||
|
||||
**Externe Kanalstruktur bei Kopplung:**
|
||||
- Allgemeiner externer Kanal (Praxis A ↔ Praxis B)
|
||||
- Optional: Aerzte ↔ Aerzte (nur Aerzte beider Praxen)
|
||||
- Optional: Sekretariat ↔ Sekretariat
|
||||
- Jeder externe Kanal wird vom jeweiligen Admin freigegeben
|
||||
|
||||
**Sicherheitsregeln:**
|
||||
- Externe Nachrichten sind IMMER als extern markiert
|
||||
- Externe Benutzer sehen NUR den freigegebenen Kanal, NICHT interne Daten
|
||||
- Trennung sofort wirksam (kein Nachlauf)
|
||||
- Verbindungshistorie im Audit-Log
|
||||
|
||||
#### 6.12 Admin-Benutzerverwaltung (VERBINDLICH, 2026-04-18)
|
||||
|
||||
**Benutzer-Objekt (Mindestfelder):**
|
||||
|
||||
| Feld | Typ | Beschreibung |
|
||||
|---|---|---|
|
||||
| `user_id` | UUID | Eindeutiger Benutzer |
|
||||
| `practice_id` | UUID | Praxis-Zugehoerigkeit |
|
||||
| `display_name` | string | Anzeigename |
|
||||
| `email` | string | E-Mail (optional, fuer Passwort-Reset) |
|
||||
| `role` | enum | admin / arzt / mpa / empfang |
|
||||
| `status` | enum | active / deactivated / deleted |
|
||||
| `pw_hash` | string | PBKDF2-SHA256 |
|
||||
| `pw_salt` | string | Zufaelliger Salt |
|
||||
| `created_by` | user_id | Wer hat den Account angelegt |
|
||||
| `created_at` | timestamp | Erstellzeitpunkt |
|
||||
| `last_login` | timestamp | Letzter Login |
|
||||
| `deactivated_at` | timestamp | Deaktivierungszeitpunkt (optional) |
|
||||
|
||||
**Admin-Aktionen:**
|
||||
- Benutzer anlegen (mit Name, Rolle, optionalem Passwort)
|
||||
- Benutzer deaktivieren (Login gesperrt, Daten bleiben)
|
||||
- Benutzer reaktivieren
|
||||
- Benutzer endgueltig loeschen (DSGVO)
|
||||
- Rolle aendern (arzt ↔ mpa ↔ empfang, Admin nur durch anderen Admin)
|
||||
- Passwort zuruecksetzen (erzeugt temporaeres Passwort)
|
||||
- Alle Sitzungen eines Benutzers beenden
|
||||
|
||||
**Nachvollziehbarkeit:**
|
||||
- `created_by` zeigt wer den Benutzer angelegt hat
|
||||
- Rollenaenderungen im Audit-Log
|
||||
- Deaktivierung/Loeschung im Audit-Log
|
||||
|
||||
#### 6.13 Admin-Geraeteverwaltung (VERBINDLICH, 2026-04-18)
|
||||
|
||||
**Device-Objekt (Mindestfelder):**
|
||||
|
||||
| Feld | Typ | Beschreibung |
|
||||
|---|---|---|
|
||||
| `device_id` | UUID | Eindeutiges Geraet |
|
||||
| `user_id` | UUID | Zugehoeriger Benutzer |
|
||||
| `practice_id` | UUID | Zugehoerige Praxis |
|
||||
| `device_name` | string | z.B. "Praxis-PC Empfang", "iPhone" |
|
||||
| `platform` | string | Windows / macOS / iOS / Android / Browser |
|
||||
| `device_type` | enum | desktop / browser / mobile / tablet |
|
||||
| `user_agent` | string | Browser-/App-Kennung |
|
||||
| `last_active` | timestamp | Letzter API-Zugriff |
|
||||
| `first_seen` | timestamp | Erstmalige Registrierung |
|
||||
| `trust_status` | enum | trusted / pending / blocked |
|
||||
| `ip_last` | string | Letzte IP-Adresse |
|
||||
|
||||
**Admin sieht pro Benutzer:**
|
||||
- Alle registrierten Geraete
|
||||
- Typ (Desktop-Icon, Browser-Icon, Handy-Icon)
|
||||
- Letzter Zugriff (relativ: "vor 2 Stunden", "vor 3 Tagen")
|
||||
- Status-Badge (aktiv / verdaechtig / gesperrt)
|
||||
|
||||
**Admin-Aktionen:**
|
||||
- Geraet als vertrauenswuerdig markieren
|
||||
- Geraet sperren (sofort, alle Sitzungen werden beendet)
|
||||
- Geraet loeschen (aus der Liste entfernen)
|
||||
- Alle Sitzungen auf einem Geraet beenden
|
||||
- Erneute Anmeldung erzwingen
|
||||
|
||||
**Automatische Erkennung:**
|
||||
- Bei jedem Login: device_id wird aus User-Agent + fingerprint abgeleitet
|
||||
(oder Cookie-basiert fuer Browser)
|
||||
- Neues Geraet: Admin erhaelt optional Benachrichtigung
|
||||
- Zu viele Geraete: Warnung an Admin
|
||||
|
||||
#### 6.14 UI-Sichtbarkeit nach Rolle
|
||||
|
||||
**Admin sieht:**
|
||||
- Praxis-Einstellungen (Name, Einladungscode, Admin-E-Mail)
|
||||
- Alle Benutzer mit Rollen + Status + letztem Login
|
||||
- Alle Geraete aller Benutzer
|
||||
- Gekoppelte Praxen + Verbindungsstatus
|
||||
- Alle internen + externen Kanaele
|
||||
- Audit-Log
|
||||
|
||||
#### 6.12 Umsetzungsphasen
|
||||
**Arzt / MPA / Empfang sieht:**
|
||||
- Eigene Praxis (Name)
|
||||
- Eigene Kanaele (interner Allgemein + Rollen-Kanal + Direktchats)
|
||||
- Eigene Aufgaben + an eigene Rolle zugewiesene Aufgaben
|
||||
- Freigegebene externe Kanaele (falls Praxis-Kopplung aktiv)
|
||||
- Eigene Geraete (nur eigene, nicht die anderer Benutzer)
|
||||
|
||||
**Phase 1 (kurzfristig – aktuell):**
|
||||
Frontend-Layout, Benutzer-Sync, Chat-Threads. Kein Backend-Umbau.
|
||||
Einzelpraxis-Betrieb reicht. practice_id wird als Konzept vorbereitet,
|
||||
aber noch nicht erzwungen.
|
||||
**Externer Praxis-Kontakt sieht:**
|
||||
- NUR den freigegebenen externen Kanal
|
||||
- Keine internen Daten, Benutzer, Aufgaben der anderen Praxis
|
||||
|
||||
**Phase 2 (mittelfristig):**
|
||||
Backend: practice_id + user_id + JWT-Auth einfuehren. Kanalstruktur serverseitig.
|
||||
Aufgaben serverseitig. Geraeteverwaltung. Admin-Panel fuer Practice Admin.
|
||||
Presence/Heartbeat. Invite-Links.
|
||||
#### 6.15 Aktueller Stand (nach V4-Deploy, 2026-04-18)
|
||||
|
||||
**Phase 3 (spaeter):**
|
||||
Multi-Tenant produktiv (mehrere Praxen). WebSocket statt Polling. Mobile-App.
|
||||
QR-Code-Kopplung. 2FA. Verschluesselte Speicherung. Externe Praxis-Verbindungen.
|
||||
**Was jetzt implementiert ist:**
|
||||
- Serverseitige Auth: PBKDF2 + Session-Cookie (empfang_routes.py V4)
|
||||
- practice_id in allen Nachrichten + Benutzern + Aufgaben
|
||||
- Login / Setup / Register mit Einladungscode
|
||||
- Rollen: admin, arzt, mpa, empfang
|
||||
- Serverseitige Aufgaben (GET/POST/DELETE /tasks)
|
||||
- Browser-Empfang mit Login-Overlay, Server-only-Daten
|
||||
- Praxisname + Admin-E-Mail beim Setup
|
||||
- Einladungscode kopieren + erneuern (Admin)
|
||||
- 3-Panel-Layout (Sidebar, Chat, Aufgaben)
|
||||
- Ton-/Benachrichtigungssystem
|
||||
- Empfangs-Desktop-Huelle
|
||||
- Caddy Rewrite (empfang.aza-medwork.ch ohne /empfang/)
|
||||
|
||||
**Was als naechstes fehlt:**
|
||||
- Serverseitige Kanalstruktur (Allgemein, Aerzte, MPA statt flacher Thread-Liste)
|
||||
- Device-Tracking (device_id bei jedem Login)
|
||||
- Admin-Panel im Browser (Benutzer verwalten, Geraete sehen)
|
||||
- Praxis-zu-Praxis-Kopplung (Federation)
|
||||
- Audit-Log
|
||||
- QR-Code-Kopplung fuer Mobile
|
||||
|
||||
#### 6.16 Umsetzungsphasen (aktualisiert 2026-04-18)
|
||||
|
||||
**Phase 1 (ERLEDIGT):**
|
||||
Backend V4 mit Auth + practice_id + Sessions + Tasks.
|
||||
Browser-Empfang mit Login, Server-only-Daten, 3-Panel-Layout.
|
||||
Einzelpraxis-Betrieb produktiv moeglich.
|
||||
|
||||
**Phase 2 (naechster Hauptblock):**
|
||||
- Serverseitige Kanalstruktur (Channel-Objekte im Backend)
|
||||
- Device-Tracking bei jedem Login
|
||||
- Admin-Panel im Browser: Benutzer verwalten, Geraete sehen
|
||||
- Presence/Heartbeat (Online-Status)
|
||||
- Hauptfenster `_send_to_empfang()` aufraumen (AO2/AO4/AO5/AO6)
|
||||
|
||||
**Phase 3 (mittelfristig):**
|
||||
- Praxis-zu-Praxis-Federation
|
||||
- WebSocket statt Polling
|
||||
- Mobile-App (iPhone/Android)
|
||||
- QR-Code-Kopplung
|
||||
- 2FA fuer Admin
|
||||
- Verschluesselte Nachrichtenspeicherung
|
||||
|
||||
**Phase 4 (spaeter):**
|
||||
- Multi-Praxis produktiv (mehrere zahlende Praxen)
|
||||
- Apple Watch / Wearable (nur Benachrichtigungen)
|
||||
- Externe Praxis-Kanaele
|
||||
- DSGVO-Loeschfunktionen
|
||||
- Audit-Export
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user