Files
ui/_docs/01_solution/solution.md
T
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

29 KiB
Raw Blame History

Azaion UI — Retrospective Solution

Output of /document Step 5. Synthesis of the implemented architecture and per-component choices, derived from the verified technical docs: _docs/02_document/architecture.md (Step 3a), system-flows.md (Step 3b), data_model.md (Step 3c), deployment/*.md (Step 3d), components/*/description.md (Step 2), 04_verification_log.md (Step 4), glossary.md and architecture.md § Architecture Vision (Step 4.5).

This is retrospective — it describes the solution as it is, with observed limitations called out per component. Future work (testability fixes, async-detect wiring, mission-planner convergence) is referenced by source and not re-stated as a plan here.

Status: synthesised-from-verified-docs (Step 5 — /document) Date: 2026-05-10 Project: Azaion UI (operator-facing browser SPA)


Product Solution Description

Azaion UI is a single-page React 19 application, statically built and served by nginx inside an ARM64 container, that operates the browser-facing half of the Azaion UAV operations suite. It lets an operator plan flights, browse and annotate captured media, run AI object detection (synchronous on images; asynchronous video detect is target-only — not wired today, see 04_verification_log.md F7), curate datasets, manage detection classes / users / aircraft, and operate the GPS-Denied positioning workflow including a planned Test Mode driven by .tlog + video pairs through SITL.

The solution communicates with the parent suite's microservices over REST and Server-Sent Events only — no WebSocket, no GraphQL, no in-browser persistence beyond a single bearer token in memory and a Secure HttpOnly refresh cookie. State management is two React Contexts (AuthContext and FlightContext); everything else is page-local.

A second React 18 + MUI 5 tree (mission-planner/) lives at the repo root as the port-source for 05_flights — it is NOT deployed, NOT compiled by the production Vite build, and is on a multi-cycle path to deletion as features migrate into src/features/flights/ (Phase B feature cycles per the convergence plan in architecture.md § Architecture Vision).

Component interaction diagram

flowchart TB
  subgraph Browser SPA
    AppShell[10_app-shell]
    AppShell --> Auth[02_auth]
    AppShell --> Login[04_login]
    Auth --> Shared[03_shared-ui<br/>Header, FlightContext,<br/>ConfirmDialog, HelpModal]
    Shared --> Flights[05_flights]
    Shared --> Annotations[06_annotations]
    Shared --> Dataset[07_dataset]
    Shared --> Admin[08_admin]
    Shared --> Settings[09_settings]
    Foundation[00_foundation<br/>types, hooks, i18n] -.shared.-> Auth
    Foundation -.shared.-> Shared
    Foundation -.shared.-> Flights
    Foundation -.shared.-> Annotations
    Foundation -.shared.-> Dataset
    Foundation -.shared.-> Admin
    Foundation -.shared.-> Settings
    ClassColors[11_class-colors] -.shared.-> Shared
    ClassColors -.shared.-> Annotations
    ClassColors -.shared.-> Dataset
    Transport[01_api-transport<br/>fetch + EventSource]
    Auth --> Transport
    Flights --> Transport
    Annotations --> Transport
    Dataset --> Transport
    Admin --> Transport
    Settings --> Transport
  end

  subgraph nginx reverse-proxy
    Transport --> Nginx[nginx<br/>strip /api/svc/]
  end

  subgraph Suite services
    Nginx --> AdminSvc[admin/]
    Nginx --> FlightsSvc[flights/]
    Nginx --> AnnotSvc[annotations/]
    Nginx --> DetectSvc[detect/]
    Nginx --> GpsDenied[gps-denied-*/]
    Nginx --> Resource[resource/]
    Nginx --> Autopilot[autopilot/]
    Nginx --> Loader[loader/]
  end

  Flights --> OWM[OpenWeatherMap<br/>direct HTTPS<br/>hardcoded key — finding]
  Flights --> OSM[OSM tile servers<br/>direct HTTPS]

Detailed per-flow sequences (F1F14): _docs/02_document/system-flows.md.


Architecture

The solution is organised as 11 components under a strict layering (_docs/02_document/module-layout.md):

  • L0 (Foundation): 00_foundation, 11_class-colors
  • L1 (Transport): 01_api-transport
  • L2 (Auth + Shared UI): 02_auth, 03_shared-ui
  • L3 (Feature pages): 04_login, 05_flights, 06_annotations, 07_dataset, 08_admin, 09_settings
  • L4 (App shell): 10_app-shell

Component dependency graph: _docs/02_document/diagrams/components.md.

Cross-cutting principles (binding constraints — architecture.md § Architecture Vision)

P1 REST + SSE only · P2 Static bundle + nginx · P3 Bearer in memory + refresh in HttpOnly cookie · P4 Two-context state (Auth + Flight) · P5 ARM-first edge deployment · P6 Bilingual (en + ua) · P7 Lift cross-cutting at 2+ touches · P8 WPF parity is a goal not a constraint · P9 Spec is source of truth for numeric enums · P10 No hardcoded credentials in source · P11 Persist what you type · P12 Admin can edit existing detection classes.


Component: 00_foundation

Solution Tools Advantages Limitations Requirements Security Cost Fit
Shared types + hooks + i18n bundles, no domain logic typescript@5.7 strict, i18next + react-i18next, custom hooks (useDebounce, useResizablePanel) Single source of truth for the suite's typed REST contract; zero runtime cost (types erased); all bilingual strings live here useResizablePanel reads UserSettings.panelWidths but never writes back — violates principle P11 (04_verification_log.md finding #11). i18next lng:'en' is hardcoded — no detector / no persistence. Inline numeric-enum comments are required by P9 (already added 2026-05-10) TypeScript strict mode; bilingual coverage; numeric-enum drift between src/types/index.ts and the suite spec must be resolved None — shared types only Negligible (transitive only) Selected — current solution. Layer-0 placement keeps every other component dependency-free w.r.t. types/hooks.

Component: 01_api-transport

Solution Tools Advantages Limitations Requirements Security Cost Fit
Native fetch wrapper + native EventSource wrapper src/api/client.ts (fetch + 401-retry refresh), src/api/sse.ts (createSSE helper) Zero added dependencies (no axios / TanStack / SWR); 401-retry is centralised — every authenticated request gets refresh-token rotation for free Bearer for SSE goes in the query string (?token=...); EventSource cannot send headers (ADR-008). EventSource holds the bearer captured at create time — refresh-rotation breaks long-running subscriptions; reconnect logic is missing today (Step 8 hardening) All authenticated fetch requests must include credentials:'include' for the HttpOnly refresh cookie to flow; SSE endpoints must accept the bearer in the URL 401-retry path is secure (POST + cookie); bootstrap GET refresh in AuthContext.tsx:24 is broken (no credentials:'include') — Step 4 fix Negligible Selected — current solution. Fits P1 (REST + SSE only) and P3 (no localStorage).

Component: 02_auth

Solution Tools Advantages Limitations Requirements Security Cost Fit
AuthContext + ProtectedRoute + login/logout/bootstrap-refresh react-router-dom@7, React Context, 01_api-transport XSS-resistant (bearer in memory, never in storage); login UX matches WPF era; refresh-token rotation is server-driven Two refresh paths in code (F2): bootstrap GET (AuthContext.tsx:24 — broken, missing credentials:'include') vs. 401-retry POST (api/client.ts:44 — correct). Bootstrap path will fail on cross-origin and force a re-login on cold load — Step 4 fix priority. ProtectedRoute spinner has no role='status' / no timeout RBAC is server-enforced; UI must NOT trust AuthUser.role for security — only for showing/hiding nav Bearer never written to storage (P3); refresh cookie is Secure HttpOnly SameSite=Strict (issued server-side); WPF-era encrypted-creds command-line handoff intentionally NOT ported (P8) Negligible Selected — current solution. Refresh-path consolidation (single POST with credentials:'include') is the planned fix; structurally sound.

Component: 03_shared-ui

Solution Tools Advantages Limitations Requirements Security Cost Fit
Header + flight dropdown + FlightContext + ConfirmDialog + HelpModal + DetectionClasses strip React Context (FlightContext), Tailwind, 01_api-transport One place for cross-page chrome; FlightContext is the only flight-selection store (P4); ConfirmDialog reused by 4 components FlightContext ceiling: GET /api/flights?pageSize=1000 is a hardcoded magic number (finding B3). selectFlight is fire-and-forget PUT — no error path. Header dropdown lacks role=combobox / aria-expanded / Esc-to-close / focus-trap. ConfirmDialog lacks aria-modal / role=dialog. HelpModal does NOT close on Esc (inconsistent with ConfirmDialog); GUIDELINES are hardcoded English instead of i18n Selected flight persists as a UserSettings field via PUT /api/annotations/settings/user (NOT /api/flights/select04_verification_log.md F3) None additional Negligible Selected — current solution. Flight-dropdown a11y + 1000-row pagination ceiling are Step 4 / Step 8 candidates.

Component: 04_login

Solution Tools Advantages Limitations Requirements Security Cost Fit
Public /login route with username + password, calls 02_auth login React, Tailwind Single dedicated public surface; clean separation from ProtectedRoute runUnlockSequence 4×600 ms theatrical animation is decorative; document only (finding B4) Receives bearer from server; cookie set server-side Login form does NOT autocomplete sensitive values; only public route in the SPA Negligible Selected — current solution. No structural concerns.

Component: 05_flights

Solution Tools Advantages Limitations Requirements Security Cost Fit
Flight CRUD + waypoints + altitude profile + GPS-Denied (Operations + planned Test Mode) — currently being ported from mission-planner/ (React 18 + MUI 5) into src/features/flights/ (React 19 + Tailwind 4) leaflet@1.9.4 + react-leaflet@5 + leaflet-draw + leaflet-polylinedecorator; chart.js@4 + react-chartjs-2; @hello-pangea/dnd@18; native fetch; EventSource for F13 live-GPS SSE; OpenWeatherMap (direct HTTPS) Replaces WPF MapMatcher with browser-native cartography; live-GPS telemetry is real (F13); altitude charts work; mission-planner port gives a high-fidelity reference UX Component spans two physical trees (one component, two trees — ADR-009). mission-planner/src/utils/flightPlanUtils.ts:60 carries a hardcoded OpenWeatherMap API key (P10 violation — Step 4 fix). Wind errors are silently swallowed; sequential per-segment await is a perf trap; battery-capacity unit ambiguous (Wh vs Ws); km vs m altitude mixing. mapIcons.ts defaultIcon CDN URL pinned to leaflet@1.7.1 (drift). Waypoint POST shape mismatches the suite spec — UI sends {name, latitude, longitude, order}; spec wants {Geopoint:{Lat,Lon,MGRS}, Source, Objective, OrderNum, Height} (finding #20 — likely 400s on a strict server). Edit-cycle is delete-then-recreate today (finding #19). FlightsPage save is N+M round-trips (delete + recreate per waypoint). MiniMap licence/responsive concerns; AltitudeDialog / JsonEditorDialog modal a11y; WaypointList drag/touch a11y; AltitudeChart bundle bloat. Test Mode (F12) is target-only.tlog + video upload, IMU sync, SITL feed — none wired today Wind data fetch + map tile fetch require browser internet; field deployments need an offline tile cache (not implemented); .tlog parser must be available client-side or server-side once Test Mode lands OpenWeatherMap key must move to .env per P10 (Step 4 testability fix); satellite tile URL is env-driven via VITE_SATELLITE_TILE_URL in mission-planner only (target: src/ once port lands) Direct browser → external HTTP costs for OWM + tiles; otherwise compute is client-side Selected — current solution; under active convergence. Per architecture.md § Architecture Vision, the mission-planner tree is on a multi-cycle path to deletion (mission-planner/src/features/flights/); convergence happens in Phase B feature cycles, not in Step 8.

Component: 06_annotations

Solution Tools Advantages Limitations Requirements Security Cost Fit
Bounding-box editor (CanvasEditor), VideoPlayer, AI Detect (sync only today), AnnotationsSidebar, MediaList browser scoped to selected flight, AnnotationsPage orchestrator HTML5 <canvas> + HTML5 <video> (replaces WPF LibVLC — ADR-003); native fetch + SSE; react-dropzone for upload; Tailwind Frame-accurate-ish video review without LibVLC; doubly-prefixed POST /api/annotations/annotations save path verified at Step 4 (F5); F14 annotation-status SSE (admin-wide, client-side filtered) is real Async video detect (F7) is NOT wired — no /api/detect/video/{id}, no /api/detect/stream/{jobId} calls anywhere; sync POST /api/detect/${id} is used for both images and videos today (silent UX hazard for long videos). VideoPlayer hardcoded fps=30 (ADR-003 consequence). CanvasEditor missing pan; wrong time-window (symmetric ±200 ms instead of asymmetric [-50, +150] ms — finding #6); missing affiliation icons; missing CombatReadiness indicator; dead AFFILIATION_COLORS. AnnotationsSidebar AI-detect doesn't stream progress; silent catches. AnnotationsPage no panel-width persistence (P11 violation); handleDownload tainted-canvas risk; handleSave fallback hides save loss; annotation save body shape mismatches spec — must add Source, WaypointId, rename time→videoTime (finding #32). MediaList uses alert(); blob: locals ignore filter. Missing keyboard shortcuts (R, V, PageUp/Down). Missing Camera config side panel (GSD computation — finding #17). Missing Tile zoom for splitTile. Hardcoded English strings in help / sidebar Detect must be wired to detect/ async pipeline once F7 ships (Phase B); X-Refresh-Token header required for long-running video detect (per _docs/10_auth.md); annotation overlay window must align to spec asymmetric [-50, +150] ms XSS-safe canvas rendering; uploads filtered by react-dropzone MIME; server is authoritative for virus scan; tainted-canvas risk on download (finding) Detect-pipeline cost is server-side; UI compute is client-side Selected — current solution. Async-detect wiring + canvas-editor parity + a11y are Phase B targets; structurally sound.

Component: 07_dataset

Solution Tools Advantages Limitations Requirements Security Cost Fit
Dataset Explorer with three tabs (annotations / editor / class-distribution), bulk-validate, status filters React, Tailwind, chart.js@4 for class-distribution chart (DatasetPage.tsx:151), reuses CanvasEditor from 06_annotations (cross-feature edge — finding) Validate button is wired (Step 4 correction — 04_verification_log.md F9); class-distribution chart is implemented (Step 4 correction); "objectsOnly" checkbox is implemented; objectsOnly filter works [V] keyboard shortcut missing (only the button works); Refresh thumbnails button missing; status-bar StatusText slots missing; IsSeed highlight missing (legacy 8 px IndianRed border — open question); editor tab does not save (finding #4); magic mediaType=1 literal (finding #5); dead ConfirmDialog import; silent catches; status filter conflates None with All; classNum=0 sentinel collides with real class 0 (finding #9); no virtualisation; no keyboard shortcuts at all AnnotationStatus numeric drift (UI 0/1/2 vs spec 0/10/20/30) surfaces as wrong status filter values on the wire — Step 4 fix per P9; DatasetItem.isSplit not in spec response — parent-suite doc fix recorded in leftovers and applied None additional Class-distribution endpoint server-side cost; otherwise client-side Selected — current solution. Bulk-validate + chart parity confirm the React port is closer to WPF parity than the original draft suggested; remaining gaps are surface-level + a11y.

Component: 08_admin

Solution Tools Advantages Limitations Requirements Security Cost Fit
Class CRUD (add + delete; edit to be re-introduced per P12), user management, AI/GPS settings forms, aircraft default-toggle React forms with useState; native fetch; reuses ConfirmDialog (only on user-deactivation) Single page consolidates 4 admin surfaces; aircraft cross-service mutation works (PATCH /api/flights/aircrafts/${id}) AI Settings & GPS Settings forms render with defaultValue only — no state, no submit handler, the Save button does nothing (PRIORITY — Step 6 problem-extraction surface). Hardcoded GPS device default '192.168.1.100' / port '5535' shipped in production bundle. handleDeleteClass has no ConfirmDialog despite being destructive (finding B4). Detection-class read uses /api/annotations/classes but write uses /api/admin/classes (cross-service split — accepted but documented). handleToggleDefault duplicated in 09_settings (aircraft default lives in two pages — surface intent at Step 6). Many hardcoded English strings (P6 violation — Step 4 fix). Admin cannot edit existing classes today (P12 violation; PATCH /api/admin/classes/{id} to introduce — Phase B task) RBAC is server-enforced (UI MUST NOT trust AuthUser.role for security); /admin route lacks role-gate — security PRIORITY RBAC server-enforced; class-delete bypasses ConfirmDialog (Step 4 fix) Compute is server-side Selected — current solution; multiple Step 4 / Step 6 / Phase B fixes queued. Structurally sound; the broken Save buttons are a P0 product-correctness defect.

Component: 09_settings

Solution Tools Advantages Limitations Requirements Security Cost Fit
System / Directory / Camera / User settings forms; aircraft default-toggle React forms, useState, native fetch Settings persist via annotations/ service (/api/annotations/settings/system + /api/annotations/settings/directories) — verified Step 4 (F11); aircraft default-toggle goes to flights/ (cross-service — accepted) saveSystem / saveDirs lack try/finally — PUT failure leaves saving:true permanently (finding B4). Numeric inputs use `parseInt(v) 0— clearing a field silently writes 0 (finding B4). No optimistic concurrency (Step 6 surface).UserSettings.panelWidthsis typed butuseResizablePaneldoesn't write back (P11 violation — Step 4 fix)./settingsroute role-gate is more nuanced than/admin` (server-enforced via 403; no SETTINGS permission code in spec) /settings role-gate per _docs/02_document/architecture.md § Security; aircraft default is a global config today (finding) RBAC server-enforced

Component: 10_app-shell

Solution Tools Advantages Limitations Requirements Security Cost Fit
App.tsx + main.tsx + routing tree + global CSS react-router-dom@7, Tailwind 4 + az-* design tokens (src/index.css), React 19 root Single composition root; clear AuthProvider → ProtectedRoute → FlightProvider → Header + Routes chain; /flights is the default authenticated route /admin and /settings lack role-based route guards (PRIORITY — security finding; complements server-side RBAC). No ErrorBoundary. No lazy code-splitting / no chunked routes (bundle bloat finding). index.html body class hardcodes hex literals (bg-[#1e1e1e] text-[#adb5bd]) instead of az-* tokens (cosmetic — ADR-005) Routing tree is the security surface for client-side navigation; server-side RBAC is authoritative UI role-gate is convenience, not security; server-enforced 403 is the actual gate Negligible Selected — current solution. Adding ErrorBoundary + lazy routes + role-gate are Step 4 / Step 8 candidates.

Component: 11_class-colors

Solution Tools Advantages Limitations Requirements Security Cost Fit
Class → color + text mapping; getPhotoModeSuffix helper; consumed by 03_shared-ui/DetectionClasses, 06_annotations, 07_dataset Pure TypeScript module; no external deps Lifted out of 06_annotations at Step 2 (P7); single source of truth for class color tokens; yoloId = classId + photoModeOffset mapping is centralised Physical file still lives at src/features/annotations/classColors.ts — the layout-doc-only mapping pending a Step 4 file move (module-layout.md Verification Needed #1, #8). getPhotoModeSuffix may duplicate the typed DetectionClass.photoMode field — likely redundant; possible deletion after typed propagation None None Negligible Selected — current solution. Cleanest L0 component; the file-move is purely cosmetic / layering hygiene.

Testing Strategy

Current state — verified at Step 4

  • Zero test coverage in src/src/**/*.test.* returns zero matches (Grep verified at Step 4, 04_verification_log.md §1).
  • No test framework configured in package.json (Vitest / Jest / Playwright are all absent).
  • No test step in CI.woodpecker/build-arm.yml runs bun install + bun run build only.
  • The legacy WPF stack had an Azaion.Test xUnit project that tested utilities only; that test surface did NOT migrate.

Target test pyramid (to be defined at autodev Step 5 — Decompose Tests)

The test-runner choice is deferred to autodev Step 3 (Test Spec) → Step 5 (Decompose Tests) per the Step 4.5 decision (architecture.md § Architecture Vision, item 7 of Open Questions). This document does not pre-empt that decision; it lists the categories the existing code already implies.

Unit / module-level

  • Foundation hooks: useDebounce, useResizablePanel — pure timing + state behavior; testable with React Testing Library + fake timers.
  • Foundation utilities: flightPlanUtils.ts (battery / distance / wind compute) — pure functions; testable in isolation once the OpenWeatherMap key is moved to .env (P10 / Step 4).
  • Class-colors module: getPhotoModeSuffix, yoloId mapping — pure functions.
  • i18n bundles: assert that every English key has a Ukrainian counterpart and vice versa (P6 mandatory check).
  • Numeric-enum coverage: assert that AnnotationStatus, MediaStatus, Affiliation, CombatReadiness numeric values match the suite spec (P9 enforcement — directly catches the enum drift that motivated Step 4 corrections).

Component / integration

  • AuthContext — login, bootstrap-refresh (currently broken — fix first), 401-retry refresh, logout. Mock 01_api-transport to assert request shape (credentials:'include' is the regression to lock down).
  • FlightContext — list pagination ceiling, selectFlight round-trip, hydration of selected flight from UserSettings.
  • CanvasEditor — bbox draw / 8-handle resize / Ctrl-multi-select; affiliation overlay; CombatReadiness indicator (once dead AFFILIATION_COLORS is wired).
  • MediaList — pagination, filter, drag-drop upload, delete with ConfirmDialog.
  • DatasetPage — bulk-validate flow (POST + UI state); class-distribution chart load; status filter (specifically that None and All are NOT conflated — finding fix).
  • AdminPage — class add / delete (currently no edit; will gain edit per P12). User add / deactivate. AI Settings / GPS Settings forms (currently broken — the Save button must POST something — Step 6 product-correctness defect).
  • SettingsPage — system / directory / camera saves; aircraft default toggle (cross-service flights/ mutation).

End-to-end (browser)

  • Login → /flights default route → flight selection → MediaList → annotation save → bulk-validate — the operator's primary loop. Already exercised manually at every release.
  • GPS-Denied Test Mode (F12) — once implemented (Phase B target). Inputs: .tlog + video; assertion: SITL feed reaches the onboard service and produces a positioning trace.
  • Async video detect (F7) — once implemented (Phase B target). Inputs: long video; assertion: SSE progress visible; final detections persisted.

Non-functional

  • Bundle size budget: vite build artifact ≤ ~2 MB gzipped (currently no enforcement — CI gate to add).
  • Auth refresh transparency: 401 → POST refresh → retry, no UI re-render past <ProtectedRoute> (regression test — locks the bootstrap-refresh fix).
  • Route guards: unauth user → /admin → redirected to /login (locks the missing role-gate fix).
  • i18n coverage: every visible string in both en.json and ua.json (P6 mandatory).
  • a11y smoke: ConfirmDialog has role=dialog + aria-modal; Header dropdown has role=combobox + aria-expanded + Esc-to-close; spinner has role=status.
  • Endpoint contract: every api.*() call URL matches the suite OpenAPI; specifically that the doubly-prefixed /api/annotations/annotations save path stays correct after any refactor.
  • Performance: long video detect — UI stays responsive; progress visible (currently NOT met — 04_verification_log.md F7 / finding #21).

Test environment expectations

  • Test DB / services: tests run against the suite docker-compose stack or a service-mock layer. The UI is HTTP-only — there is no UI-side database to bootstrap.
  • CI integration: a test step must be added to .woodpecker/build-arm.yml (currently missing — architecture.md § Deployment Model "Missing from the pipeline today").
  • Coverage target: TBD at Step 3 (Test Spec) — this document does not commit to a percentage.

References

Source docs (verified inputs)

  • _docs/02_document/00_discovery.md — Step 0 codebase discovery, dep graph, topo order
  • _docs/02_document/architecture.md — Step 3a system architecture (with Step 4.5 § Architecture Vision)
  • _docs/02_document/system-flows.md — Step 3b 14 sequence flows F1F14 (with Step 4 corrections)
  • _docs/02_document/data_model.md — Step 3c entity-relationship + enum-drift map
  • _docs/02_document/deployment/containerization.md — multi-stage Dockerfile, ARM64, nginx static serve
  • _docs/02_document/deployment/ci_cd_pipeline.md — Woodpecker .woodpecker/build-arm.yml
  • _docs/02_document/deployment/environment_strategy.md — dev / stage / production
  • _docs/02_document/deployment/observability.md — current state (no centralized client telemetry — Step 6 surface)
  • _docs/02_document/04_verification_log.md — Step 4 Verification Pass corrections
  • _docs/02_document/01_legacy_coverage_gaps.md — WPF parity rollup
  • _docs/02_document/glossary.md — Step 4.5 confirmed terminology
  • _docs/02_document/module-layout.md — Step 2.5 file-ownership map
  • _docs/02_document/components/00_foundation/description.md — through 11_class-colors/description.md
  • _docs/02_document/modules/*.md — 22 module docs covering all 77 modules
  • _docs/legacy/wpf-era.md — legacy reference

Configuration evidence

  • package.json — React 19, Vite 6, TypeScript 5.7 strict, Bun 1.3.11
  • vite.config.ts — dev /api → http://localhost:8080 proxy
  • Dockerfile — multi-stage oven/bun:1.3.11-alpinenginx:alpine
  • nginx.conf — 9 /api/<service>/ reverse-proxy routes, client_max_body_size 500M
  • .woodpecker/build-arm.yml — ARM64-only build pipeline, no test step today
  • src/index.cssaz-* Tailwind 4 design tokens
  • src/i18n/en.json, src/i18n/ua.json — bilingual bundles
  • src/types/index.ts — typed REST contract (with Step 4.5 inline numeric-enum comments per P9)

External integrations

  • OpenWeatherMap: api.openweathermap.org/data/2.5/onecall (hardcoded key in source — P10 violation, Step 4 fix)
  • OpenStreetMap: tile servers via react-leaflet TileLayer defaults
  • Suite services (via nginx): admin/, flights/, annotations/, detect/, loader/, gps-denied-{desktop,onboard}/, autopilot/, resource/
  • _docs/00_problem/ — Step 6 retrospective problem extraction (problem.md, restrictions.md, acceptance_criteria.md, input_data/, security_approach.md) — to be produced next
  • _docs/02_document/FINAL_report.md — Step 7 final integrated report — to be produced after Step 6