What each role has to do
Three roles, three jobs, one chain of custody. This page is the walkthrough — what a person in each role actually does, in order, and what the system refuses to let them do.
Describes today's behaviour on the working branch. Anything built but switched off by default is marked flag-gated with its flag named.
The spine
Nothing here is parallel. Each role hands to the next, and the handoff is the point.
Closure moved to the safety officer in round 4 (2026-09-11), reversing the earlier rule that the foreman closes. A contractor or an inspector requests closure — the dotted lines — and the officer confirms it or closes directly; either way the officer gives a reason. A request is a flag on the permit, not a status.
Contractor
The job: describe dangerous work honestly enough that someone else can judge it, then run that work and ask for it to be closed.
The contractor is the only role that creates permits. They are also the foreman — but since round 4 closure is the safety officer's action, not theirs.
What they do
- Build the permit through a seven-step wizard: type → basic info → where & when → safety checks → PPE and workers → JSA → review. Review is always last and no step is filtered out, whatever has or has not been set up elsewhere in the app. It autosaves as a
DRAFTcontinuously, and can be saved explicitly with a confirmation. - Say where and when in one step: pick a facility plan, then select a pin a safety officer placed on it (shown as a read-only marker on the plan), add a free-text location detail, the work window — a date range plus the daily start and end times that repeat across it — and a free-text note for what the window cannot express ("not working Sat/Sun"). Basic info, the step before, is just the project, the contractor and the foreman.
- Declare the PPE and the workers. PPE is ticked from seven items — Safety Glasses, Hardhat, Respiratory Protection, Earmuffs, Construction Vest, Gloves, Protective Boots — and is optional unless a deployment turns on flag-gated
PPE_REQUIRED. Workers are picked from the contractor's own directory, each with a role on this permit chosen from a list or typed. A worker not in the directory is registered in place, and gets a printable QR card carrying their id — the card the inspector's entrant scan reads. - Add missing certificates without leaving the wizard, including the certificate file.
- Submit. The server re-checks everything: readings in range, every worker holding an unexpired certificate, no blank JSA rows, and a pin once safety has an active pin on an active plan.
- Revise and resubmit if rejected. The officer's written reason is the only channel telling them what to fix.
- Mark work complete — for hot work this starts the 30-minute Fire Watch rather than closing.
- Ask for closure. Since round 4 the contractor no longer closes: they request it and a safety officer closes. The API supports the request; the contractor app has no request button yet, and its old closure checklist is now refused by the server (
403 FORBIDDEN_ROLE).
There is no area to propose any more — areas were removed in round 4, and the places a permit can point at are the pins safety has placed.
The walkthrough
What the system refuses them
- Closing a permit at all.
POST /closeis the safety officer's since round 4; the contractor app's old closure checklist now answers403 FORBIDDEN_ROLE. - Requesting closure of someone else's permit, or of one that is not
ACTIVE/FIRE_MONITOR. - Editing someone else's permit.
- Editing a
PENDINGpermit in place. Editing returns it toDRAFTand it must be resubmitted — they are warned before the edit begins, not after. An officer must never approve a version nobody showed them.
Safety Officer
The job: decide whether work is safe enough to allow, and be able to prove afterwards why you decided it.
What they do
- Work the review queue of
PENDINGpermits. - Read the permit's verdict, not their own arithmetic — the server says which readings passed and which failed, and the screen displays that.
- See what changed if the contractor edited after submitting: the review screen shows which fields moved, so a resubmission does not mean re-reading the whole document.
- See overlapping work on the same pin — other permits whose date range and daily window collide, each named with the colliding date and time and the pin's name. An advisory warning, never a block, because two crews on one pin is sometimes correct and always worth knowing.
- Approve — which issues the QR and makes the permit live — or reject with a written reason.
- Name facility plans and place pins — the facility's shared set of places. A pin's name can be changed; its position cannot, and plans and pins are deactivated, never deleted.
- Close permits, with a mandatory reason on the record — confirming a contractor's or an inspector's request, or directly. Closing a confined-space permit with people still checked in succeeds and checks them out automatically, marked as done by the system. On screen the close is still labelled as a backstop ("Close on contractor's behalf") and the app shows no request queue yet; an officer learns of a request from its notification.
- Read the audit log, including whether a field action arrived by scan or by manual entry.
- Manage accounts — contractors, safety officers, inspectors — deactivating rather than deleting.
The walkthrough
What the system refuses them
- Approving without the server having validated. The verdict is not theirs to compute or override.
- Editing or deleting an audit row. There is no path, for anyone.
- Deleting an account. Deactivation only.
- Removing the last safety officer — the system refuses to leave itself with none.
Inspector
The job: verify on the plant floor that what the paperwork promised is what is happening — usually one-handed, often with no signal.
The inspector approves nothing and creates no permits. Their power is narrower and sharper: they decide who physically goes in.
What they do
- Scan the permit's QR at the place of work. It resolves to live status — not a snapshot from when it was printed — so a permit closed an hour ago reads as closed.
- Type the code manually when a camera will not cooperate. The system records which way it was verified.
- Run the entrant register for confined spaces: check each worker in, and out again, by scanning the worker's QR card or from the visit's entrant table. A worker whose certificate has lapsed is denied at the gate, and that denial is written to the audit log. It cannot be overridden in the field. A worker who is not on site is marked not available, with a note, on their permit row — an absence, not an entry; they can still check in if they arrive late.
- Log gas readings during the work. On a confined-space permit the server owns the clock — a reading is due every two hours, with a half-hour grace — and says whether it is overdue. The app renders that verdict; it never recomputes the threshold.
- Work through one visit at a time, from an action menu. A scan starts a visit. Since round 4 the visit is a menu of four or five items worked in any order — Check-in / Check-out, PPE Check, Gas Reading (Confined Space only), Note, Request Close — each showing whether it is not done, done this visit, or has nothing pending. Only check-in/check-out blocks submit, and it is satisfied by reviewing the entrant table, never by changing it. This reverses round 3's fixed spine; it is safe only because the gas clock moved server-side, where the sweep notifies and escalates whatever a visit records. There is no fire-watch step.
- Record what they saw — a PPE check against what the contractor declared, with any undeclared gap flagged (which needs a corrective-action, emergency or incident note), photos and typed notes (
GENERAL,WARNING,CORRECTIVE_ACTION,EMERGENCY,INCIDENT) — submitted once, at the end of the visit.EMERGENCYandINCIDENTnotify the safety officers and the permit's owner;CORRECTIVE_ACTIONnotifies the owner only;GENERALandWARNINGnotify nobody. The owning contractor may read the whole visit record of their own permits through the API, so inspectors should write knowing that. - Request closure from the visit menu. The inspector never closes; a safety officer does.
- Keep working with no network on the entrant-register and gas-log screens: those actions queue on the device and sync when signal returns — and, since ticket 111, so does a check-in or check-out from inside a visit. Not-available, the PPE check and the visit submit cannot be queued, and the app says so.
- Review their own recent scans on the device — read-only, and deliberately so.
The walkthrough
What the system refuses them
- Overriding a lapsed certificate. This is the hardest rule in the product.
- Approving, rejecting or closing anything. A visit records; it changes no permit field and moves the permit through no status. A closure request only flags the permit for safety.
- Inspecting a
CLOSEDorEXPIREDpermit. Every field action refuses anything butACTIVEorFIRE_MONITOR; the QR lookup still answers, to say the permit is closed. - Editing a visit they already submitted. There is no edit path, not even for a typo — an inspector who got it wrong files another visit.
- Acting from history. Opening a past scan is read-only — a history entry proves someone was there once, not that they are there now. A state-changing action needs a fresh scan. Round 4 narrows this for one action: the server now lets an inspector start a visit from history within the window their own last scan bought — the earlier of 12 hours and the end of the permit's work window — and refuses it after (
SCAN_WINDOW_EXPIRED). The app does not offer it yet. - Being told an offline action was "saved." It says queued, because it has not reached the server yet.
Reading the three together
| Contractor | Safety Officer | Inspector | |
|---|---|---|---|
| Creates | permits, workers, certificates | accounts, facility plans and the pins on them | visit records |
| Decides | what the work is | whether it may happen | who physically goes in |
| Closes | nothing — requests closure of their own permits | any permit, with a reason | nothing — requests closure |
| Works offline | no | no | yes, by requirement |
| Can override a safety rule | no | no | no |
That last row is the shape of the whole system. There is no role that can wave a rule through, which is why the audit log is worth trusting.
Where to go next
- Domain context — the contexts behind these journeys and the rules they own.
- Why this system exists — goal, objectives and success criteria.
- Permit lifecycle — every status transition in detail.