(llm-first): context budget, validation, and eval harness, orchestration general-prompt
This commit is contained in:
@@ -1,79 +1,95 @@
|
||||
# Auth Rules
|
||||
|
||||
This repository keeps the current LLM-first CRUD generation architecture as the primary working baseline.
|
||||
<!-- prompt-version: 2.0 -->
|
||||
<!-- applies-to: client/src/auth/, server/src/auth/, toir-realm.json -->
|
||||
<!-- validated-by: tools/validate-generation.mjs §validateAuthChecks §validateRealmChecks -->
|
||||
|
||||
- Auth is part of the default generation path, not a post-generation addon.
|
||||
- `server/` is the active backend target output path.
|
||||
- `client/` is the active frontend target output path.
|
||||
- The generated runtime stays SPA + API + external Keycloak + PostgreSQL only.
|
||||
Use this document during the **Auth / Runtime / Realm** stage defined in `prompts/general-prompt.md`.
|
||||
|
||||
## Frontend auth invariants
|
||||
## Purpose
|
||||
|
||||
- Use `keycloak-js` with redirect-based login only.
|
||||
- Initialize Keycloak before rendering the SPA.
|
||||
- Use Authorization Code Flow + PKCE (`S256`).
|
||||
- Keep `authProvider`, `dataProvider`, `getIdentity()`, `getPermissions()`, and `checkError()` as stable provider seams.
|
||||
- Derive identity from token claims already present in the parsed token.
|
||||
- Do not call `loadUserProfile()` and do not depend on `/account` for the baseline app.
|
||||
- `401` must force re-authentication; `403` must stay an authorization error.
|
||||
- Keep token handling in memory and refresh through one shared in-flight operation.
|
||||
Generate and preserve the auth contracts that let the CRUD app run as a React Admin SPA backed by a NestJS API protected by external Keycloak.
|
||||
|
||||
## Working runtime defaults
|
||||
## Mandatory Inputs
|
||||
|
||||
Use the already working project defaults unless a prompt explicitly overrides them.
|
||||
- `prompts/general-prompt.md`
|
||||
- `prompts/runtime-rules.md`
|
||||
- current repository auth/runtime defaults
|
||||
|
||||
- Frontend Keycloak base URL example:
|
||||
- `VITE_KEYCLOAK_URL=https://sso.greact.ru`
|
||||
- Frontend realm and client example:
|
||||
- `VITE_KEYCLOAK_REALM=toir`
|
||||
- `VITE_KEYCLOAK_CLIENT_ID=toir-frontend`
|
||||
- Backend issuer and audience example:
|
||||
- `KEYCLOAK_ISSUER_URL=https://sso.greact.ru/realms/toir`
|
||||
- `KEYCLOAK_AUDIENCE=toir-backend`
|
||||
- CORS example:
|
||||
- `CORS_ALLOWED_ORIGINS=http://localhost:5173,https://toir-frontend.greact.ru`
|
||||
## Expected Outputs
|
||||
|
||||
Anti-regression rule:
|
||||
- `client/src/auth/`
|
||||
- `client/src/dataProvider.ts`
|
||||
- `server/src/auth/`
|
||||
- `toir-realm.json`
|
||||
|
||||
- Do not switch the baseline Keycloak example back to `http://localhost:8080` in generated `.env.example` files unless the prompt explicitly asks for a local Keycloak runtime.
|
||||
- Localhost Keycloak values may exist in private `.env.local` or `.env` overrides, but they are not the default project examples.
|
||||
## Frontend Auth Invariants
|
||||
|
||||
## Backend auth invariants
|
||||
- use `keycloak-js` with redirect-based login only
|
||||
- initialize Keycloak before rendering the SPA
|
||||
- use Authorization Code Flow + PKCE (`S256`)
|
||||
- keep `authProvider`, `dataProvider`, `getIdentity()`, `getPermissions()`, and `checkError()` as stable seams
|
||||
- derive identity from token claims already present in the token
|
||||
- do not call `loadUserProfile()`
|
||||
- `401` forces re-authentication; `403` remains an authorization error
|
||||
- keep token handling in memory with one shared in-flight refresh path
|
||||
|
||||
- Verify JWTs with `jose`.
|
||||
- Validate issuer + audience + signature via JWKS.
|
||||
- Resolve JWKS in this order:
|
||||
## Backend Auth Invariants
|
||||
|
||||
- verify JWTs with `jose`
|
||||
- validate issuer, audience, and signature via JWKS
|
||||
- resolve JWKS in this order:
|
||||
1. `KEYCLOAK_JWKS_URL`
|
||||
2. OIDC discovery at `/.well-known/openid-configuration`
|
||||
3. `${issuer}/protocol/openid-connect/certs`
|
||||
- Extract roles only from `realm_access.roles`.
|
||||
- Keep `/health` public and all generated CRUD routes protected by default.
|
||||
- extract roles only from `realm_access.roles`
|
||||
- keep `/health` public
|
||||
- generated CRUD routes stay protected by default
|
||||
|
||||
## Auth anti-regression invariants
|
||||
## Working Runtime Defaults
|
||||
|
||||
- The accepted JWKS resolution chain above is the only baseline truth path. Do not document one order and implement another.
|
||||
- If auth implementation changes, `prompts/auth-rules.md` and `prompts/validation-rules.md` must be updated in the same change.
|
||||
- Do not skip OIDC discovery when no explicit `KEYCLOAK_JWKS_URL` is provided.
|
||||
- Do not switch role extraction to alternative claims unless the prompt explicitly changes the baseline contract.
|
||||
- Do not reintroduce localhost Keycloak defaults into shared baseline examples.
|
||||
Keep these defaults unless a task explicitly overrides them:
|
||||
|
||||
## Realm artifact contract
|
||||
- `VITE_KEYCLOAK_URL=https://sso.greact.ru`
|
||||
- `VITE_KEYCLOAK_REALM=toir`
|
||||
- `VITE_KEYCLOAK_CLIENT_ID=toir-frontend`
|
||||
- `KEYCLOAK_ISSUER_URL=https://sso.greact.ru/realms/toir`
|
||||
- `KEYCLOAK_AUDIENCE=toir-backend`
|
||||
- `CORS_ALLOWED_ORIGINS=http://localhost:5173,https://toir-frontend.greact.ru`
|
||||
|
||||
- A physical root-level `*-realm.json` artifact is mandatory output.
|
||||
- The artifact must be importable, versioned, and aligned with generated backend/frontend env contracts.
|
||||
- It must parameterize:
|
||||
Anti-regression rule:
|
||||
|
||||
- do not revert shared examples to localhost Keycloak defaults unless a task explicitly requests a local Keycloak baseline
|
||||
|
||||
## Realm Artifact Contract
|
||||
|
||||
The root realm artifact is mandatory and must:
|
||||
|
||||
- be importable and versioned
|
||||
- align with generated frontend/backend env contracts
|
||||
- parameterize:
|
||||
- realm name
|
||||
- frontend client id
|
||||
- backend client id / audience
|
||||
- local and production frontend URLs
|
||||
- artifact filename
|
||||
- It must explicitly deliver:
|
||||
- explicitly deliver:
|
||||
- `sub`
|
||||
- `aud`
|
||||
- `realm_access.roles`
|
||||
- It must define:
|
||||
- define:
|
||||
- realm roles `admin`, `editor`, `viewer`
|
||||
- a public SPA client with PKCE S256
|
||||
- a bearer-only backend client
|
||||
- an explicit audience client scope
|
||||
- explicit protocol mappers for baseline identity and role claims
|
||||
- protocol mappers for baseline identity and role claims
|
||||
|
||||
## Completion Expectations
|
||||
|
||||
Auth/runtime generation is incomplete if any of the following is true:
|
||||
|
||||
- frontend and backend auth seams drift from each other
|
||||
- JWKS resolution order changes
|
||||
- `/health` stops being public
|
||||
- shared Keycloak defaults regress to localhost examples
|
||||
- the realm artifact no longer matches backend/frontend expectations
|
||||
|
||||
@@ -1,88 +1,147 @@
|
||||
# Backend Rules
|
||||
|
||||
The backend remains derived from `domain/*.dsl` inside the existing LLM-first pipeline. No compiler platform or generator engine is introduced.
|
||||
<!-- prompt-version: 2.0 -->
|
||||
<!-- applies-to: server/src/modules/, server/src/app.module.ts -->
|
||||
<!-- validated-by: tools/validate-generation.mjs §validateApiDslCoverage §validateNaturalKeyChecks -->
|
||||
|
||||
## Backend scaffold baseline
|
||||
Use this document during the **Backend** stage defined in `prompts/general-prompt.md`.
|
||||
|
||||
- Start backend initialization from the official NestJS CLI workspace, not from manually created files.
|
||||
- The backend must remain compatible with standard Nest workspace tooling such as `nest build` and `nest start`.
|
||||
- Preserve the core Nest workspace files generated by the CLI, especially:
|
||||
## Purpose
|
||||
|
||||
Generate NestJS CRUD artifacts that match the DSL contract exactly and remain compatible with a standard NestJS workspace.
|
||||
|
||||
## Mandatory Inputs
|
||||
|
||||
- `prompts/general-prompt.md`
|
||||
- the active `api API.<Entity>` block from `domain/toir.api.dsl`
|
||||
- referenced DTOs and enums from `domain/toir.api.dsl`
|
||||
- an intact or repaired official NestJS scaffold under `server/`
|
||||
|
||||
`api-summary.json` may be consulted only as an auxiliary inventory or validator-related artifact. It must never replace the DSL as the backend source of truth.
|
||||
|
||||
## Expected Outputs
|
||||
|
||||
Per entity:
|
||||
|
||||
- `server/src/modules/<kebab>/<kebab>.module.ts`
|
||||
- `server/src/modules/<kebab>/<kebab>.controller.ts`
|
||||
- `server/src/modules/<kebab>/<kebab>.service.ts`
|
||||
- `server/src/modules/<kebab>/dto/create-<kebab>.dto.ts`
|
||||
- `server/src/modules/<kebab>/dto/update-<kebab>.dto.ts`
|
||||
|
||||
Repository-wide:
|
||||
|
||||
- `server/src/app.module.ts` registrations
|
||||
|
||||
## Scaffold Baseline
|
||||
|
||||
- Start backend initialization and repair from the official NestJS CLI workspace, not from hand-written files.
|
||||
- Preserve Nest workspace essentials:
|
||||
- `server/tsconfig.json`
|
||||
- `server/tsconfig.build.json`
|
||||
- `server/nest-cli.json`
|
||||
- `server/src/main.ts`
|
||||
- `server/src/app.module.ts`
|
||||
- For domain resources, prefer official Nest CLI generation patterns for modules/controllers/services/resources and then adapt the generated code to Prisma and auth requirements.
|
||||
- Do not delete required Nest workspace files just because the LLM can inline a smaller custom structure.
|
||||
- If the workspace is degraded, repair it before generating domain code.
|
||||
|
||||
## Forbidden backend generation patterns
|
||||
Forbidden patterns:
|
||||
|
||||
- Do not bootstrap `server/` by hand-writing a pseudo-Nest project from memory.
|
||||
- Do not remove `tsconfig.json`, `tsconfig.build.json`, or `nest-cli.json` after generation.
|
||||
- Do not replace standard Nest package scripts with ad hoc commands that break `nest build` or `nest start`.
|
||||
- Do not continue CRUD generation on top of a degraded backend workspace without repairing the workspace first.
|
||||
- hand-written pseudo-Nest scaffolds
|
||||
- deleting required Nest config files after generation
|
||||
- replacing normal Nest build/start behavior with ad hoc scripts
|
||||
|
||||
## Domain-derived output
|
||||
|
||||
- `domain/*.dsl` is the source of truth for entities, fields, primary keys, foreign keys, and enums.
|
||||
- `domain-summary.json` is a derived artifact used to stabilize LLM generation and validation. It must never replace the DSL as the source of truth.
|
||||
- Each entity becomes:
|
||||
- a Prisma model
|
||||
- a NestJS module
|
||||
- a controller
|
||||
- a service
|
||||
- create/update DTOs
|
||||
|
||||
## DTO and Prisma mapping
|
||||
|
||||
- `decimal` -> Prisma `Decimal`, DTO/API `string`
|
||||
- `date` -> Prisma `DateTime`, DTO/API `string`
|
||||
- Enums remain string-valued in DTO/API contracts
|
||||
|
||||
## CRUD and natural-key invariants
|
||||
## Route And Resource Contract
|
||||
|
||||
- Use the shared entity-to-resource naming convention from `prompts/general-prompt.md`.
|
||||
- Each entity becomes a NestJS module, controller, service, and create/update DTO pair.
|
||||
- CRUD routes use the real primary key name in the path.
|
||||
- Every API record returned to React Admin must include `id`.
|
||||
- For entities whose primary key is not `id`, the backend must map the real key to `id`.
|
||||
- Natural-key list/sort logic must never build ORM `orderBy` against a fake physical `id`.
|
||||
- For natural-key entities, map the real primary key to `id` in responses and sort translation.
|
||||
|
||||
## Service invariants
|
||||
## DTO Contract
|
||||
|
||||
- Never pass raw update DTOs into Prisma update `data`.
|
||||
- Remove `id`, the real primary key, and readonly fields from update payloads before calling Prisma.
|
||||
- Keep PrismaService lightweight:
|
||||
- `DTO.<Entity>Create` defines `Create<Entity>Dto`.
|
||||
- `DTO.<Entity>Update` defines `Update<Entity>Dto`.
|
||||
- Do not invent fields or pull field lists from memory.
|
||||
- Never include `id` in Create/Update DTOs.
|
||||
|
||||
Type and decorator rules:
|
||||
|
||||
| DSL type | TS DTO type | class-validator decorator | Notes |
|
||||
|-----------|-------------|---------------------------|-------|
|
||||
| `uuid` | `string` | `@IsUUID()` | |
|
||||
| `string` | `string` | `@IsString()` | |
|
||||
| `text` | `string` | `@IsString()` | |
|
||||
| `integer` | `number` | `@IsInt()` | |
|
||||
| `number` | `number` | `@IsNumber()` | |
|
||||
| `decimal` | `string` | `@IsString()` | serialize with Prisma Decimal |
|
||||
| `date` | `string` | `@IsString()` | serialize as ISO string |
|
||||
| `boolean` | `boolean` | `@IsBoolean()` | |
|
||||
| enum name | `string` | `@IsEnum(EnumName)` | |
|
||||
|
||||
Nullability rules:
|
||||
|
||||
- every field that is not `is required` gets `@IsOptional()` before the type decorator
|
||||
- every generated DTO imports from `'class-validator'`
|
||||
|
||||
## Controller Contract
|
||||
|
||||
- Apply `@UseGuards(JwtAuthGuard, RolesGuard)` at controller class level.
|
||||
- Roles per verb:
|
||||
- `GET` -> `viewer | editor | admin`
|
||||
- `POST`, `PATCH`, `PUT` -> `editor | admin`
|
||||
- `DELETE` -> `admin`
|
||||
- Reconcile DSL HTTP shapes for repository compatibility:
|
||||
- list endpoints declared as `POST .../page` generate as `@Get()` with React Admin query params
|
||||
- update endpoints declared as `PUT` generate as `@Patch(':<pk>')`
|
||||
- Path parameters are taken from the DSL endpoint contract, not invented from generic CRUD memory.
|
||||
|
||||
## Service Contract
|
||||
|
||||
- Never pass raw update DTOs directly into Prisma update `data`.
|
||||
- Strip `id`, the real primary key, and readonly fields before writes.
|
||||
- Keep `PrismaService` lightweight:
|
||||
- extend `PrismaClient`
|
||||
- implement `OnModuleInit`
|
||||
- call `$connect()`
|
||||
- do not use `beforeExit`
|
||||
- do not add `beforeExit`
|
||||
|
||||
## Filtering contract
|
||||
List endpoint requirements:
|
||||
|
||||
- List endpoints must support React Admin query parameters:
|
||||
- `_start`, `_end`, `_sort`, `_order`
|
||||
- arbitrary field filters from query string
|
||||
- `q` for reference autocomplete search
|
||||
- String/text search filters may use `contains` with case-insensitive mode.
|
||||
- Foreign key filters must use exact-match semantics (no `contains` for FK scalar keys).
|
||||
- Enum filters must support both single and repeated query params:
|
||||
- `status=Draft`
|
||||
- `status=Draft&status=Approved`
|
||||
- Repeated enum params must map to Prisma `{ in: [...] }`.
|
||||
- Sorting must use real model scalar fields only; natural-key entities must not fallback to fake physical `id`.
|
||||
- accept React Admin query params: `_start`, `_end`, `_sort`, `_order`, `q`
|
||||
- set `Content-Range`
|
||||
- set `Access-Control-Expose-Headers: Content-Range`
|
||||
|
||||
## Reproducibility invariants
|
||||
Filtering rules:
|
||||
|
||||
- A freshly generated backend must be bootstrappable with ordinary Nest + Prisma commands from `prompts/runtime-rules.md`.
|
||||
- Missing TypeScript or Nest workspace config is a generation failure, not an acceptable simplification.
|
||||
- The baseline backend should fail only on missing runtime dependencies or env values, not because the Nest workspace itself is incomplete.
|
||||
- string/text filters may use case-insensitive `contains`
|
||||
- foreign-key scalar filters must use exact-match semantics
|
||||
- enum filters must support both single and repeated params
|
||||
- repeated enum params must map to Prisma `{ in: [...] }`
|
||||
- `_sort=id` must map to the real primary key for natural-key entities
|
||||
|
||||
## Recovery rule if backend workspace degraded
|
||||
Decimal and date handling:
|
||||
|
||||
- If required Nest scaffold files are missing or broken, restore the official workspace baseline before editing Prisma models, modules, controllers, services, or DTOs.
|
||||
- Treat workspace repair as higher priority than feature generation, because generated domain code on top of a broken workspace is invalid baseline output.
|
||||
- `decimal` writes: `new Prisma.Decimal(value)`
|
||||
- `decimal` reads: `.toString()`
|
||||
- `date` writes: `new Date(value)`
|
||||
- `date` reads: `.toISOString()`
|
||||
|
||||
## Backend auth defaults
|
||||
## Natural-Key Rules
|
||||
|
||||
- `GET` -> `viewer | editor | admin`
|
||||
- `POST`, `PATCH`, `PUT` -> `editor | admin`
|
||||
- `DELETE` -> `admin`
|
||||
For entities whose physical primary key is not `id`:
|
||||
|
||||
- route params use the real primary key name
|
||||
- responses expose `id` mapped from that primary key
|
||||
- sort/update behavior never targets a fake physical `id`
|
||||
- update payload sanitization removes both `id` and the real primary key
|
||||
|
||||
## Completion Expectations
|
||||
|
||||
Backend generation is incomplete if any of the following is true:
|
||||
|
||||
- required Nest scaffold files are missing
|
||||
- DTO decorators are incomplete or type-incorrect
|
||||
- controllers are missing guards or role decorators
|
||||
- natural-key handling regresses to a fake physical `id`
|
||||
- list/filter behavior is incompatible with React Admin expectations
|
||||
|
||||
@@ -1,65 +1,118 @@
|
||||
# Frontend Rules
|
||||
|
||||
The frontend stays a React Admin SPA generated from `domain/*.dsl` and anchored to the existing auth seams.
|
||||
<!-- prompt-version: 2.0 -->
|
||||
<!-- applies-to: client/src/resources/, client/src/App.tsx -->
|
||||
<!-- validated-by: tools/validate-generation.mjs §validateApiDslCoverage -->
|
||||
|
||||
## Frontend scaffold baseline
|
||||
Use this document during the **Frontend** stage defined in `prompts/general-prompt.md`.
|
||||
|
||||
- Start frontend initialization from the official Vite React TypeScript scaffold, not from manually assembled files.
|
||||
- Preserve a valid Vite workspace baseline, including:
|
||||
## Purpose
|
||||
|
||||
Generate React Admin resources that stay aligned with the DSL contract, the backend contract, and the repository auth/data provider seams.
|
||||
|
||||
## Mandatory Inputs
|
||||
|
||||
- `prompts/general-prompt.md`
|
||||
- the active `api API.<Entity>` block from `domain/toir.api.dsl`
|
||||
- referenced DTOs and enums from `domain/toir.api.dsl`
|
||||
- an intact or repaired official Vite React TypeScript scaffold under `client/`
|
||||
|
||||
## Expected Outputs
|
||||
|
||||
Per entity:
|
||||
|
||||
- `client/src/resources/<kebab>/<Entity>List.tsx`
|
||||
- `client/src/resources/<kebab>/<Entity>Create.tsx`
|
||||
- `client/src/resources/<kebab>/<Entity>Edit.tsx`
|
||||
- `client/src/resources/<kebab>/<Entity>Show.tsx`
|
||||
|
||||
Repository-wide:
|
||||
|
||||
- `client/src/App.tsx` resource registrations
|
||||
|
||||
## Scaffold Baseline
|
||||
|
||||
- Start frontend initialization and repair from the official Vite React TypeScript scaffold, not from a hand-written shell.
|
||||
- Preserve workspace essentials:
|
||||
- `client/index.html`
|
||||
- `client/tsconfig.json`
|
||||
- `client/vite.config.*`
|
||||
- `client/src/main.tsx`
|
||||
- Add React Admin and auth seams on top of that baseline instead of replacing the workspace with a hand-written minimal shell.
|
||||
- Do not delete required Vite entry/config files just because the LLM can write a shorter custom setup.
|
||||
- Repair the scaffold before generating resources if it is degraded.
|
||||
|
||||
## Forbidden frontend generation patterns
|
||||
## Resource Contract
|
||||
|
||||
- Do not bootstrap `client/` by hand-writing a pseudo-Vite project from memory.
|
||||
- Do not remove `index.html`, `tsconfig*`, or `vite.config.*` after generation.
|
||||
- Do not replace standard Vite package scripts with ad hoc commands that break `vite build`, `vite dev`, or `vite preview`.
|
||||
- Do not continue React Admin resource generation on top of a degraded frontend workspace without repairing the workspace first.
|
||||
- Use the shared entity-to-resource naming convention from `prompts/general-prompt.md`.
|
||||
- Every entity becomes a React Admin resource with `list`, `create`, `edit`, and `show`.
|
||||
- `Resource` registration in `client/src/App.tsx` must include `show={...}`.
|
||||
- Every frontend record must work with React Admin's `id` contract, including natural-key entities.
|
||||
|
||||
## Resource generation
|
||||
DTO-driven view rules:
|
||||
|
||||
- Each entity becomes a React Admin resource with list/create/edit/show views.
|
||||
- Resource names must stay aligned with backend path segments.
|
||||
- Foreign keys must use `ReferenceInput` / `ReferenceField`.
|
||||
- Foreign keys shown in list/show views must stay clickable via `ReferenceField link="show"` to open full details of the related resource.
|
||||
- Lists must expose filters through `List` `filters` and an actions toolbar with `FilterButton`.
|
||||
- For enum fields where multi-select is required (for example `status`), use `SelectArrayInput` in list filters.
|
||||
- For foreign key filters and form selection use `ReferenceInput` + `AutocompleteInput` with `filterToQuery={(searchText) => ({ q: searchText })}`.
|
||||
- Form mapping must stay type-safe:
|
||||
- `integer` / `decimal` -> `NumberInput`
|
||||
- `date` -> `DateInput`
|
||||
- List and Show views use fields from `DTO.<Entity>`
|
||||
- Create view uses fields from `DTO.<Entity>Create`
|
||||
- Edit view uses fields from `DTO.<Entity>Update`
|
||||
- Do not derive form fields directly from model attributes when the DTO contract is narrower
|
||||
|
||||
## Provider seams
|
||||
## Input And Field Mapping
|
||||
|
||||
- `client/src/dataProvider.ts` is the single authenticated request seam.
|
||||
- `client/src/auth/authProvider.ts` is the single React Admin auth seam.
|
||||
- Auth logic must not leak into resource components.
|
||||
Form inputs:
|
||||
|
||||
## Identity and permissions
|
||||
- `integer`, `number`, `decimal` -> `NumberInput`
|
||||
- `date` -> `DateInput`
|
||||
- required `boolean` -> `BooleanInput`
|
||||
- nullable `boolean` -> `NullableBooleanInput`
|
||||
- enum -> `SelectInput`
|
||||
- FK reference -> `ReferenceInput` + `AutocompleteInput`
|
||||
|
||||
- `getIdentity()` must resolve from parsed token claims.
|
||||
- `getPermissions()` may expose realm roles for UI awareness.
|
||||
- Backend enforcement remains authoritative.
|
||||
Display fields:
|
||||
|
||||
## React Admin compatibility
|
||||
- `integer`, `number`, `decimal` -> `NumberField`
|
||||
- `date` -> `DateField`
|
||||
- `boolean` -> `BooleanField`
|
||||
- enum -> `SelectField`
|
||||
- FK reference -> `ReferenceField`
|
||||
|
||||
- Every resource record must include `id`.
|
||||
- Natural-key resources must preserve route, update, and sort compatibility with React Admin contracts.
|
||||
- Frontend requests must continue to work when the real primary key is not named `id`.
|
||||
- `dataProvider` query serialization must preserve repeated query params for array filters (for example enum multi-select).
|
||||
- `Resource` wiring in `App.tsx` must keep `show={...}` registration for all generated resources.
|
||||
Hard failure rule:
|
||||
|
||||
## Reproducibility invariants
|
||||
- using plain `TextInput` for `integer`, `number`, `decimal`, `date`, or `boolean` is a generation failure
|
||||
|
||||
- A freshly generated frontend must remain compatible with standard Vite commands such as `npm run dev` and `npm run build`.
|
||||
- Missing Vite workspace files or missing local Vite executable wiring is a generation failure, not an acceptable simplification.
|
||||
- The generated frontend should fail only on missing installation/env/runtime backend availability, not because the Vite app structure itself is incomplete.
|
||||
## Filter And Reference Contract
|
||||
|
||||
## Recovery rule if frontend workspace degraded
|
||||
- Lists must expose filters and include a toolbar with `FilterButton`.
|
||||
- Enum multi-select filters use `SelectArrayInput`.
|
||||
- Reference filters and form selectors use `ReferenceInput` + `AutocompleteInput` with `filterToQuery={(searchText) => ({ q: searchText })}`.
|
||||
- FK list/show rendering must use `ReferenceField link=\"show\"`.
|
||||
- `dataProvider` query serialization must preserve repeated params for array filters.
|
||||
|
||||
- If required Vite scaffold files are missing or broken, restore the official workspace baseline before editing resources, auth seams, or UI code.
|
||||
- Treat workspace repair as higher priority than feature generation, because generated React Admin code on top of a broken Vite workspace is invalid baseline output.
|
||||
Reference display expression priority:
|
||||
|
||||
1. if `inventoryNumber` exists: ``(record) => `${record.inventoryNumber} — ${record.name ?? record.inventoryNumber}``
|
||||
2. else if `code` exists: ``(record) => `${record.code} — ${record.name ?? record.code}``
|
||||
3. else if `number` exists: ``(record) => `${record.number} — ${record.name ?? record.number}``
|
||||
4. else if `name` exists: `(record) => record.name ?? record.id`
|
||||
5. else: `(record) => record.id`
|
||||
|
||||
## Auth And Provider Seams
|
||||
|
||||
- `client/src/dataProvider.ts` remains the single authenticated request seam.
|
||||
- `client/src/auth/authProvider.ts` remains the single React Admin auth seam.
|
||||
- Resource components must not embed auth logic.
|
||||
- `getIdentity()` resolves from token claims.
|
||||
- `getPermissions()` may expose realm roles for UI awareness, but backend enforcement stays authoritative.
|
||||
|
||||
## Natural-Key Compatibility
|
||||
|
||||
- Frontend requests and routes must continue to work when the real primary key is not named `id`.
|
||||
- Edit/show/delete flows must preserve compatibility with backend natural-key handling.
|
||||
- Sorting and filtering assumptions must not regress to a fake physical `id`.
|
||||
|
||||
## Completion Expectations
|
||||
|
||||
Frontend generation is incomplete if any of the following is true:
|
||||
|
||||
- required Vite scaffold files are missing
|
||||
- Create/Edit inputs are type-incorrect
|
||||
- filter UI is missing or incomplete
|
||||
- reference fields stop linking to `show`
|
||||
- resource registration omits `show={...}`
|
||||
|
||||
@@ -1,146 +1,298 @@
|
||||
ROLE
|
||||
<!-- prompt-version: 3.0 -->
|
||||
<!-- applies-to: all generation tasks (master orchestration prompt) -->
|
||||
<!-- validated-by: tools/validate-generation.mjs + npm run eval:generation -->
|
||||
|
||||
You are a Staff-level Fullstack Platform Engineer working inside the established LLM-first CRUD generation baseline.
|
||||
# Role
|
||||
|
||||
Use context7 when official framework guidance is needed.
|
||||
You are the master orchestrator of the KIS-TOiR generation pipeline.
|
||||
|
||||
This repository is not a new generator engine. Do not redesign it into a planner/emitter/runtime platform.
|
||||
Own the full run: understand the current workspace, read the domain contract, coordinate sub-agents and MCP tools, generate or repair artifacts in the correct order, run the required gates, fix failures, and stop only when the repository is genuinely generation-complete.
|
||||
|
||||
GOAL
|
||||
# Project Description
|
||||
|
||||
Strengthen and use the existing LLM-first CRUD generation pipeline.
|
||||
KIS-TOiR is an LLM-first fullstack CRUD generation project for equipment maintenance management.
|
||||
|
||||
- Keep `domain/*.dsl` as the source of truth for the domain model.
|
||||
- Keep `server/` as the active backend target output path.
|
||||
- Keep `client/` as the active frontend target output path.
|
||||
- Keep Keycloak auth in the default generation path.
|
||||
- Keep PostgreSQL as the only Dockerized runtime dependency.
|
||||
- Generate and maintain:
|
||||
- `domain-summary.json`
|
||||
- a root-level `*-realm.json`
|
||||
- backend/frontend auth seams
|
||||
- runtime/env/bootstrap artifacts
|
||||
- validation-gate-compatible output
|
||||
- Backend: NestJS + Prisma
|
||||
- Frontend: Vite React TypeScript + React Admin
|
||||
- Auth/runtime: external Keycloak + PostgreSQL + repository-managed env/runtime artifacts
|
||||
|
||||
Use the already working runtime defaults for this project unless the prompt explicitly overrides them:
|
||||
The repository is intentionally prompt-driven. `prompts/*.md` define generation policy; generated code lives under `server/` and `client/`.
|
||||
|
||||
- frontend Keycloak URL example: `https://sso.greact.ru`
|
||||
- frontend realm/client examples: `toir`, `toir-frontend`
|
||||
- backend issuer/audience examples: `https://sso.greact.ru/realms/toir`, `toir-backend`
|
||||
- production frontend origin example: `https://toir-frontend.greact.ru`
|
||||
# Mission
|
||||
|
||||
Do not silently regress these examples to localhost Keycloak defaults.
|
||||
Turn the repository source contract into a buildable, validated workspace by:
|
||||
|
||||
ACTIVE KNOWLEDGE BLOCKS
|
||||
1. starting from official framework scaffolding when a workspace is missing or degraded
|
||||
2. generating Prisma, backend, frontend, auth, runtime, and realm artifacts from the DSL
|
||||
3. using sub-agents intentionally instead of carrying every concern in one context window
|
||||
4. proving completion with builds and repository validation gates
|
||||
|
||||
Read in this order:
|
||||
# Source Of Truth
|
||||
|
||||
1. `domain/dsl-spec.md`
|
||||
2. `domain/*.dsl`
|
||||
3. `domain-summary.json` if present
|
||||
4. `prompts/auth-rules.md`
|
||||
5. `prompts/backend-rules.md`
|
||||
6. `prompts/frontend-rules.md`
|
||||
7. `prompts/runtime-rules.md`
|
||||
8. `prompts/validation-rules.md`
|
||||
`domain/toir.api.dsl` is the operative source of truth for generation runs.
|
||||
|
||||
Interpretation rules:
|
||||
It is authoritative for:
|
||||
|
||||
- `domain/*.dsl` is authoritative.
|
||||
- `domain-summary.json` is derived. Regenerate or validate it against the DSL; never treat it as the source of truth.
|
||||
INPUT CONTRACT
|
||||
|
||||
Required:
|
||||
|
||||
- `domain/*.dsl`
|
||||
|
||||
Optional:
|
||||
|
||||
- `overrides/api-overrides.dsl`
|
||||
- `overrides/ui-overrides.dsl`
|
||||
- entities and enums
|
||||
- DTO shapes per operation
|
||||
- nullability and requiredness
|
||||
- primary and foreign keys
|
||||
- HTTP methods, endpoint paths, and pagination contracts
|
||||
|
||||
Rules:
|
||||
|
||||
- Do not require DTO/API/UI DSL files.
|
||||
- Do not resurrect multi-DSL source-of-truth behavior.
|
||||
- Optional overrides may refine derived API/UI behavior but must not redefine the domain model.
|
||||
- Read the DSL directly. Do not substitute `api-summary.json` for `domain/toir.api.dsl`.
|
||||
- Work from entity-scoped slices: the active `api API.<Entity>` block plus its referenced DTOs and enums.
|
||||
- Quote the relevant DSL field definitions verbatim before generating DTOs, Prisma fields, controller contracts, or React Admin components.
|
||||
- Treat `api-summary.json` only as an auxiliary artifact for quick inventory or validation/tooling that explicitly depends on it. It is never the authoritative generation input.
|
||||
|
||||
PIPELINE CONTRACT
|
||||
# Orchestration Model
|
||||
|
||||
1. Parse `domain/*.dsl`.
|
||||
2. Generate or refresh `domain-summary.json`.
|
||||
3. Scaffold with official framework CLI conventions where scaffolding is needed.
|
||||
4. Generate or maintain backend/frontend code in `server/` and `client/`.
|
||||
5. Generate or maintain the root-level realm artifact.
|
||||
6. Generate or maintain env/bootstrap/runtime artifacts.
|
||||
7. Run the lightweight validation gate.
|
||||
Use a manager-first, agent-as-tool architecture.
|
||||
|
||||
REPAIR-BEFORE-GENERATE ORDER
|
||||
- Keep one orchestrator in charge of planning, sequencing, integration, and final acceptance.
|
||||
- Delegate bounded work to specialists; do not let sub-agents redefine the source hierarchy or completion criteria.
|
||||
- Delegate by stage or artifact family, and by entity when parallelism helps.
|
||||
- If a sub-agent result conflicts with the DSL, companion rules, or validator output, trust the DSL and the gates.
|
||||
|
||||
1. Inspect whether `server/` and `client/` are still valid framework workspaces.
|
||||
2. If either workspace is degraded, repair the official scaffold baseline first.
|
||||
3. Only after workspace repair, generate or update domain-derived feature code.
|
||||
4. Only after generation, run validation and buildability checks.
|
||||
Mandatory delegation pattern for future runs:
|
||||
|
||||
CLI-FIRST SCAFFOLDING CONTRACT
|
||||
- `explorer`
|
||||
Use first for repo discovery, scaffold inspection, locating entity-scoped DSL context, and finding existing registrations/seams.
|
||||
- `docs_researcher`
|
||||
Use when framework behavior, CLI scaffolding, or prompt/orchestration patterns need verification against official docs or Context7.
|
||||
- stage worker / generator
|
||||
Use for bounded Prisma, backend, frontend, or auth/runtime implementation work after the orchestrator has assembled the right inputs.
|
||||
- `reviewer`
|
||||
Use before declaring completion. Reviewer must check DSL fidelity, prompt-contract compliance, and whether validation output supports the completion claim.
|
||||
|
||||
- Never hand-write a fresh framework workspace from scratch when an official CLI exists for that framework.
|
||||
- For `server/`, initialize the workspace from the official NestJS CLI baseline first, then generate/adapt modules/resources inside that workspace.
|
||||
- For `client/`, initialize the workspace from the official Vite React TypeScript baseline first, then add React Admin, auth seams, and generated resources.
|
||||
- Treat CLI scaffolding as the required baseline for compiler config, package scripts, workspace metadata, and default entry files.
|
||||
- Manual creation is allowed only for domain-derived feature code after the official workspace exists.
|
||||
- If a workspace already exists but is missing required CLI baseline files, repair it back to a valid official-style workspace before adding more generated code.
|
||||
If a runtime does not expose named sub-agents, preserve the same separation of responsibilities inside one agent and keep stage handoffs explicit.
|
||||
|
||||
ANTI-REGRESSION FAILURES
|
||||
# MCP Usage Model
|
||||
|
||||
Treat the following as baseline violations, not acceptable improvisations:
|
||||
Use MCP/tools deliberately, not reflexively.
|
||||
|
||||
- creating a NestJS workspace by manually writing `package.json`, `tsconfig*`, `nest-cli.json`, and `src/*` from memory instead of starting from official CLI conventions
|
||||
- creating a Vite React TypeScript workspace by manually writing `package.json`, `index.html`, `tsconfig*`, `vite.config.*`, and `src/*` from memory instead of starting from official scaffold conventions
|
||||
- deleting required framework scaffold files after generation because the app appears to work with a smaller custom structure
|
||||
- declaring generation successful when workspace validity or buildability is broken or unverified
|
||||
- letting prompts promise an auth/runtime contract that validation does not enforce
|
||||
- treating one project-specific DSL filename as the only allowed source instead of supporting `domain/*.dsl`
|
||||
- Filesystem/search tools: gather exact local context before making decisions.
|
||||
- Shell/runtime tools: run official CLI scaffolding, Prisma commands, builds, validators, and evals. Do not simulate command results from memory.
|
||||
- Context7: verify current NestJS, Prisma, React Admin, Vite, Keycloak, or prompt/orchestration guidance when repository docs are not enough.
|
||||
- Web research: only after local files and Context7 are insufficient; prefer primary sources.
|
||||
- Diff/validation tools: use before edits, after edits, and always at the end.
|
||||
|
||||
OUTPUT CONTRACT
|
||||
Tool-order policy:
|
||||
|
||||
The baseline output must include:
|
||||
1. local authoritative files
|
||||
2. Context7 / official docs
|
||||
3. web fallback
|
||||
4. validation gates
|
||||
|
||||
# Generation Roadmap
|
||||
|
||||
## 1. Preparation / Discovery
|
||||
|
||||
Purpose:
|
||||
|
||||
- establish the active scope
|
||||
- verify scaffold health
|
||||
- load only the context needed for the next stage
|
||||
|
||||
Responsible:
|
||||
|
||||
- orchestrator
|
||||
- `explorer` first
|
||||
- `docs_researcher` if scaffold conventions or framework behavior are uncertain
|
||||
|
||||
Mandatory inputs:
|
||||
|
||||
- `AGENTS.md`
|
||||
- `prompts/general-prompt.md`
|
||||
- `domain/toir.api.dsl`
|
||||
- `prompts/runtime-rules.md`
|
||||
- `.codex/AGENTS.md` and `.codex/agents/*.toml` when the runtime supports those agents
|
||||
|
||||
Expected outputs:
|
||||
|
||||
- entity-scoped DSL quotes for the active work
|
||||
- a clean stage plan
|
||||
- `server/` and `client/` confirmed healthy or repaired from official scaffolding
|
||||
|
||||
Handoff:
|
||||
|
||||
- proceed to Prisma only after the repository has a valid NestJS workspace, Vite React TypeScript workspace, or a documented repair plan using official CLIs
|
||||
|
||||
Stage rules:
|
||||
|
||||
- Use official Nest CLI for initial backend workspace creation or repair.
|
||||
- Use official Vite React TypeScript CLI for initial frontend workspace creation or repair.
|
||||
- Use Prisma CLI for Prisma initialization when relevant.
|
||||
- Do not handcraft framework scaffolds that should come from official CLIs.
|
||||
|
||||
## 2. Prisma
|
||||
|
||||
Purpose:
|
||||
|
||||
- generate the repository schema that reflects the DSL exactly
|
||||
|
||||
Responsible:
|
||||
|
||||
- orchestrator
|
||||
- Prisma-focused stage worker
|
||||
- `docs_researcher` when Prisma behavior is uncertain
|
||||
|
||||
Mandatory inputs:
|
||||
|
||||
- entity-scoped DSL quotes from `domain/toir.api.dsl`
|
||||
- `prompts/prisma-rules.md`
|
||||
|
||||
Expected outputs:
|
||||
|
||||
- `server/prisma/schema.prisma`
|
||||
- Prisma initialization or repair steps completed when the workspace was missing required baseline files
|
||||
|
||||
Handoff:
|
||||
|
||||
- backend generation starts only after schema output reflects the DSL and Prisma setup is coherent with runtime rules
|
||||
|
||||
## 3. Backend
|
||||
|
||||
Purpose:
|
||||
|
||||
- generate NestJS modules, controllers, services, DTOs, and module registration from the DSL contract
|
||||
|
||||
Responsible:
|
||||
|
||||
- orchestrator
|
||||
- backend stage worker, ideally one entity at a time when parallelized
|
||||
|
||||
Mandatory inputs:
|
||||
|
||||
- entity-scoped DSL quotes from `domain/toir.api.dsl`
|
||||
- `prompts/backend-rules.md`
|
||||
|
||||
Expected outputs:
|
||||
|
||||
- `server/src/modules/<entity>/...`
|
||||
- `server/src/app.module.ts`
|
||||
|
||||
Handoff:
|
||||
|
||||
- frontend generation starts only after backend contracts, guards, DTOs, and natural-key behavior align with backend rules
|
||||
|
||||
## 4. Frontend
|
||||
|
||||
Purpose:
|
||||
|
||||
- generate React Admin resources and resource registration that match backend and DSL contracts
|
||||
|
||||
Responsible:
|
||||
|
||||
- orchestrator
|
||||
- frontend stage worker, ideally one entity at a time when parallelized
|
||||
|
||||
Mandatory inputs:
|
||||
|
||||
- entity-scoped DSL quotes from `domain/toir.api.dsl`
|
||||
- `prompts/frontend-rules.md`
|
||||
|
||||
Expected outputs:
|
||||
|
||||
- `client/src/resources/<entity>/...`
|
||||
- `client/src/App.tsx`
|
||||
|
||||
Handoff:
|
||||
|
||||
- auth/runtime integration starts only after frontend resource contracts align with DTO-derived field sets and type mappings
|
||||
|
||||
## 5. Auth / Runtime / Realm Artifacts
|
||||
|
||||
Purpose:
|
||||
|
||||
- wire authentication, environment defaults, realm import, and runtime topology around the generated CRUD app
|
||||
|
||||
Responsible:
|
||||
|
||||
- orchestrator
|
||||
- auth/runtime stage worker
|
||||
- `docs_researcher` when Keycloak or framework integration behavior is uncertain
|
||||
|
||||
Mandatory inputs:
|
||||
|
||||
- `prompts/auth-rules.md`
|
||||
- `prompts/runtime-rules.md`
|
||||
|
||||
Expected outputs:
|
||||
|
||||
- `server/src/auth/`
|
||||
- `client/src/auth/`
|
||||
- `client/src/dataProvider.ts`
|
||||
- `server/.env.example`
|
||||
- `client/.env.example`
|
||||
- `client/src/auth/keycloak.ts`
|
||||
- `client/src/auth/authProvider.ts`
|
||||
- `client/src/dataProvider.ts`
|
||||
- `server/src/auth/*`
|
||||
- `docker-compose.yml`
|
||||
- `domain-summary.json`
|
||||
- root-level `*-realm.json`
|
||||
- `toir-realm.json`
|
||||
|
||||
The baseline output must also remain a real framework workspace, not a prompt-only file collection:
|
||||
Handoff:
|
||||
|
||||
- `server/tsconfig.json`
|
||||
- `server/tsconfig.build.json`
|
||||
- `server/nest-cli.json`
|
||||
- `client/index.html`
|
||||
- `client/tsconfig.json`
|
||||
- `client/vite.config.*`
|
||||
- verification starts only after auth seams, runtime artifacts, and realm output are aligned with backend/frontend expectations
|
||||
|
||||
NON-GOALS
|
||||
## 6. Verification / Success Gate
|
||||
|
||||
- No new generator engine
|
||||
- No compiler/IR platform
|
||||
- No heavy codegen redesign
|
||||
- No replacement of the old LLM-first architecture
|
||||
Purpose:
|
||||
|
||||
COMPLETION INVARIANTS
|
||||
- prove that the generation run is complete and not just plausible
|
||||
|
||||
- Generation is incomplete if `server/` is not a valid NestJS workspace.
|
||||
- Generation is incomplete if `client/` is not a valid Vite React TypeScript workspace.
|
||||
- Generation is incomplete if auth rules, runtime rules, and validation rules describe different truth paths.
|
||||
- Generation is incomplete if buildability is broken.
|
||||
- If buildability cannot be checked because dependencies are missing, report that state explicitly; do not report a green result for buildability.
|
||||
Responsible:
|
||||
|
||||
VALIDATION
|
||||
- orchestrator
|
||||
- `reviewer` before completion
|
||||
|
||||
Before considering the output complete, satisfy `prompts/validation-rules.md`.
|
||||
Mandatory inputs:
|
||||
|
||||
- `prompts/validation-rules.md`
|
||||
- validation command output
|
||||
- reviewer findings
|
||||
|
||||
Expected outputs:
|
||||
|
||||
- refreshed auxiliary artifacts if the validator/tooling requires them, including `api-summary.json`
|
||||
- passing validation gates
|
||||
- successful backend and frontend builds
|
||||
|
||||
Handoff:
|
||||
|
||||
- there is no next stage; report complete only when every success criterion below is satisfied
|
||||
|
||||
# Success Criteria
|
||||
|
||||
Generation is successful only if all of the following are true:
|
||||
|
||||
- `server/` exists in the project root
|
||||
- `client/` exists in the project root
|
||||
- the backend builds successfully
|
||||
- the frontend builds successfully
|
||||
- `node tools/validate-generation.mjs --artifacts-only` passes
|
||||
- `npm run eval:generation` passes
|
||||
- required auth/runtime/realm artifacts exist and match their companion rules
|
||||
- module/resource registrations are complete
|
||||
- any validator-required auxiliary artifacts, including `api-summary.json`, are refreshed and consistent
|
||||
- the reviewer has not identified unresolved contract violations
|
||||
|
||||
# Non-Goals / Constraints
|
||||
|
||||
- Do not edit `domain/toir.api.dsl` during generation.
|
||||
- Do not treat `api-summary.json` as the source of truth or default starting point.
|
||||
- Do not inline large backend/frontend/prisma/auth/runtime/validation rule sets into this master prompt; load the companion docs instead.
|
||||
- Do not generate domain artifacts on top of a broken scaffold when official CLI repair is required.
|
||||
- Do not claim success from prompt reasoning alone; use builds and repository gates.
|
||||
- Do not load the full DSL blob when entity-scoped context is enough.
|
||||
|
||||
# Companion Rule Documents
|
||||
|
||||
These documents are mandatory when their stage is active:
|
||||
|
||||
- Prisma stage: `prompts/prisma-rules.md`
|
||||
- Backend stage: `prompts/backend-rules.md`
|
||||
- Frontend stage: `prompts/frontend-rules.md`
|
||||
- Auth / realm stage: `prompts/auth-rules.md`
|
||||
- Runtime / bootstrap stage: `prompts/runtime-rules.md`
|
||||
- Verification stage: `prompts/validation-rules.md`
|
||||
|
||||
The master prompt owns orchestration. Companion docs own artifact-specific detail.
|
||||
|
||||
119
prompts/prisma-rules.md
Normal file
119
prompts/prisma-rules.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# Prisma Rules
|
||||
|
||||
<!-- prompt-version: 2.0 -->
|
||||
<!-- applies-to: server/prisma/schema.prisma -->
|
||||
<!-- generated-by: LLM following these rules -->
|
||||
<!-- source-of-truth: domain/toir.api.dsl -->
|
||||
<!-- validated-by: tools/validate-generation.mjs §validateBuildChecks -->
|
||||
|
||||
Use this document during the **Prisma** stage defined in `prompts/general-prompt.md`.
|
||||
|
||||
## Purpose
|
||||
|
||||
Generate `server/prisma/schema.prisma` as a faithful reflection of `domain/toir.api.dsl`.
|
||||
|
||||
## Mandatory Inputs
|
||||
|
||||
- `prompts/general-prompt.md`
|
||||
- the relevant entity/enum definitions from `domain/toir.api.dsl`
|
||||
- the existing Prisma header if `server/prisma/schema.prisma` already exists
|
||||
|
||||
`api-summary.json` may be used only as an auxiliary validator/inventory artifact. It is not part of the authoritative Prisma source hierarchy.
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `server/prisma/schema.prisma`
|
||||
|
||||
Never edit the schema manually during normal generation. Change the DSL and regenerate instead.
|
||||
|
||||
## Source Of Truth
|
||||
|
||||
Entity definitions, field types, PKs, FKs, enums, optionality, uniqueness, and defaults come from `domain/toir.api.dsl`.
|
||||
|
||||
## Scalar Type Mapping
|
||||
|
||||
| DSL type | Prisma scalar type |
|
||||
| --------- | ------------------ |
|
||||
| `uuid` | `String` |
|
||||
| `string` | `String` |
|
||||
| `text` | `String` |
|
||||
| `integer` | `Int` |
|
||||
| `number` | `Float` |
|
||||
| `decimal` | `Decimal` |
|
||||
| `date` | `DateTime` |
|
||||
| `boolean` | `Boolean` |
|
||||
| enum name | enum name as-is |
|
||||
|
||||
Unknown DSL types pass through as-is for forward compatibility.
|
||||
|
||||
## Primary Key Rules
|
||||
|
||||
- a field marked `key primary` becomes `@id`
|
||||
- if the primary key type is `uuid` or the field name is `id`, use `@id @default(uuid())`
|
||||
- non-uuid natural keys keep plain `@id`
|
||||
- every entity must resolve to exactly one primary key
|
||||
|
||||
## Optionality And Defaults
|
||||
|
||||
- primary keys are required
|
||||
- fields marked `is required` are required
|
||||
- all other fields are optional with Prisma `?`
|
||||
- non-primary unique fields get `@unique`
|
||||
- `default <value>` maps to Prisma `@default(...)`
|
||||
|
||||
## Foreign Key And Relation Rules
|
||||
|
||||
For a DSL field declared `key foreign { relates Entity.field }`:
|
||||
|
||||
1. emit the FK scalar field first
|
||||
2. add a relation field named `lowerFirst(relatedEntity)`
|
||||
3. if that relation name collides, append `Ref`
|
||||
4. annotate with `@relation(fields: [<fkField>], references: [<referencedField>])`
|
||||
|
||||
Inverse array relations:
|
||||
|
||||
- add inverse array fields for referencing entities automatically
|
||||
- pluralization rules:
|
||||
- `equipment` stays `equipment`
|
||||
- names ending in `s` add `es`
|
||||
- all others add `s`
|
||||
- if the inverse name collides, append `List`
|
||||
|
||||
## Enum Rules
|
||||
|
||||
- every DSL enum becomes a Prisma enum
|
||||
- preserve declaration order
|
||||
- preserve the enum name exactly
|
||||
|
||||
## Header Preservation
|
||||
|
||||
If `server/prisma/schema.prisma` already contains a `generator client { ... }` block, preserve everything before the first `enum` or `model` keyword.
|
||||
|
||||
If no valid header exists, emit:
|
||||
|
||||
```prisma
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
```
|
||||
|
||||
## Forbidden Patterns
|
||||
|
||||
- do not add fields not declared in the DSL
|
||||
- do not add `@@index`, `@@map`, or schema-level directives not declared by the DSL
|
||||
- do not add `@db.*` modifiers
|
||||
- do not change the datasource provider away from `postgresql`
|
||||
|
||||
## Completion Expectations
|
||||
|
||||
Prisma generation is incomplete if any of the following is true:
|
||||
|
||||
- `server/prisma/schema.prisma` does not exist
|
||||
- the schema no longer reflects the DSL
|
||||
- required relation fields or inverse arrays are missing
|
||||
- header generation or preservation breaks Prisma baseline behavior
|
||||
@@ -1,96 +1,86 @@
|
||||
# Runtime Rules
|
||||
|
||||
This repository keeps the current LLM-first CRUD generation architecture as the primary working baseline and strengthens the existing pipeline instead of replacing it.
|
||||
<!-- prompt-version: 2.0 -->
|
||||
<!-- applies-to: docker-compose.yml, server/.env.example, client/.env.example -->
|
||||
<!-- validated-by: tools/validate-generation.mjs §validateRuntimeContractChecks -->
|
||||
|
||||
## Baseline runtime topology
|
||||
Use this document during the **Preparation / Discovery** and **Auth / Runtime / Realm** stages defined in `prompts/general-prompt.md`.
|
||||
|
||||
- `server/` is the active backend target output path.
|
||||
- `client/` is the active frontend target output path.
|
||||
- Docker scope remains PostgreSQL only.
|
||||
- Keycloak remains external to the repository runtime.
|
||||
- The project remains LLM-first: markdown knowledge blocks in `prompts/` orchestrate generation, while active generated/maintained code lives in `server/` and `client/`.
|
||||
## Purpose
|
||||
|
||||
## Required input and derived artifacts
|
||||
Define the runtime topology, environment defaults, scaffold expectations, and bootstrap sequence for a buildable generated workspace.
|
||||
|
||||
- Source of truth:
|
||||
- `domain/*.dsl`
|
||||
- Required derived artifacts:
|
||||
- `domain-summary.json`
|
||||
- root-level `*-realm.json`
|
||||
## Mandatory Inputs
|
||||
|
||||
`domain-summary.json` exists to stabilize generation and validation; it must be regenerated from the DSL and treated as non-authoritative.
|
||||
- `prompts/general-prompt.md`
|
||||
- `prompts/auth-rules.md` when runtime changes affect auth defaults or seams
|
||||
- current repository runtime/auth defaults
|
||||
|
||||
## Output contract
|
||||
`api-summary.json` is an auxiliary artifact only. Refresh it when validator/tooling requires freshness checks or when a compact inventory helps discovery. Do not treat it as the runtime source of truth.
|
||||
|
||||
The strengthened baseline must produce and keep aligned:
|
||||
## Expected Outputs
|
||||
|
||||
- `server/prisma/schema.prisma`
|
||||
- backend/frontend env examples
|
||||
- backend/frontend auth seams
|
||||
- root `.gitignore`, `server/.gitignore`, `client/.gitignore`
|
||||
- `docker-compose.yml`
|
||||
- `domain-summary.json`
|
||||
- root-level realm import artifact
|
||||
- `server/.env.example`
|
||||
- `client/.env.example`
|
||||
- a buildable NestJS workspace under `server/`
|
||||
- a buildable Vite React TypeScript workspace under `client/`
|
||||
- any validator-required auxiliary artifacts such as `api-summary.json`
|
||||
|
||||
## Concrete runtime examples
|
||||
## Baseline Runtime Topology
|
||||
|
||||
Use these as the baseline examples for this project unless the prompt explicitly overrides them:
|
||||
- `server/` is the backend output path
|
||||
- `client/` is the frontend output path
|
||||
- Docker scope stays PostgreSQL-only
|
||||
- Keycloak remains external to repository runtime
|
||||
- the project remains LLM-first and prompt-driven
|
||||
|
||||
- Backend:
|
||||
- `PORT=3000`
|
||||
- `DATABASE_URL="postgresql://postgres:postgres@localhost:5432/toir"`
|
||||
- `CORS_ALLOWED_ORIGINS="http://localhost:5173,https://toir-frontend.greact.ru"`
|
||||
- `KEYCLOAK_ISSUER_URL="https://sso.greact.ru/realms/toir"`
|
||||
- `KEYCLOAK_AUDIENCE="toir-backend"`
|
||||
- Frontend:
|
||||
- `VITE_API_URL=http://localhost:3000`
|
||||
- `VITE_KEYCLOAK_URL=https://sso.greact.ru`
|
||||
- `VITE_KEYCLOAK_REALM=toir`
|
||||
- `VITE_KEYCLOAK_CLIENT_ID=toir-frontend`
|
||||
## Concrete Runtime Defaults
|
||||
|
||||
These example values come from the already working runtime shape and are preferred over local-only Keycloak placeholders.
|
||||
Backend:
|
||||
|
||||
## Runtime bootstrap
|
||||
- `PORT=3000`
|
||||
- `DATABASE_URL="postgresql://postgres:postgres@localhost:5432/toir"`
|
||||
- `CORS_ALLOWED_ORIGINS="http://localhost:5173,https://toir-frontend.greact.ru"`
|
||||
- `KEYCLOAK_ISSUER_URL="https://sso.greact.ru/realms/toir"`
|
||||
- `KEYCLOAK_AUDIENCE="toir-backend"`
|
||||
|
||||
1. Import the root-level realm artifact into Keycloak.
|
||||
2. Start PostgreSQL with `docker compose up -d`.
|
||||
3. From `server/` run:
|
||||
- initialize or repair the workspace with official Nest CLI scaffolding if required before generating domain code
|
||||
- `npm install`
|
||||
- `npx prisma generate`
|
||||
- `npx prisma migrate dev`
|
||||
- `npx prisma db seed`
|
||||
- `npm run build`
|
||||
- `npm run start`
|
||||
4. From `client/` run:
|
||||
- initialize or repair the workspace with official Vite React TypeScript scaffolding if required before generating app code
|
||||
- `npm install`
|
||||
- `npm run build`
|
||||
- `npm run dev`
|
||||
Frontend:
|
||||
|
||||
## Recovery and completion rules
|
||||
- `VITE_API_URL=http://localhost:3000`
|
||||
- `VITE_KEYCLOAK_URL=https://sso.greact.ru`
|
||||
- `VITE_KEYCLOAK_REALM=toir`
|
||||
- `VITE_KEYCLOAK_CLIENT_ID=toir-frontend`
|
||||
|
||||
- Repair degraded framework workspaces before applying any new domain-derived generation changes.
|
||||
- Do not mark generation complete while `server/` or `client/` remains non-buildable.
|
||||
- If dependency installation has not happened yet, buildability may be reported as skipped, but it must never be reported as green without verification.
|
||||
- Runtime/bootstrap instructions are reusable project baseline rules; TOiR names remain examples, not the only supported domain project.
|
||||
## Scaffold Expectations
|
||||
|
||||
## Scaffold expectations
|
||||
- new or repaired backend workspaces start from the official Nest CLI
|
||||
- new or repaired frontend workspaces start from the official Vite React TypeScript CLI
|
||||
- Prisma initialization uses the official Prisma CLI when relevant
|
||||
- the LLM may customize generated code after scaffold creation, but must not replace official initialization with ad hoc file creation
|
||||
|
||||
- NestJS workspace creation should follow the official Nest CLI path for new applications and resource scaffolding.
|
||||
- Vite frontend creation should follow the official Vite `create-vite` path for React TypeScript applications.
|
||||
- The LLM may customize generated code after scaffold creation, but must not replace official workspace initialization with ad hoc file creation.
|
||||
## Runtime Bootstrap
|
||||
|
||||
## Common generation failures to avoid
|
||||
1. import `toir-realm.json` into Keycloak
|
||||
2. start PostgreSQL with `docker compose up -d`
|
||||
3. from `server/`:
|
||||
- repair or create the workspace with official Nest CLI if needed
|
||||
- install dependencies
|
||||
- run Prisma commands required by the schema stage
|
||||
- run `npm run build`
|
||||
- run `npm run start`
|
||||
4. from `client/`:
|
||||
- repair or create the workspace with official Vite CLI if needed
|
||||
- install dependencies
|
||||
- run `npm run build`
|
||||
- run `npm run dev`
|
||||
|
||||
- starting feature generation before scaffold repair
|
||||
- leaving deleted framework config files unrepaired because the current diff looks smaller
|
||||
- accepting a form-only validation pass while buildability is unknown
|
||||
- binding runtime rules to one project-specific DSL filename instead of `domain/*.dsl`
|
||||
## Completion Expectations
|
||||
|
||||
## Baseline intent
|
||||
Runtime preparation is incomplete if any of the following is true:
|
||||
|
||||
- No new generator engine
|
||||
- No compiler platform
|
||||
- No planner/emitter/runtime redesign
|
||||
- Only the current LLM-first pipeline, strengthened by summary, realm, and validation artifacts
|
||||
- `server/` is missing or not buildable as a NestJS workspace
|
||||
- `client/` is missing or not buildable as a Vite React TypeScript workspace
|
||||
- framework scaffolding was hand-built instead of created or repaired from official CLIs
|
||||
- shared env defaults drift from the repository auth/runtime contract
|
||||
- runtime success is claimed without actual build verification
|
||||
|
||||
@@ -1,98 +1,101 @@
|
||||
# Validation Rules
|
||||
|
||||
Validation is now a lightweight automated gate instead of a prose-only checklist.
|
||||
<!-- prompt-version: 2.0 -->
|
||||
<!-- applies-to: tools/validate-generation.mjs and npm run eval:generation -->
|
||||
<!-- validated-by: self -->
|
||||
|
||||
## Commands
|
||||
Use this document during the **Verification / Success Gate** stage defined in `prompts/general-prompt.md`.
|
||||
|
||||
- `npm run generate:domain-summary`
|
||||
- `npm run validate:generation`
|
||||
- `npm run validate:generation:runtime`
|
||||
## Purpose
|
||||
|
||||
Define the repository gates that convert a plausible generation run into a verified one.
|
||||
|
||||
## Primary Gates
|
||||
|
||||
- `node tools/validate-generation.mjs --artifacts-only`
|
||||
- `npm run eval:generation`
|
||||
|
||||
## Auxiliary Freshness Prep
|
||||
|
||||
- `npm run generate:api-summary`
|
||||
|
||||
Run the freshness prep when the repository validator or supporting tooling expects `api-summary.json` to exist and match the current DSL. This artifact is auxiliary to validation and inventory, not the generation source of truth.
|
||||
|
||||
## Prompt-Gate Alignment Rule
|
||||
|
||||
- Every invariant described as required in the active prompt corpus must either be enforced by this gate or be called out explicitly as a manual/runtime-only check.
|
||||
- Validation must not stay silent about a violation that the prompts describe as forbidden.
|
||||
- Validation must not report green buildability when build verification was skipped.
|
||||
- every invariant marked required in the active prompt corpus must either be enforced by a gate or called out as manual/runtime-only
|
||||
- validation must not silently ignore a forbidden pattern
|
||||
- build verification must not be reported as green when it was skipped
|
||||
|
||||
## Gate groups
|
||||
## Gate Groups
|
||||
|
||||
### Build checks
|
||||
### Build Checks
|
||||
|
||||
- at least one `domain/*.dsl` file exists
|
||||
- required artifacts exist
|
||||
- Prisma schema exists
|
||||
- frontend/backend env contracts exist
|
||||
- frontend/backend framework workspace files exist
|
||||
- `domain-summary.json` matches the current DSL
|
||||
- project `.env.example` files keep the working domain-based Keycloak examples unless explicitly overridden
|
||||
- at least one `domain/*.api.dsl` file exists
|
||||
- required artifacts exist:
|
||||
- `server/prisma/schema.prisma`
|
||||
- env examples
|
||||
- required scaffold files
|
||||
- auth/runtime/realm artifacts
|
||||
- if the current validator policy checks `api-summary.json`, it exists and is fresh relative to the DSL
|
||||
- `server/` remains a valid Nest workspace
|
||||
- `client/` remains a valid Vite workspace
|
||||
- generation must not pass validation if framework scaffolding files were deleted and replaced by a hand-written minimal skeleton
|
||||
- if dependencies are installed, build verification runs for `server/` and `client/`
|
||||
- if dependencies are installed, backend and frontend build verification runs
|
||||
- if dependencies are missing, build verification is reported as skipped with reason instead of green
|
||||
|
||||
### Auth checks
|
||||
### Auth Checks
|
||||
|
||||
- frontend auth seam files exist
|
||||
- backend auth seam files exist
|
||||
- `401` and `403` semantics stay split
|
||||
- `401` and `403` semantics remain split
|
||||
- auth code keeps the required Keycloak/JWT contracts
|
||||
- JWKS resolution chain matches the contract:
|
||||
- JWKS resolution order remains:
|
||||
1. explicit `KEYCLOAK_JWKS_URL`
|
||||
2. OIDC discovery
|
||||
3. certs fallback
|
||||
|
||||
### Filter checks
|
||||
### Filter And UI Checks
|
||||
|
||||
- list resources expose filter UI (including `FilterButton`)
|
||||
- list resources expose filter UI including `FilterButton`
|
||||
- reference filters use `ReferenceInput` + `AutocompleteInput` with `filterToQuery`
|
||||
- data provider preserves repeated query params for array filters
|
||||
- backend FK filters keep exact-match semantics
|
||||
- enum repeated params are mapped to Prisma `in`
|
||||
- typed form mapping is preserved:
|
||||
- `integer` / `decimal` -> `NumberInput`
|
||||
- `date` -> `DateInput`
|
||||
- reference fields intended for navigation keep `ReferenceField link="show"`
|
||||
- `dataProvider` preserves repeated query params for array filters
|
||||
- backend FK filters remain exact-match
|
||||
- repeated enum params map to Prisma `in`
|
||||
- Create/Edit forms keep type-correct inputs
|
||||
- navigable references keep `ReferenceField link="show"`
|
||||
- resources keep `show={...}` registration in `App.tsx`
|
||||
|
||||
### Natural-key checks
|
||||
### Natural-Key Checks
|
||||
|
||||
- response records expose `id`
|
||||
- route/update contracts use the real primary key
|
||||
- natural-key sort/update paths do not regress to a fake physical `id`
|
||||
|
||||
### Realm checks
|
||||
### Realm Checks
|
||||
|
||||
- a root `*-realm.json` artifact exists
|
||||
- realm roles exist
|
||||
- audience delivery exists
|
||||
- required claims are explicit
|
||||
- SPA/backend client structure is explicit
|
||||
- required roles, audience delivery, and claims remain explicit
|
||||
- SPA and backend client structure remains explicit
|
||||
|
||||
### Runtime checks
|
||||
### Runtime Checks
|
||||
|
||||
- compose topology stays PostgreSQL-only
|
||||
- Prisma lifecycle scripts remain in place
|
||||
- `/health` stays public
|
||||
- backend can execute `npm run build` inside `server/`
|
||||
- frontend can execute `npm run build` inside `client/` after dependencies are installed
|
||||
- client/server `.env.example` stay aligned with the working runtime defaults:
|
||||
- `https://sso.greact.ru`
|
||||
- `toir`
|
||||
- `toir-frontend`
|
||||
- `toir-backend`
|
||||
- `https://toir-frontend.greact.ru`
|
||||
- optional runtime execution mode runs:
|
||||
- `npx prisma generate`
|
||||
- `npx prisma migrate dev`
|
||||
- `npx prisma db seed`
|
||||
- Docker topology remains PostgreSQL-only
|
||||
- Prisma lifecycle commands remain available where required
|
||||
- `/health` remains public
|
||||
- backend build runs inside `server/`
|
||||
- frontend build runs inside `client/`
|
||||
- client/server `.env.example` stay aligned with repository defaults
|
||||
|
||||
### Scaffold checks
|
||||
### Output Contract Checks
|
||||
|
||||
- backend initialization starts from official Nest CLI scaffolding
|
||||
- frontend initialization starts from official Vite React TypeScript scaffolding
|
||||
- feature generation happens after scaffold creation, not instead of scaffold creation
|
||||
- repair happens before generation when workspace is degraded
|
||||
- required framework configs and entry files must survive subsequent LLM edits
|
||||
- every generated Create/Update DTO imports from `'class-validator'`
|
||||
- DTO fields have type-correct decorators
|
||||
- optional/nullable fields carry `@IsOptional()` before the type decorator
|
||||
- controllers carry the required guards and roles
|
||||
- React Admin components use correct input/field types
|
||||
|
||||
The automated gate is intentionally small. It enforces the critical reproducibility contract without turning the repository into a test platform or a generator engine.
|
||||
### Eval Harness
|
||||
|
||||
- `npm run eval:generation` runs fixture-based semantic checks
|
||||
- eval failures block completion
|
||||
- prompt changes that break evals are regressions, not acceptable simplifications
|
||||
|
||||
Reference in New Issue
Block a user