The database refuses
Every table carries a clinic ID, and Postgres row-level security is enabled and forced on all of them. The application connects with a role that cannot bypass those policies, and an automated test fails if that ever changes.
Every clinic on Mediora shares one system, so separation can't depend on a developer remembering a filter. The database itself refuses to show one clinic another clinic's data.
Each layer would stop a leak on its own. Deepest first.
Every table carries a clinic ID, and Postgres row-level security is enabled and forced on all of them. The application connects with a role that cannot bypass those policies, and an automated test fails if that ever changes.
Each database query runs inside a transaction that first sets the clinic from your verified login. Developers never type the clinic filter by hand, so nobody can forget it.
Your login token carries your clinic and role. A request that can't be tied to a clinic never reaches the code that reads data, and each role only reaches the screens it's allowed to.
A small model of how it works. Switch clinics, then try to read or write the other clinic's patients.
| tenant_id | name | phone |
|---|---|---|
| clinic_a | Ayesha K. | +92 300 •••• 567 |
| clinic_b | Liam W. | +61 491 ••• 188 |
| clinic_a | Emily C. | +44 7700 ••• 142 |
| clinic_b | Omar S. | +92 321 •••• 890 |
| clinic_a | Maria L. | +1 512 ••• 0142 |
| clinic_b | Chloe N. | +61 491 ••• 131 |
Dimmed rows exist, but the policy hides them from a Maple Dental session.
What the app sees
-- set from your verified login, never from the request
SET app.current_tenant_id = 'clinic_a';
SELECT name, phone FROM patients;3 rows
Only Maple Dental's patients come back. The other clinic's rows are not filtered out by the app: the database never returns them.
Specifics, so your compliance team doesn't have to guess.
Good security includes being clear about the gaps. These are the ones a careful buyer should know about today.
Found something that looks wrong? Email security@mediora.app with what you saw and how to reproduce it. Please don’t access other clinics’ data while testing. We’ll confirm we received your report and keep you updated while we fix it.
No. Every record carries your clinic's ID, and the database itself enforces row-level security on every table, so a query made for one clinic cannot return another clinic's rows even if application code has a bug. The application also connects with a database role that cannot bypass those rules.
The owner suspends them. Their very next request is refused, on every device, and their seat frees up immediately. Their past appointments, messages and notes stay intact, because nothing in Mediora is ever hard-deleted.
Not yet. We have not completed a formal compliance audit or certification. The security page lists exactly what the system does today, so your compliance team can judge it against your obligations, and we're happy to answer their questions directly.
Your clinic does. Mediora stores and processes it on your behalf to run the service. Archived patients, staff and services are kept rather than deleted so your history and reports stay correct.
Yes. Every change made in Mediora is recorded with who did it, their role, what changed, when, and from which IP address. The database refuses edits or deletions of audit entries. Clinical content is deliberately left out of the audit log so it stays visible only to the people allowed to read it.
Bring your compliance questions to a demo. We'll walk through the architecture with whoever needs to sign off.
Or start free