Validates that every destination path stays within project_root
before writing. Prevents a malicious zip from writing outside
the project directory via ../traversal entries.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: 3140416e80b1b56e4e6cccc930d11c2d5f9b1611
In Docker, main.py lives at /app/main.py so Path.parent.parent
resolves to filesystem root /, causing PermissionError on .github
and other dirs. Now detects this case and falls back to cwd.
Also grants backenduser write access to /app for auto-update.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: 12c8bb5816a70161d5ab5d79f9240e7eab6e6e15
os.makedirs was outside try/except so permission-denied on .github
directory creation crashed the entire update. Now both makedirs and
copy are caught. Also prunes protected dirs from os.walk so the
updater never even enters .github, .git, .claude, etc.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: d4bdef4604095a82860a4bc91bec3435a878f899
The auto-updater tried to extract .github/ from the release zip,
causing Permission denied errors. Added .github and .claude to the
protected directories list so they are skipped during extraction.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: 8916fa08e005820ddbfc3b195c387dbf6187587e
Auto-update POST goes through Next.js proxy which dies when extracted
files trigger hot-reload. Network drops now transition to restart polling
instead of showing failure. Also adds admin key header and FastAPI error
field fallback. Gitignore updated to protect internal docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: 03162f8a4b7ad8a0f2983f81361df7dba42a8689
selectedEntity.id was stored as a numeric array index into data.gdelt[]
and data.news[]. After any data refresh those arrays rebuild, so the
stored index pointed to a different item — showing wrong popup content.
GDELT features now use g.properties?.name || String(g.geometry.coordinates)
as a stable id; popups resolve via find(). News popups resolve via find()
matching alertKey. ThreatMarkers emits alertKey string instead of originalIdx.
ThreatMarkerProps updated: id: number → id: string | number.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Former-commit-id: c2bfd0897a9ebd27e7c905ea3ac848a89883f140
interpFlight, interpShip, and interpSat were plain arrow functions
recreated on every render. Because interpTick fires every second,
TrackedFlightLabels received a new function reference every second
(preventing memo bailout) and all downstream useMemos closed over
these functions re-executed unnecessarily.
Wrap all three in useCallback([dtSeconds]) — dtSeconds is their
only reactive closure variable; interpolatePosition is a stable
module-level import and does not need to be listed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Former-commit-id: 84c3c06407afa5c0227ac1b682cca1157498d1a5
- Remove WorldviewRightPanel from left HUD (declutter)
- Restore sliding sidebar animation via motion.div on both HUD containers
- Left tab (LAYERS): springs to x:-360 when hidden, tab tracks edge
- Right tab (INTEL): springs to x:+360 when hidden, tab tracks edge
- Both use spring animation (damping:30 stiffness:250)
- ChevronLeft/Right icons flip direction with open state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Former-commit-id: 5a573165d27db1704f513ce9fd503ddc3f6892ef
Removes WorldviewRightPanel render and import from page.tsx.
The effects state is preserved as it continues to feed MaplibreViewer.
Left HUD column now contains only the data layers panel.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Former-commit-id: 0cdb2a60bd8436b7226866e2f4086496beed1587
Acknowledge aircraft registration databases (public FAA records).
Reword "no data collected" to specifically mean no user data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: d00580da195984ec70475d649f0f0e091a90ba48
Positions the project as a public data aggregator, not a surveillance
tool. Clarifies that no data is collected or transmitted beyond rendering.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: 53eb82c6104f5c061d361c71c44f8c61b7e12897
- Fetch interval: 30min → 24h (TLEs only update a few times daily)
- Add If-Modified-Since header for conditional requests (304 support)
- Remove 10-thread parallel blitz on TLE fallback API → sequential with 1s delay
- Increase timeout 5s → 15s (be patient with a free service)
- SGP4 propagation still runs every 60s — satellite positions stay live
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: 67b7654b6cc2d05c0a8ff00faad7c45c9cf2aa2d
Adds subtle amber glow circles behind both cluster and individual
tower markers for a pulsing radar-station effect.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: bf6cee0f3b468006356fd95dcf83a27d5e62e5f6
Replaced the circle cluster layer with a symbol layer using the same
radio tower icon. Clusters show the tower with a count label below.
No more orange blobs at any zoom level.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: 0b1cb0d2a082dde4dcefe12518cdfb28b492ab89
Individual nodes now render as amber radio tower SVGs with signal waves.
Clusters use a subtle amber glow ring with count label instead of solid
orange blobs. Much less visual clutter against the flight/ship markers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: 96baa3415440118a6084c739d500a1ce5951d27f
- kiwisdr_fetcher.py imported non-existent `smart_request` (renamed to
`fetch_with_curl`), causing silent ImportError → 0 nodes returned
- Replaced KiwiSDR iframe embed with clean "OPEN SDR RECEIVER" button.
The full KiwiSDR web UI (waterfall, frequency controls, callsign
prompt) is unusable at 288px — better opened in a new tab.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: aa0fcd92b2390d6a8943b68f2f7eb9b900c7bbb7
python:3.10-slim now resolves to Debian Trixie where ttf-unifont and
ttf-ubuntu-font-family packages were renamed/removed, causing Playwright's
--with-deps chromium install to fail. Pin to bookworm (Debian 12) for
stable font package availability.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: 805560e4b7e3df6441ed5d7221f6bf5e9e665438
Replaces array-index-based selection with stable backend identifiers so
selected entities persist correctly across data refreshes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Former-commit-id: 14e316d055ba0b1fe16a2be301fcaaf4349b5a29
Each alert bubble now has an × button in the top-right corner.
Clicking it hides the alert for the session and clears its selection
if it was active.
- Dismissal keyed by stable content hash (title+coords) so dismissed
state survives data.news array replacement on every 60s polling cycle
- Button stopPropagation prevents accidental entity selection on dismiss
- Single useState<Set<string>> — avoids naming collision with the
react-map-gl `Map` import that caused the previous black-screen crash
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: ce2dec52a9a40a581995323354414b278abdf443
The catch-all route.ts that proxies frontend /api/* requests to the backend
was accidentally deleted during the v0.8.0 rebase against PR #44. Without it,
all API fetches return 404 and nothing loads on the map.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: 811ec765320d9813efc654fee53ef0e5d5fecc78
New features:
- POTUS fleet (AF1, AF2, Marine One) with hot-pink icons + gold halo ring
- 9-color aircraft system: military, medical, police, VIP, privacy, dictators
- Sentinel-2 fullscreen overlay with download/copy/open buttons (green themed)
- Carrier homeport deconfliction — distinct pier positions instead of stacking
- Toggle all data layers button (cyan when active, excludes MODIS Terra)
- Version badge + update checker + Discussions shortcut in UI
- Overhauled MapLegend with POTUS fleet, wildfires, infrastructure sections
- Data center map layer with ~700 global DCs from curated dataset
Fixes:
- All Air Force Two ICAO hex codes now correctly identified
- POTUS icon priority over grounded state
- Sentinel-2 no longer overlaps bottom coordinate bar
- Region dossier Nominatim 429 rate-limit retry/backoff
- Docker ENV legacy format warnings resolved
- UI buttons cyan in dark mode, grey in light mode
- Circuit breaker for flaky upstream APIs
Community: @suranyami — parallel multi-arch Docker builds + runtime BACKEND_URL fix (PR #35, #44)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Former-commit-id: 7c523df70a2d26f675603166e3513d29230592cd
These are already covered by the .gitignore added in this branch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Former-commit-id: dcfdd7bb329ef7e63ee5755ccbe403bf951903f6