9.5 KiB
Post-Generation Validation
After generating the backend or fullstack application, run these checks to ensure the project will start cleanly and that the default auth model has been generated correctly.
Validation Checklist
1. Frontend and backend env files
server/.env.exampleexists and documents:PORTDATABASE_URLCORS_ALLOWED_ORIGINSKEYCLOAK_ISSUER_URLKEYCLOAK_AUDIENCE- optional
KEYCLOAK_JWKS_URL
client/.env.exampleexists and documents:VITE_API_URLVITE_KEYCLOAK_URLVITE_KEYCLOAK_REALMVITE_KEYCLOAK_CLIENT_ID
- Runtime code fails fast when required auth or database env vars are missing.
- Runtime code does not silently fall back to production auth settings.
Failure symptoms: startup succeeds with undefined auth config, or fails later with opaque auth/runtime errors.
2. Keycloak realm artifact
- A root-level generated Keycloak realm import artifact exists.
- If the repository default filename
toir-realm.jsonis not used, the project-specific equivalent is documented consistently across bootstrap and workflow docs. - The generated realm artifact is self-contained and reproducible.
- The generated realm artifact parameterizes realm name, frontend client ID, backend audience/client ID, production URLs, and artifact filename consistently with the generated project auth config.
- It defines realm roles:
admineditorviewer
- It defines a frontend SPA client consistent with the generated frontend Keycloak client ID.
- It defines a backend audience/resource client consistent with the generated backend audience/client ID.
- It defines explicit audience delivery, such as an
api-audienceclient scope. - It does not rely on undeclared built-in client scopes being present after import.
- It explicitly addresses delivery of:
subaudrealm_access.roles
Failure symptoms: access tokens are missing required claims, or realm import succeeds but generated apps still cannot authenticate/authorize reliably.
3. Frontend auth files and behavior
- Generated frontend includes:
client/src/config/env.tsclient/src/auth/keycloak.tsclient/src/auth/authProvider.tsclient/src/main.tsxclient/src/App.tsxclient/src/dataProvider.ts
keycloak-jsis installed.- Keycloak is initialized before the SPA renders.
- Login is redirect-based only.
- No custom in-app username/password login form is generated.
Authorization Code + PKCE (S256)is encoded in the frontend auth flow.client/src/dataProvider.tsor the documented shared request seam injectsAuthorization: Bearer <access_token>into all API requests.- Token refresh is concurrency-safe:
- one shared in-flight refresh operation
- no parallel refresh stampede
- Generated auth code does not persist access tokens or refresh tokens in
localStorageorsessionStorage. - React Admin auth semantics distinguish:
401-> force logout / re-authentication403-> do not re-authenticate; surface access denied / permission error
Failure symptoms: app renders before auth is ready, reference calls miss auth headers, refresh storms occur, or 403 incorrectly forces logout.
4. Backend auth files and behavior
- Generated backend includes:
server/src/auth/auth.module.ts- JWT guard
- roles guard
@Public()decorator@Roles()decorator- typed authenticated principal interface
- typed config validation in
server/src/config/
joseis installed.- JWT verification uses issuer + audience + JWKS.
- JWKS resolution follows this exact priority:
KEYCLOAK_JWKS_URL- OIDC discovery
${issuer}/protocol/openid-connect/certs
- Authorization roles are extracted only from
realm_access.roles. - Deprecated Keycloak-specific Node adapters are not used.
Failure symptoms: invalid tokens are accepted, valid tokens are rejected due to bad JWKS resolution, or RBAC depends on unstable/non-standard claims.
5. CRUD protection and RBAC defaults
/healthis public.- Each generated CRUD controller method other than explicit public routes is protected by the generated auth/RBAC infrastructure.
- CRUD RBAC defaults are present:
GET->viewer | editor | adminPOST,PATCH,PUT->editor | adminDELETE->admin
- Unauthenticated request to a protected route returns
401. - Authenticated user with insufficient role receives
403.
Failure symptoms: anonymous CRUD access remains open, or insufficient-role users are not denied properly.
6. PrismaService implementation
- A
PrismaService(or equivalent) class exists and extendsPrismaClient. - It implements
OnModuleInitand callsawait this.$connect()inonModuleInit(). - It does not use
this.$on('beforeExit', ...)or anybeforeExithook.
Failure symptom: deprecation/runtime errors in Prisma 5 when using beforeExit.
Reference: backend/prisma-service.md
7. Prisma client lifecycle
package.jsonincludes a script that runs Prisma client generation:- either
"postinstall": "prisma generate"(ornpx prisma generate) - or clear documentation to run
npx prisma generateafter install
- either
- After schema generation or change,
npx prisma generatehas been run or will run viapostinstall.
Failure symptom: Cannot find module '@prisma/client' or missing generated types.
8. Database migration
- Migration workflow is documented.
- Instruction to run
npx prisma migrate devexists after first generation or schema change. - Generation pipeline includes or documents the migration step.
Failure symptom: tables do not exist; Prisma errors on first query.
9. REST route parameters
- For each entity, path parameters use the correct primary key name from the DSL.
- Entity with PK
iduses/:id. - Entity with non-
idprimary key (for examplecode) uses the actual PK name such as/:code, not/:id.
Failure symptom: controller expects one param name while the route defines another, leading to broken CRUD behavior.
Reference: backend/architecture.md
10. DTO type mapping and React Admin ID compatibility
- DSL
decimalmaps to DTO/APIstring. - DSL
datemaps to DTO/APIstring(ISO) or equivalent string serialization. - Every API response object contains a field named
id. - If the entity primary key is not named
id, the response maps the primary key toid.
Failure symptoms: serialization issues for decimals/dates, or React Admin cannot identify records.
11. Update payload sanitization
- Update endpoints do not pass
idor the primary key in Prismadata. - Generated update methods remove
id, the entity primary key, and readonly attributes before callingprisma.*.update().
Failure symptom: Prisma throws because immutable or invalid fields are passed in update data.
12. Database runtime
docker-compose.ymlexists at the project root.- It defines a PostgreSQL service with image
postgres:16, port5432, and credentials matchingDATABASE_URL. docker compose up -dstarts the database successfully.docker-compose.ymldoes not add Keycloak in this repository.
Failure symptom: Prisma cannot reach the development database or repo topology drifts from the documented external-Keycloak model.
13. Migrations, seed, and health endpoint
npx prisma migrate devruns successfully fromserver/.- Seed script exists at
server/prisma/seed.ts(or equivalent). npx prisma db seedruns without error.- Backend exposes
GET /health. GET /healthreturns HTTP 200 with a status payload.
Failure symptom: development bootstrap cannot complete end-to-end.
Summary Table
| Check | Required artifact / rule |
|---|---|
| Frontend env | client/.env.example with required Vite auth vars |
| Backend env | server/.env.example with DB, CORS, and Keycloak vars |
| Fail-fast config | Startup fails when required auth env is missing |
| Realm artifact | Root generated realm import artifact with self-contained auth setup |
| Frontend auth | keycloak.ts, authProvider.ts, authenticated dataProvider.ts |
| Backend auth | AuthModule, guards, decorators, typed principal |
| JWKS strategy | explicit URL -> discovery -> certs fallback |
| Role source | realm_access.roles only |
| CRUD RBAC | GET viewer/editor/admin; write editor/admin; delete admin |
/health |
Public and returns 200 |
| Protected route unauthenticated | Returns 401 |
| Protected route insufficient role | Returns 403 |
| Token storage | No localStorage / sessionStorage persistence |
| Token refresh | Concurrency-safe single in-flight refresh |
| Prisma lifecycle | OnModuleInit + $connect(), no beforeExit |
| Update sanitization | Strip id / PK / readonly before Prisma update |
React Admin id |
Every record includes id |
| Database runtime | PostgreSQL compose exists and starts |
Integration with generation pipeline
- Backend and frontend generation must produce artifacts that satisfy the above by default.
- Runtime bootstrap must include Keycloak realm import/verification before app startup.
- After generation, run this checklist manually or via an automated script.
- If any check fails, update the generator context so future runs pass without manual repair.