* feat(climate+health):add shared air quality seed and mirrored health/climate RPCs
* feat(climate+health):add shared air quality seed and mirrored health/climate RPCs
* fix(air-quality): address review findings — TTL, seed-health, FAST_KEYS, shared meta
- Raise CACHE_TTL from 3600 to 10800 (3× the 1h cron cadence; gold standard)
- Add health:air-quality to api/seed-health.js SEED_DOMAINS so monitoring dashboard tracks freshness
- Remove climateAirQuality and healthAirQuality from FAST_KEYS (large station payloads; load in slow batch)
- Point climateAirQuality SEED_META to same meta key as healthAirQuality (same seeder run, one source of truth)
* fix(bootstrap): move air quality keys to SLOW tier — large station payloads avoid critical-path batch
* fix(air-quality): fix malformed OpenAQ URL and remove from bootstrap until panel exists
- Drop deprecated first URL attempt (parameters=pm25, order_by=lastUpdated, sort=desc);
use correct v3 params (parameters_id=2, sort_order=desc) directly — eliminates
guaranteed 4xx retry cycle per page on 20-page crawl
- Remove climateAirQuality and healthAirQuality from BOOTSTRAP_CACHE_KEYS, SLOW_KEYS,
and BOOTSTRAP_TIERS — no panel consumes these yet; adding thousands of station records
to every startup bootstrap is pure payload bloat
- Remove normalizeAirQualityPayload helpers from bootstrap.js (no longer called)
- Update service wrappers to fetch via RPC directly; re-add bootstrap hydration
when a panel actually needs it
* fix(air-quality): raise lock TTL to 3600s to cover 20-page crawl worst case
2 OpenAQ calls × 20 pages × (30s timeout × 3 attempts) = 3600s max runtime.
Previous 600s TTL allowed concurrent cron runs on any degraded upstream.
---------
Co-authored-by: Elie Habib <elie.habib@gmail.com>
* chore: redeploy to pick up WORLDMONITOR_VALID_KEYS fix
* fix(disease-outbreaks): use TGH lat/lng for map pins, fix location, add cases + date to tooltip
Root cause: all map pins collapsed to country centroids (getCountryCentroid) even though TGH
provides exact lat/lng per alert. Deduplication further collapsed all same-disease+country
alerts into one pin. 90-day lookback of ~1,600 TGH records was being reduced to ~10 pins.
- proto: add lat, lng, cases fields to DiseaseOutbreakItem (field 10/11/12)
- seed: preserve _lat/_lng/_cases from TGH bundle per alert
- seed: trim place_name to first comma-segment to avoid "Riga, Riga, Latvia" display
- seed: TGH items skip keyword filter (already disease-curated) and deduplication
- seed: raise cap to 150 TGH + 50 WHO/CDC/ONT (from flat 50 total)
- DeckGLMap: use item.lat/lng when non-zero, fall back to country centroid
- tooltip: add date and case count (when available) below source name
- sourceVersion bumped to v6
* chore: regenerate HealthService OpenAPI docs — add lat, lng, cases fields
* fix(mcp): address Greptile P2s — coordinate falsy coercion, dedup sort order, dead tooltip branch
- Use Number.isFinite() + null-coalescing (??) instead of || 0 for lat/lng; prevents
treating equatorial coord 0 as "missing" (even though TGH already filters !rec.lat)
- DeckGLMap: use Number.isFinite + !== 0 guard instead of falsy && check for lat/lng
- Sort otherOutbreaks by publishedAt desc BEFORE deduplication so first-seen = most recent
- Remove redundant re-sort of dedupedOthers (already sorted above)
- Simplify metaHtml: always show date (publishedAt is always set); remove dead else-branch