# Info-Board Neu - Umsetzungs-Todo ## Phase 0 - Projektbasis - [x] Projektverzeichnisstruktur unter `/srv/docker/info-board-neu` festlegen - [x] Namenskonventionen fuer Server, Player, Rollen und Pakete definieren - [x] Dokumentationsstruktur fuer Architektur, Betrieb und Deployment anlegen - [x] Entscheidung fuer Server-Tech-Stack dokumentieren - [x] Entscheidung fuer Player-Implementierung dokumentieren - [x] Sprachentscheidung dokumentieren: `Go` als bevorzugte Sprache fuer Agent und moeglichst viele Backend-Komponenten ## Phase 1 - Fachliches Fundament - [x] Rollenmodell fuer `admin` und monitorgebundene Nutzer final festschreiben - [x] Datenmodell fuer `tenant`, `screen`, `user`, `media_asset`, `playlist`, `playlist_item`, `screen_status`, `screen_snapshot` definieren - [x] Playlist-Semantik mit `duration`, `valid_from`, `valid_until`, `load_timeout`, `cache_policy`, `on_error` spezifizieren - [x] Fallback-Regel fuer ungeplante oder leere Inhalte verbindlich definieren - [x] Statusmodell fuer Online/Offline/Degraded/Error definieren - [x] Kommandokatalog fuer Admin-Aktionen finalisieren - [x] Template- und Kampagnenmodell fuer globale monitoruebergreifende Uebersteuerung finalisieren - [x] Prioritaetsregel `campaign > tenant_playlist > fallback` verbindlich festschreiben - [x] Entscheidung dokumentieren, dass `playlist_items.screen_id` entfernt wird - [x] Entscheidung dokumentieren, dass Gruppen bei Kampagnen serverseitig in Einzel-Assignments expandiert werden ## Phase 2 - Technische Zielarchitektur - [x] Server-Komponentenliste finalisieren - [x] API-Schnittstellen grob definieren - [x] MQTT-Topic-Struktur finalisieren - [x] HTTPS- und MQTT-Aufgabentrennung dokumentieren - [x] Screenshot-/Vorschaustrategie spezifizieren - [x] Offline- und Cache-Strategie bis auf Dateiebene festlegen - [x] Sicherheitsmodell fuer Uploads, Login und Rechte pruefen - [x] API fuer Templates, Kampagnen, Aktivierung und Deaktivierung ausarbeiten - [x] Provisionierungs-Workflow fuer neue Screens technisch durchplanen - [x] Secret-Handling fuer initiale Root-Passwoerter oder Bootstrap-Zugaenge definieren - [x] API-Fehlermodell und gemeinsame Fehlerantworten festlegen - [x] ACK-Timeout-Strategie fuer `device_command` festlegen - [x] `message_wall`-Rendering serverseitig verbindlich entscheiden - [x] Netzwerktopologie fuer SSH-basierte Erstprovisionierung als Worker-/Jumphost-faehiges Modell festlegen ## Phase 3 - Player-Design - [x] Minimalen Paketbedarf fuer den Player auf Raspberry Pi OS Debian 13 ermitteln - [x] X11-Minimalkonzept fuer Chromium-Kiosk dokumentieren - [x] Startmechanismus fuer Chromium ohne Desktop-Umgebung definieren - [x] Verzeichnislayout auf dem Player festlegen - [x] `player-agent` fachlich zuschneiden - [x] `player-ui` fachlich zuschneiden (lokale Kiosk-Seite mit Splash + Sysinfo-Overlay) - [x] Watchdog-Konzept fuer Browser und Agent definieren - [x] Offline-Overlay-Verhalten spezifizieren - [x] Fehlerbehandlung fuer Web-Inhalte und Timeouts ausarbeiten - [x] Display-Steuerung fuer An/Aus, Rotation und Neustart planen - [x] Sysinfo-Overlay erweitern: load, freier RAM, IP-Adresse(n) anzeigen ## Phase 4 - Server-Design - [x] API-Backend fachlich schneiden - [x] Admin-Oberflaeche in Hauptbereiche aufteilen - [x] Firmen-/Monitor-Oberflaeche in Hauptbereiche aufteilen - [x] Firmen-/Tenant-Oberfläche → siehe docs/TENANT-FEATURE-PLAN.md - [x] Storage-Konzept fuer Uploads, Cache-Dateien und Screenshots festlegen - [x] Authentifizierungskonzept festlegen - [x] Mandantentrennung im Datenmodell und in den APIs absichern - [x] Logging- und Monitoring-Konzept definieren - [x] Template-Editor fuer globale Kampagnen fachlich schneiden - [x] Aktivierungsoberflaeche fuer saisonale oder temporäre Kampagnen planen - [x] Gruppierung oder Slot-Modell fuer monitoruebergreifende Layouts planen - [x] Provisionierungs-UI fuer neue Screens fachlich und technisch schneiden - [x] Jobrunner-Konzept fuer Ansible-gestuetzte Erstinstallation planen ## Phase 5 - Prototyping - [x] Minimalen Server-Prototyp bauen - [x] Minimalen Player-Agent-Prototyp bauen - [x] Minimale Player-UI bauen - [ ] Lokale Test-Playlist mit Bild, Video, PDF und Webseite anlegen - [x] **BUG**: Datei `120papag.mpg` ist als `type: image` gespeichert, muss `type: video` sein – Player-UI versucht ``-Laden, was fehlschlägt - [x] Fallback-Verzeichnisbetrieb demonstrieren - [ ] `valid_from`/`valid_until` im Prototyp pruefen - [x] Offline-Sync mit lokalem Cache pruefen - [x] MQTT-Topic `signage/screen/{screenSlug}/playlist-changed` spezifiziert und dokumentiert - [ ] MQTT-Kommandos `reload`, `restart_player`, `reboot`, `display_on`, `display_off` testweise durchspielen - [ ] globale Kampagne testen, die tenantbezogenen Content temporär ueberschreibt - [ ] Rueckfall auf Normalbetrieb nach manueller Deaktivierung pruefen ## Phase 6 - Betriebsfaehigkeit - [x] Docker-Compose-Setup fuer den Server anlegen - [x] systemd-Units fuer den Player erstellen - [x] Chromium-Kiosk-Startskript erstellen - [x] Screenshot-Erzeugung auf dem Player integrieren - [x] Heartbeat- und Statusmeldungen integrieren - [x] MQTT-Playlist-Change-Synchronisation mit Backend-Debounce (2s) und Agent-Debounce (3s) implementiert - [ ] Fehler- und Wiederanlaufverhalten verifizieren ## Phase 7 - Ansible-Automatisierung - [x] Rolle `signage_base` erstellen - [x] Rolle `signage_player` erstellen - [x] Rolle `signage_display` erstellen - [x] Rolle `signage_server` erstellen - [x] Rolle `signage_provision` erstellen - [x] Inventar-/Variablenmodell fuer mehrere Monitore entwerfen - [x] Screen-spezifische Variablen wie `screen_id`, Rotation und Aufloesung abbilden - [x] Erstinstallation eines neuen Players automatisieren - [x] Update-Rollout eines bestehenden Players automatisieren - [x] Bootstrap ueber Root-Passwort auf SSH-Key und dauerhafte Verwaltung umstellen ## Phase 8 - Pilotbetrieb - [ ] Einen Referenzmonitor fuer den Pilotbetrieb auswaehlen - [ ] Pilotmonitor neu aufsetzen - [ ] Verbindung zum Zentralserver herstellen - [ ] Upload- und Playlist-Pflege mit einem Testmandanten pruefen - [ ] Admin-Funktionen am Pilotmonitor pruefen - [ ] globale Template-Aktivierung fuer einen oder mehrere Monitore im Pilot testen - [ ] Offline-Betrieb real testen - [ ] Browser-/Renderer-Stabilitaet ueber laengeren Zeitraum beobachten - [ ] komplette Neu-Provisionierung eines frischen Test-Screens aus dem Admin-Backend pruefen ## Phase 9 - Migration der Bestandsmonitore - [ ] Migrationsreihenfolge fuer `info01` bis `info09` festlegen - [ ] Rueckfallstrategie pro Monitor definieren - [ ] Altinhalte in das neue Medienmodell ueberfuehren - [ ] Playlists uebernehmen oder neu modellieren - [ ] Monitore nacheinander umstellen - [ ] Nach jeder Umstellung Stabilitaet und Fernsteuerung pruefen ## Phase 10 - Nacharbeiten - [ ] Betriebsdokumentation schreiben - [ ] Admin-Handbuch schreiben - [ ] Kurzhandbuch fuer Firmen-Nutzer schreiben - [ ] Backup- und Restore-Konzept dokumentieren - [ ] Update- und Release-Prozess festlegen - [ ] Langfristige Wayland-Neubewertung fuer spaetere Version vormerken ## UX-Verbesserungen (Gestaltungsplan) ### Hohe Prioritaet - [x] Flash-Messages nach Aktionen in Manage-UI (Upload, Loeschen, Speichern) — Feedback fuer den Nutzer - [x] Screen-Online/Offline-Status in Admin-Tabelle anzeigen (aus /status-Endpoint befuellen) - [x] Playlist-Tabelle in overflow-x Wrapper einwickeln (Responsive auf kleinen Screens) - [x] PDF-Darstellung: Sidebar und Toolbar im Chromium PDF-Viewer ausblenden (URL-Parameter navpanes=0, toolbar=0) - [x] PDF-Darstellung: PDF.js fuer automatisches Seitendurchblaettern integrieren ### Mittlere Prioritaet - [x] Loesch-Bestaetigung: Bulma-Modal statt browser-nativer confirm()-Dialog - [x] Status-Page: Sprache von Englisch auf Deutsch vereinheitlichen - [x] Status-Page: Relative Zeitstempel statt RFC3339 ("vor 2 Minuten") - [x] Querlinks zwischen Admin-UI und Status-Page (Navigation) - [x] Bulma und SortableJS als lokale Assets einbetten statt CDN - [x] Player-UI: CSS-Transitions fuer sanfte Content-Wechsel (Fade statt abrupt) - [x] Player-UI: Erweitertes Sysinfo-Overlay (aktueller Titel, Playlist-Laenge) - [x] Aria-Labels fuer Loesch-Buttons und Drag-Handles (Accessibility) ### Niedrige Prioritaet - [x] Upload-Fortschrittsbalken in Manage-UI - [x] vars.yml Download-Button in Provision-UI statt Copy-Paste - [x] Toggle-Switch statt Ja/Nein-Select fuer Enabled-Feld ## UX-Bug-Fixes - [x] Fix: Protokoll-relative URLs (//cdn...) werden nicht mehr durch URL-Normalisierung kaputtgeschrieben - [x] Fix: PDF-Fragment-Parameter werden mit bestehenden Fragments gemerged statt blind angehängt - [x] Fix: /api/startup-token setzt Cache-Control: no-store Header (Server + Client) - [x] Fix: TestAssetsServed Nil-Dereferenz durch tote Goroutine behoben ## Security & Code-Review (Opus, 2026-03-23) ### Kritisch — Sicherheitslücken - [x] **K2** Tenant-Isolation für `/manage/{screenSlug}/*`: `requireScreenAccess()` in allen manage-Handlern - [x] **K3** `DELETE /api/v1/media/{id}`: Tenant-Check via reqcontext.UserFromContext - [x] **K4** JSON-API Playlist-Routen (`/items`, `/playlists/*/items`, `/order`, `/duration`): `requirePlaylistAccess()` + `GetByItemID()` im Store - [x] **K1** CSRF-Schutz: Double-Submit-Cookie-Pattern (`httpapi/csrf.go`); JS-Injection in alle Templates; Middleware in Router - [x] **K6** `POST /api/v1/screens/register`: Pre-Shared-Secret via `MORZ_INFOBOARD_REGISTER_SECRET` (Header `X-Register-Secret`); Player-Agent sendet Secret mit - [x] **K5** Admin-Passwort aus Log entfernt — nur `[gesetzt]` wird geloggt ### Wichtig — Robustheit - [x] **N5** Directory-Listing auf `/uploads/` deaktiviert via `neuteredFileSystem` (`httpapi/uploads.go`) - [x] **N6** Uploads nach Tenant getrennt: `fileutil.SaveUploadedFile()` legt Dateien in `uploads/{tenantSlug}/` ab - [x] **W1** Race Condition bei `order_index` behoben: atomare Subquery in `AddItem()` - [x] **W2** Graceful Shutdown implementiert: `http.Server.Shutdown()` mit 15s Timeout auf SIGTERM/SIGINT - [x] **W3** Upload mit `http.MaxBytesReader` begrenzt (512 MB) in allen drei Upload-Handlern - [x] **W4** `err.Error()` nicht mehr an den Client — generische Fehlermeldungen, Details serverseitig - [x] **W7** Template-Execution-Errors: `bytes.Buffer`-Rendering, erst bei Erfolg an Client senden (`renderTemplate()`) ### Verbesserung — Wartbarkeit - [ ] **V3** Keine Tests für Auth, Middleware, Tenant-Handler (gesamter Phase-1-5-Code ohne Abdeckung) - [x] **V1** Upload-Logik konsolidiert in `internal/fileutil/fileutil.go` (`SaveUploadedFile`) - [x] **V5** Cookie-Name als Konstante `reqcontext.SessionCookieName` — manage/auth.go und middleware.go nutzen sie - [x] **V6** Strukturiertes Logging: `log/slog` mit JSON-Handler in `main.go`; `app.go` nutzt `slog.Info/slog.Error` - [x] **V7** DB-Pool wird im Graceful-Shutdown-Handler geschlossen (`a.dbPool.Close()`) ### Nice-to-have — Features - [x] **N1** Rate-Limiting auf `/login`: In-Memory Sliding-Window (5 Versuche/Minute pro IP) via `httpapi/ratelimit.go` - [ ] **N2** Passwort-Änderung / Self-Service-Reset - [ ] **N3** Tenant-User-Management im Admin-UI - [ ] **N4** Session-TTL via Config-Variable steuerbar (aktuell hardcoded 8h) **Hinweis K6:** `MORZ_INFOBOARD_REGISTER_SECRET` muss in `server/.env` / `docker-compose.yml` und in der Player-Config (`MORZ_INFOBOARD_REGISTER_SECRET` oder `register_secret` in `config.json`) identisch gesetzt werden. Wenn die Variable leer ist, bleibt der Endpoint offen (Rückwärtskompatibilität). ## Querschnittsthemen - [ ] Datensicherung fuer Datenbank und Medien einplanen - [ ] TLS-/Reverse-Proxy-Konzept festlegen - [ ] Ressourcenverbrauch auf Raspberry Pi beobachten - [ ] Verhalten bei grossen Videos optimieren - [ ] Verhalten bei defekten externen Webseiten absichern - [ ] Datenschutz- und Rechtefragen fuer Screenshots/Vorschauen pruefen ## Erste konkrete Abarbeitungsreihenfolge - [x] 1. Projektstruktur im neuen Verzeichnis vervollstaendigen - [x] 2. Datenmodell in eigener Datei ausformulieren - [x] 3. API- und MQTT-Vertrag definieren - [x] 4. Player-Minimalkonzept fuer Raspberry Pi OS Debian 13 festzurren - [x] 5. Server-Compose-Grundgeruest erstellen - [x] 6. Player-Prototyp mit lokalem Browser-Renderer bauen - [x] 7. Offline-Cache und Fallback robust machen - [x] 8. UIs fuer Admin und Firmen schrittweise aufbauen - [x] 9. Ansible-Rollen erstellen - [ ] 10. Pilotmonitor migrieren