Security

The architecture is the security model.

This page says what we actually do, in plain terms, including what we do not have yet. Every claim here is checked against the running system before it is published.

What we never receive

Most age verification means an ID document or a selfie, so the vendor ends up holding identity data. Tessio asks the EU Digital Identity Wallet for one claim, such as being over 18. The credential behind that answer, the EU age verification attestation, contains age booleans and nothing else: no name, no date of birth, no document number, no portrait.

That is the security model. There is no document store to breach and no retention policy to audit, because the identity data never crosses the wire. This is a property of the protocol, not a promise about our behaviour, which means you can verify it yourself instead of trusting us.

What we do store

Check outcomes: a yes or no per check, with your reference and timestamps. No personal data of the person being checked.

Your account: dashboard user emails and passwords. Passwords are hashed with Argon2id. Session tokens are stored only as SHA-256 hashes.

API keys: shown to you once, then only a SHA-256 hash and a short prefix are stored. Keys are revocable from the dashboard.

An audit log of administrative actions in your account.

Two step verification is available on every dashboard account (TOTP, RFC 6238, with single use recovery codes). It is a gate rather than a prompt: until the second factor is presented, a correct password produces a session that authenticates nothing. Codes cannot be reused, and attempts are rate limited per account as well as per source address, so guessing cannot be widened by changing address.

Where it runs

Production runs on dedicated infrastructure in Helsinki, Finland (Hetzner), inside the EU. All traffic is TLS. Data does not leave the EU.

Every tenant is isolated at the query level: each data access is scoped by tenant id, and cross tenant isolation is covered by automated tests that run on every change.

Webhooks you can verify

Webhook deliveries are signed with HMAC-SHA256 using your endpoint secret, with a timestamp in the signed payload so replays are detectable. The verification snippet is in the developer docs.

Endpoints must be HTTPS. A signature proves a delivery is genuine and unaltered, which is not the same as keeping it private, so we refuse plain HTTP endpoints rather than leaving that choice to you.

Availability and backups

Deploys are health gated with automatic rollback: a release that fails its health check never stays live.

Backups run in three independent layers, all inside the EU: a daily whole server snapshot, a nightly database dump kept on the server for 14 days, and an encrypted copy of every dump on separate storage that takes its own daily snapshots.

The dumps are encrypted before they are written, and the key that decrypts them is deliberately not on the servers, so a backup cannot be read by anyone who compromises the machine that produced it. The restore path is not a theory: a production dump has been retrieved from the off site copy without involving the production server, decrypted and restored, with the result checked against expected contents.

Externally verifiable

The verifier underneath Tessio.Cloud is open source (Apache-2.0, on NuGet), so you can read exactly what it does. It passes the OpenID Foundation conformance suite for OpenID4VP 1.0 HAIP verifiers in both credential formats the EU wallet uses. We also run free validators for the EU identity ecosystem at labs.tessio.eu.

What we do not have yet

Stated here because you would find out anyway, and it is better coming from us.

Reporting a vulnerability

Found something? Write to hello@tessio.eu and we will respond quickly. The verifier is open source, so issues in it can also be reported on GitHub. We are a small team; you will be talking to the people who wrote the code.

Free validators for the EU identity ecosystem: labs.tessio.eu