v1.0.0
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 evaluation —
normal/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.Contracts—Reading(decimal metres,DateTimeOffset) and
AlertState.Tidewatch.Ingestion— RabbitMQ transport with exchange/queue/dead-letter
topology;ReadingConsumer(dead-letters malformed/invalid messages);
per-gaugeGaugeStateHolderwith a single isolated stage-change point;
SurgeEvaluator(median base stage + trend pre-escalation + hysteresis).SurgeThresholdOptionsbound 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
/apirouting; an Argo CDApplicationsyncs 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.