mirror of
https://github.com/azaion/ui.git
synced 2026-06-21 10:51:11 +00:00
[AZ-498] [AZ-499] Cycle 2 batch 11: satellite tiles + OWM hardening
AZ-498 — self-hosted satellite tiles + drop classic/satellite toggle: - Single TILE_URL via getTileUrl() (mirrors getOwmBaseUrl/getApiBase pattern from AZ-449/AZ-450); env-var VITE_SATELLITE_TILE_URL with dev default http://localhost:5100/tiles/{z}/{x}/{y}. - FlightMap + MiniMap render one TileLayer with crossOrigin="use-credentials" so Leaflet's <img> tile fetcher attaches the same-origin satellite-provider auth cookie. - ImportMetaEnv + .env.example collapse the prior OSM/Esri pair into one var. The flights.planner.satellite i18n key is removed in lockstep across en.json + ua.json (parity preserved). - E2E harness wired end-to-end: compose passes the new var to azaion-ui; tile-stub serves /tiles/{z}/{x}/{y} with Content-Type=image/jpeg + Cache-Control + ETag matching the contract; infrastructure.e2e.ts AC-2 asserts the new path; dead OSM defenses removed from EXTERNAL_HOSTS route guard. - Fast-profile MSW handlers rewritten for the cookie-auth path shape. - 8 colocated fast tests under src/features/flights/__tests__/. AZ-499 — mission-planner OWM env-var hardening + AZ-482 source-scan gap close: - WeatherService.ts reads VITE_OWM_API_KEY + VITE_OWM_BASE_URL; fail-soft null when key unset (mirrors AZ-448 main-SPA contract). Public signature getWeatherData(lat, lon) preserved. - mission-planner/.env.example + vite-env.d.ts declare both vars. - New owm_key_in_source banned-deps kind scans src/ AND mission-planner/ for the rotated literal; STC-SEC1C row added to scripts/run-tests.sh; check-banned-deps.mjs dispatch extended. - 7 fast tests under tests/mission_planner_weather.test.ts cover AC-1..AC-4 + trailing-slash + happy path + network-error fail-soft. Spec drift (recorded in batch_11_report.md, user-approved Choose B on 2026-05-12): - AZ-498 AC-8 dropped (named tile_split_zoom* files belong to AZ-474 image-annotation surface, not map tiles). - 4 missing files added in-scope (msw tiles handler, tile-stub server, compose env, dead VITE_TILE_BASE_URL replaced). - AZ-499 STC-S6 ID conflict resolved by using STC-SEC1C. Pending USER ACTION (BLOCKING for AZ-499 close): - Revoke OpenWeatherMap key 335799082893fad97fa36118b131f919 at home.openweathermap.org/api_keys; capture evidence on AZ-499. Cross-workspace deploy gate (handled at autodev Step 16, not a Step-10 blocker for AZ-498): - satellite-provider cookie-auth on GET /tiles/{z}/{x}/{y} (separate AZAION ticket on the satellite-provider workspace). Reports: _docs/03_implementation/batch_11_report.md and _docs/03_implementation/reviews/batch_11_review.md (verdict PASS_WITH_WARNINGS — 1 Low, pre-existing trim-trailing-slash duplication across vite roots). Static gates: STC-ARCH-01, STC-ARCH-02, STC-T1, STC-FP22, STC-FP23, STC-SEC1C all PASS post-refactor. +15 fast tests; +1 STC-SEC1C row. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -17,7 +17,7 @@ Currently handles only the planning surface; the gps-denied orthophoto upload /
|
||||
|
||||
| Module | Layer | Responsibility |
|
||||
|---|---|---|
|
||||
| `types.ts` | leaf | All flight-feature-only types (`FlightPoint`, `CalculatedPointInfo`, `MapRectangle`, `WindParams`, `AircraftParams`, `MovingPointInfo`, `ActionMode`), plus tile URLs (`TILE_URLS`), `PURPOSES` (`tank` / `artillery`), and `COORDINATE_PRECISION = 8`. |
|
||||
| `types.ts` | leaf | All flight-feature-only types (`FlightPoint`, `CalculatedPointInfo`, `MapRectangle`, `WindParams`, `AircraftParams`, `MovingPointInfo`, `ActionMode`), plus the single self-hosted satellite tile URL (`TILE_URL`, AZ-498 — env-var `VITE_SATELLITE_TILE_URL`, dev default `http://localhost:5100/tiles/{z}/{x}/{y}`), `PURPOSES` (`tank` / `artillery`), and `COORDINATE_PRECISION = 8`. |
|
||||
| `mapIcons.ts` | leaf | Three coloured Leaflet `Icon` instances + the default Leaflet pin (loaded from a CDN — see Findings). |
|
||||
| `flightPlanUtils.ts` | leaf | Pure-ish helpers: `newGuid`, haversine `calculateDistance` (with plane climb/cruise/descend profile), OpenWeatherMap fetch, semi-empirical `calculateBatteryPercentUsed`, `calculateAllPoints` (sequential reduce), `parseCoordinates`, `getMockAircraftParams`. |
|
||||
| `WaypointList.tsx` | sub-component | `@hello-pangea/dnd` reorderable list, hover-only Edit/Remove buttons, shows distance / time / battery / altitude per point. |
|
||||
@@ -30,7 +30,7 @@ Currently handles only the planning surface; the gps-denied orthophoto upload /
|
||||
| `FlightListSidebar.tsx` | sub-component | Left rail: flight list, "+ Create", inline-create row, telemetry date stub. |
|
||||
| `JsonEditorDialog.tsx` | sub-component | Modal `<textarea>` over the plan JSON with live `JSON.parse` validation. |
|
||||
| `FlightParamsPanel.tsx` | composite | Hosts `WaypointList` + `AltitudeChart` + `WindEffect` + all per-flight inputs (aircraft, initial altitude, FoV, comm address, action-mode buttons, totals strip, Save / Upload / EditAsJSON / Export). |
|
||||
| `FlightMap.tsx` | composite | Wraps `MapContainer`; mounts `MapPoint` × N, `DrawControl`, `MiniMap` (when a point is moving), polyline + arrow decorator, satellite/classic toggle. |
|
||||
| `FlightMap.tsx` | composite | Wraps `MapContainer`; mounts `MapPoint` × N, `DrawControl`, `MiniMap` (when a point is moving), polyline + arrow decorator. Single satellite-only `<TileLayer>` with `crossOrigin="use-credentials"` (AZ-498); the prior classic/satellite toggle was retired. |
|
||||
| `FlightsPage.tsx` | page | Orchestrator: owns all state, talks to `api/client`, opens the SSE stream, mediates between sidebar / params panel / map / dialogs. |
|
||||
|
||||
## Key contracts (read by other docs)
|
||||
@@ -39,7 +39,7 @@ Currently handles only the planning surface; the gps-denied orthophoto upload /
|
||||
- **`CalculatedPointInfo`**: `{ bat: number /* % */; time: number /* hours */ }`. Index `i` = state at point `i` after the segment from `i-1`. `lastInfo.bat` drives the Good / Caution / Low colour status (`>12 / >5 / ≤5`).
|
||||
- **`PURPOSES = [{ value: 'tank', label: 'options.tank' }, { value: 'artillery', label: 'options.artillery' }]`** — i18n keys are `flights.planner.${label}`.
|
||||
- **JSON plan shape** (`handleEditJson` / `handleExport` / `handleJsonSave`): `{ operational_height: { currentAltitude }, geofences: { polygons: [{ northWest, southEast, fence_type: 'EXCLUSION'|'INCLUSION' }] }, action_points: [{ point: { lat, lon }, height, action: 'search', action_specific: { targets: string[] } }] }`. Used for both export-to-file and the JSON editor.
|
||||
- **Tile URLs**: classic OSM and an Esri ArcGIS `World_Imagery` (in `types.ts`). Both are direct upstream — neither goes through the suite `satellite-provider/` proxy. See Findings.
|
||||
- **Tile URL** (post AZ-498): single `TILE_URL` constant in `types.ts` resolved from `VITE_SATELLITE_TILE_URL` (dev default `http://localhost:5100/tiles/{z}/{x}/{y}`). Production builds MUST set the env var to a same-origin path so the satellite-provider auth cookie rides. The classic/satellite toggle, the prior OSM (`VITE_OSM_TILE_URL`) and Esri (`VITE_ESRI_TILE_URL`) env vars, and the `MiniMap.Props.mapType` prop are all gone. Contract: `_docs/02_document/contracts/satellite-provider/tiles.md` v1.0.0.
|
||||
|
||||
## External integrations
|
||||
|
||||
@@ -52,8 +52,7 @@ Currently handles only the planning surface; the gps-denied orthophoto upload /
|
||||
| `endpoints.flights.flightWaypoints(id)` + `endpoints.flights.flightWaypoint(flightId, wp)` → `POST/DELETE /api/flights/{id}/waypoints[/{wp}]` | `FlightsPage.handleSave` | egress | Delete-all-then-recreate, sequentially. |
|
||||
| `endpoints.flights.flightLiveGps(id)` → `GET /api/flights/{id}/live-gps` (SSE) | `FlightsPage` | egress | Open while in GPS mode + flight selected. |
|
||||
| `https://api.openweathermap.org/...` | `flightPlanUtils.getWeatherData` | egress | Direct browser→3rd-party. **Hardcoded API key.** See Findings. |
|
||||
| `tile.openstreetmap.org` (`TILE_URLS.classic`) | `FlightMap`, `MiniMap` | egress | Direct, no proxy. |
|
||||
| `server.arcgisonline.com/.../World_Imagery` (`TILE_URLS.satellite`) | `FlightMap`, `MiniMap` | egress | Direct, no proxy. |
|
||||
| `satellite-provider /tiles/{z}/{x}/{y}` (via `VITE_SATELLITE_TILE_URL`) | `FlightMap`, `MiniMap` | egress | Same-origin in production (cookie auth); `tile-stub` in e2e; `localhost:5100` dev default. AZ-498 retired the OSM + Esri direct calls. |
|
||||
| `unpkg.com/leaflet@1.7.1/dist/images/marker-icon-2x.png` | `mapIcons.defaultIcon` | egress | CDN, version pinned to 1.7.1 while package is 1.9.4 (drift). |
|
||||
| `navigator.geolocation.getCurrentPosition` | `FlightsPage` mount | browser API | Fallback to hardcoded `47.242, 35.024` (Zaporizhzhia). |
|
||||
|
||||
@@ -67,7 +66,7 @@ These are the real findings; the per-module rationale is in git history of the d
|
||||
4. **`AircraftParams.batteryCapacity` unit is ambiguous** (Wh vs W·s). `calculateBatteryPercentUsed` divides W·s by it × 100 — only correct if W·s. Verify against `mission-planner/src/services/calculateBatteryUsage.ts`. Step 4.
|
||||
5. **`flightPlanUtils.getWeatherData` swallows errors silently** (`catch { return null }`); callers can't distinguish "no wind" from "key revoked". Step 4.
|
||||
6. **`mapIcons.defaultIcon` CDN URL is leaflet@1.7.1** while `package.json` is 1.9.4. Step 4 — switch to bundled assets or match version.
|
||||
7. **`FlightMap` and `MiniMap` bypass the suite `satellite-provider/` proxy** (Esri tiles direct from `server.arcgisonline.com`). Possible licence + rate-limit concern. Step 4 + `architecture.md`.
|
||||
7. ~~**`FlightMap` and `MiniMap` bypass the suite `satellite-provider/` proxy**~~ — **resolved by AZ-498 (cycle 2)**. Both maps now consume `satellite-provider /tiles/{z}/{x}/{y}` via `VITE_SATELLITE_TILE_URL` with `crossOrigin="use-credentials"` cookie auth; the OSM + Esri direct calls and the classic/satellite toggle are gone. Cross-workspace prerequisite: `satellite-provider` cookie-auth migration on the same endpoint (user-filed separately).
|
||||
8. **`MiniMap` sets `attributionControl={false}`** — drops OSM / Esri attribution. Possible licence-compliance gap. Step 4.
|
||||
9. **`MiniMap` is fixed 240×180 + zoom 18 hardcoded** — overflows below the 640px mobile breakpoint. Step 4 vs `_docs/ui_design/README.md` responsive specs.
|
||||
10. **`AltitudeDialog` lacks Esc-to-close, backdrop-click-to-cancel, `role="dialog"`, `aria-modal`** — inconsistent with `ConfirmDialog`. Same for `JsonEditorDialog`. Pick one modal convention in Step 4.
|
||||
|
||||
Reference in New Issue
Block a user