LGPD não é “detalhe para depois”. É obrigatório desde 2021.
Multas aplicadas pela ANPD (2023-2025):
- Empresa de telecom: R$ 8,9M (vazamento de dados)
- Fintech: R$ 12,4M (uso indevido de dados)
- E-commerce: R$ 3,2M (falta de consentimento explícito)
Penalidades LGPD (Art. 52):
- Advertência com prazo para adequação
- Multa simples: até 2% do faturamento (limite R$ 50M por infração)
- Multa diária
- Publicização da infração
- Bloqueio ou eliminação dos dados
- Suspensão parcial ou total do banco de dados
Este artigo mostra checklist técnico e jurídico para compliance completo.
Os 10 princípios da LGPD (Art. 6º)
- Finalidade: Dados coletados para propósito específico e informado
- Adequação: Compatível com finalidades informadas
- Necessidade: Mínimo necessário (não coletar “por garantia”)
- Livre acesso: Titular consulta dados gratuitamente
- Qualidade: Dados exatos, claros e atualizados
- Transparência: Informações claras sobre tratamento
- Segurança: Proteção contra acessos não autorizados
- Prevenção: Medidas para evitar danos
- Não discriminação: Sem fins ilícitos ou abusivos
- Responsabilização: Demonstrar conformidade (accountability)
Bases legais para tratamento de dados (Art. 7º)
Nem todo dado precisa de consentimento. Existem 10 bases legais:
// lib/lgpd/legal-basis.ts
export enum LegalBasis {
// Base 1: Consentimento explícito
CONSENT = "consent", // "Aceito que meus dados sejam usados para X"
// Base 2: Cumprimento de obrigação legal
LEGAL_OBLIGATION = "legal_obligation", // Ex: guardar nota fiscal por 5 anos
// Base 3: Execução de contrato
CONTRACT = "contract", // Ex: dados para entrega do produto
// Base 4: Exercício regular de direitos
LEGAL_CLAIMS = "legal_claims", // Ex: defesa em processo
// Base 5: Proteção da vida
VITAL_INTEREST = "vital_interest", // Ex: dados médicos em emergência
// Base 6: Tutela da saúde
HEALTH = "health", // Ex: prontuário médico
// Base 7: Interesse legítimo
LEGITIMATE_INTEREST = "legitimate_interest", // Ex: prevenção de fraude
// Base 8: Proteção de crédito
CREDIT_PROTECTION = "credit_protection", // Ex: score de crédito
// Base 9: Execução de políticas públicas
PUBLIC_INTEREST = "public_interest", // Ex: dados do gov
// Base 10: Estudos por órgãos de pesquisa
RESEARCH = "research" // Ex: pesquisas acadêmicas
}
// Modelo de dados com base legal
interface DataProcessing {
purpose: string // "Enviar comunicações de marketing"
legalBasis: LegalBasis // CONSENT
dataCategories: string[] // ["email", "nome"]
retention: string // "Até revogação do consentimento"
consentDate?: Date // Se base = CONSENT
}
Para apps B2B, bases mais comuns:
- Contrato: Dados para prestação do serviço (nome, email, empresa)
- Legítimo interesse: Analytics, prevenção de fraude
- Consentimento: Marketing, compartilhamento com terceiros
Implementação técnica de consentimento
1. Captura de consentimento explícito
// components/ConsentForm.tsx
import { useState } from 'react'
export function ConsentForm({ onSubmit }: Props) {
const [consents, setConsents] = useState({
necessary: true, // Sempre true, não pode desmarcar
analytics: false,
marketing: false,
thirdParty: false
})
return (
<form onSubmit={handleSubmit}>
<ConsentCheckbox
checked={consents.necessary}
disabled
label="Necessários"
description="Dados essenciais para funcionamento do serviço (contrato)"
legalBasis="contract"
/>
<ConsentCheckbox
checked={consents.analytics}
onChange={(checked) => setConsents({ ...consents, analytics: checked })}
label="Análise e melhoria"
description="Cookies e analytics para melhorar sua experiência"
legalBasis="legitimate_interest"
/>
<ConsentCheckbox
checked={consents.marketing}
onChange={(checked) => setConsents({ ...consents, marketing: checked })}
label="Marketing"
description="Enviaremos newsletters e ofertas relevantes"
legalBasis="consent"
/>
<ConsentCheckbox
checked={consents.thirdParty}
onChange={(checked) => setConsents({ ...consents, thirdParty: checked })}
label="Compartilhamento"
description="Compartilhar dados com parceiros comerciais"
legalBasis="consent"
/>
<Button type="submit">Continuar</Button>
<Link href="/privacy">Política de Privacidade completa</Link>
</form>
)
}
2. Registro de consentimentos (auditável)
-- Schema PostgreSQL
CREATE TABLE user_consents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id),
purpose VARCHAR(100) NOT NULL, -- 'marketing', 'analytics', etc
legal_basis VARCHAR(50) NOT NULL,
granted BOOLEAN NOT NULL,
ip_address INET NOT NULL, -- IP no momento do consentimento
user_agent TEXT NOT NULL, -- Browser
consent_date TIMESTAMP NOT NULL DEFAULT NOW(),
revocation_date TIMESTAMP, -- Se revogou
version VARCHAR(20) NOT NULL -- Versão da política de privacidade
);
-- Índices
CREATE INDEX idx_user_consents_user ON user_consents(user_id);
CREATE INDEX idx_user_consents_purpose ON user_consents(purpose, granted);
// lib/lgpd/consent.ts
export async function recordConsent({
userId,
purpose,
legalBasis,
granted,
ipAddress,
userAgent
}: ConsentData) {
const currentPolicyVersion = await getCurrentPolicyVersion()
await prisma.userConsent.create({
data: {
userId,
purpose,
legalBasis,
granted,
ipAddress,
userAgent,
version: currentPolicyVersion,
consentDate: new Date()
}
})
// Log para auditoria
await auditLog.record({
action: 'CONSENT_RECORDED',
userId,
details: { purpose, granted, legalBasis }
})
}
// Verificar se usuário deu consentimento
export async function hasConsent(
userId: string,
purpose: string
): Promise<boolean> {
const consent = await prisma.userConsent.findFirst({
where: {
userId,
purpose,
granted: true,
revocationDate: null
},
orderBy: { consentDate: 'desc' }
})
return !!consent
}
Direitos dos titulares (Art. 18)
Todo usuário tem direito a:
- Confirmação e acesso: “Vocês têm meus dados?”
- Correção: “Meu email está errado”
- Anonimização/bloqueio/eliminação: “Deletem meus dados”
- Portabilidade: “Quero exportar meus dados”
- Eliminação de consentimento: “Não quero mais receber emails”
- Informação sobre compartilhamento: “Com quem vocês compartilham?”
- Informação sobre não consentimento: “O que acontece se eu não consentir?”
- Revogação do consentimento: “Revogo meu consentimento para X”
Implementação:
// app/api/lgpd/data-subject-request/route.ts
import { NextRequest } from 'next/server'
export async function POST(req: NextRequest) {
const { userId, requestType } = await req.json()
// Valida identidade (2FA, email confirmation)
await validateIdentity(userId)
switch (requestType) {
case 'ACCESS':
return await handleAccessRequest(userId)
case 'CORRECTION':
return await handleCorrectionRequest(userId)
case 'DELETION':
return await handleDeletionRequest(userId)
case 'PORTABILITY':
return await handlePortabilityRequest(userId)
case 'CONSENT_REVOCATION':
return await handleConsentRevocation(userId)
default:
return Response.json({ error: 'Invalid request type' }, { status: 400 })
}
}
// Exportar todos os dados do usuário (portabilidade)
async function handlePortabilityRequest(userId: string) {
const [user, bookings, payments, consents] = await Promise.all([
prisma.user.findUnique({ where: { id: userId } }),
prisma.booking.findMany({ where: { userId } }),
prisma.payment.findMany({ where: { userId } }),
prisma.userConsent.findMany({ where: { userId } })
])
const exportData = {
user: {
name: user.name,
email: user.email,
phone: user.phone,
createdAt: user.createdAt
},
bookings: bookings.map(b => ({
service: b.service,
date: b.date,
status: b.status
})),
payments: payments.map(p => ({
amount: p.amount,
date: p.date,
status: p.status
})),
consents: consents.map(c => ({
purpose: c.purpose,
granted: c.granted,
date: c.consentDate
}))
}
// Gera JSON e envia por email
const json = JSON.stringify(exportData, null, 2)
await sendEmail({
to: user.email,
subject: 'Seus dados pessoais',
attachments: [{
filename: 'meus-dados.json',
content: json
}]
})
// Log auditoria
await auditLog.record({
action: 'DATA_EXPORT',
userId,
timestamp: new Date()
})
return Response.json({ success: true })
}
// Deletar conta (direito ao esquecimento)
async function handleDeletionRequest(userId: string) {
// Anonimizar dados em vez de deletar (preserva integridade)
await prisma.user.update({
where: { id: userId },
data: {
email: `deleted-${userId}@anonimizado.com`,
name: 'Usuário Deletado',
phone: null,
cpf: null,
deletedAt: new Date(),
// Manter ID para integridade referencial
}
})
// Revoga todos os consentimentos
await prisma.userConsent.updateMany({
where: { userId },
data: { revocationDate: new Date() }
})
await auditLog.record({
action: 'ACCOUNT_DELETED',
userId,
timestamp: new Date()
})
return Response.json({ success: true })
}
Segurança técnica (medidas obrigatórias)
1. Criptografia de dados sensíveis
// lib/security/encryption.ts
import crypto from 'crypto'
const ALGORITHM = 'aes-256-gcm'
const KEY = process.env.ENCRYPTION_KEY! // 32 bytes
export function encrypt(text: string): string {
const iv = crypto.randomBytes(16)
const cipher = crypto.createCipheriv(ALGORITHM, Buffer.from(KEY, 'hex'), iv)
let encrypted = cipher.update(text, 'utf8', 'hex')
encrypted += cipher.final('hex')
const authTag = cipher.getAuthTag()
// Retorna: iv:authTag:encrypted
return `${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted}`
}
export function decrypt(encryptedData: string): string {
const [ivHex, authTagHex, encrypted] = encryptedData.split(':')
const iv = Buffer.from(ivHex, 'hex')
const authTag = Buffer.from(authTagHex, 'hex')
const decipher = crypto.createDecipheriv(ALGORITHM, Buffer.from(KEY, 'hex'), iv)
decipher.setAuthTag(authTag)
let decrypted = decipher.update(encrypted, 'hex', 'utf8')
decrypted += decipher.final('utf8')
return decrypted
}
// Uso em modelo Prisma
// Antes de salvar CPF
user.cpf = encrypt(cpf)
// Ao ler
const cpfDecrypted = decrypt(user.cpf)
2. Hashing de senhas (bcrypt, não MD5/SHA1)
// lib/security/password.ts
import bcrypt from 'bcryptjs'
const SALT_ROUNDS = 12 // Custo computacional
export async function hashPassword(password: string): Promise<string> {
return bcrypt.hash(password, SALT_ROUNDS)
}
export async function verifyPassword(
password: string,
hash: string
): Promise<boolean> {
return bcrypt.compare(password, hash)
}
3. HTTPS obrigatório (TLS 1.2+)
// next.config.js
module.exports = {
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains; preload'
}
]
}
]
}
}
4. Proteção contra SQL Injection (ORM + prepared statements)
// ❌ ERRADO (vulnerável a SQL injection)
const query = `SELECT * FROM users WHERE email = '${userInput}'`
await db.query(query)
// ✅ CORRETO (prepared statement via Prisma)
const user = await prisma.user.findFirst({
where: { email: userInput }
})
5. Rate limiting (prevenir brute force)
// middleware/rate-limit.ts
import rateLimit from 'express-rate-limit'
export const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutos
max: 5, // Máximo 5 tentativas
message: 'Muitas tentativas de login. Tente novamente em 15 minutos.',
standardHeaders: true,
legacyHeaders: false,
})
// Uso
app.post('/api/auth/login', loginLimiter, handleLogin)
6. CORS configurado corretamente
// next.config.js
module.exports = {
async headers() {
return [
{
source: '/api/:path*',
headers: [
{ key: 'Access-Control-Allow-Origin', value: 'https://seudominio.com' },
{ key: 'Access-Control-Allow-Methods', value: 'GET,POST,PUT,DELETE' },
{ key: 'Access-Control-Allow-Headers', value: 'Content-Type, Authorization' }
]
}
]
}
}
Relatório de Impacto à Proteção de Dados (RIPD)
Obrigatório quando:
- Tratamento de dados sensíveis (saúde, biometria, genéticos)
- Decisões automatizadas (perfis, scoring)
- Alto volume de dados pessoais
- Alto risco aos direitos dos titulares
Template RIPD:
# Relatório de Impacto à Proteção de Dados Pessoais
## 1. Identificação do Controlador
- Razão Social: [Nome da Empresa]
- CNPJ: XX.XXX.XXX/0001-XX
- DPO: [Nome] - [Email]
## 2. Descrição do Tratamento
- Finalidade: Conectar pacientes a fisioterapeutas
- Base legal: Consentimento (marketing) + Contrato (prestação de serviço)
- Dados tratados:
- Identificação: Nome, CPF, email, telefone
- Saúde: Histórico de lesões, laudos médicos (PDF)
- Localização: Endereço para atendimento domiciliar
- Volume: ~5.000 pacientes/mês
## 3. Análise de Riscos
| Risco | Probabilidade | Impacto | Mitigação |
|-------|---------------|---------|-----------|
| Vazamento de dados de saúde | Média | Alto | Criptografia AES-256, acesso restrito |
| Uso indevido para marketing | Baixa | Médio | Consentimento explícito, opt-out fácil |
| Acesso não autorizado | Média | Alto | 2FA, logs de auditoria |
## 4. Medidas de Segurança
- ✅ Criptografia TLS 1.3 (transporte)
- ✅ Criptografia AES-256 (dados em repouso)
- ✅ Backups diários (retenção 30 dias)
- ✅ Acesso baseado em função (RBAC)
- ✅ Logs de auditoria (quem acessou o quê)
- ✅ Teste de penetração anual
## 5. Necessidade e Proporcionalidade
- Dados coletados: Apenas essenciais para prestação do serviço
- Retenção: Até exclusão da conta ou 5 anos (prazo legal)
- Compartilhamento: Apenas com fisioterapeuta designado
## 6. Direitos dos Titulares
- Portal de autoatendimento para exercício de direitos
- Prazo de resposta: 15 dias
- Gratuito
## 7. Conclusão
Riscos identificados e mitigados adequadamente.
Tratamento está em conformidade com LGPD.
Data: 2026-11-02
Responsável: [Nome do DPO]
Indicação de DPO (Data Protection Officer)
Quando é obrigatório:
- Controladores de grande porte
- Tratamento de dados sensíveis em larga escala
- Atividade principal seja tratamento de dados
Para SMEs: DPO pode ser terceirizado (R$ 2-5K/mês).
Responsabilidades do DPO:
- Orientar funcionários sobre LGPD
- Atender requisições de titulares
- Interagir com ANPD
- Monitorar conformidade
// Contato do DPO visível no site
export function DPOContact() {
return (
<section>
<h2>Encarregado de Dados (DPO)</h2>
<p>Para exercer seus direitos ou esclarecer dúvidas sobre tratamento de dados:</p>
<ul>
<li>Nome: Maria Silva</li>
<li>Email: dpo@suaempresa.com.br</li>
<li>Telefone: (11) 1234-5678</li>
</ul>
</section>
)
}
Checklist de compliance LGPD
Antes de lançar:
- Política de Privacidade publicada e acessível
- Termos de Uso com cláusulas de tratamento de dados
- Captura de consentimento explícito (quando necessário)
- DPO indicado (nome e contato público)
- Dados sensíveis criptografados (AES-256)
- HTTPS obrigatório (TLS 1.2+)
- Senhas com bcrypt (12+ rounds)
- SQL injection prevenido (ORM/prepared statements)
- CORS configurado
- Rate limiting em endpoints sensíveis
- Logs de auditoria (acessos, modificações)
- Backup automático (retenção 30 dias)
Operacional:
- Fluxo para requisições de titulares (acesso, correção, exclusão)
- Prazo de resposta definido (menor que 15 dias)
- RIPD elaborado (se aplicável)
- Contratos com operadores (DPA - Data Processing Agreement)
- Treinamento de equipe (anual)
- Revisão de políticas (anual ou quando houver mudanças)
Incidentes:
- Plano de resposta a incidentes
- Comunicação à ANPD em menor que 72h (se vazamento)
- Comunicação aos titulares (se risco relevante)
Custos de compliance
Setup inicial:
- Consultoria jurídica (políticas): R$ 8-15K
- DPO terceirizado (setup): R$ 3-6K
- RIPD (se aplicável): R$ 5-12K
- Auditoria técnica: R$ 8-18K
- Total inicial: R$ 24-51K
Recorrente (mensal):
- DPO terceirizado: R$ 2-5K
- Ferramentas (consent management): R$ 300-1.2K
- Auditorias anuais: R$ 8-15K (diluído em 12 meses)
- Total mensal: R$ 3-7K
ROI: Evitar 1 multa de R$ 500K+ justifica investimento.
Próximos passos
- Ler LGPD completa (15 páginas, Lei nº 13.709/2018)
- Mapear dados tratados (quais, para quê, base legal)
- Implementar consentimento (se necessário)
- Criptografar dados sensíveis (CPF, dados de saúde)
- Publicar Política de Privacidade
- Indicar DPO
- Treinar equipe
- Revisar contratos com fornecedores (AWS, Stripe, etc)
Lembre-se: LGPD não é “burocracia”. É respeito aos dados dos seus clientes. Compliance = confiança = mais conversões.