Chapter 4 — Privacy and data protection: guided lab and applied synthesis
Lesson map
Lesson 04 published. Map, example, EX057.
flowchart TD
N0["Learning outcomes"]
N1["4.1 The guided lab"]
N2["4.2 Interpreting the lab"]
N3["4.3 A short plan"]
N4["4.4 Presenting to the owner"]
N5["4.5 Checking and next steps"]
N6["Lab — Loyalty app fields versus stated purposes"]
N7["Concepts — the script tests names, not values"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
N7 --> EX["Worked example"]
EX --> Q["Exercise EX057"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["4.1 The guided lab"]
N2["4.2 Interpreting the lab"]
N3["4.3 A short plan"]
N4["4.4 Presenting to the owner"]
N5["4.5 Checking and next steps"]
N6["Lab — Loyalty app fields versus stated purposes"]
N7["Concepts — the script tests names, not values"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX057"]
[Learning outcomes]
|
v
[4.1 The guided lab]
|
v
[4.2 Interpreting the lab]
|
v
[4.3 A short plan]
|
v
[4.4 Presenting to the owner]
|
v
[4.5 Checking and next steps]
|
v
[Lab — Loyalty app fields versus stated purposes]
|
v
[Concepts — the script tests names, not values]
|
v
[Worked example] --> [Exercise EX057]
Learning outcomes
You will (1) run a guided minimisation lab; (2) combine findings into a short plan; (3) present recommendations to a business owner.
4.1 The guided lab
Mr. Patel guides Sofia through a lab using the loyalty app's synthetic sign-up form and the purposes Juniper states in its notice: earning and spending points, a birthday voucher and marketing emails for those who agree. The lab compares each field collected with the fields each purpose needs. It shows that the app collects ten fields and five of them, 50%, are not needed for any stated purpose: phone, postcode, prescription items, gender and a location trail recorded by the app in the background.
4.2 Interpreting the lab
Sofia considers each unneeded field. Prescription items are health data with no stated purpose in the scheme. The location trail tracks customers' movements, which is intrusive and unexpected. Gender, postcode and phone may have been added by the vendor's default template. Mr. Patel reminds her that collecting data for no stated purpose breaks the minimisation principle and the purpose limitation principle, and that health data in a loyalty scheme also lacks the Article 9 condition it would need. None of the five fields serves a stated purpose.
4.3 A short plan
Sofia combines her findings from the month into a one-page plan with five actions: remove the five unneeded fields and stop the till sending medicine items to the loyalty vendor; sign data protection contracts with the loyalty and delivery firms; set retention periods for loyalty, delivery and newsletter data; replace counter photos with customer-free images; and keep the storeroom locked with a shredding routine. Each action has an owner, a cost estimate and a target date within three months. The plan fits on one page.
4.4 Presenting to the owner
Sofia presents the plan to Juniper's owner in fifteen minutes. She starts with the most serious issue, medicine purchases reaching the loyalty vendor, and explains it in plain words: customers' health purchases are being shared with an app company without a reason or their knowledge. The owner asks whether removing fields will reduce the app's value. Sofia shows that points and vouchers work with the remaining fields. The owner approves all five actions and asks the vendor to make the changes. She answers calmly.
4.5 Checking and next steps
Two weeks later, Sofia and Mr. Patel check the loyalty app with a new synthetic sign-up. The form now asks for five fields, and the till export contains no medicine items, only total spend and non-medicine categories. The contracts are in negotiation. Mr. Patel explains that checking after a change confirms that the plan worked rather than assuming it did. Sofia plans her next course step, governance, risk and compliance, to learn how businesses keep such improvements in place over time. The course ends.
Lab — Loyalty app fields versus stated purposes
"""Compare fields collected by a synthetic pharmacy loyalty app with fields its purposes need (stdlib only)."""
collected = ["name", "email", "phone", "date_of_birth", "postcode", "purchase_history",
"prescription_items", "gender", "location_trail", "marketing_choice"]
needs = {
"earn and spend points": {"name", "email", "purchase_history"},
"birthday voucher": {"email", "date_of_birth"},
"marketing emails": {"email", "marketing_choice"},
}
used = set().union(*needs.values())
unneeded = [f for f in collected if f not in used]
for f in collected:
print(f"{f:20s} {'needed' if f in used else 'NOT NEEDED'}")
print(f"fields collected {len(collected)}; not needed for any stated purpose {len(unneeded)} ({100*len(unneeded)/len(collected):.0f}%)")
Run with python3 lab_loyalty.py. Verified output:
name needed
email needed
phone NOT NEEDED
date_of_birth needed
postcode NOT NEEDED
purchase_history needed
prescription_items NOT NEEDED
gender NOT NEEDED
location_trail NOT NEEDED
marketing_choice needed
fields collected 10; not needed for any stated purpose 5 (50%)
Worked example
Sofia finds five of ten loyalty fields (50%) unneeded, including prescription items and a location trail, combines the month's findings into a five-action plan, gains the owner's approval and confirms the app changes.
Synthetic case. The app is synthetic; GDPR Articles 5 and 9 are real.
Errors and limits
Purposes listed in a notice may be incomplete; ask the business whether any other purpose exists before deleting fields.
Concepts — the script tests names, not values
lab_loyalty.py builds used as the union of the three purpose sets, then asks whether each collected name is in that union. A field prints needed when its name is a member. The script never opens the field and reads what was stored inside it.
| Step | What the script uses | What it cannot see |
|---|---|---|
Build used |
The union of points, birthday voucher and marketing emails | Whether that purpose is lawful |
| Mark each collected name | Membership of the name in used |
The values stored under the name |
| Count | Names in collected that are absent from used |
A medicine hidden inside purchase_history |
purchase_history is in the points set, so the script prints needed. prescription_items is in no set, so it prints NOT NEEDED. The later till check is a second test: total spend and non-medicine categories may remain; a medicine name may not. Passing the field list does not pass the content check.
Data — membership against the three sets
| Collected name | Purpose set that contains it | Script mark | Content rule from the two-week check |
|---|---|---|---|
| name, email | Points | needed | Stay |
| date_of_birth | Birthday voucher | needed | Stay |
| marketing_choice | Marketing emails | needed | Stay |
| purchase_history | Points | needed | Must not carry a medicine name |
| phone, postcode, gender, location_trail, prescription_items | None | NOT NEEDED | Remove |
The count stays the verified one: 10 collected names, 5 absent from the union.
Decision flow — someone says the form is fixed
flowchart TD
A["A claim that the loyalty change is done"] --> B["Run lab_loyalty.py on the new form"]
B --> C{"Are phone, postcode, prescription_items, gender and location_trail absent?"}
C -->|No| D["The field check failed"]
C -->|Yes| E{"Does the till export still name a medicine?"}
E -->|Yes| F["The field list passed and the content check failed"]
E -->|No| G["Both checks passed: five fields, totals and non-medicine categories"]
D --> H["Write which check failed, and the date. Leave the action open"]
F --> H
G --> I["Record both results. The action can close"]
Worked example — five clean names, one insulin line
The new form asks for name, email, date of birth, purchase history and the marketing choice. Sofia runs the script. All five names sit in the union, and none of the five rejected names remains. She then opens one night's till export and finds a line that reads insulin. The field check has passed. The content check has failed, because purchase_history is allowed as a name and the script never reads inside it. She leaves the action open and tells the owner that the export still carries a medicine. Points and the birthday voucher do not need that name.
Synthetic case. Vial-44021 in the Tuesday-night file is invented. The membership rule is the one in lab_loyalty.py. This is not legal advice.
Apply
- EX057 — Inside the field. Why can
purchase_historyprintneededwhile an insulin line stored in it is still a failure? Rubric: 3 = the script tests the field name against the union, not the values inside the field; a medicine name must stay out of the export;; 2 = the script does not read inside the field;; 1 = vague;; 0 = none. - EX058 — Two checks. The form has the five allowed fields and the export still lists insulin. Which check passed, which failed, and does Sofia close the action? Rubric: 3 = the field check passed; the content check failed; she does not close the action;; 2 = she does not close it;; 1 = she closes it;; 0 = none.
Exercises
- EX039 — Unneeded share. What share of loyalty fields were unneeded? Rubric: 3 = 5 of 10, 50%;; 2 = partly correct;; 1 = wrong;; 0 = none.
- EX040 — Location trail. Why is the location trail a concern? Rubric: 3 = intrusive and unexpected tracking;; 2 = mentions tracking;; 1 = vague;; 0 = none.
- EX041 — Vendor defaults. Where might gender, postcode and phone have come from? Rubric: 3 = the vendor's default template;; 2 = partly correct;; 1 = vague;; 0 = none.
- EX042 — Principles broken. Which two principles does unneeded collection break? Rubric: 3 = minimisation and purpose limitation;; 2 = both;; 1 = one;; 0 = none.
- EX043 — Plan actions. How many actions does Sofia's plan contain? Rubric: 3 = five;; 2 = partly correct;; 1 = wrong;; 0 = none.
- EX044 — Plan details. What does each action have? Rubric: 3 = owner, cost estimate, target date;; 2 = most;; 1 = one;; 0 = none.
- EX045 — Lead issue. Which issue did Sofia present first? Rubric: 3 = medicine purchases reaching the loyalty vendor;; 2 = partly correct;; 1 = other;; 0 = none.
- EX046 — Owner concern. What did the owner worry about? Rubric: 3 = removing fields reducing app value;; 2 = partly correct;; 1 = vague;; 0 = none.
- EX047 — Remaining fields. How many fields does the form ask for after the change? Rubric: 3 = five;; 2 = partly correct;; 1 = ten;; 0 = none.
- EX048 — Till export. What does the till export contain now? Rubric: 3 = total spend and non-medicine categories;; 2 = partly correct;; 1 = medicines;; 0 = none.
- EX049 — Post-change check. Why check after a change? Rubric: 3 = to confirm the plan worked;; 2 = mentions confirmation;; 1 = vague;; 0 = none.
- EX050 — Next study. What does Sofia plan to study next? Rubric: 3 = governance, risk and compliance;; 2 = partly correct;; 1 = vague;; 0 = none.
Continue studying — lesson 04 (chapter 04 of 04)
← Chapter 03 · Course chapter index · Next course via chapter index →
The chapter index leads to the next course in the study path.