flood-hub-guidance-feed

Turning Flood Guidance Into CAP

A field note on an experiment that polls Google Flood Hub flash-flood guidance, reconciles warning changes, and can publish generated CAP alerts through Multi Channel Relay.

The flood-hub-guidance-feed project is an experiment in a fairly specific question:

What happens when useful hazard guidance exists outside CAP, but we still want to handle it with CAP-shaped operational discipline?

The current implementation polls the Google Flood Hub Flood Forecasting API for flash-flood warnings. It keeps a local PostgreSQL inventory, caches the polygon payloads referenced by warnings, detects create/update/expiry transitions, and can generate CAP 1.2 alerts for warning creation and update events.

That last sentence needs a caveat. This is not an official public warning feed, and it is not a claim that upstream guidance automatically becomes an authoritative public alert. It is a technical experiment: can a guidance signal be represented, traced, and distributed through the same kind of machinery used for CAP alerting, while keeping provenance and uncertainty visible?

Why this was worth trying

CAP is strongest when an alerting authority publishes a public warning directly. But operational systems often need to work with adjacent signals too: guidance products, model outputs, hydrological warnings, impact forecasts, and other hazard intelligence that may not arrive as CAP.

The useful experiment was not “turn every hazard API into a public alert.” That would be too blunt.

The more careful experiment was:

  • poll a non-CAP upstream source
  • preserve the upstream identifiers and raw warning revisions
  • detect meaningful changes over time
  • generate CAP only for selected lifecycle transitions
  • publish through the same authenticated relay path as other CAP producers
  • keep the generated CAP traceable back to the guidance source

That lets the team test the boundaries between detection, guidance, publication, and downstream delivery without pretending those boundaries have disappeared.

What the service does

On each poll, the service calls the Flood Hub flash-flood search endpoint, follows pagination, and assembles a current inventory. It treats a successful poll as a full snapshot, not as an event stream.

That distinction matters. A warning is only marked expired when it was previously live and then absent from a later successful full enumeration. If the upstream request fails, pagination breaks, or the inventory is incomplete, the service does not infer expiry from that failure.

For each warning candidate, the service separates three ideas:

  • the upstream identifiers
  • a local stable warning identity
  • a revision fingerprint

That gives it a practical change model:

  • new identity means CREATED
  • same identity with a new fingerprint means UPDATED
  • same identity with the same fingerprint means UNCHANGED
  • absence from a successful later inventory means EXPIRED

The implementation also fetches and caches serialized polygon payloads. Those polygons can be converted into CAP polygon coordinates and used later for better human-readable area descriptions.

CAP generation, but with restraint

Generated CAP alerts are built for created and updated flash-flood guidance warnings.

The CAP payload includes traceability parameters such as the local warning id, revision id, fingerprint, polygon id, poll run id, forecast issue time, and source event polygon id. The event code currently uses the OASIS Event Terms value for flooding, OET-194.

The generated headline is deliberately simple:

Flash Flood Warning for ...

The hard part is the ....

Raw polygon identifiers are useful for machines and audit trails, but they are not good public language. The project now has a geometry-place-description boundary and a placeholder/scale-aware path for area wording, but the more general problem remains open: how should a system describe an irregular hazard polygon in a way that is concise, defensible, and useful to people?

That is not just a flood problem. It applies to wildfire perimeters, storm areas, river basins, coastal zones, and many other hazard geometries.

Why expiry is not a CAP cancel

One design choice I like in this experiment is the handling of natural expiry.

When a warning disappears from the next successful Flood Hub inventory, the service records that local lifecycle transition. It does not publish a CAP Cancel.

That is intentional. In CAP, Cancel means the previous alert should be cancelled. It is often interpreted as a correction to a previously issued public alert, or a statement that the earlier message should no longer be acted upon.

Absence from a refreshed guidance inventory is weaker than that. It may mean the guidance product has aged out, changed shape, or no longer appears in the current result set. That is useful internal state, but it is not automatically a public all-clear.

So the current relay notifier publishes create and update transitions, while expiry is logged and retained without emitting a public CAP message.

Publishing through Multi Channel Relay

Relay publication is opt-in and disabled by default.

When enabled, flood-hub-guidance-feed publishes generated CAP XML to multi-channel-relay using a context-scoped machine JWT. The private key is owned by the guidance-feed service. If no private JWK is supplied, the service can generate and persist its own RSA signing identity in the local database, then expose only the public import material for relay configuration.

That makes the experiment operationally useful: a generated CAP producer can be onboarded to the relay without sharing a private key with the relay.

There is also a startup CAP Test alert path. This is a small but practical deployment feature. A real flash-flood guidance update may not happen immediately after a deployment, so the startup test alert gives operators a way to prove that CAP generation, machine JWT signing, and relay publication are wired correctly.

What remains open

The experiment is useful, but it is not finished.

The open work is exactly the kind of work that determines whether this remains a lab service or becomes a reusable pattern:

  • generated CAP XML should be optionally signed with XMLDSig
  • human-readable area descriptions need stronger geospatial evidence
  • generated CAP should be run through the same validation workbench being planned for Evaluate Alert
  • downstream consumers need clear provenance and caveats
  • any production use would need governance around who is authorized to publish which kind of message

The most valuable outcome so far is not the fact that the service can generate CAP. It is the shape of the experiment: keep upstream guidance distinct, preserve auditability, use CAP carefully, and publish through authenticated relay machinery only when the operator has explicitly enabled it.

That feels like the right kind of caution for CAP-adjacent work.