This repository has been archived on 2026-09-17. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
nixos-config/docs/live-intent.md
pijukka c8cfdcd88e host(pinix): add live intent and ereader viewer services
Both run on pinix, published only through the pinix Tailnet namespace and
Traefik's web-internal entrypoint (unbound local-data + Headscale split
DNS for intent./ereader.domain2). Live Intent reads its OpenAI key from
the new pinix-only agenix secret.

ereaderViewer is a path: flake input for now; the repo split plan moves
it into its own repository on cgit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:18:55 +02:00

5.2 KiB

Live Transkript auf pinix

intent.<domain2> ist ein kleiner, ausschließlich im pinix-Tailnet erreichbarer Sprachchat für Planungs-Gespräche. Er erzeugt keinen Intent, erstellt keine Tickets und führt weder Codex-Aufträge noch andere Aktionen aus. Ein Gespräch wird nach dem Auflegen als lokales Markdown-Transkript gespeichert; die spätere Weiterverwendung im Codex-Abo ist bewusst ein manueller Schritt außerhalb dieser Anwendung.

Ablauf und Kosten

Der Browser verbindet sich per WebRTC direkt mit GPT-Live. Pinix tauscht nur das SDP-Angebot mit POST /v1/live/sessions aus; der OpenAI-Schlüssel bleibt als systemd-Credential auf dem Server. Der Browser wartet auf session.started und sendet beim Beenden session.close. Nach session.closed speichert er die empfangenen Transkriptabschnitte direkt lokal. Es gibt keinen separaten /api/draft- oder Responses-Aufruf beim Abschluss und keinen Intent-Formatzwang. Audio wird nicht aufgezeichnet.

Die Oberfläche schließt eine Session standardmäßig nach zehn Minuten. Das ist eine Begrenzung für normale Browsernutzung, aber keine serverseitige Abrechnungsgarantie bei manipulierten Clients. GPT-Live wird nach Dauer abgerechnet. Die weiterhin aktivierte Responses-Delegation kann während des Gesprächs separat kostenpflichtige API-Nutzung auslösen; das Speichern des Transkripts selbst ruft kein Modell auf.

Der Live-Default ist gpt-live-1. chatgpt-live-1 wurde in den überprüften offiziellen Referenzen nicht als Live-Modell gefunden und wird deshalb nicht still ersetzt. Beide Modelle bleiben über services.liveIntent.liveModel und services.liveIntent.backendModel konfigurierbar. Der Default gpt-5.6-luna für die in-session Responses-Delegation hat keine Tools und kann keine Aktion ausführen.

Speicherung und Fehlerverhalten

Neue Gespräche liegen mit restriktiven Rechten unter:

/var/lib/live-intent/transcripts/<YYYY-MM-DD-UUID>/transcript.md

Der Browser erzeugt die Gesprächs-ID beim Start und behält sie für einen Speicherwiederholungsversuch. Der Server validiert ID und Inhalt, schreibt in einen neuen Ordner atomar und gibt bei exakt demselben Retry dieselbe Datei zurück, ohne eine zweite Datei anzulegen. Abweichender Inhalt für dieselbe ID ergibt einen Konflikt statt eines Überschreibens. Der Download-Link ruft genau diese transcript.md ab.

Bei normal bestätigtem session.closed steht Session-Abschluss: bestätigt in der Datei. Endet der Datenkanal ohne diese Bestätigung oder läuft der 15-Sekunden-Abschluss-Fallback ab, versucht die UI trotzdem die bis dahin empfangenen Abschnitte zu speichern und kennzeichnet die Datei ehrlich als unbestätigt. Ohne empfangene Textabschnitte kann keine Datei erzeugt werden; die UI zeigt dies als Fehler an. Eine vollständige Disconnect- oder Kostenabsicherung ist nicht Teil dieses Prototyps.

Der bestehende StateDirectory bleibt erhalten. Alte Dateien unter /var/lib/live-intent/intents/ werden weder gelesen, verändert noch gelöscht.

Schutzmaßnahmen und Schlüssel

Der Dienst verwendet einen DynamicUser, StateDirectory, UMask=0077, begrenzte Anfragekörper, atomisches Schreiben sowie strikte ID-/Pfadvalidierung. Schreibende Endpunkte prüfen den exakten HTTPS-Origin. Die Traefik-Route nutzt nur web-internal; der Split-DNS-Eintrag verweist nur auf die private Tailnet-Adresse. Es gibt keinen öffentlichen Router und keine zusätzliche Firewall-Freigabe. Server-Logs enthalten weder SDP, Transkripte noch Schlüssel.

Die statische UI und die lokale Transkript-API funktionieren ohne Credential; nur das Starten einer Live-Session antwortet dann kontrolliert mit HTTP 503. Der OpenAI-Schlüssel gehört ausschließlich als agenix-Datei secrets/liveIntentOpenaiApiKey.age in eine einzelne OPENAI_API_KEY=…-Zeile. Das Modul reicht sie als systemd- LoadCredential weiter; sie erscheint weder im Browser noch im Nix-Store oder in einer HTTP-Antwort.

Prüfung und Aktivierung

Für Quellcode-Tests:

node --test services/live-intent/tests/server.test.mjs

Der dokumentierte pinix-Weg nutzt einen selektiven, nicht löschenden rsync in /home/drone/nixos-config-build und baut anschließend auf pinix lokal:

ssh pinix 'cd /home/drone/nixos-config-build && sudo nixos-rebuild switch --flake path:.#pinix --no-reexec'

Danach im Tailnet https://intent.<domain2> öffnen, Mikrofon freigeben, eine Session starten, einige Transkriptzeilen erzeugen, regulär auflegen und den Download prüfen. Ein echter Browser-/Audio-Test benötigt ein geeignetes Mikrofon und verursacht GPT-Live-Kosten; er ist nicht durch die Offline-Tests abgedeckt.

Offizielle OpenAI-Referenzen