Files
missions/_docs/00_problem/restrictions.md
T
Oleksandr Bezdieniezhnykh 7025f4d075 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.
2026-05-14 19:48:25 +03:00

8.9 KiB

Restrictions — Azaion.Missions

Status: derived-from-code (autodev /document Step 6, 2026-05-14). Each restriction below is grounded in code, configuration, or Dockerfile evidence — none are aspirational. References point to the artefact that establishes the constraint.


Hardware restrictions

# Restriction Evidence
H1 Service runs on operator-owned edge devices (Jetson Orin / OrangePI / operator-PC), one container per device Dockerfile multi-arch; ../../suite/_docs/00_top_level_architecture.md § Edge Tier
H2 Multi-arch container — ARM64 dominant (Jetson / OrangePI), AMD64 supported (operator-PC) Dockerfile --platform=$BUILDPLATFORM, dotnet publish --os linux --arch $arch; .woodpecker/build-arm.yml tag suffix -arm
H3 Vertical scale only — exactly one instance per device, no horizontal scale-out _docs/02_document/architecture.md § 3 Deployment Model; suite arch doc § Edge Tier
H4 No managed cloud — every deployment is on customer-owned hardware suite arch doc § Edge Tier
H5 Watchtower handles container restarts; flight-gate prevents container restart mid-mission suite arch doc § Edge Tier; _docs/02_document/architecture.md § 6 Availability
H6 Resource limits not enforced inside the container; device-level cgroups / docker compose limits set at suite level Dockerfile (no --memory / cpu); suite _infra/_compose/

Software restrictions

# Restriction Evidence
S1 Language: C#; runtime: .NET 10 (net10.0) Azaion.Flights.csproj (post-B5: Azaion.Missions.csproj)
S2 Web framework: ASP.NET Core (Microsoft.NET.Sdk.Web) csproj
S3 Data access library: linq2db 6.2.0 csproj <PackageReference Include="linq2db" Version="6.2.0" />
S4 Database driver: Npgsql 10.0.2 csproj
S5 Auth library: Microsoft.AspNetCore.Authentication.JwtBearer 10.0.5 csproj
S6 Swagger / OpenAPI: Swashbuckle 10.1.5, mounted unconditionally (NOT gated on IsDevelopment()) — ADR-005 carry-forward csproj + Program.cs
S7 Database engine: PostgreSQL (no other DB engines supported) Program.cs UsePostgreSQL; suite arch doc § Database Topology
S8 One csproj, one root namespace (Azaion.Missions.* post-B5) — components are logical groupings, not compilation units csproj; _docs/02_document/architecture.md ADR-008
S9 No src/ directory — project sits at the repo root repo layout; _docs/02_document/00_discovery.md § Repository Layout
S10 Layer-organized layout (Controllers/, Services/, DTOs/, Enums/, Auth/, Middleware/, Database/ at repo root) repo layout; _docs/02_document/module-layout.md
S11 No automated tests today (no tests/ directory; no test sibling project) repo layout; _docs/02_document/00_discovery.md § Test Layout
S12 No migration tool — schema bootstrap via raw CREATE TABLE IF NOT EXISTS + one-shot B9 DROP TABLE IF EXISTS block Database/DatabaseMigrator.cs; ADR-004
S13 No in-process message queue, no event bus, no RPC — components communicate via direct C# calls registered in DI _docs/02_document/architecture.md § 5; Program.cs
S14 Tables OWNED by this service (post-B7+B9): vehicles, missions, waypoints, map_objects (4 owned). 3 borrowed read-only stubs (media, annotations, detection) Database/DatabaseMigrator.cs; Database/AppDataConnection.cs; _docs/02_document/data_model.md
S15 gps-denied is decoupled by design — no runtime call in either direction; gps-denied references mission_id / waypoint_id as plain GUIDs in its own tables ADR-007

Environment / configuration restrictions

# Restriction Evidence
E1 Two required env vars at runtime: DATABASE_URL, JWT_SECRET Program.cs Environment.GetEnvironmentVariable
E2 DATABASE_URL accepts either a postgresql://user:pass@host:port/db URL OR a raw Npgsql connection string (local helper ConvertPostgresUrl) Program.cs ConvertPostgresUrl
E3 Hardcoded development fallbacks: JWT_SECRET=development-secret-key-min-32-chars!!, DATABASE_URL=Host=localhost;Database=azaion;Username=postgres;Password=changeme (NOT gated on IsDevelopment()) — ADR-005 carry-forward; production deploys MUST override Program.cs
E4 JWT_SECRET is shared across admin + every backend service on the same edge device — rotation requires a coordinated re-deploy across all of them _docs/02_document/components/05_identity/description.md; suite arch doc
E5 Container EXPOSE 8080; edge compose maps host port 5002:8080 Dockerfile; suite _infra/_compose/
E6 Image tag: ${REGISTRY_HOST}/azaion/missions:${BRANCH}-arm post-B10 (was azaion/flights:*-arm pre-B10) .woodpecker/build-arm.yml (post-B10)
E7 Entrypoint: dotnet Azaion.Missions.dll post-B5 (was Azaion.Flights.dll pre-B5) Dockerfile (post-B5)
E8 No environment-specific overrides in appsettings.*.json — single config flow via env vars Program.cs; no appsettings.Production.json in repo
E9 CORS: AllowAnyOrigin / AllowAnyMethod / AllowAnyHeader in all environments (assumed safe behind suite reverse proxy) Program.cs
E10 TLS termination is the suite reverse proxy's responsibility — container exposes plain HTTP on :8080 Dockerfile; suite arch doc

Operational restrictions

# Restriction Evidence
O1 Migrator runs at every process start; idempotent (IF NOT EXISTS); B9 adds a one-shot DROP TABLE IF EXISTS orthophotos / gps_corrections block for fielded legacy devices Database/DatabaseMigrator.cs
O2 flight-gate (suite-level) is the ONLY orchestration that prevents restart mid-mission; no Kubernetes suite arch doc § Edge Tier
O3 No version table; the migrator runs every startup Database/DatabaseMigrator.cs
O4 Single Woodpecker CI job per repo: docker build + push on [dev, stage, main] branches; no test, no security scan, no migration check .woodpecker/build-arm.yml
O5 No structured logging (Serilog / Seq) — LogError(ex, "Unhandled exception") is the only application-level log Middleware/ErrorHandlingMiddleware.cs; _docs/02_document/architecture.md § 7
O6 No correlation ID, no per-request audit trail, no per-user attribution (JWT user-id claim parsed but not consumed) Auth/JwtExtensions.cs; _docs/02_document/components/05_identity/description.md
O7 Health endpoint: GET /health returns { status: "healthy" } with no DB ping (process-liveness only) Program.cs MapGet("/health")
O8 Cascade-delete is NOT transaction-wrapped today (ADR-006) — partial failure leaves orphan rows in media / annotations / detection / map_objects Services/FlightService.cs (post-B6: MissionService.cs); Services/WaypointService.cs
O9 Each backend service is responsible for its own table migrations; if annotations is absent at deploy time, the cascade-delete walk fails on relation does not exist (abnormal edge deployment) _docs/02_document/components/02_mission_planning/description.md Caveats #6
O10 One-instance-per-device constraint means session state, in-memory caches, and rate limits are NOT cluster-aware (none of these are implemented today either) Program.cs; suite arch doc

Out-of-scope (NOT this service's responsibility)

Concern Where it lives Why it's not here
Token issuance (sign / mint) admin (central .NET service) Local validation only; offline-tolerant edge design
User CRUD, role assignment admin + ../../suite/_docs/00_roles_permissions.md Suite-level concern
Media storage / upload annotations (sibling edge service) annotations owns the table schema
AI annotation rules annotations Schema and behaviour both owned by annotations
Object detection / class definitions Detection pipeline (sibling edge service) Pipeline owns the detection table
map_objects write path autopilot (sibling edge service) This service owns the schema + cascade-delete only
Orthophoto / live-GPS / GPS correction gps-denied (separate service after B7) ADR-007
TLS / HTTPS termination Suite reverse proxy _docs/02_document/architecture.md § 7
Schema rename / column drop / type change Future migration tool (ADR-004 carry-forward) Today's IF NOT EXISTS migrator can't reshape existing schema; B9's DROP TABLE IF EXISTS is the single explicit destructive step
iss / aud JWT validation Suite-level remediation (CMMC L2 row 3, AZ-487 / AZ-494) Out of this Epic; consistent with shared-secret model today
camelCase wire-shape migration Suite-wide cutover (ADR-002 carry-forward) All-or-nothing; UI + autopilot consume PascalCase today