Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

28KB

Pro Runtime Hardening Workboard

Status: living document
Branch: feature/pro-runtime-hardening

Dieses Dokument ist das Arbeitsdokument zur schrittweisen Umsetzung des Konzepts aus fm-rds-tx_pro_runtime_hardening_concept.json.

Ziel ist nicht nur eine hübsche Roadmap, sondern ein Ort, an dem wir konkret markieren können:

  • wo wir im Code stehen,
  • welche Lücken bestätigt sind,
  • welche Entscheidungen gefallen sind,
  • welche Arbeiten offen / in Arbeit / erledigt sind,
  • welche Risiken noch bestehen,
  • welche Akzeptanzkriterien wirklich nachgewiesen wurden.

1. Arbeitsregeln für dieses Dokument

Statuswerte

  • TODO → noch nicht begonnen
  • IN PROGRESS → aktiv in Arbeit
  • BLOCKED → sinnvoll erkannt, aber blockiert
  • DONE → umgesetzt
  • VERIFIED → umgesetzt und sinnvoll geprüft
  • DEFERRED → bewusst nach hinten verschoben
  • REJECTED → bewusst verworfen

Nachweispflicht

Ein Punkt gilt erst als wirklich fertig, wenn eingetragen ist:

  1. Code-Ort(e)
  2. Was geändert wurde
  3. Wie verifiziert wurde
  4. Welche Restrisiken bleiben

Update-Regel

Wenn wir an einem Workstream arbeiten, soll dieses Dokument mitgezogen werden.
Kein „ist im Kopf klar“. Der Stand kommt hier rein.


2. Gesamtüberblick

Gesamtstatus

  • Projektphase: Umsetzung (WS-01)
  • Technischer Fokus aktuell: Entkoppelter TX-Pfad (FrameQueue + Writer)
  • Nächster sinnvoller Startpunkt laut Konzept: WS-01 Deterministische Echtzeit-TX-Pipeline mit entkoppeltem Writer
  • Vorangegangene Workstreams: WS-03 Semantische Korrektheit und konsistent angewandte Config (abgeschlossen)

Repo-bezogene bestätigte Ausgangslage

Thema Status Notiz
TX-Engine aktuell als synchroner Single-Loop CONFIRMED internal/app/engine.go
Persistenter DSP-Zustand im Generator vorhanden CONFIRMED internal/offline/generator.go
HTTP-Control vorhanden CONFIRMED internal/control/control.go
Config-Validation vorhanden, aber nicht überall semantisch konsistent CONFIRMED internal/config/config.go + Runtime-Pfade
Device/Capability-Modell vorhanden, aber noch nicht streng genug CONFIRMED internal/platform/soapy.go
Lock-freier SPSC-Audio-Ringbuffer vorhanden CONFIRMED internal/audio/stream.go

Bereits bekannte bestätigte Inkonsistenzen

ID Status Beschreibung Ort
CFG-SEM-001 CONFIRMED fm.outputDrive wird in Validation und Runtime nicht konsistent behandelt internal/config/config.go, internal/app/engine.go
CTL-UX-001 RESOLVED handleAudioStream() beschreibt --audio-http; der CLI-Schalter ist nun vorhanden und setzt den Stream-Puffer für /audio/stream direkt. internal/control/control.go, cmd/fmrtx/main.go

3. Prioritätenmodell

Priorität Bedeutung
P0 Technische Perfektion und Determinismus
P1 Betriebssicherheit und Fehlerbeherrschung
P2 Hardware-Wahrheit und RF-Qualität
P3 Sichere und saubere Runtime-Steuerung
P4 Deployment-, Release- und Service-Reife

4. Umsetzungstracker nach Workstream

WS-03 — Semantische Korrektheit und harte Config-/Runtime-Konsistenz

Priorität: P0
Gesamtstatus: IN PROGRESS

Ziel

Ein einziger, eindeutig definierter Parameterraum. Jeder Wert hat exakt eine Bedeutung und identische Constraints in Config, HTTP-API, Runtime und Telemetrie.

Warum dieser Workstream zuerst

Wenn Semantik und Grenzwerte nicht sauber vereinheitlicht sind, bauen spätere Runtime- und Fault-Mechanismen auf unstabilem Fundament.

Aufgaben

WS-03-T1 — Parameterinventar erstellen

  • Status: VERIFIED
  • Owner: Builder A
  • Code-Orte:
    • internal/config/config.go
    • internal/app/engine.go
    • internal/control/control.go
    • internal/offline/generator.go
  • Ziel: Alle öffentlich und intern verwendeten Parameter inventarisieren mit:
    • Name
    • Typ
    • Einheit
    • Bereich
    • Default
    • hot-reload-fähig ja/nein
    • safety class
    • Telemetrie-Name
  • Offene Fragen:
    • Wo leben heute implizite Parameter, die nicht sauber dokumentiert sind?
    • Welche Runtime-Werte sind abgeleitet statt direkt konfigurierbar?
  • Nachweis:
    • docs/ws-03-parameter-inventory.md enthält das inventarisierte Parameter-Tableau und referenziert Config/Control/Engine.
    • Live-Nutzung über internal/control/control.goLivePatch dokumentiert.
  • Restrisiken:
    • versteckte Semantik in Helper-Funktionen übersehen

WS-03-T2 — Validation vereinheitlichen

  • Status: VERIFIED
  • Owner: Builder A
  • Code-Orte:
    • internal/config/config.go
    • internal/app/engine.go
    • internal/app/engine_test.go
    • internal/control/control.go
  • Ziel: Config.Validate(), Runtime-Update-Pfade und API-Patch-Validierung dürfen nicht divergieren.
  • Bereits bekannter Startpunkt:
    • fm.outputDrive
  • Nachweis:
    • CFG-SEM-001: outputDrive-Validation in Engine.UpdateConfig jetzt 0..10 (wie Config.Validate).
    • Tests (go test ./...) fangen neue Range ab und besitzen aktualisierten engine_test-Check.
    • Live-Patch fließt durch txBridge und LivePatch (control) → LiveConfigUpdate.
  • Restrisiken:
    • weitere Inkonsistenzen erst beim Inventar sichtbar

WS-03-T3 — DesiredConfig / AppliedConfig einführen

  • Status: IN PROGRESS
  • Owner: Lead Coderaffe
  • Code-Orte:
    • internal/app/engine.go
    • internal/control/control.go
    • ggf. Config-/Statusmodelle
  • Ziel: API und Runtime sollen trennen zwischen:
    • gewünschter Konfiguration
    • tatsächlich angewandter Konfiguration
    • aktuellem Runtime-Zustand
  • Nachweis:
    • internal/control/control.go wartet mit Snapshot-Updates, bis LivePatch erfolgreich war.
    • internal/control/control_test.go deckt ab, dass abgelehnte Live-Updates keine neue GET /config-Ansicht schreiben.
  • Restrisiken:
    • Die API liefert noch nicht beide Sichten gleichzeitig; weitere Workstreams müssen Desired/Applied explizit zurückgeben.

WS-03 Entscheidungslog

Datum Entscheidung Notiz
2026-04-05 CFG-SEM-001: fm.outputDrive Live-Validierung auf 0..10 angeglichen, Tests angepasst, Parameterinventar dokumentiert.
2026-04-05 WS-03-T3: Desired/Applied-Gate Control-API zeigt Snapshots nur noch, wenn LivePatch erfolgreich angewendet wurde; Tests verhindern irreführende Wunschwerte.

WS-03 Verifikation

Datum Fokus Ergebnis
2026-04-05 go test ./... ✅ Bestätigt Engine.UpdateConfig, LivePatch und Parameter-Range sowie Inventar-Dokumentation. Neue Control-Tests sichern Desired/Applied-Gate.

WS-01 — Deterministische Echtzeit-TX-Pipeline mit entkoppeltem Writer

Priorität: P0
Gesamtstatus: IN PROGRESS

Ziel

Generator/Upsampler und Hardwarewriter werden als getrennte Stufen mit kleinem, kontrolliertem Frame-Puffer betrieben.

Aktueller Stand

  • Der TX-Pfad ist laut Konzept aktuell noch synchron gekoppelt: GenerateFrame -> optional FMUpsampler.Process -> driver.Write
  • Das ist elegant, aber nicht pro-level-hart gegenüber Write-Spikes und Blockaden.

Aufgaben

WS-01-T1 — FrameQueue einführen

  • Status: VERIFIED
  • Owner: Lead Coderaffe
  • Code-Orte:
    • internal/output/frame_queue.go
    • internal/output/frame_queue_test.go
    • internal/app/engine.go
  • Ziel: Bounded Queue mit fester Kapazität, sichtbarem Füllstand, Counter- / Statistikzugriff und klarer Trennung zwischen Generator und Writer.
  • Zu entscheiden:
    • Puffern vor oder nach Upsampling → Device-Frame-Ebene (Queue lebt nach dem Upsampler) für Writer-Simplifizierung.
    • Referenzkapazität: runtime.frameQueueCapacity (default 3) bleibt konfigurierbar.
  • Akzeptanzpunkte:
    • Keine unbounded Queue.
    • Fill-Level (High/Low) ist aus QueueStats sichtbar.
    • Queue-Health-Indikator (queue.health) liefert critical, low oder normal aus dem Fill-Level. EngineStats.queue zeigt den Status ebenfalls.
    • Drop/Repeat/Mute-Counter sind vorhanden und testbar.
  • Nachweis:
    • FrameQueue-Implementierung (internal/output/frame_queue.go) liefert kapazitätsgesteuerte Push/Pop-Logik und Counters.
    • Engine-Run nutzt Queue vor dem Writer und zeigt QueueStats in EngineStats.
    • Tests (internal/output/frame_queue_test.go + go test ./...) decken Push/Pop, Timeout-Counters, Stats und den neuen Queue-Health-Indikator ab.
  • Restrisiken:
    • Die Queue wird aktuell synchron getrieben; ein dedizierter Writer-Worker fehlt noch.
    • Queue-Close erwartet, dass Generator/Writer vor dem Schließen stoppen, sonst droht Panik beim Schreiben.

WS-01-T2 — Writer-Worker einführen

  • Status: VERIFIED
  • Owner: Lead Coderaffe
  • Code-Orte:
    • internal/app/engine.go (run loop, writerLoop, cloneFrame, Stats)
    • internal/dsp/* (FMUpsampler / Resampler copy GeneratedAt für Cycle-Metriken)
  • Ziel: Generator/Upsampler liefern Frames in die FrameQueue, driver.Write() läuft nur noch im dedizierten Writer.
  • Akzeptanzpunkte:
    • writerLoop() ist die einzige Stelle mit driver.Write() und zieht aus der Queue.
    • FrameQueue ist ein echter Puffer (Generator klont Frames, Writer poppt) und EngineStats.Queue zeigt den Füllstand.
    • Write- und Cycle-Latenzen plus LateBuffers bleiben in EngineStats sichtbar (MaxWriteMs, LateBuffers, MaxCycleMs).
  • Nachweis:
    • go test ./... (Engine + Queue + DSP) läuft erfolgreich.
    • EngineStats berichtet weiterhin über Queue-/Writer-Metriken.
  • Restrisiken:
    • Frame-Klonierung pro Chunk erhöht Heap-Pressure; spätere Workstreams sollten Pooling / Zero-Copy prüfen.

WS-01-T3 — Supervisor-Schicht einführen

  • Status: IN PROGRESS
  • Owner: Lead Coderaffe
  • Code-Orte:
    • internal/app/engine.go
  • Ziel: Queue-Füllstand, Late-Rate und Fehlerhäufigkeit überwachen und in explizite Runtime-Zustände überführen, sodass ein degradierter Queue-Health-Pfad automatisch auf degraded, muted oder faulted zeigt.
  • Akzeptanzpunkte:
    • Alle Runtime-Entscheidungen laufen über evaluateRuntimeState, nicht stillschweigend weiter auf running.
    • Queue-Health, Late-Buffers und Fault-Events treiben gezielt degradedmutedfaulted, damit Operatoren wissen, wann Blockaden vorliegen.
    • EngineStats und /runtime bringen runtimeIndicator, queue, faultHistory, transitionHistory und das runtimeState-Label, so Telemetrie und UI dieselben Signale sehen.
  • Nachweis:
    • internal/app/engine.go (Generator-/Writer-Loops) ruft evaluateRuntimeState auf und protokolliert Fault-Events, Transition-Historien und Counters.
    • txBridge.TXStats (cmd/fmrtx/main.go) leitet die Runtime-Infos an /status und /runtime, damit die API-Layer aktuelle Fault-Zustände spiegeln.
    • internal/app/runtime_state_test.go plus go test ./... sichern die erwarteten Transition-Reihenfolgen und Fault-Counter.
  • Restrisiken:
    • Queue-Schwellen für critical/lateBuffers brauchen noch Feldvalidierung und ggf. Konfiguration.
    • Fault-Reset/Operator-Interaktion ist im Control-Plane-UI noch zu finalisieren.

Offene Architekturfragen

  • Ist capacity_frames = 3 ein guter Startwert oder nur Konzept-Default?
  • Sollte im Fault-Fall repeat last safe frame erlaubt sein oder von Anfang an nur mute?
  • Wie eng koppeln wir WS-01 mit WS-02, ohne Overengineering zu erzeugen?

WS-01 Entscheidungslog

Datum Entscheidung Notiz
2026-04-05 FrameQueue mit Engine-Integration Queue lebt nach dem Upsampler auf DeviceFrame-Ebene, Kapazität via runtime.frameQueueCapacity, EngineStats zeigt QueueStats, Tests decken Timeouts und Counters ab.
2026-04-05 Queue-Health-Indikator QueueStats.Health gibt critical/low/normal zurück und txBridge leitet EngineStats.Queue ins /runtime-JSON.
2026-04-05 Runtime-Indikator EngineStats.RuntimeIndicator kombiniert queue.health + lateBuffers, /runtime zeigt engine.runtimeIndicator.
2026-04-05 /status runtime indicator /status reuses txBridge.TXStats() and now reports runtimeIndicator alongside the config snapshot for quick ops.
2026-04-05 /status queue stats /status spiegelt das queue-Objekt aus txBridge.TXStats() für schnelle Queue-Checks, API-Doku und TestStatusReportsQueueStats fangen den neuen Key ab.

WS-01 Verifikation

Datum Fokus Ergebnis
2026-04-05 FrameQueue + Engine integration go test ./... (im internal-Modul incl. frame_queue_test.go)
2026-04-05 Queue-Health-Indikator go test ./... deckt TestFrameQueueHealthIndicator und queue.health ab.
2026-04-05 Runtime-Indikator OK go test ./... deckt runtimeIndicator sowie /runtime-Exposition von engine.runtimeIndicator.
2026-04-05 Runtime API queue health /runtime liefert jetzt engine.queue.health dank txBridge.TXStats.
2026-04-05 /status runtime indicator /status gibt jetzt runtimeIndicator aus (control_test deckt den neuen Key).
2026-04-05 /status queue stats TestStatusReportsQueueStats plus docs/API.md zeigen, dass queue korrekt durchgereicht wird.

WS-02 — Explizite Runtime-State-Maschine und Fault-Handling

Priorität: P0
Gesamtstatus: IN PROGRESS

Ziel

Einführen eines klaren Betriebsmodells mit Fault-, Recovery- und Muted-Zuständen.

Fortschritt

  • EngineStats liefert das Runtime-State-Feld (idle, arming, prebuffering, running) und reagiert nun auf Queue-Gesundheit bzw. späte Buffers, indem es bei low/critical oder späten Buffern in degraded wechselt und sonst auf running zurückkehrt.

  • evaluateRuntimeState escalates persistent critical queues from degraded to muted, while FaultReasonQueueCritical surfaces muted severity so the mute transition stays observable.

  • evaluateRuntimeState now waits for a short healthy streak before leaving muted, logging a degraded-severity recovery event once the queue settles.

  • Persistent queue-critical streaks while muted now escalate to faulted with FaultSeverityFaulted, keeping RuntimeStateFaulted observable.

  • EngineStats and txBridge now expose transition/fault counters plus lastFault, surfacing the new telemetry through /runtime.

  • Control-plane UI now renders those WS-02 transition counters, fault count, and last-fault summary so operators can watch runtime escalations without digging through logs.

  • Control-plane now exposes POST /runtime/fault/reset so operators can acknowledge faulted state; TestRuntimeFaultReset* covers the new HTTP path.

  • Control-plane UI now also offers a Danger Zone Reset Fault button that calls the same endpoint so operators can acknowledge faults from the dashboard.

  • Control-plane UI now posts an ops toast/log entry whenever the runtime state shifts so escalations and manual acknowledgements are immediately visible.

  • Control-plane UI now keeps a compact Transition History panel beside the Fault History so operators can see recent runtime shifts without scrolling the activity log.

Zielzustände laut Konzept

  • idle
  • arming
  • prebuffering
  • running
  • degraded
  • muted
  • faulted
  • stopping

Aufgaben

WS-02-T1 — Fault-Klassifikation definieren

  • Status: IN PROGRESS
  • Owner: Lead Coderaffe
  • Beispiele:
    • queueCritical
    • lateBuffers
    • writeTimeout (z. B. Driver-Timeouts)
    • queueEmpty
    • unknown (Catch-all für unvorhergesehene Runtime-Zustände)
  • Ziel: Alle relevanten Fehlertypen als FaultReason/FaultSeverity codieren, damit sie später eindeutig auf Telemetrie und Logs abgebildet werden können.
  • Nachweis:
    • internal/app/fault.go definiert Reasons (queueCritical, lateBuffers, writeTimeout, queueEmpty, unknown) und Severity-Stufen (warn, degraded, muted, faulted).
    • internal/app/engine.go ruft recordFault im Queue- und Late-Buffer-Prozess auf, so dass jede Reason vom Fault-Historien-Log erfasst wird.
    • internal/app/runtime_state_test.go und internal/app/fault_test.go prüfen, dass die Reason/Severity-Kombinationen korrekt geloggt und ausgewertet werden.
  • Restrisiken: Weitere Driver-/Hardware-Faults (z. B. Soapy-Timeouts oder Audio-Stream-Abbrüche) müssen noch explizit getriggert und klassifiziert werden.

WS-02-T2 — Reaktionsstrategie definieren

  • Status: IN PROGRESS
  • Owner: Lead Coderaffe
  • Ziel: Reaktionen für jede FaultSeverity klar definieren (warn → loggen, degraded → degrade state, muted → stilllegen, faulted → Reset-Hürde).
    • warn only
    • degraded
    • muted
    • faulted
  • Nachweis:
    • evaluateRuntimeState eskaliert queueCritical-Läufe zuerst zu degraded, dann muted, schließlich faulted und protokolliert die entsprechenden Severity-Labels.
    • Engine.ResetFault() bringt faulted deterministisch zurück auf degraded, damit die Supervisor-Logik das Manual-Reset respektiert.
    • Tests in internal/app/runtime_state_test.go prüfen, dass die Transition-Counter (degradedTransitions, mutedTransitions, faultedTransitions) und faultCount bei den richtigen Ereignissen springen.
  • Restrisiken: Die aktuellen Schwellen basieren auf queueCritical-Streaks; zusätzliche FaultSources (Driver, Audio-Stream, Live-Update-Rejection) brauchen eigene Severity-Strategien.

WS-02-T3 — Fault-Historie und Event-Log einführen

  • Status: IN PROGRESS
  • Owner: Lead Coderaffe
  • Ziel: Zustandswechsel, Fault-Count und Trace-Historien auditierbar machen, damit /runtime und die UI eine nachvollziehbare Story liefern können.
  • Nachweis:
    • EngineStats enthält faultHistory, transitionHistory, lastFault, faultCount sowie runtimeStateDurationSeconds und Runtime-Indikatoren.
    • txBridge.TXStats leitet diese Infos in /runtime und /status weiter, internal/control/control_test.go sichert, dass faultHistory und transitionHistory korrekt serialisiert werden.
    • internal/app/runtime_state_test.go validiert die Historienkapazität, go test ./... deckt die API-Exposition ab.
  • Restrisiken: Die History-Kapazität ist auf 8 Einträge begrenzt; ein Audit-Log-Backend könnte später die Lücke auffangen.

Offene Designfragen

  • Wie fein granular darf die State-Maschine werden, ohne unwartbar zu werden?
  • Welche Transitionen sind wirklich produktiv relevant und welche nur „theoretisch schön“?

WS-02 Entscheidungslog

Datum Entscheidung Notiz
2026-04-05 Faulted escalation on persistent critical queue muted now surfaces RuntimeStateFaulted when queue health stays critical and metrics capture every transition.
2026-04-05 Manual fault reset endpoint Added POST /runtime/fault/reset so operators can acknowledge faulted before the supervisor re-enters recovery.
2026-04-05 Fault-reset UI shortcut Danger Zone now hosts a Reset Fault button wired to /runtime/fault/reset so operators get an in-app acknowledgement path without manual HTTP calls.
2026-04-06 Runtime transition visibility cue Control UI now posts toast/log entries for runtime state shifts so ops instantly sees escalations and manual reset acknowledgements.
2026-04-06 Transition history panel Added a compact Transition History panel next to the Fault History so the last few runtime state shifts stay visible even when the activity log is full.

WS-02 Verifikation

Datum Fokus Ergebnis
2026-04-05 Faulted path + transition counters go test ./... exercises TestEngineFaultsAfterMutedCriticalStreak and TestRuntimeTransitionCounters, while /runtime now surfaces engine.degradedTransitions, engine.mutedTransitions, engine.faultedTransitions, engine.faultCount, and the last fault via txBridge.
2026-04-05 Runtime fault reset API go test ./... now runs TestRuntimeFaultReset*, verifying the new HTTP path and controller error scenarios.
2026-04-06 Runtime transition visibility go test ./...; manual UI smoke verification still pending to ensure the toast/log flow shows every runtime shift.

WS-04 — Observability, Telemetrie und Diagnosefähigkeit

Priorität: P1
Gesamtstatus: TODO

Ziel

Vollständige Sichtbarkeit auf Runtime, Queue, Writer, Generator, RF-Selbsttests und API-Aktivität schaffen.

Aufgaben

WS-04-T1 — Strukturiertes Logging

  • Status: TODO
  • Owner: offen

WS-04-T2 — Prometheus-/Metrics-Schicht

  • Status: TODO
  • Owner: offen

WS-04-T3 — Debug-/Profiling-Endpunkte

  • Status: TODO
  • Owner: offen

Gewünschte Beispielmetriken

  • engine_chunks_generated_total
  • engine_late_buffers_total
  • engine_fault_transitions_total
  • writer_write_duration_seconds
  • queue_fill_ratio
  • queue_dropped_frames_total
  • queue_muted_frames_total
  • driver_write_errors_total
  • audio_stream_underruns_total
  • audio_stream_overflows_total
  • rf_selftest_pilot_db
  • rf_selftest_rds_57k_db

WS-04 Entscheidungslog

Datum Entscheidung Notiz
2026-04-06 High-watermark trend sparkline Captured audio high-watermark duration history and surface it as a new Health-panel sparkline for queue pressure visibility.
2026-04-06 Queue fill visibility Added queue fill ratio health line and sparklines to highlight real-time queue pressure alongside high-watermark trends.
2026-04-07 Underrun streak telemetry StreamStats now expose current and max underrun streak counters so queue diagnostics can see repeated underruns without touching the metrics stack.

WS-04 Verifikation

Datum Fokus Ergebnis
2026-04-06 High-watermark trend sparkline go test ./... plus manual UI check confirm the new sparkline updates with runtime audio stats.
2026-04-06 Queue fill visibility go test ./... plus UI smoke check confirm queue fill stats stay available and the new sparkline/health line react to queue health changes.
2026-04-07 Underrun streak telemetry go test ./internal/audio confirms the new streak counters plus Stats coverage so the API surfaces the same names.

WS-05 — Sichere und erwachsene Control-Plane

Priorität: P1 / P3-nah
Gesamtstatus: TODO

Ziel

API transport- und anwendungsseitig härten, state-aware machen und auditierbar gestalten.

Aufgaben

WS-05-T1 — Auth und Deploy-Modi definieren

  • Status: TODO
  • Owner: offen
  • Zielmodi:
    • localhost-only
    • trusted-lan
    • secured-remote

WS-05-T2 — HTTP-Server härten

  • Status: TODO
  • Owner: offen
  • Mindestpunkte:
    • ReadTimeout
    • WriteTimeout
    • IdleTimeout
    • ReadHeaderTimeout
    • Body-Size-Limits
    • Content-Type-Validierung
    • Method Enforcement

WS-05-T3 — API semantisch aufräumen

  • Status: TODO
  • Owner: offen
  • Ziel:
    • DesiredConfig vs AppliedConfig vs RuntimeState
    • idempotente Start/Stop-Endpunkte
    • transaktionsartige Apply-/Reject-Antworten
    • Audit-Log pro Eingriff

Frühe Quick-Wins

Diese Punkte könnten ggf. vorgezogen werden, auch wenn WS-05 formal nach WS-01/02 kommt:

  • HTTP-Timeouts
  • Body-Limits
  • sicherer Standard-Bind-Modus

WS-05 Entscheidungslog

  • 2026-04-06: /audio/stream now enforces a binary Content-Type (application/octet-stream or audio/L16) before queuing any samples.
  • 2026-04-06: /audio/stream caps uploads at 512 MiB and rejects larger bodies with 413 Request Entity Too Large before touching the ring buffer.

WS-05 Verifikation

Datum Fokus Ergebnis
2026-04-05 /audio/stream rejects non-POST requests TestAudioStreamRejectsNonPost enforces POST-only access to /audio/stream before a stream source is configured
2026-04-06 /audio/stream enforces binary Content-Type headers TestAudioStreamRejectsMissingContentType and TestAudioStreamRejectsUnsupportedContentType confirm 415 when the media type is missing or wrong
2026-04-06 /audio/stream rejects oversized uploads TestAudioStreamRejectsBodyTooLarge confirms a 413 Request Entity Too Large before buffering when the HTTP body exceeds the 512 MiB guard

WS-06 — Hardware-in-the-loop und externe RF-Wahrheitsprüfung

Priorität: P2
Gesamtstatus: TODO

Ziel

Nicht nur intern richtig rechnen, sondern extern nachweisen, dass tatsächlich korrekt gesendet wird.

Status

  • Konzept vorhanden
  • noch kein eingetragener HIL-Arbeitsstand in diesem Dokument

Offene Kernfragen

  • Welches Referenz-Setup wird verbindlich?
  • Welche Testfrequenz / Standarddauer / Schutzmaßnahmen gelten?
  • Welcher externe Decoder / Empfänger gilt als Referenz?

WS-07 — Device-aware Capability- und Kalibrierungsmodell

Priorität: P2
Gesamtstatus: TODO

Ziel

Fähigkeiten und Kalibrierungen nicht implizit, sondern explizit pro Device modellieren.

Noch offen

  • Capability-Schema konkretisieren
  • Kalibrierungsprofil definieren
  • Device-aware Validation einbauen

WS-08 — Signal-Selbstüberwachung im Betrieb

Priorität: P2
Gesamtstatus: TODO

Ziel

Pilot, Stereo, RDS und Composite-Anomalien im Betrieb erkennen.

Noch offen

  • Goertzel/FFT-Strategie festlegen
  • Schwellwerte definieren
  • in Fault-Logik einspeisen

WS-09 — Teststrategie erweitern

Priorität: P3/P4-nah
Gesamtstatus: TODO

Ziel

Von Unit-Tests zu echter Qualitätsabsicherung: Golden Vectors, Long-Run, Race, Fuzzing, API-Mutation, HIL.

Noch offen

  • Testpyramide konkretisieren
  • Nightly-/CI-Fähigkeit bestimmen

WS-10 — Service-Reife, Packaging und Reproduzierbarkeit

Priorität: P4
Gesamtstatus: TODO

Ziel

Build-, Release- und Betriebsartefakte reproduzierbar und teamtauglich machen.

Noch offen

  • Build-Metadaten
  • Service-Units
  • Config-Versionierung / Migration

5. Übergreifende Regeln

Musts

  • Jeder neue Runtime-Zustand muss per API und Telemetrie sichtbar sein.
  • Jede Recovery-, Drop- oder Mute-Strategie braucht Counter, Logs und Tests.
  • Keine neue Config-Option ohne klaren Typ, Bereich, Einheit, Default und Hot-Reload-Klassifikation.
  • Hardware-nahe Änderungen brauchen mindestens Simulations- und HIL-Validierung.
  • Alle Faults müssen eine maschinenlesbare Ursache und eine menschenlesbare Zusammenfassung haben.

Must Not

  • Keine unbounded Queues.
  • Keine stillen Fallbacks ohne Telemetrie.
  • Keine teilweise angewandten Live-Config-Änderungen ohne explizite Rückmeldung.
  • Keine unterschiedlichen Grenzwerte zwischen Config, API und Runtime.
  • Keine sicherheitsrelevanten HTTP-Endpunkte ohne Härtung im Remote-Betrieb.

6. Aktuelle offene Entscheidungen

ID Status Frage Notiz
DEC-001 RESOLVED Puffern wir auf CompositeFrame- oder DeviceFrame-Ebene? Queue lebt nach dem Upsampler (DeviceFrame-Ebene) gemäß internal/app/engine.go-Integrationsschleife.
DEC-002 OPEN Fault-Recovery zuerst mit mute, repeat last safe frame oder beidem? Muss technisch und RF-seitig sauber bewertet werden
DEC-003 OPEN Ziehen wir minimale WS-05-Basis-Härtungen vor? Timeouts/Body-Limits evtl. früher sinnvoll
DEC-004 OPEN Wie gross/simpel halten wir die erste State-Maschine? Gefahr von Overengineering

7. Nächste sinnvolle Schritte

Empfohlener Start

  1. WS-03-T1 Parameterinventar erstellen (abgeschlossen)
  2. bekannte Inkonsistenzen (CFG-SEM-001, CTL-UX-001) konkret verifizieren
  3. DesiredConfig / AppliedConfig / RuntimeState Zielmodell grob skizzieren
  4. Danach Architekturarbeit an WS-01 + WS-02 starten
  5. Aktuell: WS-01-T2 Writer-Worker einführen (Queue → Driver), danach WS-01-T3 Supervisor + WS-02 Runtime-State.

Vor dem ersten grossen Umbau klären

  • Was ist „minimal sinnvoll“ für Milestone 1?
  • Welche Dinge sind harte Must-haves und welche nur spätere Veredelung?
  • Wo wollen wir bewusst nicht sofort maximal abstrahieren?

8. Änderungsprotokoll

Datum Änderung Person / Agent
2026-04-05 Initiales Arbeitsdokument aus fm-rds-tx_pro_runtime_hardening_concept.json erstellt Alfred