/** * The one place that fetches for the life-threatening alert banner. * * `get_forecast`, `get_current_conditions` and `get_weather_summary` all call * `resolveCriticalAlertBanner` rather than each doing their own fetch-gate-format * sequence, so the **failure posture exists once**. Three copies of a safety * failure posture is how one copy drifts, and the copy that drifts is the one * that renders a fabricated all-clear. * * The posture itself is D1 of the design plan: **silent omit**, one * `logger.warn`, and no retries. That is only safe because the banner is a * positive assertion — its absence claims nothing. `get_alerts` still serves * the same data under full contract rules, where a failure propagates. Nothing * in a tool description, schema or doc may ever say these three tools "check * for alerts", or absence silently becomes an implied all-clear. * * The gate, the selection and the copy all live in `src/utils/criticalAlert.ts`, * which is pure and zero-I/O. This module is the glue between that and the * service, and holds no display logic of its own. */ import { NOAAService } from '../services/noaa.js'; import type { ResolvedLocation } from '../utils/locationResolver.js'; /** * The banner for this point, or `''` — which is every path but one. * * In order: * * 1. **NWS-jurisdiction pre-filter.** `country_code` when the resolution path * knew one, geography otherwise — `isInUS` **or** `isInNwsTerritory`, the * latter covering the four territories `isInUS` deliberately leaves out * (Guam, the southern Marianas, the USVI, American Samoa). `isInUS` is not * widened to absorb them because it backs a *rendered* NWPS coverage claim in * `get_river_conditions`, where Puerto Rico is gauged and Guam is not * (GOTCHAS G53). The code path is the two sets above, and there are two of * them because a code settles `us` and `pr` on its own while the four * territory codes must also satisfy `isInNwsTerritory` — `MP` names a * territory NWS serves only the southern half of. NOAA is the only upstream * in v1 (D2), so a point outside NWS jurisdiction returns without making any * request at all. * 2. **One fetch, no retries.** `getAlerts` caches on its own point-keyed * alerts entry with the five-minute alerts TTL (`src/services/noaa.ts`), so a * banner fetch and a real `get_alerts` call within five minutes share one * request. This module deliberately builds no key and declares no TTL of its * own — that is what keeps risk floor F5 untripped, and the acceptance check * for it is a grep of this file for either construct. * 3. **Any failure is silent.** One `logger.warn` and `''`. Never a * "could not check alerts" note: repeated benign warnings during an upstream * outage train readers to ignore the banner slot, which is worse than * nothing at all. * 4. **All-or-nothing.** With no critical alert this emits nothing — no header, * no rule, no "no critical alerts" line. * * **G53 is not tripped by the pre-filter.** These are bounding boxes, but * nothing about any box is rendered: a false negative omits a * positive-assertion-only element and claims nothing. * * **A false positive is not free, and the old wording here was wrong about it.** * A point the CONUS or Hawaii box admits but NWS does not serve — Toronto * `43.65, -79.38`; Midway `28.21, -177.38`, which sits inside the Hawaii box — * draws **HTTP 400 `Parameter "point" is invalid: out of bounds`**, not a * 200-empty collection. `NOAAService.makeRequest` (`noaa.ts:133-138`) logs a * `securityEvent` warn and throws `InvalidLocationError`; this module's catch * logs a second; and `getAlerts` never caches a failure, so every call repeats * both. That cost is known, deferred (it needs either a narrowed shared routing * box or a 4xx-branch change in `noaa.ts`, both beyond the banner), and it is * the reason `isInNwsTerritory`'s boxes are drawn tightly to the islands rather * than generously — unlike `isInGreatBritain`, whose false positive is one cheap * Nominatim call. * * @param noaaService The NOAA client; its `getAlerts` is the only method called * @param resolved The already-resolved location, carrying `country_code` when known * @param timezone IANA zone the banner's expiry is rendered in * @returns The formatted banner, or `''` */ export declare function resolveCriticalAlertBanner(noaaService: NOAAService, resolved: ResolvedLocation, timezone?: string): Promise; /** * Carry an already-resolved banner on an error about to be thrown. * * `get_forecast` and `get_current_conditions` resolve the banner concurrently * with the weather body. When the body fails, the warning is the half the * caller most needs, so it travels with the error to the one place that renders * errors (`src/server/weatherServer.ts`) instead of being dropped. This keeps error formatting * and error logging at that single site rather than duplicating either here. * * An empty banner attaches nothing at all, so a failure with no critical alert * — every point outside NWS jurisdiction, and every point inside it with nothing * life-threatening active — is byte-identical to what it was before. * * @param error The error being thrown; returned unchanged for `throw` chaining * @param banner The resolved banner, or `''` * @returns The same error */ export declare function carryCriticalAlertBannerOnError(error: unknown, banner: string): unknown; /** * The banner carried by an error, or `''`. * * Read once, by the dispatch's error path. Returning `''` for every error that * carries nothing is what keeps the existing error output unchanged. * * @param error The caught error * @returns The carried banner, or `''` */ export declare function criticalAlertBannerFromError(error: unknown): string; //# sourceMappingURL=criticalAlertBanner.d.ts.map