[AZ-315] Sync architecture docs after coupling refactor

Phase C of architecture coupling refactor (epic AZ-309). Closes the
last baseline finding (F5 — DataAccess incorrectly documented as
importing Common) and synchronizes the rest of _docs/02_document/
with the post-split project layout from AZ-312/313/314:

- module-layout.md: per-component sections for the three new csprojs
  with explicit ProjectReferences and the no-cross-sibling-reference
  invariant the split enforces.
- architecture.md: components and internal-communication tables
  updated to show calls flow through Common interfaces.
- architecture_compliance_baseline.md: F1..F5 marked Resolved with
  task IDs and commit refs; baseline summary now 0 findings.
- diagrams/components.md, components/03_tile_downloader/description.md,
  modules/{common_interfaces,services_tile_service,
  services_google_maps_downloader,tests_unit}.md updated for the
  split, RateLimitException relocation, and new ITileService methods.

Documentation-only batch — no code, no tests, no build changes.
Epic AZ-309 complete (6 tasks across 3 batches).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-10 07:25:21 +03:00
parent 8b0ddae075
commit 6b373082c8
14 changed files with 290 additions and 89 deletions
+43 -31
View File
@@ -3,17 +3,18 @@
**Status**: derived-from-code
**Language**: csharp
**Layout Convention**: custom (flat service project, per-project component separation)
**Layout Convention**: custom (per-component .csproj per logical component)
**Root**: ./
**Last Updated**: 2026-05-10
**Last Updated**: 2026-05-10 (post AZ-309 coupling refactor)
## Layout Rules
1. Each component owns ONE top-level project directory (`.csproj` boundary), except the Services project which hosts three logical components in a flat layout.
1. Each component owns ONE top-level project directory (`.csproj` boundary). The previous shared `SatelliteProvider.Services` project was split into three per-component csprojs in epic AZ-309.
2. Shared code lives under `SatelliteProvider.Common/` — the foundation layer.
3. Cross-cutting concerns (DTOs, interfaces, configs, geo-math) all reside in Common.
3. Cross-cutting concerns (DTOs, interfaces, configs, geo-math, common exceptions) all reside in Common.
4. Public API surface per component = `public` types in the namespace root. Everything marked `internal` or private is internal.
5. Tests live in separate projects: `SatelliteProvider.Tests/` (unit) and `SatelliteProvider.IntegrationTests/` (integration).
6. DI registration per component lives in a `<Component>ServiceCollectionExtensions.cs` adjacent to the component's classes (e.g. `TileDownloaderServiceCollectionExtensions.AddTileDownloader()`).
## Per-Component Mapping
@@ -26,6 +27,7 @@
- `SatelliteProvider.Common/Configs/ProcessingConfig.cs`
- `SatelliteProvider.Common/Configs/DatabaseConfig.cs`
- `SatelliteProvider.Common/DTO/*.cs` (all DTOs)
- `SatelliteProvider.Common/Exceptions/RateLimitException.cs`
- `SatelliteProvider.Common/Interfaces/*.cs` (all service interfaces)
- `SatelliteProvider.Common/Utils/GeoUtils.cs`
- **Internal**: (none — all types are public, shared across components)
@@ -55,36 +57,45 @@
### Component: TileDownloader
- **Directory**: `SatelliteProvider.Services/` (shared project)
- **Directory**: `SatelliteProvider.Services.TileDownloader/`
- **csproj**: `SatelliteProvider.Services.TileDownloader/SatelliteProvider.Services.TileDownloader.csproj`
- **Public API**:
- `SatelliteProvider.Services/GoogleMapsDownloaderV2.cs` (implements `ISatelliteDownloader`)
- `SatelliteProvider.Services/TileService.cs` (implements `ITileService`)
- **Internal**: (none — flat project, classes are public)
- **Owns**: `SatelliteProvider.Services/GoogleMapsDownloaderV2.cs`, `SatelliteProvider.Services/TileService.cs`
- `SatelliteProvider.Services.TileDownloader/GoogleMapsDownloaderV2.cs` (implements `ISatelliteDownloader`)
- `SatelliteProvider.Services.TileDownloader/TileService.cs` (implements `ITileService`)
- `SatelliteProvider.Services.TileDownloader/TileDownloaderServiceCollectionExtensions.cs` (DI: `AddTileDownloader()`)
- **Internal**: (none)
- **Owns**: `SatelliteProvider.Services.TileDownloader/**`
- **ProjectReferences**: `SatelliteProvider.Common`, `SatelliteProvider.DataAccess`
- **Imports from**: Common, DataAccess
- **Consumed by**: RegionProcessing, WebApi
- **Consumed by**: RegionProcessing (via `ITileService` from Common; no direct ProjectReference), WebApi
### Component: RegionProcessing
- **Directory**: `SatelliteProvider.Services/` (shared project)
- **Directory**: `SatelliteProvider.Services.RegionProcessing/`
- **csproj**: `SatelliteProvider.Services.RegionProcessing/SatelliteProvider.Services.RegionProcessing.csproj`
- **Public API**:
- `SatelliteProvider.Services/RegionService.cs` (implements `IRegionService`)
- `SatelliteProvider.Services/RegionProcessingService.cs` (background hosted service)
- `SatelliteProvider.Services/RegionRequestQueue.cs` (implements `IRegionRequestQueue`)
- `SatelliteProvider.Services.RegionProcessing/RegionService.cs` (implements `IRegionService`)
- `SatelliteProvider.Services.RegionProcessing/RegionProcessingService.cs` (background hosted service)
- `SatelliteProvider.Services.RegionProcessing/RegionRequestQueue.cs` (implements `IRegionRequestQueue`)
- `SatelliteProvider.Services.RegionProcessing/RegionProcessingServiceCollectionExtensions.cs` (DI: `AddRegionProcessing()`)
- **Internal**: (none)
- **Owns**: `SatelliteProvider.Services/RegionService.cs`, `SatelliteProvider.Services/RegionProcessingService.cs`, `SatelliteProvider.Services/RegionRequestQueue.cs`
- **Imports from**: Common, DataAccess, TileDownloader
- **Consumed by**: RouteManagement, WebApi
- **Owns**: `SatelliteProvider.Services.RegionProcessing/**`
- **ProjectReferences**: `SatelliteProvider.Common`, `SatelliteProvider.DataAccess`
- **Imports from**: Common, DataAccess (uses `ITileService` from Common — no compile-time dependency on TileDownloader)
- **Consumed by**: RouteManagement (via `IRegionService` and `IRegionRequestQueue` from Common; no direct ProjectReference), WebApi
### Component: RouteManagement
- **Directory**: `SatelliteProvider.Services/` (shared project)
- **Directory**: `SatelliteProvider.Services.RouteManagement/`
- **csproj**: `SatelliteProvider.Services.RouteManagement/SatelliteProvider.Services.RouteManagement.csproj`
- **Public API**:
- `SatelliteProvider.Services/RouteService.cs` (implements `IRouteService`)
- `SatelliteProvider.Services/RouteProcessingService.cs` (background hosted service)
- `SatelliteProvider.Services.RouteManagement/RouteService.cs` (implements `IRouteService`)
- `SatelliteProvider.Services.RouteManagement/RouteProcessingService.cs` (background hosted service)
- `SatelliteProvider.Services.RouteManagement/RouteManagementServiceCollectionExtensions.cs` (DI: `AddRouteManagement()`)
- **Internal**: (none)
- **Owns**: `SatelliteProvider.Services/RouteService.cs`, `SatelliteProvider.Services/RouteProcessingService.cs`
- **Imports from**: Common, DataAccess, RegionProcessing
- **Owns**: `SatelliteProvider.Services.RouteManagement/**`
- **ProjectReferences**: `SatelliteProvider.Common`, `SatelliteProvider.DataAccess`
- **Imports from**: Common, DataAccess (uses `IRegionService` / `IRegionRequestQueue` from Common — no compile-time dependency on RegionProcessing)
- **Consumed by**: WebApi
### Component: WebApi
@@ -125,16 +136,17 @@
## Allowed Dependencies (layering)
| Layer | Components | May import from |
|-------|------------|-----------------|
| 4. API / Entry | WebApi | 1, 2, 3 |
| 3. Application (Orchestration) | RouteManagement | 1, 2, 3 (RegionProcessing only) |
| 3. Application (Processing) | RegionProcessing | 1, 2, 3 (TileDownloader only) |
| 2. Domain Services | TileDownloader | 1 |
| Layer | Components | May import from (compile-time ProjectReferences) |
|-------|------------|--------------------------------------------------|
| 4. API / Entry | WebApi | Common, DataAccess, TileDownloader, RegionProcessing, RouteManagement |
| 3. Application | TileDownloader, RegionProcessing, RouteManagement | Common, DataAccess only — siblings communicate through interfaces in Common, never through direct ProjectReferences |
| 1. Foundation | Common, DataAccess | Common: (none); DataAccess: (none) |
## Verification Needed
**Key constraint enforced by the AZ-309 split**: the three Layer-3 components are compile-time siblings. Any cross-sibling call (e.g. `RegionProcessing` invoking tile download) MUST go through an interface defined in `SatelliteProvider.Common.Interfaces` and resolved via DI — adding a `ProjectReference` between siblings is now structurally impossible without re-introducing the coupling the refactor removed.
## Verification
- **Shared Services project**: TileDownloader, RegionProcessing, and RouteManagement coexist in a single `SatelliteProvider.Services/` project. File-level ownership is used (not directory-level) which is unusual for .NET. A future refactor into separate projects per component would make ownership boundaries cleaner.
- **No detected cycles**: The dependency graph is a clean DAG.
- **DataAccess layer placement**: DataAccess is placed at Layer 1 (Foundation) alongside Common because it is consumed uniformly by all service components. An alternative layering could place it at Layer 2, but the current code treats repositories as infrastructure, not domain logic.
- **No cross-sibling ProjectReferences**: TileDownloader, RegionProcessing, and RouteManagement each reference only Common + DataAccess. Verified by inspecting all three csproj files.
- **DataAccess layer placement**: DataAccess sits at Layer 1 (Foundation) alongside Common because it is consumed uniformly by all service components. An alternative layering could place it at Layer 2, but the current code treats repositories as infrastructure, not domain logic.
- **DataAccess has no ProjectReference to Common**: confirmed by inspecting `SatelliteProvider.DataAccess.csproj`. DataAccess models and repositories are self-contained (do not use any types from Common). This contradicts an earlier baseline assumption (compliance baseline F5).