Security that is structural.
Isolation you cannot misconfigure beats a policy nobody reads. This page lists what protects your customers' data — checked line by line against the source code, the address registry and our operator.
- 12
- BCrypt work factor
- 15
- Minutes until an access token dies
- 7
- Enforced rate-limit policies
- 27
- Threats analysed in the STRIDE model
Where your data lives.
Separation first, encryption second, and an exit that is a file rather than a negotiation.
Tenant isolation
An account created through signup gets its own database, and each installed module keeps its tables in their own schema inside it. In the platform's own identity tables, tenant scope is applied by the data layer as well, rather than left to each query.
Where it runs
The platform's servers are in the Netherlands, hosted by TransIP. Email delivery and SMS use providers outside the EU; the privacy policy names each one and what it receives.
Encryption at rest
The databases run with SQL Server Transparent Data Encryption, so the database files are encrypted on disk.
Stored credentials
Database connection strings and payment-provider credentials are encrypted with ASP.NET Core Data Protection before they are stored, and are never written to logs.
Getting your data out
Where an account has its own database, we can export a complete copy of it for you on request, as a standard SQL Server .bacpac file.
Identity and sessions.
Short-lived by default, revocable in one move, and every number below is fixed in code.
- 15min
- access-token lifetime
- 256bit
- random refresh tokens
- 5min
- one-time-code expiry
- 3attempts
- one-time-code cap
- 5attempts
- lockout threshold
- 12
- BCrypt work factor
Passwords
Hashed with BCrypt at work factor 12, fixed in code. Lockout after 5 failed attempts by default — tenant-configurable, and it can be switched off.
Sessions
Access tokens expire in 15 minutes. Refresh tokens are 256-bit random values, stored only as a hash, single-use, and rotated on every refresh.
One-time codes
Optional 6-digit codes by email or SMS, hashed at rest, expiring in 5 minutes with a 3-attempt cap.
Trusted devices
Host-prefixed, secure, same-site-strict cookies holding a value stored server-side as a hash. Presenting a superseded cookie revokes the device and blocks the sign-in.
Revoking access
Every trusted device can be revoked at once — and revocation fires on its own after a password change, a lockout, two-factor being switched off, or an email or phone change.
Boundaries, limits and the record.
Checks at the edge, caps on the road in, and an append-only trail behind every change.
Authorization
Permission-gated endpoints declare the permission they require, checked at the HTTP boundary against the signed token's claims without a database round-trip. Endpoints that serve only the signed-in user's own data are gated by authentication alone.
Rate limits and headers
Seven enforced rate-limit policies, and eight security headers including HSTS and a deny-by-default content-security policy on API responses.
Audit record
Changes to the platform's own tables — sign-in, roles, permissions, settings — are recorded append-only: who, what, which table and row, when, and the values after the change. Password hashes, one-time-code hashes, two-factor secrets and security stamps are excluded. A deletion records the row's key, not its former contents.
Threat model
A written STRIDE model: 27 analysed threats across four trust zones and the host-tenant boundary, with four accepted residual risks stated.
Every line above was last checked on 19 July 2026 — against the source code, and for hosting and disk encryption against the address registry and our operator.
Send us your security questionnaire.
We'll answer it line by line, with the people who wrote the code.
Get in touch