# Data Parameters — Azaion UI > Output of `/document` Step 6d. The Azaion UI is a **thin client over a typed > REST + SSE contract**; it carries no database. "Input data" therefore means > the data shapes the SPA consumes (REST response payloads, SSE event > payloads, env config). All claims trace to `_docs/02_document/data_model.md`, > `architecture.md` § 4–5, and per-component descriptions. **Status**: synthesised-from-verified-docs (Step 6d — `/document`) **Date**: 2026-05-10 --- ## Categories of input data The SPA consumes four categories: 1. **Typed REST entities** — see `_docs/02_document/data_model.md` for the full ER map; key shapes summarised below. 2. **SSE event payloads** — `live-gps`, `annotation-status`, planned `detect-stream`. 3. **Configuration / environment variables** — runtime config injected at build time or via env. 4. **Static assets** — translation bundles, icons, design tokens (compiled into the bundle). --- ## 1. Typed REST entities (defined in `src/types/index.ts`) > Every entity below mirrors the suite's REST contract. Values listed here > match the **suite spec**, which is the source of truth per principle P9. > Where the UI's current TypeScript enum drifts from the spec, the row notes > the drift and the Step 4 fix. ### Auth | Entity | Fields | Source | |--------|--------|--------| | `AuthUser` | `id`, `email`, `name`, `role`, `permissions: string[]`, `aircraftId?` | `02_auth`; `admin/` service | | `LoginRequest` | `{ email, password }` | `POST /api/admin/auth/login` body | | `LoginResponse` | `{ bearer, user: AuthUser }` (refresh cookie set server-side) | `POST /api/admin/auth/login` 200 | ### Flights | Entity | Fields | Source | |--------|--------|--------| | `Flight` | `id`, `name`, `aircraftId`, `startDate?`, `endDate?`, `description?` | `flights/` service | | `Waypoint` | **Spec**: `{ Geopoint: { Lat, Lon, MGRS }, Source, Objective, OrderNum, Height }`. **UI today**: `{ name, latitude, longitude, order }` — drift, finding #20 / Step 4 fix | `05_flights`; `flights/` service | | `Aircraft` | `id`, `name`, `model`, `isDefault`, `serialNumber?` | `flights/` (read+write); `08_admin` mutation | | `LiveGpsEvent` (SSE) | `{ flightId, lat, lon, alt, heading, speed, ts }` | `createSSE('/api/flights/${id}/live-gps')`; F13 | ### Annotations + Media | Entity | Fields | Source | |--------|--------|--------| | `Media` | `id`, `flightId`, `mediaType: MediaType`, `mediaStatus: MediaStatus`, `filename`, `waypointId?`, `videoTime?`, `thumbnail?` | `annotations/` service | | `MediaType` enum | **Spec**: `None=0`, `Image=1`, `Video=2`. **UI**: same. | `00_foundation`; P9 | | `MediaStatus` enum | **Spec**: must include `None`, `Confirmed`, `Error` plus the existing `New`, `AiProcessing`, `AiProcessed`, `ManualCreated`. **UI today**: only `New=0` / `AiProcessing=1` / `AiProcessed=2` / `ManualCreated=3` — drift, Step 4 fix | `00_foundation`; finding | | `AnnotationListItem` | `id`, `mediaId`, `videoTime`, `status: AnnotationStatus`, `source: AnnotationSource`, `detections: Detection[]`, `isSeed?: boolean` | `annotations/` | | `AnnotationStatus` enum | **Spec**: `None=0`, `Created=10`, `Edited=20`, `Validated=30`, `Deleted=40`. **UI today**: `Created=0`, `Edited=1`, `Validated=2` — drift, Step 4 fix per P9 | `00_foundation`; `04_verification_log.md` | | `AnnotationSource` enum | `AI=0`, `Manual=1` (matches spec) | `00_foundation` | | `Detection` | `{ classNum: number, x, y, w, h: number, affiliation: Affiliation, combatReadiness: CombatReadiness, confidence?: number }` (normalised pixel coords) | `06_annotations` | | `Affiliation` enum | **Spec**: must include `None` plus `Unknown`, `Friendly`, `Hostile`. **UI today**: `Unknown=0`, `Friendly=1`, `Hostile=2` — drift, Step 4 fix | finding | | `CombatReadiness` enum | **Spec**: must include `Unknown` plus `NotReady`, `Ready`. **UI today**: `NotReady=0`, `Ready=1` — drift, Step 4 fix | finding | | `DetectionClass` | `{ id, name, color, photoMode, maxSizeM }` | `08_admin` (write) + `annotations/` (read) | | Annotation save body | **Required** (per finding #32): `Source`, `WaypointId`, `videoTime`, plus `mediaId`, `detections`, `status`. **UI today**: missing `Source` and `WaypointId`; uses `time` instead of `videoTime` — Step 4 fix | `06_annotations/AnnotationsPage.tsx` | | `AnnotationStatusEvent` (SSE) | `{ annotationId, mediaId, oldStatus, newStatus, ts }` | `createSSE('/api/annotations/annotations/events')`; F14 | ### Dataset | Entity | Fields | Source | |--------|--------|--------| | `DatasetItem` | `id`, `mediaId`, `classNum`, `status: AnnotationStatus`, `thumbnail`, `isSeed?: boolean`, `isSplit?: boolean` (parent-suite-doc fix applied for `isSplit`) | `07_dataset`; `annotations/` | | `ClassDistributionItem` | `{ classNum, label, color, count }` | `annotations/` | | Bulk-validate body | `{ ids: number[], targetStatus: AnnotationStatus.Validated }` | `POST /api/annotations/dataset/bulk-status` | ### Settings + Admin | Entity | Fields | Source | |--------|--------|--------| | `SystemSettings` | as defined per `09_settings/SettingsPage.tsx` (settings keys per the suite spec) | `annotations/` (`/api/annotations/settings/system`) | | `DirectorySettings` | per `SettingsPage` directory tab | `annotations/` (`/api/annotations/settings/directories`) | | `CameraSettings` | per `SettingsPage` camera tab | `annotations/` | | `UserSettings` | `selectedFlightId?: number`, `panelWidths?: { ... }`, plus other per-user UI state | `annotations/` (`/api/annotations/settings/user`) | | `User` | `id`, `email`, `role`, `isActive`, `createdAt?` | `admin/` | ### Pagination | Entity | Shape | Source | |--------|-------|--------| | `PaginatedResponse` | `{ items: T[], totalCount: number, page: number, pageSize: number }` | shared envelope used by every list endpoint | --- ## 2. SSE event payloads | Stream | URL | Payload shape | Where consumed | |--------|-----|---------------|----------------| | Live-GPS per flight (F13) | `GET /api/flights/${flightId}/live-gps?token=${bearer}` | `LiveGpsEvent` (see above) | `src/features/flights/FlightsPage.tsx:67` | | Annotation-status events (F14) | `GET /api/annotations/annotations/events?token=${bearer}` | `AnnotationStatusEvent` | `src/features/annotations/AnnotationsSidebar.tsx:25` | | Async detect progress (F7) | `GET /api/detect/stream/${jobId}?token=${bearer}` — **target-only, NOT wired today** | `{ jobId, progress: 0..1, detections?: Detection[], status, ts }` (anticipated) | not consumed today; planned per `04_verification_log.md` F7 | Bearer goes in the **query string** (`?token=...`) per `ADR-008` — `EventSource` cannot send headers. Refresh-rotation breaks live SSE; reconnect is missing today (Step 8 hardening per `architecture.md` § Architecture Vision). --- ## 3. Configuration / environment variables | Variable | Where read | Type | Default | Source | |----------|-----------|------|---------|--------| | `VITE_OPENWEATHERMAP_API_KEY` | (target — Step 4 fix) `mission-planner/src/utils/flightPlanUtils.ts` | string (secret) | currently hardcoded `'335799082893fad97fa36118b131f919'` (must rotate) | P10 violation, Step 4 fix | | `VITE_SATELLITE_TILE_URL` | mission-planner Leaflet `TileLayer` | URL | none (unset breaks satellite imagery) | mission-planner only today | | `AZAION_REVISION` | stamped into the production image at build time | string (commit SHA) | `$CI_COMMIT_SHA` from CI | `Dockerfile`; `.woodpecker/build-arm.yml` | | `REGISTRY_HOST` | CI registry push | string | per pipeline secret | `.woodpecker/build-arm.yml` | | `i18next.lng` | `src/i18n/i18n.ts` | language code | hardcoded `'en'` (Step 4 fix — should resolve from detector) | `i18n.ts`; AC-13 | | nginx upstream hosts | `nginx.conf` | hostnames per service | docker-compose service names | `nginx.conf` | The SPA bundle MUST NOT carry secrets at build time — except OpenWeatherMap once it is moved to `.env` (per P10 the proper long-term answer is to proxy the OWM call through `flights/` so no key reaches the browser; the `.env` move is the interim Step 4 testability fix). --- ## 4. Static assets | Asset | Location | Notes | |-------|----------|-------| | Translation bundles | `src/i18n/en.json`, `src/i18n/ua.json` | English + Ukrainian; key parity is mandatory (AC-12) | | Design tokens | `src/index.css` (`az-bg`, `az-text`, `az-orange`, `az-success`, `az-danger`, `az-primary`, ...) | Tailwind 4; `ADR-005` | | Map icons | `src/features/flights/mapIcons.ts` | defaultIcon CDN URL pinned to `leaflet@1.7.1` (drift — finding) | | Aircraft / waypoint icons | bundled SVG / PNG under `src/features/flights/icons/*` (mission-planner port-source still has the larger set) | `05_flights` | | Detection-class colors | `src/features/annotations/classColors.ts` (logically owned by `11_class-colors`) | file-move pending (P11 / module-layout Verification Needed) | --- ## 5. Data flow summary 1. **Plan flight** — UI fetches `aircrafts` from `flights/`; submits flight + waypoints; receives the persisted flight (today: delete-then-recreate waypoint cycle, finding #19; lossy POST shape, finding #20). 2. **Capture media** — out-of-band via the loader / annotations services; the UI surfaces uploaded items via `MediaList` polling. 3. **Annotate** — operator edits → `POST /api/annotations/annotations`; `F14` SSE pushes other-user status changes (admin-wide stream, client-side filtered). 4. **AI Detect (sync image)** — `POST /api/detect/${id}` returns inline detections. **Used for both image and video today** (silent UX hazard for long videos — `F7` to ship in Phase B). 5. **AI Detect (async video — target)** — `POST /api/detect/video/${id}` returns a job ID → SSE on `/api/detect/stream/${jobId}` streams progress. Long videos require `X-Refresh-Token` header per `_docs/10_auth.md`. 6. **Curate dataset** — UI queries `annotations/` with status filters; bulk-validate transitions to `AnnotationStatus.Validated`; class-distribution chart loads from `/api/annotations/dataset/class-distribution`. 7. **Settings** — system / directory / camera saves go to `annotations/`; aircraft default-toggle goes to `flights/` (cross-service mutation, accepted). 8. **GPS-Denied Test Mode (target — F12)** — `.tlog` + video upload to `gps-denied-desktop/`; SITL drives `gps-denied-onboard/`; results render back through `flights/` GPS-Denied tab. Full sequence diagrams: `_docs/02_document/system-flows.md`.