Drei eng zusammenhaengende Aenderungen in einem Commit, da sie dieselbe
Template-Infrastruktur teilen und gemeinsam die HTML-Diagnoseansicht
abrunden:
1. CSS-Extraktion (Verbesserung, kein Verhalten geaendert)
Das bisherige Inline-CSS wurde in die Konstante statusPageCSS
ausgelagert. statusPageCSSBlock injiziert es per String-Konkatenation
in alle Templates, sodass kein Template-Inheritance-Mechanismus
benoetigt wird und jede Seite eigenstaendig ausfuehrbar bleibt.
2. GET /status/{screenId} -- neue HTML-Detailseite
Zeigt den letzten bekannten Datensatz eines einzelnen Screens:
Derived State, Player-Status, Connectivity und Frische als
Summary-Cards; Timing- und Endpoints-Details in aufgeraeuemten
Key-Value-Tabellen. Verlinkung zurueck auf /status und auf den
bestehenden JSON-Endpunkt. Bei unbekanntem Screen: 404 mit HTML-
Fehlerseite und Rueck-Link.
Route: GET /status/{screenId}
3. HTML-Fehlerseite fuer /status bei ungueltigen Query-Parametern
Bisher lieferte handleStatusPage einen rohen JSON-Fehler, wenn
z.B. ?stale=banana uebergeben wurde -- inkongruent fuer einen
HTML-Endpunkt. writeStatusPageQueryError rendert jetzt dasselbe
statusPageErrorTemplate wie der Not-Found-Fall der Detailseite
und gibt text/html mit 400 zurueck.
Neue Tests (router_test.go):
- ScreenDetailPageRoute: prueft Inhalt, Links, Content-Type
- ScreenDetailPageNotFound: prueft 404 + HTML + Rueck-Link
- StatusPageRejectsInvalidQueryParams: prueft jetzt auch text/html
fuer alle Fehlerfaelle
Docs (PLAYER-STATUS-HTTP.md):
- Query-Parameter-Validierung mit erlaubten Werten und Fehlercodes
- Neue /status/{screenId}-Seite und HTML-Fehlerseiten dokumentiert
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
153 lines
6.7 KiB
Markdown
153 lines
6.7 KiB
Markdown
# Info-Board Neu - Erster HTTP-Statuspfad fuer den Player-Agent
|
||
|
||
## Ziel
|
||
|
||
Dieses Dokument beschreibt den ersten bewusst kleinen Statuspfad zwischen `player/agent` und `server/backend`.
|
||
|
||
Er ist fuer die aktuelle Entwicklungsstufe gedacht und noch kein finales Persistenz-, Authentifizierungs- oder MQTT-Modell.
|
||
|
||
## V1-Dev-Entscheidung
|
||
|
||
- der Agent sendet zunaechst Statusdaten per HTTP an das Backend
|
||
- das Backend validiert und bestaetigt den Request und haelt den letzten bekannten Status pro Screen in-memory vor
|
||
- der Pfad dient als erste echte Backend-Agent-Integration vor Registration, Sync und MQTT
|
||
|
||
## Endpoint
|
||
|
||
- `POST /api/v1/player/status`
|
||
|
||
## Request-Felder
|
||
|
||
Mindestens enthalten:
|
||
|
||
- `screen_id`
|
||
- `ts`
|
||
- `status`
|
||
|
||
Fuer die aktuelle Entwicklungsstufe sind zulaessig:
|
||
|
||
- `status`: `starting`, `running`, `stopped`
|
||
- `server_connectivity`: `unknown`, `online`, `degraded`, `offline`
|
||
- `heartbeat_every_seconds`: positive Ganzzahl
|
||
|
||
Aktuell zusaetzlich enthalten:
|
||
|
||
- `server_connectivity`
|
||
- `server_url`
|
||
- `mqtt_broker`
|
||
- `heartbeat_every_seconds`
|
||
- `started_at`
|
||
- `last_heartbeat_at`
|
||
|
||
## Beispiel
|
||
|
||
```json
|
||
{
|
||
"screen_id": "info01-dev",
|
||
"ts": "2026-03-22T16:00:00Z",
|
||
"status": "running",
|
||
"server_connectivity": "online",
|
||
"server_url": "http://127.0.0.1:8080",
|
||
"mqtt_broker": "tcp://127.0.0.1:1883",
|
||
"heartbeat_every_seconds": 30,
|
||
"started_at": "2026-03-22T15:59:30Z",
|
||
"last_heartbeat_at": "2026-03-22T16:00:00Z"
|
||
}
|
||
```
|
||
|
||
## Antwort
|
||
|
||
Bei gueltigem Request liefert das Backend aktuell:
|
||
|
||
```json
|
||
{
|
||
"status": "accepted"
|
||
}
|
||
```
|
||
|
||
Bei ungueltigen Requests wird wie bei den anderen API-Endpunkten der gemeinsame Fehlerumschlag verwendet.
|
||
|
||
## Aktueller Read-Pfad
|
||
|
||
Zusätzlich zur Write-Route gibt es in dieser Stufe:
|
||
|
||
- `GET /status`
|
||
- `GET /api/v1/screens/status`
|
||
- `GET /api/v1/screens/{screenId}/status`
|
||
|
||
`GET /status` liefert eine kleine serverseitig gerenderte HTML-Statusseite fuer den Browser.
|
||
Sie nutzt dieselbe in-memory Statusuebersicht wie die JSON-Endpunkte und ist als erste sichtbare Diagnoseoberflaeche gedacht.
|
||
|
||
Die Seite bietet aktuell bewusst nur leichte Diagnosehilfen auf Basis des bestehenden Read-Pfads:
|
||
|
||
- automatisches Refresh alle 15 Sekunden
|
||
- Shortcut-Links fuer Connectivity- und Freshness-Filter wie `server_connectivity=offline|degraded` sowie `stale=true|false`
|
||
- ein kleines Filterformular fuer dieselben Uebersichtsparameter wie im JSON-Read-Pfad
|
||
- direkte JSON-Detail-Links pro Screen auf `GET /api/v1/screens/{screenId}/status`
|
||
- einen Link zur aktuell gefilterten JSON-Uebersicht auf `GET /api/v1/screens/status`
|
||
|
||
`GET /api/v1/screens/status` liefert eine kleine Uebersicht aller bisher berichtenden Screens mit ihrem jeweils letzten bekannten Datensatz.
|
||
Die Rueckgabe wird aktuell fuer Diagnosezwecke priorisiert sortiert: zuerst `offline`, dann `degraded`, dann `online`, innerhalb derselben Gruppe nach `screen_id`.
|
||
Zusaetzlich enthaelt die Antwort eine `summary` mit kompakten Counts fuer `total`, `online`, `degraded`, `offline` und `stale`.
|
||
|
||
Aktuell unterstuetzte Query-Parameter fuer die Uebersicht:
|
||
|
||
- `server_connectivity=<value>` zum Filtern nach Reachability-Zustand; erlaubte Werte: `online`, `offline`, `degraded`, `unknown`; ungueltige Werte liefern 400 (`invalid_server_connectivity`)
|
||
- `stale=true|false` zum Filtern nach serverseitiger Veraltet-Einschaetzung; ungueltige Werte liefern 400 (`invalid_stale`)
|
||
- `updated_since=<RFC3339>` zum Filtern nach `received_at`; ungueltige Zeitstempel liefern 400 (`invalid_updated_since`)
|
||
- `limit=<positive integer>` zum Begrenzen der Anzahl zurueckgelieferter Screens; nicht-positive Werte liefern 400 (`invalid_limit`)
|
||
|
||
Die Query-Parameter beeinflussen die Liste in `screens`; die `summary` beschreibt weiterhin den gesamten aktuell bekannten Statusbestand.
|
||
Dieselben Parameter koennen aktuell sowohl an `GET /api/v1/screens/status` als auch an `GET /status` verwendet werden, damit Browser-Ansicht und JSON-Uebersicht dieselbe Diagnose-Sicht teilen.
|
||
|
||
`GET /status/{screenId}` liefert eine HTML-Detailseite fuer einen einzelnen Screen.
|
||
Sie zeigt denselben Datensatz wie der JSON-Endpunkt – Derived State, Player-Status, Connectivity, Frische, Timestamps und Endpoints – in derselben visuellen Sprache wie die Uebersichtsseite.
|
||
Bei unbekanntem Screen liefert sie 404 mit einer erklaerenden HTML-Fehlermeldung und einem Rueck-Link auf `/status`.
|
||
|
||
Fehlerfall bei ungueltigem Query-Parameter auf `/status` (z.B. `?stale=banana`): statt rohem JSON liefert der Endpunkt jetzt eine HTML-Fehlerseite mit erklaerenden Hinweisen und einem Rueck-Link.
|
||
|
||
`GET /api/v1/screens/{screenId}/status` liefert den zuletzt akzeptierten Status fuer einen einzelnen Screen zurueck.
|
||
Wenn fuer den Screen noch kein Status vorliegt, liefert das Backend `404` mit dem gemeinsamen Fehlerumschlag.
|
||
|
||
Der aktuell zurueckgelieferte Datensatz enthaelt damit sowohl den Lifecycle-Status (`status`) als auch den vom Agenten lokal abgeleiteten Reachability-Zustand (`server_connectivity`).
|
||
|
||
Zusaetzlich fuegt das Backend im Read-Pfad derzeit hinzu:
|
||
|
||
- `received_at` als serverseitigen Annahmezeitpunkt des letzten gueltigen Reports
|
||
- `stale` als einfache serverseitige Einordnung, ob der letzte Report bereits veraltet wirkt
|
||
- `derived_state` als zusammengefasste Diagnoseeinschaetzung fuer Konsumenten des Read-Pfads
|
||
|
||
`stale` ist aktuell bewusst nur eine kleine Diagnosehilfe fuer die Entwicklungsstufe und noch kein vollstaendiges Online-/Offline-Modell fuer spaetere Admin-Oberflaechen.
|
||
Die Schwelle wird derzeit einfach aus dem gemeldeten `heartbeat_every_seconds` abgeleitet: mehr als zwei Intervalle ohne neuen Report gelten als veraltet.
|
||
|
||
`derived_state` wird aktuell bewusst einfach abgeleitet:
|
||
|
||
- `offline` bei `stale = true` oder `server_connectivity = offline`
|
||
- `degraded` bei `server_connectivity = degraded|unknown` oder wenn `status` nicht `running` ist
|
||
- `online` in den verbleibenden Faellen
|
||
|
||
## Abgrenzung
|
||
|
||
Noch nicht Teil dieser Stufe:
|
||
|
||
- dauerhafte Speicherung in Datenbank oder State-Store
|
||
- Screen-Authentifizierung
|
||
- MQTT-Heartbeat oder MQTT-Status
|
||
- Admin-UI-Anzeige des letzten Status
|
||
- Retry-Queue oder lokale Zwischenspeicherung im Agent
|
||
|
||
Agent-seitig wird die Server-Erreichbarkeit aktuell lokal als `unknown`, `online`, `degraded` oder `offline` aus dem Erfolg der HTTP-Reports abgeleitet.
|
||
|
||
Fuer den transportierten Wert im erfolgreichen HTTP-Report gilt aktuell bewusst einfach:
|
||
|
||
- wenn ein Report vom Backend akzeptiert wurde, wird dieser Report selbst als `server_connectivity = online` gespeichert
|
||
- anhaltende Ausfaelle werden primaer ueber lokale Agent-Zustaende und serverseitige `stale`-Ableitung sichtbar
|
||
|
||
## Folgeschritte
|
||
|
||
Auf diesem Pfad bauen spaeter auf:
|
||
|
||
- Screen-Identitaet und Authentifizierung
|
||
- persistierter letzter Heartbeat und letzter Status auf dem Server
|
||
- Trennung zwischen HTTP-Snapshot und MQTT-Heartbeat
|
||
- Admin-Vorschau fuer Online-/Offline- und Degraded-Zustaende
|