Audit trail covers opt-out processing events
Why it matters
GDPR Article 7(3) and CAN-SPAM §7704(a)(4) require opt-outs to be honored within a defined window — but "honored" means demonstrably processed end-to-end, not just acknowledged at the API boundary. CWE-778 (Insufficient Logging) applies directly: if the opt-out worker writes only a consent record but no audit log events, you cannot reconstruct when the job started, how long ESP suppression took, or whether the 10-business-day CAN-SPAM window was met for any specific request. When a data subject or regulator asks for the processing timeline of their opt-out, a consent record showing granted = false with no operational context is an incomplete answer.
Severity rationale
Low because the opt-out itself is processed correctly — the logging gap creates a compliance demonstration problem rather than an active data subject rights violation, but that distinction disappears under a regulatory inquiry.
Remediation
Add audit log writes at each stage of the opt-out worker's processing pipeline, not just at completion:
// src/workers/optout.ts
queue.process('process-optout', async (job) => {
const { contactId, scope, requestedAt } = job.data
await logAuditEvent({ event: 'optout-processing-started', contactId, scope, requestedAt, startedAt: new Date() })
await db.consentRecord.create({ data: { contactId, scope, granted: false, source: 'unsubscribe-link' } })
await logAuditEvent({ event: 'optout-consent-record-created', contactId, scope })
await emailPlatform.suppressContact(contactId)
await logAuditEvent({ event: 'optout-esp-synced', contactId, scope, espConfirmedAt: new Date() })
const processingMs = Date.now() - new Date(requestedAt).getTime()
await logAuditEvent({ event: 'optout-processing-complete', contactId, scope, processingMs })
})
With requestedAt from the job payload and espConfirmedAt from the final log entry, you can compute the exact processing duration for any opt-out request and prove CAN-SPAM compliance on demand.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Compliance & Consent Engine Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- gdpr · Art. 7(3) — Withdrawal of consent — controller must be able to show it was processed
- external · CAN-SPAM-§7704(a)(4) — CAN-SPAM Act — 10-day processing window implies demonstrable processing timeline
- cwe · CWE-778 — Insufficient logging — opt-out processing stages not recorded
- nist:rev5 · AU-2 — Event logging — opt-out lifecycle events must be captured
Taxons
History
- 2026-04-18·v1.0.0·Initial import from compliance-consent-engine·automated