mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-22 03:11:13 +00:00
[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 commitsf64d0d7+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>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
# 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.cs` — `using 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.cs` — `JwtTestHelpers.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)`; `TamperSignature` → `JwtTokenFactory.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.
|
||||
@@ -0,0 +1,55 @@
|
||||
# Code Review Report — Batch 02 cycle 3
|
||||
|
||||
**Batch**: 02 (cycle 3) — AZ-491 (consolidate JWT test-mint helpers)
|
||||
**Date**: 2026-05-12
|
||||
**Verdict**: PASS_WITH_WARNINGS
|
||||
|
||||
## Findings
|
||||
|
||||
| # | Severity | Category | File:Line | Title |
|
||||
|---|----------|----------|-----------|-------|
|
||||
| 1 | Low | Maintainability | `SatelliteProvider.TestSupport/SatelliteProvider.TestSupport.csproj:10-11` | Pinned `System.IdentityModel.Tokens.Jwt` 7.0.3 lives alongside the API's transitive `Microsoft.AspNetCore.Authentication.JwtBearer` 8.0.25 |
|
||||
|
||||
### Finding Details
|
||||
|
||||
**F1: Pinned `System.IdentityModel.Tokens.Jwt` 7.0.3 lives alongside the API's transitive `Microsoft.AspNetCore.Authentication.JwtBearer` 8.0.25** (Low / Maintainability)
|
||||
|
||||
- Location: `SatelliteProvider.TestSupport/SatelliteProvider.TestSupport.csproj:10-11`
|
||||
- Description: TestSupport's two pinned packages (`Microsoft.IdentityModel.Tokens` 7.0.3, `System.IdentityModel.Tokens.Jwt` 7.0.3) are the same versions that the integration-tests project previously pinned directly. These are *not* the same package family as the API's `Microsoft.AspNetCore.Authentication.JwtBearer` 8.0.25 — they belong to a different .NET versioning track. Token-minting logic in the test library and token-validation logic in the API consume related-but-separate `IdentityModel` types, so this is structurally fine, but a future agent reading the csproj could be confused about why the test library is one major version behind the API. The pre-AZ-491 IntegrationTests csproj had the same pinning; this batch preserved it for parity.
|
||||
- Suggestion: Defer. The 7.0.x → 8.0.x bump for `System.IdentityModel.Tokens.Jwt` would be a separate hardening task — out of scope for AZ-491 (which is a refactor, not a dependency bump). If the team chooses to align minor versions, it should ship as a single coordinated bump across all `IdentityModel.*` references with regression coverage. For AZ-491 the existing pinning is preserved unchanged so behavior parity with cycle 2 is guaranteed.
|
||||
- Task: AZ-491
|
||||
|
||||
## Phase-by-Phase Summary
|
||||
|
||||
| Phase | Result | Notes |
|
||||
|-------|--------|-------|
|
||||
| 1. Context Loading | OK | AZ-491 spec read; 6 ACs identified; Option A chosen with documented rationale |
|
||||
| 2. Spec Compliance | OK | 6/6 ACs verified at code level. AC-2 + AC-3 wait on Step 16 final test gate; their structural prerequisites (call-site signatures preserved; subject explicitly passed) are in place |
|
||||
| 3. Code Quality | OK | New `JwtTokenFactory` is a stateless static class — SRP satisfied; eliminates duplication; regression-prevention comment on the `notBefore` branch is the only doc-comment kept (justified per `coderule.mdc` — references cycle-2 fix commits) |
|
||||
| 4. Security Quick-Scan | OK | No production-code change; no new attack surface. Token-minting moved into a test-only library that production code MUST NOT consume — the `module-layout.md` entry encodes this invariant |
|
||||
| 5. Performance Scan | OK (N/A) | Test-infrastructure refactor; no hot-path code |
|
||||
| 6. Cross-Task Consistency | OK | Single task in batch; the new code-review rule introduced by this same batch will prevent future duplicate-helper regressions |
|
||||
| 7. Architecture Compliance | OK | TestSupport is correctly placed in the Shared / Cross-Cutting layer of `module-layout.md`. It is referenced only by `Tests` + `IntegrationTests` (both via `ProjectReference`); zero production projects reference it. No cycle introduced. Layering: TestSupport sits *below* both test projects (foundation); both test projects sit *outside* the production layering table |
|
||||
|
||||
## Cross-cutting observations (info, no finding)
|
||||
|
||||
- The subject-value migration is the only semantic delta. Pre-AZ-491 the integration project's `MintValidToken(secret)` defaulted to `subject = "integration-tests"`. Post-AZ-491 the same call site now reads `JwtTokenFactory.Create(secret, JwtTestHelpers.DefaultSubject)` — `JwtTestHelpers.DefaultSubject = "integration-tests"` is still the canonical runner subject; the explicit-pass form preserves behavior exactly. Unit tests retain their own subject choices ("alice", "test-user", explicit per-test) unchanged.
|
||||
- The `using System.IdentityModel.Tokens.Jwt;` and `using Microsoft.IdentityModel.Tokens;` imports were removed from `JwtTestHelpers.cs` because the file no longer uses those namespaces after the mint logic moved out. No dead-import remains.
|
||||
- The `SatelliteProvider.Tests/TestUtilities/` folder is intentionally retained (not deleted) because it still owns `UavTileImageFactory.cs`. That fixture-factory is out of scope per AZ-491 § Excluded — a future task could consolidate it into TestSupport, but only if/when integration tests also need it.
|
||||
|
||||
## Baseline Delta
|
||||
|
||||
| Class | Count | Notes |
|
||||
|-------|-------|-------|
|
||||
| Carried over | 0 | No Architecture findings in baseline; nothing recurring |
|
||||
| Resolved | 1 (informal) | The cycle-2 duplicate-helper Maintainability pattern (documented in `LESSONS.md` 2026-05-11 testing entry + retrospective Pattern 1) is structurally closed by this batch. Not an Architecture-class baseline entry, so it does not appear in the cycle-1 baseline; tracked here for the cycle retrospective |
|
||||
| Newly introduced | 0 | — |
|
||||
|
||||
## Verdict Logic
|
||||
|
||||
- 0 Critical, 0 High, 0 Medium, 1 Low → **PASS_WITH_WARNINGS**
|
||||
- The single Low finding is informational (pre-existing version pinning preserved verbatim from cycle-2 IntegrationTests csproj); does not block commit per the implement-skill auto-fix gate.
|
||||
|
||||
## Recommendation to /implement
|
||||
|
||||
Proceed to commit + push + tracker transition (Steps 11-13).
|
||||
Reference in New Issue
Block a user