# Cycle 7 — Documentation Ripple Log **Cycle**: 7 (AZ-794 z/x/y rename + AZ-795 strict-validation epic + AZ-796 inventory-endpoint validation) **Generated by**: `/document` skill (task mode) during autodev Step 13 **Resolution method**: `Grep --type cs` against every new or changed symbol introduced by the three tasks. C# `using`-based import analysis on `TileCoord` (renamed fields + `[JsonRequired]`), `InventoryRequestValidator`, `ValidationEndpointFilter`, `GlobalExceptionHandler`, `GlobalValidatorConfig`, plus `ProblemDetailsAssertions` and `ValidatorTestModuleInitializer` in the test projects. No static-analyzer (NDepend, etc.) was used — the new surface is shallow and lives almost entirely behind `Program.cs` + the two new test files, so the literal usage scan is exhaustive. ## Directly-changed source files (cycle 7) - `SatelliteProvider.Common/DTO/TileInventory.cs` (AZ-794, modified) — `TileCoord` properties renamed `TileZoom/TileX/TileY` → `Z/X/Y` with `[JsonRequired]` on each; `TileInventoryEntry` echo fields renamed in lockstep. Wire field names are `z`/`x`/`y` per the camelCase resolver. - `SatelliteProvider.Api/Program.cs` (AZ-795 + AZ-796, modified) — - `ConfigureHttpJsonOptions(o => o.SerializerOptions.UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow)` (AZ-795). - `AddProblemDetails(...)` global ProblemDetails configurator (AZ-795). - `AddExceptionHandler()` + `UseExceptionHandler()` middleware order (AZ-795). - `AddValidatorsFromAssemblyContaining()` + `GlobalValidatorConfig.ApplyOnce()` at startup (AZ-795 + AZ-796). - `.WithValidation()` on the `MapPost("/api/satellite/tiles/inventory", …)` builder (AZ-796). - Endpoint summary / description bumped to reference `tile-inventory.md` v2.0.0 + `error-shape.md` v1.0.0. - `SatelliteProvider.Api/Validators/InventoryRequestValidator.cs` (AZ-796, **new**) — `AbstractValidator` + nested `TileCoordValidator` with 9 rules (XOR, per-array cap, Z/X/Y ranges). - `SatelliteProvider.Api/Validators/ValidationEndpointFilter.cs` (AZ-795, **new**) — generic `IEndpointFilter` that runs the registered `IValidator` and emits `Results.ValidationProblem(...)` on failure. - `SatelliteProvider.Api/Validators/ValidationEndpointFilterExtensions.cs` (AZ-795, **new**) — opt-in `RouteHandlerBuilder.WithValidation()` extension; intentionally orthogonal to per-endpoint authorization configuration. - `SatelliteProvider.Api/Validators/GlobalValidatorConfig.cs` (AZ-795 + AZ-796, **new**) — idempotent `ApplyOnce()` configures FluentValidation's global `PropertyNameResolver` to camelCase (`tiles[0].z` instead of `Tiles[0].Z`) per `error-shape.md` Inv-4. Called from `Program.cs` and from the unit-test assembly's `[ModuleInitializer]`. - `SatelliteProvider.Api/GlobalExceptionHandler.cs` (AZ-795, **new**) — `IExceptionHandler` that intercepts `BadHttpRequestException(JsonException)` (the System.Text.Json strict-parse path: unknown fields, `[JsonRequired]` violations, type mismatches) and emits the same `ValidationProblemDetails` shape that FluentValidation produces. 5xx paths pass through with sanitised body + correlation id (continuation of the AZ-353 contract). - `_docs/02_document/contracts/api/error-shape.md` (AZ-795, **new**) — v1.0.0 uniform error-body contract. Single source of truth for the `ValidationProblemDetails` wire shape across both layers and across all future child tickets of the AZ-795 epic. - `_docs/02_document/contracts/api/tile-inventory.md` (AZ-794 + AZ-796, modified) — bumped to v2.0.0; documents the 9 validation rules + the `z/x/y` rename; `Producer task` block extended to credit AZ-505 + AZ-794 + AZ-796. - `SatelliteProvider.Tests/Validators/InventoryRequestValidatorTests.cs` (AZ-796, **new**) — 16 unit tests against the validator via `TestValidate(...)`. - `SatelliteProvider.Tests/TestSupport/ValidatorTestModuleInitializer.cs` (AZ-795, **new**) — calls `GlobalValidatorConfig.ApplyOnce()` at test-assembly load. - `SatelliteProvider.IntegrationTests/ProblemDetailsAssertions.cs` (AZ-795, **new**) — shared response-shape helper consumed by every future per-endpoint validation test. - `SatelliteProvider.IntegrationTests/TileInventoryValidationTests.cs` (AZ-796, **new**) — 16 end-to-end tests; one per validation rule (with sub-cases) plus a happy path. - `SatelliteProvider.IntegrationTests/TileInventoryTests.cs` (AZ-794, modified) — updated `tileZoom/tileX/tileY` JSON payloads to `z/x/y`; reduced the synthetic x/y values to stay inside the slippy-map bounds enforced by `TileCoordValidator`. - `SatelliteProvider.IntegrationTests/IdempotentPostTests.cs` (AZ-795, modified) — route-point payload PascalCase → camelCase (`lat`/`lon`) because the post-cycle-7 strict deserializer no longer silently drops the wrong field names that the test had been sending pre-cycle 7. - `scripts/probe_inventory_validation.sh` (AZ-796, **new**) — manual probe script; exercises each failure mode end-to-end and captures responses for change-review evidence. ## Importer scan results | Symbol | Importer count | Importer files | Component touched | |--------|----------------|----------------|-------------------| | `TileCoord.Z` / `TileCoord.X` / `TileCoord.Y` (renamed properties; wire names `z`/`x`/`y`) | 5 | `TileService.cs` (`Uuidv5.LocationHashForTile`), `TileInventoryTests.cs`, `TileInventoryValidationTests.cs`, `InventoryRequestValidatorTests.cs`, `TileInventory.cs` self-references in `TileInventoryEntry` | TileDownloader (production), Tests (unit + integration) | | `[JsonRequired]` on `TileCoord.Z/X/Y` | n/a | enforced at runtime by `System.Text.Json` + caught by `GlobalExceptionHandler` (no compile-time consumer) | WebApi (deserializer + handler) | | `InventoryRequestValidator` / `TileCoordValidator` | 3 | `Program.cs` (assembly-scan registration via `AddValidatorsFromAssemblyContaining()`), `InventoryRequestValidatorTests.cs`, `TileInventoryValidationTests.cs` (indirect through the running API) | WebApi (production), Tests (unit + integration) | | `ValidationEndpointFilter` / `WithValidation()` | 1 (current) + N-future | `Program.cs` (`MapPost("/api/satellite/tiles/inventory", …).WithValidation()`) | WebApi | | `GlobalValidatorConfig.ApplyOnce` | 2 | `Program.cs` (production), `ValidatorTestModuleInitializer.cs` (unit-test assembly load) | WebApi, Tests (unit) | | `GlobalExceptionHandler` | 1 | `Program.cs` (DI registration + middleware order) | WebApi | | `ProblemDetailsAssertions.AssertValidationProblem` | 1 (current) + N-future | `TileInventoryValidationTests.cs`; designed to be reused by every future per-endpoint child task under AZ-795 | Tests (integration) | | `FluentValidation` package (12.0.0) | 4 | `SatelliteProvider.Api.csproj`, `SatelliteProvider.Tests.csproj`, `InventoryRequestValidator.cs`, `InventoryRequestValidatorTests.cs` | WebApi, Tests (unit) | ## Doc refresh decisions All importers land inside components that already received targeted updates during Step 10 (Implement) and this Step 13: - **WebApi (`Program.cs`)** — updated `_docs/02_document/modules/api_program.md` with the new endpoint description, the new `Api/Validators` section (filter + extensions + validator + global config), the new `Api/GlobalExceptionHandler` section, expanded DI registration (ProblemDetails + GlobalExceptionHandler + strict JSON + FluentValidation), and the new dependency entries. - **Common (DTOs)** — updated `_docs/02_document/modules/common_dtos.md`: `TileCoord` now documents the rename + `[JsonRequired]` markers + ValidationProblemDetails fallout; `TileInventoryRequest` documents the XOR enforcement by `InventoryRequestValidator`; `TileInventoryEntry` documents the rename echo; `TileInventoryLimits` documents the validator as the enforcer. - **Validators (new subfolder)** — captured under `module-layout.md` with two new entries: - `Api/Validators/{InventoryRequestValidator,TileCoordValidator,ValidationEndpointFilter,ValidationEndpointFilterExtensions,GlobalValidatorConfig}`. - `Api/GlobalExceptionHandler`. - **Tests (unit)** — updated `_docs/02_document/modules/tests_unit.md` with the new "AZ-795 + AZ-796 — strict inventory validation (cycle 7)" subsection, the new `[ModuleInitializer]` helper, the new FluentValidation/TestHelper NuGet entry, and the cycle 7 unit-suite totals (311 tests). - **Tests (integration)** — updated `_docs/02_document/modules/tests_integration.md`: new `TileInventoryValidationTests` entry, new `ProblemDetailsAssertions` helper entry, cycle-7 stability note on `TileInventoryTests`, and the cycle-7 fix on `IdempotentPostTests` (payload rename forced by strict deserializer). System-level docs also updated this pass: - `architecture.md` — already carries the new "§ 9 Input Validation (AZ-795)" section (was added during the implementation phase along with the validator coverage table). No further changes needed; the AZ-794 wire-format rename is captured at the inventory-contract level rather than in architecture prose. - `system-flows.md` — F8 flow header updated to credit cycle 7; sequence diagram annotated with the two new validation gates (deserializer + filter); Validation Surface table expanded from 4 rows to 13 rows covering every failure mode from `error-shape.md`. - `glossary.md` — `Tile Inventory` entry updated to v2.0.0 wire shape + cite the cycle-7 validator; added three new entries: `Validation Problem Details`, `FluentValidation`, `Unmapped Member Handling`. - `module-layout.md` — Last Updated bumped + cycle-7 changelog line prepended. - `tests/blackbox-tests.md` and `tests/traceability-matrix.md` — updated during Step 12 (Test-Spec Sync): BT-27 added + 12 AC rows added (AZ-794 AC-1..AC-4 + AZ-795 epic-level + AZ-796 AC-1..AC-7) + Coverage Summary refresh. ## No-ripple components These components were NOT touched by cycle-7 changes and require no doc update: - **DataAccess** — no schema or repository signature changes in cycle 7. The cycle-6 `tiles_leaflet_path` covering index and the cycle-5 identity columns are unaffected by the wire-format rename or by the new validators. - **TileDownloader (`TileService.GetInventoryAsync`)** — the algorithm is unchanged: it still computes `Uuidv5.LocationHashForTile(z, x, y)` per coord. Only the *property names* on the DTO changed (`TileZoom` → `Z`, etc.); the value contract is identical. - **RegionProcessing / RouteManagement** — no imports against cycle-7 symbols. - **DataAccess migrations** — no new migration in cycle 7; the existing identity columns and indices already carry the production load. ## Parse-failure / heuristic notes None — every symbol resolved via direct `Grep --type cs`. No fallback heuristic was needed. The cycle 7 surface is intentionally narrow (3 tasks, all WebApi-layer concerns) which keeps the ripple log short. ## AZ-795 epic posture The `architecture.md` § 9 table classifies all other public endpoints as `partial` and tags them as "future AZ-795 child" — the epic remains open. Cycle 7 lands the shared infrastructure + the first per-endpoint application (AZ-796). Subsequent child tickets will reuse `ValidationEndpointFilter`, `ProblemDetailsAssertions`, and the `error-shape.md` contract without adding new infrastructure.