Duty of care — incidents
Alhuda is responsible for pilgrims far from home, many of them elderly. Every emergency is recorded, owned, worked through a checklist, and reflected in the traveller's journey.
Route: /operations/incidents, gated on incidents.view.
Rules: 13 · Duty of care and incidents (INC).
1. What an incident records
Thirteen types: medical, hospitalisation, death, missing traveller, lost or stolen documents, theft or loss, flight disruption, hotel problem, transport failure, security incident, legal or police matter, behaviour conflict, other (INC-001).
Each carries the travellers and group, a severity (Critical / High / Medium / Low), where and when it happened, who reported it, a named owner, a status (open → in progress → resolved → closed), a checklist, private documents, a communication log (family, consulate, insurer, hospital, authorities, tour leader) and the cost with who bears it.
2. The board
Columns by severity, cards showing type, traveller, group, city, owner, age and a response- time chip, filters by group and city, and a detail drawer. It refreshes on its own.
An open-emergency banner appears on the booking and group screens for anyone, without showing them the incident content; traveller flags appear on rooming and flight-manifest lists (INC-020).
3. Who can see it
Incident records carry health data, so they are held tighter than anything else in the system:
| Permission | Who holds it |
|---|---|
incidents.view |
CEO, GM, Operations Manager, Operations Executive, Auditor |
incidents.manage |
CEO, GM, Operations Manager, Operations Executive |
incidents.close |
CEO, GM, Operations Manager |
incidents.confirm_death |
CEO, GM |
IT_ADMIN is deliberately not granted any of them — data minimisation
(AUD-020, DPDP Act 2023).
Browser sessions cannot write incident tables at all; every change goes through a
SECURITY DEFINER function. Incident audit rows are written without customer, booking or
group tags, so incident detail never leaks onto an activity timeline that a bookings.view
holder can read. Documents live on the company Shared Drive (Incidents / the incident), are never given a
URL, and open inside the drawer through drive-file, which checks incidents.view
(ACC-074).
Customer 360 shows that a restriction exists ("Medical note — restricted") to a viewer who may not see the content (C360-003).
4. The death checklist
The twelve steps of INC-010 are seeded verbatim as a template and copied onto every death incident when it is opened — identity and place of death, informing management and assigning a family liaison, the next of kin's wishes, the hospital or police report and the Saudi death certificate, registration with the Consulate General of India in Jeddah, burial or repatriation, the insurance claim, passport and return ticket, re-planning for dependants, finance, communication to the group, and closing.
Each step records its state, who, when, a note and a document. The incident cannot be
closed while any step is neither done nor explicitly marked not applicable with a reason,
and closing needs incidents.close plus resolution notes.
Checklist templates for hospitalisation, missing traveller, lost passport, flight disruption and a generic case are seeded too, as proposed operational defaults — Operations should confirm them before release.
5. Traveller state
hospitalised, missing and deceased are set only by set_traveller_state. It never
deletes or cancels a passenger, booking, ticket or visa case. Marking a traveller deceased
needs incidents.confirm_death and the incident number typed back, and completes checklist
step 1 with the confirming manager and the time. Changing a deceased record is a correction
with the same confirmation, written as a new append-only event. Browser sessions cannot
touch the state columns at all
(INC-012).
The journey reads only the traveller state — never incident detail — so the two permissions stay separate (JRN-001).
6. Impact suggestions
Opening an incident lists what it touches: dependants, a possible mahram to review, and room-mates, each as a suggested checklist task (INT-141). "Add task" writes one checklist item after a confirmation. Suggestions never act on their own (INT-003).
Flights, transfers, visa, insurance and money are not covered, and there is no AI drafting of family or consulate messages.
7. What is shown but not done
Response times are displayed, not enforced
The INC-003 response times drive an
"Assign now / Update overdue / On track" chip on the board and the dashboard queue. A
Critical incident writes in-app notification rows for everyone holding incidents.close
and logs the escalation. Nothing is sent externally, and nothing escalates on a
timer — the duty roster and the escalation chain are still management decisions.
- INC-011, the compassionate policy, is OPEN, so nothing in the incident module moves money. A death's step 10 records the cost, the currency and who bears it against the incident and nothing else. No cancellation, refund or ledger entry follows from an incident.
- Emergency contacts are not required on a booking (INC-005); the communication log exists.
- Removing a traveller from headcounts, transport and printed manifests is Wave 3/4.
- Vaccination, insurance and medical notes are not recorded at all (HLT-001…003); readiness reports them as not applicable and names the rule that will add them.
8. Where to look
| Concern | Path |
|---|---|
| Permissions | supabase/migrations/20260919130000_incident_permissions.sql |
| Tables, functions, templates | supabase/migrations/20260919130100_duty_of_care_incidents.sql |
| Board and drawer | src/pages/operations/Incidents.tsx, src/components/incidents/ |
| Types and the proposed SLA | src/lib/incidents.ts |
| Tests | supabase/tests/incidents.sql, src/lib/incidents.test.ts, src/lib/api.incidents.test.ts |