Vocabulary for this course

The terms the chapters assume, in plain words. You can open this from any chapter.

allow-list
A list of what is permitted, with everything not on it refused by default.
fail closed
Behaving so that an error blocks the action rather than letting it through unchecked.
false refusal
A refusal of a request that was actually allowed, which costs a real user an answer.
incident
An event where the system did something harmful or outside policy, handled from detection to review.
least privilege
Giving each part of the system only the access it needs for its current job, and no more.
moderation
Checking content against rules about what is acceptable, and blocking or flagging what is not.
normalisation
Rewriting input into one standard form, such as lower case or expanded characters, before checking it.
PII
Information that can identify a person, alone or combined with other details, such as a name or address.
policy
A written rule that says what the system must allow, block or escalate, kept in code with a change history.
prompt injection
Text in input or retrieved content that tries to make the system follow the instructions of an attacker instead of yours.
provenance
The record of where a piece of content came from and how it reached the system.
red team
People or scripts that attack the system on purpose to find failures before real users do.
refusal
A reply that declines a request and says what the system can do instead, without revealing protected details.
threat model
A written list of what you are protecting, who might attack it and how, made before you build.

Guardrails and safety

Privacy and data retention

Every field you send to a model becomes data you must protect, retain and delete. Minimise it, schedule it, and make deletion reach every copy.

Part 8 of 10

Intermediate16 min readBack to Courses

Data minimisation is a design decision

Every field you send to a model is a field you now have to protect, retain and delete. The cheapest data to govern is the data you never collected, so start by asking which fields the prompt actually needs. A support assistant that answers billing questions rarely needs a date of birth, and a summary rarely needs an account number.

Minimisation is not the same as redaction. Redaction removes a value after it has entered the system; minimisation keeps it out of the request, the log and the trace in the first place. The second is stronger because there is nothing to leak, nothing to expire and nothing to explain during an audit.

Purpose limitation follows from the same question. Data collected to answer a ticket should not quietly become training data, evaluation data or a dashboard dimension. Each new use is a new decision with its own lawful basis, and the design document should name the uses rather than assume them.

Retention is a schedule, not a setting

A retention policy is a table: data class, purpose, store, retention period, deletion mechanism and owner. Prompts might live seven days, traces thirty, aggregates two years, and a fine-tuned adapter as long as the base model it corrects. Without the table, every store invents its own answer.

Pick the period from the purpose, not from the storage bill. A trace kept for debugging has no reason to outlive the debugging window, and an evaluation set kept for regression has a reason to live as long as the suite. The period is a statement about why the data exists at all.

Write the schedule where the code can read it. A retention table in a wiki drifts from the job that deletes rows, and the drift is invisible until an audit finds records older than the policy allows. A job that reads the same table the policy names cannot disagree with it, and the owner in that row is the person who answers when it does.

Crypto-shredding with a per-subject key

from cryptography.fernet import Fernet

key = Fernet.generate_key()
cipher = Fernet(key)
token = cipher.encrypt(b"card 4111 1111 1111 1111")

# Deleting the key makes every record encrypted under it unreadable.
# The row can stay; the subject's data cannot be recovered.
print(token[:16])

A retention clock per data class

Run the schedule and see which records have expired. Then add a cache store to the prompt record and confirm the deletion fan-out picks it up.

Output
Click "Run" to execute your code

Deletion has to reach every copy

A delete request is a fan-out, not a row update. The primary database, the cache, the search index, the vector store, the trace store, the evaluation set and the analytics warehouse may each hold a copy. The job is finished when every store reports back, and that report is the evidence.

Derived data is the part teams forget. An embedding is a representation of the text, a summary is a rewrite of it, and a fine-tuned adapter may have memorised it. Deleting the source row while the vector index still returns the chunk is a deletion that exists only in the ticket.

Keep a tombstone with the subject id, the stores that acknowledged and the timestamp. The tombstone contains no personal data, so it can outlive the records it describes, and it is what lets a later audit answer whether the deletion completed.

A backup is a copy with its own clock. Either the backup expires within the promised window, or the restore procedure has to replay deletions before the data is served again. A fine-tune is the same problem with no expiry date.

Requests, and the record of them

A subject access request asks what you hold, and a deletion request asks you to stop holding it. Both need an index from a person to their records, and most systems do not have one. An email address is a start, but it appears in free text, in a hash and inside a prompt.

Pseudonymisation helps the join without keeping the identifier in every store. Store a keyed hash of the subject id beside the record, keep the key in a separate system, and the trace can be linked to a request without carrying the email. Deleting the key is then a second, cheaper deletion path.

Answer within the legal window, and answer in the same units the request used. A response that lists six rows when the user asked about their account is a response that will be disputed. The record of the request, the search performed and the stores covered belongs in the audit log, not in the response.

Erase one subject from every store

Run the fan-out and confirm every store reports. Then add an eval store that holds a rewritten case for the same subject and make the deletion cover it too.

Output
Click "Run" to execute your code

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

Why is minimisation stronger than redaction?