Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

QMSentry — Quality Management System & Compliance Engine

Execution-first compliance platform for ISO 9001:2015 & 21 CFR Part 11. Engineered for banking operations, built for auditability, styled with premium fintech aesthetics.

QMSentry is not a passive policy archive — it is the primary daily operational workspace where quality management, risk mitigation, and continuous improvement are executed in real time. Every user action is cryptographically signed, hash-chained, and immutably logged before any database commit. Every endpoint is authenticated, every input Zod-validated, every file magic-byte verified.

Built with Next.js 14 App Router, TypeScript (strict), Tailwind CSS v4, Prisma ORM v6, PostgreSQL 16, TipTap v3, BullMQ, Redis, and 58 automated tests covering hash chain integrity, RBAC, Zod schemas, and file upload security.


Module Suite

21 fully integrated modules mapping to international regulatory standards. Every module has a dedicated list page, a /new creation page, and a /[id] detail page — no modals for primary workflows.

Module Route ISO 9001 Clause 21 CFR Part 11
Executive Dashboard /dashboard §9.1 View-only
Document Management (EDMS) /documents §7.5 Active Signatures
Process Mapping /processes §4.4 Audit Trail
Risk Register /risks §6.1 Audit Trail
FMEA Worksheets /fmea §6.1 Audit Trail
Non-Conformities (NC) /nc §8.7 Active Signatures
CAPA Management /capa §10.2 Active Signatures
Kaizen Suggestions /kaizen §10.3 Audit Trail
Training & Competency /training §7.2 Active Signatures
Internal Audits /audits §9.2 Audit Trail
KPI Dashboards /kpis §9.1 View-only
Management Review /management-review §9.3 Active Signatures
Change Requests /change-requests §8.5.6 Active Signatures
Supplier Quality /suppliers §8.4 Audit Trail
Customer Complaints /complaints §8.2.1 Audit Trail
Task Tracker /tasks View-only
Traceability Matrix /traceability §7.5.3 View-only
Digital Signatures /signatures 21 CFR §11 Core Engine
CBS Integration Layer /cbs Cryptographic
Settings / Admin /settings Configurable
Production Stack /settings/infrastructure Super Admin

Module Highlights

Document Management (EDMS) Full lifecycle management (Draft → Review → Approved → Released) enforced by a fixed 4-layer approval chain:

  1. Document Manager (DOCCTRL department) — completeness review
  2. Approval Group (uploader selects at submission): Group A (QM / Audit / Compliance / Risk / AML) or Group B (QM / Audit / Compliance / Risk) — all members in the chosen group approve in parallel
  3. Board Committee (BOARD department) — final sign-off; transitions status to PENDING_MOM
  4. Minutes of Meeting (MOM) — mandatory attachment upload before the document is promoted to RELEASED

Custom TipTap A4-layout editor with Arabic/RTL support, inline feedback threads, and automatic PDF rendering. Signatures are PKI-backed with RFC 3161 timestamps. Document numbers are generated atomically (no duplicate-number race conditions) via a per-prefix-year sequence counter in the database.

Process Mapping Full process profiles with 10 ordered sections per process: Purpose, Scope, Interfaces, Inputs & Outputs, Activities table, Risks & Controls, KPIs with live progress bars, Applicable Documents (L1–L4 hierarchy), Competency Requirements, and BPMN-style swimlane flow diagram. A "View as Document" toggle renders any process as a formal ISO QMS document — complete header table, numbered sections, approval signature table — ready to print or export as PDF.

Risk Register Interactive 5×5 Risk Matrix computing raw and residual scores (impact × likelihood). Each risk links to mitigations, linked documents, and CAPAs.

FMEA Worksheets Failure Mode and Effects Analysis with automated RPN calculation (Severity × Occurrence × Detection), corrective control tracking, and CAPA linking. The worksheet table includes a second header row with guiding questions under each column (e.g. "What is the process step?", "What could go wrong?", "What is the impact on the customer?") matching the standard FMEA Excel template layout.

Non-Conformities Auto-routing by department, immediate containment capture, integrated 5-Whys root cause analysis, and direct CAPA generation.

CAPA Management Closed-loop corrective and preventive actions with milestone task lists, evidence attachments, and formal verification sign-off. Linked to NCs, audit findings, complaints, and change requests.

Kaizen Suggestions 10-step improvement pipeline: current situation, root cause (5-Whys), proposed solution, benefit/risk analysis, implementation plan, resource budget, KPI targets, AI-assisted review, solution testing, and document linking.

Internal Audits Audit scheduler with auditor assignment, ISO-clause-linked checklist generation, findings with direct CAPA triggers, and annualized schedule progress tracking.

Training & Competency Per-user training records with expiry tracking, status workflow (Pending → Completed / Overdue), competency matrix grouped by role, and privileged admin view with bulk assign and delete. Stats cards: Total, Completed, Overdue, Expiring in 30 days.

CBS Integration Layer Secure Core Banking System connector handling ISO 20022 XML messages (Pacs.008, Camt.053), HMAC-verified webhook payloads, and AES-256-GCM credential storage. Sandbox and production environments.

Settings — Security Password policy, session timeouts, account lockout thresholds, and audit log retention — all persisted to the SystemSetting table and editable by ADMIN without a deployment.

Production Stack (Infrastructure View) Visual architecture dashboard at /settings/infrastructure showing all 13 production layers with status badges, feature checklists, file references, environment variable requirements, and live deployment commands.


Security Architecture (21 CFR Part 11 & Banking-Grade)

1. Tamper-Evident Immutable Audit Log (§11.10(e))

Every data modification receives a monotonically sequenced entry. Each row computes a SHA-256 hash over its own content and the previousHash of the preceding row — creating a cryptographic chain that breaks if any historical entry is altered:

entryHash = SHA-256(sequenceNumber ‖ action ‖ entityId ‖ userId ‖ createdAt ‖ previousHash)
  • Hash computation and INSERT happen atomically inside a single Prisma transaction — no race condition possible.
  • In production PostgreSQL: REVOKE UPDATE, DELETE ON "AuditLog" FROM <app_role> — the DB engine physically rejects any modification. SQL provided in scripts/db-init.sql.
  • Verified by 7 automated unit tests covering tampering of every field in the chain.

2. PKI Digital Signatures (§11.50)

Users generate RSA-PSS (2048-bit) or ECDSA (P-256) key pairs. Private keys are AES-256-GCM encrypted at rest. Each signature records: signer name, high-precision UTC timestamp, SHA-256 hash of the document snapshot at signing time, and the administrative meaning (Author / Reviewer / Approver). RFC 3161 TSA tokens provide qualified, externally-verifiable timestamp proof.

3. Authentication & Session Security

Control Implementation
Password hashing bcrypt with cost factor 12
Session strategy JWT, never stored server-side
Session expiry 8 h (standard roles), 4 h (ADMIN / APPROVER)
Cookie flags httpOnly, sameSite: strict, secure in production
Account lockout 5 failed attempts → 30-minute lockout (stored in DB)
Password complexity Min 12 chars, uppercase, lowercase, digit, special character
Forced reset mustChangePassword flag enforced at middleware — cannot be bypassed by URL
Startup validation App refuses to start if NEXTAUTH_SECRET < 32 chars or CBS_ENCRYPTION_KEY ≠ 32 bytes

4. RBAC & Department Isolation

8-level role hierarchy enforced in both middleware and every Server Action via requireRole() / requirePermission():

Role Level Capabilities
VIEWER 0 Read-only within own department; can submit Kaizens
Q_DEPT_VIEW 0 Read-only scoped to Quality department
AUDIT 1 Conduct audits, view audit logs
EDITOR 2 Full create/edit within own department
REVIEWER 3 Cross-department read for audits and compliance
APPROVER 4 Cross-department approval with cryptographic signature
DEPARTMENT_ADMIN 5 Administrative rights scoped to own branch
ADMIN 6 Global configuration, user lockout, database diagnostics

Verified by 17 automated unit tests covering all roles against all permission actions.

5. API & Route Security

  • Every /api/ route checks session before processing — including AI chat, PKI generation, signing, and file uploads.
  • withApiAuth() middleware handles session check, role validation, Zod body validation, and audit log in one place.
  • Rate limiting: Nginx (IP-level) + Upstash Redis REST (user-level). Auth: 10 req/min, Uploads: 5 req/min, Standard: 60 req/min.
  • Response headers on every route: X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, Permissions-Policy: camera=(), microphone=(), geolocation=(), Strict-Transport-Security, full Content-Security-Policy.

6. File Upload Security

  • Magic-byte verification: content signature checked against declared MIME type — a .pdf containing PE/ELF bytes is rejected.
  • Extension whitelist: only pdf, doc, docx, xls, xlsx, txt, png, jpg, jpeg, gif, webp accepted.
  • Size limits: documents max 25 MB, images max 5 MB — enforced before reading content.
  • Filename sanitization: null bytes, ../, ..\, and non-safe characters stripped; max 255 chars.
  • S3-compatible storage: files uploaded to Cloudflare R2 or AWS S3 in production; served via signed URLs (1-hour TTL max). Falls back to authenticated local API route in development.
  • Key format: {module}/{entityId}/{uuid}.{ext} — no user-controlled path segments.
  • Verified by 14 automated security tests.

Production Stack (13 Layers)

The full production stack is implemented and documented in /settings/infrastructure (visible to ADMIN). Configuration files are committed to the repo.

# Layer Technology Status
1 Routing / Reverse Proxy Nginx 1.27, TLS 1.3, HTTP/2 Configured
2 Web / Application Next.js 14.2, React 18.3, TypeScript 5 Live
3 API / Backend Next.js Route Handlers, Server Actions, Zod Live
4 Database PostgreSQL 16, Prisma ORM 6, Migrations Live
5 Database Pooling PgBouncer 1.22, Transaction Pool Mode Configured
6 Caching Redis 7, ioredis, LRU eviction Configured
7 Background Jobs BullMQ 5, Redis, Cron repeats Configured
8 Rate Limiting Upstash Redis REST + Nginx zones Live
9 Object Storage Cloudflare R2 / AWS S3, Presigned URLs Live
10 Security NextAuth, RBAC, AES-256-GCM, RSA-PSS, Hash Chain Live
11 Testing & Quality Vitest 4, Playwright 1.60, TypeScript strict Live
12 Observability Pino 10 (JSON), pino-pretty (dev), redacted fields Configured
13 Backup & Recovery pg_dump + gzip + S3, 30-day retention, crond Configured

Key production files: Dockerfile, docker-compose.prod.yml, nginx/nginx.conf, scripts/backup.sh, scripts/restore.sh, scripts/db-init.sql, src/lib/queue/index.ts, src/lib/cache/index.ts, src/lib/observability/logger.ts.


Tech Stack

Layer Technology
Framework Next.js 14 App Router, React 18
Language TypeScript 5 (strict mode, zero errors)
Styling Tailwind CSS v4
ORM Prisma v6 (fully typed — no raw SQL in src/)
Database PostgreSQL 16 + PgBouncer (transaction pool mode)
Auth NextAuth.js v4
Rich Text TipTap v3 (RTL, tables, inline comments)
Object Storage S3-compatible (Cloudflare R2 / AWS S3) with local dev fallback
Caching Redis 7 + ioredis (in-process Map fallback for dev)
Background Jobs BullMQ 5 + Redis
Rate Limiting Upstash Redis REST + Nginx limit_req_zone
Logging Pino 10 (structured JSON) + pino-pretty (dev)
Forms React Hook Form + Zod v4
AI Vercel AI SDK — streams from local Ollama (private inference)
Unit Tests Vitest v4
E2E Tests Playwright
Container Docker multi-stage build (deps → builder → runner)
Reverse Proxy Nginx 1.27 (TLS 1.3, HSTS, rate limiting, gzip)

Project Structure

qmss/
├── Dockerfile                          ← Multi-stage production build
├── docker-compose.db.yml               ← Dev: PostgreSQL 16 only
├── docker-compose.prod.yml             ← Prod: Nginx + App + PgBouncer + Redis + Backup
├── nginx/nginx.conf                    ← TLS, rate limits, security headers
├── scripts/
│   ├── backup.sh                       ← Daily pg_dump → gzip → S3 + 30-day pruning
│   ├── restore.sh                      ← S3 download + gunzip + psql restore
│   └── db-init.sql                     ← Least-privilege role + AuditLog REVOKE
├── run_qms.bat                         ← Windows smart launcher (dev)
├── vitest.config.ts
├── playwright.config.ts
├── prisma/
│   ├── schema.prisma                   ← PostgreSQL schema (21 modules)
│   ├── migrations/
│   │   ├── 20260518000000_init_postgres/          ← Full base schema
│   │   ├── 20260621000001_document_approval_layers/ ← 4-layer approval + departments
│   │   └── 20260621000002_document_sequence/      ← Atomic doc-number counter
│   ├── seed.ts                         ← Idempotent seeder (upsert-based)
│   └── reset.ts
├── tests/
│   ├── unit/                           ← Hash chain, Zod schemas, RBAC
│   ├── security/                       ← File upload, env validation
│   ├── integration/
│   └── e2e/                            ← Playwright auth + security headers
└── src/
    ├── app/
    │   ├── (auth)/                     ← Login, forced password reset
    │   ├── (dashboard)/                ← 21 modules + settings
    │   │   └── settings/
    │   │       ├── users/              ← User management (soft-delete, pagination)
    │   │       ├── security/           ← Password policy, sessions, lockout, audit retention
    │   │       ├── infrastructure/     ← Production stack architecture view (13 layers)
    │   │       ├── departments/
    │   │       ├── ai/
    │   │       └── profile/
    │   ├── (public)/                   ← Public complaint form, signature verification
    │   └── api/                        ← REST endpoints (all require session)
    ├── components/
    │   ├── layout/                     ← Sidebar, navbar, RTL wrappers
    │   ├── shared/                     ← TipTap editor, PKI modals, AI overlay
    │   ├── processes/                  ← SwimlaneBuilder, ProcessProfileForm
    │   ├── charts/                     ← KPI visualizers (Recharts)
    │   └── ui/                         ← Atomic primitives (Radix + shadcn)
    └── lib/
        ├── core/
        │   ├── auth.ts                 ← NextAuth config (session expiry, cookie flags)
        │   ├── audit.ts                ← SHA-256 hash-chained immutable logger
        │   ├── db.ts                   ← Prisma client + PgBouncer support
        │   ├── startup.ts              ← Env validation at cold start
        │   └── schemas/                ← Zod schemas for every module
        ├── security/
        │   ├── permissions.ts          ← 8-role RBAC matrix + 50+ permission actions
        │   ├── ratelimit.ts            ← Upstash Redis rate limiter
        │   ├── pki-crypto.ts           ← RSA-PSS / ECDSA / AES-256-GCM / TSA
        │   └── cbs-crypto.ts           ← HMAC webhook verification
        ├── storage/
        │   └── index.ts                ← S3/R2 upload + signed download URLs
        ├── cache/
        │   └── index.ts                ← Redis cache (withCache, CacheKeys, dev fallback)
        ├── queue/
        │   └── index.ts                ← BullMQ queues (notifications, docs, scheduled jobs)
        ├── observability/
        │   └── logger.ts               ← Pino structured logger with field redaction
        ├── middleware/
        │   ├── api-handler.ts          ← withApiAuth() — session + role + Zod + audit
        │   └── api-middleware.ts       ← API key validation for external integrations
        └── actions/                    ← React Server Actions (one file per module)
            ├── operations/             ← processes, risks, FMEA, KPIs, training
            ├── compliance/             ← audits, nc, capa, complaints
            ├── admin/                  ← users, departments, settings
            ├── integration/            ← PKI, CBS
            └── shared/                 ← attachments (magic-byte + S3), utils

Testing

# Run all unit + security tests (58 tests, ~700ms)
npm test

# Watch mode
npm run test:watch

# Coverage report
npm run test:coverage

# E2E browser tests (Playwright auto-starts dev server)
npm run test:e2e

# Playwright interactive UI
npm run test:e2e:ui

Test Coverage

Suite File Tests Status
SHA-256 hash chain integrity tests/unit/audit-hash-chain.test.ts 7 ✅ Pass
Zod schema validation tests/unit/schemas.test.ts 11 ✅ Pass
RBAC permission matrix tests/unit/rbac.test.ts 17 ✅ Pass
File upload security tests/security/file-upload.test.ts 14 ✅ Pass
Startup env validation tests/security/startup-validation.test.ts 9 ✅ Pass
E2E auth + security headers tests/e2e/auth.spec.ts 10 Requires server
Total 68 58/58 unit pass

Getting Started

Prerequisites

  • Node.js v20+
  • Docker (for PostgreSQL)
  • Git

Method A: Docker Quick-Start (Recommended)

# 1. Start PostgreSQL
docker compose -f docker-compose.db.yml up -d

# 2. Install dependencies
npm install

# 3. Configure environment
cp .env.example .env
# Edit .env — generate secrets with the commands shown in the file

# 4. Apply database migrations
npx prisma migrate deploy

# 5. Seed initial data (idempotent — safe to re-run)
npx prisma db seed

# 6. Start dev server
npm run dev

Open http://localhost:3000.

Method B: Windows Quick-Launch

.\run_qms.bat

Kills processes locking the Prisma DLL, clears stale .next cache, syncs DB schema, and starts the dev server. Requires Docker running first.


Default Credentials

Role Email Password Scope
Super Admin admin@qms.com password123 Global
CEO / Approver ceo@qms.com password123 Executive
Quality Approver approver@qms.com approver123 Compliance & QA
Department Editor editor@qms.com editor123 Operations
General Viewer viewer@qms.com viewer123 Retail Banking

Change all passwords immediately after first login in any non-development environment.


Environment Variables

Copy .env.example to .env. The app validates all required variables at startup and refuses to boot if any are missing or use placeholder values.

Variable Required Purpose Generation
DATABASE_URL PostgreSQL connection string
PGBOUNCER No Set true when routing through PgBouncer (port 6432)
NEXTAUTH_SECRET JWT encryption salt — min 32 chars openssl rand -base64 48
NEXTAUTH_URL Canonical app URL
JOB_RUNNER_SECRET Secures scheduled job routes openssl rand -hex 32
CBS_ENCRYPTION_KEY ⚠️ AES-256-GCM key — must decode to exactly 32 bytes openssl rand -base64 32
PKI_ENCRYPTION_KEY ⚠️ AES-256-GCM key for PKI private key encryption openssl rand -base64 32
UPSTASH_REDIS_REST_URL ⚠️ Distributed rate limiting Upstash dashboard
UPSTASH_REDIS_REST_TOKEN ⚠️ Rate-limiting auth token Upstash dashboard
REDIS_URL ⚠️ BullMQ queues + Redis cache redis://localhost:6379
REDIS_PASSWORD No Redis AUTH password (production)
LOG_LEVEL No Pino log level: debug/info/warn/error Default: info
S3_ENDPOINT ⚠️ Prod Object storage endpoint https://<id>.r2.cloudflarestorage.com
S3_BUCKET_NAME ⚠️ Prod Bucket name e.g., qmsentry-files
S3_REGION ⚠️ Prod AWS-compatible region auto for Cloudflare R2
S3_ACCESS_KEY_ID ⚠️ Prod S3 access key R2 / S3 console
S3_SECRET_ACCESS_KEY ⚠️ Prod S3 secret key R2 / S3 console
DB_USER ⚠️ Prod Least-privilege app DB role qmsentry_app
DB_PASSWORD ⚠️ Prod Password for DB_USER Strong random string

✅ = required at all times. ⚠️ = required in production; falls back to safe defaults in dev.


Production Deployment

Full Stack (docker-compose.prod.yml)

# Build and start all 13-layer production services
docker compose -f docker-compose.prod.yml up -d --build

# Run database migrations
docker compose -f docker-compose.prod.yml exec app npx prisma migrate deploy

# Seed initial data
docker compose -f docker-compose.prod.yml exec app npx prisma db seed

# Apply AuditLog INSERT-only constraint (run once, as DBA)
docker compose -f docker-compose.prod.yml exec postgres \
  psql -U postgres -d qmsentry -f /docker-entrypoint-initdb.d/db-init.sql

# View application logs
docker compose -f docker-compose.prod.yml logs -f app

Required post-migration DBA step (21 CFR §11.10(e))

-- Run as superuser after prisma migrate deploy
REVOKE UPDATE, DELETE ON "AuditLog" FROM qmsentry_app;
GRANT INSERT, SELECT ON "AuditLog" TO qmsentry_app;

Backup & Restore

# Manual backup (automatic daily via crond container at 02:00 UTC)
docker compose -f docker-compose.prod.yml exec backup /bin/sh /backup.sh

# Restore from a specific backup file
./scripts/restore.sh qmsentry_2026-06-07.sql.gz

Scaling

Phase Database Storage Jobs Notes
Dev PostgreSQL (Docker) Local uploads/ HTTP poll Default Docker Compose setup
Production PostgreSQL + PgBouncer Cloudflare R2 or AWS S3 Redis + BullMQ Up to ~1,000 active users
Enterprise PostgreSQL (AuditLog partitioned by year) S3 BullMQ + Meilisearch 1M+ audit rows, full-text search

At a 5-branch banking operation with ~200 quality users, expect ~500k audit entries/year and burst peaks of ~10 DB writes/second.


Security Audit Summary

A full security audit was completed covering authentication, session management, input validation, file uploads, API security, and cryptographic integrity. 19 findings were identified and all fixed.

Severity Findings Fixed
CRITICAL 2 ✅ 2
HIGH 7 ✅ 7
MEDIUM 6 ✅ 6
LOW 4 ✅ 4

Key fixes:

  • /api/ai/chat was completely unauthenticated — fixed with session guard + rate limit
  • .env.example contained real cryptographic secrets — replaced with REPLACE_ME_* placeholders
  • Session cookies lacked httpOnly, sameSite, secure flags — enforced
  • Session had no expiry (NextAuth default: 30 days) — set to 8h / 4h for privileged roles
  • changePasswordSchema only required 8 chars — raised to 12 with full complexity
  • Filenames stored without sanitization — path traversal sequences now stripped
  • X-Frame-Options was SAMEORIGIN — changed to DENY
  • No startup validation of secrets — app now refuses to boot with missing/short/placeholder values
  • __Secure- cookie prefix rejected over HTTP in dev — made environment-conditional
  • pino/thread-stream bundled by webpack in Next.js 14 — moved to serverComponentsExternalPackages

Code Quality

  • Zero raw SQL in src/ — all queries use fully typed Prisma calls.
  • Zero any casts — TypeScript strict mode enforced across the entire src/ tree.
  • npx tsc --noEmit — zero errors across the entire codebase.
  • Idempotent seedprisma/seed.ts uses upsert for reference data; safe to re-run against a live database.
  • Structured logging — Pino with field redaction for password, token, secret, cookie, authorization.

Troubleshooting

EPERM: operation not permitted during prisma generate

The dev server holds a lock on query_engine-windows.dll.node. Kill all Node processes first:

taskkill /F /IM node.exe /T
npx prisma generate

run_qms.bat does this automatically.


unable to get local issuer certificate on corporate networks

$env:NODE_TLS_REJECT_UNAUTHORIZED = "0"

run_qms.bat applies this automatically for local dev.


App refuses to start with "FATAL" error

The startup validator (src/lib/core/startup.ts) rejected a required environment variable. Check that:

  • NEXTAUTH_SECRET is at least 32 characters and is not a REPLACE_ME_* placeholder
  • DATABASE_URL is set and points to a running PostgreSQL instance
  • JOB_RUNNER_SECRET is set and not the placeholder
  • CBS_ENCRYPTION_KEY, if set, decodes to exactly 32 bytes (openssl rand -base64 32)

Can't reach database server at localhost:5432

PostgreSQL is not running. Start the Docker Compose stack:

docker compose -f docker-compose.db.yml up -d

Login always fails / all pages show Unauthorized

Verify the __Secure- cookie issue is not present. In .env, confirm NODE_ENV is not set to production during local development. The session cookie name is environment-conditional: next-auth.session-token in dev, __Secure-next-auth.session-token in prod.


© 2026 QMSentry Platform — Engineered for Banking. Refined for Compliance. Built for Execution.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages