mirror of
https://github.com/azaion/missions.git
synced 2026-06-21 11:51:07 +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.
144 lines
15 KiB
Markdown
144 lines
15 KiB
Markdown
# 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<Aircraft>` 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<Waypoint>` 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<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.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.
|