SDD V3.03 · 2026-10-18

MRRC Modern
Software Design Description

Canonical design record for architecture, interfaces, operational model, and runtime evolution of the multi-radio (FT-710 / IC-7300 / IC-7300MK2) web control system.

SDD Scope

IBM TeamSD aligned, 15 chapters, implementation-grounded content.

Attribute Value
Document ID SDD-MRRC-MODERN-2026-001
Version V3.03
Baseline Date 2026-10-09
Runtime Python 3.12+, FastAPI, Uvicorn, PyAudio, NumPy
Frontend HTML5, CSS3, vanilla JavaScript, Web Audio API
Core Interfaces 4+1 WebSockets (optional ATR1000) + Serial CAT / CI-V + FT4222 SPI / CI-V 0x27 + USB Audio

What's New

An Unattended Box Cannot Fill Its Disk: Log Rotation, a Journald Cap, and a Recording That Refuses Instead of Filling (V2.99)

logs/server-stdout.log is systemd's StandardOutput=append: target, and neither systemd nor the server rotates an append: target — which made it the one file in an image with no ceiling. Measured: a defect that logged one warning per 20 ms audio frame wrote 17 MB in five hours on a 6.5 GB root. The service layer now ships /etc/logrotate.d/mrrc (5 MB trigger, three generations, compressed, copytruncate because systemd holds the descriptor) with its own mrrc-logrotate.timer — it does not trust cron or the distro's timer to be running — and caps journald at 128 MB (the default is 10% of the filesystem).

Recordings got the non-destructive half of a retention policy: below MRRC_RECORDINGS_MIN_FREE_MB (200 MB, about seven hours at the default bitrate) a new recording is refused, with the numbers, and never started. Nothing the operator recorded is deleted to make room.

one bounded file · one bounded journal · refusals, never deletions

The Hub Can No Longer Pin a Certificate the Instance Has Replaced, and the FT8 Decoder Stops Killing Its Own Worker (V2.98)

sign_for() now signs once per name: a usable pair (CN/SAN match, more than 30 days to expiry, key and certificate paired, parseable) is reused and not rewritten, so "signed but the enrolment failed" can no longer leave the hub pinning one certificate while the instance serves another — the shape of an all-night 502 on a live entry. Rotating is an explicit act (delete the file), and a broken instance heals by clicking Connect once.

The FT8 deep path used to kill the server's DSP worker on every slot: a Fortran stop in the native decoder terminates its host process, and the launcher's startup tee stops writing to a file once the server answers HTTP — so the reason reached no log at all, only a bare worker_exit. The worker now writes its own logs/ft8-worker.log (the diagnostic bundle collects it), the FFTW thread initialisation returns a status instead of aborting, and worker_exit names the generation and the restart count.

AD-021 · idempotent enrolment · a worker's death is now diagnosable

A Shipped Box Needs No Setup: Fixed Credentials, Wi-Fi and the Public Entry from One Page (V2.92)

The flash-and-ship image (build-image.sh --preflash, off by default) bakes in the three credentials, Asia/Shanghai and zh_CN.UTF-8, so a box goes from power-on to a logged-in browser with nothing in between. Wi-Fi grew a typed SSID field (scan results only prefill it) plus a show/hide password toggle — hidden networks and an empty scan list used to be dead ends — and a new public-entry panel takes a callsign, applies to the portal and reports the entry address. The same pass fixed a real gap: the first-boot probe had never run on any image (the wrapper's MRRC_PRESEED=1 call short-circuited before it), so a radio plugged in later was never found; the probe now runs and repeats each boot until the config settles.

AD-027 · NFR-069 · first-boot probe now actually runs

15 SDD Chapters

AD-001 ... AD-030

AD-001 FastAPI/Uvicorn AD-002 Direct CAT AD-003 Dirty State Broadcast AD-004 Tagged Opus/PCM Audio AD-005 scope_pipe Isolation AD-006 Dual-Mode Spectrum AD-007 PTT Safety Flow AD-008 Audio Auto-Detection AD-009 7-Task Polling AD-010 JSON Memory Channels AD-011 48kHz Codec + 44.1kHz Bridge AD-012 Active-VFO Tracking AD-013 Meter Calibration AD-014 CAT Errata Handling AD-015 Priority CAT Preemption AD-016 Pluggable Radio Backend AD-017 Server-Side Recording AD-018 Profile-Driven Yaesu Core AD-019 Unverified-Model Policy AD-020 One-Touch CQ Call AD-021 Diagnostics Bundle AD-022 Update Channel AD-023 Remote-Session Metering AD-024 Session-Token Transport AD-025 Spectrum Bandwidth Tiers AD-026 Setup Hotspot and the Password-less Window AD-027 Factory-Preset (Ship-Ready) Image AD-028 Local Control Surface (Bluetooth Remote) AD-029 SDR Receiver (box-only public web receiver) AD-030 Antenna Bench (NanoVNA-H, /Nano)