Files
satellite-provider/_docs/02_document/ripple_log_cycle7.md
T
Oleksandr Bezdieniezhnykh bc04ba7f99 [AZ-794] [AZ-795] [AZ-796] Cycle 7 Steps 12-15 sync (test-spec / docs / security / perf)
Step 12 (Test-Spec Sync): adds BT-27 for the AZ-796 9-rule
validation surface and 12 cycle-7 AC rows + Coverage Summary
update to traceability-matrix.md.

Step 13 (Update Docs): module-layout + module docs for the new
SatelliteProvider.Api/Validators namespace + GlobalExceptionHandler
+ updated TileInventory DTO; tests_unit + tests_integration
document the new InventoryRequestValidatorTests (16 unit tests
covering all 9 rules) + TileInventoryValidationTests (16
integration tests) + ProblemDetailsAssertions support;
glossary entries for Validation Problem Details / FluentValidation
/ Unmapped Member Handling; system-flows F8 (Tile Inventory Bulk
Lookup) expanded with deserializer + validator gates and a 13-row
Validation Surface table; data_parameters § Tile Inventory
documents the v2 input schema + constraints; ripple_log_cycle7
captures the doc-side ripple decisions.

Step 14 (Security Audit): 5-phase audit ran; verdict
PASS_WITH_WARNINGS (3 Low findings — D-AZ795-1 FluentValidation
12.0.0 -> 12.1.1 recommended bump, F-AZ795-1 JsonException.Message
leak in 400 detail, F-AZ795-2 BadHttpRequestException.Message leak).
No Critical / High; auth runs before validation (confirmed in
Program.cs); two NuGet additions (FluentValidation 12.0.0 +
.DependencyInjectionExtensions 12.0.0) both CVE-clean. Per-phase
reports plus consolidated security_report_cycle7.md.

Step 15 (Performance Test): docker compose stack used for perf
run, scripts/run-performance-tests.sh exited 0 with 8/8 scenarios
PASS (second consecutive clean exit-0); added PT-09 cycle-7 smoke
probe (v2 z/x/y schema, 2500-tile all-miss batch) measuring
min=27ms median=44ms p95=73ms max=86ms (13.7x under AZ-505 AC-4
1000ms budget). PT-07/08 improvements traced to the cycle-6 TLS
handshake-overhead identification, not application-side change.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-22 11:24:27 +03:00

11 KiB

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<T>, 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/TileYZ/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<GlobalExceptionHandler>() + UseExceptionHandler() middleware order (AZ-795).
    • AddValidatorsFromAssemblyContaining<Program>() + GlobalValidatorConfig.ApplyOnce() at startup (AZ-795 + AZ-796).
    • .WithValidation<TileInventoryRequest>() 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<TileInventoryRequest> + nested TileCoordValidator with 9 rules (XOR, per-array cap, Z/X/Y ranges).
  • SatelliteProvider.Api/Validators/ValidationEndpointFilter.cs (AZ-795, new) — generic IEndpointFilter<T> that runs the registered IValidator<T> and emits Results.ValidationProblem(...) on failure.
  • SatelliteProvider.Api/Validators/ValidationEndpointFilterExtensions.cs (AZ-795, new) — opt-in RouteHandlerBuilder.WithValidation<T>() 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<Program>()), InventoryRequestValidatorTests.cs, TileInventoryValidationTests.cs (indirect through the running API) WebApi (production), Tests (unit + integration)
ValidationEndpointFilter<T> / WithValidation<T>() 1 (current) + N-future Program.cs (MapPost("/api/satellite/tiles/inventory", …).WithValidation<TileInventoryRequest>()) 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.mdTile 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 (TileZoomZ, 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<T>, ProblemDetailsAssertions, and the error-shape.md contract without adding new infrastructure.