Linear: https://linear.app/tinyland/issue/TIN-1725/openaq-payload-contract-numericnull-counts-capped-state-and-station
Problem
The OpenAQ proxy currently returns viewport-scoped GeoJSON features, but the browser cannot distinguish the cases that matter for field UX: numeric PM2.5 readings, null/unknown readings, upstream degradation, capped result sets, and sparse coverage. This makes the smog layer and downstream transmission estimates hard to explain.
Scope
- Extend the OpenAQ proxy response with top-level metadata: bbox, fetchedAt, feature count, numeric PM2.5 count, null/unknown count, degraded, and capped/limit-hit state.
- Preserve null-reading stations as explicit unknowns, but never treat them as clean air or use them in kernel estimates.
- Keep the OpenAQ key server-side only.
- Update the layer health/visibility logic to use numeric PM2.5 count, not raw feature count.
Acceptance
- Sparse Ithaca-style viewports can say "no numeric PM2.5 readings in viewport" without implying proxy failure.
- Dense viewports report numeric/null counts and whether the upstream limit was hit.
- Heatmap mode is gated on numeric readings only.
- Tests cover missing key/degraded, all-null, mixed numeric/null, and capped responses.
Related: #271, #275, #253.
Linear: https://linear.app/tinyland/issue/TIN-1725/openaq-payload-contract-numericnull-counts-capped-state-and-station
Problem
The OpenAQ proxy currently returns viewport-scoped GeoJSON features, but the browser cannot distinguish the cases that matter for field UX: numeric PM2.5 readings, null/unknown readings, upstream degradation, capped result sets, and sparse coverage. This makes the smog layer and downstream transmission estimates hard to explain.
Scope
Acceptance
Related: #271, #275, #253.