Lgpd audit logging
Design and implement immutable, hash-chained audit logging for accountability (LGPD Art. 6, X) and incident registration (Res. 15/2024 Art. 10, 5-year retention). Use when user asks 'audit log', 'log de auditoria', 'logging LGPD', 'accountability log', or as part of audit pipeline. Outputs schema + middleware patterns for Next.js.From its SKILL.md
npx -y skills add goul4rt/lgpd-skills --skill lgpd-audit-loggingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
SKILL.md
3.6 KB, as published. Nobody here has run it
Audit Logging
Log imutável encadeado para prova de conformidade (Art. 6º, X — responsabilização) e registro de incidentes (Art. 10 Res. 15/2024 — 5 anos).
Princípios
- Append-only — sem updates nem deletes
- Hash chain — cada entry referencia o hash da anterior (tamper-evident)
- Minimização — log evento e hash do payload, NÃO o payload em claro
- PII out — nunca logar PII completa (mascarar)
- Retenção — mínimo 5 anos para eventos relacionados a incidentes; 6m+ para eventos correntes
Eventos a logar
- Autenticação (login, logout, MFA, falhas)
- Acesso a dados pessoais (especialmente sensíveis)
- Mudanças em consentimento (grant, revoke)
- DSAR (recebimento, fulfillment, rejeição)
- Mudanças de configuração de privacidade
- Acesso administrativo a dados de outros usuários
- Exports e downloads em massa
- Mudanças em RBAC
Schema Prisma
model AuditLogEntry {
id String @id @default(cuid())
actorId String? // null se sistema
actorType ActorType
action String // "READ", "WRITE", "DELETE", "EXPORT", "DSAR_FULFILLED", "CONSENT_REVOKED"
resource String // "User:abc123", "Order:xyz"
subjectId String? // titular afetado (se aplicável)
legalBasis String?
purpose String?
ipAddress String? @db.Inet
userAgent String?
payloadHash String // SHA-256 do payload (sem PII)
prevHash String? // hash do registro anterior
selfHash String // SHA-256(prevHash || timestamp || action || resource || payloadHash)
timestamp DateTime @default(now())
@@index([subjectId, timestamp])
@@index([actorId, timestamp])
@@index([action, timestamp])
}
enum ActorType { USER ADMIN SYSTEM OPERATOR }
Middleware Next.js
// lib/audit.ts
import { createHash } from "crypto";
import { db } from "./db";
export async function logAudit(entry: {
actorId?: string;
actorType: ActorType;
action: string;
resource: string;
subjectId?: string;
legalBasis?: string;
purpose?: string;
payload?: object;
req?: Request;
}) {
const last = await db.auditLogEntry.findFirst({
orderBy: { timestamp: "desc" },
select: { selfHash: true }
});
const payloadHash = createHash("sha256")
.update(JSON.stringify(entry.payload ?? {}))
.digest("hex");
const timestamp = new Date();
const selfHash = createHash("sha256")
.update(`${last?.selfHash ?? ""}|${timestamp.toISOString()}|${entry.action}|${entry.resource}|${payloadHash}`)
.digest("hex");
return db.auditLogEntry.create({
data: {
...entry,
payload: undefined,
payloadHash,
prevHash: last?.selfHash,
selfHash,
ipAddress: entry.req?.headers.get("x-forwarded-for") ?? null,
userAgent: entry.req?.headers.get("user-agent") ?? null,
timestamp
}
});
}
Verificação de integridade
Script periódico que percorre todas as entries em ordem e verifica que cada selfHash bate. Qualquer divergência = tampering ou bug.
Status update
## F6 — Audit logging ✓
- Schema implementado
- Middleware ativo em rotas críticas
- Verificação de integridade agendada (semanal)
- Retenção configurada (5 anos para eventos críticos)
- Próximo: lgpd-encryption-keys