Implemented NWS weather stories support
All checks were successful
ci/woodpecker/push/build-image Pipeline was successful

This commit is contained in:
2026-05-30 06:47:18 -05:00
parent cca873cafb
commit fd820fd964
19 changed files with 931 additions and 11 deletions

69
API.md
View File

@@ -37,11 +37,12 @@ Examples:
## Canonical schemas
weatherfeeder emits four canonical domain schemas:
weatherfeeder emits five canonical domain schemas:
- `weather.observation.v1`
- `weather.forecast.v1`
- `weather.forecast_discussion.v1`
- `weather.weather_story.v1`
- `weather.alert.v1`
Each payload is described below using the JSON field names as the contract.
@@ -49,11 +50,14 @@ Each payload is described below using the JSON field names as the contract.
### Raw upstream schemas
weatherfeeder sources also emit provider-specific raw schemas before normalization.
For this feature, the raw source schema is:
Relevant raw source schemas include:
- `raw.nws.forecast_discussion.v1`
- payload type: string
- payload contents: exact fetched HTML response body
- `raw.nws.weatherstories.v1`
- payload type: object
- payload contents: exact fetched JSON response body
---
@@ -227,6 +231,38 @@ A run may contain zero, one, or many alerts.
---
## Schema: `weather.weather_story.v1`
Payload type: `WeatherStoryRun`
A `WeatherStoryRun` is a snapshot of NWS weather stories for an office as-of a point in time.
The run may contain zero, one, or many stories.
### Fields
| Field | Type | Required | Notes |
|---|---:|:---:|---|
| `officeId` | string | no | NWS office identifier, e.g. `LSX` |
| `asOf` | string (timestamp) | yes | Latest story update time or source fallback |
| `stories` | array | yes | Weather stories (order provider-dependent) |
### Nested: `stories[]` (`WeatherStory`)
| Field | Type | Required | Notes |
|---|---:|:---:|---|
| `officeId` | string | no | NWS office identifier |
| `startTime` | string (timestamp) | yes | Story validity start |
| `endTime` | string (timestamp) | yes | Story validity end |
| `updatedAt` | string (timestamp) | yes | Story update time |
| `title` | string | no | Human story title |
| `description` | string | no | Story narrative text |
| `altText` | string | no | Accessibility text for the provider graphic |
| `priority` | bool | yes | Provider priority flag |
| `order` | int | yes | Provider display order |
| `downloadUrl` | string | no | Provider download URL; weatherfeeder does not fetch the asset |
---
## Schema: `weather.forecast_discussion.v1`
Payload type: `WeatherForecastDiscussion`
@@ -337,3 +373,32 @@ It is distinct from `weather.forecast.v1`, which is period-based.
}
}
```
### Weather story event (`weather.weather_story.v1`)
```json
{
"id": "nws:weatherstories:2026-05-30T09:00:34Z",
"schema": "weather.weather_story.v1",
"source": "nws_weatherstories",
"effectiveAt": "2026-05-30T09:00:34Z",
"payload": {
"officeId": "LSX",
"asOf": "2026-05-30T09:00:34Z",
"stories": [
{
"officeId": "LSX",
"startTime": "2026-05-30T08:46:00Z",
"endTime": "2026-05-31T11:00:00Z",
"updatedAt": "2026-05-30T09:00:34Z",
"title": "Several Chances for Rain Through Monday",
"description": "Scattered showers and thunderstorms remain possible.",
"altText": "This slide shows the forecast for today through Tuesday.",
"priority": false,
"order": 1,
"downloadUrl": "https://api.weather.gov/offices/LSX/weatherstories/download/3228e499-2aae-45a8-9ff9-1c060311026f"
}
]
}
}
```