# NFR Requirements — Unit 1: master-backend ## Performance | Requirement | Specification | Source | |-------------|--------------|--------| | HTTP timeout for slave calls | Configurable via `MasterModuleOptions.HttpTimeoutSeconds`; default **10 seconds** | Q1 | | HTTP retry budget | Maximum 3 attempts (initial + 2 retries) with exponential backoff (1s, 2s); per-attempt timeout applies | Q2 | | Background service interval | Configurable via `MasterModuleOptions.IntegrityCheckIntervalMinutes`; default 60 minutes | NFR-MASTER-04 | | Controller endpoint latency | No explicit SLA; bounded by HTTP timeout × retry attempts (worst case ~33s for a single unresponsive slave during Add/UpdateStatus) | derived | --- ## Security | Requirement | Specification | Source | |-------------|--------------|--------| | ApiKey at-rest encryption | Encrypted with ASP.NET Core Data Protection before writing to DB; decrypted immediately before HTTP calls | Q3 (+ functional design) | | Data Protection key storage | **Default file system** (platform default); machine-bound; acceptable for single-instance deployment | Q3 | | ApiKey exposure | Never included in `CmsInstanceDto` or any API response; `[JsonIgnore]` or explicit DTO mapping | NFR-MASTER-03 | | Endpoint authorization | All `CmsInstanceController` actions require `[Authorize(Policy = "OwnerOnly")]` | FR-MASTER-10 | | Internal slave endpoint auth | `POST /api/internal/master/register` validated via `X-Master-Api-Key` header (Unit 2 concern) | FR-MASTER-03 | --- ## Reliability | Requirement | Specification | Source | |-------------|--------------|--------| | Fail-open on slave unreachability | Status push failure returns `SlaveContactSuccess = false` but does not roll back DB change; integrity check sets `LastIntegrityCheckFailedAt` and continues | NFR-MASTER-01 | | Retry policy | Exponential backoff: attempt 1 (immediate), attempt 2 (+1s delay), attempt 3 (+2s delay); implemented via Polly `ResiliencePipeline` | Q2 | | Background service isolation | Exceptions per slave instance are caught, logged, and do not abort the full integrity check batch | BR-BG-03 | | Background service scope | `IServiceScopeFactory` used per tick to resolve scoped `ICmsInstanceService`; scope disposed after each tick | BR-BG-01/02 | --- ## Testability | Requirement | Specification | Source | |-------------|--------------|--------| | Minimum test coverage | ≥ 80% line/branch coverage for `SlpModularCms.Modules.Master` (excluding items below) | NFR-MASTER-05 | | Coverage exclusions | Apply `[ExcludeFromCodeCoverage]` to: `MasterModule.cs` (IModule boilerplate), EF Core migration files, plain DTO/record classes with no logic | Q4 | | Test project | `SlpModularCms.Modules.Master.Tests` — separate project; mirrors production project structure | Unit decomposition decision | | Key test targets | `CmsInstanceService`, `SlaveApiClient`, `IntegrityCheckBackgroundService`, `CmsInstanceController` | NFR-MASTER-05 | | Interface-driven design | `ICmsInstanceRepository`, `ICmsInstanceService`, `ISlaveApiClient` interfaces required to enable unit test mocking | derived | --- ## Maintainability | Requirement | Specification | Source | |-------------|--------------|--------| | Log level — integrity check failures | **Warning** — slave unreachability during background checks is expected; does not require immediate attention | Q5 | | Log level — status push failures | **Error** — owner-triggered action failed to reach slave; requires visibility | Q5 | | Log level — re-registration on mismatch | **Information** — expected recovery action | derived | | Log level — background service tick | **Debug** — high frequency; only visible when debugging | derived | | Structured logging | Use `ILogger` with structured message templates; include `slaveUrl` and `instanceId` in log scope | derived | --- ## Updated `MasterModuleOptions` Fields The following field is added as a result of Q1: | Property | Type | Default | Notes | |----------|------|---------|-------| | `HttpTimeoutSeconds` | `int` | `10` | Timeout applied to each individual HTTP attempt in `SlaveApiClient` | Full updated options shape: | Property | Type | Default | Side | |----------|------|---------|------| | `IntegrityCheckIntervalMinutes` | `int` | `60` | Master | | `HttpTimeoutSeconds` | `int` | `10` | Master | | `MasterUrl` | `string?` | `null` | Master | | `CacheMinutes` | `int` | `60` | Slave | | `ApiKey` | `string?` | `null` | Slave |