# Cycle 3 — Documentation Ripple Log **Cycle**: 3 (AZ-495 doc convention + AZ-496 ASP.NET Core 8.0.25 bump + AZ-491 consolidate JWT test helpers + AZ-493 integration test DB reset hook + AZ-492 perf harness PT-07/PT-08 + AZ-494 JWT iss/aud validation) **Generated by**: `/document` skill (task mode) during autodev Step 13 (existing-code flow) **Resolution method**: each cycle-3 batch performed inline doc updates during implementation. Step 13 cycle-update mode verified completeness against the per-task spec and against `grep` of every new symbol (`JwtTokenFactory` post-AZ-491, `IntegrationTestResetGuard`, `IntegrationTestDatabaseReset`, `PerfBootstrap`, `MintAuthenticated` / `MintExpired` / `ResolveIssuerOrThrow` / `ResolveAudienceOrThrow`, `ResolveRequiredOrThrow`, `JWT_ISSUER` / `JWT_AUDIENCE`, `SEC-12` / `SEC-13`). ## Directly-changed source files (cycle 3) ### Code (production) - `SatelliteProvider.Api/Authentication/AuthenticationServiceCollectionExtensions.cs` (AZ-494: iss/aud constants, fail-fast `ResolveRequiredOrThrow`, `ValidateIssuer=true`, `ValidateAudience=true`) - `SatelliteProvider.Api/appsettings.json` (AZ-494: empty `Jwt.Issuer` + `Jwt.Audience` so prod fail-fast triggers) - `SatelliteProvider.Api/appsettings.Development.json` (AZ-494: `DEV-ONLY-` prefixed placeholders so local dev works) - `SatelliteProvider.Api/SatelliteProvider.Api.csproj` (AZ-496: `Microsoft.AspNetCore.Authentication.JwtBearer` 8.0.21 → 8.0.25; `Microsoft.AspNetCore.OpenApi` 8.0.21 → 8.0.25) ### Code (test-side) - `SatelliteProvider.TestSupport/*` (AZ-491: new project; canonical `JwtTokenFactory`. AZ-493: new `IntegrationTestResetGuard`. AZ-494: `JwtTokenFactory.Create` + `.CreateExpired` gained optional iss/aud parameters) - `SatelliteProvider.IntegrationTests/JwtTestHelpers.cs` (AZ-491: split runner-side concerns from the factory. AZ-494: added `ResolveIssuerOrThrow`, `ResolveAudienceOrThrow`, `MintAuthenticated`, `MintExpired`) - `SatelliteProvider.IntegrationTests/IntegrationTestDatabaseReset.cs` (AZ-493: new — runner-side reset using the TestSupport guard) - `SatelliteProvider.IntegrationTests/JwtIntegrationTests.cs` (AZ-491 + AZ-494: migrated to `MintAuthenticated`/`MintExpired`; added `WrongIssuer_Returns401` + `WrongAudience_Returns401`) - `SatelliteProvider.IntegrationTests/UavUploadTests.cs` (AZ-491 + AZ-493 + AZ-494: migrated to `MintAuthenticated`; removed wall-clock coordinate offset workaround) - `SatelliteProvider.IntegrationTests/Program.cs` (AZ-491 + AZ-492 + AZ-493 + AZ-494: bootstrap subcommand dispatch for `--mint-only`/`--gen-uav-fixture`; reset hook invocation; resolve secret+iss+aud at startup) - `SatelliteProvider.IntegrationTests/PerfBootstrap.cs` (AZ-492: new — perf bootstrap subcommands for `--mint-only`/`--gen-uav-fixture`. AZ-494: mint flow also resolves iss+aud) - `SatelliteProvider.IntegrationTests/SatelliteProvider.IntegrationTests.csproj` (AZ-491: `ProjectReference` to `SatelliteProvider.TestSupport`; removed `Microsoft.IdentityModel.JsonWebTokens` direct ref) - `SatelliteProvider.IntegrationTests/Dockerfile` (AZ-491: copy `SatelliteProvider.TestSupport` project) - `SatelliteProvider.Tests/Authentication/AuthenticationServiceCollectionExtensionsTests.cs` (AZ-494: 4 new fail-fast tests + updated existing tests; AZ-491: env-var save/restore pattern reused) - `SatelliteProvider.Tests/TestSupport/IntegrationTestResetGuardTests.cs` (AZ-493: new — unit tests for the two-guard model) - `SatelliteProvider.Tests/TestUtilities/JwtTokenFactory.cs` (AZ-491: deleted — duplicate of TestSupport) - `SatelliteProvider.Tests/SatelliteProvider.Tests.csproj` (AZ-491: `ProjectReference` to `SatelliteProvider.TestSupport`; AZ-496 picked up the 8.0.25 bump transitively via the `ProjectReference` to `SatelliteProvider.Api`) - `SatelliteProvider.sln` (AZ-491: registered `SatelliteProvider.TestSupport`) ### Infrastructure / config - `.env.example` (AZ-494: documented `JWT_ISSUER` + `JWT_AUDIENCE` with fail-fast contract and DEV-ONLY example values) - `docker-compose.yml` + `docker-compose.tests.yml` (AZ-494: `JWT_ISSUER` + `JWT_AUDIENCE` passed through to both `api` and `integration-tests` services. AZ-493: `INTEGRATION_TEST_DB_RESET` plumbed for the test runner) - `scripts/run-tests.sh` (AZ-493: `--keep-state` flag + DB reset plumbing. AZ-494: `JWT_ISSUER` + `JWT_AUDIENCE` env-var loading + fail-fast checks) - `scripts/run-performance-tests.sh` (AZ-492: pre-build, `--mint-only`/`--gen-uav-fixture` dispatch, PT-07 cold+warm distribution, PT-08 batch upload distribution, JWT attach across PT-01..PT-06. AZ-494: `JWT_ISSUER` + `JWT_AUDIENCE` loading and pass-through) ### Skills / conventions - `.cursor/skills/new-task/SKILL.md` (AZ-495: doc folder convention formalised) - `.cursor/skills/code-review/SKILL.md` (AZ-491: Phase 6 rule to prevent re-duplication of test helpers) ## Documentation ripple ### Architecture / module-level - `_docs/02_document/architecture.md` — JwtBearer version bump (AZ-496), token contract with `ValidateIssuer=true`/`ValidateAudience=true` (AZ-494), Security Architecture authentication paragraph (AZ-494). - `_docs/02_document/module-layout.md` — `SatelliteProvider.TestSupport` module entry (AZ-491), `IntegrationTestResetGuard` (AZ-493), `PerfBootstrap` justification + image-fixture dependency rationale (AZ-492), package version bumps (AZ-496). - `_docs/02_document/modules/api_program.md` — JWT authentication section (AZ-487 + AZ-494), package version bumps (AZ-496). - `_docs/02_document/modules/tests_unit.md` — Consolidated `AuthenticationServiceCollectionExtensionsTests` entry covering AZ-487 + AZ-494; `TestSupport` project reference (AZ-491); transitive 8.0.25 (AZ-496). - `_docs/02_document/modules/tests_integration.md` — `PerfBootstrap.cs` (AZ-492), `IntegrationTestDatabaseReset.cs` (AZ-493), `JwtTestHelpers` AZ-494 surface, AZ-494 new integration scenarios, env-var prerequisites. ### Test specs - `_docs/02_document/tests/traceability-matrix.md` — Rows added for AZ-491 AC-1..AC-6, AZ-493 AC-1..AC-6, AZ-494 AC-1..AC-7 (AC-7 deferred ◐), AZ-495, AZ-496; PT-07/PT-08 rows updated to ✓; AZ-487 / AZ-484 perf NFR rows updated to reference the AZ-492 harness. - `_docs/02_document/tests/security-tests.md` — SEC-12 (wrong iss → 401) and SEC-13 (wrong aud → 401) appended for AZ-494. - `_docs/02_document/tests/performance-tests.md` — PT-07 (cold+warm) and PT-08 (batch p95) moved from "Deferred" to "Implemented (AZ-492)". - `_docs/02_document/tests/environment.md` — Environment Variables table extended with `GOOGLE_MAPS_API_KEY`, `JWT_SECRET`, `JWT_ISSUER`, `JWT_AUDIENCE` (AZ-487, AZ-494), `INTEGRATION_TEST_DB_RESET` (AZ-493). ### Security artefacts - `_docs/05_security/security_report.md` — F-AUTH-2 flipped to **RESOLVED cycle 3 (AZ-494)**; verdict reconciliation + recommendations updated. - `_docs/05_security/owasp_review.md` — A07 status updated; residual "no token revocation list" recorded as a Low follow-up. ### Process / metrics - `_docs/03_implementation/deploy_cycle2.md` — R3 follow-up note flipped to **RESOLVED in cycle 3 (AZ-494)**. - `_docs/06_metrics/retro_2026-05-11_cycle2.md` — Action 2 (PT-07 leftover) marked **RESOLVED in cycle 3 (AZ-492)**. - `_docs/_process_leftovers/2026-05-11_perf-pt07-harness.md` — Deleted (resolved by AZ-492). ## Files NOT touched this cycle (by design) - `_docs/02_document/data_model.md` — no schema change. - `_docs/02_document/contracts/api/uav-tile-upload.md` — public contract unchanged (AZ-494 is a token-validation change, transparent to consumers that already produce correct `iss` + `aud`). - `_docs/02_document/components/03_tile_downloader/description.md` — no behavior change in the component. - Per-component descriptions under `_docs/02_document/components/0[1-5]_*` — none of the cycle-3 tasks added new functional behavior at the component layer. ## Open cross-repo doc ripple (AC-7 deferred) - `suite/_docs/10_auth.md` — AZ-494 AC-7 requires this doc (in the parent monorepo) to either name the production iss/aud values or note that satellite-provider validates them locally. This write is OUT OF SCOPE for satellite-provider's autodev (workspace-boundary rule). Documented in `deploy_cycle2.md` R3 follow-up. Will surface as a `_docs/_process_leftovers/` entry if the suite repo still needs the update after this autodev finishes.