Trust & security

What is actually built — and what isn't.

Roots HQ is a small platform. What follows is what is actually built, what is done by hand, and what does not exist — with the code behind each claim named, so you can ask us to show you.

17
controls in place
7
with stated limits
3
we do not offer
6
things we don’t claim

Roots HQ is a small platform run by the people who build it. Everything below describes how the system is built. None of it is a certification, an audit result, or a service-level agreement, and nothing on this page has been through outside counsel.

Tenant isolation

One workspace cannot read another’s data. This is the control everything else rests on.

Every query is scoped to one tenant

In place

Tenant scoping is applied by a database-client extension rather than by each query author. Models holding tenant-owned data are listed in one place, and a read or write against one of them without a tenant in context does not fall back to “all tenants” — it is constrained or rejected.

api/src/config/database.ts · api/src/middleware/tenantContext.ts

An unrecognised domain is refused, not guessed

In place

A request arrives on a hostname, and that hostname is looked up to decide which workspace it belongs to. A hostname that is not registered is rejected. It does not fall through to a default workspace, which is the failure mode that turns one misconfigured DNS record into a data leak.

api/src/middleware/tenantContext.ts · api/src/platform/domainProvision.ts

Platform staff sign in separately from your team

In place

The people who run the platform authenticate through a separate identity system with its own roles. They are not members of your workspace and do not appear in your team list.

api/src/platform/auth.ts · api/src/lib/adminSso.ts

When support can look inside your workspace

With limits

Authorised support staff can open a time-boxed session against one workspace in order to help with it. Entering requires a specific permission, a written reason, and expires after 30 minutes. Read-only is the default; making changes needs a second, separate permission. Every entry is written to the platform audit trail with who, which workspace, which mode and why.

What it does not do

  • Support staff CAN see inside a workspace during such a session — we are not going to claim otherwise. What is controlled is who may do it, that they must say why, that it ends by itself, and that it is on the record
  • The audit trail of these sessions is not currently surfaced to the workspace owner in the admin

api/src/platform/router.ts · api/src/platform/support.ts

Signing in

Who can get an account, and what happens when someone tries repeatedly and fails.

Two-factor authentication (TOTP)

With limits

Any user can turn on TOTP two-factor for their own account. Once on, it is checked at every sign-in for that account.

What it does not do

  • Opt-in per user — a workspace owner cannot currently require it for everyone
  • TOTP only; hardware security keys are not an option for tenant accounts

api/src/routes/auth.ts

Changing a password signs that account out everywhere

In place

A password reset or change immediately invalidates that account’s existing sessions, so a stolen session does not survive the response to it.

api/src/routes/auth.ts

Repeated failed logins lock the account and then block the address

In place

Failed sign-ins are counted per account and lock it after a threshold. An address responsible for heavy failed-login volume is blocked automatically — deliberately platform-wide rather than only against the workspace it was aimed at.

api/src/middleware/rateLimiter.ts · api/src/routes/auth.ts

Who can reach the admin

Restrictions a workspace owner sets for their own team, independently of every other workspace.

Admin IP allow-list, set per workspace

In place

A workspace can restrict admin access to a list of IP addresses it controls. The list is that workspace’s alone. There is a guard against removing the last address you are currently connecting from, so the feature cannot lock its owner out.

api/src/lib/ipAllowlist.ts · api/src/routes/security.ts

Geographic restrictions, set per workspace

In place

A workspace can restrict admin sign-in by country. One workspace’s rules do not affect another’s.

api/src/routes/security.ts · api/src/routes/auth.ts

Role-based permissions

In place

Actions are gated by role, so a staff account does not automatically get owner-level abilities.

api/src/middleware/auth.ts

What gets recorded

What the system writes down when something security-relevant happens.

Audit trail for security-relevant actions

With limits

Sign-in failures, staff changes, password resets, two-factor changes, IP blocks and unlocks, security-setting changes and discount changes are written to an audit trail. A settings entry records WHICH setting changed and never its value, so the log itself cannot become the leak.

What it does not do

  • Covers security and money-affecting actions, not every read of every record
  • Retained in the primary database — there is no separate append-only or off-box audit store

api/src/middleware/audit.ts · api/src/routes/settings.ts

Every AI action is recorded before it is applied

In place

Sage writes what it was asked and what it proposed to an audit table. Its suggestions are recorded as proposals; applying one is a separate, human action.

api/src/routes/sage/index.ts

Your data

What is stored, what is encrypted, what leaves the server, and how long things are kept.

Stored credentials are encrypted with AES-256-GCM

In place

API keys, OAuth tokens and provider secrets are encrypted before they are written, using AES-256-GCM with a per-value initialisation vector. They are decrypted only in memory at the point of use, and secrets are never written to logs.

api/src/utils/crypto.ts · api/src/platform/secrets.ts · api/src/lib/masterCredentials.ts

Payment records, without card details

In place

Roots HQ provisions and operates your storefront, tracks orders and keeps your business records synchronised. Customer payments are processed through your own connected payment account, and you remain the merchant of record. Roots HQ stores order totals, the processor’s transaction reference, and payment and refund status — the operational record you need to run the business. It does not store raw card numbers, CVV, or equivalent cardholder data: those go from the buyer to your provider, and there is no column anywhere in the schema that could hold them.

api/src/routes/webhooks.ts · api/src/lib/invoicePayments.ts · api/prisma/schema.prisma

Payment webhooks are signature-verified

In place

Incoming payment webhooks are verified against the provider’s signature before anything is acted on.

api/src/routes/webhooks.ts

AI conversation history is deleted after 30 days

In place

Sage conversation history and its usage log are pruned to a 30-day window automatically, so the assistant’s record of your business does not accumulate indefinitely.

api/src/routes/sage/index.ts

Exporting your data

With limits

An owner can export the contact list and consolidated multi-channel sales as CSV. The export is admin-only and is itself written to the audit trail.

What it does not do

  • This is not a full account export — it covers contacts and sales, not every record in the workspace
  • There is no self-service “download everything and close my account” flow; ask and a human does it

api/src/routes/export.ts

Deleting a workspace

With limits

A workspace can be deleted. Deletion is performed by the platform owner rather than self-service, and it is recorded in the platform audit trail.

What it does not do

  • There is no self-service delete button, and no automatic export of your data before deletion — export first (contacts and sales CSV) or ask us to
  • No published timeline for removal of data from the most recent backups, which age out on the ordinary retention schedule rather than being purged on request

api/src/platform/router.ts

What platform staff can see across workspaces

With limits

Running the platform requires knowing whether commerce is working at all, so a platform-wide total — an order count and a summed seller GMV — is shown on the platform dashboard. It is genuinely aggregate: no individual order, customer or line item, and no per-workspace breakdown. It is restricted to roles holding billing-read permission, which support roles deliberately do not have, and viewing it writes an entry to the audit trail. That figure is sellers’ money taken through sellers’ own payment accounts — it is not Roots HQ revenue and is never presented as such.

What it does not do

  • Platform owners and billing roles can see an aggregate revenue total spanning all workspaces. If that is not acceptable for your business, raise it before you sign up rather than after
  • Support roles get workspace health and counts, but no seller financial figures

api/src/platform/router.ts · api/src/platform/audit.ts · api/src/auth/permissions.ts

Backups and availability

The least flattering section on this page, and the most useful one.

Nightly encrypted backups

In place

Every night the database, uploaded media, and the configuration needed to make a restore usable are dumped, encrypted with AES-256, and written to a root-only directory. A failed dump never replaces a good one — the file is renamed into place only after the dump exits cleanly. Fourteen daily copies and eight weekly copies are kept.

What it does not do

  • Backups and the encryption key are on the same host as the database. This protects a copied backup file; it does not protect against loss of the host, and it is not off-site replication

api/scripts/backupProduction.sh

Restores are tested, not assumed

In place

Once a week the newest backup is restored into a scratch database and its row counts are compared against the live database, then the scratch database is dropped. A backup nobody has restored is a hypothesis. The first time this ran it failed — which is the entire argument for running it.

What it does not do

  • Verification compares row counts on the main tables; it does not replay application behaviour against the restored copy

api/scripts/verifyBackup.sh · api/scripts/restoreProduction.sh

Restoring cannot overwrite production by accident

In place

The restore tool defaults to a scratch database. Restoring over the live database requires an explicit flag and typing the database name to confirm. The application role deliberately cannot create databases; the scratch database is created by a separate administrative account.

api/scripts/restoreProduction.sh

Disaster recovery

With limits

Restoring the database and media onto a working host is a tested procedure. Rebuilding the host itself is not automated — it would be done by hand from the configuration captured in the nightly backup.

What it does not do

  • No recovery-time or recovery-point objective is published, because none has been measured
  • No standby host, and no off-site copy — loss of this host means recovery depends on rebuilding one

api/scripts/backupProduction.sh

Public status page

Not offered

There is no public status page. If something is wrong, the honest way to find out today is to ask us, and we will tell you what we know.

What it does not do

  • No uptime history is published, and no historical uptime figure is claimed anywhere on this site

Incident response

Not offered

There is no published incident-response policy, and no contractual notification window. What happens in practice is that the people who build Roots HQ are the people who would contact you.

What it does not do

  • No documented severity levels, response times, or post-incident report commitment
  • Do not treat anything on this page as a service-level agreement — there is none

Breach notification

Not offered

There is no contractual breach-notification window. What we will actually do is tell affected workspaces what happened, what we know, and what we do not yet know, as soon as we understand it well enough to be accurate.

What it does not do

  • No committed notification timeframe. Do not treat this as a contractual undertaking

Reporting a problem

How to reach a human about a vulnerability, and what happens next.

Reporting a vulnerability

In place

Security reports go to the same address as everything else, marked “Security”. A machine-readable security.txt points at it. We will confirm receipt, and we will not threaten anyone who reports something in good faith.

marketing/public/.well-known/security.txt

Stated plainly, because silence reads as yes

Certifications Roots HQ does not have.

Plenty of vendors imply these by never mentioning them. If any of the following is a requirement for your business, Roots HQ does not meet it today, and you should know that before you sign up rather than during procurement.

SOC 2

No SOC 2 report exists. No audit has been performed and none is in progress.

ISO 27001

Not certified, and not pursuing certification today.

PCI DSS

Roots HQ is not PCI-assessed and does not need to be for the way it works: card details go directly to your payment provider, who is. Handing card numbers to Roots HQ is not possible — there is nowhere to put them.

Penetration test

No third-party penetration test or security audit has been commissioned.

A Data Processing Agreement

There is no standard DPA on the shelf. If your business needs one, ask — that is a conversation, not a download, and we will not pretend a signed document exists when it does not.

Legal review of these pages

The terms, privacy and acceptable-use pages were written by the people who built the product. They have not been through outside counsel.

Who else can see data

Subprocessors.

The distinction most vendor pages blur: nearly every integration here runs on credentials you supply. Connecting Square means your Square account, billed to you, under your agreement with them — not ours. Only the rows marked “Roots HQ” are on our account.

ProviderAccountWhat reaches them
Hosting provider
Runs the server the application and its database sit on.
Roots HQEverything, at rest. The database and uploaded files are on this host — not in a third-party object store.
Anthropic
Powers Sage, the assistant.
Roots HQ
Optional
The text of the question and the business context needed to answer it. Sent only when someone uses Sage.
OpenAI
Alternative model provider for Sage and receipt reading.
Roots HQ
Optional
As above — the content of the request being processed.
Stripe, PayPal, Square
Take card payments from your buyers.
Yours
Optional
Order and payment details. Card details go to them directly and never through Roots HQ.
EasyPost
Carrier rates, labels and tracking.
Yours
Optional
Delivery addresses and parcel details for shipments you create.
Twilio
Sends SMS on your own Twilio number.
Yours
Optional
Phone numbers and message content for messages you send.
Your email provider
Delivers the email your storefront sends.
Yours
Optional
Recipient addresses and message content. Roots HQ does not resell email sending.
eBay, Etsy, Meta
Marketplace order sync and social publishing.
Yours
Optional
Order and listing data for the channels you choose to connect.

Found something?

Reporting a vulnerability.

Report anything you find to hello@roots-hq.com with “Security” in the subject. Tell us what you did and what you saw; a proof of concept helps. We will confirm we received it. Please do not run automated scans against the live service, access an account that is not yours, or move data out of one — report it instead and we will take it from there. We do not run a paid bug-bounty programme.

hello@roots-hq.com · security.txt

Related: how the security model works · tenant isolation architecture · privacy · terms