# Architecture Compliance Baseline **Mode**: code-review baseline (Phase 1 + Phase 7) **Date**: 2026-05-14 **Scope**: full pre-rename codebase (`Azaion.Flights.csproj`, root namespace `Azaion.Flights.*`) **Spec**: `_docs/02_document/architecture.md` + `_docs/02_document/module-layout.md` **Verdict**: **PASS_WITH_WARNINGS** (2 High Architecture findings — both resolved 2026-05-14 via doc retag, see "Resolution applied" below; 0 Critical, 0 cycles) ## Resolution applied (2026-05-14) F1 and F2 were resolved in-band by a one-edit retag in `_docs/02_document/module-layout.md`: the four persisted-column enums (`VehicleType` / `AircraftType`, `FuelType`, `WaypointSource`, `WaypointObjective`) are now owned by `04_persistence` (matching how `ObjectStatus` was already tagged), eliminating the Foundation ← Feature import violation without touching code. The `using Azaion.Flights.Enums;` directive in `Database/Entities/Aircraft.cs` and `Database/Entities/Waypoint.cs` is now an intra-component reference. F3 and F4 remain open as Low-severity items — see "Recommendations for downstream steps" at the bottom. > **Reading guide**: this is a one-time scan of the *current* code against the *post-rename* architecture documented in `architecture.md` + `module-layout.md`. Pre-rename divergences (`Azaion.Flights.*` namespace, `Aircraft*`/`Flight*`/`Orthophoto*`/`GpsCorrection*` filenames, `[Route("aircrafts"|"flights")]`, 6-table migrator, `"GPS"` policy) are explicitly NOT findings — they are tracked under Jira AZ-EPIC children **B5 (namespace), B6 (domain rename), B7 (drop GPS-Denied), B8 (HTTP routes), B9 (DB migration)**. See `_docs/_process_leftovers/2026-05-14_rename-flights-to-missions.md` for the full rename index. The findings below are *layering* / *structural* observations that survive the rename and that downstream skills (Step 4 testability refactor, Step 8 optional refactor) need to know about. ## Scope of the scan **Files scanned (37 total)**: every `*.cs` under the repo root, excluding `bin/` and `obj/`. Source layout is layer-organized at the repo root (no `src/`); component ownership is by file-path glob per `module-layout.md` § Per-Component Mapping. **Phase 7 checks performed**: | Check | Source of truth | Approach | |-------|-----------------|----------| | Layer direction (no upward imports) | `module-layout.md` § Allowed Dependencies (Foundation 1 ← Feature 3 ← Composition 4) | Parsed every `using Azaion.Flights.*` directive; mapped importer/importee files to their components per the Owns globs; flagged any importer-layer < importee-layer pair | | Public API respect (no internal imports) | `module-layout.md` § Per-Component Mapping (`Public API` rows) | The codebase has no per-component compiled public API surface (one csproj, one root namespace, no per-component `internal`). All same-namespace types are reachable. The check degenerates to "do feature components reach into another feature's files?" — none do | | New cyclic module dependencies | Import graph | Built the per-component import graph (7 nodes today including `03_gps_denied`-leftover entities, 6 post-B7); checked for cycles | | Duplicate symbols across components | Class/function name index | Walked every `class`/`record`/`static class`; cross-checked names against other components | | Cross-cutting re-implementation | Architecture.md § 7 (auth/middleware/persistence ownership) | Searched feature components for inline JWT setup, custom error envelope writers, ad-hoc DB connection construction | ## Findings | # | Severity | Category | File:Line | Title | |---|----------|----------------|------------------------------------|------------------------------------------------------| | 1 | High | Architecture | `Database/Entities/Aircraft.cs:2` | Foundation entity imports feature-component enums | | 2 | High | Architecture | `Database/Entities/Waypoint.cs:2` | Foundation entity imports feature-component enums | | 3 | Low | Maintainability| `Database/Entities/Flight.cs:2` | Dead `using Azaion.Flights.Enums;` directive | | 4 | Low | Maintainability| `Entities/`, `Infrastructure/`, `DTOs/Requests/` | Three empty scaffolding directories at repo root | **No findings** for: cyclic module dependencies, public-API bypass, duplicate symbols across components, cross-cutting re-implementation. Layer-direction is clean apart from the two enum-ownership cases below. ## Finding Details ### F1: Foundation entity imports feature-component enums (High / Architecture) - **Location**: `Database/Entities/Aircraft.cs:2` — `using Azaion.Flights.Enums;` - **Importer component**: `04_persistence` (Foundation, Layer 1) - **Importee component**: `01_vehicle_catalog` (Feature, Layer 3) — `Enums/AircraftType.cs` and `Enums/FuelType.cs` are listed in `module-layout.md` under `01_vehicle_catalog` Owns - **Symbols used**: `AircraftType` (line 14), `FuelType` (line 23) - **Why it matters**: `module-layout.md` § Allowed Dependencies declares Foundation may NOT import from Feature surfaces. The current entity references make a structural foundation file (loaded via `AppDataConnection`'s `ITable` from every feature service) depend on a *feature-owned* file. If `01_vehicle_catalog` were ever extracted to its own assembly, the entity would not compile without inverting the dependency. - **Suggested resolution** (cheapest first): 1. **Reassign ownership** in `module-layout.md`: move `Enums/AircraftType.cs` (post-B6: `Enums/VehicleType.cs`) and `Enums/FuelType.cs` to `04_persistence` Owns. They are *persisted column types*, not feature-private — `ObjectStatus.cs` is already owned by `04` for the same reason. 2. **Or relocate the files** to `Database/Enums/` (or keep them in `Enums/` and just retag ownership) so the layout doc and disk stay aligned. - **B-ticket interaction**: lands cleanly in **B6** (domain rename) since B6 already touches `AircraftType` → `VehicleType` and adds `UGV` + `GuidedMissile` variants. Re-tagging ownership at the same time is one extra `module-layout.md` edit. ### F2: Foundation entity imports feature-component enums (High / Architecture) - **Location**: `Database/Entities/Waypoint.cs:2` — `using Azaion.Flights.Enums;` - **Importer component**: `04_persistence` (Foundation, Layer 1) - **Importee component**: `02_mission_planning` (Feature, Layer 3) — `Enums/WaypointSource.cs` and `Enums/WaypointObjective.cs` are listed in `module-layout.md` under `02_mission_planning` Owns - **Symbols used**: `WaypointSource` (line 26), `WaypointObjective` (line 29) - **Why it matters**: same as F1 — Layer 1 file depends on Layer 3 file. Same fix shape. - **Suggested resolution**: reassign `WaypointSource` and `WaypointObjective` ownership to `04_persistence` in `module-layout.md`. Both are persisted column types stored as `INTEGER` in the `waypoints` table (see `DatabaseMigrator.cs:38-39`); they are domain enums, not feature-internal toggles. - **B-ticket interaction**: orthogonal to B6 (rename only). Can land standalone as a one-line `module-layout.md` edit at the same time as F1. ### F3: Dead `using Azaion.Flights.Enums;` directive (Low / Maintainability) - **Location**: `Database/Entities/Flight.cs:2` - **Description**: `Flight.cs` declares `using Azaion.Flights.Enums;` but does not reference any type from that namespace (the entity has only `Guid`, `DateTime`, `string`, `Aircraft`, `List` fields). - **Suggestion**: delete the `using` directive. C# `Microsoft.NET.Sdk` enables the analyzer that flags this in IDE; CI is not configured to fail on it today, hence it has slipped in. - **B-ticket interaction**: trivial cleanup; goes into the testability `list-of-changes.md` if other touch-ups are aggregated, otherwise leave for a future refactor pass. ### F4: Three empty scaffolding directories (Low / Maintainability) - **Locations**: - `Entities/` — empty (shadowed by `Database/Entities/`) - `Infrastructure/` — empty - `DTOs/Requests/` — empty - **Description**: each directory exists on disk with no `*.cs` files. They are scaffolding leftovers, already flagged in `module-layout.md` § Verification Needed #3. With B7 removing GPS-Denied (the historical reason for `Entities/` and `Infrastructure/` to be earmarked for orthophoto path resolvers), the rationale for keeping them is gone. - **Suggestion**: `git rm -r` all three as part of B5 (csproj/namespace) or a follow-up cleanup. No code-side impact; small clarity win for new contributors who currently have to scan three empty directories before realising they are noise. - **B-ticket interaction**: cleanest as a B5 add-on (B5 already touches the project file structure). Otherwise standalone. ## Cyclic dependencies **None detected** at the component level. Intra-component bidirectional `[Association]` annotations exist in `04_persistence` (`Flight ↔ Aircraft`, `Flight ↔ Waypoint`) but those are within a single component and are the normal linq2db pattern. The cross-feature reads in `AircraftService.DeleteAircraft` (reads `db.Flights`) and `FlightService.CreateFlight` / `UpdateFlight` (reads `db.Aircrafts`) go *through* the foundation `AppDataConnection`, not directly across feature boundaries — graph remains acyclic at component granularity (`01 → 04 ← 02`, not `01 ↔ 02`). ## Public API respect Not applicable in the strict sense: `module-layout.md` declares "no per-component public-API file; types referenced directly" because the codebase is one csproj / one root namespace (ADR-008). All same-namespace types are reachable from every other file. The intent of this check — "no feature-component reaches into another feature's internals" — is satisfied: the only cross-feature flow is `02_mission_planning` reading `db.Aircrafts`/`db.Flights` via the foundation `AppDataConnection`, which is the explicit per-component-mapping-blessed path. ## Duplicate symbols across components None. Class names (`Aircraft`, `Flight`, `Waypoint`, `Vehicle`-post-B6, `Mission`-post-B6, `MapObject`, `Media`, `Annotation`, `Detection`, `Orthophoto`-pre-B7, `GpsCorrection`-pre-B7, `AppDataConnection`, `DatabaseMigrator`, `JwtExtensions`, `ErrorHandlingMiddleware`, `PaginatedResponse`, `ErrorResponse`, every `Create*Request` / `Update*Request` / `Get*Query` DTO) all unique within the repo. ## Cross-cutting concerns No re-implementation found. JWT setup lives only in `Auth/JwtExtensions.cs` (`05_identity`). Error envelope is written only in `Middleware/ErrorHandlingMiddleware.cs` (`06_http_conventions`) — note the unused `DTOs/ErrorResponse.cs` is owned by `06` and is dead-on-the-wire, not a re-implementation. DB connection is constructed only in `Program.cs` and resolved everywhere else from DI (`07_host` → `04_persistence`). ## Pre-rename divergences (NOT findings — tracked under B-tickets) For traceability, the following items would be reported as Architecture findings if read against `architecture.md` literally, but are **explicitly excluded** because they are the Jira AZ-EPIC scope: | Tracked under | Pre-rename state in code | Post-rename target in docs | |---------------|--------------------------|----------------------------| | **B5** | `Azaion.Flights.csproj` + `namespace Azaion.Flights.*` | `Azaion.Missions.csproj` + `namespace Azaion.Missions.*` | | **B6** | `Aircraft*` / `Flight*` filenames; `AircraftType { Plane, Copter }` enum | `Vehicle*` / `Mission*` filenames; `VehicleType { Plane, Copter, UGV, GuidedMissile }` | | **B7** | `Database/Entities/Orthophoto.cs` + `GpsCorrection.cs` exist; `AppDataConnection.Orthophotos` / `GpsCorrections` ITables exist; `FlightService.DeleteFlight` cascades into `orthophotos` + `gps_corrections`; `WaypointService.DeleteWaypoint` cascades into `gps_corrections`; `JwtExtensions.cs` registers a `"GPS"` policy that no controller uses | All of the above removed; one `"FL"` policy only | | **B8** | `[Route("aircrafts")]`, `[Route("flights")]` on controllers | `[Route("vehicles")]`, `[Route("missions")]` | | **B9** | `DatabaseMigrator` creates 6 tables (`aircrafts`, `flights`, `waypoints`, `orthophotos`, `gps_corrections`, `map_objects`) | 4 tables (`vehicles`, `missions`, `waypoints`, `map_objects`) + one-shot `DROP TABLE IF EXISTS orthophotos / gps_corrections` for fielded devices | Code that does NOT diverge from the architecture doc and is therefore production-correct today (apart from the rename labels): the layering structure (Controllers → Services → AppDataConnection), the per-request scoped `DataConnection`, the `ErrorHandlingMiddleware` exception → status mapping, the JWT validation pattern, the migrator idempotency, and the cascade-delete *order* (only the `orthophotos` / `gps_corrections` *branches* of the cascade go away in B7). ## Carry-forward concerns already in `architecture.md` (NOT new findings) Re-stated here only so the reader can confirm they were considered during the scan and intentionally not re-raised: - ADR-006 — cascade delete is not transaction-wrapped. Already a recommended one-line fix to land with B6. - ADR-005 — Swagger + dev fallbacks not gated on `IsDevelopment()`. - ADR-002 — PascalCase entity wire shape vs spec's camelCase. Coordinated suite-wide cutover, not in this Epic. - `module-layout.md` Verification Needed #5 — `"FL"` policy referenced as a string literal across feature controllers. - F2 in `00_problem/restrictions.md` (E3) — hardcoded dev-fallback secrets in `Program.cs`. ## Recommendations for downstream steps | Step | Recommended action | |------|--------------------| | **Step 4 — Code Testability Revision** | Append F3 (dead `using` in `Flight.cs`) to the testability `list-of-changes.md` since the file will likely be touched by B6 anyway. Do NOT include F1/F2 — they are layout-doc edits, not code edits, and conflating them with the testability surgical scope risks scope creep. | | **Step 5 — Decompose Tests** | No baseline-driven action. Test specs are not affected by the layering doc. | | **Step 6 — Implement Tests** | No baseline-driven action. | | **Step 8 — Refactor (optional)** | Resolve F1 and F2 by reassigning enum ownership in `module-layout.md` (one Markdown edit). Optionally physically relocate the four enum files into `Database/Enums/` if a second-pass refactor wants disk-and-doc alignment. F4 (delete empty scaffolding dirs) and the carry-forward ADRs above are also reasonable Step 8 candidates. | ## Phase 1 inputs read (for traceability) - `_docs/02_document/architecture.md` — Architecture Vision, layering rules, ADRs, NFRs - `_docs/02_document/module-layout.md` — Per-Component Mapping, Allowed Dependencies, Verification Needed - `_docs/00_problem/restrictions.md` — restrictions S1–S15 (pinned tech stack, layout convention) - `_docs/02_document/state.json` — confirms `current_step: complete` for documentation - `_docs/_process_leftovers/2026-05-14_rename-flights-to-missions.md` — confirms which divergences are tracked under B-tickets and therefore NOT findings here No project-side `restrictions.md` over-ride applies. `_docs/01_solution/solution.md` exists and was *not* read because the baseline scan is structural and Phase 1 explicitly limits to architecture + layout + restrictions.