Files
ui/_docs/02_document/contracts/satellite-provider/tiles.md
T
Oleksandr Bezdieniezhnykh 20a39d3d8a [AZ-497] [AZ-498] [AZ-499] Cycle 2 New Task: epic, stories, contract draft
Closes autodev existing-code Step 9 for cycle 2.

- Epic AZ-497 (Self-Hosted Satellite Tiles - SPA Integration) added
  to _docs/02_tasks/_dependencies_table.md as the cycle-2 umbrella.
- AZ-498 (5 pts): self-hosted satellite tiles + drop map-type toggle.
  Cross-workspace prereq: satellite-provider must add cookie-auth on
  GET /tiles/{z}/{x}/{y} before merge (user files separately).
- AZ-499 (2 pts): mission-planner OWM env-var hardening + closes the
  AZ-482 source-scan gap with a new owm_key_in_source banned-deps kind.
- Contract _docs/02_document/contracts/satellite-provider/tiles.md
  v1.0.0 (draft): slippy-tile XYZ shape both sides commit to.
- _docs/_autodev_state.md: Step 9 closure note + advances pointer to
  Step 10 (Implement) for cycle 2.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 03:45:44 +03:00

6.6 KiB

Contract: satellite-provider tile serving

Component: satellite-provider Producer task: TBD — separate AZAION ticket on satellite-provider workspace (user-filed) Consumer tasks: AZ-498 — _docs/02_tasks/todo/AZ-498_satellite_tile_swap.md (suite/ui, cycle 2, epic AZ-497) Version: 1.0.0 Status: draft Last Updated: 2026-05-12

Purpose

Describe the slippy-tile HTTP interface that the suite UI consumes to render satellite imagery in FlightMap / MiniMap. Replaces the prior external-tile dependencies (OpenStreetMap, Esri ArcGIS World Imagery). The endpoint is served by SatelliteProvider.Api and backed by an on-disk + Google-Maps download cache.

Frozen post-migration: SPA authentication for this endpoint MUST be cookie-based (JWT delivered via HttpOnly; Secure; SameSite=Lax cookie on the same origin) because Leaflet's <TileLayer> issues plain <img> requests and cannot attach Authorization: Bearer … headers.

Shape

HTTP / RPC endpoints

Method Path Request body Response Status codes
GET /tiles/{z}/{x}/{y} image bytes 200, 401, 404, 503

Path parameters

Name Type Required Range / Constraint
z int yes 0 ≤ z ≤ 20 (slippy-tile zoom)
x int yes 0 ≤ x < 2^z (slippy-tile column)
y int yes 0 ≤ y < 2^z (slippy-tile row, TMS-y convention NO)

Coordinates follow the Google Maps / OSM XYZ tiling scheme (NOT the inverted TMS y-axis). Out-of-range coordinates SHOULD return 404.

Response headers (on 200)

Header Value
Content-Type image/jpeg (image bytes from the TileService)
Cache-Control public, max-age=N where N is set by TileService
ETag strong ETag tied to the cached tile's content hash

Authentication

  • Required: yes (the endpoint is NOT public).
  • Mechanism (post-migration): cookie-based JWT.
    • Cookie name: satellite_auth (TBD — defined by producer task).
    • Attributes: HttpOnly; Secure; SameSite=Lax in production; SameSite=Lax permitted over http://localhost for dev only.
  • Cross-origin behavior: same-origin only. The SPA reaches this endpoint via the suite ingress (nginx) on the SPA's origin; cross-origin direct calls from http://localhost:5173 → http://localhost:5100 will NOT carry the cookie and will receive 401 in dev unless the developer disables auth locally.

Status codes

Code Meaning
200 Cached or freshly downloaded tile; body = image bytes
304 (Optional) ETag match — body empty. UI MUST tolerate either 200 or 304.
401 Missing/invalid cookie — UI MUST treat as "user signed out"
404 Tile coordinates out of range OR upstream had no tile
503 Upstream (Google Maps) unavailable; UI MUST render placeholder

Invariants

  • The endpoint URL pattern is /tiles/{z}/{x}/{y} exactly — never /tiles/{z}/{y}/{x} (Esri-style) nor /api/satellite/tiles/{z}/{x}/{y}. This invariant survives refactors and is asserted by both producer's integration tests and consumer's blackbox tests.
  • Image format is JPEG (Content-Type image/jpeg). Switching to PNG/WEBP is a major-version change.
  • The endpoint MUST honor Cache-Control and ETag headers on every 200; clients rely on them to avoid re-fetching unchanged tiles during pan/zoom.
  • Authentication failure MUST return 401, not 200 with an HTML body — Leaflet would otherwise display a broken-image placeholder silently.

Non-Goals

  • Not covered: tile vector formats (.pbf / Mapbox Vector Tiles). This contract is raster-only.
  • Not covered: tile prewarming. Pre-warm uses the separate POST /api/satellite/request endpoint (different contract, not consumed by the UI's FlightMap).
  • Not covered: MGRS tile retrieval (returns 501 today; out of UI scope).

Versioning Rules

  • Breaking (major bump): change the path template, change the path-parameter semantics (e.g., TMS-y), change Content-Type, remove a status code from the set above, change the auth mechanism away from cookies.
  • Non-breaking (minor bump): add a new optional query parameter, broaden the zoom range, add a new status code in the 4xx/5xx space that consumers can tolerate.

Test Cases

Case Input Expected Notes
valid-tile GET /tiles/15/9876/5432 w/ cookie 200 + JPEG bytes + Cache-Control + ETag producer + consumer cover
missing-cookie GET /tiles/15/9876/5432 w/o cookie 401 consumer must NOT retry
out-of-range-coord GET /tiles/3/8/0 (x ≥ 2^z) 404 consumer renders placeholder
etag-match GET /tiles/15/9876/5432 + If-None-Match 304 OR 200 (server-policy dependent) consumer tolerates both
upstream-503 upstream Google Maps down 503 consumer renders placeholder
zoom-extreme GET /tiles/20/x/y valid coords 200 (or 404 if not cached and no on-demand) consumer caps zoom at 20

Change Log

Version Date Change Author
1.0.0 2026-05-12 Initial draft; freezes the post-migration shape (cookie auth, XYZ scheme). autodev (cycle 2 — suite/ui)