# Structural Snapshot — 2026-05-12 (post-cycle 4, AZ-500) Cycle 4 delta against `structure_2026-05-12_cycle3.md`. Source of truth: `_docs/02_document/module-layout.md` + on-disk `*.csproj` graph + `_docs/02_document/contracts/`. ## Projects | Layer | csproj | Cycle 4 delta | |-------|--------|---------------| | 1 (Foundation) | `SatelliteProvider.Common` | TFM `net8.0` → `net10.0` | | 1 (Foundation) | `SatelliteProvider.DataAccess` | TFM `net8.0` → `net10.0`; M.E.* 9.0.10 → 10.0.7 (Configuration.Abstractions, Logging.Abstractions) | | 3 (Application) | `SatelliteProvider.Services.TileDownloader` | TFM `net8.0` → `net10.0`; M.E.* 9.0.10 → 10.0.7 (Caching.Memory, Http, Logging.Abstractions, Options.ConfigurationExtensions) | | 3 (Application) | `SatelliteProvider.Services.RegionProcessing` | TFM `net8.0` → `net10.0`; M.E.* 9.0.10 → 10.0.7 (DependencyInjection.Abstractions, Hosting.Abstractions, Logging.Abstractions, Options.ConfigurationExtensions) | | 3 (Application) | `SatelliteProvider.Services.RouteManagement` | TFM `net8.0` → `net10.0`; M.E.* 9.0.10 → 10.0.7 (DependencyInjection.Abstractions, Hosting.Abstractions, Logging.Abstractions, Options.ConfigurationExtensions) | | 4 (API / Entry) | `SatelliteProvider.Api` | TFM `net8.0` → `net10.0`; `Microsoft.AspNetCore.Authentication.JwtBearer` 8.0.25 → **10.0.7**; `Microsoft.AspNetCore.OpenApi` 8.0.25 → **10.0.7**; `Swashbuckle.AspNetCore` 6.6.2 → **10.1.7** (drove transitive `Microsoft.OpenApi` 1.x → 2.3.x); `Serilog.AspNetCore` retained at 8.0.3 (Risk #4 fallback); `Program.cs` Microsoft.OpenApi 2.x setup refactor (3 internal edits — namespace, `OpenApiSecuritySchemeReference`, `JsonSchemaType` + `IOpenApiSchema`); `Swagger/ParameterDescriptionFilter.cs` namespace update | | 5 (Test-Support) | `SatelliteProvider.TestSupport` | TFM `net8.0` → `net10.0`; NuGet refs unchanged (still pinned to `Microsoft.IdentityModel.Tokens 7.0.3` + `System.IdentityModel.Tokens.Jwt 7.0.3` — cycle-3 D4 carry-over) | | 6 (Tests) | `SatelliteProvider.Tests` | TFM `net8.0` → `net10.0`; M.E.* 9.0.10 → 10.0.7 (Caching.Memory, Configuration.Json, DependencyInjection, Http, Logging.Abstractions, Logging.Console, Options); `Microsoft.AspNetCore.Authentication.JwtBearer` 8.0.25 → 10.0.7 (transitively via ProjectReference to Api) | | 6 (Tests) | `SatelliteProvider.IntegrationTests` | TFM `net8.0` → `net10.0`; transitive bumps via TestSupport + Api | **Project count**: 9 (unchanged from cycle 3 — AZ-500 is a runtime/SDK migration, not a project-graph change). ## Cross-Project Import Edges (compile-time `ProjectReference`) | Edge | Count | Cycle 4 delta | |------|-------|----------------| | Api → {Common, DataAccess, TileDownloader, RegionProcessing, RouteManagement} | 5 | unchanged | | TileDownloader → {Common, DataAccess} | 2 | unchanged | | DataAccess → {Common} | 1 | unchanged | | RegionProcessing → {Common, DataAccess} | 2 | unchanged | | RouteManagement → {Common, DataAccess} | 2 | unchanged | | Tests → {Api, TileDownloader, RegionProcessing, RouteManagement, Common, DataAccess, TestSupport} | 7 | unchanged | | IntegrationTests → {TestSupport} (+ runtime DTOs only) | 1 | unchanged | **Total ProjectReference edges**: 20 (unchanged from cycle 3). AZ-500 added zero cross-project import edges. ## Source-import sites — cycle 4 delta | Importer | Imports from | Cycle 4 delta | |----------|--------------|---------------| | `SatelliteProvider.Api/Program.cs` | `Microsoft.OpenApi` (was `Microsoft.OpenApi.Models`) | namespace move (1.x → 2.x); same conceptual surface, different package layout | | `SatelliteProvider.Api/Swagger/ParameterDescriptionFilter.cs` | `Microsoft.OpenApi` (was `Microsoft.OpenApi.Models`) | same namespace move | | All other source files | unchanged | — | **No new source-level imports introduced.** The two changed `using` directives are namespace renames forced by the Microsoft.OpenApi 2.x layout, not new dependencies. ## Graph properties - **Cycles in project import graph**: 0 (clean DAG — unchanged) - **Average ProjectReferences per component**: 20 / 9 = ~2.2 (unchanged from cycle 3) - **Max in-degree**: Common (still highest at 6 — Api, TileDownloader, DataAccess, RegionProcessing, RouteManagement, Tests). - **Max out-degree**: Tests (7 — unchanged from cycle 3). - **TestSupport position**: leaf-of-test-subgraph; no production-layer importers (unchanged). ## NuGet dependency hygiene (cycle 4) | Package | Cycle-3 version | Cycle-4 version | Status | |---------|-----------------|-----------------|--------| | `Microsoft.AspNetCore.Authentication.JwtBearer` | 8.0.25 | **10.0.7** | RESOLVED cycle-3 D1 forward (now on the 10.x line; same underlying CVE patch, current line) | | `Microsoft.AspNetCore.OpenApi` | 8.0.25 | **10.0.7** | RESOLVED cycle-3 D3 forward (same as above) | | `Swashbuckle.AspNetCore` | 6.6.2 | **10.1.7** | NEW major line — 0 known vulnerabilities; bumped to land Microsoft.OpenApi 2.x compat required by ASP.NET Core 10 | | `Microsoft.OpenApi` (transitive via Swashbuckle) | 1.x | **2.3.x** | NEW major line — 0 known vulnerabilities; drove the 3 internal `Program.cs` setup edits | | `Serilog.AspNetCore` | 8.0.3 | **8.0.3 (unchanged)** | Risk #4 fallback — no 10.x line published as of cycle 4; restores cleanly on `net10.0` via netstandard 2.0; recheck per cycle | | `Microsoft.Extensions.*` (11 distinct package IDs) | 9.0.10 | **10.0.7** | Coordinated bump across 6 csproj files; 0 known vulnerabilities on 10.0.7 line; historical CVE-2024-43483 already not applicable in cycle 3 (9.0.10 baseline post-rc.1 cutoff) | | `Microsoft.IdentityModel.Tokens` (TestSupport) | 7.0.3 | **7.0.3 (unchanged)** | Cycle-3 D4 carry-over — explicitly out of AZ-500 scope per "no unrelated package bumps" Constraint; recommend separate PBI | | `System.IdentityModel.Tokens.Jwt` (TestSupport) | 7.0.3 | **7.0.3 (unchanged)** | Same disposition as above | | `Microsoft.NET.Test.Sdk` | 17.8.0 | **17.8.0 (unchanged)** | Cycle-3 D2 carry-over (transitive `NuGet.Frameworks` flag); explicitly out of AZ-500 scope | | `SixLabors.ImageSharp` | 3.1.11 | **3.1.11 (unchanged)** | clean | | `Npgsql` | 9.0.2 | **9.0.2 (unchanged)** | clean | | `Newtonsoft.Json` | 13.0.4 | **13.0.4 (unchanged)** | clean | | `Dapper` | 2.1.35 | **2.1.35 (unchanged)** | clean | | `dbup-postgresql` | 6.0.3 | **6.0.3 (unchanged)** | clean | ## Architecture / contract surface (cycle 4 delta) - **No new public-API contracts** under `_docs/02_document/contracts/` this cycle. AZ-500 preserves every endpoint shape, every DTO, the JWT validation contract (signature + lifetime + iss + aud + 30s clock skew), the multi-source `tile-storage` contract v1.0.0, the `uav-tile-upload` contract v1.0.0, and the AZ-488 permissions claim policy. - `_docs/02_document/architecture.md` updated to reference .NET 10 / ASP.NET Core 10 / JwtBearer 10.0.7 (Authentication & Authorization paragraph + §2 Tech Stack table); the Architecture Vision prose is unchanged. - The 8 `WithOpenApi(...)` callsites in `Program.cs` now emit `ASPDEPR002` deprecation warnings — recorded as a follow-up PBI (3 SP). API surface is unchanged. ## Net Architecture delta vs cycle 3 - **Resolved**: cycle-3 D1 (CVE-2026-26130 SignalR DoS, JwtBearer 8.0.21 line) **forward-resolved by major-version bump**; cycle-3 D3 (Microsoft.AspNetCore.OpenApi 8.0.21 line) similarly forward-resolved. The cycle-3 perf-harness leftover stays OPEN per AZ-500 Constraint, NOT closed by this cycle. **Total resolved: 2 (both Low/forward).** - **Newly introduced (informational only)**: 5 new Low informational findings in `dependency_scan_cycle4.md` (F1-cy4..F5-cy4 — all "no known vulnerabilities" confirmations on the 10.x lines); 0 new Medium; 0 new High; 0 new Critical. 2 new Maintainability Mediums in code review (F1 ASPDEPR002 deprecation, F2 CS8604 nullable) — both deferred per "scope discipline" + the AZ-500 contract of "preserve behaviour during migration". - **Net Architecture delta**: 0 net architecture-level findings. The cycle is structurally neutral — same component count, same edges, same DAG, same contract surface. The only structural-equivalence change is the 11-package M.E.* + 3-package ASP.NET + 1 Swashbuckle major-line bump, all forward-clean against advisories. Cycle 4 is the first runtime/SDK-migration cycle. Net-zero is the expected outcome for that PBI shape — there is no business-logic delta to add structure. The graph properties confirming this is a "preserve-behaviour" migration: same imports, same edges, same cycles (zero), same in-degree distribution, same DAG.