# Info-Board Neu - Entwicklung ## Ziel Dieses Dokument soll den Einstieg auf einem anderen Entwicklungsrechner moeglichst reibungsfrei machen. Es beschreibt: - minimale Voraussetzungen - wichtige Verzeichnisse - Build- und Run-Kommandos - aktuelle Annahmen fuer den lokalen Entwicklungsbetrieb ## Repository - Remote: `git.az-it.net:az/morz-infoboard.git` - Standard-Branch: `main` Projektwurzel: - `/srv/docker/info-board-neu` ## Wichtige Verzeichnisse - `docs/` fuer Architektur- und Fachkonzepte - `server/backend/` fuer das zentrale Go-Backend - `player/agent/` fuer den Go-basierten Player-Agent - `ansible/` fuer Deployment und Provisionierung - `compose/` spaeter fuer den zentralen Server-Stack ## Aktueller Entwicklungsstand Bereits vorhanden: - fachliche Architektur- und Betriebskonzepte - relationaler Schema-Entwurf in `docs/SCHEMA.md` - funktionales Go-Backend (`server/backend`) mit REST-API, PostgreSQL-Anbindung und Datenverwaltung - funktionaler Go-Agent (`player/agent`) mit Server-Registrierung, Playlist-Management und Heartbeat-Sync - vollstaendiger Compose-Stack in `compose/server-stack.yml` mit PostgreSQL, Mosquitto und Backend-Service Noch nicht vorhanden: - produktives SSL/TLS-Handling fuer Deployment - Docker-Secret-Integration fuer `MORZ_INFOBOARD_ADMIN_PASSWORD` - Ansible-Variable `morz_admin_password` als Vault-Variable (Phase 6) ## Voraussetzungen auf dem Entwicklungsrechner Mindestens empfohlen: - `git` - `go` in Version `1.24.x` - `make` Spaeter zusaetzlich sinnvoll: - `docker` und `docker compose` - `postgresql-client` - `mosquitto-clients` - `golangci-lint` Fuer Container-Builds liegen erste Dockerfiles in: - `server/backend/Dockerfile` - `player/agent/Dockerfile` ## Schnellstart Repository klonen: ```bash git clone git.az-it.net:az/morz-infoboard.git cd morz-infoboard ``` Dokumentationsbasis lesen: 1. `README.md` 2. `PLAN.md` 3. `TECH-STACK.md` 4. `docs/SCHEMA.md` 5. `docs/OFFENE-ARCHITEKTURFRAGEN.md` 6. `docs/LAYOUT-JSON.md` ## Build-Kommandos ### Backend bauen ```bash cd server/backend go build ./... ``` ### Agent bauen ```bash cd player/agent go build ./... ``` ### Alternativ ueber Makefile ```bash make build ``` Aktuell bedeutet das: - `make build` baut Backend und Agent - `make build-backend` baut nur `server/backend` - `make build-agent` baut nur `player/agent` - `make run-backend` startet das Backend - `make run-agent` startet den Agenten - `make fmt` formatiert beide Go-Module - `make lint` prueft beide Go-Module mit `golangci-lint` Hinweis: - auf dem aktuellen System dieser Session sind `make` und `go` nicht installiert; die Befehle sind fuer den Entwicklungsrechner vorbereitet ## Lokale Entwicklung mit Login Seit der Implementierung des Tenant-Features ist das Backend durch eine Session-basierte Authentifizierung geschuetzt. Fuer den lokalen Entwicklungsbetrieb muessen zwei zusaetzliche Umgebungsvariablen gesetzt werden: - `MORZ_INFOBOARD_ADMIN_PASSWORD` – legt das Passwort des initialen Admin-Users fest. Beim Backend-Start wird automatisch ein User `admin` angelegt (bzw. dessen Passwort aktualisiert), der dem Standard-Tenant `morz` zugeordnet ist. Bleibt die Variable leer, wird kein Admin angelegt und der Login-Bereich ist nicht nutzbar. - `MORZ_INFOBOARD_DEV_MODE` – setzt das Session-Cookie ohne das `Secure`-Flag, sodass er auch ueber unverschluesseltes HTTP (lokales `localhost`) uebertragen wird. Ohne dieses Flag wird der Cookie nur ueber HTTPS gesetzt und der Login schlaegt im lokalen Betrieb still fehl. Empfohlener Start fuer die lokale Entwicklung: ```bash cd server/backend MORZ_INFOBOARD_ADMIN_PASSWORD=dev \ MORZ_INFOBOARD_DEV_MODE=true \ go run ./cmd/api ``` Danach ist der Login unter `http://localhost:8080/login` mit `admin` / `dev` erreichbar. Hinweis: `MORZ_INFOBOARD_DEV_MODE=true` darf niemals in einer produktiven Umgebung gesetzt werden, da der Cookie dort ausschliesslich ueber HTTPS uebertragen werden soll. --- ## Lokaler Start ### Backend lokal starten ```bash cd server/backend go run ./cmd/api ``` Standard: - HTTP-Adresse: `:8080` - Health-Endpunkt: `GET /healthz` - Basis-Endpunkt: `GET /api/v1` Konfigurierbar ueber: - `MORZ_INFOBOARD_HTTP_ADDR` – HTTP-Adresse (Standard: `:8080`) - `MORZ_INFOBOARD_STATUS_STORE_PATH` – Pfad zur JSON-Datei fuer persistenten Status-Store; leer lassen fuer reinen In-Memory-Betrieb - `MORZ_INFOBOARD_ADMIN_PASSWORD` – Passwort fuer den initialen Admin-User (leer = kein EnsureAdminUser-Lauf) - `MORZ_INFOBOARD_DEFAULT_TENANT` – Slug des Standard-Tenants, dem der Admin-User zugeordnet wird (Standard: `morz`) - `MORZ_INFOBOARD_DEV_MODE` – wenn `true`: Session-Cookie wird ohne `Secure`-Flag gesetzt (nur fuer lokale Entwicklung) Beispiele: ```bash MORZ_INFOBOARD_HTTP_ADDR=:18080 go run ./cmd/api ``` ```bash MORZ_INFOBOARD_HTTP_ADDR=:8080 \ MORZ_INFOBOARD_STATUS_STORE_PATH=/tmp/screen-status.json \ go run ./cmd/api ``` ### Agent lokal starten ```bash cd player/agent go run ./cmd/agent ``` Standardwerte: - `MORZ_INFOBOARD_SCREEN_ID=unset-screen` - `MORZ_INFOBOARD_SERVER_URL=http://127.0.0.1:8080` - `MORZ_INFOBOARD_MQTT_BROKER=` (leer = MQTT wird uebersprungen) - `MORZ_INFOBOARD_PLAYER_ADDR=127.0.0.1:8090` - `MORZ_INFOBOARD_PLAYER_CONTENT_URL=` (leer = kein Inhalt eingebettet) Optional: - `MORZ_INFOBOARD_MQTT_USERNAME` – MQTT-Benutzername - `MORZ_INFOBOARD_MQTT_PASSWORD` – MQTT-Passwort - `MORZ_INFOBOARD_CONFIG=/etc/signage/config.json` – dateibasierte Konfiguration Eine Beispielkonfiguration liegt in `player/config/config.example.json`. Der Agent stellt unter `http://127.0.0.1:8090/player` eine lokale Kiosk-Seite bereit. Beispiel ohne MQTT: ```bash MORZ_INFOBOARD_SCREEN_ID=info01-dev \ MORZ_INFOBOARD_SERVER_URL=http://127.0.0.1:8080 \ go run ./cmd/agent ``` Beispiel mit MQTT: ```bash MORZ_INFOBOARD_SCREEN_ID=info01-dev \ MORZ_INFOBOARD_SERVER_URL=http://127.0.0.1:8080 \ MORZ_INFOBOARD_MQTT_BROKER=tcp://127.0.0.1:1883 \ MORZ_INFOBOARD_MQTT_USERNAME=user \ MORZ_INFOBOARD_MQTT_PASSWORD=pass \ go run ./cmd/agent ``` ## Ansible-Deployment auf einen Zielrechner Der `ansible/`-Ordner enthaelt ein vollstaendiges Playbook fuer das Deployment auf einen Pi oder ein Debian-System. ### Voraussetzungen - Ansible auf dem Entwicklungsrechner - SSH-Key fuer den Zielrechner hinterlegt - Ansible Vault fuer MQTT-Zugangsdaten ### Inventory und Konfiguration - `ansible/inventory.yml` – Hosts und Gruppen - `ansible/host_vars//vars.yml` – host-spezifische Variablen (`screen_id`, `ansible_host`, `ansible_user`) - `ansible/group_vars/signage_players/vars.yml` – globale Defaults - `ansible/group_vars/signage_players/vault.yml` – verschluesselte Zugangsdaten (gitignored) Vault-Datei anlegen: ```bash ansible-vault create ansible/group_vars/signage_players/vault.yml ``` Inhalt: ```yaml vault_mqtt_username: "benutzername" vault_mqtt_password: "passwort" ``` In `vars.yml` referenzieren: ```yaml morz_mqtt_username: "{{ vault_mqtt_username }}" morz_mqtt_password: "{{ vault_mqtt_password }}" ``` ### Deployment ausfuehren ```bash cd ansible ansible-playbook site.yml -i inventory.yml --ask-vault-pass ``` Das Playbook erledigt: 1. Agent-Binary cross-kompilieren (lokal, `GOOS=linux GOARCH=arm64`) 2. Binary und Konfiguration auf den Zielrechner uebertragen 3. systemd-Unit fuer den Agent anlegen und starten 4. journald auf RAM-Speicherung konfigurieren (SD-Karte schonen) 5. X11-Paketstack und Chromium installieren 6. Kiosk-Startskript und systemd-Unit fuer die Anzeige anlegen ### Rollen - `signage_player` – Agent, Konfiguration, systemd-Unit, journald - `signage_display` – X11, Chromium, Kiosk-Service ## Aktuelle Architekturentscheidungen mit direkter Auswirkung auf Entwicklung - `message_wall` wird serverseitig in konkrete Screen-Szenen aufgeloest - Kampagnengruppen werden serverseitig in konkrete Screen-Assignments expandiert - `playlist_items` haben im finalen Implementierungsschema keinen direkten `screen_id`-Fremdschluessel - Provisionierung wird worker-/jumphost-faehig geplant - API-Fehler sollen einen einheitlichen Fehlerumschlag nutzen ## Empfohlene naechste Implementierungsschritte Die Punkte 1–4 der urspruenglichen Liste (Fehlerformat, Routing, Status, MQTT) sind umgesetzt. Offene Punkte aus Phase 6 des Tenant-Feature-Plans (`docs/TENANT-FEATURE-PLAN.md`): 1. Docker-Secret fuer `MORZ_INFOBOARD_ADMIN_PASSWORD` in `compose/` einrichten 2. Ansible-Variable `morz_admin_password` als Vault-Variable definieren 3. Code-Review durch Larry (SQL-Injection, Session-Fixation, bcrypt-Cost, Middleware-Reihenfolge) 4. End-to-End-Test-Checkliste in `docs/TEST-CHECKLIST-DEV.md` durchlaufen 5. Deployment: Image bauen, Migration `002_auth.sql` pruefen, Logs kontrollieren 6. Langfristig: Netzwerk-, Sync- und Kommandopfade produktionsnah ausbauen ## End-to-End-Entwicklungstest (Backend + Agent) Backend und Agent koennen lokal gegeneinander laufen. Reihenfolge: 1. Backend starten (Terminal 1): ```bash cd server/backend MORZ_INFOBOARD_STATUS_STORE_PATH=/tmp/screen-status.json go run ./cmd/api ``` 2. Agent starten (Terminal 2): ```bash cd player/agent MORZ_INFOBOARD_SCREEN_ID=info01-dev \ MORZ_INFOBOARD_SERVER_URL=http://127.0.0.1:8080 \ go run ./cmd/agent ``` 3. Status pruefen: ```bash # JSON-Uebersicht curl http://127.0.0.1:8080/api/v1/screens/status # HTML-Diagnoseseite open http://127.0.0.1:8080/status # Einzelner Screen curl http://127.0.0.1:8080/api/v1/screens/info01-dev/status # Screen loeschen curl -X DELETE http://127.0.0.1:8080/api/v1/screens/info01-dev/status ``` Die Datei `/tmp/screen-status.json` enthaelt nach dem ersten Heartbeat den persistierten Status-Store. ## Ergaenzt seit dem ersten Geruest: **Backend-REST-API (statusseite.py, playerstatus.go, messagewall.go):** - `message_wall`-Resolver im Backend fuer Szenen-Aufloesung - Basisendpunkte und `message_wall`-Validierung im Backend testseitig breiter abgedeckt - `POST /api/v1/player/status` mit Laufzeit-, Stale- und Server-Konnektivitaets-Tracking - Player-Status wird im Backend pro Screen in-memory vorgehalten und ueber Endpunkte lesbar gemacht - `GET /api/v1/screens/status` fuer Gesamt-Uebersicht mit Query-Filtern - `GET /api/v1/screens/{screenId}/status` fuer Einzelscreen-Details - `DELETE /api/v1/screens/{screenId}/status` zum Loeschen von Screen-Eintraegen - HTML-Diagnoseseite unter `/status` mit Auto-Refresh, Filterung und JSON-Drill-down - Query-Parameter: `q=` (Screen-ID-Substring), `derived_state=`, `server_connectivity=`, `stale=`, `updated_since=`, `limit=` - `derived_state` (online / degraded / offline) aus `stale`, `server_connectivity` und `status` abgeleitet - JSON-Persistenz optional in Datei (`MORZ_INFOBOARD_STATUS_STORE_PATH`) **Backend-Datenverwaltung (manage/register.go, manage/playlist.go, manage/media.go):** - PostgreSQL-Anbindung mit `DATABASE_URL`-Konfiguration - Agent-Selbstregistrierung ueber `POST /api/v1/manage/register` - Playlist-Verwaltung und -Abruf (`GET /api/v1/manage/playlists/...`) - Medien-Upload und Speicherverwaltung in `MORZ_INFOBOARD_UPLOAD_DIR` - Admin-UI mit HTML-Templates fuer Playlist und Medien-Management **Agent-Funktionalitaeten (player/agent/):** - dateibasierte Agent-Konfiguration (`config.json`) zusaetzlich zu Env-Overrides - strukturierte Agent-Logs mit internem Health-Snapshot und signalgesteuertem Shutdown - periodischer HTTP-Status-Reporter fuer Server-Registrierung - Server-Connectivity-Zustand (`unknown`, `online`, `degraded`, `offline`) - HTTP-Statuspfad transportiert `status` und `server_connectivity` - MQTT-Heartbeat (optional; wird uebersprungen wenn kein Broker konfiguriert) - MQTT-Authentifizierung mit Username und Password - Player-UI unter `/player` (HTML-Kiosk) und `/api/now-playing` (JSON) - Playlist-Rotation und lokale Playlist-Verwaltung **Infrastruktur und Deployment:** - vollstaendiger Compose-Stack (`compose/server-stack.yml`) mit PostgreSQL 17, Mosquitto, Backend-Service und Health-Checks - Ansible-Rollen `signage_player` und `signage_display` fuer vollstaendiges Deployment - journald auf volatile Storage konfiguriert (SD-Karte schonen) - Cross-Compile fuer ARM64 im Ansible-Playbook - systemd-Units fuer Agent und Kiosk-Display ## Arbeitsweise Empfohlen: - kleine, klar umrissene Commits - zuerst Konzepte anpassen, dann Code - Schema und API-Vertrag synchron halten - neue Fachentscheidungen immer in `docs/` dokumentieren ## Hinweise fuer einen zweiten Entwicklungsrechner - vor Arbeitsbeginn `git pull --rebase` oder gleichwertig den aktuellen Stand holen - bei paralleler Arbeit zuerst in den Dokumenten pruefen, ob neue Architekturentscheidungen getroffen wurden - falls lokale Tools abweichen, mindestens `go version` und `make --version` pruefen