Security

Isolation by construction, not by convention

Most multi-tenant software keeps every customer in one database and separates them with a column and a promise that nobody forgets the filter. TrackSHEQ does not. Your organisation gets its own database, its own storage bucket and its own identity organisation, and there is no query we could write that would return another customer's rows.

What "your own" means, precisely

Four separations, each of them structural. None of them depends on application code remembering to add a filter.

A database per organisation

Provisioning creates a dedicated PostgreSQL database for your organisation and connects to it with credentials scoped to that database. Requests are routed to it by the host you arrived on. Cross-customer leakage is not a bug we guard against — it is a query with nowhere to run.

A storage bucket per organisation

Photographs, certificates, method statements and attachments live in a bucket of your own. Uploads and downloads go through short-lived pre-signed links rather than a shared public path, so a URL that escapes stops working.

An identity organisation per customer

Every customer gets its own organisation, project and application in the identity provider. Your users exist in your organisation and nowhere else; tokens issued for you carry your project as their audience and are not accepted anywhere else.

Authorisation scoped to your organisation

Roles and permissions are resolved against the organisation the request resolved to. A permission granted in one customer's workspace has no meaning in another's, and a route that needs a permission checks it server-side rather than hiding a button.

The evidence trail

An EHS system that cannot say who changed what is not evidence — it is a rumour with a database behind it.

Audit logging

Consequential actions are written to an audit log as they happen: the actor, the action, the target, and the time. It is written on the way through rather than reconstructed afterwards from application logs.

Lifecycle history

A workspace's lifecycle transitions — created, provisioning, active, suspended — are kept as an immutable trail with the reason attached, so "why was this account off in March" has an answer.

Attribution end to end

Records carry who created and last changed them. Draft states are held separately from submitted ones, so an in-progress report is never mistaken for a filed one.

Operational controls

The switches that exist, who can reach them, and what they do.

Per-customer module switches

Modules can be switched off for a customer, and a route belonging to a disabled module refuses the request rather than half-working. The core machinery — accounts, permissions, storage, notifications, audit log — cannot be switched off, because the product is made of it.

Country availability gate

Signups can be refused for an entire country where we are not able to operate. The gate is checked before anything is created, so a refused signup provisions nothing.

Suspension and wind-down

A workspace can be suspended — for non-payment or by decision — which stops it serving without destroying it, and the transition is recorded with its reason. Nothing is silently deleted.

Rate limiting on the public edge

The anonymous routes — signup, verification, the activation steps — sit in a tight rate-limit scope. Signup provisions nothing until the emailed link comes back, so squatting an address costs an inbox rather than an HTTP request.

How your first credential is created

The most sensitive minute in the whole product is the one where the first password is set. Here is exactly what happens.

Signup writes a row, and nothing else

No database, no bucket, no identity organisation. A stranger who types a name into a form cannot make us build anything.

The verification link proves the inbox

Single-use, and it expires within a day. An unknown, spent or expired link all answer identically, so the endpoint cannot be used to probe for live ones.

Redeeming the link is what builds the workspace

The redemption hands back a one-time setup token and starts provisioning in the same transaction. That token is the only copy that exists outside your browser, and re-opening an old email does not mint a second one.

You set the root password, holding that token

The provisioner creates the root account with a random temporary password nobody ever sees or transmits. Your real password is set by you, against the token, once — and a second attempt is refused.

Two-factor is offered before anyone else has an account

Authenticator-app enrolment happens during setup. Confirming it — or explicitly declining it — burns the setup token, which ends activation.

Ask us the hard questions

Security review, questionnaire, or an architecture conversation with the people who built it — we would rather have it before you sign than after.