Files
satellite-provider/_docs/02_document/modules/tests_unit.md
T
Oleksandr Bezdieniezhnykh f979e18811 [AZ-494] Enable JWT iss/aud validation with fail-fast startup
Option B per user decision: production ships with empty Jwt.Issuer /
Jwt.Audience in appsettings.json so the API process refuses to start
unless JWT_ISSUER + JWT_AUDIENCE env vars are supplied. Development
ships with grep-friendly DEV-ONLY- placeholders so local + docker
flows keep working unchanged.

AuthenticationServiceCollectionExtensions flips ValidateIssuer +
ValidateAudience to true and wires ValidIssuer / ValidAudience via a
new ResolveRequiredOrThrow helper that all three required values
(secret, iss, aud) now share. JwtTokenFactory.Create + CreateExpired
gain optional iss / aud parameters (default null) so existing call
sites compile unchanged. JwtTestHelpers adds MintAuthenticated /
MintExpired wrappers that resolve iss + aud from env, plus
ResolveIssuerOrThrow / ResolveAudienceOrThrow. PerfBootstrap.MintToken
+ Program.cs JWT bootstrap migrated to the new surface so the perf
harness and the integration runner both validate against the same
contract.

Adds 4 fail-fast unit tests (missing/empty issuer + audience), 2
negative integration scenarios (WrongIssuer_Returns401,
WrongAudience_Returns401), and re-tags every existing integration
mint site via MintAuthenticated.

Compose, .env.example, run-tests.sh, run-performance-tests.sh all
load + export JWT_ISSUER + JWT_AUDIENCE alongside JWT_SECRET.

Resolves F-AUTH-2 (security_report.md + owasp_review.md). AC-7
(cross-repo suite/_docs/10_auth.md write) deferred — outside this
workspace; tracked in deploy_cycle2.md R3 follow-up.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 02:28:48 +03:00

5.1 KiB
Raw Blame History

Module: Tests/SatelliteProvider.Tests

Purpose

Unit test project for component-internal logic. Original AZ-2/AZ-3 era had only a placeholder dummy; the suite has since grown across the AZ-285..AZ-380 baseline + cycle 1 (AZ-484) + cycle 2 (AZ-487, AZ-488) tracks. The "dummy test only" note in older revisions of this file is obsolete — the project now hosts the full unit suite executed by scripts/run-tests.sh --unit-only and CI's 01-test.yml.

Public Interface (test classes)

Existing baseline (pre-cycle-2) test classes cover TileService, RegionService, RouteService, geo math, repositories, validators, idempotency, and migration helpers — not enumerated exhaustively here. Cycle-2 additions:

AZ-487 — JWT validation baseline

  • Authentication/AuthenticationServiceCollectionExtensionsTestsAddSatelliteJwt_RegistersJwtBearerScheme, AddSatelliteJwt_ThrowsOnMissingSecret, AddSatelliteJwt_ThrowsOnShortSecret.
  • Authentication/JwtTokenFactoryTestsCreate_ProducesTokenValidatedByMatchingParameters, CreateExpired_TokenFailsValidationWithLifetimeException, Create_WithExtraClaims_PropagatesClaimsThroughValidation, TamperSignature_TokenFailsValidationWithSignatureException.
  • Authentication/AuthenticationServiceCollectionExtensionsTests — covers AddSatelliteJwt registration + TokenValidationParameters shape (AZ-487, AZ-494). Includes AZ-494's fail-fast assertions: AddSatelliteJwt_ThrowsOnMissingIssuer, AddSatelliteJwt_ThrowsOnEmptyIssuer, AddSatelliteJwt_ThrowsOnMissingAudience, AddSatelliteJwt_ThrowsOnEmptyAudience, plus the updated _ConfiguresTokenValidationParameters_AsPerContract and _PrefersEnvironmentVariableOverConfiguration cases that assert ValidateIssuer = true + ValidIssuer + ValidateAudience = true + ValidAudience.
  • TestUtilities/JwtTokenFactory — helper that mints HS256 tokens with the same TokenValidationParameters used in production. Adjusts notBefore for negative-lifetime requests so JwtSecurityToken accepts the value and downstream lifetime validation can fire (IDX12401 workaround documented inline).

AZ-488 — UAV tile upload

  • UavTileQualityGateTests — one happy path + ≥ 1 reject path per rule (Rule 1 INVALID_FORMAT × 2, Rule 2 SIZE_OUT_OF_BAND × 2, Rule 3 WRONG_DIMENSIONS × 1, Rule 4 CAPTURED_AT_FUTURE / _TOO_OLD × 2, Rule 5 IMAGE_TOO_UNIFORM × 1) + rule-ordering determinism. Uses a FixedTimeProvider for Rule-4 isolation and UavTileImageFactory for deterministic JPEG fixtures.
  • UavTileUploadHandlerTests — end-to-end with a mocked ITileRepository: 1-item happy path, 3-item mixed batch (file written + InsertAsync called only for accepted), per-source UPSERT pass-through.
  • UavTileFilePathTests — verifies BuildUavTileFilePath produces tiles/uav/{z}/{x}/{y}.jpg for sample (z, x, y) tuples and that integer-typed coordinates make string-injection of path traversal impossible.
  • Authentication/PermissionsRequirementTestsPermissionsAuthorizationHandler correctly accepts a permissions claim shaped as a single string OR as a JSON array, rejects when the requested permission is absent, and short-circuits when the principal has no permissions claim at all.
  • TestUtilities/UavTileImageFactory — programmatic JPEG factories used by the gate + handler tests: CreateValidJpeg(width, height, seed), CreateUniformJpeg, CreatePng (for Rule 1 negative path).

Internal Logic

  • Tests follow Arrange / Act / Assert. Time-dependent paths inject a FixedTimeProvider (cycle-2 addition) so Rule 4 has deterministic age windows.
  • JwtSecurityTokenHandler.MapInboundClaims = false is set explicitly in JWT tests so claims read by their original names (sub, permissions, …) rather than the framework-remapped names.

Dependencies

  • Project references: SatelliteProvider.Services.TileDownloader, SatelliteProvider.Services.RegionProcessing, SatelliteProvider.Services.RouteManagement, SatelliteProvider.Common, SatelliteProvider.DataAccess, SatelliteProvider.Api (for the Authentication tests — added in AZ-487), SatelliteProvider.TestSupport (added by AZ-491; provides the canonical JwtTokenFactory consumed by both this project and SatelliteProvider.IntegrationTests).
  • NuGet: xUnit (2.5.3), Moq (4.20.72), FluentAssertions (8.8.0), coverlet.collector (6.0.0), Microsoft.NET.Test.Sdk (17.8.0), Microsoft.Extensions.* (Caching.Memory, Configuration, DI, Logging, Options, Http), Microsoft.AspNetCore.Authentication.JwtBearer 8.0.25 (consumed transitively via the ProjectReference to SatelliteProvider.Api; AZ-487 added the dependency at 8.0.21, AZ-496 bumped it to 8.0.25), SixLabors.ImageSharp 3.1.11 (added by AZ-488 for the gate tests).
  • appsettings.json copied to output (used by Authentication tests for the Jwt section binding scenario).

Consumers

  • CI pipeline (01-test.yml) and scripts/run-tests.sh --unit-only run dotnet test against this project.

Tests

This IS the test module. Cycle-2 added ~25 unit tests on top of the existing baseline; the full project executes in seconds (no external services required).