Khurram Badar / Archive / Courses / The certification client - Data Protection for Teachers: course content production

The certification client - Data Protection for Teachers: course content production

course · 2026-08-09 · 7468 words · Khurram Badar · for teachers · intro

/usr/bin/env python3 the certification client - Data Protecti...

education · legal · uae

#!/usr/bin/env python3
# the certification client - Data Protection for Teachers: course content production
# Builds: (1) Content Master (all 9 lessons + Final Check), (2) Principal Review Pack (L6, L9, one-pager)

from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.lib import colors
from reportlab.lib.styles import ParagraphStyle
from reportlab.platypus import (BaseDocTemplate, PageTemplate, Frame, Paragraph,
Spacer, Table, TableStyle, KeepTogether)

FOREST = colors.HexColor("#1B4332")
DEEP = colors.HexColor("#0B2A1C")
GOLD = colors.HexColor("#B08425")
CREAM = colors.HexColor("#F4F7F4")
INK = colors.HexColor("#20261F")

PAGE_W, PAGE_H = A4
M_L, M_R, M_T, M_B = 18*mm, 18*mm, 24*mm, 18*mm
CW = PAGE_W - M_L - M_R

def esc(t):
return t.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")

S_title = ParagraphStyle("t", fontName="Helvetica-Bold", fontSize=20, leading=24, textColor=colors.white)
S_sub = ParagraphStyle("s", fontName="Helvetica", fontSize=11, leading=14.5, textColor=CREAM)
S_meta = ParagraphStyle("m", fontName="Helvetica", fontSize=9.3, leading=12.6, textColor=colors.white)
S_h1 = ParagraphStyle("h1", fontName="Helvetica-Bold", fontSize=13.5, leading=17, textColor=DEEP,
spaceBefore=12, spaceAfter=5)
S_h2 = ParagraphStyle("h2", fontName="Helvetica-Bold", fontSize=10.6, leading=13.5, textColor=FOREST,
spaceBefore=7, spaceAfter=3)
S_body = ParagraphStyle("b", fontName="Helvetica", fontSize=9.5, leading=13, textColor=INK, spaceAfter=4)
S_bul = ParagraphStyle("bu", parent=S_body, leftIndent=9, spaceAfter=2.5)
S_habit = ParagraphStyle("hb", fontName="Helvetica-Bold", fontSize=9.6, leading=12.6, textColor=colors.white)
S_cell = ParagraphStyle("c", fontName="Helvetica", fontSize=8.7, leading=11.3, textColor=INK)
S_cellb = ParagraphStyle("cb", parent=S_cell, fontName="Helvetica-Bold")
S_cellw = ParagraphStyle("cw", fontName="Helvetica-Bold", fontSize=8.8, leading=11.3, textColor=colors.white)
S_note = ParagraphStyle("n", fontName="Helvetica-Oblique", fontSize=8.7, leading=11.6, textColor=FOREST, spaceAfter=4)
S_src = ParagraphStyle("sr", fontName="Helvetica-Oblique", fontSize=8.4, leading=11, textColor=FOREST, spaceAfter=6)

def P(t, s=S_body): return Paragraph(esc(t), s)
def PM(t, s=S_body): return Paragraph(t, s)
def B(t): return PM("&bull;&nbsp; " + esc(t), S_bul)

def make_doc(path, running_title, subject):
def hf(canv, doc):
canv.saveState()
canv.setFillColor(FOREST); canv.rect(0, PAGE_H-14*mm, PAGE_W, 14*mm, stroke=0, fill=1)
canv.setFillColor(GOLD); canv.rect(0, PAGE_H-15.2*mm, PAGE_W, 1.2*mm, stroke=0, fill=1)
canv.setFillColor(colors.white); canv.setFont("Helvetica-Bold", 8.4)
canv.drawString(M_L, PAGE_H-9.2*mm, running_title)
canv.setFont("Helvetica", 8.4)
canv.drawRightString(PAGE_W-M_R, PAGE_H-9.2*mm, "9 August 2026")
canv.setFillColor(FOREST); canv.setFont("Helvetica", 7.8)
canv.drawString(M_L, 10*mm, "the certification client - internal working document")
canv.drawRightString(PAGE_W-M_R, 10*mm, f"Page {doc.page}")
canv.setStrokeColor(GOLD); canv.setLineWidth(0.8)
canv.line(M_L, 13.5*mm, PAGE_W-M_R, 13.5*mm)
canv.restoreState()
d = BaseDocTemplate(path, pagesize=A4, leftMargin=M_L, rightMargin=M_R,
topMargin=M_T, bottomMargin=M_B, title=subject,
author="Khurram Badar - Platform Architect")
d.addPageTemplates([PageTemplate(id="all",
frames=[Frame(M_L, M_B, CW, PAGE_H-M_T-M_B, id="f")], onPage=hf)])
return d

def cover(lines_title, lines_sub, lines_meta):
rows = [[Paragraph(esc(t), S_title)] for t in lines_title]
rows.append([Spacer(1, 4)])
for s in lines_sub:
rows.append([Paragraph(esc(s), S_sub)])
rows.append([Spacer(1, 6)])
for m in lines_meta:
rows.append([Paragraph(esc(m), S_meta)])
t = Table(rows, colWidths=[CW])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), DEEP),
("LEFTPADDING", (0,0), (-1,-1), 14), ("RIGHTPADDING", (0,0), (-1,-1), 14),
("TOPPADDING", (0,0), (-1,0), 13), ("BOTTOMPADDING", (0,-1), (-1,-1), 13),
("LINEBELOW", (0,-1), (-1,-1), 2, GOLD),
]))
return t

def habit_bar(text):
t = Table([[Paragraph("ANY-TUESDAY HABIT&nbsp;&nbsp;|&nbsp;&nbsp; " + esc(text), S_habit)]], colWidths=[CW])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), FOREST),
("LEFTPADDING", (0,0), (-1,-1), 9), ("RIGHTPADDING", (0,0), (-1,-1), 9),
("TOPPADDING", (0,0), (-1,-1), 5), ("BOTTOMPADDING", (0,0), (-1,-1), 5),
]))
return t

def tbl(data, widths):
t = Table(data, colWidths=widths, repeatRows=1)
st = [("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 5), ("RIGHTPADDING", (0,0), (-1,-1), 5),
("TOPPADDING", (0,0), (-1,-1), 3.4), ("BOTTOMPADDING", (0,0), (-1,-1), 3.4),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#C9D6CC")),
("BACKGROUND", (0,0), (-1,0), FOREST)]
for i in range(1, len(data)):
if (i-1) % 2 == 1:
st.append(("BACKGROUND", (0,i), (-1,i), CREAM))
t.setStyle(TableStyle(st))
return t

def checkpoints(rows):
data = [[Paragraph("#", S_cellw), Paragraph("Checkpoint - what do you do?", S_cellw),
Paragraph("Correct response", S_cellw)]]
for i, (q, a) in enumerate(rows, 1):
data.append([Paragraph(str(i), S_cellb), Paragraph(esc(q), S_cell), Paragraph(esc(a), S_cell)])
return tbl(data, [8*mm, (CW-8*mm)*0.47, (CW-8*mm)*0.53])

============================================================

def lesson_1(story):
story.append(P("Lesson 1. What personal data is - and what this platform holds about you", S_h1))
story.append(habit_bar("Name the data before you use it."))
story.append(Spacer(1, 5))
story.append(P("Every school day you handle information about real people. This lesson gives you the words the law uses - "
"and it starts by being straight with you about what this course itself holds about you."))
story.append(P("The law's own definitions", S_h2))
for t in [
"Personal data: any data related to a specific natural person, or to a person who can be identified directly or "
"indirectly - through name, voice, image, identification number, electronic identifier, geographic location, or "
"physical, physiological, economic, cultural or social characteristics. [Art. 1]",
"Sensitive personal data: data that directly or indirectly reveals family, ethnic origin, political or philosophical "
"opinions, religious beliefs, criminal record, biometric data, or anything about health and physical, psychological, "
"mental, genetic or sexual condition. [Art. 1]",
"Biometric data: data produced by a specific technology relating to physical, physiological or behavioural "
"characteristics that allows unique identification - facial images or fingerprints, for example. [Art. 1]",
"Processing: almost anything you can do with data - collecting, storing, recording, organising, using, sharing, "
"transmitting, disclosing, erasing. If you touched it, you processed it. [Art. 1]",
]:
story.append(B(t))
story.append(P("Who is who", S_h2))
for t in [
"Data subject - the person the data is about: a student, a parent, a colleague. [Art. 1]",
"Controller - the organisation that decides how and why data is processed. For your students' data, that is the school.",
"Processor - anyone processing on the school's behalf and under its instructions: a platform, a vendor, a supplier.",
"You are neither. You act for the Controller. That distinction is the most freeing thing in this course - the "
"institution carries the legal weight, and your job is to handle well and route fast.",
]:
story.append(B(t))
story.append(P("In our school", S_h2))
for t in [
"A class list is personal data. A seating plan with photographs is personal data.",
"A note that a child is fasting, has a nut allergy, sees the counsellor, or has a learning plan - that is sensitive personal data.",
"A fingerprint or face scanner is biometric data, which is sensitive by definition.",
]:
story.append(B(t))
story.append(P("What this course holds about you", S_h2))
story.append(P("Your school email address, your progress through the lessons, your checkpoint scores, and your certificate "
"record. Your school can see completion and scores. That is the whole list. We are teaching you to ask "
"organisations this question, so we answer it first."))
story.append(checkpoints([
("A seating plan with names and photographs - is it personal data?",
"Yes. Names identify directly; photographs are identifying images. Treat it as personal data."),
("Your notes say a student has been referred to the school counsellor. Which category?",
"Sensitive personal data - it relates to psychological condition. Higher care, need-to-know only."),
("You forward a class list to your personal email to work at home. Is that processing?",
"Yes - transmitting and making available are processing. It also moves school data outside school systems: don't."),
]))
story.append(PM("<i>" + esc("Source: Federal Decree-Law No. 45 of 2021, Article 1 (Definitions), official English text, "
"UAE Legislation portal. The portal states that in case of conflict the original Arabic text prevails.") + "</i>", S_src))

def lesson_2(story):
story.append(P("Lesson 2. A school runs on personal data", S_h1))
story.append(habit_bar("Collect the minimum needed, nothing more."))
story.append(Spacer(1, 5))
story.append(P("A school is one of the most data-rich organisations a child will ever encounter. Before we talk about rules, "
"it is worth seeing the scale of what we hold."))
story.append(P("What the school holds", S_h2))
for t in [
"Enrolment records, family details, contact numbers, addresses.",
"Attendance, marks, reports, target grades, assessment history.",
"Behaviour logs, incident notes, learning plans and support records.",
"Photographs, video, displays, newsletters and social posts.",
"Medical information held by the clinic; staff records held by HR.",
]:
story.append(B(t))
story.append(P("The seven controls the law sets for handling it", S_h2))
story.append(P("Processing must be fair, transparent and lawful; data collected for a specific and clear purpose and not "
"later used in a way incompatible with it; sufficient and limited to what is necessary; accurate and updated; "
"incorrect data deleted or corrected; kept securely against unauthorised processing; and not kept once the "
"purpose is exhausted. [Art. 5]"))
story.append(P("The habit this produces", S_h2))
for t in [
"Before you create a list, ask what the smallest version of it is that still does the job.",
"Before you copy data somewhere new, ask whether the copy is necessary or merely convenient.",
"The spreadsheet that quietly grows extra columns is the most common failure in any school.",
"Old files matter: last year's mark sheet sitting in your Downloads folder is data kept past its purpose.",
]:
story.append(B(t))
story.append(P("One scope note on medical information", S_h2))
story.append(P("The law excludes from its scope personal health data that has its own legislation regulating protection and "
"processing [Art. 2(2)(e)]. Which rules govern a particular school medical record is a legal determination for "
"the school, not a judgement for a teacher to make. Your practical rule does not change either way: medical "
"information is the most sensitive thing you touch, it lives with the clinic, and you do not keep copies."))
story.append(checkpoints([
("You need to know which students have PE exemptions this term. What is the minimum data?",
"The exemption status and dates - not the diagnosis. The reason lives with the clinic."),
("Last year's full mark sheet is still on your desktop. What does the purpose rule point to?",
"The purpose is exhausted. Remove your copy; the record lives in the school system, not on your machine."),
("A colleague asks you to send the full parent contact list 'just in case'.",
"Ask what purpose it serves and share only what that purpose needs. If it is not clear, route it rather than send it."),
]))
story.append(PM("<i>" + esc("Source: Federal Decree-Law No. 45 of 2021, Articles 2 and 5. Illustrative record categories drawn "
"from reported ADEK record-keeping requirements (Abu Dhabi), used as illustration only - ADEK does not govern Dubai.") + "</i>", S_src))

def lesson_3(story):
story.append(P("Lesson 3. The school's lawful bases in practice", S_h1))
story.append(habit_bar("Extras need a yes that is real."))
story.append(Spacer(1, 5))
story.append(P("This is the lesson most often taught wrongly, and the error causes real harm in schools. Read it carefully."))
story.append(P("Where the law starts", S_h2))
story.append(P("Processing personal data without the owner's consent is prohibited - and the law then sets out eleven "
"situations excluded from that prohibition. [Art. 4]"))
story.append(P("What actually carries the school day", S_h2))
for t in [
"Processing necessary to perform a contract to which the data subject is a party. [Art. 4(9)] The enrolment contract "
"is why registers, marks, reports and timetables do not need a permission slip.",
"Processing necessary to fulfil specific obligations set out in other laws in force for the Controller. [Art. 4(10)] "
"This is why regulatory reporting happens without asking each family.",
"Other listed exclusions include protecting the vital interests of the data subject and processing connected to legal "
"claims, judicial or security procedures. [Art. 4]",
]:
story.append(B(t))
story.append(P("So: you do not need consent to mark homework, take a register, or write a report. Teaching otherwise creates "
"two bad outcomes - staff paralysed by imaginary paperwork, and schools telling families 'you consented' about "
"things consent never covered."))
story.append(P("Where consent genuinely governs", S_h2))
for t in [
"The extras: optional apps, public sharing, promotional photography and video, anything beyond the school's core job.",
"Consent must be provable by the school, prepared clearly, simply and unambiguously, easily accessible, and include the "
"right to withdraw easily. Withdrawing does not undo processing that was lawful before. [Art. 6]",
]:
story.append(B(t))
story.append(P("And the hard part - consent can fail", S_h2))
story.append(P("In a Swedish case, a school ran facial recognition to take attendance and had obtained student consent. The "
"regulator ruled the consent invalid, because students depend on the school and cannot freely refuse. Where "
"there is dependence, consent is weak. That is exactly why the school leans on contract and legal duty for "
"core work, and reserves consent for situations where a real 'no' carries no penalty."))
story.append(checkpoints([
("Do you need a parent's consent to record attendance?",
"No. Attendance sits under the enrolment contract and the school's legal duties, not consent."),
("Do you need consent to post a child's photograph on the school's public page?",
"Yes - this is an extra. Check the consent position the school holds before posting, not after."),
("A student says quietly that they would rather not appear in the promotional video.",
"Honour it without argument or consequence. If a no is not truly free, the consent was never valid."),
]))
story.append(PM("<i>" + esc("Source: Federal Decree-Law No. 45 of 2021, Articles 4 and 6. Swedish case: decision of the Swedish "
"data protection authority, 2019, as reported by the EDPB and the IAPP.") + "</i>", S_src))

def lesson_4(story):
story.append(P("Lesson 4. The rights people hold", S_h1))
story.append(habit_bar("Rights requests get routed the same day."))
story.append(Spacer(1, 5))
story.append(P("Parents and students hold rights they can exercise at any time, usually in ordinary words rather than legal "
"ones. Your job is not to answer them. It is to recognise them and route them the same day."))
rows = [
("Art. 13", "Right to receive information", "What data is processed, why, decisions made by automated processing, who it is shared with, retention, correction procedures, cross-border safeguards, what happens after a breach, how to complain to the regulator"),
("Art. 13(2)", "Told before processing starts", "Purposes, the sectors or establishments data will be shared with, and cross-border safeguards must be given up front - this is what a privacy notice is for"),
("Art. 14", "Right to request transfer", "Receive their data in an orderly, machine-readable form, and ask for transfer to another controller where technically feasible"),
("Art. 15", "Correction or erasure", "Correct inaccurate data without undue delay; request erasure in defined cases - erasure is not automatic and has stated exceptions"),
("Art. 16", "Restrict processing", "Require the school to restrict and stop processing in defined situations, including disputed accuracy"),
("Art. 17", "Object and stop", "Object to processing for direct marketing, for statistical surveys, or where processing breaches the Article 5 controls"),
("Art. 18", "Automated decisions", "Object to decisions produced by automated processing, including profiling. The Controller must include the human element in reviewing an automated decision when the person asks"),
("Art. 19", "Being able to reach us", "The school must provide clear and appropriate ways to be contacted about these rights"),
("Art. 24", "Complaints", "A person may complain to the regulator if they believe the law is being breached"),
]
data = [[Paragraph("Article", S_cellw), Paragraph("Right", S_cellw), Paragraph("What it means in practice", S_cellw)]]
for a, r, m in rows:
data.append([Paragraph(esc(a), S_cellb), Paragraph(esc(r), S_cellb), Paragraph(esc(m), S_cell)])
story.append(tbl(data, [17*mm, 36*mm, CW-17*mm-36*mm]))
story.append(P("How these arrive in real life", S_h2))
for t in [
"'Can I see everything you hold on my son?' - that is an Article 13 request.",
"'That is wrong, change it.' - Article 15.",
"'Take that photo down.' - Article 15, and a consent question underneath it.",
"'A computer decided her set placement. I want a person to look at it.' - Article 18, and the answer is yes, a person will.",
]:
story.append(B(t))
story.append(P("What you do: acknowledge that you have heard it, promise nothing about the outcome, and route it the same day. "
"What you do not do: answer it yourself, guess at what the school holds, or let it sit until the weekend."))
story.append(checkpoints([
("A parent asks to see everything the school holds about their daughter.",
"Recognise it as an information request, acknowledge it, route the same day. Do not start assembling files yourself."),
("A parent demands the school delete their child's record entirely.",
"Route it. Erasure is a real right with stated exceptions - the school decides, not you, and not on the spot."),
("A parent objects to a placement they believe a system generated automatically.",
"Route it as an automated-decision objection. Human review at the person's request is written into the law."),
]))
story.append(PM("<i>" + esc("Source: Federal Decree-Law No. 45 of 2021, Articles 13 to 19 and 24, official English text.") + "</i>", S_src))

def lesson_5(story):
story.append(P("Lesson 5. Children's data is different", S_h1))
story.append(habit_bar("For children the bar is higher - default to less."))
story.append(Spacer(1, 5))
story.append(P("Everything so far applies to adults and children alike. This lesson is about where the bar rises."))
story.append(P("The Child Digital Safety Law", S_h2))
for t in [
"Federal Decree-Law No. 26 of 2025 on Child Digital Safety came into force on 1 January 2026, with compliance required by January 2027.",
"A child is anyone under 18.",
"It applies to digital platforms and internet service providers operating in or targeting users in the UAE, and it places duties on children's caregivers.",
"Platforms are prohibited from collecting, processing, publishing or sharing the personal data of children under 13, except under specified conditions; platforms used for educational or health purposes may be exempted under conditions.",
"Privacy-by-default for children, age verification matched to platform risk, and verifiable parental consent for under-13 processing are the baseline expectations. A Child Digital Safety Council is established.",
]:
story.append(B(t))
story.append(P("What this means for a school", S_h2))
story.append(P("The school is not the primary regulated entity - platforms and providers are. But every platform we put in "
"front of a child now sits under this law, and we should be able to explain why we chose it. That is why new "
"tools go through the school, not through an individual classroom."))
story.append(P("The case worth remembering", S_h2))
for t in [
"A school in Skelleftea, Sweden, trialled facial recognition to register attendance: 22 students, three weeks.",
"The regulator fined the municipality SEK 200,000, roughly EUR 20,000 - the country's first fine under the European regulation.",
"Three failures: sensitive biometric data of children; consent invalid because students depend on the school; and no impact assessment before starting.",
"The decisive point: attendance can be taken in less intrusive ways, so the technology was disproportionate to the purpose.",
"Notice who paid. The fine landed on the municipality - the institution - not on a teacher. Institutions carry this weight. Your job is to notice and route.",
]:
story.append(B(t))
story.append(P("Our own law makes the same demand from the other direction: before processing that uses modern technologies "
"posing high risk to privacy, the Controller must assess the impact of the proposed processing - and an "
"assessment is expressly required where processing involves a large volume of sensitive personal data. [Art. 21] "
"That is precisely the step the Swedish school skipped."))
story.append(checkpoints([
("An app asks your Grade 3 class to create their own accounts with email addresses and profile photographs.",
"Stop and route to leadership. Under-13 processing on an outside platform is exactly what the child-safety law addresses."),
("A vendor offers free fingerprint attendance scanning for your corridor.",
"Route, do not pilot. Biometric data, children, and a less intrusive alternative that already works."),
("A colleague says the students all agreed, so the trial is fine.",
"Agreement from students who depend on the school is not reliable consent. That is the exact finding in the Swedish case."),
]))
story.append(PM("<i>" + esc("Sources: Federal Decree-Law No. 26 of 2025 (official UAE Legislation portal announcement; law-firm "
"analyses January-February 2026); Federal Decree-Law No. 45 of 2021, Article 21; Swedish regulator's 2019 decision.") + "</i>", S_src))

def lesson_6(story):
story.append(P("Lesson 6. The teacher's daily practice", S_h1))
story.append(habit_bar("Unsure if consent covers it - ask before posting."))
story.append(Spacer(1, 5))
story.append(P("This is the lesson that changes Tuesdays. Everything here is something you will do this week."))
story.append(P("The professional standard you already work to", S_h2))
for t in [
"Published expectations for educational staff include avoiding disclosure of confidential information about students and families outside safeguarding policy.",
"They also expect technology, including artificial intelligence, to be used legally, ethically and transparently, respecting privacy and rights - and expressly not using AI to replace human judgment in student-related matters.",
"Breaches of confidentiality sit among the serious professional-standards failures that can lead to regulatory action against staff.",
"Worth noticing: the regulator says do not let AI replace human judgment about students, and the data-protection law gives a person the right to demand human review of an automated decision. Two separate instruments, one principle.",
]:
story.append(B(t))
story.append(P("Class groups and messaging channels", S_h2))
story.append(P("Which channels the school uses is a decision for school leadership, not for this course and not for an "
"individual teacher. What this course does set is what never goes into a group, whichever channel it is:"))
for t in [
"Marks, grades, rankings or comparisons between children.",
"Medical or wellbeing information of any kind.",
"Anything about somebody else's child.",
"Personal contact details of families.",
"A simple test: if you would not read it aloud in a corridor, it does not go in a group.",
]:
story.append(B(t))
story.append(P("Photographs and displays", S_h2))
for t in [
"Before posting or displaying a photograph, check the consent position the school holds for that child.",
"If you are unsure what the school's enrolment paperwork covers, ask before posting. Asking takes a minute; removal is never fully possible.",
"Take the same care with wall displays carrying full names alongside work or achievement.",
]:
story.append(B(t))
story.append(P("Marks and reports", S_h2))
for t in [
"Share on a need-to-know basis only. A parent is entitled to detail about their own child, and to nothing about anyone else's.",
"No full class results to an individual parent. No results in group chats. No open mark sheets on a projector.",
]:
story.append(B(t))
story.append(P("AI tools", S_h2))
for t in [
"Use the school's authorised tools list - the same list taught in the AI course. If a tool is not on it, it is not approved for student data, however useful it looks.",
"Never paste identifiable student work into an unapproved tool. Remove names and identifying details before you paste anything anywhere.",
"AI can help you think. It does not make the judgment about a child - that stays with you, and both the regulator and the law say so.",
]:
story.append(B(t))
story.append(P("Four corridor answers - learn these", S_h2))
ca = [
("'How does my son compare with the rest of the class?'",
"'I can go through your son's progress in as much detail as you like. I can't share other children's results with you - and I wouldn't share his with them either.'"),
("'Why is my daughter's photograph on the school page?'",
"'Let me check what we hold for her and come back to you today. I'll pass it to [ROLE] straight away.'"),
("'Add me to the class group.'",
"'Group membership is set by the school rather than by me - I'll pass your request on today.'"),
("'Just delete everything you have about him.'",
"'That's a formal request and you're entitled to make it. I'll route it today to [ROLE], who will come back to you.'"),
]
data = [[Paragraph("What you hear", S_cellw), Paragraph("What you say - about fifteen seconds", S_cellw)]]
for q, a in ca:
data.append([Paragraph(esc(q), S_cellb), Paragraph(esc(a), S_cell)])
story.append(tbl(data, [CW*0.34, CW*0.66]))
story.append(P("Every one of them ends the same way: you are not deciding alone, and the parent leaves knowing something will happen.", S_note))
story.append(checkpoints([
("A parent presses you at the gate for the class ranking.",
"Decline the comparison warmly, offer full detail on their own child, and route the request. Use the corridor answer."),
("You want to paste a student's essay into an AI tool to help with marking.",
"Only if the tool is on the school's authorised list, and only with identifying details removed. If it is not on the list, do not."),
("A medical note about a child is posted into the class group by mistake.",
"Do not forward or comment. Report it to leadership the same day and ask for removal - this is a data breach, and Lesson 7 covers it."),
]))
story.append(PM("<i>" + esc("Sources: KHDA technical guide on staff deregistration, underpinned by the UAE Code of Conduct for "
"educational staff; Federal Decree-Law No. 45 of 2021, Article 18(4); school authorised-tools list as taught in the AI course.") + "</i>", S_src))

def lesson_7(story):
story.append(P("Lesson 7. When something goes wrong", S_h1))
story.append(habit_bar("Escalate first, investigate second."))
story.append(Spacer(1, 5))
story.append(P("Data goes astray in every organisation on earth. What separates a well-run school from a badly-run one is "
"not whether it happens - it is what happens in the first hour."))
story.append(P("What the law asks of the school", S_h2))
for t in [
"When the Controller becomes aware of a breach or violation that would prejudice the privacy, confidentiality or security "
"of a person's data, it must notify the regulator - with a description of the breach, its causes and approximate scale, "
"the data protection officer's details, likely effects, and the corrective measures taken. [Art. 9(1)]",
"The school must also notify the affected person where the breach would prejudice the privacy and confidentiality of their data. [Art. 9(2)]",
"A processor who becomes aware of a breach must notify the Controller as soon as it becomes aware. [Art. 9(3)]",
]:
story.append(B(t))
story.append(P("An honest note about timing", S_h2))
story.append(P("The law says notification happens within the period set by its Executive Regulations. As at 9 August 2026, "
"primary legal trackers report those Regulations as not yet issued, and practitioner reporting on their status "
"is openly inconsistent. So we do not teach you a number the law has not fixed. What we teach instead is the "
"part fully within our control: inside this school, escalation happens the same day, every time. If a clock is "
"running, we are already moving."))
story.append(P("What counts as something going wrong", S_h2))
for t in [
"A message or email sent to the wrong recipient.",
"A lost or stolen phone, laptop or memory stick with school data on it.",
"A shared or borrowed login, or a password written where others can see it.",
"An open mark sheet on a projector, or a document left on a printer.",
"A file shared with a link that turns out to be public.",
"Anything you would rather nobody found out about - that instinct is the signal, not the reason to stay quiet.",
]:
story.append(B(t))
story.append(P("The first hour", S_h2))
for t in [
"Note the time and what happened while it is fresh.",
"Contain what you safely can - stop the sharing, close the link, secure the device.",
"Escalate the same day through the route in Lesson 9.",
"Do not investigate alone, do not delete anything, do not quietly ask the recipient to delete it before you have told the school, and do not wait to see whether it matters.",
"You are not the Controller. Noticing and escalating is the whole of your job here - and it is the part that protects everyone.",
]:
story.append(B(t))
story.append(checkpoints([
("Twenty minutes ago you emailed a report card to the wrong parent.",
"Escalate now. Record the time, do not chase the recipient first, and let the school decide on notification."),
("Your school laptop was taken from your car overnight.",
"Same-day escalation. Assume it holds data even if you believe it does not."),
("A colleague says no harm was done and suggests letting it go.",
"Escalate anyway. That judgment belongs to the school as Controller, not to either of you."),
]))
story.append(PM("<i>" + esc("Source: Federal Decree-Law No. 45 of 2021, Article 9. Regulations status verified 9 August 2026 against "
"primary legal trackers; to be re-verified each term.") + "</i>", S_src))

def lesson_8(story):
story.append(P("Lesson 8. Around the world", S_h1))
story.append(habit_bar("Assume every dataset has a law behind it."))
story.append(Spacer(1, 5))
story.append(P("The UAE has not invented an unusual rulebook. It has joined a global one - and knowing that changes how "
"seriously the daily habits feel."))
story.append(P("How the world got here", S_h2))
for t in [
"The European regulation that applied from 2018 set the template most later laws follow: clear purposes, real rights, minimum data, security, and telling people when things go wrong.",
"Enforcement is not theoretical. Cumulative fines under that regime have reached about EUR 7.1 billion, including a single penalty of EUR 1.2 billion.",
"The most-cited academic count records 172 countries with national data-privacy laws; a different methodology puts it at 144. Either way, most of the world is now covered.",
"Around twenty more countries have bills pending - Pakistan among them.",
"Twenty US states run comprehensive privacy laws, on top of long-standing federal protection for school records and for children under 13 online.",
"The Gulf is adopting comparable frameworks at federal level and inside financial free zones.",
]:
story.append(B(t))
story.append(P("One country, three regimes", S_h2))
story.append(P("Mainland UAE runs the federal law - that is us. The DIFC and ADGM financial free zones run separate regimes of "
"their own. It matters only when data moves between them, but it is worth knowing the map exists."))
story.append(P("Why this reaches our classrooms", S_h2))
for t in [
"Families move. A record that is routine here may land in a jurisdiction with different rules next term.",
"Platforms are global. The tools on your laptop were built to satisfy several regimes at once, which is why they ask the questions they ask.",
"The principles travel almost unchanged. Learn them once and they hold wherever you teach.",
]:
story.append(B(t))
story.append(checkpoints([
("A partner school abroad asks for student records ahead of an exchange visit.",
"Route it. Moving personal data outside the country is governed by specific transfer provisions and is a school decision."),
("'These laws are for big technology companies, not a school our size.'",
"The law applies by activity, not by size. A school processes large volumes of children's data - squarely in scope."),
("Which regime governs this school?",
"The federal law, as a mainland entity. The DIFC and ADGM regimes do not apply to us."),
]))
story.append(PM("<i>" + esc("Sources: Greenleaf Global Data Privacy Laws 2025; IAPP counts; DLA Piper fines survey 2026; Banisar 2026 "
"pending-bills list; Forcepoint 2026 regional review; Federal Decree-Law No. 45 of 2021, Article 2 and Articles 22-23.") + "</i>", S_src))

def lesson_9(story):
story.append(P("Lesson 9. Who to call - our escalation map", S_h1))
story.append(habit_bar("I don't decide this alone - here's who does."))
story.append(Spacer(1, 5))
story.append(P("Eight lessons have told you to route things. This one tells you where. Roles are named rather than "
"individuals, so the map survives staff changes."))
rows = [
("A request to see, correct, transfer or delete data", "[ROLE 1 - to be confirmed]", "Same school day"),
("A suspected breach, mis-send, lost device or exposed file", "[ROLE 1 - to be confirmed]", "Immediately, same day"),
("A photograph, video or consent question", "[ROLE 2 - to be confirmed]", "Before publishing, not after"),
("A question about groups, channels or messaging", "[ROLE 2 - to be confirmed]", "Before acting"),
("A request to use a new app or AI tool with students", "[ROLE 3 - to be confirmed]", "Before any classroom use"),
("Anything touching a child's safety or welfare", "Designated safeguarding lead", "Immediately - existing route, unchanged by this course"),
]
data = [[Paragraph("What has happened", S_cellw), Paragraph("Who you tell", S_cellw), Paragraph("How fast", S_cellw)]]
for a, b_, c in rows:
data.append([Paragraph(esc(a), S_cell), Paragraph(esc(b_), S_cellb), Paragraph(esc(c), S_cell)])
story.append(tbl(data, [CW*0.47, CW*0.28, CW*0.25]))
story.append(P("What to include when you escalate", S_h2))
for t in [
"What happened, in one or two plain sentences.",
"When it happened, and when you noticed - these are often different.",
"Whose data, and roughly how many people are affected.",
"What you have already done, and what you have deliberately not touched.",
]:
story.append(B(t))
story.append(P("What the school does next", S_h2))
story.append(P("It logs the matter, assesses it, decides on any notification, and comes back to you. You will not be left "
"holding it, and you will not be asked to make the legal call. That is the arrangement, and it works in both directions: "
"we carry it for you, and in return we need to hear about it the same day."))
story.append(P("Safeguarding sits above everything here. If a data question is also a child-safety question, it goes down the "
"safeguarding route first and fastest. Nothing in this course changes that."))
story.append(checkpoints([
("A parent hands you a written request to delete all photographs of their child.",
"Acknowledge receipt, promise no outcome, route to [ROLE 1] the same day."),
("You are not sure whether a revision app is approved for classroom use.",
"Do not use it in the meantime. Ask [ROLE 3] before any student touches it."),
("You escalated yesterday and have heard nothing back.",
"Follow up today. The loop closes with you - a routed matter is not a finished matter until you know it landed."),
]))
story.append(PM("<i>" + esc("Roles confirmed by the school Principal before launch. Safeguarding routes are unchanged and take precedence.") + "</i>", S_src))

def final_check(story):
story.append(P("Final Check", S_h1))
story.append(P("Ten situations. For each, the question is not what the law says in the abstract - it is what you do next. "
"Recognise, and route. The judge marks meaning rather than wording, and works identically in English and Arabic.", S_note))
scen = [
("A parent emails: 'Please send me the full list of marks for the class so I can see where my son sits.'",
"Offer complete detail on their own child; decline the class data; route the request if pressed. Other children's marks are never shared."),
("You find a printed list of student names with medical notes left in the staff photocopier.",
"Secure it immediately, note the time, and escalate the same day. This is a breach even though it never left the building."),
("A free homework app asks your Year 4 class to register with email addresses and photographs.",
"Do not proceed. Route to the tool-approval role: under-13 processing on an outside platform needs a school decision."),
("A parent says a computer decided their daughter's set placement and demands a person review it.",
"Route it as an automated-decision objection. Human review at the person's request is a right in law."),
("You need to know which children cannot do PE this term.",
"Ask only for exemption status, not for diagnoses. The minimum that does the job."),
("A colleague forwards you a spreadsheet of another year group's results 'in case it is useful'.",
"Do not open or store it. Tell them, and route it - receiving data you have no purpose for is a problem too."),
("A parent at the gate asks you to remove a class photograph from the school's public page.",
"Use the corridor answer, promise nothing about the outcome, and route it the same day as a consent and erasure question."),
("Your school laptop is stolen from your car.",
"Escalate the same day. Assume data is on it. Do not wait to establish what was there."),
("A vendor demonstrates fingerprint attendance scanning and offers a free trial next week.",
"Route, do not trial. Biometric data of children, with a less intrusive method already in place."),
("You want help marking thirty essays and consider pasting them into an AI tool.",
"Only a tool on the school's authorised list, and only with identifying details removed. Not on the list means not used."),
]
data = [[Paragraph("#", S_cellw), Paragraph("Situation", S_cellw), Paragraph("What good looks like", S_cellw)]]
for i, (q, a) in enumerate(scen, 1):
data.append([Paragraph(str(i), S_cellb), Paragraph(esc(q), S_cell), Paragraph(esc(a), S_cell)])
story.append(tbl(data, [8*mm, (CW-8*mm)*0.48, (CW-8*mm)*0.52]))
story.append(P("On passing, the certificate is generated on demand from the course record and countersigned by the school Principal.", S_note))

============================================================

S.append(P("How to read this document", S_h1))
for t in [
"Each lesson carries one any-Tuesday habit, the teaching content, three checkpoints with correct responses, and its source line.",
"Checkpoints test recognise-and-route. No checkpoint asks a teacher to adjudicate a point of law.",
"Square-bracketed roles in Lessons 6 and 9 are confirmed by each Principal before launch.",
"Arabic derives from the official Arabic text, not from this English. The government portal states that where the English "
"and Arabic conflict, the Arabic prevails - which makes the Arabic side authoritative, not secondary.",
]:
S.append(B(t))

for fn in (lesson_1, lesson_2, lesson_3, lesson_4, lesson_5, lesson_6, lesson_7, lesson_8, lesson_9, final_check):
fn(S)

S.append(P("Production notes carried forward", S_h1))
for i, t in enumerate([
"Lessons 6 and 9 go to the Principals for review before launch; the review pack is a separate document.",
"The Regulations status line in Lesson 7 is dated and re-verified at launch and each term.",
"No penalty figure appears anywhere in this course. The law itself sets none - Article 26 leaves administrative penalties to a Cabinet decision.",
"No claim of the form 'the regulator requires teacher data-protection training' appears anywhere, because no such published requirement was found.",
"Medical-record scope (Article 2(2)(e)) is handled as a routing rule, never as a legal conclusion.",
], 1):
S.append(P(f"{i}. {t}"))
master.build(S)
print("BUILT master")

============================================================

R.append(P("1. What is being asked", S_h1))
for t in [
"1.1 Confirm the three role names that complete the escalation map in Lesson 9 - roles, not individuals, so the map survives staff changes.",
"1.2 Read the two lesson scripts that speak in the school's voice: Lesson 6 (daily practice, including what staff say to parents) and Lesson 9 (the escalation map).",
"1.3 Confirm the one-page description of what will arrive at the Principal's desk once the course is live.",
"1.4 Everything else in the course is anchored to published law and needs no school decision.",
]:
R.append(P(t))

R.append(P("2. The three roles to confirm", S_h1))
role_rows = [
("ROLE 1", "Receives rights requests and all suspected breaches", "Needs authority to act the same day and to escalate to the certification client"),
("ROLE 2", "Receives photograph, consent, group and channel questions", "Typically the person who already owns communications and consent records"),
("ROLE 3", "Receives requests to use a new app or AI tool with students", "Owns the authorised-tools list already taught in the AI course"),
]
data = [[Paragraph("Role", S_cellw), Paragraph("Receives", S_cellw), Paragraph("Note", S_cellw)]]
for a, b_, c in role_rows:
data.append([Paragraph(esc(a), S_cellb), Paragraph(esc(b_), S_cell), Paragraph(esc(c), S_cell)])
R.append(tbl(data, [16*mm, (CW-16*mm)*0.46, (CW-16*mm)*0.54]))
R.append(P("One person may hold more than one of these. Safeguarding routes are unchanged and take precedence over everything here.", S_note))

R.append(P("3. The Principal's one-pager - what arrives at your desk", S_h1))
op = [
("1", "Rights requests", "A parent or student asks to see, correct, transfer or delete data", "Logged on receipt; acknowledged; the school decides the outcome, never the teacher", "Where erasure is requested, or where the request concerns records the school must retain"),
("2", "Suspected breaches", "Mis-sent messages, lost devices, exposed files, shared logins", "Logged with the time noticed; contained; assessed for who is affected", "Immediately where sensitive data or several families are involved"),
("3", "Consent and photograph questions", "Publication, displays, promotional material, removal requests", "Checked against the consent position the school holds before anything is published", "Where the consent position is unclear or contested"),
("4", "Channel and group questions", "What may be sent through class groups and messaging", "Answered from school policy; the course itself never rules on channels", "Where a policy gap becomes visible"),
("5", "New tool requests", "Staff asking to use an app or AI tool with students", "Checked against the authorised-tools list", "Where the tool processes children's data or sits outside the list"),
]
data = [[Paragraph("#", S_cellw), Paragraph("What arrives", S_cellw), Paragraph("Looks like", S_cellw),
Paragraph("What happens to it", S_cellw), Paragraph("When the certification client leadership is called", S_cellw)]]
for n, a, b_, c, d in op:
data.append([Paragraph(n, S_cellb), Paragraph(esc(a), S_cellb), Paragraph(esc(b_), S_cell),
Paragraph(esc(c), S_cell), Paragraph(esc(d), S_cell)])
R.append(tbl(data, [7*mm, 26*mm, (CW-7*mm-26*mm)*0.33, (CW-7*mm-26*mm)*0.34, (CW-7*mm-26*mm)*0.33]))
R.append(P("Expected volume is low and front-loaded: most questions arrive in the fortnight after launch, then settle. "
"The course tells every member of staff that escalation happens the same school day.", S_note))

R.append(P("4. Lesson 6 script - as staff will read it", S_h1))
lesson_6(R)
R.append(P("5. Lesson 9 script - as staff will read it", S_h1))
lesson_9(R)

R.append(P("6. What a confirmation looks like", S_h1))
for t in [
"6.1 Three role names to complete Lesson 9 and the corridor answers in Lesson 6.",
"6.2 Any wording in either script the school would prefer changed - these two lessons speak in the school's voice, so the school has the final word on them.",
"6.3 Confirmation that the one-pager in Section 3 matches how the school wants these matters handled.",
"6.4 Nothing else is required to launch.",
]:
R.append(P(t))
review.build(R)
print("BUILT review pack")

← student internship toolkitThe Master Study Guide — Simple Edition →
Two years of working thought, indexed.
Ask me to present it in your conference room — WhatsApp +971 55 623 9111
Book Session →