[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
@@ -0,0 +1,57 @@
# Static Analysis (Cycle 10)
**Date**: 2026-06-25
**Mode**: Delta scan
**Scope**: AZ-1113 REST 400 error message sanitization. Cycle-9 baseline remains authoritative for gRPC surface.
**Files in scope**:
- `SatelliteProvider.Api/GlobalExceptionHandler.cs`
- `SatelliteProvider.Api/Validators/UavUploadValidationFilter.cs`
- `SatelliteProvider.Services.TileDownloader/UavTileUploadHandler.cs`
- `SatelliteProvider.Tests/GlobalExceptionHandlerTests.cs`
- `SatelliteProvider.Tests/UavTileUploadHandlerTests.cs`
- `SatelliteProvider.IntegrationTests/UavUploadValidationTests.cs` (+ tightened assertions in region/route/inventory validation tests)
**Method**: Read changed call sites; verify static constants replace `ex.Message` / `badRequest.Message` echoes; grep for remaining raw exception text in client-facing 400 paths.
## Resolved findings (AZ-1113)
### F-AZ795-1 — `JsonException.Message` propagated in `GlobalExceptionHandler` (Low / A09) — **RESOLVED**
- **Location**: `GlobalExceptionHandler.cs` (deserializer branch).
- **Resolution**: `errors[<path>]` values use `JsonFieldErrorMessage` (`"The field value is invalid."`). Unit test `TryHandleAsync_DeserializationFailure_WritesValidationProblemDetailsWithJsonPath_AZ795` asserts no `TileInventoryRequest` type name leak.
### F-AZ795-2 — `BadHttpRequestException.Message` propagated as `detail` (Low / A09) — **RESOLVED**
- **Location**: `GlobalExceptionHandler.cs` (non-JSON bind branch).
- **Resolution**: `detail` uses `BadRequestDetailMessage` (`"The request could not be processed."`). Unit test `TryHandleAsync_BadHttpRequestExceptionWithoutJson_UsesStaticDetail` asserts no `Latitude` echo.
### F-AZ810-1 — `JsonException.Message` in `UavUploadValidationFilter` (Low / A09) — **RESOLVED**
- **Location**: `UavUploadValidationFilter.cs`.
- **Resolution**: `errors["metadata"]` uses `MetadataJsonParseError` (`` `metadata` could not be parsed as JSON. ``). Integration test `MetadataNotAnObject_Returns400` asserts response body lacks `System.`.
### F-AZ810-1b — Defence-in-depth path in `UavTileUploadHandler` (Low / A09) — **RESOLVED**
- **Location**: `UavTileUploadHandler.cs` metadata parse catch.
- **Resolution**: Envelope error uses same static string as filter. Unit test `HandleAsync_InvalidMetadataJson_ReturnsEnvelopeError`.
## Open carry-overs (unchanged by cycle 10)
### F-AZ810-2 — `UavTileMetadata.CapturedAt` typed `DateTime` not `DateTimeOffset` (Low / Informational)
- Still open — separate task per AZ-1113 exclusions.
## Pass areas (cycle-10 delta)
| Area | Result |
|------|--------|
| SQL injection | N/A — no SQL changes |
| Hardcoded secrets | None introduced |
| 5xx sanitization (AZ-353) | Unchanged — still sanitised |
| gRPC error messages | Unchanged from cycle-9 fix — still generic |
| New attack surface | None — message content only |
## Verdict
**PASS** (cycle-10 delta) — three REST information-disclosure carry-overs resolved; zero new findings.