Row-level separation, everywhere
Every table carrying customer data has row-level security switched on — all 125 of them — governed by 409 individual policies. A query that forgets a tenant filter returns nothing rather than someone else's data.
Inspection records are legal documents. This page describes exactly how they are protected — and every item on it is something your IT team can verify, not something we are asking you to take on faith.
Access rules that live in application code can be bypassed by any path that forgets to call them. Ours live in the database, so every path is covered by default.
Every table carrying customer data has row-level security switched on — all 125 of them — governed by 409 individual policies. A query that forgets a tenant filter returns nothing rather than someone else's data.
97 of those policies are restrictive. They combine with every other policy using AND, never OR. In plain terms: even a rule that said "allow everyone" could not open a door, because the restrictive layer still refuses to let one company's data cross into another's.
Public web applications ship an API key to the browser. Ours holds direct table permissions on exactly one relation — and that one is a view which evaluates the signed-in person's own permissions rather than the owner's. Signed-in users have access to 861 by comparison.
Each customer gets their own address. A request for a workspace that was never provisioned is turned away before the application loads at all — not shown an empty login form.
This is the one that matters most in our industry. If a report has gone to a client or a building department, it needs to still say what it said.
Once a report is approved or released, the lock is enforced by the data layer itself — not by a button being hidden. Every field is compared individually, and the only change an ordinary user can still make is adding the client's countersignature.
An attempt to alter a locked report fails outright:
Approved or released reports are locked.
Create a revision or use reviewer/admin workflow.
Database triggers — not application code that could be skipped — record report releases, signatures and PDF replacements; role changes; invoice status changes; billing credential rotations; billing access grants; and document deletions.
A document delete writes its audit record before the delete happens, so the evidence cannot be removed by the same action.
Six levels, from internal through customer-confidential to restricted-financial and restricted-legal, enforced by a database constraint. New documents default to the protective value, not the permissive one.
These are live counts from the production system, not a description of what the design allows.
The administrative audit log, the sign-in log, the portal access log and the document access log have read permissions only. No signed-in account — yours, ours, or an administrator's — holds permission to write or delete a row. Only server-side processes append.
A company administrator sees their own company's administrative records and no one else's.
Every access is recorded as one of: view, download, signed-URL issue, upload, update, delete, restore, release, signature, export. The list is enforced by a constraint, so an event cannot be logged under an invented label.
Administrator, dispatcher, coordinator, project manager, inspector, biller, business development, and contractor. Billing portal users sit on a separate axis entirely — someone who can see invoices does not thereby get project access, and the reverse is also true.
Seeing a project does not mean seeing what it is worth. Financial visibility can be granted per project, and payroll is administrator-only unless an administrator grants it to a named person — a biller does not get payroll by default.
Every session ends after 12 hours, without exception. Inactivity limits differ by surface because the work does:
Password sign-in locks for 15 minutes after 5 failed attempts. SAML single sign-on through your own identity provider is supported and configured per customer; no customer is using it today.
Your clients and contractors sign in here without an account on our platform, which makes it the surface most worth hardening.
Only a PBKDF2-SHA256 hash at 210,000 iterations with a unique per-credential salt. If a client loses their code we issue a new one — we cannot look up the old one, because nobody can, including us.
A bot check runs before any code is compared. After 5 failed attempts in 15 minutes, access pauses — counted per project and per network address, whichever is higher, so neither axis can be used to hide behind the other.
If the system cannot count failures, it treats that as being at the limit rather than below it. It fails closed.
A wrong code and a project number that does not exist produce the same message after the same deliberate delay. There is no way to use the login form to discover whether a project exists.
Portal access attempts are recorded against a one-way SHA-256 hash of the network address. The address itself is never written down.
This platform does not collect payment credentials on any screen. That belongs on a payment processor's own hosted page. We store remit-to details for invoicing and nothing more.
Everything in this section is visible from outside. You do not need our cooperation to confirm it.
HTTPS is enforced with HSTS including subdomains and preload. A full Content-Security-Policy restricts what the browser may load and forbids the site being framed. MIME-sniffing is off, referrer policy is restrictive, and camera, microphone, payment and USB access are switched off outright.
curl -I https://inspectionsmanager.com
A liveness endpoint at /healthz and a readiness endpoint at /readyz, which returns an error status when the data layer is unreachable. Every response carries a request ID for support correlation.
Internal data files cannot be fetched over HTTP. The rule works by path class with a short allow-list, so a new private file is protected the day it is added rather than the day someone remembers to add it to a list.
Address validation and geocoding run server-side specifically so that the credentials for those services stay on our infrastructure and out of your users' browsers.
Data integrity, access rules, document parity and asset addressing are all re-verified before anything reaches you. If any check fails, the deploy stops.
A correct repository is not the same thing as a correct deployment. Our final gate reads what production is actually serving rather than trusting what the code says it should be.
Cached files are addressed by a hash of their contents, so a cached file can never turn out to be the wrong version of that file.
Projects, orders, reports, NCRs and RFIs, invoices, users, billing accounts, portal access history and audit history — as structured data with a manifest listing row counts and a SHA-256 checksum for every file. Attachments included.
Passwords, access codes, tokens and API keys are removed from the export by a filter that runs over every field, rather than by remembering to exclude them.
Exports can be delivered AES-256-GCM encrypted. Every export request is recorded.
The full list, including the optional services that are only contacted on particular screens, is maintained alongside the code and available on request.
Hosting, edge delivery, DNS and TLS. All application traffic passes through it.
Database, authentication and file storage. Your application data lives here.
Transactional email — assignment notices, portal links, invoice notifications.
Address validation. Contacted from our servers, never from your users' browsers.
Send us the questionnaire. We answer them directly, and we can walk your IT team through any control on this page.
This page is maintained alongside the code, so it reflects what is actually running.
Get in touch