LGPD para devs: como implementar privacidade by design

LGPD para devs: como implementar privacidade by design

Completou oito anos a LGPD e, sinceramente, o que mais me chama atenção não é a data em si — é o fato de que a maioria dos devs que eu conheço ainda trata proteção de dados como “problema do jurídico”. Segundo o Olhar Digital, Carlos Lima, do Failla Lima Riva Advogados, cravou bem: o divisor de águas agora é provar que o programa de privacidade funciona na prática. Isso é, literalmente, código rodando, logs auditáveis e decisões de arquitetura.

Neste artigo quero trazer a LGPD para dentro do editor de texto. Vou mostrar onde a lei bate na arquitetura, quais armadilhas eu já vi em produção e como implementar privacidade de verdade — não só um banner de cookies bonitinho.

O que mudou de verdade nesses oito anos (do ponto de vista de quem programa)

Quando a Lei nº 13.709/2018 foi sancionada, em 14 de agosto de 2018, a maior parte das empresas fez o movimento clássico: contratou um advogado, gerou um PDF de política de privacidade, indicou um DPO e fingiu que o assunto estava resolvido. Eu mesmo já revisei sistemas em que o “tratamento de dados” era literalmente um campo consentimento: true num formulário, sem nenhum controle por trás.

De 2020 em diante, com a vigência efetiva e depois com as sanções administrativas aplicáveis a partir de agosto de 2021, o discurso mudou. Hoje, empresas maduras tratam LGPD como requisito de engenharia: aparece em decisões de modelagem de banco, em escolha de fornecedores SaaS, em revisão de pull request e em política de retenção de logs.

Para o desenvolvedor, isso significa três obrigações técnicas concretas que não dá para terceirizar:

  • Minimização: coletar só o que é necessário, e isso vira esquema de banco e contrato de API.
  • Finalidade: cada campo de dado pessoal precisa ter propósito documentado e verificável.
  • Segurança: criptografia em trânsito e em repouso, controle de acesso, auditoria.

Privacy by Design não é slide de PowerPoint — é decisão de arquitetura

O conceito de privacy by design aparece no artigo 46 da LGPD e, na prática, obriga o dev a tomar decisões que vão desde o tipo de banco até a estratégia de log. Vou destrinchar as quatro decisões de arquitetura que eu considero não negociáveis em qualquer sistema que processa dados pessoais.

1. Modelagem: identifique o dado sensível e isole-o

A lei considera dado pessoal sensível origem racial, convicção religiosa, opinião política, dados de saúde, vida sexual, genéticos e biométricos. Isso não é “campo opcional” — é classe de armazenamento separada, com criptografia forte e acesso controlado por papel.

Em Postgres, por exemplo, eu separo a tabela users (comuns) de tabelas dedicadas como user_health_data ou user_biometric_templates, com row-level security ativada:

-- Tabela comum
CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email TEXT NOT NULL UNIQUE,
  name TEXT NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Tabela sensível, isolada
CREATE TABLE user_health_data (
  user_id UUID PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
  blood_type TEXT,
  conditions JSONB,
  -- coluna criptografada via pgcrypto
  encrypted_record BYTEA NOT NULL,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Row-level security: só o próprio user ou um médico autorizado lê
ALTER TABLE user_health_data ENABLE ROW LEVEL SECURITY;

CREATE POLICY health_data_self_access ON user_health_data
  FOR SELECT
  USING (user_id = current_setting('app.current_user_id')::UUID);

Esse padrão garante que, mesmo que um SELECT malicioso escape, ele bate na política e não retorna dado sensível para usuários não autorizados. Isso é exatamente o tipo de evidência que uma auditoria da ANPD vai pedir.

2. Logs: nunca, em hipótese nenhuma, logue dado pessoal sensível

Esse é o erro que eu mais vejo em times juniors. Eles colocam console.log(req.body) em middleware, o log vai para Datadog/CloudWatch, e de repente você tem CPF, e-mail e endereço de milhares de pessoas indexados num agregador de logs sem criptografia e com retenção infinita.

A solução é um filtro de redação no próprio logger. Em Node.js com Pino:

const pino = require('pino');

const REDACT_PATHS = [
  'req.body.cpf',
  'req.body.password',
  'req.body.email',
  'req.body.healthRecord',
  'req.headers.authorization',
  'req.headers.cookie',
  '*.token',
  '*.secret'
];

const logger = pino({
  level: 'info',
  redact: {
    paths: REDACT_PATHS,
    censor: '[REDACTED-LGPD]'
  }
});

module.exports = logger;

Por que [REDACTED-LGPD] como marcador? Porque quando o DPO for auditar, ele consegue buscar exatamente onde um dado foi redigido e validar que o sistema realmente tentou protegê-lo. Evidência documentada é metade do trabalho em conformidade.

3. Retenção: dado pessoal não é ativo eterno

O artigo 16 da LGPD obriga a eliminação dos dados pessoais após cessada a finalidade. Isso, em termos de engenharia, é um job de limpeza. Eu uso três estratégias combinadas:

  • TTL explícito por coleção no banco (MongoDB, Redis).
  • Soft delete com prazo + hard delete agendado (cron).
  • Particionamento por data em data warehouse, com drop automático de partições antigas.
// Exemplo: job Node.js rodando diariamente
const cron = require('node-cron');
const { db } = require('./db');

cron.schedule('0 3 * * *', async () => {
  const cutoff = new Date(Date.now() - 90 * 24 * 60 * 60 * 1000); // 90 dias

  // Hard delete de sessões expiradas há mais de 90 dias
  const sessions = await db.collection('sessions')
    .deleteMany({ lastActivity: { $lt: cutoff } });

  // Anonimiza pedidos antigos mantendo apenas métricas
  const orders = await db.collection('orders').updateMany(
    { createdAt: { $lt: cutoff }, anonymized: { $ne: true } },
    { $set: {
        anonymized: true,
        customerName: 'ANONIMO',
        customerEmail: null,
        customerDocument: null
      }
    }
  );

  logger.info({ sessions: sessions.deletedCount, orders: orders.modifiedCount }, 'LGPD retention job');
});

4. Consentimento e portabilidade: a API precisa expor isso

Direito de acesso (art. 18), portabilidade (art. 18, V) e eliminação (art. 18, VI) viram endpoints. Não dá para “responder depois” — o usuário pode exigir em até 15 dias. Logo, seu sistema precisa exportar tudo em formato estruturado e legível por máquina:

// Endpoint /api/me/data-export — GET
app.get('/api/me/data-export', authenticate, async (req, res) => {
  const userId = req.user.id;

  const profile = await db.users.findOne({ id: userId });
  const orders = await db.orders.find({ userId }).toArray();
  const consents = await db.consents.find({ userId }).toArray();

  const payload = {
    exportedAt: new Date().toISOString(),
    format: 'LGPD-portability-v1',
    data: { profile, orders, consents }
  };

  res.setHeader('Content-Type', 'application/json');
  res.setHeader('Content-Disposition', 'attachment; filename="meus-dados.json"');
  res.send(JSON.stringify(payload, null, 2));
});

Na Prática: checklist técnico que eu uso em revisão de PR

Quando estou revisando código em sistemas que tratam dado pessoal, rodo esse checklist mental. Adaptei de várias auditorias reais que já enfrentei:

  1. O campo novo é dado pessoal? Se sim, está marcado com tag de classificação (pii: true, sensitivity: high)?
  2. O logger tem o caminho do campo na lista de redação?
  3. A migration cria índice único que vaza informação? (Ex.: índice em cpf puro expõe existência de cadastro em queries cegas.)
  4. O endpoint tem rate-limit e audit-log?
  5. A política de retenção está documentada no schema (TTL, campo expires_at)?
  6. O dado cruza fronteira? Se sim, tem base legal específica para transferência internacional?
  7. O backup criptografado tem a mesma chave do banco? (Espero que não — chave em KMS separado.)

Erros Comuns que eu já vi (e que podem custar caro)

Erro 1 — Confundir hash com criptografia para “anonimizar”

Muito dev acha que aplicar MD5 ou SHA-256 em CPF é anonimização. Não é. Hash é determinístico: com uma rainbow table, você reverte em minutos para CPFs comuns. Para anonimização real, use técnicas como tokenização com vault, k-anonimato ou differential privacy. Para pseudonimização (que ainda é dado pessoal pela LGPD), use HMAC com sal por usuário.

Erro 2 — Guardar IP em log de aplicação sem política

IP é dado pessoal segundo o STJ (Tema 990). Se você loga IP em log de aplicação e retém por 2 anos, está em desconformidade. Defina retenção curta (30–90 dias) ou hash com sal rotativo.

Erro 3 — Banner de cookies sem granularidade

O padrão atual exige consentimento granular por finalidade. Aquele banner único com “Aceitar todos” sem opção granular já não atende mais a expectativa da ANPD. Use um CMP como OneTrust, Cookiebot ou uma implementação própria com consent string propagado para o backend.

Erro 4 — Tratamento de dado de menor sem cuidado extra

Dados de crianças e adolescentes (art. 14) exigem consentimento específico dos pais. No código, isso significa campo is_minor com tratamento bloqueante para várias finalidades de marketing e perfilização.

Erro 5 — Não documentar a base legal de cada tratamento

Cada campo precisa ter por que está sendo coletado: execução de contrato, consentimento, legítimo interesse, cumprimento de obrigação legal, etc. Sem isso, a ANPD presume consentimento — e aí você precisa provar que ele foi livre, informado e inequívoco.

Ferramentas e padrões que valem seu tempo

  • OpenSSL + AWS KMS / GCP KMS para criptografia gerenciada, sem reinventar.
  • pgcrypto (Postgres) ou TDE (SQL Server) para criptografia em repouso.
  • Open Policy Agent (OPA) para políticas de acesso declarativas e auditáveis.
  • HashiCorp Vault para gestão de segredos e tokens de pseudonimização.
  • Privacidade desde o design revisada em ADR (Architecture Decision Records) — cada decisão de schema com PII vira um ADR versionado no Git.

FAQ — Perguntas que devs realmente fazem

1. CPF é dado sensível?

Não na classificação direta da lei, mas é dado pessoal e, na prática, equivale a um identificador único. Combinações de CPF + nome + endereço permitem reidentificação, então trate sempre como categoria alta de cuidado.

2. Preciso de DPO se minha startup é pequena?

A LGPD exige a indicação de encarregado para praticamente todos os controladores. Para startups, uma única pessoa pode acumular, mas as responsabilidades técnicas (auditoria, resposta a incidentes, comunicação com a ANPD) continuam existindo. Automatize o máximo possível.

3. Qual o prazo para responder a um pedido de titular?

A lei dá prazo razoável, interpretado pela ANPD como 15 dias. Implemente o fluxo de “direitos do titular” como feature do produto, não como processo manual.

4. Logs de aplicação podem conter e-mail do usuário?

Só se houver base legal e política de retenção explícita. O default seguro: redigir e-mail em log e usar apenas ID interno. Se precisar rastrear, gere um correlation token opaco.

5. Preciso criptografar banco em produção se o provedor já oferece?

Criptografia em repouso do provedor protege contra roubo de disco físico. Não te protege contra SQL injection, acesso indevido de aplicação ou dump indevido. São camadas complementares, não substitutas.

O que vem agora: do “está documentado” para o “está provado”

O recado do Carlos Lima, reproduzido pelo Olhar Digital, é exatamente o que eu vivo em consultorias: o próximo ciclo é de evidência. Dashboards de DSR (Data Subject Requests), métricas de tempo de resposta, trilhas de auditoria imutáveis, testes automatizados de privacidade. Vai virar CI/CD com etapa de compliance — e quem chegar antes vai economizar muito dinheiro em multa e em retrabalho.

Se você chegou até aqui, meu conselho pragmático: abra seu repositório agora, rode grep -r "cpf\|password\|email" --include="*.log" e veja o que aparece. Aposto que vai encontrar coisa que não devia. Comece por aí.

Gostou? Me segue no GitHub e deixa um comentário se tiver dúvida ou quiser aprofundar algum ponto.

Y

Yuri Sousa

Front-End Developer / Designer

Desenvolvedor apaixonado por criar experiências digitais acessíveis e visualmente perfeitas. Escrevo sobre desenvolvimento web, design e tecnologia.