Updated JWT authentication to use configuration values instead of hardcoded secrets, improving security and flexibility. Enhanced CORS policy to conditionally allow origins based on configuration settings, with logging for permissive defaults. Updated README to reflect project renaming and clarify service context.
15 KiB
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.mdfor 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.csandEnums/FuelType.csare listed inmodule-layout.mdunder01_vehicle_catalogOwns - 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 viaAppDataConnection'sITable<Aircraft>from every feature service) depend on a feature-owned file. If01_vehicle_catalogwere ever extracted to its own assembly, the entity would not compile without inverting the dependency. - Suggested resolution (cheapest first):
- Reassign ownership in
module-layout.md: moveEnums/AircraftType.cs(post-B6:Enums/VehicleType.cs) andEnums/FuelType.csto04_persistenceOwns. They are persisted column types, not feature-private —ObjectStatus.csis already owned by04for the same reason. - Or relocate the files to
Database/Enums/(or keep them inEnums/and just retag ownership) so the layout doc and disk stay aligned.
- Reassign ownership in
- B-ticket interaction: lands cleanly in B6 (domain rename) since B6 already touches
AircraftType→VehicleTypeand addsUGV+GuidedMissilevariants. Re-tagging ownership at the same time is one extramodule-layout.mdedit.
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.csandEnums/WaypointObjective.csare listed inmodule-layout.mdunder02_mission_planningOwns - 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
WaypointSourceandWaypointObjectiveownership to04_persistenceinmodule-layout.md. Both are persisted column types stored asINTEGERin thewaypointstable (seeDatabaseMigrator.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.mdedit at the same time as F1.
F3: Dead using Azaion.Flights.Enums; directive (Low / Maintainability)
- Location:
Database/Entities/Flight.cs:2 - Description:
Flight.csdeclaresusing Azaion.Flights.Enums;but does not reference any type from that namespace (the entity has onlyGuid,DateTime,string,Aircraft,List<Waypoint>fields). - Suggestion: delete the
usingdirective. C#Microsoft.NET.Sdkenables 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.mdif other touch-ups are aggregated, otherwise leave for a future refactor pass.
F4: Three empty scaffolding directories (Low / Maintainability)
- Locations:
Entities/— empty (shadowed byDatabase/Entities/)Infrastructure/— emptyDTOs/Requests/— empty
- Description: each directory exists on disk with no
*.csfiles. They are scaffolding leftovers, already flagged inmodule-layout.md§ Verification Needed #3. With B7 removing GPS-Denied (the historical reason forEntities/andInfrastructure/to be earmarked for orthophoto path resolvers), the rationale for keeping them is gone. - Suggestion:
git rm -rall 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<T>, 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.mdVerification Needed #5 —"FL"policy referenced as a string literal across feature controllers.- F2 in
00_problem/restrictions.md(E3) — hardcoded dev-fallback secrets inProgram.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— confirmscurrent_step: completefor 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.