Security

Built to keep every message safe.

A contact form carries people’s names, emails and plans. Here is how Heartdove handles them.

Spam checks the server can trust

Origins must match the registered website exactly, every visitor is rate limited, and each message is scored using a hidden trap field, link counts and your deny rules before anything is stored. High scores are quarantined, not alerted. Forms that use Cloudflare Turnstile also need a token verified on the server against the registered hostname and form action.

Workspaces are isolated in the database

Postgres row-level security limits every read to members of the workspace. Submission intake and delivery run through service-only database functions that browsers cannot call, and these rules are covered by automated contract tests.

Keys are never stored in plain text

Public form keys are stored only as keyed HMAC-SHA256 hashes. Provider credentials and widget secrets live in the service’s secret store, never in the database or the browser.

Webhooks you can verify

Every webhook is signed with a timestamped HMAC-SHA256 signature and carries a stable event ID. Redirects are never followed, and only operator-approved HTTPS hosts can receive deliveries.

Provider events are authenticated

Bounce, complaint and delivery reports from the email provider, and billing events from Stripe, are accepted only with a valid signature and recorded once.

Bounded retention

Message content is kept for 90 days on Free and one year on paid plans, unless you set a shorter period. Privacy mode keeps content out of the inbox entirely and encrypts transient delivery payloads with AES-GCM, removing them within 24 hours.

Where your data lives

Submissions are stored in a dedicated Supabase Postgres project in the United States (us-east-1). Form intake and delivery run on Cloudflare Workers. Email is sent through Resend and payments are handled by Stripe; Heartdove never sees card numbers.

Heartdove does not yet hold a third-party security certification. If you need a data processing agreement or have a security question, contact the team before you go live.