Trust · security

Security and privacy.

How ClinicalBrief controls who sees what, keeps patient data on the machine, and records access. Every point here is enforced in code, and the limits are listed just as plainly.

01 · Access

Sign-in, then a role, then the data

Authentication

Sign-in uses Supabase Auth. The backend verifies every token itself (JWKS or legacy HS256), checking audience and expiry.

New accounts start as pending: every endpoint answers 403 until an admin assigns a role from the command line. Roles are never taken from signup data.

The one exception is a public demo sandbox, built but not switched on yet: an anonymous sign-in would get the read-only demo role, which sees only the synthetic patients flagged for the demo and cannot change anything.

Authorization

Six roles, plus the public demo role, are enforced in the API and mirrored in Postgres row-level security, so the browser's public key cannot read or write past them. Clinical tables are read-only to clients; all writes go through the API.

"Not yours" and "doesn't exist" both return 404, so record ids cannot be probed.

Permissions by role
Permissions by role
Permissionadminclinicianconsultantcoderauditorresearcher
See patient recordsclinician: assigned patients only
Create patients, upload notes
Review AI output
Audit log and governance
FHIR export

Researchers read records but never see original note text: the note view gives them the redacted version, and search returns no note text at all.

02 · Audit

Every read of clinical data leaves a trace

The audit log records who and which id, never the content. Clients cannot write to it.

  • Viewing a patient record, note text, or a note's AI output and evidence.
  • Every review decision: approve, reject or edit.
  • Copilot questions, logged without the question text.
  • Record search, logged without the query.
  • Each FHIR export.
03 · AI and patient data

The model runs on this machine, and must cite its sources

Local only

Copilot talks to a local Ollama model. The server URL must be a loopback address (localhost, 127.0.0.1, ::1), and Ollama "cloud" models are refused, so patient data does not leave the machine.

Guardrails, checked in code
  • Note text is sent as data inside evidence tags, and the prompt says it is never instructions.
  • Every factual sentence must cite a record; sentences without a source are removed, never shown.
  • Treatment or dosing advice withholds the whole answer, not just the sentence.
  • An answer citing a record with instruction-like text is never labelled grounded.
04 · Files and secrets

Small surface, explicit switches

Uploads

UTF-8 .txt only, at most 5 MB. Files are stored under a server-generated name; the original filename is for display only. Storage buckets are private.

Secrets and databases

The frontend holds only public values, never a service key. A git hook scans commits and pushes for secrets.

The backend refuses to connect to a remote database unless that process is started with an explicit opt-in flag; the setting is never read from the shared config file.

05 · Honest limits

What this does not protect

  • Redaction is regex only

    PHI redaction matches patterns (dates, US and Australian phone numbers, emails, record and insurance numbers). It is not a validated de-identification method; names, addresses and Medicare numbers are not detected.

  • Some outputs are not de-identified

    Only the note-text view is redacted. Copilot citations, entity evidence sentences and patient demographics are shown as stored.

  • Copilot sessions are hard-deleted

    Deleting a session removes the transcript permanently; what the AI said cannot be reconstructed. The audit log keeps who deleted it, for which patient. A clinical deployment would need retention instead.

  • A prototype, not a certified system

    No certification, compliance audit or penetration test has been done. It is a research and portfolio project, not a medical device, and runs on synthetic data only.

The full list lives in the README under "Known gaps".