Files
Oleksandr Bezdieniezhnykh 510df68bcf [AZ-447] autodev Steps 1-4 baseline: docs, tests, refactor specs
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>
2026-05-11 00:38:49 +03:00

7.1 KiB

Problem Statement — Azaion UI

Output of /document Step 6a. Retrospective problem definition synthesised from _docs/02_document/architecture.md (System Context, Components), component descriptions, system flows, and the Step 4.5 Architecture Vision. No README exists in the repo today (the workspace's tracked README is the parent suite's; the UI repo has only the autodev-generated README.md stub). All claims here trace to verified _docs/02_document/ artifacts.

Status: synthesised-from-verified-docs (Step 6a — /document) Date: 2026-05-10


What is this system?

Azaion UI is the operator-facing browser of the Azaion UAV operations suite — a single-page React 19 application served by nginx as a static bundle inside an ARM64 container. It is the React rewrite of the front-end half of the legacy WPF stack (Azaion.Annotator + Azaion.Dataset + MapMatcher); the heavyweight machinery (LibVLC playback, Cython sidecars, SQLite outbox, per-app DI host, binary-split key-fragment loader handoff) moved server-side into the parent suite (suite/) as separate services.

The UI's narrowed responsibility is to render the suite's REST + SSE contract beautifully and accessibly — it carries no domain logic that belongs on the server, no in-browser persistence beyond a single bearer in memory and a Secure HttpOnly refresh cookie, and no Node.js runtime in the production image.

What problem does it solve?

Operators of UAV / aerial-imagery missions (military and defense use cases) need a single browser surface to:

  1. Plan flights — define waypoints, altitudes, aircraft, GPS-Denied parameters; consult wind data; visualise routes on a map.
  2. Capture and review media — browse uploaded images and videos scoped to a flight; play video frame-accurately; tag bounding boxes manually or via AI inference.
  3. Run AI object detection — synchronously on images today; asynchronously on video (target — not wired today, see 04_verification_log.md F7).
  4. Curate datasets — filter by class / status, validate annotations in bulk, view class-distribution analytics.
  5. Administer the system — manage detection classes, users, aircraft, AI / GPS settings.
  6. Operate GPS-Denied positioning — including a planned Test Mode that drives SITL simulation from a pre-recorded .tlog + video pair (_docs/how_to_test.md).

This UI replaces the WPF desktop applications; it is the single browser client for all of the above use cases. Every action goes through the suite's typed REST contract or SSE stream — the browser is treated as untrusted, so the server is authoritative for every state transition.

Who are the users?

  • Operator (primary persona) — flies missions, reviews captured media, runs AI detect, curates datasets. The UI's default authenticated route (/flights) targets this persona. Bilingual UI is mandatory (Ukrainian
    • English).
  • Admin (privileged operator) — adds detection classes, manages users and aircraft, configures AI / GPS settings. Lives at /admin. Today this route lacks a client-side role-gate (server-side RBAC is authoritative; the missing UI gate is a finding).
  • System integrator — uses the GPS-Denied Test Mode and the Settings pages to validate end-to-end pipelines.

The UI does NOT have an end-customer / public-facing surface. It is internal to authenticated operators.

How does it work at a high level?

flowchart LR
  Operator[Operator browser] -->|HTTPS| Nginx[nginx<br/>static SPA + reverse-proxy]
  Nginx -->|/api/admin/*| Admin[admin/]
  Nginx -->|/api/flights/*| Flights[flights/]
  Nginx -->|/api/annotations/*| Ann[annotations/]
  Nginx -->|/api/detect/*| Detect[detect/]
  Nginx -->|/api/gps-denied-*/*| GPS[gps-denied-*/]
  Nginx -->|/api/resource/*| Resource[resource/]
  Nginx -->|/api/autopilot/*| Autopilot[autopilot/]
  Operator -->|HTTPS direct| OWM[OpenWeatherMap]
  Operator -->|HTTPS direct| OSM[OSM tile servers]
  1. Operator hits the nginx host. nginx serves dist/index.html + chunks.
  2. The SPA boots; AuthContext attempts a bootstrap refresh (currently broken — Step 4 fix candidate); on 401 the ProtectedRoute redirects to /login.
  3. Login (POST /api/admin/auth/login) returns a bearer in the response body and sets a Secure HttpOnly refresh cookie.
  4. Subsequent authenticated requests carry the bearer in the Authorization header. On 401, the 01_api-transport layer issues POST /api/admin/auth/refresh with credentials:'include' and retries.
  5. Page-level fetches go to the matching suite service; nginx strips the /api/<service>/ prefix and reverse-proxies. Long-lived streams (live-GPS per flight, annotation-status events) come over SSE.
  6. State is two React Contexts (AuthContext, FlightContext) plus page-local useState. No Redux, no Zustand, no TanStack Query (ADR-004, P4).

The dominant runtime pattern is thin client over a typed REST contract — no business logic in the browser; the server is the authority for every mutation.

Cross-reference with README

The repo's tracked README.md is a placeholder (untracked at the time of this analysis — see git status). The parent suite's docs (suite/_docs/*) are the canonical product reference; the UI's own derived docs in _docs/02_document/ complement those.

If a user-facing README is created in a future cycle, it should mirror the "What this system is" paragraph above and link to _docs/02_document/architecture.md for the full technical view.

What this system explicitly does NOT do

  • No in-browser persistence beyond bearer + i18n cache — every reload re-fetches.
  • No SSR / no React Server ComponentsDockerfile + nginx.conf ship a static bundle (ADR-001, P2).
  • No WebSocket — REST + SSE only (ADR-002, P1).
  • No localStorage / sessionStorage for tokens — bearer is in memory; refresh is in HttpOnly cookie (ADR-001 consequence, P3).
  • No SEO — operator-only application.
  • No mobile-first design — Header has a bottom-nav variant for ≥ 768 px; mobile is a P2 use-case (see _docs/02_document/architecture.md § 6 NFRs).
  • No port of three legacy WPF features: WPF-era encrypted-creds command-line handoff (P8 — security infra moved server-side), Sound Detections (Step 4.5 decision — dropped), Drone Maintenance / "Аналіз стану БПЛА" (Step 4.5 decision — dropped).

Open product questions (carried forward)

These are not blocking Step 6 retrospective extraction; they are recorded in _docs/02_document/architecture.md § Architecture Vision "Open questions / drift signals". Phase B feature cycles will resolve them per task.

  1. Async video detect (F7) wiring — when in Phase B does the SSE consumer ship?
  2. IsSeed annotation visual — does the modern API still expose isSeed?
  3. Camera-config side panel (GSD) — per-user, per-flight, or per-detect-job?
  4. Status-bar clock + help-text-blink — port WPF UX or replace with toasts?
  5. mission-planner/ end-state — delete after parity port (preferred per Step 4.5 decision) or keep as continuously-vendored reference?