Security
Server-side authorization, an audit log on every mutation, and a credential vault. This page is usually read by the person who can stop the purchase, so it is written for them.
1
Audit event per mutation
Written in the same transaction. No event, no change.
2
Layers of tenant isolation
An orgId on every table, and row-level security under it.
0
Credentials in the browser
Decrypted server-side at the moment of the call, never serialised.
4
Sub-processors, named
Most of the stack is ours, so the list stays short.
The short version
Written plainly, and with no claim we would not repeat in writing.
Authorization & audit
The prototype this product replaces kept its rules in the page, which is how rules get bypassed at six on a Friday. Here they live on the server, in one place.
Every server action
Each action asserts the caller’s permission for a module and a verb — view, create, edit, delete, approve or export — against the matrix in your database. A sales agent’s scoping to their own book is applied in the query layer, so it holds for exports and reports as well as screens.
A static test in the build fails if any exported action is missing the check. It is not a convention anyone has to remember.
Every mutation
Anything that changes a record writes an audit event in the same transaction. If the event cannot be written, the change does not happen. Administrative impersonation is audited like anything else, and cannot be done quietly.
The credential vault
Each tenant’s integration credentials — the FMCSA key, the load-board secrets, the ELD token — are encrypted against your organisation and referenced by the integration record rather than embedded in it. They are decrypted server-side at the moment of an outbound call and never serialised into a page, an API response or a client bundle. They are deliberately not in environment files either: environment variables hold Harbor’s own platform credentials and nothing of yours, so adding a tenant is never a server configuration change.
Where your data lives
Every part of the system runs on infrastructure we operate, in containers we can move. No vendor can hold your operating history, and no vendor’s outage becomes yours.
What runs it
What that means for you
What runs it
What that means for you
What runs it
What that means for you
What runs it
What that means for you
What runs it
What that means for you
What runs it
What that means for you
Because the whole system is a set of containers and two volumes, it runs wherever you need it to. The region is agreed before onboarding and written into the DPA — and on a single-tenant deployment it is an instance of your own, not a shared one with your rows tagged.
In transit: TLS on every connection, certificates renewed automatically, no unencrypted route in. At rest: the database and object-storage volumes sit on encrypted disks, and per-tenant credentials are encrypted a second time at the row level — so a copy of the database is not a copy of your provider accounts.

Backups & recovery
Freight records are the evidence behind an invoice dispute two years after the container moved. They are worth keeping properly.
Sub-processors
Self-hosting has an unglamorous benefit: very few third parties sit in the path of your data, and the ones that remain are named before you sign.
What it handles
Terms
What it handles
Terms
What it handles
Terms
What it handles
Terms
Not sub-processors, because they are ours: the database, the object storage, the job queue, the reverse proxy, error tracking and website analytics. They appear on no vendor’s list because there is no vendor.
Stated plainly
Harbor TMS does not hold a SOC 2 report or an ISO 27001 certificate today, and this page will say so until it does. A badge nobody has audited is worse than no badge.
What a reviewer can have now: this page in writing, a signed DPA, a completed vendor questionnaire, and — on a single-tenant deployment — a review of the configuration your data will actually run on.
Suspected vulnerabilities, exposed credentials and anything that looks like unauthorised access go to a monitored address, not a contact form.
We acknowledge it, establish the scope, and tell affected tenants what happened and when we knew. The audit log is what makes a scope statement possible rather than a guess — which is most of the reason it exists.