# Static Analysis (Cycle 13) **Date**: 2026-06-26 **Mode**: Delta scan **Scope**: AZ-1126 `capturedAt` → `DateTimeOffset` + `UtcOffsetRequiredDateTimeOffsetConverter`. Cycle-10 baseline remains authoritative elsewhere. **Files in scope**: - `SatelliteProvider.Common/DTO/UavTileMetadata.cs` - `SatelliteProvider.Common/Json/UtcOffsetRequiredDateTimeOffsetConverter.cs` - `SatelliteProvider.Api/Validators/UavTileMetadataValidator.cs` - `SatelliteProvider.Api/Validators/UavUploadValidationFilter.cs` - `SatelliteProvider.Services.TileDownloader/UavTileQualityGate.cs` - `SatelliteProvider.Services.TileDownloader/UavTileUploadHandler.cs` - Unit + integration tests for offset-less rejection **Method**: Read changed call sites; verify offset-less ISO strings rejected before persistence; confirm no new `ex.Message` echoes; grep for remaining `DateTimeKind` branching on upload path. ## Resolved findings (AZ-1126) ### F-AZ810-2 — `UavTileMetadata.CapturedAt` typed `DateTime` not `DateTimeOffset` (Low / Informational) — **RESOLVED** - **Location**: `UavTileMetadata.cs`, validators, quality gate, upload handler. - **Resolution**: `CapturedAt` is `DateTimeOffset` with `UtcOffsetRequiredDateTimeOffsetConverter` rejecting offset-less strings at deserialization. Freshness rules compare via `UtcDateTime`. Integration test `ItemCapturedAtOffsetLess_Returns400` binds the rejection path. ## Pass areas (cycle-13 delta) | Area | Result | |------|--------| | SQL injection | N/A — no SQL changes | | Hardcoded secrets | None introduced | | Information disclosure (400 paths) | Unchanged from AZ-1113 — static strings preserved | | New attack surface | Narrower — ambiguous timestamps rejected earlier | | Inventory read path | `TileInventoryEntry.CapturedAt` remains `DateTime?` — intentional, out of scope | ## Verdict **PASS** (cycle-13 delta) — F-AZ810-2 closed; zero new findings.