Trust

Security

Written to be checked, not admired. Every claim below corresponds to a control we can demonstrate on request.

Tenant isolation

TrainGridis multi-tenant, and separating one organization's data from another's is the control everything else rests on. Every tenant table carries an organization id and has PostgreSQL Row Level Security enabled: policies restrict every read and every write to organizations the signed-in user actually belongs to. That enforcement lives in the database, beneath the application, not in application code alone.

Privileged database functions run with a pinned search path and check membership before doing any work. A small number of server-only workflows use a privileged credential that can bypass row-level security; those paths also enforce organization checks in application code and get focused security review. We won't claim an application bug is incapable of causing exposure — no honest security statement can.

Isolation is re-tested on every change. Our regression suite impersonates real users at the database level and asserts that cross-organization reads and writes return zero rows, including for deactivated accounts.

Authentication, roles and scoping

Roles. Administrator, Manager, Training Coordinator, Supervisor and Auditor (read-only), plus optional custom roles that may only ever restrict their base role and never exceed it.

Capabilities — import, archive, delete, record completions, export, billing and others — can be turned off per role. Enforcement is layered across server actions, database policies and guarded database functions according to the operation; these are not merely hidden buttons.

Location scoping limits a signed-in supervisor to their own site, in the application and in the exports available to their session.

Account creation is invite-only. Direct calls to the authentication API from outside the product are rejected unless the email holds a live invitation. Passwords require a minimum of 8 characters and are stored salted and hashed by the authentication provider — TrainGrid never sees them. Deactivating a login revokes database authority immediately, not just interface access. Single sign-on (Microsoft Entra ID) is available and can be enabled during onboarding.

Encryption

In transit. HTTPS/TLS is used for browser-to-application, application-to-database and application-to-storage connections. The exact TLS version is negotiated with each managed platform rather than fixed by TrainGrid. HTTP Strict Transport Security is enabled with a two-year max-age and subdomains included.

At rest.Database volumes, backups and uploaded files use our managed providers' encryption-at-rest controls.

Append-only audit log

An append-only audit log records who did what, to which record, and when — including before and after values. Browser credentials cannot insert, edit or delete audit entries.

Training records can be corrected or deleted only by users holding the relevant capability, and changes made through the application are recorded rather than being silent. An assignment cannot be moved between employees, courses or organizations by an ordinary edit. The audit log exports to CSV for your own retention.

Recording a completion is the one write that can only be made one way. Completions go through the completion routine, which writes the audit entry and creates the next occurrence of recurring training; the database refuses a completion written any other way — so the evidence trail and the recurrence schedule do not depend on which client made the request.

To be precise about the boundary: signed-in users hold scoped row-level access to their own organization's data, so a determined member using their own credentials could change a record they are already permitted to change without the application writing its audit entry alongside it. What they cannot do is exceed their permissions, reach another organization, alter an existing audit entry, or record a completion outside the audited routine — those are enforced in the database.

Files and attachments

Attachments — signed class rolls, certificates, licences — are stored in a private bucket, addressed under the owning organization, and are readable only through short-lived signed links issued to users whose role and location scope permit it. Uploads are limited to 10 MB per file and to document and image types.

Infrastructure

The database, authentication and file storage run on Supabase-managed PostgreSQL in the Canada Central (ca-central-1) region. The application is hosted on Vercel as immutable deployments that can be rolled back to a prior release. Transactional email is delivered by Resend, and subscription billing by Stripe — TrainGrid never stores card numbers.

Choosing a Canadian database region locates the primary database and file storage in Canada. It is not a promise that every processor handles every copy only in Canada: application requests are processed by Vercel and email content by Resend, including in the United States or other locations permitted by their terms. See data protection for the full subprocessor picture.

Backups and recovery

Backups run nightly and encrypted, and cover both the database and the uploaded files. That second half matters more than it sounds: managed database backups contain metadata about your files but not the files themselves — and the files are the audit evidence.

Restores are tested, not assumed: we have restored from a real backup artifact end to end. Application releases are immutable and can be rolled back independently of the data.

Secure development and hardening

Every change runs a full gate before release: type checking, linting, the unit suite, database and row-level-security regression suites, and an end-to-end browser suite. Production dependencies are audited automatically and the release gate fails on a high-severity production advisory.

Security headers are enforced on every response — a Content-Security-Policy, frame denial, MIME-sniffing protection, a referrer policy and a permissions policy — and the server does not advertise its framework. Outbound webhooks are protected against server-side request forgery: private, loopback, link-local and cloud-metadata addresses are refused, and the validated address is pinned for the actual request to defeat DNS rebinding.

To be clear about what we do not claim: TrainGrid holds no SOC 2 or ISO 27001 certification and has not been through a third-party penetration test. The controls above are ones we test ourselves and can demonstrate.

Incident response

If we become aware of a security incident affecting your data we will notify your organization's administrators without undue delay, consistent with applicable breach-notification requirements — with what happened, what data was involved, what has been done, and what we recommend you do. A written post-incident report follows.

Reporting a vulnerability

If you believe you have found a security issue in TrainGrid, email support@solvesoftcorp.com with enough detail to reproduce it. We will acknowledge your report, keep you updated while we investigate, and we will not pursue action against researchers who report in good faith, avoid privacy violations and data destruction, and give us a reasonable chance to fix the issue before disclosing it.

Related reading: data protection and our Privacy Policy.