Guidelines›Security›Secure documents

The document service · encryption, access, and the limits that are real

The part everything else rests on, including what it cannot do.

Every compliance claim on this site — the American, the European, the British, the German — eventually points at one piece of machinery: the service that stores clinical documents. This page explains how it works, in ordinary language, and then does something most vendor documentation avoids.

It lists the risks that have no technical fix. Not the ones we solved and would like to tell you about — the ones where the honest answer is "this can happen, here is why we chose it, and here is what you must do about it". If you only read one section, read that one.

Security reviewers Data protection officers Clinical directors Whoever will hold the key
AES-256-GCMon every version 1key per document version 0keys in the database 0ways to recover a lost key 7risks named below
01 — The idea

Two locks, and the second one is not in the building

Imagine every clinical document in a box with its own padlock, and every padlock having a different key. Those keys are themselves locked in one safe. The documents and the little keys live in your database. The safe key does not.

That is the whole design. Everything below is detail on top of it, and the consequences are worth stating before the mechanics:

Consequence one

A stolen database is not a data breach

Someone who copies your entire database gets the boxes and the locked little keys. Without the safe key, none of it opens. This is what makes the encryption exemption in breach law available to you — you can argue the data was unintelligible, provided the safe key was not taken too.

Consequence two

Disposal can be proved

To dispose of a document you destroy its little key. The box remains, empty and unopenable forever. That is stronger than deleting a row — a deleted row comes back from last night's backup, a destroyed key does not.

Consequence three

Losing the safe key loses everything

There is no master copy, no vendor escrow, no recovery service. If the safe key is gone, every clinical document you hold is gone with it. This is deliberate, and section 05 explains why any "solution" to it would be worse than the problem.

02 — The mechanics

How a document is actually encrypted

The technique is called envelope encryption, and it is what banks and cloud providers use for the same problem. There are three layers. The reason for three rather than one is in the third column.

LayerWhat it isWhy it is separate
The document version The actual file — a session report, an incident record, an identity document — encrypted with AES-256-GCM. The encrypted result is written to a directory of its own on disk, outside Odoo's ordinary file storage, and is never served through the normal download route. Keeping ciphertext out of the ordinary file area means a misconfigured web server cannot accidentally publish clinical files, because they are not where a web server would look.
The data key (DEK) A fresh random 256-bit key, generated for every version of every document. Not per patient, not per document — per version. It is stored in the database, but only in wrapped form. One key per version is what makes disposal precise. Destroying a version's key disposes of exactly that version and nothing else, so a correction can be kept while the original is disposed of, or the reverse.
The deployment key (KEK) One 256-bit key for the whole installation, held in a file on the server, which wraps every data key. It is never stored in the database and never leaves the server. This is the separation that does the work. Database and keys are different things in different places with different backups, so obtaining one does not give you the other.

Where each piece actually lives

Six things exist for every document version. They are deliberately kept in different places, because the whole design rests on no single place holding two of them.

The pieceWhere it is keptWhat holding only this gets you
The file itself, encrypted A directory of its own on the server, laid out as <store>/<first 2 of uuid>/<next 2>/<uuid>.enc.v<version>. Directories are owner-only, files owner read/write. Outside Odoo's filestore, so it is not reachable through /web/content and not touched by attachment garbage-collection. Nothing. Authenticated ciphertext with no key. One file per version, so filing a new version cannot overwrite the one before it.
The nonce and two hashes In the database, on the version row: the nonce used for this encryption, a hash of the plaintext, and a hash of the ciphertext. Nothing on its own — but the plaintext hash is needed to rebuild the binding below, so losing it makes the ciphertext undecryptable. That is by design, not an oversight.
The data key, wrapped In the database, encrypted under the deployment key. The unwrapped form exists only in memory, for the length of one read, and is discarded immediately after. Nothing without the deployment key. A stolen database gives you wrapped keys and ciphertext paths, and neither opens anything.
The deployment key A file on the server, readable only by the account Odoo runs as. Never in the database. Never in the filestore. Never inside a declared backup root — each of those is checked at startup and is fatal, not a warning. Nothing without the database, which holds the wrapped data keys, and without the ciphertext store. Three separate things are needed, and they are kept in three places.
The access rules In the database, as records — who may open what, on what basis, and until when. They decide what a colleague can open. They have no effect on somebody who has the files but not the keys, which is the case encryption is for.
The access log In the database, append-only and hash-chained. Every read, not only every change. The record of who opened what. It is written before the content is handed over, so a download somebody cancels is still recorded as an access.

The two flows, step by step

Everything above is easier to check against these. The first is what happens when a document is filed; the second is what happens when somebody asks to see one. Read the second one closely — it is where most systems are weaker than they claim.

1 the software does this by itself 1 a person does something ✕ the software refuses
Write path Filing a document — from the upload to the disk The plaintext exists in memory and nowhere else. At no point in this sequence is an unencrypted byte written to disk.
  1. Somebody uploads a file

    A session report, an incident record, an identity document. It arrives in memory.

  2. A brand-new key is generated for this version

    32 bytes from the operating system's cryptographic random source. Not derived from a password, not reused from another document, not reused from the previous version of this document.

    one key per version — this is what makes disposal precise
  3. The content is fingerprinted, and a fresh nonce is drawn

    A SHA-256 of the plaintext, and a 96-bit number used once. No function in the encryption core accepts a nonce from its caller, so the classic reuse mistake cannot be made here.

  4. The file is encrypted, bound to this exact document and version

    AES-256-GCM, with uuid | version number | content fingerprint as additional authenticated data. That binding is mandatory. A ciphertext later copied onto a different document or a different version will refuse to decrypt rather than quietly open under the wrong person's access rules.

  5. The data key is wrapped under the deployment key

    Encrypted with the deployment key, tagged with the key generation and the key namespace, and stored in the database in that form. The unwrapped key is discarded from memory immediately.

  6. The ciphertext is written to its own store, atomically

    Written to a temporary file in the destination directory, flushed to the physical disk, then renamed into place — so a crash mid-write cannot leave a half-written version. The temporary file holds ciphertext, never plaintext.

  7. The database keeps the pointer, not the content

    Storage path, nonce, both hashes, size, and the wrapped key. Never the plaintext, never an unwrapped key, never the deployment key.

  8. The filing is written to the access log

    Who filed it, when, how large, and what type. Append-only and chained to the entries before it.

What a backup of the database now contains: paths, hashes, and keys that are themselves encrypted. Restoring it onto a machine without the deployment key opens nothing.
Read path Opening a document — how the key is found and used Six checks stand between a request and a decrypted byte. Each of them can refuse, and four of them refuse before the key is ever read from disk.
  1. Somebody asks for a document

    A clinician in the back office, or a client on their own records page. Both go through the same checks; neither route bypasses the other's.

  2. Not signed in with two steps? Refused

    On the client-facing route, records are not shown to an account that has only a password. The refusal says what to do about it rather than pretending the document does not exist.

  3. Reading too many, too fast? Refused

    A per-person rate limit on the client-facing route. Told plainly, because saying so leaks nothing and saves a support call.

  4. The access decision runs, in a fixed order

    Deny rules first — a single one is final. Then allow rules: if none matches, the answer is no. Emergency access is consulted only at that point, so it can reach what was never granted but cannot overturn a refusal. Sensitivity labels are applied last and can only take access away.

    closed by default · no superuser branch exists in this check
  5. The read is logged before anything is decrypted

    The entry is written first, so a transfer somebody aborts halfway is still on the record as an access. The log is append-only and hash-chained; entries cannot be quietly removed afterwards, by us or by your own administrator.

  6. The stored file is checked against its recorded hash

    Before any key is touched. Corruption in the store is then reported as corruption, rather than surfacing later as a confusing authentication failure.

  7. Now — and only now — the deployment key is read from its file

    Used to unwrap this version's data key, checking the key generation and namespace as it goes. A key wrapped for one namespace cannot be unwrapped as another even by someone holding both deployment keys.

  8. The file is decrypted in memory, and the binding is verified

    The document identifier, version number and content fingerprint are rebuilt and must match. Tampering, a wrong key, and a ciphertext moved from another record all fail here — and all fail identically, because telling an attacker which part failed is free information.

  9. The bytes are streamed to the reader, then forgotten

    The data key is dropped from memory. No code path in this product writes a decrypted byte to disk — not for previews, not for thumbnails, not for search indexing.

  10. If the key was destroyed, there is no path at all

    A disposed version reports that its key no longer exists. There is no fallback, no cached copy and no recovery route, which is the point of disposing of it that way.

Read this as the answer to "who can see my records". Steps 2 to 4 decide whether, step 5 makes it provable, and steps 6 to 9 mean that even a correct decision produces only a stream of bytes, never a decrypted file left lying somewhere.

The deployment key: how it is made, and what the server refuses

One key protects every data key in the installation, so its handling is the part worth checking line by line. All of the checks below run at startup and all of them are fatal — the server does not start rather than running with protection you believe you have and do not.

How it is generated

32 bytes from the operating system's random source, written to a file created with owner-read-only permission in a single step, so it is never briefly readable by anyone else.

The file must hold either 32 raw bytes or 64 hexadecimal characters. Nothing else is accepted — a passphrase is refused rather than stretched into a key, because a stretched passphrase is a weaker key that looks like a stronger one.

Where it may not live

Not in the database. Not in Odoo's data directory, its addons path or its filestore. Not inside the ciphertext store. Not inside any directory you have declared as a backup root.

That last one is the one people get wrong. A backup holding both the database and the key is a compromised key, and it puts the deployment outside the American breach safe harbour and the European Art. 34(3)(a) exemption — which is the entire reason the encryption is here.

Rotation, and why it is cheap

Rotating the deployment key re-wraps the data keys and does not rewrite a single byte of ciphertext. A hundred thousand documents rotate as fast as a hundred keys can be re-encrypted, not as fast as a hundred thousand files can be rewritten.

The generation number is inside the wrapping, so a key wrapped under the old generation cannot be silently opened as if it were the new one.

Destruction, and what remains

Disposing of a version overwrites its wrapped key with random bytes rather than blanking the field, so there is nothing left to recover even from the database page.

The version's metadata shell and the whole access log survive — you can still prove you held the document and disposed of it correctly. A version cannot be deleted while its key still exists, so the order can never be the wrong way round.

Three details a reviewer should ask about

These are the places where encryption is usually implemented almost-correctly, and almost is the whole of the difference.

Every ciphertext is bound to its own record

When a version is encrypted, the encryption is tied to that document's identifier, its version number and a fingerprint of its content. Cryptographers call this the additional authenticated data, and it is mandatory here — no caller can skip it.

The effect: a ciphertext copied onto another document, or another version, refuses to decrypt. It does not quietly open under the wrong patient's access rules — which is precisely the attack that a system without this binding is exposed to.

A nonce is never reused

AES-GCM is catastrophically weak if the same nonce is used twice with the same key: an attacker who sees two such ciphertexts can recover information from both. It is the classic implementation mistake.

Here every encryption generates its own nonce and no function accepts a nonce from the caller. The mistake is not made harder to make; it is made impossible to make.

The crypto has no Odoo in it

The encryption core is written as a standalone piece with no dependency on the application framework, so that somebody auditing the encryption claim can read and test it on its own without running a clinic system.

If your security team wants to verify the claims on this page rather than believe them, that is the file to hand them, and it is a short one.

Two keys, not one, for therapy notes

Where the law separates a therapist's own process notes from the clinical record — the American psychotherapy-notes carve-out is the clearest case — those notes are encrypted under a second, different deployment key. The key that opens the ordinary record does not open them.

This matters because it makes the separation a property of the storage rather than of the access rules. If every permission in the system were wrong tomorrow, the ordinary key still would not decrypt those notes. It also means the second key must be configured before go-live: filing such a note without it fails rather than quietly falling back to the main key, because a silent fallback would destroy the separation without anybody noticing.

03 — Who can open one

Encryption decides what a thief gets. This decides what a colleague gets

The two are often confused. Encryption protects against someone who should not be in the system at all. It does nothing about the far more common problem: somebody who is in the system, looking at a record they have no business reading.

That is what the authorisation layer is for, and it works on a different principle from most systems: access follows the treatment relationship, not the job title.

What happens on every single read

Every time. Not once at login.

  1. Who is asking?A signed-in person, resolved to an individual. Not a role, not a group, not "the system".
  2. Is there a rule that allows it?Because they are the subject, because they hold a current care relationship, or because someone granted them named access. No rule, no access.
  3. Is there a rule that forbids it?A refusal always beats a permission. Sealed documents, withheld records and separately-kept therapy notes refuse on every route in.
  4. Write the log entryBefore any content is sent back. If the log write fails, the content is not served.
  5. Unwrap the key, decrypt in memory, streamThe plaintext is never written to disk on the way out and never lands in the ordinary file area.

What does not get you in

Stated explicitly, because reviewers ask

  1. Being an administratorAn admin account opens no clinical document by itself. There is no maintenance override and no support back door.
  2. Having written it yourselfIncident and safeguarding files are closed even to the person who filed them, because they are filed to the director.
  3. Being seniorClinical roles decide which screens somebody reaches. They never decide what somebody can open.
  4. Being the patientA client sees a record about themselves only where a rule specifically grants it — a clinical and legal decision, recorded with its reason and its author.
  5. Guessing a referenceA document you may not see returns "not found", never "forbidden", so the difference between the two answers cannot be used to discover which records exist.
Emergency access exists, and it is never quiet

A clinician sometimes genuinely needs a record they have no relationship with — a crisis, an out-of-hours call, a colleague taken ill. Where your organisation permits it, break-glass access is available. Using it opens a recorded session that is reviewed afterwards.

A system that only ever refuses is unsafe in its own way, and in the United Kingdom it is explicitly non-compliant: Caldicott Principle 7 makes the duty to share as important as the duty to protect. So the access exists, and the use of it is never silent.

04 — The life of a document

From filing to disposal, and what is left behind

1 the software does this by itself 1 a person does or decides something ✕ the software refuses
One session report, start to finish Filed on a Tuesday in 2026, disposed of in 2046 Twenty years is not a hypothetical span — it is the British retention period for mental-health records, and it is what the retention engine was designed around.
  1. A therapist writes the report and files it

    Against a document type — that type is what decides the rules, the retention period and who may open it.

  2. The filing dialog says who will be able to open it

    In plain words, before it is saved. Most mis-filing happens because nobody knew where a document would land.

  3. A fresh key is generated and the content is encrypted

    Bound to this document, this version, and a fingerprint of this content.

  4. The key is wrapped under the deployment key and stored

    The unwrapped key exists only in memory, for the moment it is needed.

  5. The ciphertext is written outside the ordinary file area

    With its own permissions, in its own directory.

  6. Colleagues on the care team open it over the years

    Each opening logged before the content appears.

  7. A correction is filed

    As a new version, with its own new key. The original is untouched and still readable — an amendable record is worthless as evidence.

  8. Somebody tries to move the ciphertext onto another record

    It refuses to decrypt, because the encryption is bound to the original document's identity.

  9. Treatment ends, and the retention clock starts

    From the end of the relationship — not from the day the file was created.

  10. Twenty years later, a scheduled job disposes of it

    The key material is overwritten with random bytes, then the key row is deleted. Overwriting first is deliberate: if the process is interrupted, the failure mode is a document that cannot be read, never one that survives when it should not have.

  11. What remains: an empty shell and the audit trail

    You can still prove the record existed, who saw it across twenty years, and that it was disposed of on schedule. The content is unreadable by anyone, permanently, including us.

A legal hold stops all of this. While litigation, a complaint or an investigation is open, disposal is suspended and nothing is destroyed — which is the case where an automatic retention job would otherwise do real damage.
05 — The honest part

Seven risks with no technical fix

Everything above is what the system does well. This section is the opposite: the places where something bad can happen and no amount of engineering closes it — because the closure would cost more protection than it buys.

Each one says what actually happens, what we do about it, and what is left with you. If a supplier tells you their encryption has none of these, they have either not thought about it or are hoping you will not.

1 · The deployment key is lost or deleted — everything is gone

What happens: the key file is deleted, the disk fails, the server is rebuilt without it, or the one person who knew where it was has left. Every clinical document in the system becomes permanently unreadable. Not difficult to recover — impossible. The database is intact and worthless.

Why we do not fix it: the only fixes are a vendor-held copy or a recovery back door. Both destroy the property the whole design exists for. If we held a copy, then "a stolen database is not a breach" stops being true, and every promise on this page about what we cannot see becomes false. A recoverable key is a key somebody else can use.

What we do: the system refuses to start if the key is missing, rather than quietly running and letting you discover the problem when a document will not open. The startup check also refuses if the key file is readable by anyone but its owner, or owned by the wrong account.

What is yours: back the key up, separately from the data, and test that you can restore it. Two people should know where it is. This is the single highest-consequence operational duty in the entire platform, and it takes about ten minutes to get right.

2 · The key is copied to someone who should not have it

What happens: an administrator emails the key file to a colleague, pastes it into a ticket, copies it to a laptop, or a departing engineer keeps a copy. Anyone holding both that file and a copy of the database can decrypt every document, offline, with no login, and nothing is written to your access log — because the log records reads through the application, and this bypasses the application entirely.

Why we do not fix it: the key must be readable by the software that uses it. Any process that can read it can copy it. Hardware security modules move this problem rather than solving it — the software still has to be able to ask the module to unwrap keys, so an attacker with that software's privileges still gets plaintext.

What we do: the file permissions are enforced at startup, so a key readable by everyone stops the system rather than passing unnoticed. And because you self-host, we never have the file at all — the population of people who could copy it is your staff, not your staff plus ours.

What is yours: treat the key like a controlled physical object. Restrict who can log in to the server, use individual admin accounts rather than a shared one, and rotate the key when somebody with server access leaves — section 06 explains why rotation is cheap.

3 · The key ends up in the same backup as the data

What happens: the quietest and commonest failure. Somebody sets up a backup that sweeps the whole server, and the key file is inside the same archive as the database. Now one stolen backup tape contains both halves, the encryption protects nothing, and — worse — you would still be claiming the encryption exemption in a breach report, because on paper everything was encrypted.

Why it is hard: nothing about the running system looks different. It works perfectly. The problem exists only in the backup, and only matters on the day the backup is stolen.

What we do: this is the one in this list we partly did engineer against. You declare your backup directories in the configuration, and the system refuses to start if the key file sits inside one of them. If you declare no backup paths at all, it warns that the exemption cannot be verified — because an unchecked claim is the dangerous kind.

What is yours: declare the backup roots honestly, and check what your backup tool actually includes rather than what you think it includes.

4 · A person with legitimate access reads something they should not

What happens: a therapist opens the file of a client who is also their neighbour. A receptionist looks up a local celebrity. Every rule was satisfied — the person had a valid care relationship, or valid grounds, and simply misused it. Encryption is irrelevant here. So is access control, because access was granted.

Why no system fixes it: software cannot read intent. A system that tried — blocking access because a name looks local — would block genuine clinical work in an emergency, which is its own harm and, in the UK, its own compliance failure.

What we do: make it visible rather than impossible. Every opening is recorded before content appears, in a log nobody can edit — including your administrators and including us. Care relationships end, and access ends with them after a short grace period, so the window is narrow. Emergency access is a separate, deliberate, reviewed act rather than a quiet capability.

What is yours: somebody must actually read the log. The governance module gives the review a home — cadence, named reviewer, findings trail — but a log nobody looks at deters nobody. This is the control that most often exists on paper and never happens.

5 · Someone with root on the server reads a document while it is open

What happens: to show a document to an authorised clinician, the software must decrypt it. For that moment it exists in the server's memory as readable text. Somebody with full control of the operating system can, in principle, read it there — or modify the software to keep copies.

Why no system fixes it: this is true of every system that ever displays anything to anyone. If the machine can show the document, the machine's owner can obtain the document. Encryption protects data at rest and in transit; it cannot protect data from the computer that is lawfully processing it.

What we do: minimise the window — decryption happens in memory for the moment of the read and the plaintext is never written to disk. And self-hosting means you are the party with root, not us.

What is yours: server administration is the highest-privilege role you have. Few people, named individually, keys not passwords, and a record of who holds access. It belongs on the joiners-and-leavers checklist next to the clinical accounts.

6 · A document is disposed of and should not have been

What happens: a retention rule is configured wrongly, or a shred is run on the wrong selection. The keys are overwritten and the documents are unreadable. There is no undo, and restoring last night's backup does not help — the backup contains the same ciphertext, and its key is gone.

Why we do not fix it: a reversible disposal is not a disposal. The entire value of crypto-shredding to a regulator is that it cannot be walked back. A "recycle bin" for destroyed keys would mean the data was never really destroyed, and every erasure claim you made would be false.

What we do: keys cannot be deleted through any ordinary path — the delete operation is blocked outright and disposal happens only through the shredding route, which writes an audit entry as it goes. Legal holds suspend disposal entirely. Retention counts from stored anchor dates rather than file age, so the commonest cause of wrong-date disposal does not arise.

What is yours: check the retention configuration before go-live, not after the first disposal run. And confirm the scheduled jobs are actually running — a retention job that stopped silently is a different problem, but it is discovered the same way, which is to say too late.

7 · Today's encryption will not be strong forever

What happens: mental-health records are kept for twenty years and sometimes longer. AES-256 is not currently considered breakable, including by the quantum computers people speculate about — but no honest engineer promises anything about 2046 with a straight face.

Why nobody fixes it: you cannot buy protection against a mathematical result that has not happened yet. Anyone selling "quantum-proof" storage for clinical records is selling a story.

What we do: make the algorithm and the keys replaceable without touching your data. Key rotation re-wraps every data key under a new deployment key without rewriting a single byte of ciphertext, so it is a background task rather than a migration project. The cryptography is isolated in one small reviewable component precisely so it can be replaced when the time comes.

What is yours: rotate periodically rather than never, and expect to re-encrypt once in the lifetime of a twenty-year record. Plan for it as maintenance, not as a crisis.

The pattern across all seven

Look at what the seven have in common. In every case the "fix" that would close the risk — a recoverable key, a reversible disposal, a system that reads intent, protection against your own administrators — would destroy something more valuable than it protects. The design choice is not that these risks were overlooked. It is that closing them would make the remaining guarantees untrue.

What is left for you is small, specific and mostly procedural: back up the key separately, control who can reach the server, declare your backup paths, read the access log, and check the retention settings once. That list fits on one page and it is the whole of it.

06 — Key custody

What the system checks, and what only you can do

Given that risk 1 and risk 2 are the two highest-consequence items on this page, it is worth being precise about which parts are automatic and which are yours.

CheckStatusWhat happens
The key exists ✓ Verified at startup. A missing key stops the system rather than letting it run and fail later, one document at a time, in front of a patient.
Only its owner can read it ✓ A key readable by the group or by everyone is fatal at startup, not a warning in a log nobody reads.
It is owned by the right account ✓ Checked against the account the service runs as. A key owned by a departed engineer's login is a finding.
It is not inside a backup directory ✓ You declare your backup roots; the system refuses to start if the key sits inside one. If you declare none, it warns that the breach exemption cannot be verified.
It is not somewhere it would travel with the data ✓ A short list of directories the key must never live in is refused outright.
It is a real key ✓ Accepted only as 32 raw bytes or 64 hexadecimal characters. A truncated or corrupted file is refused rather than used to produce documents nobody can ever open.
It is backed up, separately — Yours, and the software cannot help. We cannot verify a backup we are not allowed to see, and a system that could check its own key backup would be a system that can reach it. Two people, two places, tested restore.
Who may reach the server — Yours. Anybody with root can read the key. That list should be short, named, and reviewed when people leave.
Rotation when somebody leaves ⚙ Supported and cheap: rotation re-wraps every data key under a new deployment key without rewriting any ciphertext, and superseded keys can be kept to unwrap anything still in flight. Deciding when to rotate is yours. After a server administrator leaves is the obvious moment, and it is the one most often missed.
✓AutomaticChecked by the software, every time it starts. ⚙Supported — you decide whenBuilt and cheap to run; the timing is an operational choice. —Only you can do itNot a gap in the software. Something software cannot verify without defeating its own purpose.
07 — What it will never do

Four limits that are inherent, not unfinished

Consequences of the design, stated so nobody discovers them later

  • Documents cannot be searched by their content. Encrypted text cannot be indexed without building a searchable copy of exactly what the encryption exists to protect. Documents are found by subject, type and date. Any supplier promising both strong encryption and full-text search of the same content is promising one of them falsely — ask them which.
  • It is not an electronic health record. No clinical charting, no structured notes, no HL7 or FHIR messaging, no prescribing. It stores and controls documents. Where you need an EHR, it comes from elsewhere and this holds the documents.
  • The core knows nothing about healthcare law. Encryption, access, logging and retention are jurisdiction-neutral by design. Every country-specific rule arrives as a separate module on top, which is why the same core serves American, European, British and German deployments without one country's assumptions leaking into another's.
  • It cannot protect a document after a person is looking at it. A clinician with lawful access can photograph the screen, copy the text, or read it aloud on a train. No storage system reaches past the display. That is a staff, training and disciplinary matter, and the access log is what makes it investigable afterwards.
The one-paragraph summary

Every version of every clinical document is encrypted with its own key, bound to that document's identity so it cannot be moved elsewhere. Those keys are wrapped under one deployment key that lives outside the database and never leaves your server — so a stolen database is not a disclosure, and disposal is done by destroying a key rather than deleting a row. Documents open only for people with a current treatment relationship, and every opening is written to a chained log first, so misuse is visible even when access was legitimate. What cannot be fixed by engineering is named in section 05, and the short version of your side of it is: back up the key separately, keep server access short and named, declare your backup paths, read the log, and check the retention settings once before go-live.