Files
satellite-provider/_docs/02_document/modules/common_dtos.md
T
Oleksandr Bezdieniezhnykh e3cd388577
ci/woodpecker/push/01-test Pipeline was successful
ci/woodpecker/push/02-build-push Pipeline was successful
[AZ-487] [AZ-488] docs: cycle 2 doc sync (task mode)
Step 13 (Update Docs) for cycle 2. Most cross-cutting docs were
already updated during Step 10 (architecture.md, glossary.md,
components/03_tile_downloader, modules/api_program.md, data_model.md,
contracts/api/uav-tile-upload.md). This commit completes the remaining
module-level + module-layout updates and writes the cycle-2 ripple log.

* modules/common_configs.md: + UavQualityConfig section and
  appsettings-section row (UavQuality).
* modules/common_dtos.md: + UavTileMetadata, UavTileBatchMetadataPayload,
  UavTileBatchUploadResponse, UavTileUploadResultItem, UavTileUploadStatus,
  UavTileRejectReasons (closed enumeration v1.0.0).
* module-layout.md: refresh Common (+ UavQualityConfig + UAV DTOs),
  TileDownloader (+ UavTileQualityGate, UavTileUploadHandler, +
  SixLabors.ImageSharp 3.1.11 PackageReference), and WebApi (+
  Authentication/*, DTOs/UavTileBatchUploadRequest, + JwtBearer 8.0.21
  PackageReference). Updates the "Last Updated" stamp to cycle 2.
* modules/tests_unit.md: replace the obsolete "only a dummy test"
  description; add cycle-2 AZ-487 / AZ-488 test classes
  (AuthenticationServiceCollectionExtensionsTests, JwtTokenFactoryTests,
  UavTileQualityGateTests, UavTileUploadHandlerTests, UavTileFilePathTests,
  PermissionsRequirementTests) + new ProjectReference / package
  references.
* modules/tests_integration.md: + JwtIntegrationTests, UavUploadTests
  (incl. wall-clock-seeded coordinate counter rationale from the Step 11
  fix), and the StubAndErrorContractTests update for the removed 501
  stub.
* ripple_log_cycle2.md (new): cycle-2 reverse-dependency scan results
  showing every importer of the new symbols resolves inside the three
  already-updated components (WebApi, TileDownloader, Common). No
  unexpected ripple, no heuristic fallback needed.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 00:04:05 +03:00

6.1 KiB
Raw Blame History

Module: Common/DTO

Purpose

Data transfer objects used across all layers — API requests/responses, inter-service communication, and queue messages.

Public Interface

GeoPoint

Geographic coordinate with tolerance-based equality.

  • Lat (double): latitude, JSON property "lat"
  • Lon (double): longitude, JSON property "lon"
  • Constructor: GeoPoint(), GeoPoint(double lat, double lon)
  • Equality: two points are equal if both coordinates differ by less than 0.00005 (PRECISION_TOLERANCE)
  • Operator overloads: ==, !=

Direction

Result of a directional calculation between two points.

  • Distance (double): distance in meters
  • Azimuth (double): bearing in degrees (0360)

SatTile

Represents a single map tile with its spatial bounds.

  • X, Y (int): tile coordinates in the slippy map scheme
  • Zoom (int): zoom level
  • LeftTop, BottomRight (GeoPoint): computed bounding box corners (via GeoUtils.TileToWorldPos)
  • Url (string): download URL
  • FileName → string: formatted as {X}.{Y}.{Zoom}.jpg

TileMetadata

Metadata about a stored tile (mirrors TileEntity but without DB-specific concerns).

  • Id (Guid), TileZoom, TileX, TileY (int), Latitude, Longitude (double)
  • TileSizeMeters (double), TileSizePixels (int), ImageType (string)
  • Version (int?), FilePath (string)
  • CreatedAt, UpdatedAt (DateTime)

RegionRequest

Queue message for async region processing.

  • Id (Guid), Latitude, Longitude (double), SizeMeters (double)
  • ZoomLevel (int), StitchTiles (bool)

RegionStatus

Response DTO for region status queries.

  • Id (Guid), Status (string), CsvFilePath, SummaryFilePath (string?)
  • TilesDownloaded, TilesReused (int), CreatedAt, UpdatedAt (DateTime)

RoutePoint

Input point in a route creation request.

  • Latitude (double, JSON: "lat"), Longitude (double, JSON: "lon")

RoutePointDto

Output point in a route response (includes computed fields).

  • Latitude, Longitude (double), PointType (string: "start"/"end"/"action"/"intermediate")
  • SequenceNumber, SegmentIndex (int), DistanceFromPrevious (double?)

CreateRouteRequest

API request body for route creation.

  • Id (Guid), Name (string), Description (string?)
  • RegionSizeMeters (double), ZoomLevel (int)
  • Points (List<RoutePoint>), Geofences (Geofences?)
  • RequestMaps (bool), CreateTilesZip (bool)

RouteResponse

API response for route queries.

  • All fields from the route entity plus Points (List<RoutePointDto>)
  • MapsReady (bool), TilesZipPath (string?)

GeofencePolygon

Axis-aligned bounding box defined by NW and SE corners.

  • NorthWest (GeoPoint?), SouthEast (GeoPoint?)

Geofences

Container for multiple geofence polygons.

  • Polygons (List<GeofencePolygon>)

UavTileMetadata (added AZ-488)

Per-tile metadata payload inside a UAV batch upload (POST /api/satellite/upload). Indexed-correlated with the multipart IFormFileCollection.

  • Latitude, Longitude (double)
  • TileZoom (int)
  • TileSizeMeters (double)
  • CapturedAt (DateTime, UTC; subject to AZ-488 Rule 4 future-skew / age checks)

UavTileBatchMetadataPayload (added AZ-488)

JSON envelope deserialized from the metadata form field of a UAV batch upload.

  • Items (IReadOnlyList<UavTileMetadata>)

UavTileBatchUploadResponse (added AZ-488)

Wire response for POST /api/satellite/upload. Returned with HTTP 200 regardless of per-item outcomes; envelope-level failures (auth, oversize, deserialization) bypass this shape.

  • Items (List<UavTileUploadResultItem>)

UavTileUploadResultItem (added AZ-488)

Per-item result inside UavTileBatchUploadResponse.

  • Index (int): zero-based index into the request batch.
  • Status (string): one of UavTileUploadStatus.Accepted / UavTileUploadStatus.Rejected.
  • TileId (Guid?): set on accept (matches the new/updated tiles.id); null on reject.
  • RejectReason (string?): closed-enum reason code from UavTileRejectReasons; null on accept.
  • RejectDetails (string?): short human-readable note. MUST NOT leak server-internal paths / exception types / hostnames (AZ-488 Security NFR; covered by SEC-11).

UavTileUploadStatus (added AZ-488, static string constants)

  • Accepted = "accepted"
  • Rejected = "rejected"

UavTileRejectReasons (added AZ-488, static string constants — closed enumeration v1.0.0)

Authoritative reject-reason codes for the UAV upload quality gate. Adding a new code requires a minor-version bump of _docs/02_document/contracts/api/uav-tile-upload.md.

  • InvalidFormat = "INVALID_FORMAT" — Rule 1 (content-type or JPEG magic bytes).
  • SizeOutOfBand = "SIZE_OUT_OF_BAND" — Rule 2 (bytes outside [MinBytes, MaxBytes]).
  • WrongDimensions = "WRONG_DIMENSIONS" — Rule 3 (image width/height ≠ MapConfig.TileSizePixels).
  • CapturedAtFuture = "CAPTURED_AT_FUTURE" — Rule 4 (timestamp ahead of now + CapturedAtFutureSkewSeconds).
  • CapturedAtTooOld = "CAPTURED_AT_TOO_OLD" — Rule 4 (timestamp older than MaxAgeDays).
  • ImageTooUniform = "IMAGE_TOO_UNIFORM" — Rule 5 (luminance variance below MinLuminanceVariance).
  • StorageFailure = "STORAGE_FAILURE" — reserved for the orphan-row-recovery path when the on-disk write succeeds but the DB UPSERT fails; surfaced per-item without failing the envelope (AZ-488 Reliability NFR).

Internal Logic

  • GeoPoint uses a precision tolerance of 0.00005 degrees (~5.5 meters) for equality comparison.
  • SatTile eagerly computes its bounding box corners on construction by calling GeoUtils.TileToWorldPos.

Dependencies

  • GeoPoint, Direction — no imports
  • SatTileSatelliteProvider.Common.Utils.GeoUtils
  • All others — no internal dependencies (or only System.Text.Json.Serialization)

Consumers

  • All services, repositories, and API endpoints consume these DTOs
  • RegionRequest is the message type for IRegionRequestQueue

Data Models

These ARE the data models (DTOs). They map closely to the database entities but are decoupled from the persistence layer.

Configuration

None consumed directly.

External Integrations

None.

Security

None.

Tests

No dedicated DTO tests.