# 07 — Host (Composition Root) **Spec source**: `../../../suite/_docs/00_top_level_architecture.md` § Edge compose excerpt -- confirms the env vars (`DATABASE_URL`, `JWT_SECRET`), port (`5002:8080`), and DB target (`postgres-local`). **Implementation status**: ✅ implemented. > **NOTE (forward-looking)**: post-rename. Today's source has `Azaion.Flights` namespace + `dotnet Azaion.Flights.dll` entrypoint + container image `azaion/flights:*-arm`. Renames + DLL/image/compose changes tracked under Jira AZ-EPIC children B5 (namespace), B10 (Dockerfile + Woodpecker + suite compose). **Files**: `Program.cs`, `GlobalUsings.cs` ## 1. High-Level Overview **Purpose**: Build the ASP.NET Core web host: read environment, register all DI services, configure the request pipeline, run the schema migrator at startup, and serve the API on port 8080 (mapped to host 5002 in edge compose). **Architectural pattern**: Composition root + ASP.NET Core minimal-host bootstrap (top-level statements). **Upstream dependencies**: Every other component in this service. **Downstream consumers**: The container runtime (`ENTRYPOINT ["dotnet", "Azaion.Missions.dll"]` in `Dockerfile` after B10) and any local `dotnet run`. ## 2. Internal Interface None. The host has no exported types -- its surface is the running HTTP server. ## 3. External API | Endpoint | Method | Auth | Description | |----------|--------|------|-------------| | `/health` | GET | Public | Returns `{ "status": "healthy" }` | | `/swagger/*` | GET | Public | Swagger UI + JSON spec, served unconditionally in all environments | | (mapped controllers from feature components) | various | Per-controller `[Authorize]` | See components 01 (vehicles) and 02 (missions). | ## 4. Data Access Patterns - Opens a single scope at startup to call `DatabaseMigrator.Migrate(db)` -- populates the 4 owned tables in the shared local PostgreSQL. - Registers `AppDataConnection` as **scoped** so each HTTP request gets a fresh `DataConnection` (one Npgsql connection per request from the pool). ## 5. Implementation Details **State Management**: Stateless (request pipeline). The only run-once side effect is the migrator call. **Key Dependencies**: | Library | Version | Purpose | |---------|---------|---------| | `Microsoft.AspNetCore` (in `Microsoft.NET.Sdk.Web`) | net10.0 | Web host + middleware pipeline | | `linq2db` | 6.2.0 | DB access via `AppDataConnection` registration | | `Npgsql` | 10.0.2 | PostgreSQL driver (used through linq2db) | | `Swashbuckle.AspNetCore` | 10.1.5 | Swagger UI + JSON spec generation | **Error Handling**: Delegated to `06_http_conventions`' middleware, placed FIRST in the pipeline so it wraps everything else. **Configuration**: Reads `DATABASE_URL` and `JWT_SECRET` from `IConfiguration` -> `Environment.GetEnvironmentVariable` -> hardcoded dev fallback. Both fallbacks are dev-only and MUST be overridden in production. **`ConvertPostgresUrl` helper**: ad-hoc parser converting `postgresql://user[:pass]@host[:port]/db` to Npgsql key=value form. Does not URL-decode user/password -- caveat for credentials with `@`, `:`, `/`, `%`. ## 6. Extensions and Helpers - `GlobalUsings.cs` -- three project-wide `global using` directives for LinqToDB. ## 7. Caveats & Edge Cases - **No environment guards**: Swagger and the dev fallbacks for secrets are NOT gated on `IsDevelopment()`. If `JWT_SECRET` is unset in production, the service silently runs with the well-known development secret. - **CORS open by default**: `AllowAnyOrigin/Method/Header` applied unconditionally. Spec doesn't mandate a CORS policy -- likely safe behind suite's reverse proxy on edge, but worth confirming. - **Migrator failure crashes the process** at startup. Container orchestrator (Watchtower-restarted Docker) is expected to bring it back; `flight-gate` (per `../../../suite/_docs/00_top_level_architecture.md`) ensures this doesn't happen mid-mission. - **No HTTPS redirection** middleware; assumes a TLS-terminating reverse proxy upstream (Caddy fronting Gitea is documented but in-deployment TLS termination is environment-specific). - **Port 8080** matches the Dockerfile `EXPOSE 8080` and edge compose `5002:8080` mapping per `../../../suite/_docs/00_top_level_architecture.md` excerpt. - **No GPS-Denied service registration** here. Earlier drafts of this doc reserved a slot for a GPS-Denied feature component; per Jira AZ-EPIC child B7, GPS-Denied lives in a separate (out-of-this-repo) service, so this host registers only `VehicleService`, `MissionService`, `WaypointService`. ## 8. Dependency Graph **Must be implemented after**: every other component (01-06). **Blocks**: nothing internal (it is the runtime root). ## 9. Logging Strategy ASP.NET Core defaults (Console / Debug providers, no Serilog/structured logging configured). The only structured log emitted by app code is `06_http_conventions`' middleware `LogError(ex, "Unhandled exception")`. No correlation ID, no request tracing.