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:
+31
@@ -0,0 +1,31 @@
|
||||
# Application Design — Local Dev Master/Slave Setup
|
||||
|
||||
Consolidated design summary. See individual files for full detail: `components.md`, `component-methods.md`, `services.md`, `component-dependency.md`.
|
||||
|
||||
## Key Decision
|
||||
|
||||
The only real design decision in this feature (no new business logic exists) is **how to share host bootstrap code between the master and slave processes without duplication (NFR-1)**. Resolved as: move `ModuleOrchestrator`, `ServiceCollectionExtensions`, and `ApiPrefixConvention` out of `SlpModularCms.Api` and into the existing `SlpModularCms.Core` project (new `SlpModularCms.Core.Hosting` namespace). Both host projects already reference `Core`, so this achieves a single shared copy with no new project and no file-linking, at the cost of two new package references on `Core` (`Asp.Versioning.Mvc`, `Microsoft.AspNetCore.OpenApi`) that it doesn't currently have.
|
||||
|
||||
## Components (see components.md)
|
||||
1. `SlpModularCms.Core.Hosting` — relocated shared bootstrap code
|
||||
2. `SlpModularCms.Api` — existing master host, now sources bootstrap from `Core.Hosting`
|
||||
3. `SlpModularCms.Api.Slave` — new slave-only host, no `Modules.Master` reference
|
||||
|
||||
## Component Methods (see component-methods.md)
|
||||
All method signatures are unchanged from today's implementation — only their namespace/location moves. Module exclusion for the slave is achieved entirely through the absence of a `ProjectReference`, not new conditional code.
|
||||
|
||||
## Services (see services.md)
|
||||
No new domain services. Existing master-side (`CmsInstanceService`, `SlaveApiClient`) and slave-side (`MasterAvailabilityService`, `MasterApiKeyProtector`) services are reused unchanged. A sequence diagram documents the intended local verification flow (start both, use the existing Add CMS Instance dialog, confirm connected status).
|
||||
|
||||
## Component Dependencies (see component-dependency.md)
|
||||
Dependency matrix and data-flow diagram showing both host projects depending on `Core` (+ `Modules.Availability`/`Modules.Identity`), with only `SlpModularCms.Api` additionally depending on `Modules.Master`. Each host uses its own local database; the frontend can target either host via `VITE_API_BASE_URL`.
|
||||
|
||||
## Traceability to Requirements
|
||||
|
||||
| Requirement | Design Element |
|
||||
|---|---|
|
||||
| FR-1 (slave-only host project) | `SlpModularCms.Api.Slave` component |
|
||||
| NFR-1 (no duplication) | `Core.Hosting` relocation |
|
||||
| FR-2 (distinct run config) | component-dependency.md ports/DB mapping |
|
||||
| FR-3 (frontend against either instance) | component-dependency.md data-flow diagram |
|
||||
| NFR-2 (DB isolation) | Separate `SlpModularCmsLocal_Master`/`SlpModularCmsLocal_Slave` in data-flow diagram |
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
# Component Dependencies — Local Dev Master/Slave Setup
|
||||
|
||||
## Dependency Matrix
|
||||
|
||||
| Component | Depends On | Depended On By |
|
||||
|---|---|---|
|
||||
| `SlpModularCms.Core` (incl. new `Core.Hosting`) | — | `SlpModularCms.Api`, `SlpModularCms.Api.Slave`, `Modules.Master`, `Modules.Availability`, `Modules.Identity` |
|
||||
| `SlpModularCms.Modules.Master` | `Core` | `SlpModularCms.Api` only |
|
||||
| `SlpModularCms.Modules.Availability` | `Core` | `SlpModularCms.Api`, `SlpModularCms.Api.Slave` |
|
||||
| `SlpModularCms.Modules.Identity` | `Core` | `SlpModularCms.Api`, `SlpModularCms.Api.Slave` |
|
||||
| `SlpModularCms.Api` (master host) | `Core`, `Modules.Master`, `Modules.Availability`, `Modules.Identity` | — (top-level executable) |
|
||||
| `SlpModularCms.Api.Slave` (new, slave host) | `Core`, `Modules.Availability`, `Modules.Identity` | — (top-level executable) |
|
||||
| `frontend` | Backend HTTP API (either instance, via `VITE_API_BASE_URL`) | — |
|
||||
|
||||
## Communication Patterns
|
||||
|
||||
- **Build-time**: Standard MSBuild `ProjectReference` — no new communication mechanism. The exclusion of `Modules.Master` from `SlpModularCms.Api.Slave` is achieved purely by omitting that `ProjectReference`, which in turn keeps `Modules.Master.dll` out of the slave's build output, which in turn means `ModuleOrchestrator.DiscoverModules` (running inside the slave process) never finds it.
|
||||
- **Runtime — Master ↔ Slave**: Unchanged existing HTTP-based protocol between `Modules.Master`'s `SlaveApiClient` (master side) and `Modules.Availability`'s `MasterController` (slave side), authenticated via a per-instance API key. This feature does not touch that protocol — it only makes it possible to point one local instance at another.
|
||||
- **Runtime — Frontend ↔ Backend**: Standard HTTPS/CORS, `VITE_API_BASE_URL` selects which backend instance the frontend dev server talks to; `Cors:AllowedOrigins` in the target instance's `appsettings` must include the calling frontend's origin.
|
||||
|
||||
## Data Flow (Local Setup)
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
FE["frontend (Vite dev server)"]
|
||||
ApiM["SlpModularCms.Api<br/>:5284 / :7221"]
|
||||
ApiS["SlpModularCms.Api.Slave<br/>:5285 / :7222"]
|
||||
DBM["Local DB: SlpModularCmsLocal_Master"]
|
||||
DBS["Local DB: SlpModularCmsLocal_Slave"]
|
||||
|
||||
FE -- "VITE_API_BASE_URL (master mode)" --> ApiM
|
||||
FE -- "VITE_API_BASE_URL (slave mode)" --> ApiS
|
||||
ApiM -- "master/slave protocol (API key)" --> ApiS
|
||||
ApiM --> DBM
|
||||
ApiS --> DBS
|
||||
|
||||
classDef fe fill:#f6e05e,stroke:#c05621,stroke-width:1px,color:#000;
|
||||
classDef api fill:#63b3ed,stroke:#2b6cb0,stroke-width:1px,color:#000;
|
||||
classDef db fill:#9ae6b4,stroke:#2f855a,stroke-width:1px,color:#000;
|
||||
class FE fe;
|
||||
class ApiM,ApiS api;
|
||||
class DBM,DBS db;
|
||||
```
|
||||
|
||||
Text alternative: The frontend dev server can point at either the master (5284/7221) or slave (5285/7222) backend depending on which env mode is active. The master backend talks to the slave over the existing master/slave protocol. Each backend uses its own local database, keeping master and slave data isolated.
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
# Component Methods — Local Dev Master/Slave Setup
|
||||
|
||||
All method signatures below are **unchanged from the existing implementation** — this feature only relocates the containing classes to `SlpModularCms.Core.Hosting` (namespace change only, per Application Design Q1/Q2 resolution). No business-rule changes.
|
||||
|
||||
## `SlpModularCms.Core.Hosting.ModuleOrchestrator`
|
||||
|
||||
| Method | Signature | Purpose |
|
||||
|---|---|---|
|
||||
| Constructor | `ModuleOrchestrator(ILogger<ModuleOrchestrator> logger)` | Create orchestrator instance |
|
||||
| `DiscoverModules` | `void DiscoverModules()` | Scan the host's own build output directory for `SlpModularCms.Modules.*.dll`, load them, and instantiate every `IModule` implementation found |
|
||||
| `RegisterModuleServices` | `void RegisterModuleServices(IServiceCollection services)` | Call `RegisterServices` on each discovered module |
|
||||
| `UseModules` | `void UseModules(IApplicationBuilder app)` | Call `UseModule` on each discovered module to wire up its middleware/pipeline |
|
||||
|
||||
**Slave-relevant note**: Because `DiscoverModules` scans the calling assembly's own output directory, and `SlpModularCms.Api.Slave.csproj` has no reference to `Modules.Master`, that DLL will simply not be present for `DiscoverModules` to find — no code change needed here to achieve module exclusion.
|
||||
|
||||
## `SlpModularCms.Core.Hosting.ServiceCollectionExtensions` (static)
|
||||
|
||||
| Method | Signature | Purpose |
|
||||
|---|---|---|
|
||||
| `AddCoreInfrastructure` | `IServiceCollection AddCoreInfrastructure(this IServiceCollection services, IConfiguration configuration)` | Registers DB context, Identity, JWT auth, authorization policies, exception handling, API versioning, OpenAPI |
|
||||
| `AddCmsCors` | `IServiceCollection AddCmsCors(this IServiceCollection services, IConfiguration configuration)` | Registers CORS policy from `Cors:AllowedOrigins` config |
|
||||
| `AddCmsRateLimiting` | `IServiceCollection AddCmsRateLimiting(this IServiceCollection services, IConfiguration configuration)` | Registers login/refresh rate limiters from `RateLimiting:*` config |
|
||||
|
||||
**Slave-relevant note**: `AddCmsCors` reads `Cors:AllowedOrigins` from whichever `appsettings` the calling host loads — the slave's own `appsettings.local.json` will list the frontend origin(s) that should be allowed to call it (see FR-3/component-dependency.md).
|
||||
|
||||
## `SlpModularCms.Core.Hosting.ApiPrefixConvention`
|
||||
|
||||
| Method | Signature | Purpose |
|
||||
|---|---|---|
|
||||
| Constructor | `ApiPrefixConvention(string prefix)` | Store the route prefix (`"api/v1"`) to apply |
|
||||
| `Apply` | `void Apply(ApplicationModel application)` | Prepend the prefix to every discovered controller's route template |
|
||||
|
||||
## New/Changed Files Summary
|
||||
|
||||
| File | Change |
|
||||
|---|---|
|
||||
| `SlpModularCms.Core/Hosting/ModuleOrchestrator.cs` | New location (moved from `SlpModularCms.Api/Infrastructure/ModuleOrchestrator.cs`) |
|
||||
| `SlpModularCms.Core/Hosting/ServiceCollectionExtensions.cs` | New location (moved from `SlpModularCms.Api/Extensions/ServiceCollectionExtensions.cs`) |
|
||||
| `SlpModularCms.Core/Hosting/ApiPrefixConvention.cs` | New location (moved from `SlpModularCms.Api/Infrastructure/ApiPrefixConvention.cs`) |
|
||||
| `SlpModularCms.Api/Program.cs` | Updated `using` statements to `SlpModularCms.Core.Hosting`; no logic change |
|
||||
| `SlpModularCms.Api.Slave/Program.cs` | New file, same structure as `SlpModularCms.Api/Program.cs` |
|
||||
| `SlpModularCms.Core.csproj` | Add `Asp.Versioning.Mvc` and `Microsoft.AspNetCore.OpenApi` package references |
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
# Components — Local Dev Master/Slave Setup
|
||||
|
||||
## 1. `SlpModularCms.Core.Hosting` (new namespace within existing `SlpModularCms.Core` project)
|
||||
|
||||
**Purpose**: Single, shared home for the ASP.NET Core host bootstrap/orchestration code that both the master and slave API hosts use identically.
|
||||
|
||||
**Responsibilities**:
|
||||
- Discover and instantiate `IModule` implementations from the host's own build output directory (unchanged behavior).
|
||||
- Register core cross-cutting services (DB context, Identity, JWT auth, authorization policies, exception handling, API versioning, OpenAPI, CORS, rate limiting) shared by every instance regardless of which optional modules (e.g. `Modules.Master`) are present.
|
||||
- Apply the `api/v1` route prefix convention to all discovered controllers.
|
||||
|
||||
**Interfaces**: Unchanged public API — `ModuleOrchestrator` (class), `AddCoreInfrastructure`/`AddCmsCors`/`AddCmsRateLimiting` (extension methods on `IServiceCollection`), `ApiPrefixConvention` (implements `IApplicationModelConvention`). Only the namespace moves (`SlpModularCms.Api.Extensions`/`SlpModularCms.Api.Infrastructure` → `SlpModularCms.Core.Hosting`).
|
||||
|
||||
**Not responsible for**: Any module-specific business logic — modules remain fully self-contained (`Modules.Master`, `Modules.Availability`, `Modules.Identity`).
|
||||
|
||||
## 2. `SlpModularCms.Api` (existing project, master host)
|
||||
|
||||
**Purpose**: The main CMS instance — full stack, including the Master module, used for day-to-day development and as the "master" side of a local master/slave test.
|
||||
|
||||
**Responsibilities**: Unchanged from today. `Program.cs` now sources `ModuleOrchestrator`/`ServiceCollectionExtensions`/`ApiPrefixConvention` from `SlpModularCms.Core.Hosting` instead of its own local files.
|
||||
|
||||
**Interfaces**: No change — same controllers, same routes, same behavior. Its own copies of `ModuleOrchestrator.cs`, `Extensions/ServiceCollectionExtensions.cs`, `Infrastructure/ApiPrefixConvention.cs` are deleted (moved to Core).
|
||||
|
||||
**Project references**: `Core` (now including the hosting code), `Modules.Availability`, `Modules.Identity`, `Modules.Master` — unchanged set, just implicitly picks up `Core.Hosting` via the existing `Core` reference.
|
||||
|
||||
## 3. `SlpModularCms.Api.Slave` (new project)
|
||||
|
||||
**Purpose**: A minimal, Master-less host used purely as a local target for testing the master↔slave connection. Not intended for end-user CMS administration beyond what's needed to validate connectivity.
|
||||
|
||||
**Responsibilities**: Bootstraps identically to `SlpModularCms.Api` (via `Core.Hosting`), but its build output never contains `SlpModularCms.Modules.Master.dll`, so `ModuleOrchestrator.DiscoverModules` never loads the Master module for this instance.
|
||||
|
||||
**Interfaces**: Same shape as `SlpModularCms.Api` (`Program.cs` calling into `Core.Hosting`), minus anything Master-specific (there is none in `Program.cs` today — the exclusion works purely through the project-reference/build-output mechanism).
|
||||
|
||||
**Project references**: `Core`, `Modules.Availability`, `Modules.Identity`. Deliberately **no** reference to `Modules.Master`.
|
||||
|
||||
**Configuration**: Own `appsettings.json` / `appsettings.Development.json` / `appsettings.local.json` (gitignored) and own `launchSettings.json` (ports 5285 HTTP / 7222 HTTPS), per FR-2 in requirements.md.
|
||||
|
||||
## Component Diagram
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Core["SlpModularCms.Core<br/>(incl. new Core.Hosting)"]
|
||||
Master["SlpModularCms.Modules.Master"]
|
||||
Avail["SlpModularCms.Modules.Availability"]
|
||||
Ident["SlpModularCms.Modules.Identity"]
|
||||
ApiMaster["SlpModularCms.Api<br/>(master host)"]
|
||||
ApiSlave["SlpModularCms.Api.Slave<br/>(slave host, new)"]
|
||||
|
||||
ApiMaster --> Core
|
||||
ApiMaster --> Master
|
||||
ApiMaster --> Avail
|
||||
ApiMaster --> Ident
|
||||
ApiSlave --> Core
|
||||
ApiSlave --> Avail
|
||||
ApiSlave --> Ident
|
||||
Master --> Core
|
||||
Avail --> Core
|
||||
Ident --> Core
|
||||
|
||||
classDef core fill:#63b3ed,stroke:#2b6cb0,stroke-width:1px,color:#000;
|
||||
classDef module fill:#9ae6b4,stroke:#2f855a,stroke-width:1px,color:#000;
|
||||
classDef host fill:#f6e05e,stroke:#c05621,stroke-width:1px,color:#000;
|
||||
class Core core;
|
||||
class Master,Avail,Ident module;
|
||||
class ApiMaster,ApiSlave host;
|
||||
```
|
||||
|
||||
Text alternative: Two host projects (`SlpModularCms.Api` and the new `SlpModularCms.Api.Slave`) both depend on `Core` (which now includes the shared hosting/bootstrap code) and on `Modules.Availability`/`Modules.Identity`. Only `SlpModularCms.Api` additionally depends on `Modules.Master` — `SlpModularCms.Api.Slave` deliberately omits that reference. All three module projects depend on `Core`.
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
# Services — Local Dev Master/Slave Setup
|
||||
|
||||
## No new domain services
|
||||
|
||||
This feature introduces no new business/domain service. All existing services are reused unchanged:
|
||||
|
||||
- **Master-side** (only present in `SlpModularCms.Api`, because only it references `Modules.Master`): `CmsInstanceService`, `SlaveApiClient`, `ApiKeyProtector` — manage registered CMS instances and communicate with them.
|
||||
- **Slave-side** (present in both `SlpModularCms.Api` and `SlpModularCms.Api.Slave`, since both reference `Modules.Availability`): `MasterAvailabilityService`, `MasterApiKeyProtector` — accept and validate a master's per-instance API key.
|
||||
- **Shared cross-cutting**: `IAuthService`, `IInvitationService`, `ISetupService` (from `Core.Identity` via `AddCoreInfrastructure`) — identical in both hosts.
|
||||
|
||||
## Orchestration Service
|
||||
|
||||
`ModuleOrchestrator` (relocated to `SlpModularCms.Core.Hosting`, see components.md) is the only "orchestration" element in this feature, and its role is unchanged: at startup, discover whichever module DLLs are present next to the host executable and wire them into DI + the request pipeline. Its behavior naturally differs between the two hosts only because of what's present in each host's build output — not because of any new conditional logic.
|
||||
|
||||
## Interaction Sequence — Local Master/Slave Connection Test
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box rgba(246,224,94,0.4) Developer
|
||||
participant Dev as Developer
|
||||
end
|
||||
box rgba(99,179,237,0.4) Master Instance (5284/7221)
|
||||
participant MasterApi as SlpModularCms.Api
|
||||
participant CmsInstanceSvc as CmsInstanceService
|
||||
end
|
||||
box rgba(154,230,180,0.4) Slave Instance (5285/7222)
|
||||
participant SlaveApi as SlpModularCms.Api.Slave
|
||||
participant MasterCtrl as MasterController
|
||||
end
|
||||
|
||||
Dev->>MasterApi: dotnet run --launch-profile master
|
||||
Dev->>SlaveApi: dotnet run --launch-profile slave
|
||||
Dev->>MasterApi: Open frontend, use Add CMS Instance dialog with slave URL
|
||||
MasterApi->>CmsInstanceSvc: Register CMS instance (slave URL + generated API key)
|
||||
CmsInstanceSvc->>MasterCtrl: Push registration / poll status using API key
|
||||
MasterCtrl-->>CmsInstanceSvc: Accepted, status healthy
|
||||
CmsInstanceSvc-->>MasterApi: Instance connected
|
||||
MasterApi-->>Dev: CMS Instance shows as Connected
|
||||
```
|
||||
|
||||
Text alternative: The developer starts the master and slave backends on their respective ports, then uses the master frontend's existing Add CMS Instance dialog. The master's CmsInstanceService registers and communicates with the slave's MasterController using a per-instance API key, and the frontend reflects the resulting connected status.
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
# Unit of Work Dependency Matrix — Local Dev Master/Slave Setup
|
||||
|
||||
| Unit | Depends On | Blocks |
|
||||
|---|---|---|
|
||||
| Unit 1 — Backend dual-instance hosting | Application Design (approved) | Unit 2 |
|
||||
| Unit 2 — Frontend dual-instance tooling & runbook | Unit 1 (needs a working, running slave backend) | Build and Test (final manual verification) |
|
||||
|
||||
## Rationale
|
||||
|
||||
- Unit 1 is the critical path: without `SlpModularCms.Api.Slave` actually building and running on its own ports/database, there is nothing for Unit 2's frontend config or runbook to point at or verify against.
|
||||
- Unit 2 has no reverse dependency — it does not require any change to Unit 1 once Unit 1 is complete.
|
||||
- No parallelization opportunity given the small scope and single-developer nature of this feature (per Q2 = A, sequential execution was explicitly confirmed).
|
||||
|
||||
## Update Strategy
|
||||
|
||||
- **Update Approach**: Sequential (Unit 1 then Unit 2)
|
||||
- **Critical Path**: Unit 1
|
||||
- **Coordination Points**: The slave backend's HTTPS URL (`https://localhost:7222`) is the one piece of information Unit 2 needs from Unit 1's output.
|
||||
- **Testing Checkpoints**: After Unit 1 — verify both backends build/start independently. After Unit 2 — verify the full manual master/slave connection flow via the runbook.
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
# Unit of Work — Requirement Map — Local Dev Master/Slave Setup
|
||||
|
||||
No user stories exist for this feature (User Stories stage was skipped — pure developer tooling, no user-facing functionality). Functional and non-functional requirements from `requirements.md` are mapped directly to units instead.
|
||||
|
||||
| Requirement | Unit |
|
||||
|---|---|
|
||||
| FR-1: Slave-only backend host project | Unit 1 |
|
||||
| FR-2: Distinct local run configuration per instance | Unit 1 |
|
||||
| FR-3: Frontend configurable against either instance | Unit 2 |
|
||||
| FR-4: Documentation for the local master/slave workflow | Unit 2 |
|
||||
| NFR-1: No logic duplication between host projects | Unit 1 |
|
||||
| NFR-2: Isolation (separate databases) | Unit 1 |
|
||||
| NFR-3: Local-only scope | Unit 1 + Unit 2 (both — neither touches production/CI) |
|
||||
| NFR-4: Secrets hygiene | Unit 1 (backend appsettings.local.json) + Unit 2 (frontend .env.slave.local) |
|
||||
|
||||
All requirements are covered by exactly one or both units — no orphaned requirements.
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
# Unit of Work — Local Dev Master/Slave Setup
|
||||
|
||||
## Unit 1 — Backend Dual-Instance Hosting
|
||||
|
||||
**Responsibility**: Make it possible to run a Master-less slave backend locally alongside the existing master backend, on separate ports and databases, without duplicating bootstrap code.
|
||||
|
||||
**Scope**:
|
||||
- Relocate `ModuleOrchestrator`, `ServiceCollectionExtensions`, `ApiPrefixConvention` from `SlpModularCms.Api` into `SlpModularCms.Core` (new `SlpModularCms.Core.Hosting` namespace); add `Asp.Versioning.Mvc` and `Microsoft.AspNetCore.OpenApi` package references to `Core`.
|
||||
- Update `SlpModularCms.Api/Program.cs` to use the relocated classes (no behavior change); delete the old files from `SlpModularCms.Api`.
|
||||
- Add new `SlpModularCms.Api.Slave` project: references `Core`, `Modules.Availability`, `Modules.Identity` (no `Modules.Master`); own `Program.cs` mirroring `SlpModularCms.Api`'s bootstrap.
|
||||
- Add `SlpModularCms.Api.Slave`'s `appsettings.json` / `appsettings.Development.json` / `appsettings.local.json` (gitignored) with its own `ConnectionStrings:DefaultConnection` (separate database) and `Cors:AllowedOrigins`.
|
||||
- Add `SlpModularCms.Api.Slave/Properties/launchSettings.json` with profiles on port 5285 (HTTP) / 7222 (HTTPS).
|
||||
- Add `SlpModularCms.Api.Slave.csproj` to the solution file.
|
||||
- No dedicated test project (Q3 = A) — mirrors `SlpModularCms.Api`'s current pattern.
|
||||
|
||||
**Depends On**: Application Design decisions (already approved).
|
||||
|
||||
**Completion Criteria**: Both `SlpModularCms.Api` (master) and `SlpModularCms.Api.Slave` build and start successfully via `dotnet run --launch-profile <name>`; existing test suites (`Modules.Master.Tests`, `Modules.Availability.Tests`, `Modules.Identity.Tests`, `Core.Tests`) still pass unchanged; the slave instance's Scalar/OpenAPI page loads and shows no Master-related endpoints.
|
||||
|
||||
## Unit 2 — Frontend Dual-Instance Tooling & Runbook
|
||||
|
||||
**Responsibility**: Let the existing frontend point at either the master or slave backend, and document the manual workflow for connecting them.
|
||||
|
||||
**Scope**:
|
||||
- Add `.env.slave.local` (gitignored, mirrors `.env.local`) with `VITE_API_BASE_URL=https://localhost:7222`.
|
||||
- Update `.env.example` to document both `.env.local` (master) and `.env.slave.local` (slave) modes.
|
||||
- Add an npm script `dev:slave` (e.g. `vite --mode slave --port 5174`) to `frontend/package.json`; introduce a `.env.slave` (non-local, checked-in) mode file if needed for Vite's mode-based env loading, or rely on `--mode slave` reading `.env.slave.local`.
|
||||
- Add a runbook section (in `frontend/README.md` and/or a new `docs/local-master-slave-setup.md` referenced from the root README) with step-by-step instructions: start master backend, start slave backend, start master frontend, (optionally) start slave frontend, use the existing "Add CMS Instance" dialog to register the local slave, confirm connected status.
|
||||
|
||||
**Depends On**: Unit 1 must be complete and verified working (Q2 = A) — the runbook's steps assume a working slave backend to point at and to actually exercise end-to-end.
|
||||
|
||||
**Completion Criteria**: Frontend can be started against either instance via the documented commands; the runbook has been manually followed once to confirm the "Add CMS Instance" flow successfully connects the local master to the local slave.
|
||||
|
||||
## Sequencing
|
||||
|
||||
Unit 1 → Unit 2 (strictly sequential; Unit 2's runbook and manual verification require Unit 1's working slave backend).
|
||||
Reference in New Issue
Block a user