1 Architektur
chinux edited this page 2026-05-30 18:31:17 +00:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Architektur

Datenfluss

PWA (Mikro/Text)
      │  Audio bzw. Text  (+ OIDC-Bearer-Token)
      ▼
FastAPI Backend
      │
      ├─► faster-whisper   Audio → Text (deutsch)         [nur bei Sprachaufnahme]
      │
      ├─► OpenRouter LLM   Text → strukturiertes JSON
      │
      ▼
Review-Karte (Frontend)   Nutzer bestätigt / korrigiert
      │
      ▼
CalDAV  →  Nextcloud      VEVENT (Termin) / VTODO (Aufgabe)

authentik (OIDC) hängt vorne an PWA und Backend: die PWA holt per Authorization Code + PKCE ein Token, das Backend validiert es bei jedem Request gegen die JWKS von authentik.

Komponenten

Teil Technik Aufgabe
Frontend React + Vite + vite-plugin-pwa Erfassung, Review, Einstellungen, PWA-Installierbarkeit
Backend FastAPI Orchestrierung, Token-Prüfung
STT faster-whisper (large-v3-turbo) Audio → Text
LLM OpenRouter (OpenAI-kompatibel) Text → strukturierter Eintrag
Kalender CalDAV (python caldav + icalendar) Schreiben in Nextcloud
Auth authentik OIDC Zugangsschutz

Wichtige Designentscheidungen

  • Single-Tenant: genau eine Nextcloud. Die CalDAV-Zugangsdaten liegen als Secret in der .env (Nextcloud-App-Passwort) kein verschlüsselter Pro-Nutzer-Speicher, keine eigene Datenbank nötig.
  • OIDC ≠ CalDAV-Auth: OIDC sichert nur die App. Das Schreiben in die Nextcloud läuft über das CalDAV-App-Passwort, da Nextcloud-CalDAV kein OIDC spricht.
  • Review-Schritt ist Pflicht: STT und LLM können sich bei Eigennamen und Uhrzeiten irren. Vor dem Schreiben sieht der Nutzer das Ergebnis und kann es korrigieren.
  • Relative Zeiten: Das Backend gibt dem LLM den aktuellen Zeitpunkt, Wochentag und die Zeitzone mit, damit Angaben wie „morgen 15 Uhr" korrekt aufgelöst werden.
  • Konfigurierbares Modell: Das LLM-Modell wird nicht hart kodiert, sondern zur Laufzeit aus einer kleinen JSON-Datei gelesen und ist über die Einstellungen in der App umstellbar.

Container

docker compose startet zwei Dienste:

  • backend FastAPI/uvicorn, intern auf Port 8000, mit Volumes für den Whisper-Modell-Cache und die Laufzeit-Einstellungen.
  • frontend nginx, liefert das gebaute React-Bundle aus und proxyt /api intern auf das Backend. Nach außen ist nur dieser Dienst (Port 8080) sichtbar davor gehört ein Reverse Proxy mit HTTPS.