Assemble QMS app + SQLite refactor + Unraid single-container deploy
Build and Push Docker Image / build (push) Successful in 1m12s
Build and Push Docker Image / build (push) Successful in 1m12s
Reconstruct the full app from init-source overlays (base + fix-1..6 + update-1..3, last-wins) at the repo root, complete the missing pieces so it builds and runs, and stage the Unraid deployment. App completion: - types/index.ts: former Prisma enums as string-literal unions + AppUser - pages/_app.tsx + styles/globals.css (mount AppProvider/ToastProvider) - API routes: auth/login, auth/me, users, submissions (+REVIEW_READY notify), forms (list/create), notifications - scripts/create-admin.js: idempotent first-admin bootstrap - 14 unbuilt nav targets stubbed via ComingSoon placeholder SQLite refactor (single-container, no external DB): - schema provider -> sqlite; enums -> String; Json -> String; FormField.options String[] -> JSON-encoded String - lib/forms.ts (de)serialises options at the DB boundary - drop mode:"insensitive" (unsupported on SQLite) - enum imports repointed from @prisma/client to @/types Deploy: - multi-stage Dockerfile (next build -> prod runner), docker-entrypoint.sh (prisma db push -> create-admin -> next start), .dockerignore - docker-compose.yml: br0 10.2.0.x, /mnt/user/appdata/qms -> /data volume - README rewritten for the Unraid/Gitea Actions flow; .env scrubbed of the live Supabase credential; vercel.json removed Verified: next build clean (41 routes); live SQLite round-trip of login/session, form options array, and submission -> REVIEW_READY. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
# V11 Enterprise QMS
|
||||
|
||||
Full-stack quality management system — Next.js 15 (pages router) + Prisma + **SQLite**,
|
||||
packaged as a **single Docker container** for self-hosting on Unraid. Starts from zero
|
||||
data and learns as your team uses it.
|
||||
|
||||
> **Status — partial build.** The implemented modules are: authentication, the first-build
|
||||
> **Form builder** (admin), **Fill / Report an issue** (production), **Nonconformances + Resolutions
|
||||
> library** (QC), **Client release / Shipments**, **Client issues / Quality escapes**, and the
|
||||
> **living Shipping standard**. The remaining nav items (Admin dashboard, Users, Audit trail,
|
||||
> Settings, QC dashboard, CAPA, Audits, Documents, Risk, Suppliers, Standards, My submissions,
|
||||
> Management dashboard & Reports) are wired into navigation but render a "Coming soon" placeholder —
|
||||
> the data model for them already exists in `prisma/schema.prisma`.
|
||||
|
||||
## Roles & access
|
||||
|
||||
| Role | Access |
|
||||
|------|--------|
|
||||
| **Admin** | Everything: form builder, users, settings, audit trail |
|
||||
| **QC** | CAPA, audits, NCRs, resolutions, documents, risk, suppliers, standards, shipping standard |
|
||||
| **Production** | Fill first-build forms, report issues |
|
||||
| **Production lead** | Production + client release, client issues, shipping standard, NCRs |
|
||||
| **Logistics lead** | Client release, client issues, shipping standard, NCRs |
|
||||
| **Management** | Read-only dashboards and reports |
|
||||
|
||||
Only **Admin / Production lead / Logistics lead** can email a client release package.
|
||||
|
||||
---
|
||||
|
||||
## Deploy on Unraid (the intended setup)
|
||||
|
||||
CI/CD: push to Gitea → Gitea Actions builds the image → pushes to `registry.alwisp.com/jason/qms:latest`
|
||||
→ install/Force-update from the Unraid Docker GUI.
|
||||
|
||||
### 1. Build & push (automatic)
|
||||
`.gitea/workflows/docker-build.yml` builds and pushes the image to
|
||||
`registry.alwisp.com/<owner>/<repo>:latest` on every push to `main`. It needs two repo secrets:
|
||||
`REGISTRY_USER` and `REGISTRY_TOKEN`.
|
||||
|
||||
### 2. Run on Unraid
|
||||
Either `docker compose up -d` with the bundled [`docker-compose.yml`](docker-compose.yml), or add a
|
||||
container in the Unraid Docker GUI with the equivalent settings:
|
||||
|
||||
| Setting | Value |
|
||||
|---|---|
|
||||
| Repository | `registry.alwisp.com/jason/qms:latest` |
|
||||
| Network | **Custom: br0** — assign a free IP in `10.2.0.0/24` |
|
||||
| Volume | `/mnt/user/appdata/qms` → `/data` |
|
||||
| `DATABASE_URL` | `file:/data/qms.db` |
|
||||
| `NEXT_PUBLIC_APP_URL` | `http://<the-br0-ip>:3000` |
|
||||
| `ADMIN_EMAIL` / `ADMIN_PASSWORD` / `ADMIN_NAME` | first-run admin (created only if no admin exists) |
|
||||
| `SMTP_*` (optional) | enables outbound email; omit to keep notifications in-app only |
|
||||
|
||||
On first start the container runs `prisma db push` (creates `/data/qms.db`), then `create-admin`
|
||||
(creates the admin from `ADMIN_*` only if none exists), then serves on port `3000`. The SQLite file
|
||||
lives entirely in the mapped volume, so the container is disposable — update by pulling a new image.
|
||||
|
||||
The app is reached at `http://<the-br0-ip>:3000`. Sign in with the admin credentials and change the
|
||||
password.
|
||||
|
||||
---
|
||||
|
||||
## Local development
|
||||
|
||||
```bash
|
||||
npm install
|
||||
cp .env.example .env # DATABASE_URL defaults to file:./dev.db
|
||||
npm run db:push # create the SQLite schema
|
||||
npm run create-admin # seed the first admin from ADMIN_* in .env
|
||||
npm run dev # http://localhost:3000
|
||||
```
|
||||
|
||||
Useful scripts: `npm run build`, `npm run start`, `npm run db:studio`.
|
||||
|
||||
---
|
||||
|
||||
## Why SQLite (not Postgres)
|
||||
|
||||
This deploy targets a single self-contained container, so the schema was converted from PostgreSQL to
|
||||
SQLite. SQLite (via Prisma) supports neither native enums nor `Json`/scalar-list columns, so:
|
||||
|
||||
- former enums are stored as `String` and validated in app code (union types in [`types/index.ts`](types/index.ts));
|
||||
- former `Json` columns (`AuditLog.before/after`, `FormSubmission.data`, `QualityStandard.specs`) and the
|
||||
`FormField.options` list are stored as **JSON-encoded strings**, (de)serialised at the DB boundary
|
||||
(see [`lib/forms.ts`](lib/forms.ts)).
|
||||
|
||||
## Project structure
|
||||
|
||||
```
|
||||
/pages
|
||||
/api ← backend API routes (auth, forms, submissions, ncrs, escapes, shipments, …)
|
||||
/admin /qc /fill /management ← role-scoped pages
|
||||
/components ← layout shell, shared UI kit, form field renderer
|
||||
/lib ← prisma client, auth/session, email, form (de)serialisation helpers
|
||||
/prisma ← schema.prisma (SQLite)
|
||||
/scripts ← create-admin.js (first-run bootstrap)
|
||||
Dockerfile · docker-compose.yml · docker-entrypoint.sh · .gitea/workflows/build.yml
|
||||
```
|
||||
|
||||
> `init-source/` holds the original delivery (base snapshot + fix/update overlays) for provenance;
|
||||
> it is excluded from the build and the image.
|
||||
Reference in New Issue
Block a user