Security you can check
We hold clinical records for other people's patients. This page says exactly what we do about that, specifically enough that you could verify it, and honestly enough to include what we have not done yet.
Keeping practices apart
Every practice group's data is separated by PostgreSQL row-level security. The database itself refuses to return another group's rows.
This is not an application filter that a developer has to remember to add. It is a rule the database enforces on every query, and the default with no tenant context set is to return nothing at all.
PostgreSQL silently ignores row-level policies for superuser connections. A platform can have every policy correctly written and still leak everything, with all its tests passing. Our API connects as a restricted role that cannot bypass them, and it refuses to start if it is ever pointed at a privileged connection. Eight automated tests exist purely to try to read across the boundary.
Encryption
Everywhere data moves and everywhere it sits.
In transit
TLS 1.2 or better on every connection, with HSTS so browsers never fall back.
At rest
Database, backups and object storage are all encrypted with AES-256.
Scans and photographs
A private bucket, never public. Access is by a pre-signed link minted per request.
Accounts and access
Staff accounts, how they authenticate, and what happens when something goes wrong.
- PasswordsHashed with
argon2idat OWASP parameters. We never see or store the plaintext. - Two-factorTOTP, available to every account and recommended for all. Practices can make it mandatory for their staff.
- Sessions15-minute access tokens. Refresh tokens rotate on every use.
- Stolen tokensReplaying a rotated refresh token revokes every session that user holds, immediately.
- LockoutRepeated failed sign-ins lock the account temporarily.
- Least privilegeEvery person has a role with only the access it needs. A technician has no access to patient demographics at all.
- RevocationDeactivating someone ends their sessions at once, not when a token happens to expire.
Patient sign-in
Patients never hold a password. They prove who they are with things only they should know, then a one-time code.
All three must match the record on file.
Short-lived, with a limited number of attempts, and rate limited per number and per IP address.
The reply is the same whether or not the details match, so the page cannot be used to discover real patient references.
Carries a separate audience claim and is refused by every staff endpoint. A patient can only ever reach their own record.
Every attempt, successful or not, is logged.
What gets logged
Every read and write of a patient record.
What is recorded
The actor, timestamp, IP address and the resource touched, for reads as well as writes. Viewing a record leaves a trace, not just editing it.
Why it is per patient
The log can be produced for a single patient on request. That is what makes a subject access request answerable in minutes rather than days.
Clinical safety controls
The AI produces evidence and a suggested verdict. A registered clinician decides, and the system will not let it be otherwise.
- Only a permitted, registered clinician can approve a plan
Their role must be allowed to prescribe in that country and their professional registration number must be on file. The registration relied upon is stamped on the approval.
- Only a registered clinician can record a scan decision
Disagreeing with the AI is recorded as an override, with the clinician’s name against it.
- A patient cannot advance past a hold
Nor advance on a no-go verdict. The app enforces this, and so does the API behind it.
- Every AI-produced row stores its model version
So a verdict can be reproduced, and explained, months later.
Where data lives, and how it comes back
Hosted in the EU
Database and file storage run in Helsinki, Finland. No patient data goes to a US-region service without a transfer risk assessment.
Backups and recovery
Our current backup and restore arrangements are documented, and we share them on request as part of due diligence.
How we build
The controls above are only as good as the process that ships them.
- Isolation, roles and patient sign-in are tested on every change. A failure blocks the deploy.
- Dependencies are audited on every install. We do not ship with known vulnerabilities.
- Secrets live in a managed secret store. Never in the repository, never reachable from a browser.
- The API runs as an unprivileged user in a container that has no root.
Certifications and audits
We would rather tell you than let you assume.
- Independent penetration test
Not yet carried out. Planned before general availability.
Planned - Cyber Essentials Plus
Not yet held. Planned before general availability.
Planned - ISO 27001
Not yet held. Planned before general availability.
Planned - UK GDPR
How we handle personal data as a processor is set out in full on our data protection page.
In place
Ask us where these stand. We will give you the current answer, not a marketing one.
Ask a questionReporting a vulnerability
If you find something, tell us before you tell anyone else. We will not pursue anyone acting in good faith who avoids privacy violations, data destruction and service disruption.
Include what you found and how to reproduce it. Please do not test against real patient data; ask and we will give you a sandbox.
A named person, not an auto-reply.
We tell you how serious we think it is and when it will be fixed.
For anything else, including customer security questionnaires, use the contact page.
Report a vulnerabilityThis page is reviewed with every material change to the platform. Questions about anything on it: contact us.
