Files
satellite-provider/_docs/02_document/modules/dataaccess_models.md
T
Oleksandr Bezdieniezhnykh 61612044fb [AZ-503] [AZ-504] Cycle 5 Steps 11-15 sync
Wrap up cycle 5 verification + documentation:
- Steps 10/11 wrap-up reports (implementation_completeness +
  implementation_report) for the AZ-503-foundation + AZ-504 batch.
- Step 12 test-spec sync: AZ-503-foundation/AZ-504 ACs appended;
  AZ-505 deferred ACs recorded.
- Step 13 update-docs: architecture, data-model, glossary, module-
  layout, uav-tile-upload contract (v1.1.0), DataAccess + Services
  + Tests module docs synced; new common_uuidv5.md module doc.
- Step 14 security audit: PASS_WITH_WARNINGS; 0 new Critical/High;
  2 new Low informational (F1 flightId provenance, F2 pgcrypto
  deploy gap).
- Step 15 performance test: PASS_WITH_INFRA_WARNINGS; PT-08
  passed twice (AZ-504 fix verified); PT-01/02 failed due to
  recurring local Docker/colima DNS cold-start (not an app
  regression). Cycle-3 perf-harness leftover stays OPEN with
  replay #5 documented.
- Autodev state moved to Step 16 (Deploy).

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

4.4 KiB

Module: DataAccess/Models

Purpose

Database entity classes that map directly to PostgreSQL tables via Dapper. Property names use PascalCase; column mapping is done with SQL aliases in repository queries.

Public Interface

TileEntity

Maps to tiles table.

  • Id (Guid) — AZ-503: deterministic UUIDv5 of {tile_zoom}/{tile_x}/{tile_y}/{source}/{flight_id or '00000000-0000-0000-0000-000000000000'} under namespace Uuidv5.TileNamespace. Stable across re-ingests; preserved on UPSERT conflict.
  • TileZoom (int), TileX (int), TileY (int)
  • Latitude, Longitude (double), TileSizeMeters (double), TileSizePixels (int)
  • ImageType (string), MapsVersion (string?), Version (int) — MapsVersion/Version are vestigial post-AZ-484 (kept nullable for backward compatibility; no longer part of the unique key)
  • Source (string) — AZ-484 producer wire value, defaults to TileSourceConverter.GoogleMapsWireValue ("google_maps"). Stored as plain string (not the TileSource enum) due to Dapper issue #259 — see _docs/LESSONS.md L-001. Convert via SatelliteProvider.Common.Enums.TileSourceConverter.{ToWireValue,FromWireValue}.
  • CapturedAt (DateTime, UTC) — AZ-484 imagery acquisition timestamp; drives the most-recent-across-sources selection.
  • FilePath (string), CreatedAt, UpdatedAt (DateTime)
  • FlightId (Guid?) — AZ-503: optional flight identifier. null for Google Maps tiles; populated from UavTileMetadata.FlightId on UAV uploads. Part of the AZ-503 UPSERT conflict key via COALESCE(flight_id, '00000000-0000-0000-0000-000000000000'::uuid), so two flights uploading the same (z, x, y) cell produce two separate rows.
  • LocationHash (Guid) — AZ-503 NOT NULL: deterministic UUIDv5 of {tile_zoom}/{tile_x}/{tile_y} under Uuidv5.TileNamespace. Identical across flights and sources for the same cell. Backfilled in migration 014 via a pg_temp.uuidv5 PL/pgSQL function; subsequent inserts compute it in the application layer (TileService + UavTileUploadHandler). Reserved for AZ-505's Leaflet covering index (POST /tiles/inventory) — not yet on a unique constraint.
  • ContentSha256 (byte[]?) — AZ-503: SHA-256 digest of the JPEG body. Application code enforces NOT NULL for new writes via TileService.BuildTileEntity (Google Maps) and UavTileUploadHandler.PersistAsync (UAV). The DB column is bytea NULL because legacy pre-migration rows could not be backfilled reliably from disk (file paths are volatile). See batch_02_cycle5_report.md "Low maintainability finding" for the rationale.
  • LegacyId (Guid?) — AZ-503: pre-migration id value, populated by migration 014 from every existing row's id. Preserves random-Guid provenance for one cycle (per AZ-503 Risk 1 mitigation) so external references to the old id can still be diagnosed before deletion.

RegionEntity

Maps to regions table.

  • Id (Guid), Latitude, Longitude (double), SizeMeters (double)
  • ZoomLevel (int), Status (string: "queued"/"processing"/"completed"/"failed")
  • CsvFilePath, SummaryFilePath (string?)
  • TilesDownloaded, TilesReused (int), StitchTiles (bool)
  • CreatedAt, UpdatedAt (DateTime)

RouteEntity

Maps to routes table.

  • Id (Guid), Name (string), Description (string?)
  • RegionSizeMeters (double), ZoomLevel (int)
  • TotalDistanceMeters (double), TotalPoints (int)
  • RequestMaps, MapsReady, CreateTilesZip (bool)
  • CsvFilePath, SummaryFilePath, StitchedImagePath, TilesZipPath (string?)
  • CreatedAt, UpdatedAt (DateTime)

RoutePointEntity

Maps to route_points table.

  • Id (Guid), RouteId (Guid), SequenceNumber (int)
  • Latitude, Longitude (double), PointType (string)
  • SegmentIndex (int), DistanceFromPrevious (double?)
  • CreatedAt (DateTime)

Internal Logic

Plain POCOs with no logic.

Dependencies

None.

Consumers

  • All repository implementations (TileRepository, RegionRepository, RouteRepository)
  • TileService — creates TileEntity instances for persistence
  • RegionService — creates/updates RegionEntity
  • RouteService — creates RouteEntity and RoutePointEntity
  • RouteProcessingService — reads entities from repositories
  • GoogleMapsDownloaderV2.GetTilesWithMetadataAsync — accepts IEnumerable<TileEntity> to check existing tiles

Data Models

These ARE the data model.

Configuration

None.

External Integrations

None.

Security

None.

Tests

No dedicated tests.