# Weather Data Internals This document describes the implemented weather data ingestion boundary. ## Purpose `internal/adapters/weatherapi` fetches normalized weather data from one configured weather API endpoint and assembles a `forecast.Bundle`. ## Inputs and Outputs Input: - `config.Config` with `weather_api.base_url`, `format`, `units`, `timezone`, `precision`, timeout, and missing-source policy. Output: - `forecast.Bundle` containing observation, current conditions, hourly forecast, narrative forecast, alerts, discussion, stub source slots, provenance, and source warnings. ## Boundaries - The adapter performs HTTP calls and decoding only. - Forecast derivation, daypart grouping, report periods, report rendering, and `scriptorium` execution are outside this boundary. - Hourly forecast data is required. Other missing or malformed source sections use the configured missing-source policy. ## External Adapter The adapter calls: - `/observations` - `/conditions/current` - `/forecast/hourly` - `/forecast/narrative` - `/alerts/active` - `/discussion` Forecast routes use the full-product endpoints, not day-slice endpoints. ## State `app.FetchAndSaveBundle` can save an inspectable bundle JSON file using an atomic rename. No report state, snapshots, or prompt input packages are written yet. ## Failure Behavior - HTTP and envelope decode failures return actionable errors with endpoint context. - Missing hourly data fails the fetch. - Missing or malformed optional sources follow `error`, `warn`, or `none`. - Source identity uses SHA-256 over compacted raw `data` JSON. ## Tests Inspect: - `internal/adapters/weatherapi/client_test.go` - `internal/app/app_test.go` ## Invariants - Weather facts come from normalized source data. - External API details stay inside `internal/adapters/weatherapi`. - Source provenance and warnings remain inspectable for later briefing builders.