mirror of
https://github.com/azaion/missions.git
synced 2026-06-21 06:41: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.
3.8 KiB
3.8 KiB
Flow F1 — Vehicle CRUD
Post-rename / post-B7. Today:
[Route("aircrafts")],Aircraft*files. See02_mission_planningis unaffected by route prefix.
Description
Operator manages the inventory of Vehicle rows. Six endpoints: POST, PUT, DELETE, GET-list (unpaginated by spec), GET-by-id, PATCH /default. Every endpoint is gated by [Authorize(Policy = "FL")]. The "exactly one default vehicle" exclusivity rule is stricter than spec — the code clears IsDefault on every other row before setting it on the target. See 01_vehicle_catalog Caveats #1, tracked under Jira AZ-551 (B12).
Preconditions
- Service is running and schema is in place (Flow F6 has completed).
- Caller holds a JWT with
permissions=FL(Flow F5 succeeds).
Sequence Diagram (POST /vehicles with IsDefault: true)
sequenceDiagram
autonumber
participant UI as Operator UI
participant Pipeline as ASP.NET Pipeline
participant Identity as 05_identity
participant Errs as 06_http_conventions
participant Ctrl as VehiclesController
participant Svc as VehicleService
participant DB as 04_persistence (postgres-local)
UI->>Pipeline: POST /vehicles + Bearer JWT + body
Pipeline->>Errs: enter middleware (catches exceptions)
Errs->>Identity: validate JWT + policy "FL"
alt JWT or policy fails
Identity-->>UI: 401 / 403
else authorized
Identity-->>Ctrl: ClaimsPrincipal attached
Ctrl->>Svc: CreateVehicle(req)
opt req.IsDefault == true
Svc->>DB: UPDATE vehicles SET is_default=FALSE WHERE is_default=TRUE
note right of Svc: Stricter than spec. Race-prone (no transaction). B12.
end
Svc->>DB: INSERT INTO vehicles VALUES (...)
DB-->>Svc: row id
Svc-->>Ctrl: Vehicle entity
Ctrl-->>Errs: 201 Created + Vehicle (PascalCase JSON)
Errs-->>UI: 201 Created
end
Flowchart (DELETE /vehicles/{id})
flowchart TD
Start([DELETE /vehicles/id]) --> Auth{JWT + FL valid?}
Auth -->|no| Reject([401 / 403])
Auth -->|yes| Lookup[SELECT 1 FROM vehicles WHERE id=?]
Lookup --> Exists{Found?}
Exists -->|no| NotFound([KeyNotFoundException → 404])
Exists -->|yes| Refs[SELECT 1 FROM missions WHERE vehicle_id=?]
Refs --> InUse{Any mission references it?}
InUse -->|yes| Conflict([InvalidOperationException → 409])
InUse -->|no| Del[DELETE FROM vehicles WHERE id=?]
Del --> Done([204 No Content])
Data Flow
| Step | From | To | Data | Format |
|---|---|---|---|---|
| 1 | UI | VehiclesController |
CreateVehicleRequest / UpdateVehicleRequest / SetDefaultRequest / query string |
JSON (PascalCase) |
| 2 | VehicleService |
vehicles table |
INSERT / UPDATE / DELETE | SQL |
| 3 | vehicles table |
VehicleService |
row(s) | LinqToDB entity mapping |
| 4 | VehicleService |
UI | Vehicle entity |
JSON (PascalCase) — entity returned directly, no DTO mapping |
Error Scenarios
| Error | Where | Detection | Recovery |
|---|---|---|---|
| Missing / invalid JWT | Pipeline | JwtBearerHandler |
401; client refreshes token |
Missing "FL" claim |
Policy evaluator | Claim lookup | 403 |
| Vehicle not found | Service entity lookup | null result |
KeyNotFoundException → 404 |
| Delete-with-references | VehicleService.DeleteVehicle |
IsAny<Mission> true |
InvalidOperationException → 409 |
| Concurrent default-set | VehicleService.{Create,Update}Vehicle / SetDefault |
none (no transaction) | Race window: 2+ defaults OR zero defaults. B12 |
Performance Expectations
| Metric | Target | Notes |
|---|---|---|
| End-to-end latency (CRUD) | <10ms typical | Single round-trip against local PostgreSQL |
| Throughput | Operator-paced | Not load-tested; catalog is small in practice (tens to low hundreds of rows) |