# 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.