mirror of
https://github.com/azaion/missions.git
synced 2026-06-21 21:11:06 +00:00
7025f4d075
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.
174 lines
12 KiB
Markdown
174 lines
12 KiB
Markdown
# 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 is `Azaion.Flights.csproj`, and namespace is `Azaion.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 by `07_host` for DI registration; `02_mission_planning` consumes its existence semantics through the DB)
|
||
- **Owns (exclusive write)** (post-rename):
|
||
- `Controllers/VehiclesController.cs`
|
||
- `Services/VehicleService.cs`
|
||
- `DTOs/CreateVehicleRequest.cs`
|
||
- `DTOs/UpdateVehicleRequest.cs`
|
||
- `DTOs/GetVehiclesQuery.cs`
|
||
- `DTOs/SetDefaultRequest.cs`
|
||
- **Internal**: none — every file is publicly importable in C# without explicit visibility annotations
|
||
- **Imports from**: `04_persistence` (`AppDataConnection`, `Vehicle` entity, `VehicleType` enum, `FuelType` enum), `05_identity` (`[Authorize(Policy = "FL")]`), `06_http_conventions` (exception → middleware mapping is implicit)
|
||
- **Consumed by**: `02_mission_planning` (FK existence-check on `vehicle_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 in `07_host`)
|
||
- **Owns (exclusive write)** (post-rename):
|
||
- `Controllers/MissionsController.cs`
|
||
- `Services/MissionService.cs`
|
||
- `Services/WaypointService.cs`
|
||
- `DTOs/CreateMissionRequest.cs`
|
||
- `DTOs/UpdateMissionRequest.cs`
|
||
- `DTOs/GetMissionsQuery.cs`
|
||
- `DTOs/CreateWaypointRequest.cs`
|
||
- `DTOs/UpdateWaypointRequest.cs`
|
||
- `DTOs/GeoPoint.cs`
|
||
- **Internal**: none
|
||
- **Imports from**: `04_persistence` (incl. `WaypointSource` + `WaypointObjective` enums), `05_identity`, `06_http_conventions` (`PaginatedResponse<T>`), `01_vehicle_catalog` (existence semantics through DB FK)
|
||
- **Consumed by**: `07_host` (DI), and external `autopilot` / `ui` (cross-service over HTTP)
|
||
|
||
### Component: 04_persistence
|
||
|
||
- **Epic**: Jira AZ-EPIC
|
||
- **Directory(ies)**: `Database/`, plus `Enums/ObjectStatus.cs` (cross-cutting status enum)
|
||
- **Public API**: `Database/AppDataConnection.cs` (the `DataConnection` type other components depend on), `Database/DatabaseMigrator.cs` (called by `07_host` at startup), all 7 entities under `Database/Entities/` (referenced by services + DTOs as row maps), the four persisted-column enums under `Enums/` (`VehicleType`, `FuelType`, `WaypointSource`, `WaypointObjective`, `ObjectStatus`)
|
||
- **Owns (exclusive write)** (post-rename):
|
||
- `Database/AppDataConnection.cs`
|
||
- `Database/DatabaseMigrator.cs`
|
||
- `Database/Entities/Vehicle.cs`
|
||
- `Database/Entities/Mission.cs`
|
||
- `Database/Entities/Waypoint.cs`
|
||
- `Database/Entities/MapObject.cs`
|
||
- `Database/Entities/Media.cs` (borrowed schema)
|
||
- `Database/Entities/Annotation.cs` (borrowed schema)
|
||
- `Database/Entities/Detection.cs` (borrowed schema)
|
||
- `Enums/VehicleType.cs` (persisted on `vehicles.type`; consumed by `01_vehicle_catalog` DTOs)
|
||
- `Enums/FuelType.cs` (persisted on `vehicles.fuel_type`; consumed by `01_vehicle_catalog` DTOs)
|
||
- `Enums/WaypointSource.cs` (persisted on `waypoints.waypoint_source`; consumed by `02_mission_planning` DTOs)
|
||
- `Enums/WaypointObjective.cs` (persisted on `waypoints.waypoint_objective`; consumed by `02_mission_planning` DTOs)
|
||
- `Enums/ObjectStatus.cs` (persisted on `map_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 by `07_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/`, plus `DTOs/ErrorResponse.cs` and `DTOs/PaginatedResponse.cs`
|
||
- **Public API**: `Middleware/ErrorHandlingMiddleware` (registered by `07_host`); `DTOs/PaginatedResponse<T>` (returned by `02_mission_planning`); `DTOs/ErrorResponse` is unused on the wire today (see component description Caveats #2)
|
||
- **Owns (exclusive write)**:
|
||
- `Middleware/ErrorHandlingMiddleware.cs`
|
||
- `DTOs/ErrorResponse.cs`
|
||
- `DTOs/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.cs`
|
||
- `GlobalUsings.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 policies
|
||
- **`06_http_conventions`** (`Middleware/` + 2 DTOs) — error envelope + paginated response envelope
|
||
- **`04_persistence`** — provides shared `AppDataConnection` to 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 against `annotations` and `admin` layout) or should a future refactor move toward feature-folders?
|
||
- [ ] **`Entities/` and `Infrastructure/` at the root are EMPTY** — `Entities/` is shadowed by `Database/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.mdc` says "For existing projects, follow the established directory structure." → established structure is "no `src/`"; 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**: should `05_identity` expose a typed `PolicyNames.FL` constant? Cheap improvement; not a blocker for documentation.
|
||
- [ ] **Cross-component DTO clusters**: `DTOs/` directory mixes payloads from `01`, `02`, and `06`. 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 sibling `Azaion.Missions.Tests` csproj — at `tests/Azaion.Missions.Tests/` (suite-canonical) or somewhere else? Confirm.
|
||
- [ ] **Cycles spanning components**: none detected. The `Vehicle → Mission → Waypoint` association graph is intra-component (entirely inside `04_persistence`).
|