# Logical Components — Unit 1: master-backend ## Full Component Wiring Diagram ```mermaid graph TD subgraph ServiceLayer["Service Layer"] CmsService["CmsInstanceService"] Deps["MasterServiceDependencies\n(constructor record)"] Repo["ICmsInstanceRepository"] SlaveClientIface["ISlaveApiClient"] ApiKeyProt["IApiKeyProtector"] HttpCtxAcc["IHttpContextAccessor"] Logger["ILogger"] Opts["MasterModuleOptions\n(via IOptions)"] end subgraph SecurityLayer["Security Layer"] ApiKeyProtImpl["ApiKeyProtector"] DataProt["IDataProtectionProvider\n(ASP.NET Core)"] Purpose["Purpose string\nSlpModularCms.Master.ApiKey"] end subgraph HttpLayer["HTTP + Resilience Layer"] SlaveClientImpl["SlaveApiClient"] PollyPipeline["Polly ResiliencePipeline\nRetry x2 + Timeout"] HttpClientInst["HttpClient\n(IHttpClientFactory)"] end subgraph BackgroundLayer["Background Service"] BgSvc["IntegrityCheckBackgroundService"] ScopeFactory["IServiceScopeFactory"] Scope["IServiceScope\n(per tick)"] PeriodicT["PeriodicTimer\n(IntegrityCheckIntervalMinutes)"] end subgraph DataLayer["Data Layer"] RepoImpl["CmsInstanceRepository"] DbCtx["MasterDbContext"] Table["CmsInstances table"] end CmsService --> Deps Deps --> Repo Deps --> SlaveClientIface Deps --> ApiKeyProt Deps --> HttpCtxAcc Deps --> Logger Deps --> Opts ApiKeyProt --> ApiKeyProtImpl ApiKeyProtImpl --> DataProt DataProt --> Purpose SlaveClientIface --> SlaveClientImpl SlaveClientImpl --> PollyPipeline PollyPipeline --> HttpClientInst Repo --> RepoImpl RepoImpl --> DbCtx DbCtx --> Table BgSvc --> PeriodicT BgSvc --> ScopeFactory ScopeFactory --> Scope Scope --> CmsService classDef service fill:#9ae6b4,stroke:#2f855a,stroke-width:2px,color:#000 classDef security fill:#FC8181,stroke:#C53030,stroke-width:1px,color:#000 classDef http fill:#63b3ed,stroke:#2b6cb0,stroke-width:1px,color:#000 classDef background fill:#CE93D8,stroke:#6A1B9A,stroke-width:1px,color:#000 classDef data fill:#FFC107,stroke:#F57F17,stroke-width:1px,color:#000 classDef record fill:#B0BEC5,stroke:#546E7A,stroke-width:1px,color:#000 class CmsService,Repo,SlaveClientIface,ApiKeyProt service class Deps record class ApiKeyProtImpl,DataProt,Purpose security class SlaveClientImpl,PollyPipeline,HttpClientInst,HttpCtxAcc http class BgSvc,ScopeFactory,Scope,PeriodicT background class RepoImpl,DbCtx,Table,Logger,Opts data ``` Text alternative: CmsInstanceService receives all dependencies via MasterServiceDependencies record; IApiKeyProtector wraps Data Protection; ISlaveApiClient wraps SlaveApiClient backed by Polly pipeline; ICmsInstanceRepository wraps MasterDbContext; IntegrityCheckBackgroundService creates a new IServiceScope per PeriodicTimer tick to resolve CmsInstanceService. --- ## Component Responsibility Summary | Component | Type | NFR Pattern | |-----------|------|------------| | `MasterServiceDependencies` | Record | Constructor aggregation (reduces constructor arity) | | `IApiKeyProtector` / `ApiKeyProtector` | Interface + Singleton | Security — Data Protection wrapper; mock-friendly | | `SlaveApiClient` | Typed HTTP client | Resilience — Polly retry + timeout applied via `AddResilienceHandler` | | `IntegrityCheckBackgroundService` | Singleton `BackgroundService` | Reliability — per-tick `IServiceScope`; exception isolation per slave | | `MasterDbContext` | EF Core DbContext | Maintainability — per-module migrations; own connection | | `CmsInstanceService` | Scoped service | Orchestration — resolved via `IServiceScope` by background service | --- ## DI Registration Order (in `MasterModule.RegisterServices`) ``` 1. services.AddDataProtection() 2. services.AddSingleton() 3. services.Configure(config.GetSection("MasterModule")) 4. services.AddDbContext(...) 5. services.AddScoped() 6. services.AddScoped() 7. services.AddScoped() 8. services.AddHttpClient() .AddResilienceHandler("slave-resilience", ...) 9. services.AddHostedService() 10. services.AddHttpContextAccessor() (if not already registered by host) ``` --- ## NFR Coverage Traceability | NFR | Pattern Applied | Component | |-----|----------------|-----------| | Fail-open (NFR-MASTER-01) | `SlaveApiClient` catches failures, returns `false`; service continues | `SlaveApiClient`, `CmsInstanceService` | | API key security (NFR-MASTER-03) | `IApiKeyProtector` wraps Data Protection; never returns key in DTO | `ApiKeyProtector`, `CmsInstanceDto` mapping | | Configurable interval (NFR-MASTER-04) | `PeriodicTimer` reads `MasterModuleOptions.IntegrityCheckIntervalMinutes` | `IntegrityCheckBackgroundService` | | ≥80% test coverage (NFR-MASTER-05) | All service/repository/client classes have interfaces; `MasterServiceDependencies` simplifies test setup | All interfaces | | Per-module migrations (NFR-MASTER-06) | `MasterDbContext` with own migration assembly; applied in `UseModule` | `MasterDbContext`, `MasterModule` | | Retry resilience (Q2) | Polly exponential backoff on `IHttpClientBuilder` | `SlaveApiClient` registration | | Timeout (Q1) | Polly `AddTimeout` per attempt, driven by `HttpTimeoutSeconds` | `SlaveApiClient` registration | | Logging levels (Q5) | `Error` for status push failures; `Warning` for integrity check failures | `CmsInstanceService`, `IntegrityCheckBackgroundService` |