Architecture guide for building an enterprise SaaS app where every client can have a different validation flow, different UI fields and labels, different languages, and different custom fields — without forking the codebase. Database-per-client isolation, single API + single frontend deployment, subdomain per client.
Open index.html in a browser.
| # | Page | Topic |
|---|---|---|
| 00 | index.html | Overview |
| 01 | 01-findings.html | FluentValidation suitability analysis |
| 02 | 02-architecture.html | Pipeline, components, storage, caching |
| 03 | 03-code-sketch.html | End-to-end C# sketch |
| 04 | 04-ui-rule-config.html | Admin-UI rule editor + JSON rule engine |
| 05 | 05-result-pattern.html | Three issue kinds (Advisory / Confirmable / Blocking) |
| 06 | 06-reconciliation.html | Bridge to ErrorOr + ValidationProblemDetails house style |
| 07 | 07-ui-schema.html | Per-client fields, labels, ordering |
| 08 | 08-i18n-l10n.html | i18n / l10n / G11n architecture |
| 09 | 09-extension-fields.html | Client-defined custom fields via jsonb |
| 10 | 10-tenancy-model.html | Database-per-client isolation, request resolution, migrations |
| ADR | Decision |
|---|---|
| ADR-0001 | Hybrid validation: FluentValidation + Strategy + Rule Engine |
| ADR-0002 | Database-per-client tenancy isolation |
| ADR-0003 | Frontend stack (React + MUI + Zod + RHF + RQ + Zustand + Vite) |
| ADR-0004 | Authorization & permission model (replaces GNUMS SEC_) |
| Doc | Purpose |
|---|---|
| Modules Inventory | GNUMS legacy module/proc counts |
| GNUMS Org Hierarchy | Legacy INS_* DAG: spanning trees, bridges, self-refs |
| Hierarchy Comparison | Two GNUMS instances side-by-side — proves hierarchies differ per tenant |
| Exam Module Scope | Recon of legacy exam module |
| Replication Strategy | Playbook + cluster-by-cluster plan |
- ASP.NET Core Web API (latest, .NET 10)
- PostgreSQL 17+ with
ltreeextension; identifiers in PascalCase, double-quoted - EF Core 9 (Npgsql) + Dapper for reads
- ErrorOr + FluentValidation
- Traditional layered / service-oriented; controllers → services via DI
- React (latest, 19+) + TypeScript (latest)
- MUI (latest, v7+)
- Zod (latest) + React Hook Form (latest) — schemas + form state
- React Query / TanStack Query (latest, v5+) — server state
- Zustand (latest) — client state
- i18next +
react-i18next - Vite (latest) — build tool
- DB-per-client tenancy — each client owns its Postgres database; one API + one frontend deployment; subdomain per client; client code from JWT/header resolves connection string per request.
- No CQRS. No MediatR. No Minimal APIs. MVC controllers only.
- PascalCase for all DB identifiers (database, table, column).
Project-specific rules and decisions live in memory/. Read memory/MEMORY.md first when resuming work.
Living document. Pages evolve as the platform takes shape.