Files
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

110 lines
6.5 KiB
Markdown

# Satellite Provider — Documentation Report
## Executive Summary
Full bottom-up documentation of the Satellite Provider service — a .NET 10 backend (migrated from .NET 8 LTS by AZ-500 in cycle 4) that pre-downloads, caches, and composites satellite imagery for a GPS-denied UAV navigation system. The analysis identified 5 logical components across 16 modules, documented 6 system flows, and produced a complete data model, deployment guide, and architecture reference.
## Problem Statement
UAVs operating without GPS need pre-cached satellite imagery for visual positioning. This service automates tile acquisition from satellite imagery providers (first implementation: Google Maps), organizes tiles by coordinates/zoom, generates composite maps for routes and regions, and will accept UAV-captured imagery (Layer 2) for improved accuracy. The downloader is provider-agnostic via `ISatelliteDownloader`.
## Architecture Overview
Single-instance containerized monolith with layered architecture (API → Services → DataAccess → PostgreSQL) and asynchronous background processing via in-process queues. No authentication (internal/trusted network service).
**Technology stack**: C# 14 / .NET 10 (cycle 4 — was C# 12 / .NET 8.0 through cycle 3), ASP.NET Core Minimal API, PostgreSQL 16, Dapper, Docker, Woodpecker CI
**Deployment**: Docker Compose (API + PostgreSQL), ARM64 primary, self-hosted registry
## Component Summary
| # | Component | Purpose | Dependencies |
|---|-----------|---------|-------------|
| 01 | Common | Shared DTOs, interfaces, configs, geospatial math | — |
| 02 | DataAccess | PostgreSQL persistence via Dapper + DbUp migrations | Common |
| 03 | TileDownloader | Provider-agnostic satellite tile acquisition with dedup | Common, DataAccess |
| 04 | RegionProcessing | Batch tile downloads, stitching, CSV/summary output | Common, DataAccess, TileDownloader |
| 05 | RouteManagement | Route interpolation, geofencing, consolidated map output | Common, DataAccess, RegionProcessing |
| — | WebApi | HTTP endpoints, DI configuration, startup | All above |
**Dependency layering** (bottom-up):
1. Common (foundation)
2. DataAccess (persistence)
3. TileDownloader (domain services)
4. RegionProcessing, RouteManagement (application/orchestration)
5. WebApi (entry point)
## System Flows
| Flow | Description | Key Components |
|------|-------------|---------------|
| Single Tile Download | Client requests tile by lat/lon/zoom; cache check → download → store | WebApi, TileDownloader, DataAccess |
| Region Request | Submit region definition; queued for async processing | WebApi, RegionProcessing |
| Region Processing | Background: calculate grid → download tiles → stitch → output files | RegionProcessing, TileDownloader |
| Route Creation | Submit waypoints; interpolate points, persist | WebApi, RouteManagement |
| Route Map Processing | Background: geofence filter → create regions → wait → ZIP | RouteManagement, RegionProcessing |
| Status Query | Poll region/route by ID | WebApi, DataAccess |
## Risk Summary
| Level | Count | Key Risks |
|-------|-------|-----------|
| High | 1 | Queue state lost on restart (in-process Channel, no persistence) |
| Medium | 2 | Single-instance limitation; no retry persistence for failed tiles |
| Low | 2 | No auth layer; MGRS/Upload endpoints are stubs |
## Test Coverage
| Component | Unit Tests | Integration Tests |
|-----------|-----------|------------------|
| Common | None | Indirect |
| DataAccess | None | Indirect (via integration) |
| TileDownloader | Placeholder only | Tile download tests |
| RegionProcessing | None | Region processing tests (multiple sizes/zooms) |
| RouteManagement | None | Basic, complex, extended route tests |
**Gap**: Unit test coverage is minimal (placeholder only). Integration tests provide the primary verification via Docker Compose.
## Key Decisions
| # | Decision | Rationale | Alternatives Rejected |
|---|----------|-----------|----------------------|
| 1 | Minimal API (no controllers) | Small endpoint surface, less ceremony | MVC controllers |
| 2 | Dapper over EF Core | Raw SQL control, performance, simplicity | Entity Framework (too heavy for this use case) |
| 3 | In-process Channel queue | No external dependencies, single instance | RabbitMQ, Redis queues |
| 4 | File-based tile storage | Fast reads, simple backup, immutable files | Blob storage, DB binary |
| 5 | Background hosted services | Clean lifecycle, framework-managed | Separate worker process |
| 6 | Provider-agnostic downloader interface | Future provider flexibility | Hardcoded Google Maps calls |
## Open Questions
| # | Question | Impact | Owner |
|---|----------|--------|-------|
| 1 | Which additional satellite imagery providers will be integrated? | New `ISatelliteDownloader` implementations needed | Product |
| 2 | Layer 2 upload: what orthogonal tile format/metadata will UAVs provide? | Upload endpoint design | Product |
| 3 | MGRS endpoint: what coordinate conversion library to use? | Implementation of tile-by-MGRS | Engineering |
| 4 | Should queue state survive restarts (persistent queue)? | Data loss risk on crash during processing | Engineering |
## Artifact Index
| File | Description |
|------|-------------|
| `_docs/00_problem/problem.md` | Problem statement |
| `_docs/00_problem/restrictions.md` | Constraints and dependencies |
| `_docs/00_problem/acceptance_criteria.md` | Measurable acceptance criteria |
| `_docs/00_problem/data_parameters.md` | Input/output data schemas |
| `_docs/01_solution/solution.md` | Solution overview with per-component analysis |
| `_docs/02_document/00_discovery.md` | Codebase discovery (structure, deps, tech stack) |
| `_docs/02_document/architecture.md` | Full architecture document |
| `_docs/02_document/system-flows.md` | System flows with sequence diagrams |
| `_docs/02_document/data_model.md` | Database schema and migration history |
| `_docs/02_document/glossary.md` | Domain and technical glossary |
| `_docs/02_document/module-layout.md` | File ownership and layering map |
| `_docs/02_document/04_verification_log.md` | Verification results |
| `_docs/02_document/modules/*.md` | Per-module documentation (16 files) |
| `_docs/02_document/components/*/description.md` | Per-component specs (5 files) |
| `_docs/02_document/diagrams/components.md` | Component relationship diagram |
| `_docs/02_document/deployment/containerization.md` | Docker setup |
| `_docs/02_document/deployment/ci_cd_pipeline.md` | Woodpecker CI pipeline |
| `_docs/02_document/deployment/environment_strategy.md` | Environment config |