mirror of
https://github.com/azaion/missions.git
synced 2026-06-22 02:41:08 +00:00
refactor: enhance JWT authentication and CORS configuration
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.
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
# Flow F6 — Service startup + schema migration
|
||||
|
||||
> One-shot per process start. Idempotent migrator (`CREATE ... IF NOT EXISTS`). Post-B9 the migrator additionally `DROP TABLE IF EXISTS orthophotos / gps_corrections` for fielded edge devices that previously ran the legacy schema.
|
||||
|
||||
## Description
|
||||
|
||||
`Program.cs` builds the DI graph from environment, runs `DatabaseMigrator.Migrate(db)` once inside a startup scope, then starts serving HTTP. The migrator only owns the 4 tables this service is responsible for (`vehicles`, `missions`, `waypoints`, `map_objects`); the borrowed tables (`media`, `annotations`, `detection`) are migrated by their owner services in their own startups.
|
||||
|
||||
## Preconditions
|
||||
|
||||
- `DATABASE_URL` resolves (env or hardcoded dev fallback).
|
||||
- `postgres-local` is reachable.
|
||||
- The `azaion` database itself exists in PostgreSQL (created at provisioning time, NOT by this migrator).
|
||||
|
||||
## Sequence Diagram
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Docker as Docker / Watchtower
|
||||
participant Host as 07_host (Program.cs)
|
||||
participant Cfg as IConfiguration
|
||||
participant Identity as 05_identity
|
||||
participant DI as DI container
|
||||
participant Migrator as DatabaseMigrator
|
||||
participant DB as postgres-local
|
||||
|
||||
Docker->>Host: ENTRYPOINT dotnet Azaion.Missions.dll
|
||||
Host->>Cfg: read DATABASE_URL → ConvertPostgresUrl → Npgsql connection string
|
||||
Host->>Cfg: read JWT_SECRET (env or hardcoded fallback)
|
||||
Host->>Identity: AddJwtAuth(jwtSecret) — DI registration only, no network
|
||||
Host->>DI: register controllers + middleware + scoped AppDataConnection + scoped services
|
||||
Host->>DI: build Host
|
||||
Host->>Migrator: scope.Resolve<AppDataConnection>(); Migrate(db)
|
||||
Migrator->>DB: CREATE TABLE IF NOT EXISTS vehicles (...)
|
||||
Migrator->>DB: CREATE TABLE IF NOT EXISTS missions (...)
|
||||
Migrator->>DB: CREATE TABLE IF NOT EXISTS waypoints (...)
|
||||
Migrator->>DB: CREATE TABLE IF NOT EXISTS map_objects (...)
|
||||
Migrator->>DB: CREATE INDEX IF NOT EXISTS ix_missions_vehicle_id, ix_waypoints_mission_id, ix_map_objects_mission_id
|
||||
Migrator->>DB: DROP TABLE IF EXISTS orthophotos
|
||||
Migrator->>DB: DROP TABLE IF EXISTS gps_corrections
|
||||
note right of Migrator: B9 one-shot. Idempotent on devices that already cleaned up.
|
||||
Migrator-->>Host: void
|
||||
Host->>Host: register ErrorHandlingMiddleware FIRST in pipeline
|
||||
Host->>Host: UseAuthentication / UseAuthorization
|
||||
Host->>Host: MapControllers + MapGet("/health") + UseSwagger
|
||||
Host->>Docker: app.Run() — listening on 0.0.0.0:8080
|
||||
```
|
||||
|
||||
## Flowchart
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([Container start]) --> ReadCfg[Read DATABASE_URL + JWT_SECRET]
|
||||
ReadCfg --> RegDI[DI registrations: controllers, middleware, scoped DB + services]
|
||||
RegDI --> Build[Build Host]
|
||||
Build --> OpenScope[Open startup scope]
|
||||
OpenScope --> Migrate[Run DatabaseMigrator.Migrate]
|
||||
Migrate --> Create["CREATE TABLE IF NOT EXISTS x4 + indexes"]
|
||||
Create --> Drop["DROP TABLE IF EXISTS orthophotos, gps_corrections (B9)"]
|
||||
Drop --> Pipeline[Wire pipeline: error MW first, auth, controllers, /health, Swagger]
|
||||
Pipeline --> Run([app.Run on :8080])
|
||||
Migrate -. on failure .-> Crash([Process exits non-zero — Watchtower restarts])
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
|
||||
| Step | From | To | Data | Format |
|
||||
|------|------|----|------|--------|
|
||||
| 1 | Environment / appsettings | `Program.cs` | `DATABASE_URL`, `JWT_SECRET` | string |
|
||||
| 2 | `Program.cs` | DI container | service registrations | C# code |
|
||||
| 3 | `DatabaseMigrator` | `postgres-local` | DDL statements (CREATE / INDEX / DROP) | SQL |
|
||||
| 4 | `Program.cs` | OS / Docker | bind to `0.0.0.0:8080` | TCP listener |
|
||||
|
||||
## Error Scenarios
|
||||
|
||||
| Error | Where | Detection | Recovery |
|
||||
|-------|-------|-----------|----------|
|
||||
| `postgres-local` unreachable | Migrate step | Npgsql `IOException` / `SocketException` | Process exits non-zero. Watchtower restarts; `flight-gate` prevents restart mid-mission. **Fix**: ensure `postgres-local` healthcheck passes before `missions` starts (compose `depends_on` with `condition: service_healthy`) |
|
||||
| `azaion` database missing | Migrate step | Npgsql `3D000` (`invalid_catalog_name`) | Process exits. Operator must create the database — provisioning concern, not this service. Documented in `../../suite/_docs/00_top_level_architecture.md` |
|
||||
| `DROP TABLE IF EXISTS orthophotos` fails because table is locked by `gps-denied` | B9 one-shot | Lock timeout or `55006` | Process exits, Watchtower restarts in a few seconds. **Out-of-band ordering**: deploy `gps-denied` FIRST so it has its own copy of the schema before `missions` drops the legacy tables. Documented in B9 ticket |
|
||||
| One `CREATE TABLE` succeeds, the next fails | Mid-Migrate | Npgsql exception on later statement | Process exits. Each statement is individually idempotent (`IF NOT EXISTS`) so the next startup retries safely from the start. No partial-migration cleanup needed |
|
||||
| Wrong PostgreSQL version (e.g., < 13) | Migrate step | Specific syntax errors in newer features | Process exits. Suite-supported version is PG 16+; older devices need a Postgres upgrade |
|
||||
| `DATABASE_URL` malformed (e.g. user password contains `@`) | `ConvertPostgresUrl` | parse failure / silent mis-parse | `ConvertPostgresUrl` does NOT URL-decode user/password — caveat for credentials with `@`, `:`, `/`, `%`. `07_host` Caveats. Mitigation: avoid those chars in passwords, OR pass a raw Npgsql key=value string instead of a URL |
|
||||
|
||||
## Performance Expectations
|
||||
|
||||
| Metric | Target | Notes |
|
||||
|--------|--------|-------|
|
||||
| Cold start total time | <2 seconds typical on Jetson Orin | Migrator runs ~10 DDL statements; all are no-ops on a steady-state device |
|
||||
| Cold start with legacy GPS-Denied tables present | +1 second | First-time-on-device B9 `DROP` adds two DDL statements |
|
||||
| Crash recovery (Watchtower restart) | ~10 seconds | Container restart latency dominates |
|
||||
Reference in New Issue
Block a user