Files
rustification-server/docs/realtime/issues/01-research-webrtc-tauri-mobile.md
MDietermann 55a2af4756 docs(realtime): record the design decisions behind the realtime layer
Eleven resolved decision tickets plus two research notes, produced with
/wayfinder before any code was written. They live next to the code they explain
rather than in the issue tracker: they are reasoning documents, not open work,
and in a tracker they would drift from the code with no diff and no review.

The value is in the rejected alternatives. Why a counter under a row lock and
not BIGSERIAL, why an event log and not a column on messages, why resync is a
200 with a discriminated body and not a 4xx, why the fan-out trait was deleted
again, why voice is peer-to-peer with a hard six-person cap and no speculative
SFU seam, and why Linux needs a native media stack while the other three
platforms do not.

Two entries record where the spec was wrong and got corrected: created_at was
never a safe sort key, and an unread count cannot be derived without fetching
because seq counts events rather than messages.

Open work is tracked as issues, not here.
2026-08-14 19:04:41 +02:00

88 lines
4.6 KiB
Markdown

# Recherche: WebRTC im Tauri-WebView (Mobile)
Type: research
Status: resolved
Blocked by: —
Parent: ../map.md
## Question
Funktioniert WebRTC — insbesondere `getUserMedia` für Mikrofonzugriff und `RTCPeerConnection` —
im WebView einer Tauri-v2-App auf **Android** und **iOS**? Und wenn ja, unter welchen
Bedingungen?
Das ist die riskanteste Unbekannte des gesamten Efforts. Fällt die Antwort negativ aus,
ist das Voice-Signaling-Design für die Hälfte der Zielplattformen wertlos, und die
Voice-Topologie-Frage sieht völlig anders aus.
### Zu klären
- **iOS**: Tauri v2 rendert in `WKWebView`, nicht in Safari. `getUserMedia` ist dort
historisch problematisch gewesen. Gilt das noch? Ab welcher iOS-Version? Braucht es
Entitlements, `Info.plist`-Einträge (`NSMicrophoneUsageDescription`), oder
WebView-Konfiguration, die Tauri nicht standardmäßig setzt?
- **Android**: Tauri v2 nutzt Android System WebView. Wie werden
`PermissionRequest`-Callbacks (`RESOURCE_AUDIO_CAPTURE`) durchgereicht? Muss die
Tauri-App das abfangen, oder passiert es automatisch?
- **Berechtigungen**: Wie beantragt eine Tauri-v2-App Mikrofonrechte auf beiden
Plattformen? Gibt es dafür ein offizielles Plugin oder Muster?
- **Alternative**: Falls WebView-WebRTC ausfällt — gibt es einen brauchbaren nativen
Pfad? (`webrtc-rs` im Tauri-Rust-Layer, Audio-Streams zwischen Rust und WebView).
Reifegrad, Mobile-Tauglichkeit, Aufwand.
- **Desktop-Gegenprobe**: Läuft es auf Windows (WebView2) und Linux (WebKitGTK)?
Auf Linux ist WebRTC in WebKitGTK-Builds nicht selbstverständlich einkompiliert.
### Quellenqualität
Primärquellen bevorzugen: Tauri-v2-Dokumentation und Issue-Tracker, WebKit-/Chromium-
Release-Notes, Apple-Entwicklerdoku. Blogposts nur als Hinweisgeber, nicht als Beleg —
und immer mit Datum, dieses Feld bewegt sich.
### Erwartetes Ergebnis
Eine Markdown-Datei im Repo mit: klarer Ja/Nein/Teilweise-Antwort pro Plattform,
den nötigen Konfigurationsschritten, den Versionsuntergrenzen, und den Quellen. Wenn
irgendwo „unklar" steht, muss dabeistehen, welches Experiment die Frage entscheiden würde.
## Answer
Vollständiges Ergebnis: [`../research/01-webrtc-tauri-mobile.md`](../research/01-webrtc-tauri-mobile.md)
| Plattform | Antwort | Aufwand |
|---|---|---|
| **iOS** (WKWebView) | **Ja**, ab 14.3 (praktisch 15.0) | eine Zeile: `NSMicrophoneUsageDescription` in `Info.ios.plist` |
| **Android** (System WebView) | **Ja**, ab API 21 | zwei Manifest-Zeilen: `RECORD_AUDIO` **und** `MODIFY_AUDIO_SETTINGS` |
| **Windows** (WebView2) | **Ja**, ohne Konfiguration | — |
| **Linux** (WebKitGTK 4.1) | **Nein** | drei unabhängige Gates, eines davon distro-seitig unlösbar |
**Council-Risiko 2 ist positiv aufgelöst.** Mobile trägt WebRTC im WebView; das
Voice-Signaling-Design ist für Android und iOS nicht wertlos. *Voice-Topologie* ist entblockt.
Belegt gegen die tatsächlich aufgelösten Versionen (`wry 0.55.1` über
`tauri-runtime-wry 2.11.4` mit `^0.55.0`), nicht gegen `dev` — wichtig, weil wry 0.56
die Permission-Lage geändert hat, aber von Tauri 2.11.x nicht gezogen werden kann.
### Drei Befunde, die andere Tickets verändern
1. **Der Problemfall ist Linux, nicht Mobile.** `ENABLE_WEB_RTC` folgt
`ENABLE_EXPERIMENTAL_FEATURES` (= OFF); Debian/Ubuntu und Alpine setzen es belegbar
nicht. Dazu `WebKitSettings:enable-webrtc` Default FALSE (von wry nie gesetzt) und
`permission-request` Default Deny (in 0.55.1 nicht verbunden). Gate 2 und 3 wären per
`with_webview` lösbar — Gate 1 hängt am Distro-Paket des Nutzers.
→ eigenes Ticket *Voice auf Linux*.
2. **Der Signaling-Server kann DTLS-Fingerprints tauschen** (RFC 8827) und damit den
Audio-Stream vollständig MITMen. Der spezifizierte Gegenmechanismus (W3C Identity for
WebRTC, IdP) ist in **keiner** der vier Ziel-Engines implementiert. Fingerprints müssen
durch einen E2EE-authentifizierten Kanal übertragen und gepinnt werden.
→ harte Randbedingung für *Voice-Signaling-Protokoll*.
3. **wry vergibt Mikrofonrechte ohne App-Beteiligung** — auf iOS in 0.55.1 bedingungslos
`Grant` für jeden Origin. Unkritisch, solange nur eigener gebündelter Code im WebView
läuft; sofort kritisch, sobald fremde Origins (iframe, Preview-Einbettung) dazukommen.
→ Architekturregel in den Notes der Map.
### Offen (blockiert die Spec nicht, gehört vor die Implementierung)
Sieben benannte Experimente in §8 der Ergebnisdatei. Höchste Priorität E1: `getUserMedia`
auf einem physischen iPhone, je einmal mit und ohne Info.plist-Key — entscheidet zugleich
das offene Upstream-Issue tauri#12068.