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>
7.3 KiB
Code Generation Summary — Unit 1: Backend Dual-Instance Hosting
Created
src/SlpModularCms.Core/Hosting/ModuleOrchestrator.cssrc/SlpModularCms.Core/Hosting/ServiceCollectionExtensions.cssrc/SlpModularCms.Core/Hosting/ApiPrefixConvention.cssrc/SlpModularCms.Api.Slave/SlpModularCms.Api.Slave.csprojsrc/SlpModularCms.Api.Slave/Program.cssrc/SlpModularCms.Api.Slave/appsettings.jsonsrc/SlpModularCms.Api.Slave/appsettings.Development.jsonsrc/SlpModularCms.Api.Slave/appsettings.local.json.examplesrc/SlpModularCms.Api.Slave/Properties/launchSettings.jsonsrc/SlpModularCms.Core.Tests/Hosting/ApiPrefixConventionTests.cs(relocated fromModules.Identity.Tests)src/SlpModularCms.Core.Tests/Hosting/ModuleOrchestratorTests.cs(relocated fromModules.Identity.Tests)
Modified
src/SlpModularCms.Core/SlpModularCms.Core.csproj— addedAsp.Versioning.MvcandMicrosoft.AspNetCore.OpenApipackage referencessrc/SlpModularCms.Api/Program.cs—usingstatements updated toSlpModularCms.Core.Hosting(no logic change)src/SlpModularCms.Modules.Identity.Tests/SlpModularCms.Modules.Identity.Tests.csproj— removedProjectReferencetoSlpModularCms.Api(no longer needed; the only tests using it were relocated toCore.Tests)SlpModularCms.sln— addedSlpModularCms.Api.Slaveproject entry, build configurations, and solution-folder nesting undersrc
Deleted
src/SlpModularCms.Api/Infrastructure/ModuleOrchestrator.cs(moved to Core)src/SlpModularCms.Api/Extensions/ServiceCollectionExtensions.cs(moved to Core)src/SlpModularCms.Api/Infrastructure/ApiPrefixConvention.cs(moved to Core)src/SlpModularCms.Modules.Identity.Tests/Infrastructure/ModuleOrchestratorTests.cs(relocated toCore.Tests/Hosting/)src/SlpModularCms.Modules.Identity.Tests/Infrastructure/ApiPrefixConventionTests.cs(relocated toCore.Tests/Hosting/)
Notes / Deviations from Plan
- Discovered during generation that
SlpModularCms.Modules.Identity.TestsreferencedSlpModularCms.Apisolely to testModuleOrchestrator/ApiPrefixConvention— an existing layering quirk, not something this feature introduced. Since those classes now live inCore, their tests were relocated toCore.Tests/Hosting/(which already referencesCoreand already has all needed test packages: FluentAssertions, NSubstitute, xunit). This removed the odd cross-project test dependency as a side effect. ServiceCollectionExtensions.csneeded explicitusing Microsoft.Extensions.Configuration;,using Microsoft.Extensions.DependencyInjection;,using Microsoft.AspNetCore.Builder;, andusing Microsoft.AspNetCore.Http;after the move —SlpModularCms.Apiis aMicrosoft.NET.Sdk.Webproject (implicit ASP.NET Core usings), whileSlpModularCms.Coreis a plainMicrosoft.NET.Sdkproject, so these weren't implicitly available.- Left
Asp.Versioning.MvcandMicrosoft.AspNetCore.OpenApipackage references in place onSlpModularCms.Api.csprojeven though they're now also referenced transitively viaCore— removing them was optional per the plan and the build succeeds either way; left as-is to minimize unrelated diff.
Verification Performed
dotnet build SlpModularCms.sln— succeeds, no errors.dotnet test SlpModularCms.sln— all 4 existing test projects pass unchanged:Core.Tests(54),Modules.Availability.Tests(60),Modules.Identity.Tests(37),Modules.Master.Tests(42).- Manually ran
dotnet run --launch-profile httpsin bothSlpModularCms.ApiandSlpModularCms.Api.Slave:- Master (
SlpModularCms.Api): discovers and loads all 3 modules — Availability, Identity, Master. - Slave (
SlpModularCms.Api.Slave): discovers and loads exactly 2 modules — Availability, Identity. Master is correctly excluded.
- Master (
- Full end-to-end run (requiring a real local SQL Server/localdb instance and manual "Add CMS Instance" registration) is deferred to Build and Test / Unit 2, per the plan.
Follow-up: Real appsettings.local.json for the Slave (user request)
The user reported the slave's connection string looked wrong and asked for a real src/SlpModularCms.Api.Slave/appsettings.local.json (gitignored, mirroring src/SlpModularCms.Api/appsettings.local.json's credentials but with its own database). Created with Database=SlpModularCmsSlave (vs. master's SlpModularCms), same Server=127.0.0.1,1433;User ID=sa;Password=... credentials and same JwtSettings.Secret. Verified via git check-ignore that it's not tracked.
Verified working: running dotnet run --launch-profile https --no-build in SlpModularCms.Api.Slave with this file present successfully connected to the local SQL Server, created the SlpModularCmsSlave database, and applied EF Core migrations (CREATE DATABASE, __EFMigrationsHistory setup, migration application) — confirming the connection string is correct. This environment does have a reachable SQL Server at 127.0.0.1:1433, unlike assumed earlier in Build and Test.
Known issue hit during this verification, not related to the fix: a subsequent attempt to run both master and slave simultaneously hit Failed to bind to address ... address already in use on both :7221 and :7222 — leftover dotnet run child processes from earlier manual verification steps in this session likely survived their parent timeout calls and are still holding those ports. This is a session/environment artifact, not a defect in the generated code. Resolved: user closed their own processes and confirmed via Get-CimInstance/Get-NetTCPConnection that no SlpModularCms processes or listeners remained on ports 7221/7222/5284/5285.
Follow-up: Slave Database Migration Gap (discovered while checking migration status)
User asked whether the necessary migrations exist and both databases are up to date. Checked via dotnet ef migrations list for every DbContext/startup-project combination:
| Database | Context | Status before fix |
|---|---|---|
SlpModularCms (master) |
ApplicationDbContext (Core/Identity) |
✅ Applied (2/2) |
SlpModularCms (master) |
AvailabilityDbContext |
✅ Applied (1/1) |
SlpModularCms (master) |
MasterDbContext |
✅ Applied (1/1) |
SlpModularCmsSlave (slave) |
AvailabilityDbContext |
✅ Applied (1/1) — auto-migrated via Database.Migrate() in AvailabilityModule.UseModule |
SlpModularCmsSlave (slave) |
ApplicationDbContext (Core/Identity) |
❌ 2 migrations pending — SlpModularCms.Core's ApplicationDbContext is never auto-migrated (only Modules.Availability and Modules.Master call Database.Migrate() in their UseModule); it always requires the manual dotnet ef database update step documented in root README.md, and nobody had run it yet for the new slave database. |
Fixed: ran dotnet ef database update --project src/SlpModularCms.Core --startup-project src/SlpModularCms.Api.Slave --context ApplicationDbContext. Re-checked with migrations list — both 20260612191736_InitialCreate and 20260619130625_AddsDisplayName now show as applied (no (Pending) marker). Slave database is now fully up to date.
Documentation fix: added a note + the exact command to the "Lokaal Master + Slave Draaien (Dev)" runbook in root README.md, right after the slave-startup instructions, so this doesn't get missed again by whoever (re)creates the slave database.