# 00 — Codebase Discovery

> **Step 0 output for `/document`.** Read by Step 1 (per-module docs) to drive
> processing order, by Step 2 (component assembly) to seed groupings, and by
> Step 3 (system synthesis) for the tech-stack table.
>
> **Scope** (chosen at the autodev gate, 2026-05-10):
> - `src/` — Azaion UI (React 19 SPA, the live front-end of the suite).
> - `mission-planner/` — embedded React 18 + MUI sub-project (port-source for
>   `src/features/flights/`). Documented as a separate component group.
> - `_docs/` already contained user-curated reference content
>   (`legacy/wpf-era.md`, `ui_design/`, `_autodev_state.md`); the document
>   skill writes alongside, not over.
>
> **Out of scope**: `node_modules/`, `dist/`, `bun.lock`, `package-lock.json`,
> `.git/`, `.cursor/`, `_docs/` (read-only inputs), `.idea/`, `.claude/`,
> `.superpowers/`, `mission-planner/public/` static assets.

---

## 1. Workspace at a glance

```
suite/ui/                              ← Cursor workspace root
├── src/                               ← Azaion UI (React 19, the live SPA)
├── mission-planner/                   ← embedded port-source (React 18 + MUI)
├── _docs/                             ← user-curated + autodev artifacts
│   ├── legacy/wpf-era.md              read-only reference (WPF predecessor)
│   ├── ui_design/                     read-only reference (HTML wireframes)
│   ├── _autodev_state.md              autodev state pointer
│   └── 02_document/                   ← this folder (autodev outputs)
├── .cursor/                           skills/rules/agents
├── .woodpecker/build-arm.yml          CI: arm64 Docker build → Harbor
├── Dockerfile                         multi-stage: bun build → nginx static
├── nginx.conf                         /api/* reverse proxy → suite services
├── index.html                         SPA shell (mounts /src/main.tsx)
├── package.json                       react 19, bun 1.3.11, vite 6, tw 4
├── tsconfig.json                      strict ESM, `@/*` → `src/*`
├── vite.config.ts                     react + tailwind plugin, /api proxy
├── README.md                          repo overview + maturation plan
└── .gitignore                         node_modules, .env.*, playwright-report/
```

`src/` and `mission-planner/` are **disjoint** — no file in one imports from
the other. The Vite alias `@ → src` is defined only in the workspace
`vite.config.ts`; `mission-planner/vite.config.ts` has no aliases. Each has
its own `package.json`, `tsconfig`, `index.html`, and entry point. The
production bundle (`Dockerfile`) builds **only the workspace**, not
`mission-planner/`.

`mission-planner/` ships a (mostly) functional flight-mission UI that the
`src/features/flights/*` files are mechanically translating into the new
SPA. Per the workspace `README.md`, `mission-planner/` is **not** part of
the deployed product.

## 2. Tech stack

### 2a. Workspace `src/` (Azaion UI)

| Concern        | Choice                              | Source                   |
|----------------|-------------------------------------|--------------------------|
| Language       | TypeScript 5.7 (`strict: true`)     | `tsconfig.json`          |
| UI framework   | React 19 (`react-dom/client`)       | `package.json`           |
| Bundler        | Vite 6                              | `package.json`, `vite.config.ts` |
| Pkg manager    | Bun 1.3.11 (declared via `packageManager`) | `package.json`     |
| Styling        | Tailwind CSS 4 (`@tailwindcss/vite`) + custom `az-*` tokens in `src/index.css` | `package.json`, `vite.config.ts` |
| Routing        | `react-router-dom` 7                | `src/App.tsx`            |
| i18n           | `i18next` + `react-i18next` (UA / EN) | `src/i18n/i18n.ts`     |
| Map            | `leaflet` 1.9 + `react-leaflet` 5 + `leaflet-draw` + `leaflet-polylinedecorator` | `package.json`, `src/features/flights/*` |
| Charts         | `chart.js` 4 + `react-chartjs-2`    | `package.json`           |
| DnD            | `@hello-pangea/dnd` 18              | `package.json`           |
| File upload    | `react-dropzone`                    | `package.json`           |
| Icon set       | `react-icons`                       | `package.json`           |
| HTTP transport | native `fetch` (custom thin wrapper) | `src/api/client.ts`     |
| Realtime       | native `EventSource` (SSE)          | `src/api/sse.ts`         |
| State mgmt     | React Context only — `AuthContext`, `FlightContext`. **No** Redux / Zustand / TanStack Query. | `src/auth/`, `src/components/FlightContext.tsx` |
| Tests          | **none** (no test framework configured) | (verified via Glob)  |
| Build target   | static bundle → nginx (multi-stage Dockerfile) | `Dockerfile`, `nginx.conf` |
| Runtime        | nginx in container, ARM64 image     | `.woodpecker/build-arm.yml` |

### 2b. `mission-planner/` (port-source)

| Concern        | Choice                                   | Source                       |
|----------------|------------------------------------------|------------------------------|
| Language       | TypeScript 5.7 (`strict: true`)          | `mission-planner/tsconfig.app.json` |
| UI framework   | React 18                                 | `mission-planner/package.json` |
| Bundler        | Vite 6                                   | `mission-planner/vite.config.ts` |
| Pkg manager    | npm (lockfile not committed)             | (no `bun.lock` in `mission-planner/`) |
| UI library     | MUI 5 (`@mui/material` + `@mui/icons-material` + `@emotion/*`) | `mission-planner/package.json` |
| Map            | `leaflet` 1.9 + `react-leaflet` 4.2 + `leaflet-draw` + `leaflet-polylinedecorator` | `mission-planner/package.json` |
| Charts         | `chart.js` 4 + `react-chartjs-2`         | `mission-planner/package.json` |
| DnD            | `@hello-pangea/dnd` 16                   | `mission-planner/package.json` |
| Flags          | `react-world-flags`                      | `mission-planner/package.json` |
| Tests          | Jest implied (`@testing-library/jest-dom` import in `setupTests.ts`, `describe/it/expect` in `src/test/jsonImport.test.ts`) but **no** Jest dep nor config in `package.json` — test currently cannot run as-is. | `mission-planner/package.json`, `src/setupTests.ts`, `src/test/jsonImport.test.ts` |
| Env config     | `.env.example` declares `VITE_SATELLITE_TILE_URL` | `mission-planner/.env.example` |
| Build target   | not built or shipped by the suite        | (Dockerfile copies only workspace `src/`) |

## 3. Configuration & infrastructure files

| Path                                | Role                                                                 |
|-------------------------------------|----------------------------------------------------------------------|
| `package.json` (workspace)          | scripts: `dev`, `build` (`tsc -b && vite build`), `preview`. No `test`. |
| `tsconfig.json`                     | `strict: true`, `noUnusedLocals/Parameters: false` (lax), `paths: {"@/*": ["./src/*"]}`. |
| `vite.config.ts`                    | `@vitejs/plugin-react` + `@tailwindcss/vite`. Dev proxy `/api → http://localhost:8080`. |
| `index.html`                        | `<div id="root"></div>` + `<script type="module" src="/src/main.tsx">`. Body class hardcodes `bg-[#1e1e1e] text-[#adb5bd]`. |
| `Dockerfile`                        | Stage 1: `oven/bun:1.3.11-alpine`, `bun install --frozen-lockfile`, `bun run build`. Stage 2: `nginx:alpine`, copies `dist/` to `/usr/share/nginx/html`, exposes 80. `ENV AZAION_REVISION=$CI_COMMIT_SHA`. |
| `nginx.conf`                        | Reverse-proxies 9 `/api/<service>/` paths → `http://<service>:8080/`. Enumerates: annotations, flights, admin, resource, detect, loader, gps-denied-desktop, gps-denied-onboard, autopilot. SPA fallback `/index.html`. `client_max_body_size 500M`. |
| `.woodpecker/build-arm.yml`         | Triggers on push to `dev`/`stage`/`main`. Builds + pushes `${REGISTRY_HOST}/azaion/ui:${branch}-arm` with OCI labels (revision, created, source). |
| `.gitignore`                        | `node_modules/`, `.env.local`, `.env.development.local`, `.env.test.local`, `.env.production.local`, `package-lock.json`, `yarn.lock`, `/test-results/`, `/playwright-report/`, `/blob-report/`, `/playwright/.cache/`, `/playwright/.auth/`. (Playwright entries are aspirational — no Playwright installed.) |
| `.env.example` (workspace)          | **absent** — README §"Local development" notes this as a testability fix scheduled for Step 4. API base URL is currently hardcoded via the dev proxy + nginx routing. |
| `mission-planner/package.json`      | scripts: `dev`, `build`, `preview`. **No** `test` script despite the test file. |
| `mission-planner/tsconfig.app.json` | `exclude: ["src/**/*.test.ts", "src/**/*.test.tsx", "src/setupTests.ts"]`. |
| `mission-planner/.env.example`      | `VITE_SATELLITE_TILE_URL` only.                                      |
| `mission-planner/public/manifest.json` | PWA manifest (vestigial CRA scaffolding).                         |

## 4. Entry points

| Project          | File                                            | Mounts                                                              |
|------------------|-------------------------------------------------|---------------------------------------------------------------------|
| `src/`           | `src/main.tsx`                                  | `<StrictMode><BrowserRouter><App /></BrowserRouter></StrictMode>` into `#root`. Imports `./i18n/i18n` for side effects (i18next init) and `./index.css`. |
| `src/`           | `src/App.tsx`                                   | Top-level `Routes`. `/login` is public; everything under `/*` is wrapped in `AuthProvider → ProtectedRoute → FlightProvider → Header + nested Routes` (`/flights`, `/annotations`, `/dataset`, `/admin`, `/settings`, `*` → `/flights`). |
| `mission-planner/` | `mission-planner/src/main.tsx`               | `<StrictMode><LanguageProvider><FlightPlan /></LanguageProvider></StrictMode>` into `#root`. Imports `leaflet/dist/leaflet.css` and `leaflet-draw/dist/leaflet.draw.css`. |
| `mission-planner/` | `mission-planner/src/App.tsx`                | Empty CRA stub — **not used** by `main.tsx`. (Vestigial.)            |

## 5. Test structure

| Project        | Test file(s)                                | Framework    | Status                                                      |
|----------------|---------------------------------------------|--------------|-------------------------------------------------------------|
| `src/`         | none                                        | n/a          | **Zero test coverage.** Confirmed via Glob over `src/**/*.{test,spec}.*`. |
| `mission-planner/` | `mission-planner/src/test/jsonImport.test.ts` | Jest (implied — uses `describe/it/expect`) | **Cannot run** — Jest is not in `package.json`; only `@testing-library/jest-dom` is imported in `setupTests.ts`. |
| `mission-planner/` | `mission-planner/src/setupTests.ts`     | -            | One-line `import '@testing-library/jest-dom'`. |

This vacancy is the explicit input for autodev Steps 3–7 (test-spec, testability revision, decompose tests, implement tests, run tests).

## 6. Existing documentation

| Path                                  | Status         | Owner / used by                                                            |
|---------------------------------------|----------------|----------------------------------------------------------------------------|
| `README.md` (workspace)               | maintained     | Single source of truth for repo intent + maturation plan.                   |
| `_docs/legacy/wpf-era.md`             | reference      | Captures WPF predecessor (`Azaion.Annotator`, `Azaion.Dataset`, Cython sidecars) at commit `22529c2`. Authoritative for §10 "What survived into the new world" and §11 "What is intentionally NOT being ported". |
| `_docs/ui_design/README.md`           | reference      | Authoritative UX spec: pages, breakpoints, panel layouts, keyboard shortcuts, color tokens, affiliation icons, combat readiness, annotation row gradient, video time-window display, confirmation dialogs. |
| `_docs/ui_design/{flights,annotations,dataset_explorer,admin,settings}.html` | reference  | HTML wireframes for each page (inherited from WPF UI mockups). |
| `_docs/_autodev_state.md`             | maintained     | autodev state pointer (this document is being produced under it).          |
| `mission-planner/README.md`           | stale          | CRA boilerplate; does not describe the actual app.                         |
| Suite-level `../_docs/`               | external       | Suite-wide architecture, schema, deployment topology. Not owned by this workspace; consulted as needed during Step 3. |

## 7. Dependency graph

`src/` and `mission-planner/` are independent dependency islands. Each is
acyclic by inspection (verified by following the import chains in §8 and §9
from leaves outward).

### 7a. Workspace `src/` (intra-repo edges only; React/leaflet/etc. omitted)

```mermaid
graph LR
  main[main.tsx] --> App[App.tsx]
  main --> i18n_init[i18n/i18n.ts]
  i18n_init --> en[i18n/en.json]
  i18n_init --> ua[i18n/ua.json]

  App --> AuthProvider[auth/AuthContext.tsx]
  App --> FlightProvider[components/FlightContext.tsx]
  App --> ProtectedRoute[auth/ProtectedRoute.tsx]
  App --> Header[components/Header.tsx]
  App --> LoginPage[features/login/LoginPage.tsx]
  App --> FlightsPage[features/flights/FlightsPage.tsx]
  App --> AnnotationsPage[features/annotations/AnnotationsPage.tsx]
  App --> DatasetPage[features/dataset/DatasetPage.tsx]
  App --> AdminPage[features/admin/AdminPage.tsx]
  App --> SettingsPage[features/settings/SettingsPage.tsx]

  AuthProvider --> apiClient[api/client.ts]
  AuthProvider --> typesIdx[types/index.ts]
  ProtectedRoute --> AuthProvider
  FlightProvider --> apiClient
  FlightProvider --> typesIdx

  Header --> AuthProvider
  Header --> FlightProvider
  Header --> HelpModal[components/HelpModal.tsx]
  Header --> typesIdx

  sse[api/sse.ts] --> apiClient

  ConfirmDialog[components/ConfirmDialog.tsx]
  DetectionClasses[components/DetectionClasses.tsx] --> apiClient
  DetectionClasses --> classColors[features/annotations/classColors.ts]
  DetectionClasses --> typesIdx

  LoginPage --> AuthProvider

  AdminPage --> apiClient
  AdminPage --> ConfirmDialog
  AdminPage --> typesIdx

  SettingsPage --> apiClient
  SettingsPage --> typesIdx

  classColors
  flightsTypes[features/flights/types.ts]
  flightPlanUtils[features/flights/flightPlanUtils.ts] --> flightsTypes
  mapIcons[features/flights/mapIcons.ts]

  WaypointList[features/flights/WaypointList.tsx] --> flightsTypes
  AltitudeChart[features/flights/AltitudeChart.tsx] --> flightsTypes
  WindEffect[features/flights/WindEffect.tsx] --> flightsTypes
  MiniMap[features/flights/MiniMap.tsx] --> flightsTypes
  MapPoint[features/flights/MapPoint.tsx] --> flightsTypes
  MapPoint --> mapIcons
  DrawControl[features/flights/DrawControl.tsx] --> flightsTypes
  DrawControl --> flightPlanUtils
  AltitudeDialog[features/flights/AltitudeDialog.tsx] --> flightsTypes
  FlightListSidebar[features/flights/FlightListSidebar.tsx] --> typesIdx
  JsonEditorDialog[features/flights/JsonEditorDialog.tsx]

  FlightParamsPanel[features/flights/FlightParamsPanel.tsx] --> WaypointList
  FlightParamsPanel --> AltitudeChart
  FlightParamsPanel --> WindEffect
  FlightParamsPanel --> flightsTypes
  FlightParamsPanel --> typesIdx
  FlightMap[features/flights/FlightMap.tsx] --> DrawControl
  FlightMap --> MapPoint
  FlightMap --> MiniMap
  FlightMap --> mapIcons
  FlightMap --> flightsTypes
  FlightsPage --> FlightProvider
  FlightsPage --> apiClient
  FlightsPage --> sse
  FlightsPage --> ConfirmDialog
  FlightsPage --> FlightListSidebar
  FlightsPage --> FlightParamsPanel
  FlightsPage --> FlightMap
  FlightsPage --> AltitudeDialog
  FlightsPage --> JsonEditorDialog
  FlightsPage --> flightPlanUtils
  FlightsPage --> flightsTypes
  FlightsPage --> typesIdx

  CanvasEditor[features/annotations/CanvasEditor.tsx] --> typesIdx
  CanvasEditor --> classColors
  VideoPlayer[features/annotations/VideoPlayer.tsx] --> typesIdx
  AnnotationsSidebar[features/annotations/AnnotationsSidebar.tsx] --> apiClient
  AnnotationsSidebar --> sse
  AnnotationsSidebar --> classColors
  AnnotationsSidebar --> typesIdx
  MediaList[features/annotations/MediaList.tsx] --> FlightProvider
  MediaList --> apiClient
  MediaList --> useDebounce[hooks/useDebounce.ts]
  MediaList --> ConfirmDialog
  MediaList --> typesIdx
  AnnotationsPage --> useResizablePanel[hooks/useResizablePanel.ts]
  AnnotationsPage --> apiClient
  AnnotationsPage --> MediaList
  AnnotationsPage --> VideoPlayer
  AnnotationsPage --> CanvasEditor
  AnnotationsPage --> AnnotationsSidebar
  AnnotationsPage --> DetectionClasses
  AnnotationsPage --> classColors
  AnnotationsPage --> typesIdx

  DatasetPage --> apiClient
  DatasetPage --> useDebounce
  DatasetPage --> useResizablePanel
  DatasetPage --> FlightProvider
  DatasetPage --> DetectionClasses
  DatasetPage --> ConfirmDialog
  DatasetPage --> CanvasEditor
  DatasetPage --> typesIdx
```

### 7b. `mission-planner/src/`

```mermaid
graph LR
  mp_main[main.tsx] --> flightPlan[flightPlanning/flightPlan.tsx]
  mp_main --> LanguageProvider[flightPlanning/LanguageContext.tsx]

  mp_types[types/index.ts]
  mp_config[config.ts]
  mp_utils[utils.ts]

  translations[constants/translations.ts] --> mp_types
  languages[constants/languages.ts] --> mp_types
  purposes[constants/purposes.ts] --> mp_types
  actionModes[constants/actionModes.ts]
  maptypes[constants/maptypes.ts]
  tileUrls[constants/tileUrls.ts]

  mapIcons[icons/MapIcons.tsx]
  pointIcons[icons/PointIcons.tsx]
  sidebarIcons[icons/SidebarIcons.tsx]
  phoneIcon[icons/PhoneIcon.tsx]

  calcDistance[services/calculateDistance.ts] --> mp_types
  AircraftService[services/AircraftService.ts] --> mp_types
  WeatherService[services/WeatherService.ts] --> mp_types
  calcBattery[services/calculateBatteryUsage.ts] --> AircraftService
  calcBattery --> WeatherService
  calcBattery --> mp_types

  Aircraft[flightPlanning/Aircraft.ts] --> mp_utils
  WindEffect2[flightPlanning/WindEffect.tsx] --> LanguageProvider
  WindEffect2 --> translations
  AltitudeChart2[flightPlanning/AltitudeChart.tsx] --> LanguageProvider
  AltitudeChart2 --> translations
  AltitudeChart2 --> mp_types
  AltitudeDialog2[flightPlanning/AltitudeDialog.tsx] --> LanguageProvider
  AltitudeDialog2 --> mp_config
  AltitudeDialog2 --> translations
  AltitudeDialog2 --> purposes
  DrawControl2[flightPlanning/DrawControl.tsx] --> mp_types
  JsonEditorDialog2[flightPlanning/JsonEditorDialog.tsx] --> LanguageProvider
  JsonEditorDialog2 --> translations
  TotalDistance[flightPlanning/TotalDistance.tsx] --> LanguageProvider
  TotalDistance --> calcDistance
  TotalDistance --> translations
  TotalDistance --> mp_types
  LanguageSwitcher[flightPlanning/LanguageSwitcher.tsx] --> LanguageProvider
  LanguageSwitcher --> languages
  LanguageSwitcher --> translations
  MapPoint2[flightPlanning/MapPoint.tsx] --> LanguageProvider
  MapPoint2 --> purposes
  MapPoint2 --> translations
  MapPoint2 --> pointIcons
  MapPoint2 --> mp_types
  MiniMap2[flightPlanning/MiniMap.tsx] --> MapView2
  MiniMap2 --> maptypes
  MiniMap2 --> tileUrls
  MiniMap2 --> mp_types
  PointsList[flightPlanning/PointsList.tsx] --> AltitudeDialog2
  PointsList --> mp_utils
  PointsList --> LanguageProvider
  PointsList --> translations
  PointsList --> calcBattery
  PointsList --> calcDistance
  PointsList --> mp_types
  MapView2[flightPlanning/MapView.tsx] --> DrawControl2
  MapView2 --> mp_utils
  MapView2 --> AltitudeDialog2
  MapView2 --> LanguageProvider
  MapView2 --> pointIcons
  MapView2 --> translations
  MapView2 --> actionModes
  MapView2 --> MiniMap2
  MapView2 --> MapPoint2
  MapView2 --> mapIcons
  MapView2 --> maptypes
  MapView2 --> purposes
  MapView2 --> tileUrls
  MapView2 --> mp_types
  LeftBoard[flightPlanning/LeftBoard.tsx] --> LanguageProvider
  LeftBoard --> PointsList
  LeftBoard --> AltitudeChart2
  LeftBoard --> TotalDistance
  LeftBoard --> LanguageSwitcher
  LeftBoard --> translations
  LeftBoard --> actionModes
  LeftBoard --> sidebarIcons
  LeftBoard --> mp_config
  LeftBoard --> mp_types
  flightPlan --> mp_utils
  flightPlan --> MapView2
  flightPlan --> AltitudeDialog2
  flightPlan --> JsonEditorDialog2
  flightPlan --> LeftBoard
  flightPlan --> mp_config
  flightPlan --> actionModes
  flightPlan --> AircraftService
  flightPlan --> phoneIcon
  flightPlan --> purposes
  flightPlan --> mp_types
```

> **Note** — `MiniMap2` imports `UpdateMapCenter` (a *named* helper) **from**
> `MapView2`, while `MapView2` imports `MiniMap2` as a child component. They
> import in opposite directions, which would normally form a dependency
> cycle, but module-level execution is non-circular because each side only
> uses the *type/handle* exposed by the other at call time. **Flagged for
> Step 1** (will document the named export contract precisely) and surfaced
> in §11 below as a structural caveat.

## 8. Cross-feature edges in `src/` (architectural caveats)

These are edges where a "lower-layer" module imports from a "higher-layer"
sibling. Surfaced now so Step 2 (Component Assembly) and Step 2.5
(module-layout.md) can decide whether to formalise them in the layering
table or flag them for the architecture baseline scan (Step 2 of autodev).

| Edge                                                                                | Direction                       | Comment |
|-------------------------------------------------------------------------------------|---------------------------------|---------|
| `components/DetectionClasses.tsx` → `features/annotations/classColors.ts`           | shared ← feature-specific       | A `shared/` component depends on `features/annotations/`. The shared layer should not know about a specific feature. **Likely candidate for refactor**: extract `classColors.ts` into a feature-neutral location (e.g. `src/components/detection/classColors.ts`) or into a `shared/` module. |
| `features/dataset/DatasetPage.tsx` → `features/annotations/CanvasEditor.tsx`        | feature ← sibling feature       | Cross-feature import, but consistent with the legacy WPF design where `Azaion.Dataset` reused `CanvasEditor` from `Azaion.Common.Controls` (see `_docs/legacy/wpf-era.md` §5). The proper fix is to lift `CanvasEditor` out of `features/annotations/` into a shared location. |
| (none observed)                                                                     | back-edge from `App` to `main`  | -       |

Also: every page calls `api/client.ts` directly with **string-literal URLs**
(`/api/admin/auth/login`, `/api/flights?...`, `/api/annotations/settings/user`,
etc.). There is no per-service API client module. This is the testability
issue the workspace `README.md` calls out for Step 4 — but since it does
not yet break compilation or layering, it is recorded here, not blocked.

## 9. Topological processing order — `src/` (40 modules, 8 batches)

Layer = max distance from leaves. Step 1 of `/document` MUST process modules
in this order (leaves first), batched by ~5 with a session-break heuristic
between batches.

> JSON files (`i18n/en.json`, `i18n/ua.json`) and `vite-env.d.ts` are
> **inputs**, not modules — they are not separately documented; their content
> is summarised inside the consumers (`i18n/i18n.ts`, the global TS env).
> Counted modules: 40.

| Batch | Modules                                                                              | Layer |
|-------|--------------------------------------------------------------------------------------|-------|
| **B1** | `types/index.ts`, `hooks/useDebounce.ts`, `hooks/useResizablePanel.ts`, `features/flights/types.ts`, `features/annotations/classColors.ts` | 0     |
| **B2** | `features/flights/mapIcons.ts`, `features/flights/flightPlanUtils.ts`, `api/client.ts`, `i18n/i18n.ts`, `components/HelpModal.tsx` | 0–1   |
| **B3** | `components/ConfirmDialog.tsx`, `components/DetectionClasses.tsx`, `auth/AuthContext.tsx`, `components/FlightContext.tsx`, `api/sse.ts` | 1–2   |
| **B4** | `auth/ProtectedRoute.tsx`, `components/Header.tsx`, `features/login/LoginPage.tsx`, `features/admin/AdminPage.tsx`, `features/settings/SettingsPage.tsx` | 2–3   |
| **B5** | `features/flights/{WaypointList,AltitudeChart,WindEffect,MiniMap,AltitudeDialog}.tsx` | 1–2   |
| **B6** | `features/flights/{MapPoint,DrawControl,FlightListSidebar,JsonEditorDialog,FlightParamsPanel}.tsx` | 2     |
| **B7** | `features/flights/FlightMap.tsx`, `features/annotations/{CanvasEditor,VideoPlayer,AnnotationsSidebar,MediaList}.tsx` | 2–3   |
| **B8** | `features/flights/FlightsPage.tsx`, `features/annotations/AnnotationsPage.tsx`, `features/dataset/DatasetPage.tsx`, `App.tsx`, `main.tsx` | 3–5   |

## 10. Topological processing order — `mission-planner/` (37 modules, 8 batches)

Excluded from analysis: `vite-env.d.ts`, `types/leaflet-polylinedecorator.d.ts`,
`types/react-world-flags.d.ts` (type shims for external libs), `setupTests.ts`,
`App.tsx` (vestigial CRA stub — flagged for delete in §11), and `index.css`,
`*.css` files. The Jest test (`src/test/jsonImport.test.ts`) is documented
inline with `flightPlanning/flightPlan.tsx` (its target), not as a standalone
module. Counted modules: 37.

| Batch | Modules                                                                                                                                       | Layer |
|-------|-----------------------------------------------------------------------------------------------------------------------------------------------|-------|
| **MP-B1** | `types/index.ts`, `utils.ts`, `config.ts`, `constants/{actionModes,maptypes,tileUrls}.ts`                                                 | 0     |
| **MP-B2** | `constants/{translations,languages,purposes}.ts`, `services/{calculateDistance,AircraftService,WeatherService}.ts`                        | 1     |
| **MP-B3** | `services/calculateBatteryUsage.ts`, `flightPlanning/Aircraft.ts`, `flightPlanning/LanguageContext.tsx`, `icons/{MapIcons,PointIcons}.tsx` | 1–2   |
| **MP-B4** | `icons/{SidebarIcons,PhoneIcon}.tsx`, `flightPlanning/{WindEffect,DrawControl,LanguageSwitcher}.tsx`                                       | 2     |
| **MP-B5** | `flightPlanning/{AltitudeChart,AltitudeDialog,JsonEditorDialog,TotalDistance,MapPoint}.tsx`                                                | 2–3   |
| **MP-B6** | `flightPlanning/MapView.tsx` (cycle group with `MiniMap.tsx`), `flightPlanning/MiniMap.tsx`, `flightPlanning/PointsList.tsx`               | 3–4   |
| **MP-B7** | `flightPlanning/LeftBoard.tsx`, `flightPlanning/flightPlan.tsx`                                                                            | 5–6   |
| **MP-B8** | `main.tsx`, `test/jsonImport.test.ts` (analysis only — covered by `flightPlan.tsx` doc)                                                    | 7     |

## 11. Discovery findings to carry forward

The following observations are not documentation gaps; they are **inputs**
for downstream steps. Each lists the step that owns the follow-up.

1. **Workspace `src/` has zero tests.** → Owned by `/test-spec` (Step 3 of autodev) and `/decompose-tests` + `/implement` (Steps 5–6).
2. **Hardcoded API URL paths** (`/api/admin/...`, `/api/flights/...`, `/api/annotations/...`) inlined throughout features. → Testability fix scheduled by autodev Step 4 (workspace `README.md` §"Local development" already calls this out).
3. **No `.env.example` in workspace.** → Same — Step 4.
4. **Cross-layer imports** (§8): `components/DetectionClasses.tsx` → `features/annotations/classColors.ts`, `features/dataset/DatasetPage.tsx` → `features/annotations/CanvasEditor.tsx`. → Surface to autodev Step 2 (Architecture Baseline Scan); the testability refactor (Step 4) may also lift these.
5. **`mission-planner/src/test/jsonImport.test.ts` cannot run** — Jest is not installed and there is no test script. → Out of scope for the live SPA test plan; document in `mission-planner/` component spec but do **not** add Jest just to run this one legacy test.
6. **`mission-planner/src/App.tsx`** is an unused CRA stub; `main.tsx` mounts `FlightPlan` directly. → Note in `mission-planner/` component spec; deletion candidate but only after the `mission-planner` → `src/features/flights/` port is complete (out of `/document` scope).
7. **`mission-planner/src/flightPlanning/MapView.tsx ↔ MiniMap.tsx`** import each other (`MiniMap` imports the *named* `UpdateMapCenter` helper from `MapView`; `MapView` imports `MiniMap` as a JSX child). → Document the contract precisely in Step 1; analyse together as a 2-module group in MP-B6 per the Step 1 cycle-handling rule.
8. **`react-i18next` is used only in workspace `src/`**; `mission-planner/` uses its own `LanguageContext` + raw translation tables. → Capture the divergence in Step 5 (Solution Extraction) — the port to `src/features/flights/` should consume `react-i18next` instead.
9. **No CI test step** in `.woodpecker/build-arm.yml` — only build + push. → To be added by autodev Step 7 (Run Tests) once the test suite exists.
10. **The body of `index.html`** hardcodes Tailwind arbitrary-value classes for the global background and text color rather than using the `az-bg` / `az-text` tokens defined in `src/index.css`. → Cosmetic; record in the workspace component spec but no action required.

---

**Step 0 status**: complete. Proceeding to Step 1 (per-module documentation,
batch B1).
