Ownware
Home›Safora›Manual
Safora · Manual

Safora Manual, as shipped in the download

Safora — User Manual

A food-safety diary you own, keep and can hand to an inspector. Version 3.1.5 [src: app/controllers/api.php:19].

About this manual

Every statement here was written by reading Safora's own source, and each one carries the file it came from in a bracketed src marker. Paths are relative to the folder this docs directory sits in. If a sentence disagrees with the application, the application is right and this manual has a bug — the markers exist so you can check rather than take our word for it.

Nothing is described that the code does not do. Where something is deliberately limited, that is said plainly rather than left out — which matters more here than in most products, because somebody may be relying on the record.

Read this before anything else

Safora is a record-keeping and compliance-documentation tool. It does not certify compliance and it is not professional food-safety advice [src: app/src/FoodSafety.php:13].

The temperature limits it ships with are sensible HACCP-aligned defaults, and every one of them is configurable — per business and per piece of equipment [src: app/src/FoodSafety.php:24]. Several carry an explicit "verify against your local rules" note in the source [src: app/src/FoodSafety.php:29].

That matters because the defaults are drawn from UK guidance. The cooking and reheating minimums cite UK and Scottish guidance [src: app/src/FoodSafety.php:25], and hot-holding and cooling cite the UK Food Standards Agency [src: app/src/FoodSafety.php:30]. If you are not in the UK, treat them as a starting point to be replaced rather than as your rules.

What gets recorded

Six kinds of record [src: app/src/FoodSafety.php:42]: temperature readings, cooking, cooling, deliveries, cleaning and checklists.

Equipment is one of five types [src: app/src/FoodSafety.php:41], and each piece can carry its own range rather than inheriting the business default [src: app/src/FoodSafety.php:99].

The whole rule engine is offline and pure

Every rule the product enforces — the ranges, the cooking and cooling limits, the delivery checks, the corrective-action rule, the daily colour and the temperature conversion — lives in one place with no database and no network, so it can be proven in isolation and reused identically by the browser, the seeder and the audit exporter [src: app/src/FoodSafety.php:3].

Temperatures

Everything is stored in Celsius. The display unit only affects rendering and the parsing of what you type [src: app/src/FoodSafety.php:10], so switching between °C and °F never changes a stored reading.

A reading sitting exactly on a limit counts as in range, by way of a deliberate float tolerance [src: app/src/FoodSafety.php:21].

Readings outside a physically sane window are rejected before they reach the database, which also keeps every stored value inside its column and stops an absurd input overflowing the database [src: app/src/FoodSafety.php:35].

The rule that makes the diary worth keeping

An out-of-range reading cannot be saved without a corrective action [src: app/src/FoodSafety.php:179]. Attempting it returns a refusal saying exactly that [src: app/src/FoodSafety.php:187].

This is the invariant the whole product is built around, and it is what turns a list of numbers into a document an inspector can use: every deviation on the record carries what was done about it.

And the second half — verification

Recording the action at the time is one half of HACCP. The other is somebody senior confirming afterwards that the action actually worked, and that was added as an open-to-verified lifecycle on any out-of-range entry [src: app/src/Database.php:155].

The save-time rule is untouched by it [src: app/src/Database.php:154] — verification is a follow-up the product did not previously have, not a relaxation of the original guard.

Verifying in bulk runs in a transaction, because verifying half a list and then failing is worse than verifying none [src: app/src/Database.php:66].

The daily colour

Each day gets a colour worked out from that day's readings and its scheduled checks [src: app/src/FoodSafety.php:231]:

ColourMeaning
greenEvery scheduled check done and every reading in range
amberOut-of-range readings that have a corrective action, or checks still pending today
redAn out-of-range reading with no corrective action, or a required check missed on a day already past
noneNothing scheduled and nothing recorded

The precedence is strict, and the order is the point: an unresolved breach is red before anything else is considered, and a missed check only hardens to red once the day is in the past [src: app/src/FoodSafety.php:233].

Closed days

A day you declare closed cannot be missing a check, because nobody was there to make it [src: app/src/FoodSafety.php:254].

But closing does not erase what was recorded. An unresolved breach on a closed day is still red, and the source gives the reason in one line: "we were shut" is not a corrective action [src: app/src/FoodSafety.php:256].

Scheduled checks — knowing something is due

Recording what already happened is the easy half. The half an inspector actually asks about is "how do you know the closing fridge check got done on the 14th?" [src: app/src/Checks.php:6].

A schedule says this check, this often, by this time [src: app/src/Checks.php:7], from which a due list can be derived for any date and published as a calendar feed [src: app/index.php:121].

There is deliberately no cron job. Due-ness is computed from the schedule and the log at the moment you read it, and the reasoning is worth understanding: a missed check is not an event that has to be caught as it happens — it is the absence of a matching log entry, and that absence is just as visible tomorrow as it was at 09:01 [src: app/src/Checks.php:10].

The practical consequence is that nothing can be lost because a scheduled task failed to run, and an installation that was switched off for a week still shows exactly which checks were missed.

A check counts as done because a matching record exists, not because somebody ticked a box.

Bank holidays

If a date is an England and Wales bank holiday, the sign-off card asks whether the kitchen was shut rather than assuming it [src: app/controllers/app.php:277]. The source describes the behaviour as "offered, never assumed", and the intent is to save a manager explaining a red day later.

The holiday list is England and Wales only [src: app/src/FoodSafety.php:371]. Scotland, Northern Ireland and every other jurisdiction differ, and the prompt simply will not appear on their holidays. It changes nothing but that prompt — no status, no deadline and no rule depends on it.

Users and roles

Three roles [src: app/src/Perms.php:17]. The source names the line it draws, and it is the right one for this product:

who can change what "safe" means. Kitchen staff record readings and the corrective action they took; only a manager edits a threshold, signs off a day, or verifies that a corrective action worked. Moving a threshold retroactively turns yesterday's failures into passes, which is precisely what an inspection is looking for [src: app/src/Perms.php:5].

This table was produced by executing the product's own permission function against every permission the routes ask for.

Permissionviewermemberadmin
dashboard.viewyesyesyes
logs.viewyesyesyes
equipment.viewyesyesyes
reports.viewyesyesyes
schedules.viewyesyesyes
logs.create—yesyes
entry.photo—yesyes
actions.verify——yes
day.signoff——yes
equipment.manage——yes
schedules.manage——yes
settings.view / settings.manage——yes
team.view / team.manage——yes
audit.view——yes

Note that verifying a corrective action and signing off a day are both admin-only, which is the docblock's rule enforced rather than merely stated. Grants below admin are enumerated rather than wildcarded [src: app/src/Perms.php:11].

Backups are admin-only

Both /backup.json and /backup.sqlite need the settings permission, which only an admin holds [src: app/controllers/api.php:320], [src: app/controllers/api.php:326]. Before 3.1.5 they were gated by sign-in alone, so a viewer could download them.

The API and agent access

Five tools are exposed to an agent, of which two write [src: app/controllers/v3.php:24]: the monitored equipment, the open corrective actions and a compliance report on the read side; recording a reading and closing an action on the write side.

The instructions given to an agent are the plainest in the catalogue, and they matter:

An out-of-range reading cannot be saved without a corrective action — that refusal is the product working, not an error to route around. Safora documents records; it does not certify compliance [src: app/controllers/v3.php:22].

Temperatures may be sent in Fahrenheit and are converted on the way in [src: app/controllers/v3.php:21], so an agent reading a probe in °F never has to do the arithmetic itself.

Recording a reading from something other than a person

Safora does not talk to probes or sensors — there is no driver and nothing polls hardware.

It does, however, accept a reading over its own API: POST /api/readings [src: app/index.php:178], and record_reading over the agent endpoint [src: app/controllers/v3.php:57]. Anything that can make an authenticated HTTP request — a sensor gateway, a script, a building-management system — can therefore put a reading into the diary.

A reading posted without source keeps the person's rule: out of range with no corrective action is refused [src: app/src/FoodSafety.php:183]. A reading posted with "source": "sensor" — a probe cannot know what was done about a warm fridge — is stored as an open breach instead [src: app/src/FoodSafety.php:198]: the day turns red [src: app/src/FoodSafety.php:241], the breach chase picks it up, and a manager cannot verify it until a person records the corrective action on the Corrective actions screen [src: app/src/Checks.php:220], [src: app/index.php:132].

Worth being precise about the distinction: Safora does not connect out to sensors, but it does accept readings in.

What Safora does not do

It does not certify compliance [src: app/src/FoodSafety.php:14], and it is not food-safety advice. It documents what you recorded.

It does not decide your thresholds. The defaults are UK-derived and every one is configurable [src: app/src/FoodSafety.php:24]; several say so in the source and tell you to verify them locally [src: app/src/FoodSafety.php:29].

It does not chase you in real time. There is no cron and no alarm at the moment a check becomes late — the absence shows on the day's record and stays visible afterwards [src: app/src/Checks.php:10].

It does not know your country's holidays. England and Wales only, and only to offer a "were you shut?" prompt [src: app/src/FoodSafety.php:371].

It does not let a bad reading through quietly. Out of range without a corrective action is refused, for people and agents alike [src: app/src/FoodSafety.php:179].

← Back to Safora · Quickstart · API · Test run

Affiliate program
Recommend tools people own — earn 35% on every sale. 90-day tracking, instant delivery, payouts by Lemon Squeezy.
Become an affiliate →