Skip to content

v1.1.0 — Demo & polish

Choose a tag to compare

@goldbarth goldbarth released this 12 Jun 15:02
· 24 commits to main since this release
d2ad734

port-tidewatch v1.1.0

Release date: 2026-06-12

Demo & polish (M6). v1.0 was a complete, observable pipeline; v1.1 makes it
demonstrable and richer — a scripted storm surge so severe actually happens,
a presentable dashboard, more to watch per gauge, and alert events published off
the stage-change chokepoint.

Demo

The simulator drives one gauge (CUX) through a scripted surge while the others
hold normal, so the full normal → warning → severe → recede cascade is
visible end to end:

If the player does not load, download the clip
(≈ 60 s).

All gauges normal CUX entering severe at the surge peak CUX sustained severe with the peak marker near the top band
Calm — all normal. Peak — CUX severe (5.65 m). Held severe (5.75 m).

What you're seeing. Cards are gauges on a fixed 0–6 m NHN scale; the
shaded bands are the WADI thresholds (warning 4.50 m, severe 5.50 m).
The header summarises gauges per stage, the highest current level, and overall
status, and the live / last-updated indicator makes stale data obvious.

Highlights

  • Scripted storm-surge scenario — the simulator now drives a tide baseline
    plus a smooth raised-cosine surge (peak/period parameterisable via
    SURGE_PEAK_M / SURGE_PERIOD_S), so severe is reachable and the cascade
    tells a story instead of random noise.
  • Tidal operations dashboard — banded area charts on a fixed 0–6 m domain
    (the bands are the thresholds), a header summary, relative time-in-stage
    ("warning for 3 min"), a live / stale / offline indicator, self-hosted fonts,
    and animated stage transitions.
  • Richer per-gauge signals — the API DTO gains rate-of-change (m/min),
    time-in-current-stage, and window min/max, computed in the mapper (state stays
    raw, ADR-002) and surfaced as a trend arrow.
  • Alert-event publishing — a genuine stage change publishes an AlertEvent
    (gauge, previous → new stage, level, timestamp) to a fanout exchange from the
    single ApplyStageChange chokepoint (ADR-001), traced consistently with the
    existing OpenTelemetry path.

What's changed

Simulator

  • Composite level model (baseline + tide + scripted surge + small noise) with
    per-gauge roles; one gauge surges, the rest stay normal. The Reading
    contract and the publish path are unchanged — only level generation differs.

API & dashboard

  • GaugeDto gains rateMetersPerMin, timeInStageSeconds, windowMin,
    windowMax; the endpoint passes a single UtcNow so a response is internally
    consistent.
  • Dashboard reworked: banded charts with a peak marker, header summary, relative
    stage time, connection indicator (last good snapshot held across a failed
    poll — ADR-002 addendum), dark "tidal operations" theme with self-hosted
    Fraunces + IBM Plex Mono.

Ingestion

  • New AlertEvent contract and an IAlertPublisher seam; RabbitMqTransport
    declares a fanout alert exchange plus a durable audit queue and owns a
    dedicated publish channel. The initial normal establishment is suppressed,
    so a held stage publishes nothing.

Tests

  • Unit coverage for the computed DTO fields; integration tests that a single
    transition yields exactly one alert event and a held stage yields none.

Known limitations (by design)

  • No notification delivery — the chokepoint publishes alert events, but
    acting on them (email / push, a notification consumer) is out of scope.
  • Simulator is still the sole source — a real PEGELONLINE Elbe feed is the
    v1.2 (M7) step.
  • Dashboard remains read-only and polling-based.

What's next (v1.2)

Real data — see M7 in docs/ISSUES.md: a PEGELONLINE source
adapter (cm → m, PNP → NHN) alongside the simulator, a source-selection switch,
and a threshold "what-if" panel.