Files
abdulive/docs/decisions/ADR-0005-zugangsdaten.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

4.0 KiB

ADR-0005: Zugangsdaten kommen aus der App, nicht aus der .env

Status: akzeptiert · Datum: 2026-09-09

Kontext

Das Toolkit braucht Client-ID und Client-Secret zweier Twitch-Apps, ein obs-websocket-Passwort und später Discord-/Bluesky-Zugänge. Der erste Entwurf sah dafür eine .env-Datei vor, die von Hand befüllt wird.

Das passt nicht zum Nutzer. Abdu ist Streamer, kein Entwickler. „Kopiere .env.example nach .env und trage sieben Werte ein" ist die Stelle, an der ein Werkzeug liegen bleibt. Und es kommt ein zweites Problem dazu, das für diesen Anwendungsfall besonders zählt: Wer eine Klartextdatei mit Zugangsdaten öffnet, während er sendet, hat sie live gezeigt.

Entscheidung

Zugangsdaten werden über einen Einrichtungs-Assistenten im Browser eingegeben, unter http://localhost:4792/setup. Gespeichert werden sie verschlüsselt in /db/secrets.json im Docker-Volume.

Die .env bleibt bestehen, enthält aber nur noch optionale Werte (Log-Level, Pfad zum Wiedergabepuffer). Ohne .env startet alles.

Damit fällt auch Port 4780 weg: Einrichtung, OAuth-Rücksprung und später Sichtungsseite und Dashboard laufen über einen Server auf Port 4792. Die Redirect-URI in der Twitch-App lautet entsprechend http://localhost:4792/callback.

Speicherung

Ort /db/secrets.json, benanntes Volume abdulive-db
Verfahren AES-256-GCM, Schlüssel in /db/.secret-key (Modus 0600)
Schlüssel wird beim ersten Start erzeugt, nie ausgegeben, nie geloggt
Nicht in SQLite damit das Backup-Skript sie nie mitkopiert

Die Secrets liegen bewusst außerhalb der Datenbank. scripts/backup.ps1 zieht die .db aus dem Volume nach data/db/backup/ — also auf die Windows-Seite, wo sie in einer Cloud-Synchronisation landen kann. Was dort nichts zu suchen hat, darf gar nicht erst in der Datenbank stehen.

Was diese Verschlüsselung leistet — und was nicht

Der Schlüssel liegt im selben Volume wie die verschlüsselten Daten. Gegen jemanden, der Zugriff auf das Volume hat, schützt das nicht, und es wird hier auch nicht so getan.

Wogegen es schützt, und das ist der eigentliche Zweck:

  • Versehentliche Anzeige im Stream. cat secrets.json zeigt Kauderwelsch, keine Client-Secrets.
  • Verirrte Kopien. Ein Volume-Export oder ein weitergegebener Ordner enthält ohne die Schlüsseldatei nichts Verwertbares.
  • Grep-Unfälle. Secrets tauchen in keiner Volltextsuche und in keinem versehentlich geteilten Log auf.

Gegen eine Kompromittierung der Maschine schützt es nicht. Das ist bei einem lokalen Einzelplatzwerkzeug auch nicht das Bedrohungsmodell — wer dort Zugriff hat, hat auch Zugriff auf OBS, den Browser und die gespeicherten Twitch-Cookies.

Konsequenzen für die Oberfläche

  • Der Einrichtungs-Assistent zeigt gespeicherte Secrets nie wieder an. Nach dem Speichern steht dort •••••• gespeichert und ein Knopf Ersetzen.
  • Über der Seite steht ein Hinweis: „Diese Seite zeigt Zugangsdaten — nicht im Stream öffnen."
  • Der Server ist nur lokal erreichbar. Nicht dadurch, dass er im Container auf 127.0.0.1 bindet — das wäre dort die Container-Loopback, die Dockers Portweiterleitung nie erreicht, der Dienst wäre schlicht tot. Die Abschottung kommt aus zwei Teilen: der Container bindet auf 0.0.0.0 innerhalb seines eigenen Netzwerk-Namensraums, und Compose veröffentlicht den Port ausschließlich als 127.0.0.1:4792. Außerhalb von Docker bindet der Server weiterhin auf die Loopback-Adresse; gesteuert über BIND_HOST, das nur das Image auf 0.0.0.0 setzt.
  • Secrets werden nie geloggt, auch nicht bei Fehlern. Der Logger maskiert bekannte Schlüsselnamen.
  • check-env meldet, ob Zugangsdaten hinterlegt sind, nie welche.

Preis

Der Einrichtungs-Assistent kostet in S1 ungefähr einen zusätzlichen Tag — kleiner HTTP-Server, eine Seite, der Secret-Speicher. Dafür entfällt der gesamte .env-Schritt aus der Inbetriebnahme, und das Werkzeug lässt sich später ohne Texteditor umkonfigurieren.