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.
12 KiB
Module Layout
Status: derived-from-code (post-rename, forward-looking — see Verification Needed)
Language: csharp
Layout Convention: custom (layer-organized, NOT per-component-directory — see ## Verification Needed below)
Root: ./ (no src/ directory; .NET Microsoft.NET.Sdk.Web project at the repo root)
Last Updated: 2026-05-14
NOTE (forward-looking): file paths reflect the post-rename + post-GPS-Denied-removal state. Today's source still uses
Aircraft*/Flight*/Orthophoto*/GpsCorrection*filenames, csproj isAzaion.Flights.csproj, and namespace isAzaion.Flights.*. Renames + drops are tracked under Jira AZ-EPIC children B5 (namespace), B6 (rename), B7 (GPS-Denied removal), B8 (HTTP routes), B9 (DB migration), B10 (Dockerfile / image / compose).
Layout Rules
This codebase does not follow the "one directory per component" convention from the template. It is organized horizontally by architectural layer:
./
├── Auth/ ← cross-cutting (component 05_identity)
├── Controllers/ ← API surface (one file per feature component, 01 + 02)
├── Database/ ← persistence (component 04)
│ └── Entities/
├── DTOs/ ← payload types (split across components 01, 02, 06)
├── Enums/ ← domain enums (split across components 01, 02, 04)
├── Middleware/ ← cross-cutting (component 06_http_conventions)
├── Services/ ← business logic (one file per feature component, 01 + 02)
├── Entities/ ← EMPTY (scaffolding leftover)
├── Infrastructure/ ← EMPTY (scaffolding leftover)
├── Program.cs ← composition root (component 07_host)
└── GlobalUsings.cs ← composition root (component 07_host)
Consequence: each component's Owns glob is a SET OF FILE PATHS spanning multiple directories, NOT a single directory glob. There is no shared/ directory; cross-cutting concerns (05_identity, 06_http_conventions) own their root-level dirs (Auth/, Middleware/) directly.
The C# project has no separate per-component csproj — there is one project (post-rename: Azaion.Missions.csproj; today: Azaion.Flights.csproj) and effectively one root namespace (post-rename: Azaion.Missions.*). Other components reference each other through types directly; there is no compiled "Public API" boundary.
Per-Component Mapping
Component: 01_vehicle_catalog
- Epic: Jira AZ-EPIC (rename + multi-vehicle support)
- Directory(ies): spread across
Controllers/,Services/,DTOs/,Enums/ - Public API (types other components reference):
Services/VehicleService.cs(consumed by07_hostfor DI registration;02_mission_planningconsumes its existence semantics through the DB) - Owns (exclusive write) (post-rename):
Controllers/VehiclesController.csServices/VehicleService.csDTOs/CreateVehicleRequest.csDTOs/UpdateVehicleRequest.csDTOs/GetVehiclesQuery.csDTOs/SetDefaultRequest.cs
- Internal: none — every file is publicly importable in C# without explicit visibility annotations
- Imports from:
04_persistence(AppDataConnection,Vehicleentity,VehicleTypeenum,FuelTypeenum),05_identity([Authorize(Policy = "FL")]),06_http_conventions(exception → middleware mapping is implicit) - Consumed by:
02_mission_planning(FK existence-check onvehicle_id),07_host(DI registration)
Component: 02_mission_planning
- Epic: Jira AZ-EPIC
- Directory(ies): spread across
Controllers/,Services/,DTOs/,Enums/ - Public API (post-rename):
Services/MissionService.cs,Services/WaypointService.cs(DI-registered in07_host) - Owns (exclusive write) (post-rename):
Controllers/MissionsController.csServices/MissionService.csServices/WaypointService.csDTOs/CreateMissionRequest.csDTOs/UpdateMissionRequest.csDTOs/GetMissionsQuery.csDTOs/CreateWaypointRequest.csDTOs/UpdateWaypointRequest.csDTOs/GeoPoint.cs
- Internal: none
- Imports from:
04_persistence(incl.WaypointSource+WaypointObjectiveenums),05_identity,06_http_conventions(PaginatedResponse<T>),01_vehicle_catalog(existence semantics through DB FK) - Consumed by:
07_host(DI), and externalautopilot/ui(cross-service over HTTP)
Component: 04_persistence
- Epic: Jira AZ-EPIC
- Directory(ies):
Database/, plusEnums/ObjectStatus.cs(cross-cutting status enum) - Public API:
Database/AppDataConnection.cs(theDataConnectiontype other components depend on),Database/DatabaseMigrator.cs(called by07_hostat startup), all 7 entities underDatabase/Entities/(referenced by services + DTOs as row maps), the four persisted-column enums underEnums/(VehicleType,FuelType,WaypointSource,WaypointObjective,ObjectStatus) - Owns (exclusive write) (post-rename):
Database/AppDataConnection.csDatabase/DatabaseMigrator.csDatabase/Entities/Vehicle.csDatabase/Entities/Mission.csDatabase/Entities/Waypoint.csDatabase/Entities/MapObject.csDatabase/Entities/Media.cs(borrowed schema)Database/Entities/Annotation.cs(borrowed schema)Database/Entities/Detection.cs(borrowed schema)Enums/VehicleType.cs(persisted onvehicles.type; consumed by01_vehicle_catalogDTOs)Enums/FuelType.cs(persisted onvehicles.fuel_type; consumed by01_vehicle_catalogDTOs)Enums/WaypointSource.cs(persisted onwaypoints.waypoint_source; consumed by02_mission_planningDTOs)Enums/WaypointObjective.cs(persisted onwaypoints.waypoint_objective; consumed by02_mission_planningDTOs)Enums/ObjectStatus.cs(persisted onmap_objects.object_status)
- Internal: none
- Imports from: nothing internal
- Consumed by:
01_vehicle_catalog,02_mission_planning,07_host
Component: 05_identity
- Epic: Jira AZ-EPIC
- Directory(ies):
Auth/ - Public API:
Auth/JwtExtensions.AddJwtAuth(...)(called by07_host); the"FL"policy NAME (referenced as a string by feature controllers — string-typed dependency, NOT compile-checked) - Owns (exclusive write):
Auth/JwtExtensions.cs
- Internal: none
- Imports from: nothing internal
- Consumed by:
01_vehicle_catalog,02_mission_planning,07_host
Component: 06_http_conventions
- Epic: Jira AZ-EPIC
- Directory(ies):
Middleware/, plusDTOs/ErrorResponse.csandDTOs/PaginatedResponse.cs - Public API:
Middleware/ErrorHandlingMiddleware(registered by07_host);DTOs/PaginatedResponse<T>(returned by02_mission_planning);DTOs/ErrorResponseis unused on the wire today (see component description Caveats #2) - Owns (exclusive write):
Middleware/ErrorHandlingMiddleware.csDTOs/ErrorResponse.csDTOs/PaginatedResponse.cs
- Internal: none
- Imports from: nothing internal
- Consumed by:
02_mission_planning(PaginatedResponse<T>),07_host(middleware registration), all components implicitly (exception → status code mapping)
Component: 07_host
- Epic: Jira AZ-EPIC
- Directory(ies): repo root
- Public API: none (it is the runtime entry point)
- Owns (exclusive write):
Program.csGlobalUsings.cs
- Internal: none
- Imports from:
04_persistence,05_identity,06_http_conventions,01_vehicle_catalog,02_mission_planning - Consumed by: nothing internal — invoked by the .NET runtime via
dotnet Azaion.Missions.dll(post-rename) /dotnet Azaion.Flights.dll(today)
Shared / Cross-Cutting
There is no shared/ directory in this codebase. The role canonically taken by shared/* is filled by:
05_identity(Auth/) — auth setup + named policies06_http_conventions(Middleware/+ 2 DTOs) — error envelope + paginated response envelope04_persistence— provides sharedAppDataConnectionto all feature components
All five enums under Enums/ (VehicleType, FuelType, WaypointSource, WaypointObjective, ObjectStatus) are owned by 04_persistence because they are persisted column types — every one of them maps to an INTEGER column in the schema (Database/DatabaseMigrator.cs) and is referenced from a 04_persistence-owned entity (Vehicle, Waypoint, MapObject). Feature components (01, 02) consume them as foundation types, never own them. This was retagged on 2026-05-14 to resolve baseline findings F1 + F2 (see _docs/02_document/architecture_compliance_baseline.md); previously VehicleType / FuelType were tagged under 01 and WaypointSource / WaypointObjective under 02, which created a Foundation ← Feature layering violation.
Allowed Dependencies (layering)
Read top-to-bottom; an upper layer may import from a lower layer but NEVER the reverse.
| Layer | Components | May import from |
|---|---|---|
| 4. Composition root | 07_host | 1, 2, 3 |
| 3. Feature surfaces | 01_vehicle_catalog, 02_mission_planning | 1, 2 |
| 2. Domain (none today) | — | 1 |
| 1. Foundation | 04_persistence, 05_identity, 06_http_conventions | (none) |
There is no "Domain" layer in this codebase — feature components are thin (controller + service + DTOs) and bind directly to persistence entities. This matches typical CRUD-style ASP.NET Core services and is the deliberate shape per ../../suite/_docs/02_missions.md.
Violations of this table are Architecture findings in code-review Phase 7 (High severity).
Layout Conventions (reference)
| Language | Root | Per-component path | Public API file | Test path |
|---|---|---|---|---|
| C# (.NET) | src/ (canonical) |
src/<Component>/ |
src/<Component>/<Component>.cs (namespace root) |
tests/<Component>.Tests/ |
| C# (this repo) | ./ (NOT canonical) |
spread by horizontal layer | (no per-component public-API file; types referenced directly) | no tests project |
Verification Needed
- Forward-looking file paths: every "Owns" path above reflects the post-rename target (B5/B6/B7/B8). Today the files still have
Aircraft*/Flight*/Orthophoto*/GpsCorrection*names. Implementers of B5–B10 should treat this layout as the spec for the rename, not the current ground truth. After B6 ships the layout matches the disk. - Layer-organized vs component-organized layout: this codebase organizes files by horizontal layer (
Controllers/,Services/,DTOs/,Enums/) not by feature component. The Owns globs are composed from multiple directories, which is unusual and means a single directory rename would touch multiple components' Owns. Question for user: keep as-is (matches the rest of the suite's .NET services? — needs verification againstannotationsandadminlayout) or should a future refactor move toward feature-folders? Entities/andInfrastructure/at the root are EMPTY —Entities/is shadowed byDatabase/Entities/. With GPS-Denied moving out of this repo, the historical "earmarked for orthophoto path resolver" reason is gone. Question for user: delete both empty dirs as part of B5?- No
src/directory — the .NET project sits at the repo root.coderule.mdcsays "For existing projects, follow the established directory structure." → established structure is "nosrc/"; this layout DOC respects that. Confirm we should NOT move it. - Policy name is string-typed — feature controllers reference
"FL"as a raw string. A typo would silently turn into a permanent 403. Question for user: should05_identityexpose a typedPolicyNames.FLconstant? Cheap improvement; not a blocker for documentation. - Cross-component DTO clusters:
DTOs/directory mixes payloads from01,02, and06. Owns globs are file-by-file. Acceptable for now; a future refactor could split into per-component subfolders (e.g.DTOs/Vehicle/,DTOs/Mission/,DTOs/Common/). - No
tests/project exists (per../../suite/_docs/_process_leftovers/2026-04-22_ci-unit-test-lane-missing-projects.md). Test-spec / test-implement steps in autodev will need to create a siblingAzaion.Missions.Testscsproj — attests/Azaion.Missions.Tests/(suite-canonical) or somewhere else? Confirm. - Cycles spanning components: none detected. The
Vehicle → Mission → Waypointassociation graph is intra-component (entirely inside04_persistence).