mirror of
https://github.com/azaion/annotations.git
synced 2026-06-22 22:31:06 +00:00
docs+src: complete Steps 1-3 outcomes + auth re-sync baseline
This commit captures everything produced during autodev existing-code Steps 1 (Document), 2 (Architecture Baseline Scan), and 3 (Test Spec), together with the targeted auth + CORS re-sync triggered on 2026-05-14 when codebase drift was detected at Step 4 entry. None of this work was previously committed. Step 1 (Document) — 50+ _docs/02_document/ files: problem, solution, architecture, system flows, glossary, module-layout, per-component specs (01..06), modules, deployment, diagrams, data model, FINAL report, verification log, discovery. Step 2 (Architecture Baseline) — architecture_compliance_baseline.md. Verdict PASS_WITH_WARNINGS (0 Critical, 0 High, 1 Medium, 2 Low). No High/Critical findings; auto-chained to Step 3 per existing-code flow. Step 3 (Test Spec) — _docs/02_document/tests/* (67 scenarios across blackbox, security, resilience, resource-limit, performance), plus e2e/docker-compose.test.yml, e2e/seed/run.sh, scripts/run-tests.sh, scripts/run-performance-tests.sh. Coverage 88% over the active scope (40 of 45 items covered, 6 RB-deferred, 5 documented-as-uncovered). Targeted auth + CORS re-sync — replaces the deleted in-house token issuer with a JWKS-verifier model. AuthController and TokenService removed; JwtExtensions switched from HS256 symmetric to ES256 over admin's JWKS. ConfigurationResolver and CorsConfigurationValidator added under src/Infrastructure/. ADR-002 and ADR-006 retired; SEC-01, SEC-02, SEC-03 marked Closed. One new testability risk recorded in architecture.md Open Risks Section 6 (JWKS HTTPS gating). Source changes: - src/Auth/JwtExtensions.cs (modified) — ES256, JWKS, alg pinning - src/Program.cs (modified) — DI wiring for ConfigurationResolver and CorsConfigurationValidator - src/Controllers/AuthController.cs (deleted) — no in-service issuance - src/Services/TokenService.cs (deleted) — same - src/Infrastructure/ConfigurationResolver.cs (new) - src/Infrastructure/CorsConfigurationValidator.cs (new) - .env.example (new) — required env var documentation - .gitignore (updated) Cross-repo coordination: _docs/cross-repo/flights_h1_h2_h3_change_spec captures the change-spec for downstream services that consumed the now deleted /auth endpoints. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
# Flights — parallel H1/H2/H3 change spec
|
||||
|
||||
Drop-in equivalent of the H1/H2/H3 fixes landed in `annotations/` this cycle. The
|
||||
workspace boundary rule (`.cursor/rules/workspace-boundary.mdc`) prevents this
|
||||
agent from editing the `flights/` repo directly; this document is the contract
|
||||
the flights workspace should implement on its own branch.
|
||||
|
||||
Source of truth for the new files / patterns is the annotations workspace:
|
||||
|
||||
- `annotations/src/Auth/JwtExtensions.cs` — JWKS verifier wiring.
|
||||
- `annotations/src/Infrastructure/ConfigurationResolver.cs` — fail-fast env-var helper.
|
||||
- `annotations/src/Infrastructure/CorsConfigurationValidator.cs` — CORS allow-list guard.
|
||||
- `annotations/src/Program.cs` — composition root.
|
||||
|
||||
The flights changes are byte-equivalent except for the items called out under
|
||||
"Differences" below.
|
||||
|
||||
## H1 — JWKS verifier (replace HS256 shared secret)
|
||||
|
||||
In `flights/Auth/JwtExtensions.cs`:
|
||||
|
||||
- Replace `AddJwtAuth(string jwtSecret)` with `AddJwtAuth(IConfiguration configuration)`.
|
||||
- Resolve `JWT_ISSUER`, `JWT_AUDIENCE`, `JWT_JWKS_URL` via the new
|
||||
`ConfigurationResolver.ResolveRequiredOrThrow` helper (no fallbacks).
|
||||
- Build a `ConfigurationManager<JsonWebKeySet>` over a minimal
|
||||
`IConfigurationRetriever<JsonWebKeySet>` (admin only exposes JWKS, not the full
|
||||
OIDC discovery doc — copy the `JwksRetriever` private class verbatim from
|
||||
annotations).
|
||||
- `TokenValidationParameters` must be:
|
||||
- `ValidateIssuer = true`, `ValidIssuer = issuer`
|
||||
- `ValidateAudience = true`, `ValidAudience = audience`
|
||||
- `ValidateLifetime = true`, `ValidateIssuerSigningKey = true`
|
||||
- `ValidAlgorithms = [SecurityAlgorithms.EcdsaSha256]` (pinned)
|
||||
- `RequireSignedTokens = true`, `RequireExpirationTime = true`
|
||||
- `ClockSkew = TimeSpan.FromSeconds(30)`
|
||||
- `IssuerSigningKeyResolver` returns `jwks.GetSigningKeys()` filtered by `kid`.
|
||||
- Keep the existing authorization policies in place (`FL`, `GPS`).
|
||||
|
||||
## H2 — fail-fast env vars (drop insecure defaults)
|
||||
|
||||
In `flights/Program.cs`:
|
||||
|
||||
- Delete `?? "Host=localhost;Database=azaion;Username=postgres;Password=changeme"` for `DATABASE_URL` and resolve it through `ConfigurationResolver.ResolveRequiredOrThrow`.
|
||||
- Delete `?? "development-secret-key-min-32-chars!!"` for `JWT_SECRET` and remove the variable entirely (`AddJwtAuth` now takes `IConfiguration`).
|
||||
|
||||
## H3 — config-driven CORS allow-list
|
||||
|
||||
In `flights/Program.cs`:
|
||||
|
||||
- Read `CorsConfig:AllowedOrigins` (string array) and `CorsConfig:AllowAnyOrigin` (bool).
|
||||
- Call `CorsConfigurationValidator.EnsureSafeForEnvironment(...)` before `AddCors`. In `Production` with empty origins and `AllowAnyOrigin=false`, throw.
|
||||
- Build the default policy with `WithOrigins(allowedOrigins)` (locked) or `AllowAnyOrigin()` (permissive opt-in) per `ShouldUsePermissivePolicy`.
|
||||
- After `builder.Build()`, log a warning when running with the permissive default in a non-Production environment (`ShouldWarnAboutPermissiveDefault`).
|
||||
|
||||
Copy `CorsConfigurationValidator.cs` verbatim, only changing the namespace to
|
||||
`Azaion.Flights.Infrastructure`.
|
||||
|
||||
## Side-effect: local token minting
|
||||
|
||||
If flights has its own `Services/TokenService.cs` or `Controllers/AuthController.cs`
|
||||
that mints tokens with HS256 (matching the pattern annotations had before this
|
||||
cycle), it MUST be removed; otherwise the new validator (`ValidAlgorithms` pinned
|
||||
to `EcdsaSha256`) will reject the locally-minted tokens at the next
|
||||
`[Authorize]` hop. Admin is the sole token issuer for the suite after this
|
||||
change.
|
||||
|
||||
If flights had no local token minting before, this section does not apply.
|
||||
|
||||
## Differences from annotations
|
||||
|
||||
- Authorization policies in `JwtExtensions`: keep flights' existing `FL` and
|
||||
`GPS` policies; do NOT add annotations' `ANN`/`DATASET`/`ADM` policies.
|
||||
- Namespace prefix: `Azaion.Flights` instead of `Azaion.Annotations`.
|
||||
|
||||
## `.env.example` (new file)
|
||||
|
||||
Mirror annotations' template; required keys:
|
||||
|
||||
```
|
||||
DATABASE_URL=
|
||||
JWT_ISSUER=AzaionApi
|
||||
JWT_AUDIENCE=Annotators/OrangePi/Admins
|
||||
JWT_JWKS_URL=https://admin.azaion.com/.well-known/jwks.json
|
||||
# CorsConfig__AllowedOrigins__0=https://...
|
||||
# CorsConfig__AllowAnyOrigin=false
|
||||
```
|
||||
|
||||
Confirm the `Issuer` / `Audience` values against the production admin
|
||||
deployment before merging.
|
||||
|
||||
## Docs to update in `flights/_docs/`
|
||||
|
||||
- `02_document/modules/auth-identity.md` (or equivalent) — verifier-only role,
|
||||
remove any HS256 references, document the JWKS resolver wiring.
|
||||
- `02_document/deployment/environment_strategy.md` (or equivalent) —
|
||||
required-vs-optional env table; remove `JWT_SECRET`, add the three new JWT
|
||||
vars and the CORS config keys.
|
||||
- `02_document/architecture.md` (or equivalent) — retire any ADRs that pinned
|
||||
HS256 / wide-open CORS.
|
||||
|
||||
## Verification before merge
|
||||
|
||||
1. `dotnet build` succeeds.
|
||||
2. Manually unset `JWT_ISSUER` (or `JWT_AUDIENCE`, `JWT_JWKS_URL`, `DATABASE_URL`) and confirm startup throws `InvalidOperationException` with a helpful message naming the env var.
|
||||
3. With `ASPNETCORE_ENVIRONMENT=Production` and no `CorsConfig:AllowedOrigins`, confirm startup throws.
|
||||
4. With a valid admin-issued ES256 token, confirm `[Authorize]` endpoints return 200.
|
||||
5. With a token forged using `alg=HS256` and admin's public key as the HMAC secret, confirm the endpoint returns 401 (alg-confusion attack rejected).
|
||||
Reference in New Issue
Block a user