Skip to content

Releases: d3mocide/Sovereign_Watch

Release - v1.1.2 - Performance, Globe Visualization, and JS8Call Integration

Choose a tag to compare

@d3mocide d3mocide released this 10 Jul 23:02

Sovereign Watch v1.1.2 introduces critical performance optimizations, renders corrections for the 3D Global Situation view, fixes UDP bridge compatibility with JS8Call and KiwiSDR audio nodes, and includes an API information leakage security patch.


High-Level Summary

This release resolves the visual artifact on the Global Situation globe view where night-shading appeared as a jagged, misplaced chord. It integrates LayerCache logic inside the globe view to prevent redundant 60Hz GPU buffer uploads. Startup delays for fresh map loads have been eliminated via WebSocket client last-value caching, concurrent RSS pre-warming, and Vite-level module preloading. In addition, JS8Call and KiwiSDR communication bridges have been corrected, and connection-level exception disclosures have been fully sanitized.

Key Changes

  • Globe Visualization Improvements:
    • Fixed 3D terminator Night overlay geometry by densifying pole-closing meridian edges to follow the sphere's curvature.
    • Memoized static global layer stack builders to eliminate CPU and GPU resource starvation on cold dashboard load.
    • Re-enabled depth-testing and depth-bias on globe night-shading to prevent far-hemisphere overlays from bleeding to the daylight side.
  • Cold-Start Map & Dashboard Optimizations:
    • Added last-value caching (LVC) to the event broadcast manager to stream active tracks to fresh clients instantly on connect.
    • Implemented concurrent RSS fetching and stale-while-revalidate pre-warming loops to prevent blocked text widgets.
    • Hoisted critical Mapbox/MapLibre and Deck.gl module preloading links into the index template at build time.
  • Operational Hardware Integrations:
    • Corrected the JS8Call UDP bridge listener model to dynamically route replies to active sender addresses and format lowercase API keys.
    • Aligned virtual KiwiSDR clients with standard plaintext password auth formatting.
  • Security & Stability Enhancements:
    • Sanitized outbound news article connection exceptions to return generic status details instead of internal stack traces.
    • Vectorized SGP4 groundtrack propagation and ECEF-to-LLA conversions using NumPy arrays, yielding up to a 5x speedup.
    • Coalesced consecutive WebSocket updates into batches to prevent packet drops.

Technical Details

  • Database Migrations: None.
  • Dependencies: None.
  • Performance Impact:
    • CPU/GPU allocation churn reduced significantly in dense environments due to paced render cycles (30 FPS cap under load) and binary attribute uploads.
    • SGP4 propagation latency reduced by ~3.5x.
    • Event time parsing and LLA coordinate conversions improved by ~5x.
    • Map painting and dashboard news loading latency dropped from ~30s to near-instant.

Upgrade & Deployment Instructions

To upgrade a local deployment to v1.1.2:

# 1. Pull the latest release changes
git fetch origin && git checkout main && git pull

# 2. Rebuild and restart the container services
docker compose down
docker compose up -d --build

Release - v1.1.1 - Core Rendering, Performance, and Position Stabilization

Choose a tag to compare

@d3mocide d3mocide released this 12 Jun 19:27

Summary

Sovereign Watch v1.1.1 is a patch release focusing on rendering pipeline optimization, client-side performance, tracking stabilization, and security hardening. It introduces frontend layer memoization and vendor code splitting to dramatically improve initial page load times and main-thread responsiveness, resolves a critical satellite position jump/surge bug, hardens news article extraction against DNS-rebinding SSRF attacks, and refactors UI control surfaces to improve keyboard and screen reader accessibility.

Key Features

⚡ Rendering & Performance Optimization

  • Frontend Layer Caching (LayerCache): Implemented a keyed layer cache for static overlays (airspaces, cables, alerts, etc.) in composeAllLayers(), returning identical Layer instances across frames. This allows deck.gl to skip diffing and attribute re-uploads entirely, reducing per-frame CPU overhead.
  • Pulse Quantization: Quantized shimmer pulse calculations to a 10 Hz interval (rather than 60 Hz), keeping static animated layers cached for consecutive frames.
  • Bundle Code-Splitting: Code-split large chunks (Vite config manualChunks for deck-gl, maplibre, mapbox, and echarts) and lazy-loaded major routes (TacticalMap, OrbitalMap, IntelGlobe, DashboardView, and RadioTerminal), reducing the initial JavaScript payload from ~5MB to ~200KB.
  • Vectorized Groundtrack Propagation: Batched ECEF-to-LLA conversion in get_groundtrack to process coordinate sequences using NumPy's vectorized functions in a single call, resulting in a 5x speedup on the SGP4 pass path.
  • Track History Loop Optimization: Precalculated the starting Julian date and step increments to step mathematically through fractional days, eliminating datetime construction and redundant conversions.

🛰️ Tracking & Position Stabilization

  • Epoch-Anchored Dead Reckoning: Anchored the dead reckoning (DRState) blend time directly to SGP4 propagation epochs rather than message receive times, resolving persistent display lag and eliminating the startup "fast-forward" catch-up surge.
  • Teleport Guard & Frame Stall Reset: Implemented a distance-based teleport guard in interpolatePVB to immediately snap elements when the visual-to-target gap exceeds normal bounds, and automatically clear visual state during long frame stalls (>1s) to prevent catch-up surges.
  • Antimeridian Crossing: Unwrapped longitude updates to ensure entities snap cleanly across the antimeridian rather than wrapping around the globe.

🛡️ Security Hardening

  • SSRF DNS-Rebinding Mitigation: Implemented a custom SSRFSafeTransport for httpx that resolves domain names to IP addresses exactly once, validates them against private/multicast ranges, and rewrites the request URL to target the validated IP. This closes the TOCTOU DNS-rebinding window on article extraction and RSS feed fetches.

♿ Operational Accessibility (A11y) Sweep

  • Form & Filter Labeling: Added explicit id and corresponding <label htmlFor="..."> attributes across all layer filters and visibility controls to support keyboard navigation and screen readers.
  • Button Safety & Types: Added explicit type="button" attributes, ARIA labels, and custom focus indicators to standalone UI controls, mitigating accidental form submissions and popover close accessibility issues.

Technical Details

  • Database Migrations: No database schema migrations are introduced in this patch.
  • Verification Gates: Passed all test suites on the host environment:
    • Frontend: pnpm run lint (clean), pnpm run typecheck (clean), pnpm run test (278/278 tests passed).
    • Backend API: ruff check (clean), pytest (158/158 tests passed).
    • Space Pulse: ruff check (clean), pytest (63/63 tests passed).

Upgrade Instructions

To apply these updates, pull the latest changes and rebuild the development or production stack:

git pull origin main
make dev  # or make prod

For production deployments, rebuild and restart the containers:

docker compose build sovereign-frontend sovereign-backend sovereign-space-pulse
docker compose up -d

Release - v1.1.0 - Security, Orbital Feeds, and Accessibility Hardening

Choose a tag to compare

@d3mocide d3mocide released this 26 May 15:02

Summary

Sovereign Watch v1.1.0 represents a significant milestone in platform security, data ingestion reliability, performance optimization, and accessibility. It hardens news aggregation against advanced server-side request forgery (SSRF), migrates core satellite tracking to standard CelesTrak OMM CSV formats, and delivers a robust accessibility overhaul across high-use operator controls.

Key Features

🛡️ Security Hardening

  • SSRF DNS-Rebinding Protection: Hardened the /api/news/article extraction gateway to resolve target hostnames via DNS and actively filter resolved IP addresses against private, loopback, link-local, and multicast ranges before dispatching HTTP request handles.

🛰️ Orbital Feeds & Performance

  • CelesTrak OMM CSV Feed Migration: Migrated the space_pulse orbital poller away from legacy, fixed-width TLE text endpoints to CelesTrak's modern OMM CSV feed format (FORMAT=CSV). Ingestion now uses standard sgp4.omm schemas to build orbital models without disrupting downstream SGP4 propagation or TAK event streams.
  • SGP4 Pass Prediction Optimization: Deferred strftime formatting and dictionary allocations in the orbital pass predictor loop to execute only when satellites exceed the minimum elevation threshold, preventing up to 8,640 redundant allocations per window and reducing CPU overhead.

♿ Operational Accessibility (A11y) Sweep

  • Keyboard & Screen Reader Access: Integrated aria-expanded, aria-controls, and onKeyDown support for collapsible panels across the dashboard (such as accordion grids in ListeningPost).
  • Interactive Control States: Bound aria-pressed, aria-label, and aria-hidden attributes across custom map toggles and NWS alerts widgets.
  • Semantic Disabled States: Standardized watchlist buttons around aria-disabled="true" with custom tooltips, preserving focus capability for keyboard users.
  • Action Authorization Prompts: Integrated dynamic aria-label feedback explaining authorization requirements for locked SITREP action panels.

🛠️ Ingestion & Packaging Compatibility

  • PEP 517 Standards: Standardized Python packaging setups across microservices (backend/api, aviation_poller, gdelt_pulse, js8call) to eliminate setuptools flat-layout discovery errors.
  • Space Pulse Alignment: Upgraded asyncpg to 0.31.0 for full Python 3.12 compatibility.

Technical Details

  • Ingestion cache files shifted suffix from .tle to .omm.csv to ensure clean cache transitions.
  • All unit test and lint gates (frontend 272/272 tests, backend 158/158 tests, space pulse OMM validation tests) passed successfully.

Upgrade Instructions

To apply these updates, pull the latest changes and rebuild the docker stack:

git pull origin main
make dev  # or make prod

For production environments, rebuild and restart the containers to activate the updated frontend and backend services:

docker compose build sovereign-frontend sovereign-backend sovereign-space-pulse
docker compose up -d

Release - v1.0.10 - Sovereign HUD Unification

Choose a tag to compare

@d3mocide d3mocide released this 22 Apr 20:55

Summary

This release focuses on UI/UX stability and critical production connectivity fixes. We have unified the tactical and orbital map HUDs into a single, vertically stacked container that eliminates panel overlaps and maintains perfect alignment with the right sidebar. Additionally, we have resolved a critical authentication regression in the JS8Call radio service and improved the accuracy of satellite telemetry.

Key Features

  • Unified HUD Stacking: All map-overlay widgets (NWS Alerts, Space Weather, Risk Analysis) now share a centralized vertical stack. Panels automatically reflow based on visibility and dynamically offset when the right sidebar is toggled.
  • JS8Call Auth Stabilization: Restored production WebSocket connectivity for the JS8Call radio terminal by ensuring proper JWT token propagation.
  • Improved TLE Accuracy: Increased satellite TLE refresh frequency from 24h to 6h to provide higher-fidelity orbital tracking.
  • HUD Layout Polish: Standardized analyst panel width to 380px for better readability and removed redundant alert indicators to reduce HUD clutter.

Technical Details

  • Frontend Refactor: Moved map-overlay logic from TacticalMap.tsx and OrbitalMap.tsx to a centralized mapHudStack in App.tsx.
  • Python 3.12 Compliance: Sanitized datetime.utcnow() calls across the ingestion stack to resolve deprecation warnings.
  • Resilient AI Caching: Implemented automated retry logic for the AI semantic cache to handle transient Redis connectivity issues.
  • SQL Optimization: Hardened the analysis router with explicit connection pooling for parallel fusion requests.

Upgrade Instructions

To apply these updates, pull the latest changes and rebuild the containers:

git pull origin main
make dev  # or make prod

If running in production, ensure you rebuild the frontend specifically to bake in the new HUD layout:

docker compose build sovereign-frontend
docker compose up -d

Release - v1.0.9 - Database Telemetry Hotfix

Choose a tag to compare

@d3mocide d3mocide released this 18 Apr 17:16

This emergency patch release targets a runaway CPU pipeline observed inside the TimescaleDB intelligence database that degraded platform responsiveness.

Key Features

  • Structural Indexing for Landmass Filters: Dark vessel detections check incoming satellite heat signatures against known terrestrial land boundaries to eliminate land-based false positives (like factories or forest fires). We've replaced the dynamic array parsing for these boundaries with native, statically indexed GIST Polygons.
  • Drastic CPU Reduction: Because PostGIS no longer builds Cartesian coordinate planes from scratch on every incoming operator request, TimescaleDB CPU utilization will drop from an artificial 700% floor back down to standard idle limits, ensuring long-term container health.

Upgrade Instructions

git pull origin main
make prod

Release - v1.0.8 - UI Telemetry Stabilization

Choose a tag to compare

@d3mocide d3mocide released this 18 Apr 17:05

This patch release shores up several tactical UI surfaces to resolve text overflow issues, eliminates redundant screen clutter, and completes the dashboard telemetry transition.

Key Features

  • Accurate Dashboard Stream Telemetry: The stream status bar previously monitored legacy backend configurations, showing whether API keys were merely loaded. It now taps directly into the active polling registry to display the true, real-time health (HEALTHY, STALE, ERROR) of active streams like Maritime AIS, Aviation ADS-B, OSINT, and Orbital passes.
  • Responsive Alert Summaries: Conflict and intelligence warning widgets now wrap threat-level counts to a clean sub-header row, improving layout scaling across all browser windows constraints.
  • Visual Decluttering: The obsolete generic "ALERTS" indicator has been scrubbed from the top tactical map bar, returning more screen real estate to direct situational feeds.

Upgrade Instructions

git pull origin main
make prod

Release — v1.0.7 — Security Hardening & Intelligence Accuracy

Choose a tag to compare

@d3mocide d3mocide released this 18 Apr 15:43

Released: 2026-04-18
Type: Patch
Previous: v1.0.6


Summary

v1.0.7 ships a high-priority security patch alongside a set of runtime stability fixes and a significant accuracy improvement to the Active Conflict Zone intelligence engine. Operators on HTTPS deployments will also see mixed-content WebSocket and WebSDR iframe errors resolved.


Key Changes

🛡️ Security

  • SSRF Fix — News Article Reader (HIGH)
    The /api/news/article reader endpoint now blocks requests to private/loopback addresses (127.0.0.1, 192.168.x.x, 169.254.x.x, etc.) and non-HTTP schemes before making any outbound connection. This closes a Server-Side Request Forgery vector that could have allowed authenticated operators to probe internal services.

🎯 Active Conflict Zone Accuracy

The ACTIVE CONFLICT ZONES panel previously showed [0] almost always, even with active warzones (Ukraine, Israel, Sudan) appearing in the actor feed. Root cause: the old Goldstein thresholds were calibrated against an idealised model rather than real GDELT data distributions.

What changed:

  • CRITICAL threshold: ≤ −6.0≤ −4.5 (Ukraine/Gaza cluster at −3 to −5)
  • ELEVATED threshold: ≤ −3.0≤ −2.0
  • New material-conflict volume shortcut: actors with >150 kinetic events → CRITICAL; >50 → at least ELEVATED (prevents dilution by high diplomatic-media volume)
  • MONITORING-level actors now appear in the conflict zone panel with a yellow WATCH badge, so operators see the full threat spectrum instead of just the top tier

🔧 Runtime Stability

  • AI Model Overload Advisory — Analyst Panel now shows an amber "Model Overloaded" notice instead of silently presenting heuristic fallback text when the LLM provider returns 503 / high demand.
  • SatNOGS Timeout Resilience — One retry added for transient station fetch timeouts; timeout vs. network failures now distinguished in response metadata.
  • HTTPS WebSocket Fix — Shared URL resolver promotes ws:///http:// build-time endpoints to same-origin secure paths when the app is served behind TLS. Eliminates mixed-content failures on HTTPS deployments.
  • WebSDR HTTPS Iframe — WebSDR receiver iframes are now HTTPS-upgraded on secure pages; original HTTP URL preserved as an external link fallback.
  • FIRMS Poller — Normalized legacy VIIRS_SNPP_NR alias; fixed empty-cache cooldown guard that caused tight re-poll loops.
  • News Feed — DefenseNews removed from the default feed set (intermittent non-standard HTTP status).

🐛 Code Review Bug Audit

A parallel audit identified and patched 7 confirmed bugs across the backend, frontend, and JS8Call service:

Component Bug Severity
analysis.py detect_rendezvous() / detect_emergency_transponders() called .description on a list → AttributeError crash when multiple anomalies fired simultaneously High
stats.py Octant index into OCT_LABELS without bounds check → IndexError on unexpected DB data Medium
js8call/server.py UDP send socket not closed in exception path → resource leak Medium
App.tsx res.json() called before res.ok check → HTTP error bodies silently parsed as valid GeoJSON Medium
analysis.py Bare except Exception: pass on intel-context DB lookup → failures completely invisible Low
kiwi_client.py self._password stored but never read → unnecessary sensitive-data retention in memory Low
auth.ts res.status !== 204 guard unreachable (204 is 2xx, res.ok already true) → dead code Low

A second set of findings (pool exhaustion risk, lock-free read in kiwi_directory.py, orphaned subprocess handles) was documented in the task log as a backlog for the next audit cycle.


⚙️ Configuration

  • GDELT Conflict Keywords — Now configurable via GDELT_CONFLICT_KEYWORDS env var without a code change.
  • ReliefWeb App Name — Now configurable via RELIEFWEB_APPNAME env var.
  • nginx-spa.confindex.html is no longer cached, reducing stale-bundle issues after deploys behind CDNs.

Technical Notes

  • No database migrations — no schema changes in this release.
  • No new environment variables are mandatory; all new vars have sensible defaults matching previous behaviour.
  • The sovereign-backend container should be rebuilt to pick up AI overload handling, SatNOGS, and news changes.
  • The sovereign-gdelt-pulse container should be rebuilt to pick up the conflict-filter and ReliefWeb config changes.
  • The sovereign-space-pulse container should be rebuilt to pick up the FIRMS poller alias fix.
  • Frontend: no rebuild required for already-deployed prod builds if served via nginx (nginx-spa.conf change only affects cache headers, not functionality).

Verification

Suite Result
Frontend lint ✅ Clean
Frontend typecheck ✅ Clean
Frontend tests ✅ 272/272
Backend API lint ✅ Clean
Backend API tests ✅ 152/152
GDELT threshold tests ✅ 11/11 (6 new)

Upgrade Instructions

git pull origin dev

# Rebuild affected services
docker compose up -d --build sovereign-backend sovereign-gdelt-pulse sovereign-space-pulse

# Frontend (if running prod static build)
docker compose up -d --build sovereign-frontend

No docker compose down required. No migrations to run.

Release - v1.0.6 - Thermal Watch

Choose a tag to compare

@d3mocide d3mocide released this 16 Apr 04:35

Summary

v1.0.6 delivers the FIRMS thermal intelligence layer and dark-vessel anomaly engine to operators, resolves the two hold items that blocked the v1.0.6 candidate, and closes out a sweep of backend ingestion reliability fixes. The ISS ground-track now updates live in the animation loop and renders cleanly after container restarts. Fire hotspot data is now sourced globally by design, while the thermal layer starts off by default to reduce initial map noise.

Key Features

  • NRT NASA FIRMS Thermal Layer — VIIRS/MODIS thermal infrared hotspots on the tactical map with FRP-scaled radii and confidence-coded colors.
  • Dark Vessel Anomaly Detection — Backend engine cross-references FIRMS heat signatures against AIS vessel positions. Vessel-scale hotspots with no AIS broadcast within 5nm/2h are surfaced as anomaly candidates.
  • FIRMS Source Health Visibility — Operations surfaces now show compact per-source FIRMS ingest summaries so NOAA-20, NOAA-21, and SNPP drift can be diagnosed without container log inspection.
  • Live ISS Ground Track — WebSocket-delivered positions now normalise Unix integer timestamps to ISO-8601 on arrival, keeping the orbital trail current in the animation loop.
  • ISS Track Gap Detection — Consecutive positions separated by >10 minutes start a new path segment, eliminating the distorted line artifact after container restarts.

Bug Fixes

  • FIRMS thermal visibility now defaults to false, while dark-vessel anomalies remain enabled and FIRMS coverage stays global.
  • FIRMS poller health now distinguishes healthy, empty, and failed upstream source responses instead of silently reporting partial upstream degradation as healthy.
  • ISS live-track timestamps normalised at the hook boundary (useISSTracker) so all sources (WebSocket, REST, DB) produce trail points that pass the buildISSLayer filter.
  • ISS track gap rendering fixed in splitTrackAtAntimeridian.
  • SatNOGS pagination loop indentation corrected; PeeringDB IXP coordinates recovered from facility centroids; IODA Nominatim geocoder restored.

Technical Details

  • TimescaleDB migration V004 adds firms_hotspots hypertable and dark_vessel_candidates table.
  • space_pulse cadence policy: daily TLE refresh gated on UTC hour, FIRMS/space-weather cadence persisted in Redis across restarts.
  • FIRMS no longer supports a mission-vs-global ingest mode; the poller always uses the NASA world endpoint and FIRMS_BBOX_MODE is no longer part of the runtime configuration.
  • FIRMS source-cycle snapshots are now published to Redis under firms:source_status and surfaced through /api/config/poller-health.
  • No breaking API or schema changes, no new required environment variables.

Verification

  • Frontend: pnpm run lint ✅ · pnpm run typecheck ✅ · pnpm run test ✅ (18/18 files, 268/268 tests)
  • Backend API: uv tool run ruff check . && uv run python -m pytest tests/test_firms_router.py tests/test_system_router.py ✅ (7 targeted tests)
  • Targeted poller verification: space_pulse lint ✅; host space_pulse pytest remains blocked by the known Windows/Python 3.14 asyncpg==0.30.0 build issue.

Upgrade Instructions

git pull origin main
docker compose pull
docker compose up -d --build

TimescaleDB migration V004 runs automatically on backend startup.

SITREP Status: [GO]

Release - v1.0.5 - Glass Command

Choose a tag to compare

@d3mocide d3mocide released this 14 Apr 03:25

High-Level Summary

This release, codenamed "Glass Command", restores 100% visibility into the Sovereign Watch data fusion pipeline. Operators now have access to high-cadence real-time tracking of the International Space Station (ISS), expanded tactical intelligence from global RSS feeds, and a high-density "Sovereign Glass" System Health HUD that eliminates UI clutter while providing deeper diagnostics.

Key Features

  • Condensed "Sovereign Glass" Health HUD: A complete redesign of the system monitoring interface, now featuring a 2-column high-density grid and consolidated SatNOGS tracking.
  • ISS Real-time Tracking: Restored the 5-second polling loop for the International Space Station with full historical archival to TimescaleDB.
  • Tactical News Expansion: Integrated mission-critical intelligence feeds including UN News, The Aviationist, Defense News, and Reuters World.
  • Telemetry Restoration: Resolved persistent PENDING states for Ocean Buoys (NDBC) and National Weather Service (NWS) alerts by aligning heartbeat reporting with the centralized HUD registry.

Technical Details

  • Poller Heartbeats: All infrastructure pollers now use a unified Redis-backed heartbeat mechanism (infra:last_*).
  • Data Integrity: Resolved a hypertable constraint issue in the ISS ingestion loop to ensure stable long-term tracking.
  • Aggregator Resilience: Fixed heartbeat reporting gaps in the RSS aggregator, ensuring the service status is reflected even when serving from cache.

Upgrade Instructions

To apply these updates, pull the latest changes and rebuild the service containers:

# Rebuild and restart the stack
docker compose up -d --build

SITREP Status: [GO]
All Domain Agents Verified - Operational Stability Restored.

Release — v1.0.4 — Global Airspace Intelligence

Choose a tag to compare

@d3mocide d3mocide released this 12 Apr 19:05

Released: 2026-04-12


Summary

v1.0.4 replaces the deprecated FAA NOTAM integration with a full-stack OpenAIP airspace zones pipeline, giving operators global polygon-based airspace coverage for the first time — no institutional credentials required.

This release also eliminates a long-standing stale-polygon artifact when switching mission areas, adds operator-controlled zone type filtering with zero latency, and unifies the draw-order of all tactical map layers under a coherent visual hierarchy.


Key Features

🌐 OpenAIP Global Airspace Zones

  • Covers PROHIBITED, RESTRICTED, DANGER, WARNING, TRA, TSA, ADIZ, CTR, FIR, FIS, VFR zones worldwide.
  • Actual polygon geometries — not point markers — for accurate airspace boundary situational awareness.
  • 24-hour poll cadence matches the slow-changing nature of published airspace; Redis cache (25h TTL) with TimescaleDB archival.
  • Graceful degradation: missing OPENAIP_API_KEY is logged as a warning; the map continues to load normally.

🔄 Event-Driven Cache Synchronization

  • Backend emits a clearing Redis signal before wiping its cache and an updated signal after the new data lands.
  • Frontend immediately clears displayed polygons on clearing — no stale zones from the previous mission area leak into the new view.
  • Replaces the timing-based polling approach entirely; the map is now deterministically in sync with backend state.

🎛️ Zone Type Sub-Filter

  • 12-type toggle grid (PROHIB / RESTRI / DANGER / WARN / TRA / TSA / ADIZ / MIL / CTR / FIR / FIS / VFR) rendered in the Sovereign Glass tile aesthetic matching the AIR/SEA entity filter panels.
  • Client-side filtering — instant response, zero API calls.
  • Each toggle retains its zone-type color accent when active; dims to neutral when off.

🗺️ 7-Tier Z-Order Unification

  • All tactical map layers now follow a documented depthBias hierarchy:
    Shading → NWS Alerts → Airspace Zones → Cables/Infra → Buoys/Assets → Jamming/Clusters → Entities
  • Airspace zones no longer occlude outage fills, and entity chevrons always float above all signal layers.

🧪 Playwright E2E Test Suite

  • Chromium-based E2E tests auto-start the dev server via pnpm run test:e2e.
  • golden-path.spec.ts: 6 smoke tests covering login, dashboard navigation, and map load.
  • airspace-layer.spec.ts: 9 tests covering all three API endpoint contracts and the UI toggle lifecycle.

Technical Details

New API Endpoints

Endpoint Description
GET /api/airspace/zones Active zones from Redis fast-path
GET /api/airspace/history Historical zones from TimescaleDB (type/country filters, 1–720h)
GET /api/airspace/types Zone type summary and counts

Database Migration

  • V003__airspace_zones.sql — new airspace_zones TimescaleDB hypertable, 30-day retention, indexes on zone_id, type, country.
  • Applied automatically at backend startup via migrate.py. No manual intervention required.

Configuration (Optional)

Add to .env if you have an OpenAIP API key:

OPENAIP_API_KEY=your_key_here
OPENAIP_BBOX_EXPAND_DEG=2.0
OPENAIP_TYPES=0,1,2,3,4,5,6,7,8,9,10

The service runs without these variables but will skip airspace polling and log a warning.

Breaking Changes

None. All existing layers, endpoints, and state contracts are preserved.


Upgrade Instructions

# Pull latest
git pull origin main

# Rebuild and restart all services
make prod

# Or for development
make dev

The V003 migration applies automatically on first docker compose up. Verify with:

SELECT * FROM schema_migrations ORDER BY version;

Verification

Frontend lint:      pnpm run lint       → 0 errors, 0 warnings
Frontend typecheck: pnpm run typecheck  → no errors
Frontend tests:     pnpm run test       → 205/205 passed
Backend lint:       ruff check .        → clean
Backend tests:      pytest              → 133 passed