morz-infoboard/docs/OFFENE-ARCHITEKTURFRAGEN.md
2026-03-22 13:35:41 +01:00

5.2 KiB

Info-Board Neu - Architekturentscheidungen vor dem ersten Code

Ziel

Dieses Dokument sammelt die Punkte, die vor dem Einstieg in die Implementierung bewusst entschieden werden mussten.

Es geht nicht um offene Detailfragen fuer spaeter, sondern um Entscheidungen mit Einfluss auf Datenmodell, API, Player-Verhalten und Admin-UI.

Stand: Diese Punkte sind fuer v1 entschieden.

1. message_wall-Rendering

Frage

Wer berechnet die Aufteilung eines Gesamtmotivs oder Schriftzugs auf die beteiligten Displays?

Moegliche Varianten:

  • serverseitig beim Aktivieren einer Kampagne
  • playerseitig anhand von Slot-Metadaten

Entscheidung

Fuer v1 wird message_wall serverseitig in konkrete Screen-Szenen aufgeloest.

Begruendung

  • weniger Komplexitaet im Player
  • identische Berechnung fuer alle beteiligten Screens
  • einfachere Vorschau im Admin-Backend
  • Kampagnen werden vor Aktivierung bereits in konkrete Zielinhalte ueberfuehrt

Konsequenz

  • message_wall wird im Backend oder Worker in konkrete template_scenes pro Slot/Screen transformiert
  • der Player bekommt nur noch seinen eigenen fertigen Ausschnitt
  • layout_json muss trotzdem klar definiert werden, dient dann aber primaer der Serverlogik und UI-Vorschau

2. Secret-Handling fuer Provisionierung

Frage

Wie werden initiale Root-Passwoerter oder Bootstrap-Secrets verarbeitet, ohne sie unkontrolliert in der Datenbank liegen zu lassen?

Entscheidung

Separate Secret-Verwaltung mit kurzer Lebensdauer:

  • Secret nicht direkt in provisioning_jobs
  • stattdessen separater Secret-Eintrag mit TTL
  • verschluesselt mit App-Key
  • automatische Loeschung nach Abschluss oder Abbruch des Jobs

V1-Loesung fuer dieses Projekt

  • Tabelle fuer kurzlebige Provisionierungs-Secrets
  • AES-verschluesselte Speicherung via Server-App-Key
  • Referenz ueber provided_secret_ref
  • Cleanup-Job entfernt Secrets nach erfolgreicher Provisionierung oder nach Ablauf

3. ACK-Timeout fuer Kommandos

Frage

Wann wird ein device_command ohne ACK als fehlgeschlagen oder abgelaufen markiert?

Entscheidung

Ein serverseitiger Worker uebernimmt Timeouts und Statusuebergaenge.

Vorgeschlagenes Verhalten:

  • queued -> sent
  • falls innerhalb eines konfigurierten Zeitfensters kein ACK kommt: expired
  • falls technische Zustellung fehlschlaegt: failed

Startwerte fuer v1

  • reload, refresh_snapshot: 30 Sekunden
  • restart_player, display_on, display_off: 60 Sekunden
  • reboot: 120 Sekunden

Wenn nach Ablauf kein ACK eingegangen ist, wird der Befehl auf expired gesetzt.

Konsequenz

  • es braucht einen periodischen Background-Job
  • ACK-Timeouts werden nicht im Web-Request, sondern im Worker behandelt

4. Netzwerktopologie fuer Erstprovisionierung

Frage

Kann der zentrale Server die Zielgeraete bei der Erstinstallation direkt per SSH erreichen?

Entscheidung

Das wird als harte Betriebsannahme explizit dokumentiert und geprueft.

Moegliche Betriebsmodelle:

  • Server steht im selben Netz oder VLAN wie die Player
  • Server erreicht die Player ueber Routing/Firewall-Freigaben
  • Provisionierungs-Worker laeuft auf einem Jumphost im richtigen Netz

V1-Entscheidung:

  • die Provisionierung wird so gebaut, dass der Worker auch auf einem separaten Jumphost laufen kann
  • direkte SSH-Erreichbarkeit vom Hauptserver ist erlaubt, aber nicht vorausgesetzt
  • die Netzposition des Workers wird als Betriebsparameter behandelt

Konsequenz

Die Provisionierungsarchitektur ist erst dann belastbar, wenn klar ist:

  • wo der Worker laeuft
  • welche Netze er erreicht
  • ob SSH direkt moeglich ist
  • ob spaeter ein Jumphost-Konzept benoetigt wird

5. Kleine Modellbereinigung vor Implementierung

playlist_items.screen_id

Aktuell ist das Feld fachlich redundant, weil das Item bereits ueber die Playlist einem Screen zugeordnet ist.

Entscheidung:

  • das Feld wird aus dem finalen Implementierungsschema entfernt
  • die Screen-Zuordnung laeuft ausschliesslich ueber playlists.screen_id

template_assignments

Aktuell ist das Schema auf konkrete Screens ausgelegt.

Entscheidung:

  • fuer v1 werden Gruppen serverseitig in Einzelzuordnungen expandiert
  • laufende Kampagnen werden bei spaeteren Gruppenänderungen nicht automatisch neu berechnet
  • falls das spaeter anders gewuenscht ist, braucht es ein bewusstes Reconciliation-Konzept

6. API-Fehlermodell

Frage

Wie sehen konsistente API-Fehlerantworten aus?

Entscheidung

Ein gemeinsamer Fehlerumschlag fuer alle API-Endpunkte.

Beispiel:

{
  "error": {
    "code": "screen_not_found",
    "message": "Screen existiert nicht",
    "details": null
  }
}

Konsequenz

  • Backend, Frontends und Player koennen Fehler einheitlich behandeln
  • Logging und Monitoring werden einfacher

Ergebnis fuer v1

  1. message_wall wird serverseitig aufgeloest
  2. Provisionierungs-Secrets werden kurzlebig und verschluesselt referenziert gespeichert
  3. ACK-Timeouts werden vom Worker ausgewertet und setzen Kommandos auf expired
  4. Provisionierung wird worker-basiert und jumperfaehig geplant
  5. playlist_items.screen_id wird im finalen Schema entfernt
  6. Gruppen werden bei Kampagnen in Einzel-Assignments expandiert
  7. API-Fehler verwenden einen einheitlichen Fehlerumschlag