DEE Docs
Guides

Compliance

How the DEE supports regulatory compliance for outbound communication.

Overview

Outbound communication is heavily regulated. The DEE is designed to make compliance provable — not just "we think we're compliant" but "here is the cryptographically verifiable audit trail proving it."

Regulations

The engine helps with compliance for:

RegulationScopeKey Requirements
CAN-SPAMUS emailUnsubscribe mechanism, physical address, no deception
GDPREU all channelsConsent, right to erasure, data processing records
TCPAUS voice/SMSPrior express consent, time-of-day restrictions, DNC
CASLCanada emailExpress/implied consent, identification, unsubscribe
PECRUK email/voiceConsent, opt-out, caller ID display

The engine tracks consent status per contact per channel:

interface ConsentRecord {
  contactId: string;
  channel: 'email' | 'voice';
  status: 'granted' | 'revoked' | 'expired';
  type: 'express' | 'implied';
  grantedAt: Date;
  expiresAt?: Date;
  source: string;        // where consent was obtained
  evidence: string;       // link to consent proof
}

Before every channel action, the engine checks consent:

1. Check consent status for contact + channel
   ├── GRANTED → Proceed with action
   ├── REVOKED → Skip step, log as "skipped:no_consent"
   ├── EXPIRED → Skip step, log as "skipped:consent_expired"
   └── MISSING → Skip step, log as "skipped:no_consent_record"

Consent checks are recorded in the audit log — you can prove that every send was authorized.

Time-of-Day Restrictions

Voice calls are restricted to permitted hours based on the contact's time zone:

const voice = new VoiceChannel({
  callingHours: {
    start: '08:00',  // local time
    end: '21:00',    // local time
    timezone: 'contact', // use contact's timezone
    daysOfWeek: [1, 2, 3, 4, 5], // Mon-Fri only
  },
});

If a call step is reached outside permitted hours, the engine pauses the run and resumes at the next permitted window. This is recorded in the audit log:

[tick 432000] call-attempt: paused (outside_calling_hours, next_window: 2025-01-20T08:00:00-05:00)
[tick 471600] call-attempt: resumed (within_calling_hours)
[tick 471601] call-attempt: send_voice → answered

Suppression Lists

The engine maintains suppression lists at multiple levels:

  • Global — Contacts who have unsubscribed from all communication
  • Channel — Contacts who opted out of a specific channel (email only, no calls)
  • Plan — Contacts who opted out of a specific sequence
  • Regulatory — DNC registry entries, GDPR erasure requests
await engine.suppress({
  contactId: 'contact_123',
  level: 'global',
  reason: 'unsubscribe',
  source: 'email_link',
});

Audit Reports

Generate compliance reports for specific time periods:

const report = await engine.compliance.report({
  period: { from: '2025-01-01', to: '2025-03-31' },
  include: [
    'total_sends_by_channel',
    'consent_status_at_time_of_send',
    'suppression_events',
    'calling_hours_compliance',
    'unsubscribe_processing_time',
  ],
});

Reports include:

  • Proof that every send had valid consent at time of execution
  • Time-of-day compliance for all voice calls
  • Unsubscribe request processing times (must be < 10 business days for CAN-SPAM)
  • Complete hash chain verification for audit log integrity

On this page