# Unit of Work — Master CMS Module ## Unit Decomposition Overview | # | Unit Slug | Project(s) | Test Project | Construction Cycle | |---|-----------|-----------|--------------|-------------------| | 1 | `master-backend` | `SlpModularCms.Modules.Master` (NEW) | `SlpModularCms.Modules.Master.Tests` (NEW) | FD → NFR Req → NFR Design → Code Gen | | 2 | `slave-availability-extension` | `SlpModularCms.Modules.Availability` (EXTENDED) | `SlpModularCms.Modules.Availability.Master.Tests` (NEW) | FD → NFR Req → NFR Design → Code Gen | | 3 | `frontend-cms-page` | `frontend/` (EXTENDED) | Existing frontend test setup | FD → NFR Req → NFR Design → Code Gen | | 4 | `documentation` | `README.md`, `frontend/README.md` | N/A | Code Gen only | --- ## Unit 1 — master-backend **Project**: `src/SlpModularCms.Modules.Master/` (new project added to solution) **Test Project**: `src/SlpModularCms.Modules.Master.Tests/` (new; parallel to existing `Availability.Tests`) **Construction Cycle**: Functional Design → NFR Requirements → NFR Design → Code Generation **Scope**: - New `SlpModularCms.Modules.Master` class library project - `MasterModule : IModule` — module registration, service wiring, migration application - `MasterDbContext` — per-module EF Core DbContext; owns `CmsInstances` table - `CmsInstance` entity + `CmsInstanceStatus` enum - `ICmsInstanceRepository` / `CmsInstanceRepository` — data access - `ICmsInstanceService` / `CmsInstanceService` — business orchestration - `ISlaveApiClient` / `SlaveApiClient` — typed HTTP client for master → slave calls - `CmsInstanceController` — REST endpoints (`GET`, `POST`, `PUT /status`) with `[Authorize(Policy = "OwnerOnly")]` - `IntegrityCheckBackgroundService` — periodic master URL integrity verification - `MasterModuleOptions` — configuration POCO - DTOs: `CmsInstanceDto`, `CreateCmsInstanceRequest`, `UpdateStatusRequest` - EF Core migrations for `CmsInstances` table **Dependencies**: `SlpModularCms.Core` (for `IModule`, shared types) **Deliverables**: - Functional, tested module registered in `SlpModularCms.Api` - REST API endpoints accessible to Owner role - Background service running on master CMS startup - EF Core migration applied at startup --- ## Unit 2 — slave-availability-extension **Project**: `src/SlpModularCms.Modules.Availability/` (existing project, extended) **Test Project**: `src/SlpModularCms.Modules.Availability.Master.Tests/` (new; separate from existing `Availability.Tests` to isolate master-related slave changes) **Construction Cycle**: Functional Design → NFR Requirements → NFR Design → Code Generation **Scope**: - `MasterRegistration` entity — stores master URL on slave side - `AvailabilityDbContext` — new per-module EF Core DbContext in Availability module; owns `MasterRegistrations` table - `IMasterAvailabilityService` / `MasterAvailabilityService` — pull/cache/fallback service; static field caching - `AvailabilityMiddleware` (extended) — two-phase gate: Master gate (outer) + existing local gate (inner) - `AvailabilityController` (extended) — `POST /api/internal/master/register` endpoint added - `RegisterMasterRequest` request model - `MasterGateResult` result record - EF Core migrations for `MasterRegistrations` table - `GET /api/internal/master/registration` endpoint (read registered master URL, used by integrity check) **Dependencies**: Unit 1 API contract (endpoint schemas that slave exposes must match what `ISlaveApiClient` calls) **Deliverables**: - Two-phase availability gate active on slave CMS instances - Slave accepts master registration calls with API key validation - Slave pulls and caches master status with fail-open fallback - EF Core migration applied at startup --- ## Unit 3 — frontend-cms-page **Project**: `frontend/` (existing React SPA, extended) **Test Project**: Existing frontend test setup (no separate test project added) **Construction Cycle**: Functional Design → NFR Requirements → NFR Design → Code Generation **Scope**: - `CmsPage` — page component at route `/cms`; Owner-only guard - `CmsInstanceList` — table component with status badges; Inactive rows greyed out - `AddCmsInstanceDialog` — modal form (Name, URL, ApiKey) - `SetStatusDialog` — modal with status dropdown and conditional DisableMessage field - `useCmsInstances.ts` — TanStack Query hook: GET `/api/v1/CmsInstances` - `useAddCmsInstance.ts` — TanStack Query mutation: POST `/api/v1/CmsInstances` - `useUpdateCmsInstanceStatus.ts` — TanStack Query mutation: PUT `/api/v1/CmsInstances/{id}/status` - TypeScript types: `CmsInstance`, `CmsInstanceStatus` enum - Route registration in existing router **Dependencies**: Unit 1 REST API (endpoint definitions must be finalized before frontend hooks) **Deliverables**: - `/cms` page renders list of slave CMSes - Owner can add a slave and set its status - Status badge display for all three states; Inactive greyed out - Mandatory DisableMessage enforced in UI when NotAvailable selected --- ## Unit 4 — documentation **Files**: `README.md` (root), `frontend/README.md` **Test Project**: N/A **Construction Cycle**: Code Generation only (Functional Design, NFR Requirements, NFR Design skipped — documentation-only unit) **Scope** (per FR-MASTER-15): - `README.md` — "Database Migraties" section: document per-module migration pattern - `README.md` — "Nieuwe Module Toevoegen" section: document optional per-module DbContext pattern - `README.md` — "Productie Setup" section: add `MasterModule__CacheMinutes` and `MasterModule__IntegrityCheckIntervalMinutes` env vars - `frontend/README.md` — replace boilerplate with project-specific content **Dependencies**: Units 1–3 (must be complete so final patterns are known before documenting) **Deliverables**: - README accurately reflects per-module migration workflow - Module guide covers optional DbContext pattern - Production env vars list is complete - Frontend README is project-specific and useful