Skip to content

v1.0.0

Choose a tag to compare

@goldbarth goldbarth released this 11 Jun 17:01
· 34 commits to main since this release
adb3274

port-tidewatch v1.0.0

Release date: 2026-06-11

First release. A small, focused storm-surge ingestion service modelled on the
Hamburg warning service (WADI): it ingests water-level readings, evaluates them
against staged thresholds in metres above NHN, and surfaces per-gauge alert
state on a read-only dashboard — observable end to end and deployable two ways.

Highlights

  • End-to-end ingestion pipeline — simulator → RabbitMQ → ingestion → state,
    with a dead-letter path for poison messages.
  • Staged, trend-aware surge evaluationnormal / warning (4.50 m) /
    severe (5.50 m), with a rising-trend nudge and de-escalation hysteresis so
    the stage does not flap on single outliers.
  • Distributed tracing — OpenTelemetry across the whole path (simulator →
    broker → ingestion) with W3C context propagation through the AMQP headers.
  • Read-only dashboard — Angular (standalone + signals), per-gauge level,
    stage, and a recent-history sparkline, polling a small HTTP API.
  • Two deployment targets — Kubernetes + Argo CD (GitOps) and Azure Container
    Apps, both verified.

What's included

Service & domain

  • Tidewatch.ContractsReading (decimal metres, DateTimeOffset) and
    AlertState.
  • Tidewatch.Ingestion — RabbitMQ transport with exchange/queue/dead-letter
    topology; ReadingConsumer (dead-letters malformed/invalid messages);
    per-gauge GaugeStateHolder with a single isolated stage-change point;
    SurgeEvaluator (median base stage + trend pre-escalation + hysteresis).
  • SurgeThresholdOptions bound from configuration and validated at startup
    (a bad threshold config fails fast).
  • Tidewatch.Simulator — emits readings for four gauges (CUX, HEL, STP, BHV).

API & dashboard

  • Read-only HTTP API on the ingestion host: GET /api/gauges (snapshot + a
    trend downsampled to a fixed bucket count) and /healthz.
  • Angular dashboard: gauge cards (level, stage badge, sparkline), 4 s polling,
    runtime-configurable API base URL, same-origin in dev/k8s and cross-origin
    (CORS) on the cloud stack.

Observability & tests

  • OpenTelemetry tracing with OTLP export; spans for receipt → evaluation →
    stage change, dead-letter outcomes marked as errors.
  • Unit tests for the evaluator (boundary, trend, hysteresis, outlier damping)
    and Testcontainers integration tests (boundary and rising-trend, end to end
    against a real broker).

Deployment

  • Kubernetes + Argo CD (primary) — Kustomize manifests for rabbitmq,
    ingestion, simulator, dashboard, and Jaeger, with an Ingress for same-origin
    /api routing; an Argo CD Application syncs from the repo. Runs on a local
    kind cluster (€0); portable to AKS.
  • Azure Container Apps — azd + Bicep (ACR, Container Apps environment, the
    three apps) plus Azure Static Web Apps (Free) for the dashboard. GitHub
    Actions: CI on push/PR, manual deploy via federated OIDC.

Decisions

Recorded as ADRs 001–004 under docs/adrs/ (threshold placement, dashboard
state, deploy target, evaluator algorithm). Runbooks for all three run modes are
under docs/.

Known limitations (by design)

  • No alert-event publishing yet — the stage-change chokepoint updates state
    only; publishing to a dedicated exchange is the v1.1 step (ADR-001).
  • Dashboard is intentionally minimal and read-only.
  • No cloud tracing backend in the Container Apps stack; tracing is exercised
    locally (and in the Kubernetes stack via an in-cluster Jaeger).
  • Kubernetes target is a local cluster (kind), chosen to keep cost at €0;
    AKS is a later swap.

What's next (v1.1)

Demo and polish — see M6 in docs/ISSUES.md: a storm-surge
scenario in the simulator (so severe is demonstrable), dashboard visual polish,
richer per-gauge signals, demo assets, and alert-event publishing.