Files
infoscreen/.github/copilot-instructions.md
Olaf 03e3c11e90 feat: crash recovery, service_failed monitoring, broker health fields, command expiry sweep
- Add GET /api/clients/crashed endpoint (process_status=crashed or stale heartbeat)
- Add restart_app command action with same lifecycle + lockout as reboot_host
- Scheduler: crash auto-recovery loop (CRASH_RECOVERY_ENABLED flag, lockout, MQTT publish)
- Scheduler: unconditional command expiry sweep per poll cycle (sweep_expired_commands)
- Listener: subscribe to infoscreen/+/service_failed; persist service_failed_at + unit
- Listener: extract broker_connection block from health payload; persist reconnect_count + last_disconnect_at
- DB migration b1c2d3e4f5a6: service_failed_at, service_failed_unit, mqtt_reconnect_count, mqtt_last_disconnect_at on clients
- Add GET /api/clients/service_failed and POST /api/clients/<uuid>/clear_service_failed
- Monitoring overview API: include mqtt_reconnect_count + mqtt_last_disconnect_at per client
- Frontend: orange service-failed alert panel (hidden when empty, auto-refresh, quittieren action)
- Frontend: MQTT reconnect count + last disconnect in client detail panel
- MQTT auth hardening: listener/scheduler/server use env credentials; broker enforces allow_anonymous false
- Client command lifecycle foundation: ClientCommand model, reboot_host/shutdown_host, full ACK lifecycle
- Docs: TECH-CHANGELOG, DEV-CHANGELOG, MQTT_EVENT_PAYLOAD_GUIDE, copilot-instructions updated
- Add implementation-plans/, RESTART_VALIDATION_CHECKLIST.md, TODO.md
2026-04-05 10:17:56 +00:00

6.2 KiB

Copilot instructions for infoscreen_2025

Purpose

This file is a concise, high-signal brief for coding agents. It is not a changelog and not a full architecture handbook.

TL;DR

  • Stack: Flask API + MariaDB, React/Vite dashboard, MQTT listener, scheduler, worker.
  • Main areas:
    • API logic in server/
    • Scheduler logic in scheduler/
    • UI logic in dashboard/src/
  • Keep changes minimal, match existing patterns, and update docs in the same commit when behavior changes.

Fast file map

  • scheduler/scheduler.py - scheduler loop, MQTT event publishing, TV power intent publishing, crash auto-recovery, command expiry sweep
  • scheduler/db_utils.py - event formatting, power-intent helpers, crash recovery helpers, command expiry sweep
  • listener/listener.py - discovery/heartbeat/log/screenshot/service_failed MQTT consumption
  • server/init_academic_periods.py - idempotent academic-period seeding + auto-activation for current date
  • server/initialize_database.py - migration + bootstrap orchestration for local/manual setup
  • server/routes/events.py - event CRUD, recurrence handling, UTC normalization
  • server/routes/eventmedia.py - file manager, media upload/stream endpoints
  • server/routes/groups.py - group lifecycle, alive status, order persistence
  • server/routes/system_settings.py - system settings CRUD and supplement-table endpoint
  • server/routes/clients.py - client metadata, restart/shutdown/restart_app command issuing, command status, crashed/service_failed alert endpoints
  • dashboard/src/settings.tsx - settings UX and system-defaults integration
  • dashboard/src/components/CustomEventModal.tsx - event creation/editing UX
  • dashboard/src/monitoring.tsx - superadmin monitoring page
  • TV_POWER_INTENT_SERVER_CONTRACT_V1.md - Phase 1 TV power contract

Service picture

  • API: server/ on :8000 (health: /health)
  • Dashboard: dashboard/ (dev :5173, proxied API calls)
  • MQTT broker: Mosquitto (mosquitto/config/mosquitto.conf)
  • Listener: MQTT consumer that updates server-side state
  • Scheduler: publishes active events and group-level TV power intents
  • Nginx: routes /api/* and /screenshots/* to API, dashboard otherwise
  • Prod bootstrap: docker-compose.prod.yml server command runs migrations, defaults init, and academic-period init before Gunicorn start

Non-negotiable conventions

  • Datetime:
    • Store/compare in UTC.
    • API returns ISO strings without Z in many routes.
    • Frontend must append Z before parsing if needed.
  • JSON naming:
    • Backend internals use snake_case.
    • API responses use camelCase (via server/serializers.py).
  • DB host in containers: db (not localhost).
  • Never put secrets in docs.

MQTT contracts

  • Event list topic (retained): infoscreen/events/{group_id}
  • Group assignment topic (retained): infoscreen/{uuid}/group_id
  • Heartbeat topic: infoscreen/{uuid}/heartbeat
  • Logs topic family: infoscreen/{uuid}/logs/{error|warn|info}
  • Health topic: infoscreen/{uuid}/health
  • Dashboard screenshot topic: infoscreen/{uuid}/dashboard
  • Client command topic (QoS1, non-retained): infoscreen/{uuid}/commands (compat alias: infoscreen/{uuid}/command)
  • Client command ack topic (QoS1, non-retained): infoscreen/{uuid}/commands/ack (compat alias: infoscreen/{uuid}/command/ack)
  • Service-failed topic (retained, client→server): infoscreen/{uuid}/service_failed
  • TV power intent Phase 1 topic (retained, QoS1): infoscreen/groups/{group_id}/power/intent

TV power intent Phase 1 rules:

  • Schema version is "1.0".
  • Group-only scope in Phase 1.
  • Heartbeat publish keeps intent_id; semantic transition rotates intent_id.
  • Expiry rule: expires_at = issued_at + max(3 x poll_interval_sec, 90s).
  • Canonical contract is TV_POWER_INTENT_SERVER_CONTRACT_V1.md.

Backend patterns

  • Routes in server/routes/*, registered in server/wsgi.py.
  • Use one request-scoped DB session, commit on mutation, always close session.
  • Keep enum/datetime serialization JSON-safe.
  • Maintain UTC-safe comparisons in scheduler and routes.
  • Keep recurrence handling backend-driven and consistent with exceptions.
  • Academic periods bootstrap is idempotent and should auto-activate period covering date.today() when available.

Frontend patterns

  • Use Syncfusion-based patterns already present in dashboard.
  • Keep API requests relative (/api/...) to use Vite proxy in dev.
  • Respect FRONTEND_DESIGN_RULES.md for component and styling conventions.
  • Keep role-gated UI behavior aligned with backend authorization.
  • Holiday status banner in dashboard should render from computed state and avoid stale message reuse in 3rd-party UI components.

Environment variables (high-value)

  • Scheduler: POLL_INTERVAL_SECONDS, REFRESH_SECONDS
  • Power intent: POWER_INTENT_PUBLISH_ENABLED, POWER_INTENT_HEARTBEAT_ENABLED, POWER_INTENT_EXPIRY_MULTIPLIER, POWER_INTENT_MIN_EXPIRY_SECONDS
  • Monitoring: PRIORITY_SCREENSHOT_TTL_SECONDS
  • Crash recovery: CRASH_RECOVERY_ENABLED, CRASH_RECOVERY_GRACE_SECONDS, CRASH_RECOVERY_LOCKOUT_MINUTES, CRASH_RECOVERY_COMMAND_EXPIRY_SECONDS
  • Core: DB_CONN, DB_USER, DB_PASSWORD, DB_HOST, DB_NAME, ENV
  • MQTT auth/connectivity: MQTT_BROKER_HOST, MQTT_BROKER_PORT, MQTT_USER, MQTT_PASSWORD (listener/scheduler/server should use authenticated broker access)

Edit guardrails

  • Do not edit generated assets in dashboard/dist/.
  • Do not change CI/build outputs unless explicitly intended.
  • Preserve existing API behavior unless task explicitly requires a change.
  • Prefer links to canonical docs instead of embedding long historical notes here.

Documentation sync rule

When services/MQTT/API/UTC/env behavior changes:

  1. Update this file (concise deltas only).
  2. Update canonical docs where details live.
  3. Update changelogs separately (TECH-CHANGELOG.md, DEV-CHANGELOG.md, dashboard/public/program-info.json as appropriate).

Canonical docs map

  • Repo entry: README.md
  • Instruction governance: AI-INSTRUCTIONS-MAINTENANCE.md
  • Technical release details: TECH-CHANGELOG.md
  • Workspace/development notes: DEV-CHANGELOG.md
  • MQTT payload details: MQTT_EVENT_PAYLOAD_GUIDE.md
  • TV power contract: TV_POWER_INTENT_SERVER_CONTRACT_V1.md
  • Frontend patterns: FRONTEND_DESIGN_RULES.md
  • Archived historical docs: docs/archive/