Files
abdulive/docs/01-architecture.md
T
ZeasyAlexandClaude Opus 5 d07c18441b S1: Einrichtungs-Assistent, Twitch-Auth, Datenbank und Chat-Aufnahme
Zugangsdaten kommen jetzt aus der App statt aus einer .env: ein
Einrichtungs-Assistent auf http://localhost:4792/setup nimmt Client-ID,
Secret und OBS-Passwort entgegen, der OAuth-Rueckruf laeuft auf denselben
Server. Gespeichert wird verschlueselt (AES-256-GCM) in einem Volume,
bewusst nicht in der Datenbank - die wird auf die Windows-Seite gesichert.
Siehe ADR-0005.

Technikbasis vereinfacht: Node 24 bringt node:sqlite, WebSocket, fetch und
die Ausfuehrung von TypeScript mit. Das Projekt hat damit null
Laufzeitabhaengigkeiten und keinen Build-Schritt; pnpm-Workspaces und die
Paketmanifeste sind entfallen, Importe laufen ueber die imports-Map der
Wurzel-package.json. erasableSyntaxOnly verhindert Syntax, die das Type
Stripping stillschweigend entfernen wuerde. Siehe Nachtrag 2 in ADR-0001.

Enthalten:
- packages/core: Config, Layout, Logger mit Secret-Maskierung, Retry, YAML
- packages/db: Migrationen, Repositories, alle SQL-Anweisungen an einem Ort
- packages/twitch: Secret-Speicher, OAuth, Helix mit Token-Bucket, IRC
- apps/ingest: Daemon, Einrichtungsseite, Spike-Erkennung
- 20 Tests (IRC-Parser, Spike-Detektor, Datenbankschicht)

Der Chat verbindet sich anonym, solange nichts hinterlegt ist - damit laesst
sich die Datenaufnahme pruefen, bevor die Twitch-Apps existieren.

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

6.3 KiB

Architektur

Bild

                    Twitch                     OBS
              ┌──────────────────┐        ┌───────────┐
              │ EventSub (WS)    │        │ obs-      │
              │ IRC / Chat       │        │ websocket │
              │ Helix REST       │        └─────┬─────┘
              └────────┬─────────┘              │
                       │                        │
              ┌────────▼────────────────────────▼────────┐
              │           apps/ingest  (Daemon)          │
              │  normalisiert alles zu Events            │
              └────────┬─────────────────────┬───────────┘
                       │                     │
             schreibt  │                     │  publiziert
                       ▼                     ▼
              ┌─────────────────┐   ┌──────────────────────┐
              │  SQLite         │   │  Event-Bus           │
              │  data/db/       │   │  (in-proc + WS 4790) │
              └────────┬────────┘   └──────────┬───────────┘
                       │                       │
   ┌───────────┬───────┼───────────┬───────────┼───────────┬──────────┐
   ▼           ▼       ▼           ▼           ▼           ▼          ▼
 dashboard  recap  raid-scout  vod-chapters community  overlay-   clipper
                                                        server       │
                                                          │          │
                                                    overlay-web   ffmpeg
                                                    (Browser-      whisper
                                                     Source)          │
                                                                 data/clips
                                                                      │
                                                                 broadcaster

Prozesse

Der Verbund besteht aus wenigen langlaufenden Prozessen und mehreren Kurzläufern, gestartet über docker compose up -d.

Im MVP gilt das noch nicht. Dort laufen Ingest und Clipper als ein Prozess in einem Container; die Aufteilung unten ist der Zielzustand ab Meilenstein M3, wenn es mehr als einen Konsumenten gibt. Siehe 07-mvp-plan.md.

Langläufer (laufen immer, auch offline):

Prozess Port Aufgabe
ingest 4790 (WS) EventSub, IRC, OBS-WS, Viewer-Polling → DB + Bus
overlay-server 4791 (HTTP+WS) liefert Overlay-Seiten, nimmt Chat-Commands entgegen
dashboard 4792 (HTTP) Analytics-UI

Kurzläufer (event- oder zeitgetriggert):

Prozess Trigger
clipper Clip-Event vom Bus, oder manuell über CLI
broadcaster stream.online
recap stream.offline (+ 5 min Karenz)
vod-chapters stream.offline
raid-scout manuell / Chat-Command !raidziel

community und loyalty sind keine eigenen Prozesse, sondern Module, die im overlay-server mitlaufen — sie brauchen dieselbe Chat-Verbindung und denselben WS-Kanal zum Overlay.

Event-Bus

Der Ingest normalisiert alles auf ein einheitliches Event-Format:

type StreamEvent = {
  id: string;            // ULID
  ts: string;            // ISO-8601, UTC
  type: EventType;       // 'chat.message' | 'stream.online' | ...
  streamId: string | null;
  userId: string | null;
  payload: unknown;      // typisiert pro EventType
};

Transport: In-Prozess ein EventEmitter, prozessübergreifend ein WebSocket-Broadcast auf ws://127.0.0.1:4790. Kein Kafka, kein Redis. Wenn ein Konsument abstürzt, holt er sich beim Neustart die verpassten Events aus der events-Tabelle über ts > lastSeen.

Vollständige Event-Liste: siehe 03-data-model.md.

Pakete

Paket Inhalt
packages/shared Ereignistypen, ULID
packages/core Config, Layout, Logger mit Maskierung, Retry, YAML-Leser
packages/twitch Secret-Speicher, OAuth, Helix-Client, IRC-Client
packages/db SQLite-Verbindung, Migrationen, Repositories

Regel: Apps dürfen von Paketen abhängen, Pakete nie von Apps. Apps hängen nicht voneinander ab — Kommunikation läuft über Bus und DB.

Importiert wird über die imports-Map der Wurzel-package.json (#core/config.ts, #db/repos.ts). Das ist eine Node-Funktion, kein Build-Werkzeug — es gibt keinen Bundler und keine Pfad-Aliasse im Compiler.

Technologie

  • TypeScript auf Node 24, ohne Build-Schritt und ohne Laufzeitabhängigkeiten — Node führt die .ts-Dateien direkt aus. Siehe ADR-0001
  • SQLite über das eingebaute node:sqlite — siehe ADR-0002
  • EventSub über WebSocket, nicht Webhooks — siehe ADR-0003
  • ffmpeg (CLI) für Videoverarbeitung
  • whisper.cpp (CLI) für Untertitel — kein Python, keine GPU
  • Serverseitiges HTML ohne Framework für Einrichtung und Sichtungsseite; für Dashboard und Overlays ab M3 ggf. Vite + Preact
  • Docker Compose für den Betrieb — siehe ADR-0004

Fehlerverhalten

  • Jeder Netzwerkaufruf hat Retry mit exponentiellem Backoff (packages/core/retry).
  • Der Ingest darf niemals wegen eines Konsumentenfehlers sterben. Konsumenten laufen in eigenen Prozessen; ein Fehler dort schreibt in logs/ und wird im Dashboard als Warnung angezeigt.
  • Wenn EventSub die Verbindung verliert: Reconnect mit Session-Resume, danach Lücke über Helix-Polling schließen (stream.online-Status, Follower-Liste).