Files
Oleksandr Bezdieniezhnykh c396740644
ci/woodpecker/push/01-test Pipeline was successful
ci/woodpecker/push/02-build-push Pipeline was successful
[AZ-491] Cycle 3 batch 2: consolidate JWT test-mint helpers into TestSupport
AZ-491 (3 SP): eliminate the cycle-2 duplicate of JWT-minting logic
that existed in both SatelliteProvider.Tests/TestUtilities/
JwtTokenFactory.cs (unit-side) and SatelliteProvider.IntegrationTests/
JwtTestHelpers.cs (integration-side), where the same Expires <
NotBefore bug needed parallel fixes in commits f64d0d7 + 11b7074.

Option A chosen: new SatelliteProvider.TestSupport class library
(no test framework) holds the canonical JwtTokenFactory.Create /
CreateExpired / TamperSignature. Both Tests and IntegrationTests
consume it via ProjectReference; production projects (Api, Common,
DataAccess, Services.*) cannot depend on it. The notBefore-shift
workaround is preserved with an inline regression-prevention comment
back-referencing the cycle-2 fix commits.

SatelliteProvider.IntegrationTests/JwtTestHelpers.cs is stripped to
runner-only concerns: ResolveSecretOrThrow, AttachDefaultAuthorization,
and the DefaultSubject = "integration-tests" constant. Call sites in
Program.cs, JwtIntegrationTests.cs, and UavUploadTests.cs (10 sites)
switched to JwtTokenFactory.* with JwtTestHelpers.DefaultSubject
explicitly passed for the runner subject - behavior parity preserved.

Dockerfile for IntegrationTests gets the new TestSupport csproj
in its pre-restore COPY layer. Api Dockerfile unchanged (TestSupport
is NOT a production dependency).

A new code-review SKILL.md Phase 6 checklist row flags near-identical
helper logic across test projects as a Medium / Maintainability
finding with explicit cycle-2 retro back-reference, so this whole
pattern stops at one occurrence.

module-layout.md adds a TestSupport Shared/Cross-Cutting entry
documenting the production-isolation invariant. tests_unit.md +
tests_integration.md updated to describe the consolidated layout.
sln updated.

Test-suite gate (AC-2 + AC-3) deferred to Step 16 Final Test Run
per implement-skill convention. Per-batch review verdict:
PASS_WITH_WARNINGS with 1 Low (pre-existing 7.0.3 version pin
preserved verbatim from cycle-2 IntegrationTests csproj for parity;
not blocking; deferred bump).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 01:32:24 +03:00

8.3 KiB

Batch Report — Batch 02 cycle 3

Batch: 02 (cycle 3) Tasks: AZ-491 (consolidate JWT test-mint helpers) Date: 2026-05-12

Task Results

Task Status Files Modified Tests AC Coverage Issues
AZ-491_consolidate_jwt_test_helpers Done 2 added + 12 modified + 1 deleted (see below) Existing 253 unit tests + integration JWT/UAV tests now consume the consolidated factory (Step 16 final gate) 6/6 ACs covered 0 blockers

AC Test Coverage: All covered (6 of 6)

Code Review Verdict: pending (this batch report precedes per-batch review)

Auto-Fix Attempts: 0

Stuck Agents: None

What was implemented

Chose Option A — new SatelliteProvider.TestSupport class library. Rationale: cleaner long-term layering (production code may NOT depend on test-support; integration tests do NOT acquire a dependency on unit tests); pre-stages AZ-492 which needs the same canonical mint surface for the perf harness.

Added

  • SatelliteProvider.TestSupport/SatelliteProvider.TestSupport.csproj (class library, .NET 8.0, no test framework). PackageReferences: Microsoft.IdentityModel.Tokens 7.0.3, System.IdentityModel.Tokens.Jwt 7.0.3.
  • SatelliteProvider.TestSupport/JwtTokenFactory.cs — canonical implementation. Exposes Create(secret, subject=DefaultSubject, lifetime, extraClaims, algorithm), CreateExpired(secret, subject), TamperSignature(token). The Expires <= NotBefore workaround (shift notBefore behind expires for non-positive lifetimes) is preserved with an inline comment back-referencing the cycle-2 commits f64d0d7 + 11b7074 to prevent regression.

Modified

  • SatelliteProvider.Tests/SatelliteProvider.Tests.csproj — added ProjectReference to TestSupport.
  • SatelliteProvider.Tests/Authentication/JwtTokenFactoryTests.csusing SatelliteProvider.Tests.TestUtilities;using SatelliteProvider.TestSupport;. The 4 existing test methods (Create_ProducesTokenValidatedByMatchingParameters, Create_WithExtraClaims_PropagatesClaimsThroughValidation, CreateExpired_TokenFailsValidationWithLifetimeException, TamperSignature_TokenFailsValidationWithSignatureException) now exercise the consolidated factory.
  • SatelliteProvider.Tests/Authentication/AuthenticationServiceCollectionExtensionsTests.cs — same namespace switch for the JwtTokenFactory.Create(envSecret) call site.
  • SatelliteProvider.IntegrationTests/SatelliteProvider.IntegrationTests.csproj — added ProjectReference to TestSupport; removed the explicit System.IdentityModel.Tokens.Jwt PackageReference (now flowing transitively through TestSupport).
  • SatelliteProvider.IntegrationTests/JwtTestHelpers.cs — stripped to runner-only concerns: JwtSecretEnvVar, DefaultSubject = "integration-tests", ResolveSecretOrThrow, AttachDefaultAuthorization. Removed MintValidToken, MintExpiredToken, TamperSignature. The using System.IdentityModel.Tokens.Jwt; / using Microsoft.IdentityModel.Tokens; imports were removed since they are no longer needed at this site.
  • SatelliteProvider.IntegrationTests/Program.csJwtTestHelpers.MintValidToken(jwtSecret)JwtTokenFactory.Create(jwtSecret, JwtTestHelpers.DefaultSubject). using SatelliteProvider.TestSupport; added.
  • SatelliteProvider.IntegrationTests/JwtIntegrationTests.cs — 3 call sites switched: MintExpiredToken(secret)JwtTokenFactory.CreateExpired(secret, JwtTestHelpers.DefaultSubject); MintValidToken(secret)JwtTokenFactory.Create(secret, JwtTestHelpers.DefaultSubject); TamperSignatureJwtTokenFactory.TamperSignature. using SatelliteProvider.TestSupport; added.
  • SatelliteProvider.IntegrationTests/UavUploadTests.cs — 6 call sites of JwtTestHelpers.MintValidToken(secret, extraClaims: ...) switched to JwtTokenFactory.Create(secret, JwtTestHelpers.DefaultSubject, extraClaims: ...). using SatelliteProvider.TestSupport; added.
  • SatelliteProvider.IntegrationTests/Dockerfile — added COPY ["SatelliteProvider.TestSupport/SatelliteProvider.TestSupport.csproj", "SatelliteProvider.TestSupport/"] before the dotnet restore step so the build context restores the new ProjectReference correctly. The API Dockerfile is unchanged (TestSupport is NOT a production dependency).
  • SatelliteProvider.sln — new project entry for TestSupport + ProjectConfigurationPlatforms rows.
  • .cursor/skills/code-review/SKILL.md Phase 6 — added a bolded checklist row: "Duplicate test helpers across test projects (AZ-491)" — flags near-identical credential-minting / fixture-generation logic across Tests + IntegrationTests + future perf harnesses as a Medium / Maintainability finding with recommended consolidation into SatelliteProvider.TestSupport. The cycle-2 retro f64d0d7 + 11b7074 precedent is cited inline so future agents understand this is a security-relevance maintenance risk, not just a style nit.
  • _docs/02_document/module-layout.md — added a new "TestSupport (added by AZ-491)" Shared / Cross-Cutting entry with Public API, PackageReferences, Consumed-by, and an explicit "NOT consumed by production projects" invariant. Documents what stays in JwtTestHelpers (runner-side concerns) vs. what moved.
  • _docs/02_document/modules/tests_unit.md and _docs/02_document/modules/tests_integration.md — updated to reflect the new dependency on SatelliteProvider.TestSupport and the split of mint logic (TestSupport) vs. runner concerns (JwtTestHelpers).

Deleted

  • SatelliteProvider.Tests/TestUtilities/JwtTokenFactory.cs (82 lines; content migrated verbatim to TestSupport with the notBefore regression-prevention comment expanded). The TestUtilities/ directory itself is retained because it still owns UavTileImageFactory.cs (out of scope per the AZ-491 task spec § Excluded).

AC Verification

AC Status Evidence
AC-1: Single source of truth — only one JwtSecurityToken( constructor call in test code rg "new JwtSecurityToken" returns only SatelliteProvider.TestSupport/JwtTokenFactory.cs:46
AC-2: Integration tests pass unchanged Deferred to Step 16 Call-site signatures preserved (subject explicitly passed via JwtTestHelpers.DefaultSubject); semantics identical
AC-3: Unit tests pass unchanged Deferred to Step 16 Identical method shapes; only the import statement changed
AC-4: Runner-side concerns preserved ResolveSecretOrThrow + AttachDefaultAuthorization + DefaultSubject unchanged in JwtTestHelpers.cs
AC-5: Cycle-2 IDX12401 fix preserved The notBefore shift branch is verbatim from the cycle-2 fixes, with an additional regression-prevention comment citing commits f64d0d7 + 11b7074
AC-6: Code-review rule lands .cursor/skills/code-review/SKILL.md Phase 6 now carries a duplicate-helper detection rule with severity, finding-category, and project-name guidance

Open follow-ups (non-blocking)

  • AZ-492 dependency: the perf harness PBI can now consume SatelliteProvider.TestSupport.JwtTokenFactory directly (or via a shell-based JWT minter that mirrors the same parameters). The _docs/_process_leftovers/2026-05-11_perf-pt07-harness.md leftover entry can be closed by AZ-492's implementation.
  • AZ-494 dependency: the planned iss / aud issuer/audience parameters on JwtTokenFactory.Create will be added by AZ-494 (still gated on external admin team input for the actual values). The current signature deliberately keeps issuer: null, audience: null so all current tests continue to pass against the existing ValidateIssuer = false / ValidateAudience = false API configuration.
  • Test-suite gate: AZ-491 AC-2 + AC-3 require ./scripts/run-tests.sh --full to be green. Deferred to Step 16 (Final Test Run). Risk for AZ-491 is moderate — the consolidation touches every JWT test call site — but every change is a syntactic rewrite, not a semantic one.

Next Batch: AZ-493 (Integration test DB-reset hook)

AZ-493 is 2 SP. It introduces a startup-side database-reset hook in SatelliteProvider.IntegrationTests/Program.cs to truncate FK-safe tables (tiles, regions, routes, ...) before the test suite runs, eliminating the wallclock-seeded _coordinateCounter workaround that UavUploadTests adopted in cycle 2. Independent of AZ-491; can run in parallel but we keep sequential per implement-skill convention.