What protects a practice here
Every claim on this page names the thing that makes it true. Where a protection has a cost, the cost is written down beside it.
One practice cannot see another
The database enforces it, not the code
Every table carrying a practice’s data has row-level security switched on and forced, and the application connects as a role that owns nothing and cannot bypass it. A query that forgot its practice returns nothing rather than everything.
A row cannot point at another practice’s row
References are made on the pair (practice, row) rather than on the row alone. A plain reference would let one practice point at another’s records, because those checks run with the owner’s rights and see past the isolation.
Getting in
Passwords are stored as Argon2id hashes
64 MiB, three passes, four lanes, with the parameters recorded beside each hash so an old password still verifies after the defaults are raised — and is rehashed the next time it is used.
A wrong password and an unknown address answer the same
Both take the same work, because an unknown address is checked against a real hash of a value nobody knows. Answering faster for one would let somebody discover who has an account by timing it.
A platform administrator cannot exist without a second factor
The database refuses to record one, and refuses to remove the factor afterwards. Enforcing it in the application would mean enforcing it at every door that ever signs anybody in.
A stolen session is noticed when it is used
Sessions change as they are used. Presenting one that has already changed is treated as a theft: everything in that family is revoked, everybody is signed out, and it goes in the log.
The record of what happened
Written with the thing it records, and never altered
Each entry is written in the same transaction as the action, so a booking that happened and a line saying who made it cannot come apart. A trigger refuses any later change.
Exactly one amendment is permitted
Forgetting who somebody was, when an account is erased. That is named in the trigger rather than allowed by loosening it, so every other kind of edit is still impossible.
Reading the platform-wide log is itself recorded
There is no way for an administrator to look without leaving a trace of having looked.
Leaving
A copy of your records, in formats that open elsewhere
Your account, your practices and your appointments as a calendar file any other diary will read. A patient asking for their own file is answered from that patient’s page, in the browser, because the reports are sealed and this server could only hand over ciphertext.
Deletion means the rows are gone
A test asks the database which columns name a person and then asks each of them about the erased account. Adding a table the erasure does not know about fails that test by name.
A practice you own alone cannot be deleted while it still has records. It has to be handed over or emptied first.
What we can read, and what we cannot
We cannot read what was done in a session
The report is sealed in your browser to your practice’s own key before it is sent. Any colleague you have let in can read it — that is the point of it being the practice’s key rather than yours — and this server holds ciphertext and a wrapped key it has no half of.
A forgotten password is a real loss. The recovery key printed when the practice was set up is the way back, and there is no other: we cannot reset what we cannot read.
Nobody at all can read your personal notes
The other half of a session is sealed to your own key, not the practice’s. Not a colleague, not the owner, not the platform administrator, and not this server.
Lose your password and your own notes go with it. The practice’s recovery key opens the practice’s reports, not one person’s notes.
What is not built yet
An erasure reaches the live database and not last night’s backup, which is the honest limit of deleting anything from a system that keeps one — destroying a key is what makes an old copy unreadable, and that is the direction this is going. A deleted note is deleted rather than struck through, and whether a clinical record should allow that at all is a question we would rather settle than discover.