Files
slp-modular-cms/aidlc-docs/features/master-cms-module/construction/master-backend/code/code-summary.md
T
SluijsensandClaude Sonnet 5 0447993181 Completes local-dev-master-slave-setup: dual-instance frontend tooling, module-capability gating, and master/slave protocol self-healing fixes
Frontend (Unit 2 completion): dual dev-server tooling (pnpm dev:slave,
pnpm dev:all), per-instance browser tab titles, and a backend
capability check (SystemController + useSystemCapabilities +
ModuleGuard) so a Master-only page is hidden on a slave instance
instead of assuming every backend has every module.

Master/slave protocol fixes surfaced by actually running master and
slave side by side locally:
- Deactivating a CMS instance (Inactive) now releases the slave's
  master gate instead of leaving it stuck on its last pushed status.
- The periodic integrity check now also re-pushes status to every
  reachable slave (previously URL-verification only) and runs once
  immediately on startup.
- Added the originally-specified (but never implemented) slave-pull
  path: a slave now periodically polls its own status from the master
  (GET /api/v1/SlaveStatus) and fails open to Available if the master
  is unreachable for too long, complementing the existing push.
- The slave's own Settings page can no longer "successfully" change
  local availability while the master controls it; it's now locked
  with an explanatory banner and the backend rejects the write with
  409 instead of silently no-op'ing it.
- CMS instance status badges now match the dashboard's color/icon
  styling instead of a plain grey badge.

Also corrected the master-cms-module design docs to match this
as-built behavior, and flagged (without a full rewrite) a larger,
pre-existing divergence between its inception-stage application
design and what construction actually built.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 19:53:52 +02:00

5.6 KiB

Code Summary — Unit 1: master-backend

New Project: SlpModularCms.Modules.Master

File Description
SlpModularCms.Modules.Master.csproj Project file; references Core; adds Microsoft.Extensions.Http.Resilience 9.6.0
Options/MasterModuleOptions.cs Configuration POCO: IntegrityCheckIntervalMinutes, HttpTimeoutSeconds, MasterUrl, CacheMinutes, ApiKey
Data/Entities/CmsInstanceStatus.cs Enum: Available=0, NotAvailable=1, Inactive=2
Data/Entities/CmsInstance.cs EF Core entity with all domain fields including LastIntegrityCheckFailedAt
Data/MasterDbContext.cs Per-module DbContext; table MasterCmsInstances; configured via OnModelCreating
Models/CmsInstanceDto.cs Record DTO (excludes ApiKey); ExcludeFromCodeCoverage
Models/CreateCmsInstanceRequest.cs Record request for POST; ExcludeFromCodeCoverage
Models/UpdateStatusRequest.cs Record request for status update; ExcludeFromCodeCoverage
Models/UpdateStatusResult.cs Record result with Success + SlaveContactSuccess; ExcludeFromCodeCoverage
Repositories/ICmsInstanceRepository.cs Interface: GetAllAsync, GetActiveAsync, GetByIdAsync, AddAsync, Update, SaveChangesAsync
Repositories/CmsInstanceRepository.cs EF Core implementation; GetActiveAsync excludes Inactive
Services/IApiKeyProtector.cs Interface: Protect/Unprotect
Services/ApiKeyProtector.cs Data Protection wrapper; purpose string "SlpModularCms.Master.ApiKey"
Services/ISlaveApiClient.cs Interface: RegisterMasterAsync, PushStatusAsync, GetRegisteredMasterUrlAsync
Services/SlaveApiClient.cs Typed HTTP client; X-Master-Api-Key header on each call; fail-open (returns false on exception)
Services/MasterServiceDependencies.cs Record aggregating 6 CmsInstanceService dependencies; ExcludeFromCodeCoverage
Services/ICmsInstanceService.cs Interface: GetAllAsync, AddAsync, UpdateStatusAsync, VerifyIntegrityAsync
Services/CmsInstanceService.cs Business logic; HttpContext → config fallback for MasterUrl; never returns ApiKey in DTO
BackgroundServices/IntegrityCheckBackgroundService.cs PeriodicTimer; per-tick IServiceScope; catches all exceptions per tick
Controllers/CmsInstanceController.cs [Authorize(Policy="OwnerOnly")]; GET / POST / PUT /{id}/status
MasterModule.cs IModule implementation; DI registration; db.Database.Migrate() in UseModule; ExcludeFromCodeCoverage
Migrations/.gitkeep Placeholder; run CLI to generate migration (see below)

New Project: SlpModularCms.Modules.Master.Tests

File Description
SlpModularCms.Modules.Master.Tests.csproj xUnit + NSubstitute + FluentAssertions + EF InMemory
Repositories/CmsInstanceRepositoryTests.cs EF InMemory; covers all repository methods
Services/ApiKeyProtectorTests.cs Uses EphemeralDataProtectionProvider; round-trip + invalid ciphertext tests
Services/SlaveApiClientTests.cs FakeHttpMessageHandler; tests success/failure/exception paths + header assertion
Services/CmsInstanceServiceTests.cs NSubstitute; covers all business logic branches including HttpContext fallback
BackgroundServices/IntegrityCheckBackgroundServiceTests.cs PeriodicTimer integration; verifies exception isolation
Controllers/CmsInstanceControllerTests.cs NSubstitute ICmsInstanceService; verifies all HTTP response codes

Modified Files

File Change
src/SlpModularCms.Api/SlpModularCms.Api.csproj Added ProjectReference to SlpModularCms.Modules.Master
SlpModularCms.sln Added both new projects with GUIDs and src folder nesting

EF Core Migration

After building the solution, run:

dotnet ef migrations add InitialCreate --project src/SlpModularCms.Modules.Master --startup-project src/SlpModularCms.Api

This generates the Migrations/ folder contents. The migration is applied automatically on startup via db.Database.Migrate() in MasterModule.UseModule.

Notes

  • Microsoft.Extensions.Http.Resilience version 9.6.0 — verify/update during dotnet restore if a newer version is available for .NET 10
  • IntegrityCheckIntervalMinutes = 0 in tests forces immediate PeriodicTimer ticks (valid for test scenarios only)
  • Slave-side endpoints (/api/v1/master/register, /api/v1/master/status, /api/v1/master/registered-url) are implemented in Unit 2 (slave-availability-extension)

Addendum — 2026-07-04 (added outside this unit's original scope, in local-dev-master-slave-setup follow-up fixes)

This unit predates the following; see slave-availability-extension/functional-design/business-rules.md Rule Set 5 and application-design/application-design.md for the full picture:

File Description
Controllers/SlaveStatusController.cs New. [AllowAnonymous] GET /api/v1/SlaveStatus; authenticates via X-Master-Api-Key header matched against each active CmsInstance's decrypted key; lets a slave pull its own status instead of relying solely on the master's push
Services/ICmsInstanceService.cs / CmsInstanceService.cs GetStatusForApiKeyAsync(plainApiKey) added; UpdateStatusAsync's Inactive branch now pushes Available/null to release the gate (previously a no-op); VerifyIntegrityAsync now also re-pushes persisted status to every reachable active slave each cycle
BackgroundServices/IntegrityCheckBackgroundService.cs Now runs one tick immediately on startup, in addition to the periodic timer
Models/SlaveStatusPollResponse (in ICmsInstanceService.cs) New record: IsAvailable, DisableMessage