Files
satellite-provider/_docs/03_implementation/batch_01_cycle2_report.md
T
Oleksandr Bezdieniezhnykh 96cd3c4495
ci/woodpecker/push/01-test Pipeline failed
ci/woodpecker/push/02-build-push unknown status
[AZ-487] JWT validation baseline (HS256, all endpoints)
Adds Microsoft.AspNetCore.Authentication.JwtBearer 8.0.21 and the
SatelliteProvider.Api.Authentication.AddSatelliteJwt extension that
validates HS256 tokens against a shared JWT_SECRET (>=32 bytes, fail
fast at startup). Every minimal-API endpoint now carries
.RequireAuthorization(); the middleware chain is UseExceptionHandler ->
UseHttpsRedirection -> UseCors -> UseAuthentication -> UseAuthorization
-> endpoints. Swagger UI gets a Bearer security definition so the
Authorize button works.

Test infrastructure: JwtTokenFactory (unit) and JwtTestHelpers
(integration) mint deterministic tokens against the same secret; the
integration test runner attaches a default Bearer token to its shared
HttpClient so existing tests continue to exercise protected endpoints.
JwtIntegrationTests adds AC-1..AC-4 and AC-7 (Swagger advertises
Bearer) end-to-end; AuthenticationServiceCollectionExtensionsTests
covers AC-5 (missing/empty/short secret fail-fast) plus env-var
precedence; JwtTokenFactoryTests covers AC-6 (claims pass through
the JwtSecurityTokenHandler.ValidateToken path JwtBearer uses).

docker-compose and scripts/run-tests.sh now propagate JWT_SECRET to
the api and integration-tests containers, with a >=32-byte guard.
.env.example documents the required keys; .env stays gitignored.

Code review verdict: PASS_WITH_WARNINGS (2 Low findings surfaced
in _docs/03_implementation/reviews/batch_01_cycle2_review.md).

Cross-component coordination: gps-denied-onboard and the mission
planner UI must attach Bearer tokens before this lands in dev.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 23:06:23 +03:00

4.9 KiB

Batch Report — Batch 01 cycle 2

Batch: 01 (cycle 2) Tasks: AZ-487 (JWT validation baseline) Date: 2026-05-11

Task Results

Task Status Files Modified Tests AC Coverage Issues
AZ-487_jwt_validation_baseline Done 12 modified + 6 added (.env.example, SatelliteProvider.Api/Authentication/AuthenticationServiceCollectionExtensions.cs, SatelliteProvider.IntegrationTests/JwtIntegrationTests.cs, JwtTestHelpers.cs, SatelliteProvider.Tests/Authentication/AuthenticationServiceCollectionExtensionsTests.cs, JwtTokenFactoryTests.cs, SatelliteProvider.Tests/TestUtilities/JwtTokenFactory.cs) To run (Step 11) 8/8 ACs covered 0 blockers; 2 Low findings (see review)

AC Test Coverage: All covered (8 of 8)

Code Review Verdict: PASS_WITH_WARNINGS

Auto-Fix Attempts: 0

Stuck Agents: None

What was implemented

  • New AuthenticationServiceCollectionExtensions.AddSatelliteJwt(IConfiguration) — registers Microsoft.AspNetCore.Authentication.JwtBearer 8.0.21 with TokenValidationParameters matching the suite-level auth contract (HS256, ValidateLifetime, RequireSignedTokens, RequireExpirationTime, no issuer/audience validation, 30 s clock skew). Secret resolution prefers JWT_SECRET env var, falls back to Jwt:Secret configuration, fails fast on missing/short (<32-byte) secret.
  • Program.cs wires AddSatelliteJwt + AddAuthorization into DI, adds UseAuthentication + UseAuthorization middleware after UseCors, and decorates every minimal-API endpoint with .RequireAuthorization(). Swagger UI gets a Bearer security definition + global security requirement so the "Authorize" button renders.
  • Configuration: appsettings.json adds an empty Jwt:Secret placeholder; appsettings.Development.json ships a clearly-tagged dev placeholder (≥32 bytes). The JWT_SECRET env var overrides both when set.
  • Test infrastructure:
    • SatelliteProvider.Tests.TestUtilities.JwtTokenFactory — mints, expires, and tampers tokens using the same secret as the API.
    • SatelliteProvider.Tests.Authentication.AuthenticationServiceCollectionExtensionsTests — 6 tests covering registration, parameter shape, missing/empty/short secret handling, and env-var-precedence semantics.
    • SatelliteProvider.Tests.Authentication.JwtTokenFactoryTests — 4 tests covering token mint + claims propagation + expired + tampered.
    • SatelliteProvider.IntegrationTests.JwtTestHelpers — runner-side helpers for token mint + bearer attachment.
    • SatelliteProvider.IntegrationTests.JwtIntegrationTests — 5 end-to-end checks (anon → 401, expired → 401, tampered → 401, valid → handler, Swagger advertises Bearer).
    • SatelliteProvider.IntegrationTests.Program — resolves JWT_SECRET at startup, mints a default token, attaches it to the shared HttpClient so legacy non-auth tests continue to pass against protected endpoints.
  • Docker / scripts:
    • docker-compose.yml: api gets JWT_SECRET=${JWT_SECRET}.
    • docker-compose.tests.yml: integration-tests gets the same env var (api inherits via extends).
    • scripts/run-tests.sh: loads JWT_SECRET from .env (alongside GOOGLE_MAPS_API_KEY), rejects missing/short values, exports for compose runs.
    • .env.example (new): documents GOOGLE_MAPS_API_KEY and JWT_SECRET with generation guidance.
    • .env (gitignored): dev JWT_SECRET added locally.
  • Docs:
    • architecture.md § Architecture Vision: added Authentication & Authorization sub-section.
    • architecture.md § Security Architecture: replaced "no auth" prose with JWT description; documented placeholder semantics and operator obligations.
    • modules/api_program.md: updated DI Registration (#9), Startup (middleware chain), Dependencies (JwtBearer 8.0.21), Configuration (Jwt:Secret + env var precedence), Security (per-endpoint .RequireAuthorization()).

Open follow-ups (non-blocking)

  • Doc-folder choice (F1 in review): the task spec referenced _docs/02_document/components/01_web_api/description.md, which does not exist. Updated modules/api_program.md + architecture.md instead. User should decide whether to add a stub 01_web_api component folder for symmetry, or to formalize the "WebApi has no components/* folder" pattern.
  • Cross-component coordination: per the AZ-487 spec, gps-denied-onboard and the mission planner UI must attach Bearer tokens to their outbound calls before this change ships to dev. Flagged for the operator to coordinate before deploy (Step 16).

Next Batch: AZ-488 (UAV tile upload endpoint with batch + 5-rule quality gate)

AZ-488 is an 8 SP task (user-accepted over-cap). It introduces a new endpoint, DTOs, quality gate, configuration class, and ~15 unit + integration tests. Recommend a fresh conversation for context freshness before starting (per protocols.md Context Budget Heuristic).