Trust

Security

Everything below describes the system as it actually runs, verified against the production host rather than copied from a policy template. Where a control does not exist, this page says so instead of leaving it out.

Reporting a vulnerability: [email protected] · security.txt (RFC 9116)

Where the data lives

All production data sits on hardware operated by Hetzner Online GmbH in Nuremberg (nbg1), Germany. There is no managed third-party database and no replica outside the EU: PostgreSQL, the connection pooler and the search engine all run on that single host.

The database is not reachable from the internet. PostgreSQL, the pooler, the search engine and the application process are all bound to the loopback interface; the only ports that answer from outside are HTTP, HTTPS and SSH. SSH accepts public keys only — password and keyboard-interactive authentication are disabled — and repeated failures are banned automatically.

Web fonts are served from our own origin, so rendering a page does not hand a visitor's IP address to a font CDN. The full list of third parties that touch data is published separately. Sub-processors →

Data in transit

The entyrix.com virtual host negotiates TLS 1.2 and TLS 1.3 only; older protocol versions are not offered. HSTS is set to one year and includes subdomains, so a browser that has seen the site once will refuse to fall back to plaintext.

Every response carries a content security policy that blocks plugins and framing by third parties and pins form submissions to our own origin, together with MIME-sniffing protection, a no-referrer policy and a permissions policy that switches off camera, microphone, geolocation, payment and the rest of the powerful browser APIs. You can read these off any response with a single request.

curl -sI https://entyrix.com/ | grep -i strict-transport

Credentials and personal data

ControlHow
API keys are never stored in plaintextSHA-256 digest at authentication time (src/api/middleware/auth.ts)
IP addresses are never persisted rawSHA-256 over the IP and a salt that rotates at UTC midnight, so cross-day correlation is deliberately hard (src/lib/ip-hash.ts)
Access to personal data is logged per responseA row in gdpr.access_log for every response on a personal-data route — the record a data-subject request or an abuse investigation is answered from
Authentication secrets are compared in constant timecrypto.timingSafeEqual with a length guard, so a wrong token leaks no timing signal
Output escaping and URL whitelisting are centralisedOne escaping helper and one protocol whitelist for every link and attribute built from external data — not re-implemented per template
Outbound webhooks are signed and SSRF-guardedHMAC SHA-256 signature per delivery, with private and link-local destinations blocked
Rate limiting on every route600 requests per minute per API key, or per IP for unauthenticated traffic; only the liveness and readiness probes are exempt

Personal-data handling is narrower than the security controls above and is documented on its own: natural persons are withheld rather than merely hidden from a user interface, dates of birth are reduced to a year for adults and suppressed for minors, and the same rules apply over the API and the MCP server as on the website. Privacy policy →

Backups

WhatFrequencyWhereRetention
Offsite, encrypted (irreplaceable set)Daily 03:30 UTCCloudflare R2, client-side encrypted14 daily · 8 weekly · 12 monthly · 7 yearly
API keysDaily 02:30 UTCOn-host dump30 days + 12 months
Application tables (PostgreSQL)Weekly, Sunday 03:00 UTCOn-host dump3 weekly + 1 monthly (disk-bound)
Secrets file (.env)Weekly, Sunday 04:00 UTCAES-256-CBC + PBKDF2, passphrase-protectedJob refuses to run unencrypted

The offsite job covers the irreplaceable set — the personal-data schema and the application tables that hold keys, subscriptions, monitoring state and sanctions matches — and encrypts it on this server before it leaves, so the storage provider holds ciphertext it cannot read. The bulk register corpus is deliberately excluded: it is re-derivable from the public sources it came from, so its recovery path is re-ingestion rather than restore.

Recovery — and how we know it works

Restore tests are automated, not promised. Every Tuesday a job pulls the latest offsite snapshot, restores it into a scratch database, asserts that the expected tables and row counts are present, and destroys the scratch database. A failure notifies the operator. An untested backup is not a backup, so this runs whether or not anyone is looking.

RPO (recovery point): at most 24 hours for the irreplaceable set, bounded by the daily 03:30 UTC offsite run. Registry content restored by re-ingestion returns to the freshness of its upstream source, which is published per source on the status page.

RTO (recovery time): under 4 hours is our documented target, and it is a target rather than a measurement. The rebuild is scripted end to end and the restore path from the offsite copy is exercised weekly, but no full timed rebuild of the complete service has been performed, so we will not present a number as if it had been. If a contract needs a committed RTO, that is a conversation to have before signing, not after.

What we do not have

GapWhat that means for you
No ISO 27001 or SOC 2 certificationThere is no audited certification. Controls are documented and verifiable, not third-party attested. If your procurement requires an attestation, tell us before you start an evaluation.
The production volume is not encrypted at restBackups leaving the server are encrypted client-side and the secrets file is encrypted separately, but the running volume itself relies on the provider's physical and logical isolation rather than full-disk encryption. Almost all of the corpus is public-register data; the personal-data schema and the credential store are exactly what the encrypted offsite copy covers.
Single region, single hostOne server in one datacentre. There is no hot standby, so an outage of that host is an outage of the service. Recovery runs from the offsite backup — see the recovery objectives above.
No bug-bounty programmeWe do not pay for reports. We do read every one, and we will credit you if you want to be credited.

Reporting a vulnerability

Write to [email protected]. The same address is published in /.well-known/security.txt per RFC 9116, in Slovak or English.

Please include enough detail to reproduce the issue, and give us a reasonable window to fix it before publishing. We will not pursue anyone who reports in good faith and does not exfiltrate data, degrade the service or access other people's information. Please do not run automated scanners against production — the rate limiter will simply block you and the findings will be noise.

Anything that is not a vulnerability — contracts, data questions, a data-subject request — goes to [email protected] or through the pages below.