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>
This commit is contained in:
+41
@@ -0,0 +1,41 @@
|
||||
# Build and Test Summary — Local Dev Master/Slave Setup
|
||||
|
||||
## Build Status
|
||||
- **Build Tool**: .NET 10 SDK (`dotnet build`)
|
||||
- **Build Status**: ✅ Success
|
||||
- **Build Artifacts**: `src/SlpModularCms.Api.Slave/bin/` (new), plus unchanged outputs for all existing projects
|
||||
- **Build Time**: ~5 seconds (incremental)
|
||||
|
||||
## Test Execution Summary
|
||||
|
||||
### Unit Tests
|
||||
- **Total Tests**: 193 (54 + 60 + 37 + 42 across `Core.Tests`, `Modules.Availability.Tests`, `Modules.Identity.Tests`, `Modules.Master.Tests`)
|
||||
- **Passed**: 193
|
||||
- **Failed**: 0
|
||||
- **Coverage**: Unchanged from before this feature (no new business logic; relocated code retains its existing tests)
|
||||
- **Status**: ✅ Pass
|
||||
|
||||
### Integration Tests
|
||||
- **Test Scenarios**: 2 (module isolation; end-to-end master/slave connection via existing Add CMS Instance flow)
|
||||
- **Passed**: 1 (module isolation — verified via manual `dotnet run` of both hosts, confirmed via log output: master loads 3 modules, slave loads exactly 2, Master excluded)
|
||||
- **Failed**: 0
|
||||
- **Not Run**: 1 (end-to-end connection scenario — requires a local SQL Server instance; no container runtime available in this sandboxed session. Documented as a manual step for the developer in `integration-test-instructions.md` and the root `README.md` runbook.)
|
||||
- **Status**: ⚠️ Partial — the scenario this feature actually changes (module isolation) is fully verified; the scenario exercising the pre-existing, unmodified master/slave protocol requires manual follow-up.
|
||||
|
||||
### Performance Tests
|
||||
- **Status**: N/A — this feature is local developer tooling with no performance requirements (NFR-3, local-only scope).
|
||||
|
||||
### Additional Tests
|
||||
- **Contract Tests**: N/A — no API contracts changed
|
||||
- **Security Tests**: N/A — no new attack surface; `appsettings.local.json` secrets-hygiene pattern (NFR-4) followed and verified via `git check-ignore`
|
||||
- **E2E Tests**: See Integration Tests Scenario 2 above
|
||||
|
||||
## Overall Status
|
||||
- **Build**: ✅ Success
|
||||
- **All Automated Tests**: ✅ Pass (193/193)
|
||||
- **Manual Follow-up Required**: Yes — developer should run the end-to-end connection test (root `README.md`, "Lokaal Master + Slave Draaien (Dev)") at least once with a real local SQL Server to confirm the full workflow before relying on it.
|
||||
- **Ready for Operations**: Yes (Operations is a placeholder for this project; no deployment/monitoring work applicable to local dev tooling)
|
||||
|
||||
## Next Steps
|
||||
- Developer runs the manual end-to-end verification (Scenario 2) locally to close out the one remaining unverified item.
|
||||
- Feature is otherwise complete: `SlpModularCms.Api.Slave` exists and correctly excludes the Master module, `SlpModularCms.Core.Hosting` avoids code duplication between the two hosts, frontend tooling and documentation are in place.
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
# Build Instructions — Local Dev Master/Slave Setup
|
||||
|
||||
## Prerequisites
|
||||
- **Build Tool**: .NET 10 SDK
|
||||
- **Dependencies**: NuGet packages restore automatically on build (no new external dependencies introduced by this feature)
|
||||
- **Environment Variables**: None required to build (runtime config is via `appsettings.local.json`, see below)
|
||||
- **System Requirements**: Same as the rest of the repository — no new system requirements
|
||||
|
||||
## Build Steps
|
||||
|
||||
### 1. Restore & Build
|
||||
```powershell
|
||||
dotnet build SlpModularCms.sln
|
||||
```
|
||||
|
||||
### 2. Verify Build Success
|
||||
- **Expected Output**: `Build succeeded.` with 0 errors (NuGet advisory warnings for `Microsoft.OpenApi` and a few `NU1510`/prune warnings are pre-existing and unrelated to this feature).
|
||||
- **Build Artifacts**: `src/SlpModularCms.Api/bin/`, `src/SlpModularCms.Api.Slave/bin/` (new), plus all existing project outputs.
|
||||
- **Common Warnings**: NU1903 (Microsoft.OpenApi advisory) and NU1510 (package pruning) appear across multiple projects — pre-existing, not introduced by this feature.
|
||||
|
||||
### Actual Result (this session)
|
||||
Ran `dotnet build SlpModularCms.sln` — **Build succeeded**, 0 errors.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Build Fails with `CS0246` in `SlpModularCms.Core/Hosting/*.cs`
|
||||
- **Cause**: `SlpModularCms.Core` is a plain `Microsoft.NET.Sdk` project (not `Sdk.Web`), so ASP.NET Core implicit usings (`Microsoft.Extensions.DependencyInjection`, `Microsoft.Extensions.Configuration`, `Microsoft.AspNetCore.Builder`, `Microsoft.AspNetCore.Http`) aren't automatically available like they are in `SlpModularCms.Api`.
|
||||
- **Solution**: Already fixed during Code Generation — explicit `using` statements were added to `ServiceCollectionExtensions.cs`. If this recurs after further edits, add the missing explicit `using`.
|
||||
|
||||
### `SlpModularCms.Api.Slave` fails to start with a SQL connection error
|
||||
- **Cause**: Missing `src/SlpModularCms.Api.Slave/appsettings.local.json` (gitignored, must be created locally per developer).
|
||||
- **Solution**: Copy `appsettings.local.json.example` to `appsettings.local.json` and fill in your local SQL Server credentials, using a **different** `Database=` name than the master instance (e.g. `SlpModularCmsSlave`).
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
# Integration Test Instructions — Local Dev Master/Slave Setup
|
||||
|
||||
## Purpose
|
||||
|
||||
Verify that the two backend instances (Unit 1) and frontend tooling (Unit 2) work together correctly: the slave instance genuinely excludes the Master module, and the existing master↔slave connection mechanism (unchanged by this feature) can be exercised end-to-end using the two local instances.
|
||||
|
||||
## Test Scenarios
|
||||
|
||||
### Scenario 1: Module isolation — Slave excludes Master, Master keeps all modules
|
||||
|
||||
**Description**: Confirm `SlpModularCms.Api.Slave`'s `ModuleOrchestrator` never discovers `Modules.Master`, while `SlpModularCms.Api` is unaffected.
|
||||
|
||||
**Setup**: None beyond a successful build (no database required — module discovery happens before any DB access).
|
||||
|
||||
**Test Steps** (already executed in this session):
|
||||
```powershell
|
||||
dotnet run --project src/SlpModularCms.Api --launch-profile https --no-build
|
||||
dotnet run --project src/SlpModularCms.Api.Slave --launch-profile https --no-build
|
||||
```
|
||||
|
||||
**Expected Results**:
|
||||
- Master log output: `Module ontdekt: Availability`, `Module ontdekt: Identity`, `Module ontdekt: Master`, `3 modules succesvol geladen.`
|
||||
- Slave log output: `Module ontdekt: Availability`, `Module ontdekt: Identity`, `2 modules succesvol geladen.` — **no** `Master` line.
|
||||
|
||||
**Actual Result**: ✅ **Passed** — confirmed exactly as expected in this session's console output (see Unit 1 code generation summary).
|
||||
|
||||
**Cleanup**: Stop both processes (Ctrl+C / process termination).
|
||||
|
||||
### Scenario 2: End-to-end master/slave connection via the existing "Add CMS Instance" flow
|
||||
|
||||
**Description**: With both instances running against separate local databases, use the master frontend's existing "Add CMS Instance" dialog to register the local slave and confirm the connection is established (per FR-4 and the runbook in root `README.md`).
|
||||
|
||||
**Setup**:
|
||||
1. A local SQL Server instance reachable from both backends (e.g. via the `podman run ... mcr.microsoft.com/mssql/server` command in root `README.md`).
|
||||
2. `src/SlpModularCms.Api/appsettings.local.json` (master) and `src/SlpModularCms.Api.Slave/appsettings.local.json` (slave, from `appsettings.local.json.example`) pointing at **different** database names on that SQL Server.
|
||||
3. Master and slave backends running (`dotnet run --project src/SlpModularCms.Api --launch-profile https` and `dotnet run --project src/SlpModularCms.Api.Slave --launch-profile https`).
|
||||
4. Master frontend running (`pnpm dev` in `frontend/`), logged in as an Owner.
|
||||
|
||||
**Test Steps**:
|
||||
1. Navigate to the `/cms` page on the master frontend.
|
||||
2. Use "Add CMS Instance" with URL `https://localhost:7222` (the local slave).
|
||||
3. Observe the instance's status in the UI.
|
||||
|
||||
**Expected Results**: The instance appears in the list and its status reflects a successful connection (per the existing, unchanged `CmsInstanceService`/`SlaveApiClient` ↔ `MasterController` protocol documented in root `README.md`'s "Master CMS Module" section).
|
||||
|
||||
**Actual Result**: ⚠️ **Not run in this session** — this sandboxed environment has no accessible container runtime (`docker`/`podman` both unavailable), so no local SQL Server instance could be provisioned to run either backend past module discovery. **This step requires manual execution by the developer** following the runbook in root `README.md` ("Lokaal Master + Slave Draaien (Dev)"). Scenario 1 (module isolation, which does not require a database) was fully verified automatically and is the aspect this feature actually changes — Scenario 2 exercises the pre-existing, unmodified master/slave protocol and primarily validates that the new run configuration (ports, separate databases, CORS) doesn't get in the way of it.
|
||||
|
||||
**Cleanup**: Remove the CMS instance registration if desired; stop both backends and frontends; stop the SQL Server container if it was started solely for this test.
|
||||
|
||||
## Notes
|
||||
|
||||
- No automated integration test suite was added for Scenario 2 — it's an inherently manual, cross-process, cross-database verification of local developer tooling, not a candidate for CI automation (per NFR-3, this feature is explicitly local-only in scope).
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
# Unit Test Execution — Local Dev Master/Slave Setup
|
||||
|
||||
## Run Unit Tests
|
||||
|
||||
### 1. Execute All Unit Tests
|
||||
```powershell
|
||||
dotnet test SlpModularCms.sln
|
||||
```
|
||||
|
||||
### 2. Review Test Results
|
||||
- **Expected**: All existing test suites pass unchanged — this feature adds no new business logic, so no new unit tests were written (per Unit of Work Q3 = A).
|
||||
- **Test Coverage**: Unchanged from before this feature (the relocated `ModuleOrchestrator`/`ApiPrefixConvention` classes retain their existing test coverage, now in `SlpModularCms.Core.Tests/Hosting/` instead of `SlpModularCms.Modules.Identity.Tests/Infrastructure/`).
|
||||
- **Test Report Location**: Console output from `dotnet test`; no separate report file generated by default.
|
||||
|
||||
### Actual Result (this session)
|
||||
Ran `dotnet test SlpModularCms.sln`:
|
||||
|
||||
| Test Project | Passed | Failed | Skipped |
|
||||
|---|---|---|---|
|
||||
| `SlpModularCms.Core.Tests` (incl. relocated `Hosting` tests) | 54 | 0 | 0 |
|
||||
| `SlpModularCms.Modules.Availability.Tests` | 60 | 0 | 0 |
|
||||
| `SlpModularCms.Modules.Identity.Tests` | 37 | 0 | 0 |
|
||||
| `SlpModularCms.Modules.Master.Tests` | 42 | 0 | 0 |
|
||||
| **Total** | **193** | **0** | **0** |
|
||||
|
||||
No regressions from relocating `ModuleOrchestrator`, `ServiceCollectionExtensions`, and `ApiPrefixConvention` into `SlpModularCms.Core`, or from moving their tests into `Core.Tests`.
|
||||
|
||||
### 3. Fix Failing Tests
|
||||
Not applicable this run — all tests passed on first execution after Code Generation.
|
||||
Reference in New Issue
Block a user