Security
Security you can check.No smoke and mirrors.
A trust registry is only as strong as what it refuses to leak. This page explains, in plain language, exactly how TheHumanBehind protects the data behind it, and what we deliberately never store. Everything here matches how the system is actually built.
- Your email is never public
- The database itself rejects any change to the date or the hash, including changes made by our own administrators
- No ID documents, no biometrics
- Infrastructure in the EU
The database defends itself
The protection is not a promise in the application code. It's enforced by the database, at the lowest level, for every query.
Row-level security on every table
Every table in the registry has row-level security (RLS) enabled. Anonymous visitors can read public records only, never drafts, never removed data, never internal tables. The database itself enforces these rules on each query, so even a bug in the application cannot bypass them.
Your email is never exposed
Your email lives only in the authentication system. It is not even a column in the records table, so there's nothing to leak into a public record, the directory or the API. Claim messages, which do contain an email, are locked to administrators only.
Your number and your date, untouchable for us too
Once a record is sealed, its THB number and its registration date cannot be changed from any account the application uses, including our own administrators: a database trigger rejects the attempt every time. The SHA-256 fingerprint always follows the current content, and every previous version stays archived forever in an append-only ledger, so an edit is visible rather than silent. What that constraint can't rule out is someone with direct, privileged access to the underlying infrastructure bypassing it, and we won't pretend otherwise. That's why the hash has a public recipe anyone can recompute, and why, every day, the whole registry is anchored to OpenTimestamps and to two independent timestamp authorities: services we do not control, on infrastructure we do not own. From that point on the date is no longer ours to move, and you can check it without asking us.
One public surface, one public view
The public record page, the directory and the API all read from a single public view that contains the public fields of a record and nothing else. Internal identifiers, account data and verification references are excluded structurally: they aren't filtered out, they're simply not there.
Try to rewrite history
This is not a policy document. It's a database constraint. Any update that touches the sealed fields fails with the same error, whether it's run by the owner or by our own administrators:
update records set registered_at = now() where slug = 'laia';
-- ERROR: immutable_columnsEverything you send is checked at the door
Registrations, claims and the contact form all pass through the same discipline before anything touches the database or an inbox.
Validated on the server, every time
Every field is checked again on the server with a strict schema: type, length and format. The checks in your browser are there for comfort, not for trust. If a value doesn't fit the rules, it's rejected before it goes anywhere.
Parameterised queries, always
The database is queried through bound parameters, never by gluing your text into a query string. That single habit is what closes the door on SQL injection: your input is treated as data, never as commands.
Your words are escaped, never executed
Anything you submit that later appears on a page or inside an email is escaped first. A message can't smuggle in a script (no cross-site scripting) and can't sneak extra headers into an email (no header injection). Text stays text.
Throttled and screened
Form endpoints are rate-limited and screened for bots, so nobody can hammer them or flood an inbox. Outbound requests only ever reach two fixed, known services, so a submission can't be turned into a request to somewhere it shouldn't go.
What we never store
The safest data is the data that was never collected. Minimisation is a design rule of the registry, not a preference.
- The public fields of your record: name, type, where it operates, responsible person
- Your THB number, sealed registration date and SHA-256 fingerprint
- Your account email: private, used only to sign in and contact you
- For verified records, once verification opens: the result of the identity check, its date and a session reference
- Your ID document, or any copy, photo or scan of it
- Biometric data of any kind: no face templates, no voice prints
- Tracking or advertising profiles: audience measurement is cookieless and anonymous
- Passwords in readable form: authentication is handled by Supabase Auth
Identity checks are carried out by Stripe Identity, on Stripe's infrastructure. TheHumanBehind never sees or stores your document: our database has no place to put it.
The edges are guarded too
From the network to the sign-up form, the boring parts are covered.
EU infrastructure
The site is served through Cloudflare (hosting, CDN and DDoS protection). The registry database runs on Supabase, on Postgres hosted in the European Union (eu-west region).
Cookies that scripts cannot read
This website sets no tracking cookies at all. Visits are measured with Cloudflare Web Analytics, which uses no cookies and builds no identifier for your browser. On the registry platform, session cookies are HttpOnly, invisible to JavaScript, and scoped strictly to the platform domain.
Bots hit three walls
Sign-ups and claims are protected by a honeypot field, a minimum-time check and Cloudflare Turnstile. All three are validated on the server, so client-side tricks don't help.
Removal leaves a trace, not a hole
Records are never hard-deleted. If you unpublish yours, it disappears from the directory but the registry keeps minimal proof that it existed and was removed, so a number can never be silently reused by someone else.
Where the secrets live
There is a backend, and that is the point: the sensitive work runs on our servers, never in the page you download. This is the line between the two.
Your browser only holds public keys
The only database key that ever reaches your browser is the publishable one, and it can do nothing that row-level security does not already permit. The privileged key that could bypass those rules never leaves the server.
Secrets stay on the server
The keys for email, identity checks and bot verification live only in server-side environment variables. View the page source and search the bundle: they are not there, because they never ship to the browser.
Locked down in transit
Every request travels over HTTPS, with HSTS so a browser refuses to fall back to plain HTTP, and a strict content-security-policy that limits what a page is even allowed to load or connect to.
Least privilege, by default
Each part of the system reaches only what it needs: the public site reads a single read-only view, your session touches only your own rows, and an administrator sees only the narrow slice a task requires.
An honest note
No system is unbreakable, and we won't pretend this one is. What we can promise is concrete: we collect very little, we keep no sensitive documents that would be worth stealing, every input is validated and escaped on the server, and the database enforces its own rules even against us. Traffic runs over HTTPS and our secrets never reach your browser. If you find a vulnerability, please tell us. Write with “Security” in the subject and we'll respond as fast as we can.