Meridian

Architecture

Six modules, one protocol boundary, and a rule about what may depend on what.

Meridian decides which satellite passes are worth receiving, schedules them, monitors the stations doing the work, and reports measured reliability. The parts that do this are kept deliberately separate, because the boundaries are what make the claims checkable.

Layers

Meridian layer diagram Anyone, anywhere reaches the dashboard and public API, which sits on the platform. The platform contains orbit feeding prediction feeding scheduler, plus the observation store, registry and reliability modules. External archives connect to the platform by an optional, data-only path. Below the platform, the Meridian Station Protocol connects three kinds of station: station 001 on a Pi with an SDR, a microcontroller station, and fifty simulated stations, labelled as simulated. ANYONE, ANYWHERE DASHBOARD + PUBLIC API PLATFORM orbit prediction scheduler observation store registry reliability external archives data only MERIDIAN STATION PROTOCOL Station 001 Pi + SDR Microcontroller station 50 simulated labelled as such

The independence test. Remove every dashed element and the system still schedules, receives, decodes, monitors and reports. External archives are a source of training data, never a runtime dependency — if every external service went offline permanently tomorrow, Meridian would still work using our own stations alone.

Modules

orbit
Propagation, element-set archive, uncertainty model. It owns the boundary to the propagation libraries — no other module imports them, so a propagator change never ripples outward. Provides pass windows for a location and capability, look angles over time, the expected Doppler curve, and position uncertainty for a given element-set age. Coordinate frames are where silent bugs live: the frame SGP4 outputs is not an Earth-fixed frame and is not a topocentric one, so every conversion is deliberate and tested against known passes.
prediction
Feature extraction, yield model, horizon inference, calibration. Provides the probability of a successful decode for a given station and pass, a learned per-azimuth horizon profile, and calibration metrics. It degrades to geometry alone for a station with no history, and it knows nothing about the protocol or about HTTP.
scheduler
Constrained optimisation over candidate passes. It consumes predictions and does not read the observation store directly. It enforces non-overlap including slew and settling time, per-station capability limits, and operator priority weights. The reasoning behind each assignment is a first-class output rather than something reconstructed later, because the dashboard has to show why a pass was chosen or skipped.
registry
Station registration, capabilities, tokens, health state, last-heartbeat age. It is the authority on whether a station was listening at a given moment, which is what every reliability metric ultimately rests on.
observations
Ingest, normalisation, deduplication — the system of record. Records are immutable once written and corrections are additive. Every record carries provenance, and the simulated flag propagates from registration through to every derived record and every API response.
reliability
Service level indicators, objectives, the irrecoverable-loss budget, and failure injection. This module owns one definition that the whole project depends on, described below.

The rules

  1. Module boundaries are firm. Cross-module access goes through interfaces, not database queries.
  2. Only the orbit module imports propagation libraries.
  3. Only the reliability module decides what counts as a miss.
  4. The simulated flag propagates from registration to every derived record and every API response.
  5. The station client never assumes connectivity. Reception is never blocked on the platform being reachable.
  6. No transmit code paths anywhere. Stations receive; they do not transmit.

Absence is not a miss

A station that reported no data has not necessarily missed anything. It is counted as having missed a pass only when the registry confirms it was listening, on the right frequency, for the right target. Silence from a station that was switched off is not a failure to receive; it is an absence of evidence, and recording it as a miss would quietly corrupt every reliability figure built on top of it.

This distinction is load-bearing, so it is encoded in exactly one place and never duplicated.

Honesty rules

Three constraints exist because a reliability platform that overstates itself is worth nothing:

  • Simulated data is labelled as simulated at every layer — database column, API field, dashboard badge, report. A simulated result presented as a measured one would destroy the credibility of every other number.
  • Evaluation uses temporal splits only. Shuffling time-series observation data into training and test sets leaks the future into the past and produces a model that looks excellent and predicts nothing.
  • Every number in a report is regenerable from a dataset snapshot, a configuration file and a seed.

Deployment

Everything runs under Docker Compose, with PostgreSQL and TimescaleDB on the station computer's own storage — observations are time-series data and are stored as such. Public access is via a secure tunnel, so no static IP is required and the platform works from behind a restrictive network.

docker compose up on a clean machine must produce a working platform in under ten minutes. That is a requirement, not an aspiration.

Read the full architecture document on GitHub, or see the protocol for how stations connect.