# Plan: Offline-/Fehler-Robustheit (und ihr Wow-Effekt)

Stand: 2026-08-07 · Status: **Entwurf zur Freigabe** · kein Code

## Warum
Der AD arbeitet **im Auto** – Netz bricht weg (Funkloch, Tunnel, Tempo). Heute hängen mehrere Schritte
am Netz: Besuche laden (`/visits`), Briefing/Report (`/preparation`, `/report`), und vor allem das
**Live-Voice-Gespräch** (LiveKit + xAI). Fällt das Netz während der Doku, ist der Kern-Flow betroffen.

## Was heute passiert (Ist)
- **HTTP-Reads** (Liste/Briefing/Report): Fehlerzustände vorhanden (Error-View + Retry), aber jeder
  Neustart lädt frisch → offline = leere/fehlerhafte Ansicht.
- **Voice-Doku:** LiveKit trennt bei Netzverlust (`participant_disconnected`); die laufende Extraktion
  kann verloren gehen. Das ist der schmerzhafteste Fall.
- **Kein lokaler Cache**, keine Warteschlange für später.

## Bausteine (nach Wirkung)
**Eine** Nummerierung, in Bau-Reihenfolge (früher gab es zwei widersprüchliche – bereinigt).

1. **Offline-Banner:** dezentes Banner via `NWPathMonitor`, damit der AD weiß, warum etwas nicht
   aktuell ist. *Aufwand: klein. Wow: klein-mittel (Vertrauen).*
2. **JSON-Lese-Cache (Offline-Ansicht):** letzte `/visits` + je Besuch `preparation`/`report` lokal als
   JSON-Datei cachen. Offline → letzter Stand statt Fehler, mit „Stand von HH:mm"-Hinweis.
   *Aufwand: mittel. Wow: mittel (App fühlt sich verlässlich an).*
3. **Freigabe-Queue:** Freigabe (`POST /freigabe`) offline vormerken → automatisch senden, sobald online,
   mit klarem Status („wird gesendet, sobald wieder online"). *Aufwand: mittel. Wow: mittel.*
4. **Voice-Resilienz (aufwändig, größter Wow):** bei kurzem Abbruch **automatisch reconnecten** und die
   Session fortsetzen; bei längerem Ausfall die **gesammelten Turns lokal sichern** und die Extraktion
   nachziehen. *Aufwand: hoch (LiveKit-Reconnect + Turn-Persistenz + Nachlauf-Extraktion). Wow: HOCH.*
5. **On-Device-STT — NICHT im PoC (Go-Live).** `SFSpeechRecognizer` nähme das Gespräch auch ohne Netz auf,
   Extraktion später serverseitig. Bewusst nicht im PoC (Elmar, 2026-08-07) – verändert die Architektur.

**Umfang jetzt (freigegeben): 1 + 2 + 3** (Banner + JSON-Cache + Freigabe-Queue).
**#4 Voice-Resilienz** später (aufwändigster Wow-Schritt), **#5** Go-Live.

## Cache-Technik: JSON-Dateien vs. SwiftData

**Frage:** Aktuell liegt alles als JSON. Später Umzug auf **Supabase** (Postgres). Was macht Sinn?

**JSON-Datei-Cache** (Codable → Documents-Ordner):
- Die dekodierten Server-Antworten (`/visits`, `preparation`, `report`) als Datei ablegen, beim Start lesen.
- **Pro:** trivial, passt 1:1 zu den bestehenden JSON-Kontrakten, keine Schema-Migration, leicht zu debuggen.
- **Contra:** kein Abfragen/Filtern, ganze Blobs, manuelle Invalidierung, keine Beziehungen. Für einen
  **Lese-Cache** von wenigen Besuchen/Berichten aber völlig ausreichend.

**SwiftData** (Apple, iOS 17+, Nachfolger von Core Data):
- Echter lokaler Store mit Abfragen (`@Query`), Beziehungen, Change-Tracking – der **Stand der Technik**
  für On-Device-Persistenz in SwiftUI und die übliche Basis **offline-first** Apps.
- **Contra:** zweite Modell-Schicht (`@Model`-Klassen parallel zu den Codable-DTOs), Migrationen, mehr Zeremonie.

**Was Offline-Apps generell tun:** offline-first heißt meist **lokale DB als Wahrheit** (SQLite via
SwiftData/Core Data, GRDB oder Realm), die mit dem Server **synct**. Für echtes Offline-first führt an
einer lokalen DB kein Weg vorbei.

**Bezug Supabase:** `supabase-swift` hat **keine** eingebaute Offline-Persistenz/Sync (anders als z. B.
Firebase Firestore). D. h. für Offline-first bei Supabase baut man den lokalen Store **selbst** – dann ist
SwiftData der natürliche Spiegel der Supabase-Tabellen + eine Sync-Schicht.

**Empfehlung (gestaffelt):**
- **Jetzt (PoC):** **JSON-Datei-Cache.** Billig, deckt „letzten Stand offline zeigen" ab, passt zu den
  JSON-Kontrakten. Kein Over-Engineering (Simplicity First) für eine Handvoll Lese-Blobs.
- **Go-Live (Supabase, echtes Offline-first):** **SwiftData** als lokaler Store + Sync gegen Supabase.
  Dort zahlt sich die DB aus (Queries, Beziehungen, Change-Tracking, Konfliktbehandlung).

Der Migrationsaufwand JSON→SwiftData ist gering; der Lese-Cache ist ohnehin gekapselt.

## Wow-Effekt – ehrliche Einordnung
- **Kein sichtbares Feature, sondern Vertrauen.** „Offline funktioniert" beeindruckt in der Demo nur,
  wenn man es **inszeniert**: Flugmodus an → App zeigt weiter Tour/Briefing (Cache), Doku läuft weiter
  bzw. bricht sauber ab und **geht nichts verloren** → Netz wieder an → alles synct. Das ist ein starker
  „im-Auto-tauglich"-Beweis.
- **Größter Wow-Hebel:** Baustein **4 (Voice-Resilienz)** – der Moment „Netz weg mitten im Reden, aber
  meine Doku ist trotzdem sicher" trifft genau die Zielgruppen-Angst.
- **Bestes Aufwand/Wirkung fürs erste:** Bausteine **1 + 2 + 3** (Banner + Cache + Freigabe-Queue)
  liefern eine spürbar verlässliche App mit überschaubarem Aufwand; **4** als Ausbaustufe mit dem
  eigentlichen Wow.

## Bau-Reihenfolge (jetzt: 1–3) mit Verifikation
1. **Offline-Banner** (`NWPathMonitor`) → *verify:* Flugmodus zeigt Banner.
2. **JSON-Lese-Cache** für `/visits` (+ Briefing/Report) → *verify:* offline zeigt letzten Stand.
3. **Freigabe-Queue** → *verify:* offline freigeben → sendet bei Reconnect.
4. *(später)* **Voice-Resilienz** → *verify:* Netz-Drop in der Doku, nichts geht verloren.

## Offene Entscheidungen
- **A.** ~~Reihenfolge~~ → **entschieden:** jetzt **1 + 2 + 3** (Banner + Cache + Freigabe-Queue),
  **4 (Voice-Resilienz)** später.
- **B.** ~~Cache-Technik~~ → **entschieden:** JSON-Cache im PoC, SwiftData bei Go-Live (Supabase).
- **C.** ~~On-Device-STT~~ → **entschieden:** klar Go-Live, nicht PoC (gemerkt).
