The record has to be trustworthy, or none of it counts.
Veristep has the controls a serious security review asks about: a full audit trail, each firm's project data kept apart, a history nobody can rewrite, and the right people seeing the right things. They're enforced, not just promised. The register below says exactly what's proven, what's built, what's optional and what isn't there yet.
The record can't be faked
The same rules that keep quality honest are the security boundary. A required step can't be skipped, a closed record can't be edited, and evidence can't be back-dated — not from the office, not from the field, not through the API. There is no screen to go around, because the rule isn't on the screen.
Your project data stays separated and protected
One organization can never read another's data, and that isn't a claim: an automated test signs in as each kind of person and proves that reading another firm's records, forging evidence and promoting yourself all fail.
The history doesn't disappear
Events, audit entries and closed-check evidence can only be added to — they cannot be edited or deleted by anyone, including an administrator. Mistakes are corrected by adding a new, attributed, logged entry, never by overwriting the original. The audit trail even outlives the account it describes.
Any change to the record is detectable
Every entry is sealed against the one before it, forming an unbroken chain. Alter or remove a single entry and the chain no longer checks out, so any tampering shows — and the whole trail can be re-verified end to end at any time, inside the platform or from your export. (The engineering detail is on the technical pages.)
Every action is recorded — who, when and why
Routine work runs on its own; anything high-risk waits in a human approval queue to approve, refuse, or edit. Every action — who did it, when, and why — is recorded, and the AI assistants are ones you can actually watch: a live activity log shows what each one did and the exact machine or document it acted on, filterable to a single assistant. An auditor can ask about anything and get an answer.
GPS-verified presence
Clock-ins are checked against the job-site geofence, and evidence for restricted equipment can't be recorded unless the device is physically on site. Our server works out the distance itself, so a device can't just claim it was there.
A record you own
The chain of custody is yours, exportable at any moment on every paid plan, and Veristep never holds a dollar — billing hands off to your own books. What we deliberately don't store matters too: site access is captured as requirements and named contacts, never the codes, keys, or clearance secrets themselves.
We have tests that would fail if any of this weren’t true.
A standing set of stress tests tries the attacks a real attacker would — reading another firm’s data, closing a check with no evidence, deleting the steps that block a close, forging a pre-satisfied record, poisoning the audit log, escalating privilege. Every one must fail before anything ships. Security isn’t a feature bolted on; it’s the shape of the platform.
Where things stand, in the words your reviewer uses.
Four states, no fifth. Proven means an automated test would fail if the claim were untrue. Built means it is in the code and you can read it. Opt-in means it’s there, but it isn’t enforced until you turn it on. Not yet means exactly that. Nothing on this list is ahead of what’s true today.
| Control | Status | What you can rely on |
|---|---|---|
| Each firm's data kept apart | Proven by tests | One firm can't see another firm's records. The database checks every row on every table, so neither the app nor a stolen login token hitting the API directly can read around it (row-level security). In the tests, an organization administrator reads zero rows of another workspace across the register. Proof: test/tenancy.test.mjs, test/stress.test.mjs — run against the real migrations, offline |
| Nothing answers a stranger | Proven by tests | Every way into the system checks who's asking before it answers. Nothing is reachable without signing in, except what's meant to be public, like the tour. (No database function is callable with the public key unless a row-security policy, a view, the storage resolver or the public tour needs it; every function a session can call checks who is asking. A test creates the three Supabase roles and asserts the list.) Proof: db/080 · test/function-exposure.test.mjs |
| Audit trail | Proven by tests | Every business event, every AI decision and every sign-in is written once and can only be added to, never changed (append-only). Not even a database superuser can edit or delete one. Each event is sealed to the one before it with a SHA-256 hash, so the whole chain can be re-checked end to end. Proof: db/001, db/041, db/069 · test/audit-chain.test.mjs, test/stress.test.mjs |
| Evidence integrity | Proven by tests | A required step can't be skipped, a check can't close while a step is still open, and closed evidence is frozen. The database enforces it (with triggers), not the screen. Proof: test/stress.test.mjs, test/enforcement.test.mjs |
| Role-based access | Built | Three levels of access: platform, organization and per project. A field role on one job gives nothing on the next. Outside parties (clients, subs, vendors) only reach the projects they were explicitly given. Proof: 01-product/architecture/ROLES.md · db/058, db/075 |
| Multi-factor authentication | Built, opt-in | Two-factor codes from an authenticator app are built in; once someone turns it on, a password alone won't get them to any page inside — they're asked for the code first (TOTP, Supabase Auth AAL2 step-up). Anyone can turn it on for themselves, and a firm's administrator can require it for the firm's administrators and managers, or for all of its staff. It is off until a firm turns it on. Once required, a person who hasn't set it up is sent to set it up before any other screen, and the database itself refuses a session without the code the writes that grant or change access — adding or removing people, changing roles, API keys, and the rule itself. Once someone has an authenticator, the database treats a password-only session as nobody: it can read and change nothing, by any route, until the code is entered. Someone who is required to set it up but hasn't yet is held back by the screens until they do. Proof: db/142, db/187 · test/required-two-factor.test.mjs (the database refusals with and without the code; the screen redirect is text-checked, not exercised against a live authenticator) · test/two-factor-everywhere.test.mjs (a password-only session on an account with an authenticator reads nothing; with a stubbed factor table) · src/lib/auth.ts, src/lib/supabase/middleware.ts |
| Single sign-on | Built | Single sign-on with your company's own login provider, set up per firm on request (SAML 2.0 through Supabase Auth, per firm, enabled by Veristep on request; identity only, access is still granted per person). An organization's administrator asks with the firm's own email domains and its identity provider's metadata URL; a person from Veristep registers the provider and confirms. Signing in with the company login proves who someone is — it never adds them to a workspace. Proof: db/114 · test/sso.test.mjs (the request, the enabling, the sign-in screen's question; the browser round-trip to an identity provider is not exercised offline) |
| Encryption in transit | Built | Every connection is encrypted, and browsers are told never to connect without it. (TLS on every connection through Vercel's edge and Supabase; HSTS preload header shipped.) Proof: next.config.ts headers |
| Encryption at rest | Built | Your data is encrypted wherever it's stored (Supabase, AES-256), and your QuickBooks connection gets a second layer of encryption on top, so those tokens sit scrambled even inside the database, behind row security that lets no one read them. (QuickBooks OAuth tokens: application-layer AES-256-GCM on top of deny-all row security.) Proof: src/lib/qb.ts |
| Browser protection and rate limits | Built | The site is locked down against common browser attacks and can't be embedded in other sites. Sign-ins, password resets, QR scans, trial sign-ups, contact requests and the assistant are rate-limited, so repeated guessing gets cut off. (Strict Content-Security-Policy, frame-ancestors none, nosniff, scoped Permissions-Policy; database-backed rate limits shared across every serverless instance.) Passwords are twelve characters or more, and a lost-password request gets the same reply whether or not the address exists, so it can't be used to find out who has an account. Proof: db/026, db/074, db/099, db/100, db/106 · test/security.test.mjs (eleven failures in fifteen minutes trips the throttle), test/profile.test.mjs |
| Threat monitoring | Built | A security watchdog (the sentinel) looks for five suspicious patterns and raises alerts, scored by risk, for a person to act on: bursts of sign-in attempts, someone scanning QR codes in bulk, dormant accounts waking up, an AI assistant drifting from its usual work, and activity at hours that are unusual for that particular person. (Five transparent SQL rules over append-only signals.) Proof: db/026, db/027 · test/stress.test.mjs |
| Data residency | Built | Your database, files and sign-in system run on Supabase in AWS us-east-2 (Ohio). The app runs on Vercel, with its server functions in the Cleveland region, next to the database. No data is stored outside the United States. Proof: app/vercel.json |
| Data export and deletion | Built | Every record as CSV and every file as one archive, on demand for customers and for ninety days after a plan ends. Then the workspace is archived, unopened and undeleted, for two years, and can be reactivated in place. Closing a workspace removes files and access; the audit trail, which can only ever be added to, stays sealed and unreachable rather than deleted. That's stated in the terms, not hidden. Proof: db/079 · test/plan-doors.test.mjs · /trust/terms §10 |
| Backups | Built | The database runs on Supabase Pro, which takes a full backup every day and keeps seven days of them. Files and the sign-in system are on the same platform. Ask and we'll tell you the current schedule. |
| Point-in-time recovery and a rehearsed restore | Not yet | Restoring to any exact second (rather than to the last daily backup) is a Supabase add-on we've chosen not to turn on yet, and we haven't rehearsed a restore on a cloned project. Both are on the list, and we'll say so here when they're done. |
| Incident response | Not yet | If you find a security problem, there's a published contact for reporting it (/.well-known/security.txt), and the sentinel plus the audit trail give the forensic record. A written incident-response runbook with notification timelines isn't finished. |
| Vulnerability management | Not yet | Before we push a change we run the type check, the lint, the whole test suite and a production build, and sign in as every role to open each screen. The same full check runs on our build service when we start it (CI) — it no longer runs on its own for every push or every night. Automated scanning of the third-party code we depend on isn't part of any of that yet; we audit dependencies by hand today. |
| Penetration test | Not yet | We haven't commissioned an outside penetration test (a hired firm trying to break in). Our own internal stress tests aren't a substitute, and we don't present them as one. |
| SOC 2 | Not yet | There's no SOC 2 report. The controls above are the ones an auditor examines; the audit itself is a later step, and we'll say when it's scheduled, not before. |
| Service level agreement | Not yet | We don't publish or promise an uptime percentage. Availability follows Vercel and Supabase; a written SLA comes with a program agreement, not the list price. |
Last reviewed 2026-09-15. The proof column names files in our codebase; if you’re a customer under agreement, we’ll walk you through any of them.
Who touches your data, and when.
Six companies, all in the United States. Nobody else sees your records. When this list changes, every workspace administrator hears about it first.
Supabase
their terms- What
- PostgreSQL database, file storage, authentication
- Where
- AWS us-east-2 (Ohio), United States
- When
- Always — this is where the record lives.
Vercel
their terms- What
- Application hosting and edge network
- Where
- United States (global edge for static assets)
- When
- Always — every page and API call is served through it.
Google (Gemini API)
their terms- What
- The language model the AI assistants draft with, and the Ask box answers with
- Where
- United States
- When
- When an AI assistant runs, and when a signed-in person types a question to the assistant. It receives the text needed for that draft or that answer — the records being reasoned over, the question, and the names of the pages and actions that person may use — and nothing else. Which model is in use is a configuration we can state on request.
Resend
their terms- What
- Transactional email — sign-in, password-recovery and email-change mail, the trial welcome, plan notices, message and mention notifications, lead notifications, and any email an AI assistant drafts and a person approves
- Where
- United States
- When
- When a message is sent. It receives the recipient address and the message text, nothing else. Sent from hello@veristep.app under DKIM, SPF and DMARC.
Intuit (QuickBooks Online)
their terms- What
- Invoice push and status sync
- Where
- United States
- When
- Only if your organization connects its own QuickBooks. Tokens are stored encrypted and never leave your workspace.
Stripe
their terms- What
- Card payments, subscriptions and invoices for what your firm pays Veristep
- Where
- United States
- When
- Only when your firm pays by card or by invoice. It gets your firm's name, the billing email, and the amounts and project counts on each bill. Your card number goes straight to Stripe's own payment page and never passes through Veristep. None of your project records go to Stripe.
Boundaries a reviewer should know about.
No payments, no payroll
Veristep never holds a dollar. It prices proven work and hands the invoice to your own QuickBooks; hours go to your own payroll provider. That means less to attack, and no financial regulator in the picture.
No door codes, keys or clearance secrets
Site access is recorded as requirements and named contacts — never the code, the combination, or the key number. A breach of Veristep cannot open a door.
No autonomous high-risk action
The AI assistants draft; a named person approves anything consequential. This is enforced in the running system, and no workspace can configure it away. The assistant in the Ask box is the same: it shows what it understood on a card, and only after you confirm does it act — as you, with your permissions, through the same checks the form runs.
No certification of any kind
Veristep holds no professional licence and inspects no machine. It records what your people attest to, and refuses to close a check without the evidence they promised.
Bring your hardest questions.
Send us your security questionnaire. We’ll answer every line from the register above, with the same four words, and we’ll say “not yet” where it’s not yet.
