Files
satellite-provider/_docs/02_document/00_discovery.md
T
Oleksandr Bezdieniezhnykh af4219fce6
ci/woodpecker/push/01-test Pipeline was successful
ci/woodpecker/push/02-build-push Pipeline was successful
[AZ-500] Cycle 4 Steps 12-15 sync (test-spec / docs / security / perf)
Step 12 (Test-Spec Sync) - cycle-update mode
  - traceability-matrix: 8 AZ-500 AC rows + .NET 10 runtime
    restriction supersession + Cycle-4 coverage shape note
    (no new tests; ACs verified by re-running existing 78-test
    suite + build pipeline + manifest grep)

Step 13 (Update Docs) - task mode
  - FINAL_report, 00_discovery, architecture, module-layout,
    api_program, tests_unit: .NET 8 -> .NET 10 / C# 12 -> 14 /
    Swashbuckle 6.6.2 -> 10.1.7 + Microsoft.OpenApi 2.x
    refactor note in api_program; Serilog.AspNetCore 8.0.3
    fallback documented inline per AZ-500 Risk #4
  - deployment/{containerization, ci_cd_pipeline}: Docker
    aspnet/sdk:8.0 -> :10.0
  - ripple_log_cycle4: empty import-graph ripple recorded
    (Program.cs is entry point; ParameterDescriptionFilter only
    consumed by Program.cs; csproj/global.json/Dockerfile have
    no import edges)

Step 14 (Security Audit) - resume mode
  - dependency_scan_cycle4: AZ-500 19-package delta scanned;
    cycle-3 D1+D3 (CVE-2026-26130) closed by major-version
    bump; cycle-3 D2 (Test.Sdk 17.8.0 NuGet.Frameworks flag)
    carried over - explicitly out of AZ-500 scope
  - security_report_cycle4: PASS_WITH_WARNINGS (only carry-over
    Medium open; AZ-500 introduced 0 new Critical/High); cycle-3
    static_analysis/owasp_review/infrastructure_review carried
    forward unchanged (AZ-500 made no source-level edits to
    those surfaces)

Step 15 (Performance Test) - perf mode, full default-param run
  - perf_2026-05-12_cycle4: 7 Pass + 1 Unverified (PT-08 hit
    pre-existing scripts/run-performance-tests.sh:417 grep-
    pipefail bug, NOT a .NET 10 regression)
  - PT-07 warm p95 = 301ms (7.7x improvement vs cycle-3 short
    variant - .NET 10 pipeline + N=20 dilution); cold p95 =
    2782ms (-14%); PT-06 90ms (-49%)
  - AZ-500 NFR (Performance) MET for 7/8 scenarios
  - Cycle-3 perf-harness leftover updated with replay #3
    results; STAYS OPEN per AZ-500 Constraint (deletes only on
    fully clean run)

Recommended follow-up PBIs (out of cycle-4 scope, surfaced for
the backlog):
  - 1 SP fix scripts/run-performance-tests.sh:416-417 grep-
    pipefail (replace grep -o ... | wc -l with grep -c ... ||
    true) - unblocks PT-08 + closes the cycle-3 perf leftover
  - 3 SP migrate WithOpenApi(...) callsites to ASP.NET Core 10
    minimal-API metadata extensions (clears 8 ASPDEPR002
    warnings; recorded in batch_01_cycle4_review.md)
  - 1 SP Microsoft.OpenApi 2.x nullable cleanup (CS8604 in
    ParameterDescriptionFilter.cs:25)
  - 1 SP bump Microsoft.NET.Test.Sdk 17.8.0 -> 17.13.0+
    (closes cycle-3 D2 NuGet.Frameworks transitive flag)

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

13 KiB

Codebase Discovery

Directory Tree

satellite-provider/
├── SatelliteProvider.sln
├── global.json
├── docker-compose.yml
├── docker-compose.tests.yml
├── goal.md
├── README.md
├── AGENTS.md
├── .woodpecker/
│   ├── 01-test.yml
│   └── 02-build-push.yml
├── SatelliteProvider.Api/
│   ├── Dockerfile
│   ├── Program.cs
│   ├── SatelliteProvider.Api.csproj
│   ├── Properties/launchSettings.json
│   ├── appsettings.json
│   └── appsettings.Development.json
├── SatelliteProvider.Common/
│   ├── SatelliteProvider.Common.csproj
│   ├── Configs/
│   │   ├── DatabaseConfig.cs
│   │   ├── MapConfig.cs
│   │   ├── ProcessingConfig.cs
│   │   └── StorageConfig.cs
│   ├── DTO/
│   │   ├── CreateRouteRequest.cs
│   │   ├── Direction.cs
│   │   ├── GeoPoint.cs
│   │   ├── GeofencePolygon.cs
│   │   ├── RegionRequest.cs
│   │   ├── RegionStatusResponse.cs
│   │   ├── RoutePoint.cs
│   │   ├── RoutePointDto.cs
│   │   ├── RouteResponse.cs
│   │   ├── SatTile.cs
│   │   └── TileMetadata.cs
│   ├── Interfaces/
│   │   ├── IRegionRequestQueue.cs
│   │   ├── IRegionService.cs
│   │   ├── IRouteService.cs
│   │   ├── ISatelliteDownloader.cs
│   │   └── ITileService.cs
│   └── Utils/
│       └── GeoUtils.cs
├── SatelliteProvider.DataAccess/
│   ├── SatelliteProvider.DataAccess.csproj
│   ├── DatabaseMigrator.cs
│   ├── Migrations/
│   │   ├── 001_CreateTilesTable.sql
│   │   ├── 002_CreateRegionsTable.sql
│   │   ├── 003_CreateIndexes.sql
│   │   ├── 004_AddVersionColumn.sql
│   │   ├── 005_CreateRoutesTables.sql
│   │   ├── 006_AddStitchTilesToRegions.sql
│   │   ├── 007_AddRouteMapFields.sql
│   │   ├── 008_AddGeofenceFlagToRouteRegions.sql
│   │   ├── 009_AddGeofencePolygonIndex.sql
│   │   ├── 010_AddTilesZipToRoutes.sql
│   │   └── 011_AddTileCoordinates.sql
│   ├── Models/
│   │   ├── RegionEntity.cs
│   │   ├── RouteEntity.cs
│   │   ├── RoutePointEntity.cs
│   │   └── TileEntity.cs
│   └── Repositories/
│       ├── IRegionRepository.cs
│       ├── IRouteRepository.cs
│       ├── ITileRepository.cs
│       ├── RegionRepository.cs
│       ├── RouteRepository.cs
│       └── TileRepository.cs
├── SatelliteProvider.Services/
│   ├── SatelliteProvider.Services.csproj
│   ├── GoogleMapsDownloaderV2.cs
│   ├── RegionProcessingService.cs
│   ├── RegionRequestQueue.cs
│   ├── RegionService.cs
│   ├── RouteProcessingService.cs
│   ├── RouteService.cs
│   └── TileService.cs
├── SatelliteProvider.Tests/
│   ├── SatelliteProvider.Tests.csproj
│   ├── GoogleMapsDownloaderTests.cs
│   └── appsettings.json
└── SatelliteProvider.IntegrationTests/
    ├── SatelliteProvider.IntegrationTests.csproj
    ├── Dockerfile
    ├── Program.cs
    ├── Models.cs
    ├── BasicRouteTests.cs
    ├── ComplexRouteTests.cs
    ├── ExtendedRouteTests.cs
    ├── RegionTests.cs
    ├── TileTests.cs
    └── RouteTestHelpers.cs

Tech Stack

Category Technology Version
Language C# 14 (.NET 10) — was C# 12 / .NET 8.0 through cycle 3 (AZ-500)
Framework ASP.NET Core (Minimal API) 10.0 — was 8.0 through cycle 3 (AZ-500)
Database PostgreSQL 16 (Docker image)
ORM/Data Access Dapper 2.1.35
DB Migrations DbUp (PostgreSQL) 6.0.3
Logging Serilog (Console + File) 8.0.3 (Serilog.AspNetCore — fallback retained on .NET 10 per AZ-500 Risk #4: no 10.x line published; restores cleanly via netstandard 2.0)
Image Processing SixLabors.ImageSharp 3.1.11
JSON Serialization Newtonsoft.Json + System.Text.Json 13.0.4
API Docs Swagger / Swashbuckle 10.1.7 (was 6.6.2; bumped by AZ-500 to land Microsoft.OpenApi 2.x compat — required by ASP.NET Core 10)
HTTP Client IHttpClientFactory built-in
Containerization Docker (multi-stage) -
Orchestration Docker Compose -
CI/CD Woodpecker CI -
Unit Testing xUnit + Moq + FluentAssertions 2.5.3 / 4.20.72 / 8.8.0
Integration Testing Console app (custom harness) -
SDK .NET 10 (latestMinor rollForward) 10.0.0+ — was .NET 8.0 / 8.0.0+ through cycle 3 (AZ-500)

Dependency Graph

Project References

SatelliteProvider.Common          (leaf — no project references)
SatelliteProvider.DataAccess      (leaf — no project references; NuGet: Dapper, Npgsql, DbUp)
SatelliteProvider.Services        → Common, DataAccess
SatelliteProvider.Api             → Common, DataAccess, Services
SatelliteProvider.Tests           → Services, Common
SatelliteProvider.IntegrationTests (standalone console app, no project references)

Mermaid Dependency Diagram

graph TD
    Api[SatelliteProvider.Api] --> Services[SatelliteProvider.Services]
    Api --> DataAccess[SatelliteProvider.DataAccess]
    Api --> Common[SatelliteProvider.Common]
    Services --> DataAccess
    Services --> Common
    Tests[SatelliteProvider.Tests] --> Services
    Tests --> Common
    IntTests[SatelliteProvider.IntegrationTests] -.->|HTTP calls| Api

Topological Processing Order

Leaf modules first, then dependent modules:

  1. SatelliteProvider.Common — DTOs, interfaces, configs, geo utilities (no internal dependencies)
  2. SatelliteProvider.DataAccess — entities, repositories, migrations (no project dependencies)
  3. SatelliteProvider.Services — business logic (depends on Common + DataAccess)
  4. SatelliteProvider.Api — web layer, DI, endpoints (depends on all above)
  5. SatelliteProvider.Tests — unit tests (depends on Services + Common)
  6. SatelliteProvider.IntegrationTests — integration tests via HTTP (standalone)

Entry Points

  • Application entry: SatelliteProvider.Api/Program.cs — minimal API startup, DI registration, DB migration, endpoint mapping
  • Background services: RegionProcessingService (queue consumer), RouteProcessingService (polling loop)
  • Integration test entry: SatelliteProvider.IntegrationTests/Program.cs

Leaf Modules

  • SatelliteProvider.Common/Configs/* — configuration POCOs
  • SatelliteProvider.Common/DTO/* — data transfer objects
  • SatelliteProvider.Common/Interfaces/* — service contracts
  • SatelliteProvider.Common/Utils/GeoUtils.cs — static geo math utilities
  • SatelliteProvider.DataAccess/Models/* — database entity classes
  • SatelliteProvider.DataAccess/Migrations/* — SQL migration scripts

Cycles

No dependency cycles detected. The dependency graph is a clean DAG.

External Integrations

Integration Module Protocol
Google Maps Tile API GoogleMapsDownloaderV2 HTTPS (tile.googleapis.com, mt*.google.com)
PostgreSQL All repositories TCP (Npgsql, port 5432)
File system (tiles) StorageConfig, TileService, GoogleMapsDownloaderV2 Local FS (./tiles/)
File system (output) RegionService, RouteProcessingService Local FS (./ready/)
File system (logs) Serilog Local FS (./logs/)

Existing Documentation

  • README.md — comprehensive API docs, architecture overview, configuration guide
  • AGENTS.md — agent-oriented documentation with architecture details and conventions
  • goal.md — original requirements and TODO items
  • Swagger/OpenAPI — auto-generated at runtime (/swagger)

Test Structure

  • Unit tests: SatelliteProvider.Tests/ — xUnit, currently contains only a dummy test (DummyTests.Dummy_ShouldWork)
  • Integration tests: SatelliteProvider.IntegrationTests/ — console app that runs against a live API+DB instance in Docker. Tests cover tile downloads, region requests, route creation with intermediate points, geofencing, extended routes with map requests.

CI/CD

  • Woodpecker CI pipelines in .woodpecker/:
    • 01-test.yml: runs dotnet restore + dotnet test on push/PR to dev/stage/main (ARM64)
    • 02-build-push.yml: builds Docker image and pushes to private registry (depends on 01-test, ARM64 matrix with AMD64 slot commented out)

Updates Since Baseline

Treat the directory tree, dependency listing, and test-structure section above as a 2026-05-10 snapshot. Refer to module-layout.md for the current authoritative layout. Material changes since baseline:

2026-05-10 — AZ-309 (02-coupling-refactoring)

  • SatelliteProvider.Services/ was split into three csprojs: SatelliteProvider.Services.TileDownloader, SatelliteProvider.Services.RegionProcessing, SatelliteProvider.Services.RouteManagement. Cross-sibling calls now flow only through interfaces in SatelliteProvider.Common.Interfaces.
  • RateLimitException moved from Services into SatelliteProvider.Common.Exceptions.
  • Per-component DI extension methods (AddTileDownloader, AddRegionProcessing, AddRouteManagement) now own their registrations; Program.cs calls them.

2026-05-11 — AZ-350 (03-code-quality-refactoring), 27 changes C01..C27

  • Format / static-analysis tooling added (AZ-372 / C19):
    • .editorconfig at repo root: indent_style=space, indent_size=4, end_of_line=lf, charset=utf-8 (no BOM), trim_trailing_whitespace=true, insert_final_newline=true, file-scoped namespaces.
    • Directory.Build.props enables Microsoft.CodeAnalysis.NetAnalyzers repository-wide; CA1001, CA1051, CA1816, CA2227 elevated to warning.
    • Coverlet (coverlet.collector) wired into SatelliteProvider.Tests; dotnet test --collect:"XPlat Code Coverage" writes cobertura.xml to TestResults/.
    • scripts/run-tests.sh runs dotnet format whitespace --verify-no-changes as Step 0 (gating); --unit-only, --smoke, --full modes documented.
  • HTTP / DI hardening:
    • IExceptionHandler-based GlobalExceptionHandler sanitizes 5xx ProblemDetails (AZ-353 / C03).
    • Permissive CORS replaced with strict-by-default policy (AZ-354 / C04); permissive policy is opt-in per CorsConfig.AllowAnyOrigin and warns in production.
    • Stub endpoints /api/satellite/tiles/mgrs and /api/satellite/upload now return HTTP 501 instead of 500 (AZ-356 / C05).
    • Idempotent POST contract for /api/satellite/request and /api/satellite/route returns the existing resource on duplicate id without re-enqueueing (AZ-362 / C09).
    • Typed HttpClient GoogleMapsTiles registered in DI (AZ-374 / C21).
  • Domain model cleanup:
    • RegionStatus and RoutePointType enums replace string status fields end-to-end with case-insensitive parse + lowercase write (AZ-370 / C17).
    • Tile Version and MapsVersion deprecated (AZ-357 / C06, AZ-373 / C20); migration 012 dedupes existing rows and reshapes the unique index to (latitude, longitude, tile_zoom, tile_size_meters).
  • Algorithmic / structural cleanup:
    • RouteProcessingService god-class decomposed (AZ-364 / C11); RouteService.CreateRouteAsync decomposed (AZ-365 / C12); IServiceProvider lookups replaced with explicit dependencies (AZ-360 / C08); RegionService catch ladder consolidated (AZ-359 / C07).
    • Shared helpers extracted: TileCsvWriter (AZ-368 / C15), TileGridStitcher (AZ-367 / C14), Haversine + filename parser (AZ-366 / C13).
    • Inline DTOs moved out of Program.cs into Common.DTO (AZ-369 / C16).
    • Repository ColumnList constants extracted (AZ-379 / C26); per-cell FirstOrDefault tile lookup replaced with HashSet membership (AZ-375 / C22); Earth + tile-pixel constants consolidated to GeoUtils and MapConfig.DefaultTileSizePixels (AZ-377 / C24).
    • Dead code removed: FindExistingTileAsync (AZ-376 / C23), CalculatePolygonDiagonalDistance (AZ-380 / C27), unused write-only counters in RegionRequestQueue (AZ-363 / C10).
    • Empty catch in ExtractTileCoordinatesFromFilename replaced with logging + sentinel return (AZ-352 / C02); null logger in DatabaseMigrator fixed (AZ-351 / C01).
    • Magic numbers promoted to ProcessingConfig / MapConfig (AZ-371 / C18).
    • Unused repo logger fields removed from RegionRepository and RouteRepository; TileRepository keeps its logger and emits slow-query warnings ≥ 500ms (AZ-378 / C25).
  • Test growth: 37 unit tests → 200 unit tests (per AZ-37x batch test sweeps); smoke run extended with AZ-353/AZ-356/AZ-357/AZ-362/SEC-01..04/CORS scenarios.

For the authoritative current layout see _docs/02_document/module-layout.md. For the per-batch detail see _docs/03_implementation/batch_*_report.md and _docs/03_implementation/reviews/.