Files
abdulive/docs/decisions/ADR-0006-ein-dach.md
T
ZeasyAlexandClaude Opus 5 684f10eb02 S2: obs-websocket, Wiedergabepuffer und der !clip-Ausloeser
Eigener obs-websocket-v5-Client (das Protokoll ist klein genug, und das
Projekt bleibt ohne Abhaengigkeiten). Anmeldung, Wiederverbindung mit
wachsender Pause, Ereignisse fuer ReplayBufferSaved und Szenenwechsel.

Der Clipper loest zwei Wege gleichzeitig aus: OBS-Wiedergabepuffer fuer die
Rohdatei in Aufnahmequalitaet, Twitch-Clip fuer die teilbare URL. Faellt
einer aus, ist der andere trotzdem etwas wert. Ein direkt in OBS gedrueckter
Hotkey wird ohne unseren Umweg erkannt und als vollwertiger Ausloeser
behandelt.

Die Pfaduebersetzung Windows -> Container hat eine eigene Datei und eigene
Tests - das ist die Stelle, an der die Pipeline am ehesten scheitert. Dazu
Warten auf den abgeschlossenen Schreibvorgang, bevor die Datei uebernommen
wird.

Zum Testvektor der OBS-Anmeldung: die Spezifikation nennt Salt und Challenge,
aber kein erwartetes Ergebnis. Der Erwartungswert wurde unabhaengig mit
Pythons hashlib aus derselben Beschreibung gerechnet; der Test sagt das im
Kommentar, statt einen amtlichen Vektor vorzutaeuschen.

29 Tests gruen. Die Abnahme von S2 braucht ein laufendes OBS und steht aus.

Ausserdem: ADR-0006 haelt fest, dass alles unter einem Dach laeuft - eine
lokale Weboberflaeche plus Kindprozesse fuer Rechenarbeit. Die Prozessliste
in der Architekturdoku ist entsprechend ersetzt. Der Onboarding-Assistent
ist als Teil von S5 aufgenommen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VTGjd92LsDDWF3frd9FTB
2026-09-09 10:10:54 +02:00

82 lines
4.2 KiB
Markdown

# ADR-0006: Ein Dach — lokale Weboberfläche, lokale Arbeitsprozesse
**Status:** akzeptiert · **Datum:** 2026-09-09
## Kontext
Die ursprüngliche Architektur ([`01-architecture.md`](../01-architecture.md))
sah neun weitgehend eigenständige Apps vor, die über einen Event-Bus reden, und
drei getrennte Langläufer (Ingest, Overlay-Server, Dashboard). Beim Bau von S1
hat sich gezeigt, dass das für diese Größe zu viel Struktur ist.
Die Frage, die dahinter steht: Soll alles über **eine Weboberfläche** bedienbar
sein, mit lokalen Komponenten dort, wo tatsächlich lokal gearbeitet werden muss
(Video, OBS, Chat)?
## Entscheidung
Ja. Das Toolkit ist eine **lokale Web-Anwendung**: ein Prozess, der die
Oberfläche ausliefert und die Dauerverbindungen hält, plus **Kindprozesse für
schwere oder abstürzgefährdete Arbeit**.
```
Browser (localhost:4792) OBS ────────┐
│ eine Oberflaeche, │ obs-websocket
│ neun Werkzeuge als Seiten │
▼ ▼
┌──────────────────────────────────────────────────────┐
│ toolkit (ein Node-Prozess, ein Container) │
│ │
│ Weboberflaeche · Einrichtung · Sichtung · Dashboard │
│ Ingest: IRC, EventSub, Helix-Polling │
│ Module: Community, Loyalty, Raid, Recap, Kapitel │
│ Overlay-Server fuer die OBS-Browser-Quellen │
└───────────────┬──────────────────────────────────────┘
│ spawn, ueberwacht, darf abstuerzen
▼
ffmpeg · whisper.cpp SQLite (Volume)
```
## Begründung
**Die Trennlinie verläuft nicht zwischen Werkzeugen, sondern zwischen
Verbindungshalten und Rechenarbeit.** Die neun Werkzeuge teilen sich
Chat-Verbindung, Datenbank und Oberfläche — sie zu trennen erzeugt nur
Verbindungsverdopplung und Abstimmungsaufwand. Was dagegen wirklich getrennt
gehört, ist alles, was minutenlang die CPU belegt oder abstürzen kann: ffmpeg
und whisper. Die laufen als Kindprozesse und dürfen scheitern, ohne die
Chat-Aufnahme mitzureißen.
**Eine Oberfläche ist der eigentliche Gewinn.** Neun Werkzeuge, die man einzeln
starten und einzeln aufrufen muss, benutzt man nach zwei Wochen nicht mehr. Ein
Tab mit Navigation ist der Unterschied zwischen Werkzeugkasten und
Bastelkeller.
**Lokal, nicht Cloud.** Die Oberfläche liegt auf demselben Rechner wie OBS. Das
ist keine Einschränkung, sondern Voraussetzung: Replay-Buffer, Szenenwechsel und
Videoverarbeitung brauchen die lokale Maschine ohnehin. Es gibt nichts zu
verteilen.
## Konsequenzen
- **Der Ingest darf nie sterben.** Er läuft im selben Prozess wie die
Oberfläche, also gilt: jede Route hat eigenes Fehlerabfangen, kein
Oberflächenfehler beendet den Prozess. Rechenarbeit läuft ausschließlich in
Kindprozessen.
- **Die Oberfläche ist eine Sicht auf Zustand, kein Ort für Zustand.** Alles
Dauerhafte steht in SQLite. Ein Neustart der Oberfläche verliert nichts.
- **Neustart heißt Chat-Lücke.** Wer während eines Streams eine Änderung
ausrollt, verliert ein paar Sekunden Chat. Das ist hinnehmbar; wenn es stört,
lässt sich der Ingest später als eigener Prozess herauslösen — die Naht dafür
ist die Datenbank und existiert bereits.
- **Kein Fernzugriff, keine Anmeldung.** Der Dienst ist an `127.0.0.1` des
Hosts gebunden. Falls Abdu später vom Handy auf das Dashboard schauen will,
ist der Weg ein Tunnel (Tailscale, Cloudflare Tunnel) — **nicht** ein
geöffneter Port mit selbstgebauter Anmeldung.
- **Gefahr Rumpelkammer.** Neun Werkzeuge unter einer Navigation werden
unbrauchbar, wenn die Oberfläche einfach wächst. Gegenmaßnahme: die Startseite
zeigt den aktuellen Stream und die anstehenden Entscheidungen (Clips zum
Freigeben, Raid-Vorschläge, Erstchatter), nicht eine Liste von Werkzeugen.
- Die Prozessliste in [`01-architecture.md`](../01-architecture.md) ist damit
überholt und wurde ersetzt.