Overview

The compliance layer covers three concerns, each independently configurable and off by default — existing organizations and deployments behave exactly as before until an operator opts in:
  • PII redaction — scrub credit-card numbers, national ids, phone numbers, and emails out of stored transcripts, webhook payloads, and log lines.
  • Consent capture — record whether the remote party consented to the call (e.g. to recording), on the call record and in webhooks.
  • Toll-fraud guards — block outbound dials to premium/satellite destinations, restrict destination countries, and cap outbound calls per org per day.

Per-organization settings (COMPLIANCE block)

Managed by a super-admin via GET/PUT /admin/organizations/{org_id}/compliance:

Redaction categories

Matches are replaced with <REDACTED:category> placeholders. Redaction is pure regex + checksum (no network, no LLM), idempotent, and applied at:
  • transcript persistence — the realtime-feedback events saved on the call record and the transcript file uploaded to storage,
  • webhook payloads — transcript / transcript_object on call_ended and call_analyzed,
  • log lines that echo call content (pass-through with zero cost when redaction is off).
Scope notes (v1, honest edges):
  • Redaction applies to new calls from the moment it is enabled. Already-stored transcripts are NOT rewritten — scrubbing historical data is an operator migration, out of scope here.
  • Audio recordings are not redacted — redaction is text-only; the recording still contains the spoken PII. Disable recording for PII-sensitive agents if that matters to you.
  • Structured extraction outputs (post_call_data, gathered variables) are the agent’s intended data capture and are not redacted.
When consent_required is true for the org, the platform expects consent to be recorded per call:
  • POST /api/v1/workflow/{workflow_id}/runs/{run_id}/mark-consent with optional body {"consent_given": true|false} (defaults to true) stamps consent_given + consent_ts (UTC) on the call record.
  • Both fields — plus consent_required — are included in the call_ended / call_analyzed webhook call object. consent_given: null means consent was never recorded for the call.
v1 records consent state only. Playing a consent prompt and branching on the answer is agent configuration: add a consent question as the agent’s first turn (or IVR keypress) and have your webhook receiver / a tool call hit mark-consent. The platform does not block or terminate calls on missing consent in v1.

Outbound toll-fraud guards

Enforced at the make-call routes (/telephony/initiate-call and the public trigger-call API) before a run is created or the provider dials. Blocked calls get a clean 403 with {"code": "toll_fraud_blocked", "reason": ...} and emit a structured TOLL_FRAUD_BLOCKED org=... destination=... reason=... log line. Configuration (platform level via env or GET/PUT /admin/compliance; the stored config overrides env): The builtin premium/satellite blocklist (+870 Inmarsat, +881, +882, +883, +888, +979 international premium rate, +1900) activates as soon as any guard is configured and takes precedence over the country allowlist. Block reasons: premium_rate_destination, destination_country_not_allowed, outbound_daily_limit_reached. Scope notes:
  • Guards apply to destinations in international form (+/00 prefix). Local-format numbers and SIP URIs carry no country information and pass through unchanged.
  • Campaign batch dialing goes through its own dispatcher and is not gated by these guards in v1 (campaigns already have concurrency/CPS controls and a circuit breaker).
  • Guard-infrastructure failures (config store or counter unavailable) fail open — availability first — and are logged as errors.