# Azaion.Missions — Final Documentation Report > **Status**: complete (autodev `/document` Step 7, 2026-05-14). > **Mode**: retrospective documentation of an existing codebase, post-Step 4 verification + Step 4.5 user-confirmed glossary & vision. > **Forward-looking caveat**: every artefact in this set describes the **post-rename, post-GPS-Denied-removal** target. Today's source still uses pre-rename names; the doc-vs-code reconciliation table lives in `04_verification_log.md` § 0 and the implementation deltas are tracked under Jira AZ-EPIC AZ-539 children B4–B12 (see `_docs/_process_leftovers/2026-05-14_rename-flights-to-missions.md`). --- ## Executive Summary `missions` is the edge-tier .NET 10 REST service that owns the mission domain (vehicles, missions, waypoints) of an Azaion deployment. The autodev `/document` skill produced a complete bottom-up documentation set across 8 steps: discovery → 12 module docs → 6 component specs → module-layout (file ownership + 5-layer dependency table) → architecture / system-flows / data-model / deployment → verification (9 inline corrections, 2 drift items captured) → user-confirmed glossary & architecture vision → retrospective solution / problem / restrictions / acceptance-criteria / security-approach. This terminates Phase A Step 1 of the autodev `existing-code` flow; Step 2 (Architecture Baseline Scan) is the next auto-chained step. ## Problem Statement The system is the per-device authority for **vehicle inventory** (Plane / Copter / UGV / GuidedMissile), **mission plans**, and **ordered waypoints** — and is the single orchestrator of the cross-service cascade-delete that keeps `media` / `annotations` / `detection` / `map_objects` consistent when missions or waypoints are removed. It runs as one container per device alongside `annotations`, the detection pipeline, `autopilot`, `gps-denied`, and the React `ui`, sharing one local PostgreSQL with per-service table ownership enforced by convention. JWTs are validated locally with a shared HMAC secret — the service never calls back to the central `admin` issuer. Full statement in `_docs/00_problem/problem.md`. ## Architecture Overview **Pattern**: thin ASP.NET Core controller → service class → linq2db active-record over a per-HTTP-request scoped `AppDataConnection`. No repository abstraction; no in-process message queue / event bus; no background workers. **Technology stack**: C# / .NET 10 (`net10.0`) on ASP.NET Core, linq2db `6.2.0` over PostgreSQL via Npgsql `10.0.2`, JWT bearer (HS256, shared secret), Swashbuckle `10.1.5` (Swagger UI mounted unconditionally — ADR-005). **Deployment**: docker compose per edge device (Jetson Orin / OrangePI / operator-PC); multi-arch ARM64 + AMD64 image built by Woodpecker; Watchtower handles container restarts; `flight-gate` prevents container restart mid-mission; vertical scale only (one instance per device). 8 ADRs (see `architecture.md` § 8): one Postgres per device (ADR-001), PascalCase wire shape carry-forward (ADR-002), manual cascade-delete (ADR-003), `IF NOT EXISTS` schema bootstrap (ADR-004), Swagger + dev fallbacks ungated (ADR-005), cascade-not-transaction-wrapped carry-forward (ADR-006), GPS-Denied moved out (ADR-007), one-csproj layering by convention (ADR-008). ## Component Summary | # | Component | Purpose | Dependencies (logical layer) | Spec / Epic | |---|-----------|---------|------------------------------|-------------| | 01 | `01_vehicle_catalog` | Vehicle CRUD + `is_default` exclusivity (stricter than spec — B12 decision pending) | Layer 3 → `04_persistence`, `05_identity` | suite spec § 6.1; B6 / B12 | | 02 | `02_mission_planning` | Mission + Waypoint CRUD + cross-service cascade-delete walk | Layer 4 → `01_vehicle_catalog` (existence check), `04_persistence`, `05_identity`, `06_http_conventions` | suite spec § 6.2; B6 / B7 / B8 | | 04 | `04_persistence` | `AppDataConnection` (linq2db `ITable`) + `DatabaseMigrator` (`CREATE TABLE IF NOT EXISTS` + B9 one-shot `DROP`) | Layer 1 → linq2db + Npgsql only | B7 / B9 | | 05 | `05_identity` | `JwtExtensions.AddJwtAuth` — HS256 local validation + `"FL"` policy | Layer 2 → ASP.NET Core only | suite-level remediation (AZ-487/AZ-494 carry-forward) | | 06 | `06_http_conventions` | `ErrorHandlingMiddleware` + `PaginatedResponse` + dead `ErrorResponse` DTO | Layer 2 → ASP.NET Core only | ADR-002 carry-forward | | 07 | `07_host` | `Program.cs` composition root: env adapter, JWT registration, scoped DI, run migrator, register middleware, `MapGet("/health")`, mount Swagger | Layer 5 → every other component | B5 (csproj rename) / B10 (image tag) | **Implementation order** (based on dependency graph in `module-layout.md`): 1. **Layer 1**: `04_persistence` — depends only on linq2db + Npgsql. 2. **Layer 2**: `05_identity`, `06_http_conventions` — depend on ASP.NET Core only. 3. **Layer 3**: `01_vehicle_catalog`. 4. **Layer 4**: `02_mission_planning` (reads `vehicles` for existence checks; uses `PaginatedResponse`). 5. **Layer 5**: `07_host` (composition root). No circular dependencies between components. ## System Flows | Flow | Description | Key components | Criticality | |------|-------------|----------------|-------------| | F1 | Vehicle CRUD | `01_vehicle_catalog` → `04_persistence` | High | | F2 | Mission create / read / update with `vehicle_id` existence check | `02_mission_planning` → `04_persistence`, with `01_vehicle_catalog` lookup | High | | F3 | Mission delete with cross-service cascade (touches `map_objects`, `media`, `annotations`, `detection`, `waypoints`, `missions`) | `02_mission_planning` → `04_persistence` + cross-service tables | **Critical** (data integrity; not transaction-wrapped today — ADR-006) | | F4 | Waypoint CRUD (delete is a scoped F3 cascade) | `02_mission_planning` (`WaypointService`) → `04_persistence` | High | | F5 | JWT bearer validation (cross-cutting; local HS256 only) | `05_identity` (pipeline middleware) | **Critical** (every authenticated route) | | F6 | Service startup + idempotent schema migration (B9 one-shot `DROP TABLE IF EXISTS` for fielded legacy devices) | `07_host` → `04_persistence` | High | | F7 | Anonymous `GET /health` probe (process-liveness only; no DB ping) | `07_host` | Medium | Full sequences and per-flow Mermaid diagrams in `system-flows.md` and `diagrams/flows/flow_*.md`. ## Risk Summary The codebase has no automated tests today, so "risks" here are **observed-from-code carry-forward concerns** (architecture.md § Carry-forward + 00_discovery.md § Spec ↔ Code Divergences), classified by impact. Mitigation column points at the responsible Jira child or the suite-level ticket. | Level | Count | Items | |-------|-------|-------| | Critical | 1 | Cascade-delete is **NOT transaction-wrapped** (ADR-006) — partial failure leaves orphan rows. **One-line fix**, recommended to land with B6 | | High | 3 | (a) `JWT_SECRET` / `DATABASE_URL` dev fallbacks not gated on `IsDevelopment()` (ADR-005, suite-tracked); (b) JWT `iss`/`aud` validation disabled (CMMC L2 row 3, AZ-487/AZ-494 suite-tracked); (c) Wire-shape divergence — entity/DTO bodies PascalCase, error envelope missing `errors` field (ADR-002 carry-forward) | | Medium | 4 | (a) "Exactly one default vehicle" stricter than spec + race-prone (B12 / AZ-551 — decision-only ticket); (b) `vehicle_id`-not-found returns 400 instead of spec's 404 (carry-forward); (c) Swagger UI mounted unconditionally (ADR-005); (d) CORS open in all environments (carry-forward) | | Low | 4 | (a) `ErrorResponse` DTO is dead on the wire and has wrong shape; (b) `Geopoint` stored as 3 flat columns instead of spec's auto-converting `string GPS`; (c) `FL` permission code retains legacy "Flight" wording post-rename (suite-level fleet-wide change); (d) `FuelType` enum may not fit single-use `GuidedMissile` | **Mitigation status**: every Critical/High item is either covered by an open Jira ticket (B6, B12, AZ-487/AZ-494) or explicitly logged as a suite-level carry-forward in `04_verification_log.md`. No Critical/High item is unaccounted for. ## Test Coverage **No automated tests exist today.** Verification of every documented behaviour is by code inspection only. The autodev `existing-code` flow's Phase A Steps 3 → 7 is the planned path to convert `_docs/00_problem/acceptance_criteria.md` (10 AC groups, ~60 individual criteria) into runnable test cases. | Component | Integration | Performance | Security | Acceptance | AC coverage today | |-----------|-------------|-------------|----------|------------|-------------------| | `01_vehicle_catalog` | 0 | 0 | 0 | 0 | AC-1 (9 criteria) — inspection only | | `02_mission_planning` | 0 | 0 | 0 | 0 | AC-2 (8) + AC-3 (7) + AC-4 (7) — inspection only | | `04_persistence` | 0 | 0 | 0 | 0 | AC-6 (10) — inspection only | | `05_identity` | 0 | 0 | 0 | 0 | AC-5 (9) + AC-9 (4) — inspection only | | `06_http_conventions` | 0 | 0 | 0 | 0 | AC-8 (7) — inspection only | | `07_host` | 0 | 0 | 0 | 0 | AC-6 (10) + AC-7 (4) + AC-10 (6) — inspection only | **Overall AC coverage by automated tests**: 0 / ~60 (0%) — the gap that Phase A Steps 3–7 will close. ## Rename Epic Roadmap (Jira AZ-EPIC AZ-539) The full doc-vs-code rename + GPS-Denied removal is tracked as one Jira Epic + 12 child tickets. B1–B3 (the documentation half) landed in this turn; B4–B12 (the code half) are still **To Do**. | Order | Plan ID | Jira | Type | SP | Status | Component / artefact | |-------|---------|------|------|----|--------|-----------------------| | Epic | — | [AZ-539](https://denyspopov.atlassian.net/browse/AZ-539) | Epic | — | To Do | umbrella | | 1 | B1 | [AZ-540](https://denyspopov.atlassian.net/browse/AZ-540) | Task | 3 | **Done** (this turn) | local docs (this repo's `_docs/`) | | 2 | B2 | [AZ-541](https://denyspopov.atlassian.net/browse/AZ-541) | Task | 3 | **Done** (this turn) | suite docs (`../../suite/_docs/`) | | 3 | B3 | [AZ-542](https://denyspopov.atlassian.net/browse/AZ-542) | Task | 3 | **Done** (this turn) | local + suite state bookkeeping | | 4 | B4 | [AZ-543](https://denyspopov.atlassian.net/browse/AZ-543) | Task | 3 | To Do | repo rename (Gitea + suite `.gitmodules` + `git mv`) | | 5 | B5 | [AZ-544](https://denyspopov.atlassian.net/browse/AZ-544) | Story | 3 | To Do | csproj + namespace `Azaion.Flights` → `Azaion.Missions` | | 6 | B6 | [AZ-545](https://denyspopov.atlassian.net/browse/AZ-545) | Story | 5 | To Do | domain rename `Aircraft → Vehicle`, `Flight → Mission`, `AircraftType → VehicleType { Plane, Copter, UGV, GuidedMissile }` | | 7 | B7 | [AZ-546](https://denyspopov.atlassian.net/browse/AZ-546) | Story | 3 | To Do | drop GPS-Denied entities, `"GPS"` policy, cascade branches, migrator entries | | 8 | B8 | [AZ-547](https://denyspopov.atlassian.net/browse/AZ-547) | Story | 3 | To Do | HTTP routes `/aircrafts → /vehicles`, `/flights → /missions` | | 9 | B9 | [AZ-548](https://denyspopov.atlassian.net/browse/AZ-548) | Story | 5 | To Do | DB migration: `ALTER TABLE` rename + `DROP TABLE IF EXISTS` for legacy GPS-Denied | | 10 | B10 | [AZ-549](https://denyspopov.atlassian.net/browse/AZ-549) | Task | 2 | To Do | Dockerfile entrypoint + Woodpecker image tag + suite compose service block | | 11 | B11 | [AZ-550](https://denyspopov.atlassian.net/browse/AZ-550) | Story | 5 | To Do | consumer cutover (autopilot + ui + suite e2e) | | 12 | B12 | [AZ-551](https://denyspopov.atlassian.net/browse/AZ-551) | Task | 2 | To Do | decision-only: lift "exactly one default" into spec + transaction-wrap, OR drop from code | **Total estimated effort (remaining)**: 35 SP across 9 To-Do tickets. Implementation order has hard dependencies (B5 → B6 → B7 → B8 → B9 → B10 → B11; B4 ride-along; B12 independent decision). ## Key Decisions Made (during documentation) | # | Decision | Rationale | Alternatives rejected | |---|----------|-----------|------------------------| | 1 | Document the **post-rename** target rather than today's pre-rename source | Aligns with the user's intended end state and the Jira Epic; avoids documenting code that's about to be deleted (B7) | (a) Document today's code as-is — rejected: would require a near-total rewrite the moment B5–B7 land. (b) Document both — rejected: doubles maintenance burden until B5–B7 ship | | 2 | Each forward-looking doc carries an explicit "post-rename" note pointing at the responsible Jira child | Future readers can reconcile what they see in code against the doc without re-running discovery | Implicit forward-looking — rejected: too easy to mistake a doc for current state | | 3 | Treat the verification step as **rename-aware** | The doc-vs-code rename mapping is captured once in `04_verification_log.md` § 0; mismatches not covered by the mapping are the only flagged drift | Treat every rename as a verification failure — rejected: would flag every entity name and produce noise | | 4 | Component count went 7 → 6 (dropped `03_gps_denied`) and `01_aircraft_catalog` → `01_vehicle_catalog` | Matches the post-rename suite spec; logged in `state.json.decomposition_revised` | Keep 7 with `03_gps_denied` as deprecated — rejected: would conflict with B7's removal scope | | 5 | `architecture.md` § "Architecture Vision" + `glossary.md` were both confirmed by the user (Step 4.5) | Downstream skills (refactor, decompose, new-task) treat these as authoritative | Skip the glossary — rejected: existing-code projects benefit most from explicit terminology reconciliation | | 6 | Solution / problem / restrictions / acceptance / security all describe **today's behaviour with carry-forward divergences explicitly called out** | Tests against the docs will catch unintended behaviour changes; spec-conformance fixes are intentional | Rewrite the docs to match the suite spec — rejected: would misrepresent the running code | ## Open Questions (for Phase A Step 2 onward) | # | Question | Impact | Where it surfaces next | |---|----------|--------|-------------------------| | 1 | Will B12 / AZ-551 lift "exactly one default vehicle" into spec (with transaction-wrap) or drop the rule from code? | AC-1.2 / AC-1.3 / AC-1.4 will change shape; the F1 test scenarios in Step 3 will pin whichever resolution the user picks | B12 / AZ-551 ticket | | 2 | Should B6 also land the cascade transaction-wrap (ADR-006 carry-forward, one-line fix)? | Closes the only Critical risk; B6 is a rename pass and the transaction wrap can ride along cheaply | B6 / AZ-545 review | | 3 | When does the suite-wide camelCase wire-shape migration happen (ADR-002 carry-forward)? | Affects every `Mission` / `Vehicle` / `PaginatedResponse` consumer (UI + autopilot); not in this Epic | Suite-level ticket (not yet filed) | | 4 | Does `gps-denied` need to be deployed BEFORE B9's `DROP TABLE IF EXISTS` runs on fielded devices? | Out-of-band ordering matters: AC-10.5; F6 error scenario | B9 / B10 acceptance review | | 5 | Will B11 cover any other consumers besides UI + autopilot? | Determines B11 scope | B11 / AZ-550 review | These do not block Step 2 (Architecture Baseline Scan); they are inputs to subsequent test-spec / refactor / new-task work. ## Artifact Index ### Documentation (this repo, `_docs/`) | File | Description | |------|-------------| | `_docs/00_problem/problem.md` | High-level problem statement (post-rename target) | | `_docs/00_problem/restrictions.md` | Hardware / software / environment / operational restrictions (4 categories, 41 items) | | `_docs/00_problem/acceptance_criteria.md` | 10 AC groups (~60 criteria), every criterion grounded in code | | `_docs/00_problem/input_data/data_parameters.md` | Env vars, HTTP DTOs, table schemas (4 owned + 3 borrowed), enum values, endpoint matrix | | `_docs/00_problem/security_approach.md` | Authn / authz / data protection / input validation / CORS / 8 production-deploy footguns / threat-model summary | | `_docs/01_solution/solution.md` | Retrospective solution: per-component table + cross-cutting choices + implementation order + testing strategy | | `_docs/02_document/00_discovery.md` | Suite context, repository layout, tech stack, entry points, configuration, dependency graph (5 layers), spec ↔ code divergences (15 items) | | `_docs/02_document/04_verification_log.md` | Step 4 verification: rename-aware mode, counts, per-symbol sweep, drift mapping table | | `_docs/02_document/architecture.md` | Architecture (Vision + 8 sections + 8 ADRs); confirmed by user at Step 4.5 | | `_docs/02_document/system-flows.md` | F1–F7 narrative + cross-cutting concerns + per-flow error tables | | `_docs/02_document/data_model.md` | Entity / table / cross-service ownership map | | `_docs/02_document/glossary.md` | Glossary; confirmed by user at Step 4.5 | | `_docs/02_document/module-layout.md` | File ownership + 5-layer dependency table; status `derived-from-code` | | `_docs/02_document/components/01_vehicle_catalog/description.md` | Component spec (post-rename) | | `_docs/02_document/components/02_mission_planning/description.md` | Component spec | | `_docs/02_document/components/04_persistence/description.md` | Component spec | | `_docs/02_document/components/05_identity/description.md` | Component spec | | `_docs/02_document/components/06_http_conventions/description.md` | Component spec | | `_docs/02_document/components/07_host/description.md` | Component spec | | `_docs/02_document/modules/{auth,controller_missions,controller_vehicles,database,dtos,entities,enums,middleware,program,service_mission,service_vehicle,service_waypoint}.md` | 12 module docs | | `_docs/02_document/diagrams/components.md` | Mermaid component relationship diagram | | `_docs/02_document/diagrams/flows/flow_{vehicle_crud,mission_lifecycle,mission_cascade_delete,waypoint_lifecycle,jwt_validation,startup_migration,health_probe}.md` | Per-flow Mermaid sequence diagrams | | `_docs/02_document/deployment/{containerization,ci_cd_pipeline,environment_strategy,observability}.md` | Deployment notes | ### State / process artefacts | File | Description | |------|-------------| | `_docs/_autodev_state.md` | Autodev orchestrator state (this skill: Phase A Step 1, complete on Step 7 write) | | `_docs/02_document/state.json` | Document skill internal state | | `_docs/_process_leftovers/2026-05-14_rename-flights-to-missions.md` | Rename leftover index — kept until B4–B12 ship | | `_docs/tasks/done/AZ-540_missions_rename_b1_local_docs.md` | B1 task spec (Done) | | `_docs/tasks/done/AZ-542_missions_rename_b3_state_bookkeeping.md` | B3 task spec (Done) | | `_docs/tasks/todo/AZ-544_missions_rename_b5_csproj_namespace.md` | B5 task spec | | `_docs/tasks/todo/AZ-545_missions_rename_b6_domain_rename.md` | B6 task spec | | `_docs/tasks/todo/AZ-546_missions_rename_b7_drop_gps_denied.md` | B7 task spec | | `_docs/tasks/todo/AZ-547_missions_rename_b8_http_routes.md` | B8 task spec | | `_docs/tasks/todo/AZ-548_missions_rename_b9_db_migration.md` | B9 task spec | | `_docs/tasks/todo/AZ-551_missions_rename_b12_default_vehicle_rule.md` | B12 task spec | ### Suite-level cross-references (read-only from this repo) | File | Description | |------|-------------| | `../../suite/_docs/02_missions.md` | Primary spec (post-rename) | | `../../suite/_docs/00_top_level_architecture.md` | Topology, error envelope, pagination | | `../../suite/_docs/00_database_schema.md` | Authoritative ER diagram | | `../../suite/_docs/00_roles_permissions.md` | `FL` permission origin | | `../../suite/_docs/11_gps_denied.md` | Separate `gps-denied` service (post-B7) | | `../../suite/_docs/05_security/cmmc_l2_scorecard.md` | CMMC L2 row 3 finding (AZ-487/AZ-494) | | `../../suite/_docs/_repo-config.yaml` | Repo registry (post-rename `name: missions`) | ## Next Step in the Autodev Existing-Code Flow Phase A Step 2 — **Architecture Baseline Scan**: invoke `code-review/SKILL.md` in baseline mode (Phase 1 + Phase 7) against the full codebase, save the output to `_docs/02_document/architecture_compliance_baseline.md`. The scan compares the running code against the just-confirmed `architecture.md` + `module-layout.md` and flags pre-existing High/Critical structural issues. After the baseline is clean, the autodev auto-chains to Step 3 (Test Spec) — which produces `_docs/02_document/tests/traceability-matrix.md` and per-flow scenario files for F1–F7, the seed set for the test suite implementation in Steps 5–7.