# Architecture Compliance Baseline **Date**: 2026-05-10 **Mode**: Baseline (Phase 1 + Phase 7) **Scope**: Full existing codebase **Verdict**: PASS_WITH_WARNINGS ## Findings | # | Severity | Category | File:Line | Title | |---|----------|----------|-----------|-------| | 1 | High | Architecture | SatelliteProvider.Services/TileService.cs:11 | Concrete dependency on GoogleMapsDownloaderV2 bypasses ISatelliteDownloader | | 2 | High | Architecture | SatelliteProvider.Common/Interfaces/ISatelliteDownloader.cs | ISatelliteDownloader interface is dead code | | 3 | Medium | Architecture | SatelliteProvider.Api/Program.cs:141 | API endpoint directly injects concrete downloader + repository | | 4 | Medium | Architecture | SatelliteProvider.Services/ | No physical boundary between logical components in shared project | | 5 | Low | Architecture | module-layout.md | DataAccess documented as importing Common but actually has zero cross-project dependencies | ## Finding Details **F1: Concrete dependency on GoogleMapsDownloaderV2** (High / Architecture) - Location: `SatelliteProvider.Services/TileService.cs:11` - Description: `TileService` depends on the concrete class `GoogleMapsDownloaderV2` instead of `ISatelliteDownloader`. DI registration is also concrete (`AddSingleton()`). This couples the entire tile pipeline to a single provider. - Impact: Adding a new satellite imagery provider requires modifying TileService and Program.cs DI wiring rather than just registering a new implementation. - Suggestion: Have `GoogleMapsDownloaderV2` implement `ISatelliteDownloader`, update DI to register via interface, inject interface into TileService. **F2: ISatelliteDownloader is dead code** (High / Architecture) - Location: `SatelliteProvider.Common/Interfaces/ISatelliteDownloader.cs` - Description: The interface exists (declares `GetTiles(GeoPoint, double, int, CancellationToken)`) but NO class implements it and NO code references it. The actual downloader method used is `GoogleMapsDownloaderV2.GetTilesWithMetadataAsync()` which has a different signature. - Impact: The provider-agnostic abstraction doesn't function. Interface and implementation have diverged. - Suggestion: Update `ISatelliteDownloader` to match the actual API surface needed by consumers, then implement it in `GoogleMapsDownloaderV2`. **F3: API endpoint bypasses service layer** (Medium / Architecture) - Location: `SatelliteProvider.Api/Program.cs:141` (`ServeTile`) and `:206` (`GetTileByLatLon`) - Description: Two API endpoints directly inject `GoogleMapsDownloaderV2` and `ITileRepository` instead of using `ITileService`. This bypasses the service layer and creates a shortcut from Layer 4 to Layer 2. - Impact: Business logic (caching, dedup) in TileService is bypassed for these endpoints; tile download logic is duplicated. - Suggestion: Route all tile operations through `ITileService`. **F4: No physical boundary in Services project** (Medium / Architecture) - Location: `SatelliteProvider.Services/` (all files) - Description: Three logical components (TileDownloader, RegionProcessing, RouteManagement) share one `.csproj`. No compiler-enforced boundary prevents direct cross-component coupling. - Impact: Over time, services may accumulate hidden coupling that's hard to detect without code review. - Suggestion: Accept as-is for current scale; consider splitting into separate projects if the codebase grows significantly. **F5: module-layout.md incorrect — DataAccess has no Common dependency** (Low / Architecture) - Location: `_docs/02_document/module-layout.md` - Description: DataAccess was documented as "Imports from: Common" but `SatelliteProvider.DataAccess.csproj` has no ProjectReference to Common and no `using SatelliteProvider.Common` in any file. - Impact: Documentation inaccuracy; no code impact. - Suggestion: Correct module-layout.md. ## Summary | Severity | Count | |----------|-------| | Critical | 0 | | High | 2 | | Medium | 2 | | Low | 1 | The two High findings both relate to the same root cause: the `ISatelliteDownloader` abstraction was created but never wired into the system. The concrete `GoogleMapsDownloaderV2` is used directly everywhere. This is the primary architecture gap — addressing it would enable the provider-agnostic design the system intends to have.