Captures the full output of autodev existing-code Phase A through Step 4 (Code Testability Revision) for the Azaion UI workspace: - Step 1 Document: _docs/02_document/ (FINAL_report, architecture, glossary, components/, modules/, diagrams/, system-flows, module-layout) plus _docs/00_problem/ + _docs/01_solution/ + _docs/legacy/ + _docs/how_to_test + README. - Step 2 Architecture Baseline: architecture_compliance_baseline.md. - Step 3 Test Spec: _docs/02_document/tests/ (environment, test-data, blackbox/performance/resilience/security/ resource-limit tests, traceability-matrix), enum_spec_snapshot, expected_results/results_report.md (98 rows), plus the run-tests.sh + run-performance-tests.sh runners. - Step 4 Code Testability Revision: 01-testability-refactoring/ run dir (list-of-changes C01-C07, deferred_to_refactor, analysis/research_findings + refactoring_roadmap) and the 7 child task specs AZ-448..AZ-454 under _docs/02_tasks/todo/ plus _dependencies_table.md. - _docs/_autodev_state.md pins the cursor at Step 4 / refactor Phase 4 entry so /autodev resumes cleanly. Epic AZ-447 (UI testability gates) tracks the 7 child tasks that will land in subsequent commits. Co-authored-by: Cursor <cursoragent@cursor.com>
10 KiB
Data Parameters — Azaion UI
Output of
/documentStep 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:
- Typed REST entities — see
_docs/02_document/data_model.mdfor the full ER map; key shapes summarised below. - SSE event payloads —
live-gps,annotation-status, planneddetect-stream. - Configuration / environment variables — runtime config injected at build time or via env.
- 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<T> |
{ 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
- Plan flight — UI fetches
aircraftsfromflights/; submits flight + waypoints; receives the persisted flight (today: delete-then-recreate waypoint cycle, finding #19; lossy POST shape, finding #20). - Capture media — out-of-band via the loader / annotations services;
the UI surfaces uploaded items via
MediaListpolling. - Annotate — operator edits →
POST /api/annotations/annotations;F14SSE pushes other-user status changes (admin-wide stream, client-side filtered). - AI Detect (sync image) —
POST /api/detect/${id}returns inline detections. Used for both image and video today (silent UX hazard for long videos —F7to ship in Phase B). - AI Detect (async video — target) —
POST /api/detect/video/${id}returns a job ID → SSE on/api/detect/stream/${jobId}streams progress. Long videos requireX-Refresh-Tokenheader per_docs/10_auth.md. - Curate dataset — UI queries
annotations/with status filters; bulk-validate transitions toAnnotationStatus.Validated; class-distribution chart loads from/api/annotations/dataset/class-distribution. - Settings — system / directory / camera saves go to
annotations/; aircraft default-toggle goes toflights/(cross-service mutation, accepted). - GPS-Denied Test Mode (target — F12) —
.tlog+ video upload togps-denied-desktop/; SITL drivesgps-denied-onboard/; results render back throughflights/GPS-Denied tab.
Full sequence diagrams: _docs/02_document/system-flows.md.