--- description: AdminJS panel must stay in sync with Prisma schema changes globs: backend/src/admin/**,backend/prisma/schema.prisma,backend/prisma/migrations/** alwaysApply: false --- # AdminJS ↔ Prisma sync (required) Ops panel at `/admin` (`backend/src/admin/`). Resources are a **manual allowlist** — Prisma does **not** auto-update AdminJS. ## When you change `schema.prisma` **Before finishing the task**, update AdminJS: 1. Open [`backend/src/admin/resources.ts`](backend/src/admin/resources.ts) (`buildAdminResources`). 2. **New model** ops may need to inspect/fix → add `resource(...)` + navigation group + hide secrets. 3. **Renamed / removed model** → update or remove the matching resource (broken `getModelByName` breaks `/admin` boot). 4. **New secret fields** (hashes, tokens, share tokens) → hide via `isVisible: false` (list/filter/show/edit). 5. **Catalog-like reference data** → list/show/edit only; disable `new` / `delete` / `bulkDelete`. 6. **Composite `@@id` only** (no single `@id`) → **do not register** — AdminJS list returns 500 (`Resource does not have an id property`). Examples: `LabCaseDetail`, `MembershipPermission`, read-cursor tables. 7. Skip pure join/cursor tables unless ops need them and they have a single id. Auth: `ADMINJS_EMAIL` / `ADMINJS_PASSWORD` — production login disabled if password missing or still `admin123`. Production Docker: `ADMIN_JS_TMP_DIR=/app/adminjs-tmp` (not `.adminjs`) so `components.bundle.js` can be written/served. ## Secrets to hide `passwordHash`, session `token`/`refreshToken`, invite/OTP `tokenHash`/`codeHash`, `LabCase.accessToken`.