using System.Text.Json.Serialization; namespace SatelliteProvider.Common.DTO; // AZ-488 / `uav-tile-upload.md` v1.0.0 — per-tile metadata supplied with each // batch item. `CapturedAt` is normalized to UTC by the upload handler before // reaching the persistence layer. // // AZ-503: `FlightId` is optional. When provided, two UAVs uploading the same // (z, x, y) cell from different flights coexist as distinct DB rows and write // to per-flight on-disk paths (./tiles/uav/{flight_id}/{z}/{x}/{y}.jpg). When // absent, the row is treated as flight-anonymous and the UPSERT collapses to // the AZ-484 "single row per (cell, source)" semantics via COALESCE-to-zero. // // AZ-810 (cycle 8) added [JsonRequired] to every non-optional axis so the // deserializer rejects partial payloads with HTTP 400 + ValidationProblemDetails // via GlobalExceptionHandler BEFORE the FluentValidation + IUavTileQualityGate // layers run. FlightId stays optional per AZ-503 anonymous-flight semantics. public record UavTileMetadata { [JsonRequired] public double Latitude { get; init; } [JsonRequired] public double Longitude { get; init; } [JsonRequired] public int TileZoom { get; init; } [JsonRequired] public double TileSizeMeters { get; init; } [JsonRequired] public DateTime CapturedAt { get; init; } public Guid? FlightId { get; init; } } public record UavTileBatchMetadataPayload { [JsonRequired] public List Items { get; init; } = new(); }