Compliance
Cabinet Resolution 56/2024, enforced in SQL, not in the prompt.
Compliant AI outbound to property owners is the whole reason this product exists. Every guardrail below is a database constraint, a locked prompt section, or a compiler invariant with a failing test if it's ever removed. Prompts drift. SQL doesn't.
Controls in force
| Law / Rule | What it requires | How EstateCaller enforces it |
|---|---|---|
| TDRA calling window | 09:00–18:00 GST only, no calls on public holidays. | Database check constraint on campaigns. Dialer refuses to dial outside window; queues for the next open slot. |
| TDRA Do-Not-Call Registry (DNCR) | Numbers on the DNCR must never be dialled. | Suppression list scrubbed at claim time, dropped rows are audit-logged, never even attempted. |
| PDPL, Federal Decree-Law No. 45 of 2021 | Data subject must be notified of recording before processing begins. Purpose disclosed at point of collection. | Recording notice + purpose statement in the locked opening. Compiler invariant INV-1b blocks a build without them. |
| PDPL, Right to be forgotten | 'Remove me' must halt processing across the controller, immediately. | Owner-triggered removal writes to suppression, cascades workspace-wide. Any future campaign in the workspace skips that owner. No override in the UI. |
| RERA / Dubai Law 85 of 2006 | Brokerage must disclose registered name (and BRN on request). | Company name enforced in the identity section. ORN pulled from the workspace, said on request. |
| TDRA cadence rules | No more than one call per owner per 20 hours across all campaigns. | `claim_due_calls()` SQL function joins across campaigns before releasing a number. Enforced at the row-lock level, not the app layer. |
| 'Are you AI?' honesty | Denying AI when asked is misrepresentation under UAE fair-dealing rules. | Verbatim locked response: 'I am, I'm an AI assistant for {company}.' Compiler invariant INV-8. Cannot be edited or removed. |
Enforcement
Four layers, one direction: down into SQL.
Layer
Database
Check constraints on campaigns, RLS by org_id, atomic `claim_due_calls` with FOR UPDATE SKIP LOCKED, suppression trigger.
Layer
Compiler
Locked prompt sections (recording notice, remove-me, are-you-AI, data-source) with test-enforced invariants. speakable=false knowledge (prices, rents, service charges) never reaches the voice provider.
Layer
Runtime
Every webhook signature verified on raw body. Every dial checked against calling window, DNCR, whitelist, and 20-hour cap in order.
Layer
Audit
Every state change written to audit log with actor, before/after, timestamp. Downloadable per campaign.