Adds SlpModularCms.Api.Slave for local master/slave dev testing (Unit 1)
Relocates ModuleOrchestrator, ServiceCollectionExtensions, and ApiPrefixConvention from SlpModularCms.Api into SlpModularCms.Core.Hosting so a new Master-less SlpModularCms.Api.Slave host project (ports 5285/7222) can share the same bootstrap code without duplicating it. This lets a developer run a master instance and a slave instance side by side locally to test the master/slave connection, without touching the existing master/slave protocol itself. Relocates the two orchestrator/convention test files from Modules.Identity.Tests to Core.Tests, dropping an incidental ProjectReference to SlpModularCms.Api that existed only for those tests. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+44
@@ -0,0 +1,44 @@
|
||||
# Code Generation Plan — Unit 1: Backend Dual-Instance Hosting
|
||||
|
||||
## Unit Context
|
||||
|
||||
- **Requirements covered**: FR-1, FR-2, NFR-1, NFR-2, NFR-4 (see `inception/requirements/requirements.md`)
|
||||
- **Design source**: `inception/application-design/components.md`, `component-methods.md`, `unit-of-work.md`
|
||||
- **Dependencies**: None (first unit)
|
||||
- **Blocks**: Unit 2 (Frontend dual-instance tooling & runbook)
|
||||
- **Workspace root**: `K:\Development\Projects\SlpModularCms` (brownfield — modify existing files where noted, create new ones elsewhere)
|
||||
- **Solution file**: `SlpModularCms.sln`
|
||||
|
||||
## Steps
|
||||
|
||||
- [x] **Step 1 — Relocate shared bootstrap code into `SlpModularCms.Core`**
|
||||
- Create `src/SlpModularCms.Core/Hosting/ModuleOrchestrator.cs` (moved from `src/SlpModularCms.Api/Infrastructure/ModuleOrchestrator.cs`, namespace `SlpModularCms.Api.Infrastructure` → `SlpModularCms.Core.Hosting`, logic unchanged)
|
||||
- Create `src/SlpModularCms.Core/Hosting/ServiceCollectionExtensions.cs` (moved from `src/SlpModularCms.Api/Extensions/ServiceCollectionExtensions.cs`, namespace `SlpModularCms.Api.Extensions` → `SlpModularCms.Core.Hosting`, logic unchanged; update its internal `using SlpModularCms.Api.Infrastructure;` to `SlpModularCms.Core.Hosting`)
|
||||
- Create `src/SlpModularCms.Core/Hosting/ApiPrefixConvention.cs` (moved from `src/SlpModularCms.Api/Infrastructure/ApiPrefixConvention.cs`, namespace `SlpModularCms.Api.Infrastructure` → `SlpModularCms.Core.Hosting`, logic unchanged)
|
||||
- Delete the three original files from `src/SlpModularCms.Api/`
|
||||
- Modify `src/SlpModularCms.Core/SlpModularCms.Core.csproj`: add `PackageReference` for `Asp.Versioning.Mvc` (version `10.0.0`, matching `SlpModularCms.Api.csproj`) and `Microsoft.AspNetCore.OpenApi` (version `10.0.9`, matching `SlpModularCms.Api.csproj`)
|
||||
|
||||
- [x] **Step 2 — Update `SlpModularCms.Api` to consume relocated code**
|
||||
- Modify `src/SlpModularCms.Api/Program.cs`: change `using SlpModularCms.Api.Extensions;` and `using SlpModularCms.Api.Infrastructure;` to `using SlpModularCms.Core.Hosting;` (keep `using Scalar.AspNetCore;`); no other logic changes
|
||||
- Modify `src/SlpModularCms.Api/SlpModularCms.Api.csproj`: remove `Asp.Versioning.Mvc` and `Microsoft.AspNetCore.OpenApi` `PackageReference` entries (now transitively available via `Core`) — **only if** removing them doesn't break the build; otherwise leave them (harmless duplication is acceptable, functional correctness takes priority over cleanliness here)
|
||||
|
||||
- [x] **Step 3 — Create `SlpModularCms.Api.Slave` project**
|
||||
- Create `src/SlpModularCms.Api.Slave/SlpModularCms.Api.Slave.csproj`: `Microsoft.NET.Sdk.Web`, `net10.0`, same `PropertyGroup` as `SlpModularCms.Api.csproj`; `ProjectReference`s to `SlpModularCms.Core`, `SlpModularCms.Modules.Availability`, `SlpModularCms.Modules.Identity` (**no** `SlpModularCms.Modules.Master` reference); `PackageReference` to `Scalar.AspNetCore` (`2.16.3`, for Development-only Scalar UI, matching `SlpModularCms.Api.csproj`) and `Microsoft.EntityFrameworkCore.Design` (`10.0.9`, matching `SlpModularCms.Api.csproj`)
|
||||
- Create `src/SlpModularCms.Api.Slave/Program.cs`: identical structure to `src/SlpModularCms.Api/Program.cs` (post Step 2), using `SlpModularCms.Core.Hosting` and `Scalar.AspNetCore`
|
||||
|
||||
- [x] **Step 4 — Configuration files for `SlpModularCms.Api.Slave`**
|
||||
- Create `src/SlpModularCms.Api.Slave/appsettings.json`: mirror `SlpModularCms.Api/appsettings.json` structure; omit the `MasterModule` section (not applicable — no `Modules.Master` loaded); placeholder `ConnectionStrings:DefaultConnection` for `SlpModularCms Slave` database
|
||||
- Create `src/SlpModularCms.Api.Slave/appsettings.Development.json`: mirror `SlpModularCms.Api/appsettings.Development.json`; `ConnectionStrings:DefaultConnection` pointing at `Database=SlpModularCmsSlave` (localdb, distinct from master's `SlpModularCms`); `Cors:AllowedOrigins` including `http://localhost:5174`/`https://localhost:5174` (the slave frontend dev-server port reserved for Unit 2); omit `MasterModule` section
|
||||
- Create `src/SlpModularCms.Api.Slave/appsettings.local.json.example` (documented template, since the real file is gitignored — mirrors the pattern of `SlpModularCms.Api`, which doesn't commit `appsettings.local.json` itself)
|
||||
- Create `src/SlpModularCms.Api.Slave/Properties/launchSettings.json`: `http` profile on `http://localhost:5285`; `https` profile on `https://localhost:7222;http://localhost:5285`; both with `ASPNETCORE_ENVIRONMENT=Development`, `launchUrl: scalar`
|
||||
|
||||
- [x] **Step 5 — Add `SlpModularCms.Api.Slave` to the solution**
|
||||
- Modify `SlpModularCms.sln`: add project entry for `SlpModularCms.Api.Slave.csproj` following the existing format/GUID conventions used for other projects in the file
|
||||
|
||||
- [x] **Step 6 — Documentation summary**
|
||||
- Create `aidlc-docs/features/local-dev-master-slave-setup/construction/unit-1-backend-dual-instance-hosting/code/summary.md` documenting what was created/modified, matching the Code Generation completion message content
|
||||
|
||||
## Notes
|
||||
|
||||
- No new business logic, no new tests required for this unit (per Unit of Work Q3 = A) — verification happens via Build and Test (does it compile, does it start, do existing test suites still pass).
|
||||
- `appsettings.local.json` for the slave (actual gitignored file with real local connection string) is created locally by the developer following the `.example` template — consistent with how `SlpModularCms.Api/appsettings.local.json` already works today (present on disk, gitignored, not part of generated code deliverables in aidlc-docs).
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
# Code Generation Plan — Unit 2: Frontend Dual-Instance Tooling & Runbook
|
||||
|
||||
## Unit Context
|
||||
|
||||
- **Requirements covered**: FR-3, FR-4, NFR-3, NFR-4 (see `inception/requirements/requirements.md`)
|
||||
- **Design source**: `inception/application-design/component-dependency.md` (data-flow diagram), `unit-of-work.md`
|
||||
- **Dependencies**: Unit 1 (Backend dual-instance hosting) — complete and verified (master discovers 3 modules, slave discovers 2, no Master)
|
||||
- **Blocks**: Build and Test (final manual verification)
|
||||
- **Workspace root**: `K:\Development\Projects\SlpModularCms`
|
||||
|
||||
## Steps
|
||||
|
||||
- [ ] **Step 1 — Frontend env files for slave mode**
|
||||
- Create `frontend/.env.slave.local` (gitignored via existing `frontend/.gitignore` `*.local` pattern — verified via `git check-ignore`): `VITE_API_BASE_URL=https://localhost:7222`
|
||||
- Modify `frontend/.env.example`: add a second documented block showing the slave-mode value, alongside the existing master-mode `VITE_API_BASE_URL` example
|
||||
|
||||
- [ ] **Step 2 — `dev:slave` npm script**
|
||||
- Modify `frontend/package.json`: add `"dev:slave": "vite --mode slave --port 5174"` to the `scripts` section. Vite's mode-based env loading will load `.env.slave.local` when run with `--mode slave` (Vite loads `.env.[mode].local` in addition to `.env.local`; since both files would apply, and `.env.local` takes precedence per Vite's env-file priority for the same key when both exist for a mode, name the slave file `.env.slave.local` specifically — this file only loads when `--mode slave` is passed, so there is no conflict with the default `.env.local` used by `pnpm dev`)
|
||||
|
||||
- [ ] **Step 3 — Runbook documentation**
|
||||
- Modify root `README.md`: add new section **"Lokaal Master + Slave Draaien (Dev)"** immediately after the existing "Master CMS Module" section, covering:
|
||||
1. Starting the master backend (`dotnet run --project src/SlpModularCms.Api --launch-profile https`)
|
||||
2. Starting the slave backend (`dotnet run --project src/SlpModularCms.Api.Slave --launch-profile https`), noting it needs its own `appsettings.local.json` (from `appsettings.local.json.example`) with a separate local database
|
||||
3. Starting the master frontend (`pnpm dev`, port 5173) and, optionally, the slave frontend (`pnpm dev:slave`, port 5174)
|
||||
4. Using the existing "Add CMS Instance" dialog on the master frontend to register the slave (URL `https://localhost:7222`) and confirm it shows as connected/healthy
|
||||
5. Cross-reference to this feature's requirements doc for anyone wanting the full rationale
|
||||
|
||||
- [ ] **Step 4 — Documentation summary**
|
||||
- Create `aidlc-docs/features/local-dev-master-slave-setup/construction/unit-2-frontend-dual-instance-tooling/code/summary.md` documenting what was created/modified
|
||||
|
||||
## Notes
|
||||
|
||||
- No new tests for this unit — it's env/config/docs only, no testable logic.
|
||||
- Final end-to-end manual verification (actually starting both instances with real local databases, registering the slave, confirming the connection) happens in Build and Test, since it requires a running local SQL Server/localdb the automated agent cannot fully provision headlessly.
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
# Code Generation Summary — Unit 1: Backend Dual-Instance Hosting
|
||||
|
||||
## Created
|
||||
|
||||
- `src/SlpModularCms.Core/Hosting/ModuleOrchestrator.cs`
|
||||
- `src/SlpModularCms.Core/Hosting/ServiceCollectionExtensions.cs`
|
||||
- `src/SlpModularCms.Core/Hosting/ApiPrefixConvention.cs`
|
||||
- `src/SlpModularCms.Api.Slave/SlpModularCms.Api.Slave.csproj`
|
||||
- `src/SlpModularCms.Api.Slave/Program.cs`
|
||||
- `src/SlpModularCms.Api.Slave/appsettings.json`
|
||||
- `src/SlpModularCms.Api.Slave/appsettings.Development.json`
|
||||
- `src/SlpModularCms.Api.Slave/appsettings.local.json.example`
|
||||
- `src/SlpModularCms.Api.Slave/Properties/launchSettings.json`
|
||||
- `src/SlpModularCms.Core.Tests/Hosting/ApiPrefixConventionTests.cs` (relocated from `Modules.Identity.Tests`)
|
||||
- `src/SlpModularCms.Core.Tests/Hosting/ModuleOrchestratorTests.cs` (relocated from `Modules.Identity.Tests`)
|
||||
|
||||
## Modified
|
||||
|
||||
- `src/SlpModularCms.Core/SlpModularCms.Core.csproj` — added `Asp.Versioning.Mvc` and `Microsoft.AspNetCore.OpenApi` package references
|
||||
- `src/SlpModularCms.Api/Program.cs` — `using` statements updated to `SlpModularCms.Core.Hosting` (no logic change)
|
||||
- `src/SlpModularCms.Modules.Identity.Tests/SlpModularCms.Modules.Identity.Tests.csproj` — removed `ProjectReference` to `SlpModularCms.Api` (no longer needed; the only tests using it were relocated to `Core.Tests`)
|
||||
- `SlpModularCms.sln` — added `SlpModularCms.Api.Slave` project entry, build configurations, and solution-folder nesting under `src`
|
||||
|
||||
## 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 to `Core.Tests/Hosting/`)
|
||||
- `src/SlpModularCms.Modules.Identity.Tests/Infrastructure/ApiPrefixConventionTests.cs` (relocated to `Core.Tests/Hosting/`)
|
||||
|
||||
## Notes / Deviations from Plan
|
||||
|
||||
- Discovered during generation that `SlpModularCms.Modules.Identity.Tests` referenced `SlpModularCms.Api` solely to test `ModuleOrchestrator`/`ApiPrefixConvention` — an existing layering quirk, not something this feature introduced. Since those classes now live in `Core`, their tests were relocated to `Core.Tests/Hosting/` (which already references `Core` and already has all needed test packages: FluentAssertions, NSubstitute, xunit). This removed the odd cross-project test dependency as a side effect.
|
||||
- `ServiceCollectionExtensions.cs` needed explicit `using Microsoft.Extensions.Configuration;`, `using Microsoft.Extensions.DependencyInjection;`, `using Microsoft.AspNetCore.Builder;`, and `using Microsoft.AspNetCore.Http;` after the move — `SlpModularCms.Api` is a `Microsoft.NET.Sdk.Web` project (implicit ASP.NET Core usings), while `SlpModularCms.Core` is a plain `Microsoft.NET.Sdk` project, so these weren't implicitly available.
|
||||
- Left `Asp.Versioning.Mvc` and `Microsoft.AspNetCore.OpenApi` package references in place on `SlpModularCms.Api.csproj` even though they're now also referenced transitively via `Core` — 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 https` in both `SlpModularCms.Api` and `SlpModularCms.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.**
|
||||
- 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.
|
||||
Reference in New Issue
Block a user