Context: Why LGPD Hits Harder in Online Education
Online learning platforms collect more sensitive data than e-commerce sites or social networks:
- Educational records (LGPD Art. 11 — classified as sensitive personal data when they reveal health or well-being conditions)
- Rich behavioral data — time spent on each lesson, study patterns, difficulties, pre-exam anxiety
- Data on minors — elementary and middle school + high school = ~80% of the Brazilian K-12 market
- Parent/guardian data (via GuardianLink linkage)
- Biometric data when proctoring with webcam is used (Studeia does not have this natively, but LTI integrations with Examity/ProctorU do)
Brazil's ANPD has already audited EdTech companies in 2024–2025. Fines of up to R$50 million (2% of gross revenue, capped at R$50M) are real.
8 Mandatory Compliance Fronts
1. DPO (Data Protection Officer) — Art. 41
Companies must designate a natural person as the data processing officer. Responsibilities include:
- Receiving complaints and communications from data subjects
- Receiving communications from the ANPD
- Advising employees on LGPD
- Executing compliance plans
Options:
| Model | Cost | Best For |
|---|---|---|
| Internal DPO (salaried) | R$8–20k/month salary | Companies with 100+ employees |
| External DPO (specialized consulting) | R$2–8k/month | Companies with 10–100 employees |
| Virtual DPO (law firm) | R$1–3k/month | Micro-businesses |
Must be publicly listed: DPO name + email in the privacy policy.
2. Real Parental Consent for Minors — Art. 14
LGPD Art. 14 §1: "The processing of personal data of children must be carried out with specific and prominent consent given by at least one of the parents or by the legal guardian."
Platforms that ignore this face steep penalties:
- ❌ Anti-pattern: checkbox "I am over 13 years old" with no verification
- ❌ Anti-pattern: "Father's email" field without verifying it's real
- ✅ Studeia's approach: student registers → status
pending_parental_consent→ email/SMS sent to parent → parent clicks link + completes SMS verification (anti-fraud) → statusactive
Additionally: the parent configures their child's access level via ProgressSharingConfig. For students under 13: parent has FULL access by default. Ages 13–17: parent configures.
Concrete implementation:
// Student registers
if (user.age < 18) {
user.isMinor = true;
user.status = "pending_parental_consent";
// GuardianLink created but inactive
await prisma.guardianLink.create({
data: {
childId: user.id,
parentEmail: parentEmail,
parentPhone: parentPhone,
verified: false,
verificationToken: generateSecureToken(),
}
});
// Email + SMS sent to parent with verification link
await sendVerification({ ... });
}
The student CANNOT access content while status != "active". No loopholes.
3. Data Export — Art. 18 IV
A data subject may request a copy of ALL personal data you process about them, in a structured and readable format.
Studeia: GET /api/user/data-export returns JSON with:
{
"user": { id, email, name, role, ... },
"enrollments": [ ... ],
"lessonCompletions": [ ... ],
"quizAttempts": [ ... ],
"chatSessions": [ ... ], // AI tutor chat history
"messages": [ ... ], // direct messages + forum
"badges": [ ... ],
"gamificationProfile": { ... },
"aiSupervisorIncidents": [ ... ], // if applicable
"consentRecords": [ ... ]
}
Rate limit: 1 export per 24 hours per user (anti-abuse). Redis key data-export-cooldown:{userId} TTL 86400.
Delivered within 15 days of the request (LGPD does not define an exact deadline, but 15 days is the ANPD standard).
4. Account Deletion — Art. 18 VI
A data subject may request the erasure of their personal data. But there are nuances:
- PII (personally identifiable data) — MUST be erased or anonymized
- Historical academic data — MAY be RETAINED for a legitimate purpose (fiscal retention, proof of the student's credentials, defense in potential litigation)
Studeia's approach:
// DELETE /api/user/account
await prisma.$transaction(async (tx) => {
// 1. Anonymize PII
await tx.user.update({
where: { id: userId },
data: {
email: `deleted-${userId}@anonymous.studeia.com`,
name: "Deleted user",
phone: null,
address: null,
avatarUrl: null,
cpf: null, // Brazilian tax ID also removed
status: "deleted",
deletedAt: new Date(),
}
});
// 2. Delete conversational data
await tx.chatSession.deleteMany({ where: { userId } });
await tx.directMessage.deleteMany({ where: { senderId: userId } });
await tx.directMessage.updateMany({ where: { recipientId: userId }, data: { recipientId: ANONYMIZED } });
// 3. Anonymize academic data (retain history but remove PII)
// LessonCompletion, QuizAttempt, Grade already reference User.id (retained)
// Since User.email and User.name are anonymized, academic data becomes "anonymous"
// 4. Anonymize safety incidents (retain severity + category for compliance)
await tx.aiSupervisorIncident.updateMany({
where: { userId },
data: {
messagesSnapshot: [],
supervisorReasoning: null,
appealText: null,
}
});
// 5. Cron purges academic data older than 5 years automatically
});
5 years = LGPD-friendly fiscal retention (Lei 10.406/2002 + Brazilian Constitution Art. 7º XXIX).
5. DPA with Third Parties — Mandatory Disclosure
Tenants MUST list ALL third-party data processors in their privacy policy.
Studeia provides each tenant with the following list:
- Anthropic (Claude) — processes prompts + responses. GDPR/LGPD DPA. Headquarters: USA. Data retention: 30 days.
- OpenAI (GPT fallback) — same. Headquarters: USA. Data retention: 30 days.
- Voyage AI (primary embeddings) — processes text for embedding. Headquarters: USA. Data retention: 30 days.
- Stripe (USD payments) — PCI-DSS Level 1. Headquarters: USA. Retention: 7 years (fiscal).
- Asaas (Brazilian PIX/boleto payments) — headquarters: Brazil. Retention: 7 years.
- Supabase (database + auth + storage) — headquarters: USA. Region: us-east-1 (default) or sa-east-1 optional.
- Sentry (observability) — Session replay with maskAllText:true + blockAllMedia:true (LGPD-compliant).
- PostHog (analytics) — IP anonymization on. No PII tracking.
- Resend / SendGrid (email) — headquarters: USA. Retention: 30 days.
Tenants copy this list into their privacy policy. This satisfies the disclosure requirement.
6. Real Tenant Isolation — RLS + Mandatory Filter
LGPD Art. 6 V: personal data must be processed with appropriate security.
Multi-tenant LMS = data from School A can NEVER appear in a query from School B. Studeia implements this in 3 layers:
- Mandatory filter in Prisma queries: every
prisma.X.findMany()call in application code MUST includewhere: { tenantId }. This is Critical Rule #6 of the project. - Supabase RLS: automatic policy on all relevant tables:
CREATE POLICY tenant_isolation_courses ON courses FOR SELECT USING (tenant_id = current_setting('app.current_tenant_id')::uuid); - RAG tenantOnlyMode: retrieval never surfaces material from another institution.
7. Immutable Audit Log
LGPD Art. 37 + ANPD Resolution CD/ANPD No. 4/2023: record of data processing operations.
Studeia: AdminAuditLog model with:
model AdminAuditLog {
id String @id @default(uuid())
actorId String // who performed the action
action AdminAuditAction
targetType String // "user", "tenant", "course", etc.
targetId String?
metadata Json?
ip String?
userAgent String?
createdAt DateTime @default(now())
}
Audited actions (15+ types):
- impersonate.start / stop
- tenant.create / plan.change / config.update / delete
- user.role.change / tenant.link
- ai_supervisor.* (incident transitions, prompt updates, etc.)
- subscription.admin_update
- payment.manual.record
Immutable: append-only. There is no endpoint to delete records (by design).
8. Incident Response Plan
LGPD Art. 48: a security incident that may cause relevant risk or harm = notification to the ANPD within a reasonable timeframe (interpreted as: 24 hours).
Studeia: runbook at docs/runbooks/incident-response.md with SEV table:
| SEV | Trigger | Primary Action | Notification SLA |
|---|---|---|---|
| SEV1 | PII breach > 100 users | ANPD reporting + clients + status page | <2h |
| SEV2 | Outage > 30min OR PII breach < 100 users | Clients + status page | <4h |
| SEV3 | Performance degradation | Status page | <12h |
| SEV4 | Functional bug without PII impact | Prioritized backlog | N/A |
Plus: public postmortem (sanitized) in docs/incidents/ for SEV1/SEV2.
Studeia-Specific Additions
LLM Prompt Logging
Before sending a prompt to Anthropic/OpenAI:
// Redact known PII
function redactPIIBeforeLLM(prompt: string, user: User): string {
return prompt
.replace(new RegExp(user.email, 'gi'), '[EMAIL_REDACTED]')
.replace(new RegExp(user.cpf ?? '', 'g'), '[CPF_REDACTED]')
.replace(new RegExp(user.phone ?? '', 'g'), '[PHONE_REDACTED]');
}
Before logging a prompt in AiUsageLog:
function redactPIIBeforeLog(prompt: string): string {
// Generic patterns
return prompt
.replace(/\b\d{3}\.\d{3}\.\d{3}-\d{2}\b/g, '[CPF]')
.replace(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g, '[EMAIL]')
.replace(/\b\d{4,5}-?\d{4}\b/g, '[PHONE]');
}
AiUsageLog.prompt stores the redacted version. Cost tracking + analytics work without exposing PII.
AI Tutor + Chat History
Students can access "My Conversations" and view their history. Parents with permission can also view it (depending on ProgressSharingConfig.viewChatHistory).
However, the ANPD may request it via court order. Response procedure:
- Studeia retains chat history for 1 year (default retention, configurable per tenant)
- After 1 year: the
/api/cron/chat-cleanupcron job anonymizes data (retains turn count for analytics, deletes text content) - Upon a court order: exports JSON with the requested content
- Access is logged in AdminAuditLog (action:
data.judicial_request)
What to NEVER Do
❌ Collect more data than necessary (data minimization principle, Art. 6 III) ❌ Share student data for marketing purposes (even "internally") ❌ Train an AI model on student data without explicit consent ❌ Sell study behavior data to third parties ❌ Use data from minors for targeted advertising (prohibited by law) ❌ Retain data without a clear stated purpose (Art. 16) ❌ Use an AI tutor without disclosing it is AI (transparency, Art. 6 VI)
Real-Time AI Avatars (available — opt-in)
Studeia now offers a real-time talking avatar with video/voice (HeyGen LiveAvatar / D-ID, BYO provider key) as an opt-in feature per course. LGPD considerations when enabling it:
- Additional explicit consent recommended (for the use of a "virtual AI tutor image")
- Disclosure that it is AI (footer: "AI-generated virtual tutor")
- Do not use the real voice of a public figure without licensing (deepfake risk)
- The provider's master API key stays server-side and is never sent to the client; only ephemeral session tokens reach the browser. See Avatar & TTS.