Commit Graph

7 Commits

Author SHA1 Message Date
jing
941f5032e0 wave3: layer registry + generic GeoJSON factory (+ 4 new free layers)
- js/layers/geojson-layer.js: one factory expressing fetch/dedupe+revision/
  time-anchoring/cap/style/status — adding a GeoJSON feed is now data entry
- js/registry.js: quakes & fires refactored onto it (verified parity — same
  counts/colors/time-anchoring), plus 4 new REAL layers, all default-off:
  GDACS disasters (93), NWS severe weather US (13), Launch Library (30),
  NSW RFS bushfires (21)
- deleted js/layers/quakes.js + fires.js (now registry entries); removed dead
  CONFIG.quakes/fires blocks
- factory honors default-off (ds.show synced to enabled); zero console errors

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 00:26:13 +10:00
jing
96926091a6 wave3: swap military feed to free adsb.lol (drop the paid RapidAPI dependency)
proxy/mil forwards api.adsb.lol/v2/mil — free, keyless, identical {ac:[...]}
shape to ADS-B Exchange, so the layer is unchanged bar its label. 60s server
cache for politeness (no quota to guard). proxy/adsbx-mil stays server-side as
an unused paid fallback; John can cancel the RapidAPI sub once it lapses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 00:15:28 +10:00
jing
bb09bcfae7 harden ADSBx quota guard: 5-min → 10-min single-flight cache
The $10 ADSBx BASIC tier has NO hard limit and bills $0.0015/request over
10k/month, so the cache TTL must guarantee we stay under. Widened the cache
window 5→10 min: since proxy_cache_lock coalesces all requests into ONE upstream
call per window, this caps upstream at ~144 calls/day (~4.4k/month, <half the
10k cap) regardless of visitors or poll rate. Prod nginx also got
proxy_cache_lock_timeout/age for a hard single-flight guarantee even under a slow
upstream. Dev serve.py ADSBX_CACHE_SEC 300→600 to match. Frontend poll stays
5 min for display freshness (cheap cache hits; the server cache governs quota).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 23:51:57 +10:00
jing
0bbdb30719 feat: Military (ADS-B Exchange) layer — real unfiltered military aircraft
Wires John's paid ADS-B Exchange RapidAPI feed ($10/mo, ~10k req/month) into a
new layer showing the military traffic OpenSky/FR24 hide (C-17 "Reach" airlift,
tankers, the Area 51 "Janet" shuttle, etc.).

- serve.py: proxy/adsbx-mil injects the x-rapidapi-key/host headers SERVER-SIDE
  (key read from gitignored adsbxcredentials.json, never in the browser) and
  HARD-caches /v2/mil/ for 5 min — the quota guard: <=~288 upstream calls/day
  (~8.6k/month) no matter how many tabs poll. Stale-on-error; 503 if unconfigured.
- js/layers/military.js: BillboardCollection like the civilian layer but a
  distinct red; live-only (no history feed), 5-min poll matched to the cache.
  ADSBx altitude is FEET (→metres for Cesium). Emergency squawks (7500/7600/
  7700) highlight brighter+bigger and flip the HUD status to err. Click overlay
  shows type / tail / altitude / speed / squawk.
- config.js: adsbx block + militaryReal/militaryEmerg colours.

Verified in dev: proxy miss→hit (5-min cache, key not leaked), 412 military
aircraft render over CONUS, click RCH042 → C17 / 99-0062 / 34000ft / 424kt,
zero console errors. adsbxcredentials.json stays gitignored + server-side.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 23:07:40 +10:00
jing
dadc068271 wave2 phase 1: earthquakes layer (real USGS, time-anchored)
New js/layers/quakes.js — fetches the USGS all_day GeoJSON directly (ACAO:*,
no proxy), refreshes every 5 min regardless of scrub state. Quakes are
time-anchored via availability: in-window quakes appear as the slider crosses
their origin time, older-than-window quakes stay visible the whole window
(intervals clamped to [start, stop]). Magnitude ramps amber→red, size scales
with magnitude, quakes <1h old pulse (age-aware callback), labels only for
M>=4.5. Deduped by feature id across refreshes, capped at 400 (smallest mag
dropped first). HUD row "Earthquakes (USGS)" with count/max-mag status.

Also: serve.py now sends Cache-Control: no-store on all responses (was
proxy-only) so iterative js/css edits always take effect on reload — the
module graph was caching stale copies during dev.

Verified in browser: 223 quakes, 11 labeled, time-anchoring confirmed
(187 visible at -6h → 223 at now), zero console errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 16:01:59 +10:00
jing
6c7b945848 phases 2-5: satellite, aircraft, ship, infra & event layers
- satellites: Celestrak TLE -> SGP4 -> time-dynamic entities w/ glowing orbit
  paths; per-source cap + reordering so COSMOS/ISS aren't starved by the 72-sat
  Gaofen fleet (now ~97 sats, diverse); chunked propagation, orbital InfoBox
- aircraft: global OpenSky ADS-B -> BillboardCollection primitive (6444 planes
  verified), altitude-banded, quota/scrub/visibility-gated polling, click overlay
- ships: [DEMO] fleet through Hormuz incl. toll-route carrier, dark-vessel AIS
  gap, Fujairah idle cluster; optional aisstream.io live path
- infra: choke-point rings, Petroline + Habshan-Fujairah pipelines, 9 facilities
- events: [DEMO] time-anchored pulsing markers that appear as the slider crosses
- authored + adversarially hardened via parallel agent workflow

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 12:25:51 +10:00
jing
7356d62381 phase 1: globe core — viewer, dual basemaps, clock, HUD, layer contract
- CesiumJS viewer (token-free, baseLayer:false), Carto dark + EOX Sentinel-2
- clock spans now +/-6h CLAMPED; built-in timeline/animation = the space-time slider
- HUD: brand, LIVE/SCRUBBED chip, Data/Photo mode toggle, layer rows, credits
- lighting is mode-aware: OFF in Data (high-contrast asset map), ON in Photo
  (realistic day/night terminator) — refines SPEC 6.1's global-lighting note
- main.js defines the layer-factory contract + dynamic loader; layers land next
- serve.py now forwards OpenSky X-Rate-Limit-* headers for the aircraft status line

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 12:06:05 +10:00