[AZ-1113] Cycle 10 closeout: docs, perf harness, security

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-06-26 10:55:59 +03:00
parent 01d7e7d584
commit c79998bfa7
24 changed files with 600 additions and 46 deletions
+18 -2
View File
@@ -205,7 +205,7 @@
| Blackbox (negative) | 5 | — | — |
| Performance | 8 | 4 | 1 |
| Resilience | 6 | 4 | 3 |
| Security | 11 | 9 (AZ-487 AC-1..AC-7, AZ-488 AC-6, leak-hygiene NFR) | 1 (AZ-487 supersedes "No authentication") |
| Security | 14 | 9 (AZ-487 AC-1..AC-7, AZ-488 AC-6, leak-hygiene NFR) + 3 (AZ-1113 AC-1..AC-3) | 1 (AZ-487 supersedes "No authentication") |
| Resource Limits | 7 | 5 | 4 |
| Cycle 1 — AZ-484 (integration + unit) | 6 | 7/7 | — |
| Cycle 2 — AZ-487 (integration + unit + behavioral) | 4 integration + 3 unit + 1 behavioral | 8/8 | — |
@@ -215,7 +215,9 @@
| Cycle 6 — AZ-505 inventory + HTTP/2 + leaflet covering index (integration + blackbox + perf) | 3 integration files + 4 blackbox (BT-23..BT-26) + 1 perf (PT-09) | 7/7 (AC-1..AC-7; AC-7 is doc-only). Also resolves the 5 AZ-503 deferrals (AC-5, 6, 9, 10, 12). | — |
| Cycle 7 — AZ-794 + AZ-795 + AZ-796 strict inventory validation + z/x/y rename (integration + unit + blackbox + contract) | 1 integration file (`TileInventoryValidationTests`, 16 tests) + 1 unit file (`InventoryRequestValidatorTests`, 16 tests) + 1 blackbox (BT-27 with 16 sub-cases) + 1 new contract (`error-shape.md` v1.0.0) + 1 bumped contract (`tile-inventory.md` v2.0.0) | 12/12 in-scope (AZ-794 AC-1..AC-4, AZ-795 epic-level, AZ-796 AC-1..AC-7); 2 ACs (AZ-794 AC-3 + AZ-796 AC-5) are `◐ doc-verified at Step 13`. | — |
| Cycle 8 — AZ-808 + AZ-809 + AZ-810 + AZ-811 + AZ-812 strict validation sweep + region OSM rename (integration + unit + blackbox + contracts) | 4 integration files (`RegionRequestValidationTests`, `CreateRouteValidationTests`, `UavUploadValidationTests`, `GetTileByLatLonValidationTests` — ≥ 45 failure methods + 4 happy paths) + 5 unit files (`RegionRequestValidatorTests`, `CreateRouteRequestValidatorTests`, `RoutePointValidatorTests`, `GeofencePolygonValidatorTests`, `UavTileMetadataValidatorTests`, `UavTileBatchMetadataPayloadValidatorTests`, `GetTileByLatLonQueryValidatorTests` — ≥ 35 methods across the 4 endpoints) + 4 blackbox (BT-28..BT-31 with ≥ 41 sub-cases) + 4 new contracts (`region-request.md` v1.0.0, `route-creation.md` v1.0.0, `tile-latlon.md` v1.0.0, `uav-tile-upload.md` v1.2.0 bump) + 4 probe scripts | 41/41 in-scope (AZ-808 AC-1..AC-8, AZ-809 AC-1..AC-8, AZ-810 AC-1..AC-9, AZ-811 AC-1..AC-9, AZ-812 AC-1..AC-6); 8 ACs are `◐ doc-verified at Step 13` (per-endpoint OpenAPI / system-flows updates) + 2 advisory non-tested (AZ-809 AC-9, AC-10 — naming consistency surfaced for parent-suite). AZ-810 AC-9 (no AZ-488 regression) verified after the AZ-810 test-data coord-clamp fix (commit `b763da3`) — the original "traced by source" verification was a false-PASS; the green full-suite re-run is the binding evidence. | — |
| **Total** | **167** | **116/116 in-scope (100%); 2 AZ-504 ACs gated at Step 15; 10 ACs doc-verified at Step 13 (2 cycle-7 + 8 cycle-8); 2 advisory non-tested (cycle-8 AZ-809 AC-9/AC-10)** | **8/8 (100%)** |
| Cycle 9 — AZ-1074 + AZ-1075 gRPC RouteTileDelivery (integration + unit + blackbox) | 1 integration file (`RouteTileDeliveryGrpcTests`) + orchestrator unit tests + 1 blackbox (BT-32 with 6 sub-cases) + `SatelliteProvider.GrpcContracts` | 7/7 (AZ-1074 AC-1..AC-4, AZ-1075 AC-1..AC-3) | — |
| Cycle 10 — AZ-1113 REST 400 error message sanitization (integration + unit + blackbox + contract patch) | 3 integration assertion paths (inventory deserializer, latlon bind, UAV metadata) + 3 unit methods (`GlobalExceptionHandlerTests` ×2, `UavTileUploadHandlerTests` ×1) + 1 blackbox (BT-33 with 3 sub-cases) + 3 security (SEC-14..SEC-16) + `error-shape.md` v1.0.1 patch | 5/5 in-scope (AZ-1113 AC-1..AC-5) | — |
| **Total** | **170** | **121/121 in-scope (100%); 2 AZ-504 ACs gated at Step 15; 10 prior-cycle ACs doc-verified at Step 13 (2 cycle-7 + 8 cycle-8); 2 advisory non-tested (cycle-8 AZ-809 AC-9/AC-10)** | **8/8 (100%)** |
**Coverage shape notes (Cycle 5 — AZ-503 foundation):**
- AZ-503 was split mid-cycle (Option C, autodev Step 10 batch 2): 7 of 12 original ACs land here; 5 (AC-5, AC-6, AC-9, AC-10, AC-12) are deferred to AZ-505 with a `Blocks` link in Jira and an entry in `_docs/02_tasks/_dependencies_table.md`. The deferred rows above are marked `◐ deferred → AZ-505` so the matrix surfaces the scope boundary explicitly.
@@ -271,6 +273,11 @@
| AZ-1075 AC-1 | gRPC happy-path passes in docker-compose full run | Full `scripts/run-tests.sh --full` / `docker-compose.tests.yml` (cycle 9 Step 11 — passed) | ✓ |
| AZ-1075 AC-2 | Each invalid variant returns expected gRPC status | BT-32 sub-cases 13; `RouteTileDeliveryGrpcTests.RunInvalidRequests` | ✓ |
| AZ-1075 AC-3 | REST and gRPC tile metadata consistent for same route | BT-32 sub-case 5; `RouteTileDeliveryGrpcTests.RunRestConsistency` | ✓ |
| AZ-1113 AC-1 | `GlobalExceptionHandler` + inner `JsonException` → static `errors[]` message (no `.NET` type leak) | SEC-14, BT-33 sub-case 1 (blackbox); `GlobalExceptionHandlerTests.TryHandleAsync_DeserializationFailure_WritesValidationProblemDetailsWithJsonPath_AZ795` (unit); `TileInventoryValidationTests.UnknownNestedField_Returns400` + region/route/create-route validation tests asserting `"The field value is invalid."` (integration) | ✓ |
| AZ-1113 AC-2 | `BadHttpRequestException` without `JsonException` → static `detail` | SEC-15, BT-33 sub-case 2 (blackbox); `GlobalExceptionHandlerTests.TryHandleAsync_BadHttpRequestExceptionWithoutJson_UsesStaticDetail` (unit); `GetTileByLatLonValidationTests.LatTypeMismatch_Returns400` (integration) | ✓ |
| AZ-1113 AC-3 | `UavUploadValidationFilter` metadata parse → static `errors["metadata"]` | SEC-16, BT-33 sub-case 3 (blackbox); `UavUploadValidationTests.MetadataNotAnObject_Returns400` (integration; asserts no `System.` in body) | ✓ |
| AZ-1113 AC-4 | `UavTileUploadHandler` defense-in-depth metadata parse → static envelope error | `UavTileUploadHandlerTests.HandleAsync_InvalidMetadataJson_ReturnsEnvelopeError` (unit) | ✓ |
| AZ-1113 AC-5 | `error-shape.md` v1.0.1 Information Disclosure section documents static strings | doc-state AC; verified at Step 13 (Update Docs) | ✓ |
**Coverage shape notes (Cycle 9 — AZ-1074 + AZ-1075 gRPC RouteTileDelivery):**
- Cycle 9 adds the first gRPC blackbox surface alongside the existing REST suite. BT-32 is the binding blackbox spec; integration coverage lives in `RouteTileDeliveryGrpcTests` wired into both smoke and full suites via `Program.cs`.
@@ -278,3 +285,12 @@
- Cycle 9 Step 11 initially failed integration startup due to host port 5433 conflict with sibling project `fleet-viewer-dev-db`. Fixed by making `docker-compose.tests.yml` self-contained (no host port publishing — compose-internal networking only) and pointing `scripts/run-tests.sh` at that file alone for integration runs. Unit count is now 448 (includes orchestrator + gRPC validation tests).
- No perf / security NFRs declared in AZ-1074/1075 task specs beyond existing JWT-on-gRPC-metadata (inherits AZ-487/494 invariants). Load testing explicitly excluded.
- Cycle-update rule check: no NFR conflicts.
**Coverage shape notes (Cycle 10 — AZ-1113 REST 400 error message sanitization):**
- Cycle 10 is a **patch-level** contract tightening (`error-shape.md` v1.0.0 → v1.0.1) — no new HTTP routes, no new validation rules, no perf/security harness changes. The observable change is message *content* on existing 400 paths only; field paths and HTTP status codes are unchanged (AZ-1113 Compatibility NFR).
- Three call sites sanitized: `GlobalExceptionHandler` (JSON deserializer + non-JSON bind), `UavUploadValidationFilter`, `UavTileUploadHandler` (defense-in-depth). gRPC `DeliveryError` path was already sanitized in cycle 9 — out of scope per task spec.
- BT-33 + SEC-14..SEC-16 are deliberately **cross-cutting** rather than per-endpoint duplicates of BT-27..BT-31 — cycle-update rule 4 preserves existing traceability IDs; the cycle-8 rows remain the binding functional specs, cycle-10 rows add the message-content contract on top.
- Integration tests that previously asserted substring matches on raw `JsonException.Message` were updated to assert the static strings (`RegionRequestValidationTests`, `CreateRouteValidationTests`, `TileInventoryValidationTests`, `UavUploadValidationTests`). No new integration test *files* — assertion tightening on existing failure methods.
- AZ-1113 AC-5 is doc-only (`error-shape.md` §Information disclosure) — verified at Step 13 (`api_program.md` + contract doc).
- Step 11 evidence: smoke PASS 450/450 unit + integration EXIT:0 (~2.5m) per state file; full perf gate unchanged (REST-only PT scenarios still apply).
- Cycle-update rule check: no NFR conflicts. Inv-5 scope expands from 5xx-only (AZ-353) to include deserializer/binding 4xx — not a conflict because no prior cycle declared the opposite for 4xx message content.