Dependencies
Internal Dependencies
Text alternative: Both host projects reference Core and their modules; every module references only Core; each test project targets its own production project; the admin SPA calls the API at runtime and is itself built by the API project at publish time — a bidirectional coupling between backend and frontend.
Dependency Details
SlpModularCms.Api → SlpModularCms.Core
- Type: Compile
- Reason:
AddCoreInfrastructure, AddCmsCors, AddCmsRateLimiting, ModuleOrchestrator, ApiPrefixConvention.
SlpModularCms.Api → Modules.Identity, Modules.Availability, Modules.Master
- Type: Compile (present to force the module DLLs into the output directory)
- Reason:
ModuleOrchestrator discovers modules by globbing SlpModularCms.Modules.*.dll in the app base directory, so a project reference is how a module ends up deployed. The code itself does not call into the modules directly. Consequence for deployment: which modules an instance has is determined by which DLLs the published output contains.
SlpModularCms.Api.Slave → Core, Modules.Identity, Modules.Availability
- Type: Compile
- Reason: Same as above, minus the Master module — the omission is the entire point of this host.
Modules.Identity → Core
- Type: Compile
- Reason: Identity entities,
IAuthService, IInvitationService, ISetupService, request/response models, authorization policies.
Modules.Availability → Core
- Type: Compile
- Reason:
IAvailabilityService, AvailabilityStatus, AvailabilityOptions, MasterControlledAvailabilityException, IModule.
Modules.Master → Core
- Type: Compile
- Reason:
IModule, authorization policies, shared exception types.
Test projects → their production project (and transitively Core)
- Type: Test
- Reason: Each suite mirrors one production project, per the solution-folder rules in
CLAUDE.md.
frontend → SlpModularCms.Api
- Type: Runtime (HTTP/REST)
- Reason: All data comes from
/api/v1/** at VITE_API_BASE_URL, with credentials so the refresh cookie travels.
SlpModularCms.Api → frontend (build-time, reverse direction)
- Type: Build
- Reason: The
BuildAndCopyAdminFrontend MSBuild target runs pnpm install --frozen-lockfile and pnpm build in frontend/ before publish and copies dist/** into wwwroot/admin/. This makes Node and pnpm hard prerequisites of dotnet publish on any build agent.
Cross-instance runtime dependencies
Not project references, but real coupling between deployed instances:
- A Master instance calls each registered slave's
POST /api/v1/master/register and POST /api/v1/master/status, authenticated with X-Master-Api-Key, through a resilience pipeline (2 retries, exponential backoff with jitter, configurable timeout).
- Each slave calls its Master's
GET /api/v1/SlaveStatus on a timer (MasterPolling:PollIntervalSeconds), and fails open to Available after MasterPolling:FailOpenAfterMinutes of unreachability.
- Both directions require the two instances to be reachable over HTTP from one another, which is a deployment/network consideration rather than a code one.
External Dependencies
Backend — SlpModularCms.Core
| Package |
Version |
Purpose |
License |
Microsoft.EntityFrameworkCore.SqlServer |
10.0.9 |
SQL Server persistence |
MIT |
Microsoft.AspNetCore.Identity.EntityFrameworkCore |
10.0.9 |
Users, roles, password hashing |
MIT |
Microsoft.AspNetCore.Authentication.JwtBearer |
10.0.9 |
Bearer token validation |
MIT |
Microsoft.AspNetCore.OpenApi |
10.0.9 |
OpenAPI document generation |
MIT |
Asp.Versioning.Mvc |
10.0.0 |
API version reporting |
MIT |
Microsoft.Extensions.DependencyInjection.Abstractions |
10.0.9 |
DI abstractions |
MIT |
Microsoft.Extensions.Hosting.Abstractions |
10.0.9 |
Hosting abstractions |
MIT |
Microsoft.Extensions.Logging.Abstractions |
10.0.9 |
Logging abstractions |
MIT |
FrameworkReference: Microsoft.AspNetCore.App |
net10.0 |
Lets a class library use ASP.NET Core types, incl. Data Protection |
MIT |
Backend — SlpModularCms.Api
| Package |
Version |
Purpose |
License |
Asp.Versioning.Mvc |
10.0.0 |
API versioning |
MIT |
Microsoft.AspNetCore.Authentication.JwtBearer |
10.0.9 |
Bearer auth |
MIT |
Microsoft.AspNetCore.OpenApi |
10.0.9 |
OpenAPI |
MIT |
Microsoft.EntityFrameworkCore.Design |
10.0.9 (PrivateAssets) |
dotnet ef tooling |
MIT |
Scalar.AspNetCore |
2.16.3 |
/scalar API reference, Development only |
MIT |
SlpModularCms.Api.Slave carries Microsoft.EntityFrameworkCore.Design and Scalar.AspNetCore at the same versions.
Backend — modules
| Project |
Package |
Version |
Purpose |
License |
Modules.Master |
Microsoft.Extensions.Http.Resilience |
9.6.0 |
Retry/timeout for master→slave calls (pulls in Polly) |
MIT |
Modules.Availability |
— |
— |
No external packages beyond Core's transitives |
— |
Modules.Identity |
— |
— |
No external packages beyond Core's transitives |
— |
Version note: Microsoft.Extensions.Http.Resilience 9.6.0 is a 9.x package on net10.0 targets. It works, but it is the one dependency out of step with the otherwise uniform 10.0.x line — worth pinning deliberately rather than by accident in any CI setup.
Backend — test projects (all four, identical set)
| Package |
Version |
Purpose |
License |
Microsoft.NET.Test.Sdk |
17.14.1 |
Test host |
MIT |
xunit |
2.9.3 |
Test framework |
Apache-2.0 |
xunit.runner.visualstudio |
3.1.4 |
Test adapter |
Apache-2.0 |
FluentAssertions |
8.10.0 |
Assertions |
Dual: free for non-commercial / paid commercial from v8 — worth verifying against how this project is used |
NSubstitute |
5.3.0 |
Mocking |
BSD-3-Clause |
AutoFixture |
4.18.1 |
Test data generation |
MIT |
Microsoft.EntityFrameworkCore.InMemory |
10.0.9 |
In-memory provider for tests |
MIT |
coverlet.collector |
6.0.4 |
Coverage collection |
MIT |
Frontend — runtime (frontend/package.json dependencies)
| Package |
Version |
Purpose |
License |
react, react-dom |
^19.2.6 |
UI framework |
MIT |
@tanstack/react-router |
^1.170.16 |
Routing (honours BASE_URL, so /admin works) |
MIT |
@tanstack/react-query |
^5.101.0 |
Server state |
MIT |
@radix-ui/react-{dialog,dropdown-menu,label,select,slot} |
1.x–2.x |
Accessible primitives |
MIT |
react-hook-form |
^7.79.0 |
Forms |
MIT |
@hookform/resolvers |
^5.4.0 |
Validation bridge |
MIT |
zod |
^4.4.3 |
Schema validation (also validates app config) |
MIT |
i18next, react-i18next, i18next-browser-languagedetector |
26 / 17 / 8 |
NL/EN localisation |
MIT |
lucide-react |
^1.21.0 |
Icons |
ISC |
sonner |
^2.0.7 |
Toasts |
MIT |
class-variance-authority, clsx, tailwind-merge |
0.7 / 2.1 / 3.6 |
Class composition |
MIT |
Frontend — build and test (devDependencies)
| Package |
Version |
Purpose |
License |
vite |
^8.0.12 |
Build tool / dev server |
MIT |
@vitejs/plugin-react |
^6.0.1 |
React support |
MIT |
typescript |
~6.0.2 |
Type checking (tsc -b gates the build) |
Apache-2.0 |
tailwindcss, @tailwindcss/vite |
^4.3.1 |
Styling |
MIT |
vitest, @vitest/coverage-v8 |
^4.1.9 |
Tests and coverage |
MIT |
jsdom |
^29.1.1 |
DOM for tests |
MIT |
@testing-library/{react,jest-dom,user-event} |
16.3 / 6.9 / 14.6 |
Component testing |
MIT |
msw |
^2.14.6 |
Request mocking |
MIT |
eslint, typescript-eslint, eslint-plugin-react-hooks, eslint-plugin-react-refresh, @eslint/js, globals |
10 / 8.59 / 7.1 / 0.5 / 10 / 17.6 |
Linting |
MIT |
prettier |
^3.8.4 |
Formatting |
MIT |
concurrently |
^9.1.2 |
Runs dev:all (master + slave dev servers) |
MIT |
@types/{node,react,react-dom} |
24 / 19.2 / 19.2 |
Type definitions |
MIT |
Lockfiles and reproducibility
frontend/pnpm-lock.yaml exists, and the publish target uses --frozen-lockfile, so frontend installs are reproducible.
- There is no
packages.lock.json for any .NET project — NuGet restore is not locked, so dotnet restore can resolve differently over time on floating transitive versions. Relevant if reproducible CI builds matter.
Dependencies that are absent but expected by this feature
No package currently provides uptime, analytics, error tracking or structured logging. Adding Sentry (a Sentry.AspNetCore package on the backend and @sentry/react on the frontend) and Umami (a script tag, no package) would be new dependencies; UptimeRobot is external and needs only an HTTP endpoint to probe.