Entrar como:FuncionalidadesDoc
Pular para o conteúdo
← Voltar para a visão geral
✅ ConcluídoCard #48 · M8

LGPD Editor de Termos Versionado

Marco M8: Comunicação & Documentos (SULTS-inspired)

👤Wellington Santiago (via ZCode)

✅ EXECUÇÃO — 15/08/2026

Implementado e validado em produção (homolog). Commits: 2062f6c (fundação: 21 tabelas), 080c857 (features), bbfa277 (lint). Deploy CI verde.

Validação ao vivo: página(s) da feature respondendo 200 com a role correta + procedures tRPC testadas via HTTP (respostas JSON corretas). Ver relatório da sessão.

Detalhes de implementação e decisões: conforme o design acima deste documento (schema, procedures e páginas seguidos conforme especificado; ajustes menores documentados no commit).

📄 Card 48 [M8] — LGPD Editor de Termos Versionado

📚 Referência SULTS: https://www.sults.com.br/produtos/lgpd Editor de termos de uso com versionamento imutável, aceite obrigatório com bloqueio de tela e registro (nome, data, hora, versão) para auditorias da ANPD.

🎯 Objetivo

Expandir o ConsentRecord existente (Card 2) em um módulo completo de gestão de termos LGPD:

  • Editor rico de Termos de Uso (seções numeradas, links, formatação jurídica)
  • Versionamento imutável (toda alteração registra data/hora/autor)
  • Documentos por perfil: Política de Dados, Termo de Confidencialidade, DPA
  • Aceite com bloqueio de tela + assinatura obrigatória
  • Registro imutável (nome completo + data/hora + versão aceita)
  • Exportação de relatórios de aderência (ANPD)

📚 Documentação de Referência

  • docs/SEGURANCA_LGPD.md §2.3 (Consentimento)
  • prisma/schema.prismaConsentRecord já existe (expandir)

🛠️ Especificação Técnica

Schema Prisma (novo + expandir)

model LgpdTerm {
  id              String        @id @default(cuid())
  type            LgpdTermType                       // PRIVACY_POLICY, CONFIDENTIALITY, DPA, TERMS_OF_USE
  title           String
  version         Int                               // auto-incremento por tipo
  content         String        @db.Text             // markdown jurídico
  isActive        Boolean       @default(true)
  publishedAt     DateTime?
  publishedById   String
  publishedBy     User          @relation(fields: [publishedById], references: [id])
  targetRoles     String[]                          // roles que precisam aceitar
  acceptances     LgpdAcceptance[]
  createdAt       DateTime      @default(now())
  updatedAt       DateTime      @updatedAt

  @@unique([type, version])
}

model LgpdAcceptance {
  id              String   @id @default(cuid())
  termId          String
  term            LgpdTerm @relation(fields: [termId], references: [id])
  userId          String
  user            User     @relation(fields: [userId], references: [id])
  termVersion     Int                                 // snapshot da versão aceita
  acceptedAt      DateTime @default(now())
  ipAddress       String?
  userAgent       String?

  @@unique([termId, userId])
}

enum LgpdTermType { PRIVACY_POLICY  CONFIDENTIALITY  DPA  TERMS_OF_USE  IMAGE_AUTHORIZATION }

⚠️ Manter ConsentRecord (Card 2) para consentimentos granulares (LGPD opt-in por feature). LgpdTerm é para termos formais versionados.

Rotas (page.tsx)

  • /master/lgpd — painel admin (editor + versionamento + relatório aderência)
  • /master/lgpd/[termId]/editor — editor rico (markdown)
  • Componente <LgpdGate /> — wrapper que bloqueia navegação se há termo pendente

Procedures tRPC (master.lgpd)

  • terms.list (todos os tipos + versões)
  • terms.create (rascunho de nova versão)
  • terms.publish (publica nova versão — exige re-aceite de todos)
  • terms.archive
  • pendingForUser (termos que o usuário ainda não aceitou na versão vigente)
  • accept (registra LgpdAcceptance com IP + userAgent)
  • report (aderência por termo: % aceitos, pendentes, export CSV)

Editor rico

  • Usar componente <MarkdownEditor /> (pode ser react-markdown + @uiw/react-md-editor)
  • Preview side-by-side
  • Auto-save rascunho (não versiona até publish)

Lógica de trava (Gate)

  • Hook useLgpdGate(): ao montar AppShell, chama pendingForUser
  • Se houver pendente → renderiza <LgpdGate /> em tela cheia com termo + checkbox "Li e aceito" + botão confirmar
  • Não dá pra navegar sem aceitar

✅ Critérios de Aceite

  1. MASTER cria/edita/publica termos com editor rico markdown
  2. Nova versão publicada → todos precisam re-aceitar
  3. Trava de tela no login se há termo pendente
  4. Registro imutável: userId + versão + timestamp + IP + userAgent
  5. Relatório de aderência exportável CSV (ANPD)
  6. Imutabilidade: versões antigas não editáveis (apenas archived)
  7. Build passa + lint OK

🔌 Handoff

  • Hook useLgpdGate() plugado no AppShell (similar useSurveyGate)
  • Bucket lgpd-terms para anexos (se necessário)
  • Procedimento de auditoria futura: query em LgpdAcceptance por usuário/versão

🎯 Próximo

Card 49: NPS (Pesquisa de Satisfação 0-10) — M9

← Voltar para a visão geral