chore: scaffold Next.js 15 + Supabase clients + vitest
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
# Technical Specification
|
||||
## HSE Incident Management System — Build Spec for Claude Code
|
||||
|
||||
This document tells Claude Code *how* to build what `01_PRD_HSE_Incident_Management_System.md` describes. Give Claude Code both files together. If you're new to coding: you don't need to understand every line below — just hand this file to Claude Code and let it explain each decision to you as it builds.
|
||||
|
||||
---
|
||||
|
||||
## 1. Recommended Tech Stack
|
||||
|
||||
Chosen for one reason above all: **you're a beginner, so fewer moving parts = fewer things that can break and fewer things you need to host/manage yourself.**
|
||||
|
||||
| Layer | Choice | Why |
|
||||
|---|---|---|
|
||||
| Frontend + backend | **Next.js** (React) | One framework handles both the web pages and the server logic — no separate backend project to manage |
|
||||
| Database + Auth + File Storage | **Supabase** (hosted Postgres) | Gives you a database, user login system, and file storage (for photos/videos) in one dashboard, with a generous free tier. You don't manage servers. |
|
||||
| Hosting | **Vercel** (frontend) + Supabase cloud | Both have simple free/low-cost tiers, deploy with a few clicks, no server administration |
|
||||
| AI features | **Claude API** (Anthropic) | For triage suggestions, RCA/CAPA drafting, and the JKKP form auto-fill logic described in the PRD §8 |
|
||||
| Notifications | **Resend** or SendGrid (email) + **WhatsApp Business Cloud API** (Meta) | Matches PRD §7 |
|
||||
| QR codes | `qrcode` npm package (generates codes for each site/zone, no external cost) | |
|
||||
| PDF generation (JKKP forms) | `pdf-lib` (fills the official JKKP 6/7 PDF templates with stored data) | |
|
||||
|
||||
**Alternative stack** (if you later hand this to a professional dev team instead of building it yourself): Python/FastAPI backend + PostgreSQL + AWS S3 for storage + React frontend. Same schema and logic below applies either way — this spec is written to be stack-agnostic where it matters.
|
||||
|
||||
**Budget note:** Video evidence storage is the main cost driver as usage grows. Start on Supabase's free/starter storage tier; if video volume grows heavy in Phase 3+, migrate large-file storage to **Cloudflare R2** (cheaper for large files, still simple to set up) while keeping structured data in Supabase.
|
||||
|
||||
---
|
||||
|
||||
## 2. System Architecture (module view)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Reporter mobile/web app → QR scan → incident form │
|
||||
└───────────────────────────┬─────────────────────────────┘
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Next.js application │
|
||||
│ - Incident intake & workflow engine │
|
||||
│ - CAPA module │
|
||||
│ - Dashboard & analytics │
|
||||
│ - Admin (users, sites, roles) │
|
||||
└───────┬───────────────┬───────────────┬───────────────────┘
|
||||
▼ ▼ ▼
|
||||
┌───────────────┐ ┌──────────────┐ ┌─────────────────────┐
|
||||
│ Supabase DB │ │ Supabase │ │ Claude API │
|
||||
│ (Postgres) │ │ Storage │ │ - triage suggestion │
|
||||
│ + Auth (RLS) │ │ (photos/ │ │ - RCA/CAPA drafting │
|
||||
│ │ │ videos/docs)│ │ - JKKP form drafting │
|
||||
└───────────────┘ └──────────────┘ └─────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Notifications: Email (Resend) + WhatsApp Cloud API │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Database Schema
|
||||
|
||||
Core tables (Postgres). Claude Code should generate this as Supabase migrations. Field lists are the minimum required — add more as needed during build, don't remove any listed here.
|
||||
|
||||
**sites** — id, name, address, region, active
|
||||
**zones** — id, site_id (FK), name (e.g. "Dock A", "Cold Storage"), qr_code_token (unique)
|
||||
**users** — id, name, email, phone, role (enum: reporter/supervisor/hse/capa_owner/management/admin), department, site_id, active
|
||||
**incidents** — id, reference_no (unique, auto-generated), incident_type (enum: injury/near_miss/hazard/asset_damage/environmental/security/fire), site_id, zone_id, reported_by, reported_at, description, severity (1-5, nullable until triaged), status (enum: reported/triaged/investigating/capa_pending/verification/closed), injury_involved (bool), asset_involved (bool), medical_status (enum: none/first_aid/medical_treatment/lti, nullable), lost_days (int, nullable), closed_at (nullable)
|
||||
**evidence_files** — id, incident_id (FK), stage (enum: report/response/investigation/capa/verification), file_url, file_type, file_hash, uploaded_by, uploaded_at
|
||||
**investigations** — id, incident_id (FK), investigator_id, method (enum: five_why/fishbone/other), findings_text, root_cause_summary, alcohol_test_result (nullable), witness_statement_refs, completed_at
|
||||
**capa_actions** — id, incident_id (FK), root_cause_ref, description, owner_user_id, department, due_date, priority (enum: low/med/high), status (enum: open/in_progress/overdue/pending_verification/verified/reopened/closed), completed_at, verified_by, verified_at, effectiveness_recheck_date
|
||||
**dosh_reports** — id, incident_id (FK), form_type (enum: jkkp6/jkkp7/jkkp8), status (enum: not_required/pending/submitted), submitted_at, submitted_by, file_url (generated PDF)
|
||||
**notifications_log** — id, incident_id or capa_id, channel (email/whatsapp/in_app), recipient, sent_at, status
|
||||
**audit_log** — id, table_name, record_id, action, changed_by, changed_at, old_value, new_value
|
||||
|
||||
**Row-level security (RLS):** Enforce role-based access at the database level using Supabase RLS policies — e.g., a `capa_owner` can only see/update `capa_actions` rows where `owner_user_id` or `department` matches their own; a `reporter` can only see incidents where `reported_by` = themselves. This is safer than hiding buttons in the UI alone (per PRD §11).
|
||||
|
||||
---
|
||||
|
||||
## 4. Screens / Pages to Build
|
||||
|
||||
Organize as Claude Code build tasks in roughly this order (also see the phased roadmap doc):
|
||||
|
||||
1. **Login / role-based home redirect**
|
||||
2. **Report incident** (mobile-first form, QR pre-fills site/zone, photo/video upload, offline-capable)
|
||||
3. **My reports** (reporter's own submission status tracker)
|
||||
4. **Incident inbox** (supervisor/HSE view — list + filters by site/status/severity)
|
||||
5. **Incident detail** (full timeline: report → response → investigation → CAPA → verification, with evidence gallery per stage)
|
||||
6. **Triage panel** (severity + classification, shows AI suggestion + regulatory checklist from PRD §9)
|
||||
7. **Investigation workspace** (RCA template picker: 5-Why / fishbone, findings entry, AI-drafted root cause/CAPA suggestions to accept or edit)
|
||||
8. **CAPA board** (Kanban + table view, filters, overdue highlighting)
|
||||
9. **CAPA detail** (owner uploads completion evidence, HSE verifies)
|
||||
10. **Dashboard** (KPIs, heatmap by site/zone, leading/lagging split, DOSH filing status — per PRD §10)
|
||||
11. **DOSH register** (JKKP 6/7 draft generator, JKKP 8 annual register export)
|
||||
12. **Admin** (manage users, sites/zones + QR generation, form field config)
|
||||
|
||||
---
|
||||
|
||||
## 5. AI Integration Details (Claude API)
|
||||
|
||||
Map directly to PRD §8. Each is a server-side call from Next.js to the Claude API, never client-side (keep your API key secret):
|
||||
|
||||
- **Report quality check**: on form submit, send description + evidence count to Claude; return a short list of missing items (e.g., "no photo attached for an injury report").
|
||||
- **Severity/category suggestion**: send description + incident type; return suggested severity (1-5) + confidence + category, for the triaging user to confirm.
|
||||
- **Similar-incident retrieval**: use vector embeddings (Supabase supports `pgvector`) on incident descriptions; on new report, query top-5 similar past incidents by embedding distance + same site/zone.
|
||||
- **RCA/CAPA drafting assistant**: send investigation findings text; return suggested root cause categories and 2-3 draft CAPA descriptions for HSE to edit/accept.
|
||||
- **JKKP form drafting**: send structured incident + investigation data in a prompt that asks Claude to produce the JKKP 6/7 field values as JSON; feed that JSON into `pdf-lib` to fill the actual form template.
|
||||
|
||||
All AI calls are logged (which incident, which suggestion, what the human ultimately chose) — this creates a useful dataset over time and keeps a clear line between "AI suggested" and "human decided," which matters if a record is ever audited.
|
||||
|
||||
---
|
||||
|
||||
## 6. Security & Auth
|
||||
|
||||
- Supabase Auth with email/password or phone OTP (phone OTP likely better adoption for warehouse floor staff without corporate email).
|
||||
- Role stored in `users.role`, enforced via RLS (see §3) — never trust role checks only in the frontend.
|
||||
- File uploads scanned/validated for type and size before storage.
|
||||
- All admin actions (user role changes, site config) logged to `audit_log`.
|
||||
|
||||
---
|
||||
|
||||
## 7. Deployment Recommendation
|
||||
|
||||
1. Supabase project (free tier to start) → run schema migrations from §3.
|
||||
2. Next.js app → deploy to Vercel, connect to Supabase via environment variables (never commit API keys to code).
|
||||
3. Custom domain (e.g. `hse.setiacorp.com`) once MVP is validated.
|
||||
4. Set up Resend/WhatsApp Cloud API credentials as environment variables.
|
||||
5. Claude API key as environment variable, called only from server-side API routes.
|
||||
|
||||
This matches the phased build order in `03_Development_Roadmap_and_Claude_Code_Brief.md` — start with local development, deploy to a free-tier staging environment after Phase 1 (MVP) so real users can start testing early.
|
||||
Reference in New Issue
Block a user