mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-22 00:31:15 +00:00
[AZ-309] Refactor 02-coupling-refactoring Phase 0-2 artifacts
- Baseline metrics, list of changes, and analysis (research findings, refactoring roadmap) for the coupling refactor run - Six task specs AZ-310..AZ-315 covering endpoint routing through ITileService, Services csproj split, consumer rewire, DI extension methods, and docs sync - Existing test coverage assessment for Phase 3 safety net gate - Dependencies table updated with the refactor block Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# Phase 2b — Refactoring Roadmap
|
||||
|
||||
**Run**: 02-coupling-refactoring
|
||||
**Date**: 2026-05-10
|
||||
|
||||
## Solution Assessment
|
||||
|
||||
Acceptance criteria (`_docs/00_problem/acceptance_criteria.md`) all map to public HTTP behavior. None of the proposed changes alter that behavior — they redistribute internal ownership. The smoke + unit suite remains the gate.
|
||||
|
||||
## Gap Analysis
|
||||
|
||||
| Acceptance Criterion (paraphrased) | Current State | Post-Refactor State | Verification |
|
||||
|------------------------------------|---------------|---------------------|--------------|
|
||||
| AC: download single tile by lat/lon/zoom returns image metadata | Endpoint inlines logic (Program.cs:206) | Endpoint delegates to `ITileService.DownloadAndStoreSingleTileAsync` | Smoke `RunGetTileByLatLonTest` |
|
||||
| AC: serve tile by z/x/y returns image bytes | Endpoint inlines logic + cache (Program.cs:141) | Endpoint delegates to `ITileService.GetOrDownloadTileAsync` | Manual smoke (no integration test exists for `/tiles/{z}/{x}/{y}` — note as a follow-up coverage gap) |
|
||||
| AC: region processing pipeline | RegionService in `Services` csproj | RegionService in `Services.RegionProcessing` csproj | Smoke `RunRegionProcessingTest_200m_Zoom18` + unit RegionServiceTests |
|
||||
| AC: route management pipeline | RouteService in `Services` csproj | RouteService in `Services.RouteManagement` csproj | Smoke `RunRouteWithTilesZipTest` + unit RouteServiceTests |
|
||||
| AC: zoom validation rejects invalid zoom | GoogleMapsDownloaderV2 in `Services` csproj | Same class in `Services.TileDownloader` csproj | Unit GoogleMapsDownloaderZoomValidationTests |
|
||||
|
||||
**Coverage gap noted but out of scope**: there is no integration test exercising the `/tiles/{z}/{x}/{y}` endpoint specifically. The unit-level cache logic in C01 will be tested via new TileService unit tests; integration coverage can be added in a future cycle.
|
||||
|
||||
## Phased Roadmap
|
||||
|
||||
### Phase A — Endpoint routing (low risk, sequential)
|
||||
|
||||
1. **AZ-NEW-1 (refactor C01)** — `ITileService.GetOrDownloadTileAsync(z,x,y)` + ServeTile handler thinning.
|
||||
2. **AZ-NEW-2 (refactor C02)** — `ITileService.DownloadAndStoreSingleTileAsync(lat,lon,zoom)` + GetTileByLatLon handler thinning.
|
||||
|
||||
After Phase A, F3 from the architecture baseline is resolved. Smoke + unit suite stays green.
|
||||
|
||||
### Phase B — Project split (medium risk, sequential due to compiler dependency chain)
|
||||
|
||||
3. **AZ-NEW-3 (refactor C03)** — Create `Services.TileDownloader`, `Services.RegionProcessing`, `Services.RouteManagement` csprojs and move the seven files.
|
||||
4. **AZ-NEW-4 (refactor C04)** — Update `SatelliteProvider.Tests` and `SatelliteProvider.IntegrationTests` to reference the new csprojs.
|
||||
5. **AZ-NEW-5 (refactor C05)** — Update `SatelliteProvider.Api` csproj, `Program.cs` namespaces, and `Dockerfile` COPY paths.
|
||||
|
||||
After Phase B, F4 from the architecture baseline is resolved. The solution builds, smoke + unit suite stays green, the API container still runs.
|
||||
|
||||
### Phase C — Documentation (low risk, last)
|
||||
|
||||
6. **AZ-NEW-6 (refactor C06)** — Update `module-layout.md`, `architecture.md`, refresh `architecture_compliance_baseline.md` (mark F3, F4 Resolved; correct F5).
|
||||
|
||||
After Phase C, doc-code parity is restored.
|
||||
|
||||
## Hardening Tracks
|
||||
|
||||
User Phase 0 + Phase 1 approvals already excluded hardening. The only optional track that would fit is:
|
||||
|
||||
- **Track A — Tech Debt**: pre-existing FluentAssertions community-license warning would belong here, but it's a licensing decision (legal cost vs. switching to `Shouldly` or `xunit.assert`), not a code-structure decision. Surfacing as a follow-up backlog item rather than including in this run.
|
||||
|
||||
No hardening tracks added to this run. Pure structural refactor.
|
||||
|
||||
## Applicability Gate
|
||||
|
||||
Every roadmap item carries `Selected` status from `research_findings.md`. No `Rejected`, `Experimental only`, or `Needs user decision` entries remain. Gate: **passed**.
|
||||
|
||||
## Self-Verification
|
||||
|
||||
- [x] All ACs mapped to current vs post-refactor state.
|
||||
- [x] Phased order respects compiler dependencies (endpoint refactor before split).
|
||||
- [x] Each item has a verification path (smoke or unit suite).
|
||||
- [x] No item violates the Project Constraint Matrix.
|
||||
- [x] Hardening track decision recorded.
|
||||
@@ -0,0 +1,74 @@
|
||||
# Phase 2a — Research Findings
|
||||
|
||||
**Run**: 02-coupling-refactoring
|
||||
**Date**: 2026-05-10
|
||||
|
||||
## Project Constraint Matrix (extracted)
|
||||
|
||||
From `_docs/00_problem/problem.md`, `_docs/00_problem/restrictions.md`, `_docs/00_problem/acceptance_criteria.md`, `_docs/02_document/architecture.md`:
|
||||
|
||||
| Constraint | Source | Implication for this refactor |
|
||||
|------------|--------|--------------------------------|
|
||||
| .NET 8.0 / ASP.NET Core minimal API | `restrictions.md`, `architecture.md` | New code stays on .NET 8 + minimal API. No framework swap. |
|
||||
| PostgreSQL via Dapper | `restrictions.md` | DataAccess layer unchanged. |
|
||||
| Public HTTP API surface stable | `acceptance_criteria.md` (AC-1..AC-3) | Routes, query/body shapes, response shapes preserved exactly. |
|
||||
| No DB schema rename | project `coderule.mdc` | Migrations not touched. |
|
||||
| Source under `src/` only for new projects; existing layout retained | project `coderule.mdc` | New `Services.*` csprojs sit at the repo root next to existing `SatelliteProvider.*` csprojs (existing layout). |
|
||||
| Dockerized deploy via `docker-compose.yml` | `architecture.md`, `AGENTS.md` | API + IntegrationTests Dockerfiles must be updated when csproj layout changes. |
|
||||
| Test environment runs in Docker | `_docs/02_document/tests/environment.md` | Smoke + unit suite must pass under the existing Docker test runner. |
|
||||
|
||||
## Current State Analysis
|
||||
|
||||
| Aspect | Pattern in code | Strength | Weakness |
|
||||
|--------|-----------------|----------|----------|
|
||||
| API layer | ASP.NET minimal API (`MapGet`, `MapPost` in `Program.cs`) | Compact, easy to read | Two endpoints (`ServeTile`, `GetTileByLatLon`) bypass the service layer (baseline F3) |
|
||||
| Service layer | Single csproj `SatelliteProvider.Services` containing 7 files | Simple to navigate | No compiler-enforced boundary between TileDownloader / RegionProcessing / RouteManagement (baseline F4) |
|
||||
| Data access | Dapper repositories injected via interfaces | Clean separation | None |
|
||||
| DI | Built-in `Microsoft.Extensions.DependencyInjection` | Standard, no surprises | None |
|
||||
| Testing | xUnit + Moq + FluentAssertions (community license warning, pre-existing) | Standard, expressive | FluentAssertions licensing is a pre-existing concern, out of scope |
|
||||
|
||||
## Alternative Approaches Considered
|
||||
|
||||
This refactor is structural-only. No new library/SDK/framework is being added or replaced. The mandatory **API Capability Verification** flow does not apply because no replacement candidates exist — the proposed changes reuse existing patterns:
|
||||
|
||||
- ASP.NET Core minimal API → kept.
|
||||
- `IMemoryCache` from `Microsoft.Extensions.Caching.Memory` → kept (moves into TileService instead of being injected into the endpoint handler).
|
||||
- xUnit / Moq / FluentAssertions → kept.
|
||||
- DbUp / Dapper → not touched.
|
||||
|
||||
`context7` lookup is therefore not required for this refactor (no replacement candidates to verify).
|
||||
|
||||
### Alternatives explicitly considered and rejected (already in `list-of-changes.md`)
|
||||
|
||||
| Alternative | Status | Reason |
|
||||
|-------------|--------|--------|
|
||||
| Adopt MediatR / CQRS layering | Rejected | Heavy dependency for a small codebase; conflicts with the "simplest solution" coderule; not required by any AC. |
|
||||
| Move `ISatelliteDownloader` into the new TileDownloader csproj | Rejected | Forces RegionService/RegionProcessingService to depend on TileDownloader, defeating the boundary the split is supposed to create. |
|
||||
| Inline `IMemoryCache` into the public `ITileService` interface | Rejected | Leaks an implementation choice (memory vs. distributed cache) into the public abstraction. |
|
||||
|
||||
## Constraint-Fit Table
|
||||
|
||||
| Recommendation | Pinned Mode | Constraints Checked | Evidence | Mismatches | Status |
|
||||
|----------------|-------------|---------------------|----------|------------|--------|
|
||||
| C01 — `ITileService.GetOrDownloadTileAsync(z,x,y)` | New interface method on existing service | HTTP route preserved; ETag/Cache-Control preserved | Smoke `RunGetTileByLatLonTest` will exercise post-refactor; existing TileServiceTests already cover the cache+download logic at unit level | None | Selected |
|
||||
| C02 — `ITileService.DownloadAndStoreSingleTileAsync(lat,lon,zoom)` | New interface method on existing service | Query string + DownloadTileResponse shape preserved; zoom validation chain unchanged | Smoke + unit | None | Selected |
|
||||
| C03 — Split Services into 3 csprojs | New `.csproj` files, code MOVE only | No code logic change; namespaces change | Compiler verifies; smoke verifies behavior | None | Selected |
|
||||
| C04 — Update test projects | Move `using` + `ProjectReference` only | No test logic change | `dotnet test` post-refactor | None | Selected |
|
||||
| C05 — Update API project + Dockerfiles | Move `using` + `ProjectReference` + Dockerfile COPY paths | API container builds and runs | `docker compose build` + smoke | None | Selected |
|
||||
| C06 — Update docs | Documentation only | None | Manual review against new csproj layout | None | Selected |
|
||||
|
||||
All six recommendations are `Selected`. None require user decision beyond the Phase 0 / Phase 1 scope approval already obtained.
|
||||
|
||||
## Quick Wins vs Strategic Improvements
|
||||
|
||||
- **Quick wins** (low risk, immediate value): C01, C02, C04, C06.
|
||||
- **Strategic** (medium risk, foundation for future work): C03, C05.
|
||||
|
||||
## Self-Verification
|
||||
|
||||
- [x] Project Constraint Matrix extracted.
|
||||
- [x] Current state vs. alternatives analyzed.
|
||||
- [x] All recommendations grounded in actual code (file paths, method names verified).
|
||||
- [x] No replacement libraries → API capability verification is N/A and explicitly noted.
|
||||
- [x] Rejected alternatives documented.
|
||||
- [x] No recommendation violates the Project Constraint Matrix.
|
||||
Reference in New Issue
Block a user