cf
CallFunnel.ai

Docs · Setup

Security & DSR.

How we isolate tenants, encrypt secrets, redact PII, log audits, and handle data-subject requests under DPDP, TCPA, and GDPR.

Tenant isolation

Hard isolation, not row-level. Every store is partitioned per tenant:

  • Postgres — schema per tenant (cf_t_{id}) inside shared databases
  • MongoDB — database per tenant (cf_t_{id})
  • Qdrant — collections per tenant (cf_t_{id}_company_kb, cf_t_{id}_customer_data)
  • HashiCorp Vault — path per tenant (secret/cf/tenants/{id}/)
  • Redis — key namespace per tenant (cf:t:{id}:*)
  • Object storage — prefix per tenant (t_{id}/)
  • Keycloak — group per tenant (t_{id}), tenant_id claim in every JWT

Why: one missing WHERE tenant_id=… can leak across customers in a row-level design. Schema/database/collection per tenant means there's no shared row to leak.

Auth & secrets

Passwords — Argon2id (OWASP 2024). Bcrypt legacy hashes rejected.

JWT — HS256, claims include sub, tid (tenant), role, exp, 7-day TTL. HttpOnly Secure cookie + bearer header fallback.

BYOK provider secrets — AES-256-GCM envelope-encrypted in Postgres. Master key in env or Vault, never logged. Decryption per-call, in memory.

Webhook signatures — Every inbound webhook (payment processor, Twilio) is signature-verified with replay-window protection.

PII redaction (pre-LLM)

Before every Claude call, customer data passes through the redactor. Patterns covered:

  • Phone (E.164, Indian regional, US 10-digit)
  • Email
  • PAN (India)
  • Aadhaar (India)
  • SSN (US)
  • IFSC, bank account number (India)
  • Money amount
  • Address (multi-line postal)

Tokens like {{phone:1}} survive the LLM round-trip and are reinjected before customer-facing output. Logs keep the redacted form; full-fidelity originals live only in the per-tenant tables.

Recording & consent

Voice — Recording disclosure played on the first turn of every call. Cannot be disabled. Consent record written per contact, per scope.

Consent scopes per contact: marketing_call, marketing_wa, recording, data_sharing_with_creator, transactional_only.

Opt-out — Spoken opt-out parsed in-call ("don't call me again," "remove me from your list"), added to internal DNC immediately. Customer also receives a confirmation message on the channel they opted out from.

DNC + (post-launch) NCPR scrub

Internal DNC list per tenant: numbers added on opt-out, support escalation, or manual import. Outbound dialer filters against it before queueing.

India NCPR daily scrub is on the post-launch roadmap (Phase 8): we pull the TRAI registry once a day, fold into the exclusion set. Until that ships, NCPR enforcement is via your manual DNC additions + Exotel's own pre-call check.

DSR — export

POST /dsr/export with the contact identifier (phone or email) returns the full bundle: every Contact record, every Conversation, every Turn, every Approval, every consent record, every audit log entry — across all your collections.

Bundle is JSON + optional ZIP of call recordings. Returned in under 30 seconds because hard isolation means it's a single-schema query, not a cross-tenant search.

DSR — erase

POST /dsr/erase with the contact identifier:

  • Drops the contact's Mongo documents (turns, conversations, decisions)
  • Deletes Postgres rows per retention policy (configurable: default delete-immediately)
  • Pseudonymises audit-keep rows (those we must retain for legal/regulatory reasons) — replaces PII with stable hashes
  • Removes Qdrant chunks tagged to the contact
  • Purges S3 prefixes (call recordings) for that contact

Audit trail of the erasure itself is retained (you have to be able to prove you erased them).

Audit logs

Per-tenant — every workflow change, every approval decision, every concession, every DSR action, every user login. Queryable from Dashboard → Audit or via API. Regulator format on request.

Global — tenant lifecycle events on the control plane: provisioning, suspension, archival, erasure. Internal; available to DPOs on request.

Data residency

India tenants → Mumbai. US tenants → us-east. EU tenants → eu-west (post-launch). Pick at tenant creation; we don't move silently. Cross-region DSR transit is logged.

Sub-processors

See the integrations page for the full list. DPA available on request to dpo@callfunnel.ai.

Disclosure

Security issues: security@callfunnel.ai (PGP on request).

DPDP / GDPR data-subject requests: dpo@callfunnel.ai.