Security
Caddi is a multi-tenant agency platform. Tenant isolation, encryption, and an audit trail are first-class.
Tenant isolation
Every record is keyed by workspace_id, and most are also keyed by client_id. Postgres row-level security (RLS) enforces this at the database layer — application bugs cannot leak across tenants.
We run an automated RLS audit harness on every PR that asserts a sample of tables return zero rows when queried as a different agency. This blocks merges if isolation is broken.
Encryption
- In transit: TLS 1.2+ everywhere. HSTS preload on the dashboard and portal.
- At rest: Postgres on Supabase Pro (AES-256 disk + automated encrypted backups).
- Provider tokens: GitHub, Vercel, and Cloudflare credentials are stored in Supabase Vault with envelope encryption and a customer-managed key.
- Form submissions with PII: encrypted on write with a per-agency key.
Authentication
- Email + password for agency users; 2FA TOTP required for Owners.
- Magic links for end-client portal users; 7-day sessions, refreshable.
- All sessions are revocable from the agency dashboard or the user’s account settings.
- SSO via SAML is on the roadmap.
Webhooks
Inbound webhooks (GitHub, Vercel, Stripe) verify HMAC signatures and dedupe by delivery ID. Replays are silently dropped. We never trust a webhook payload without a passing signature.
Audit log
Every meaningful action is recorded — see Audit log. Exportable to CSV at any time.
Data ownership and export
- You own your data. We are a processor.
- One-click export of all agency data as JSON + R2 file URLs.
- Deletion: a 30-day grace window after request, then full purge from primary storage and backups within 90 days.
Compliance
We are pre-SOC 2 — Type I report in progress, expected within the next two quarters. GDPR and CCPA compliant by design (DPA available on request). Subprocessor list: Supabase, Vercel, Cloudflare, Resend, Sentry, Inngest.
Reporting a vulnerability
See /.well-known/security.txt or email [email protected]. We respond within 24 hours.