Security
Public embed by design — harden the edges: allowlists, honeypot, least-privilege keys, and CORS.
Project public key
pk_… is meant to appear in HTML. It only unlocks public routes. Admin mutations require a session token.
Domain allowlist
Mutating public routes check Origin / Referer. Unknown hosts → 403. Always register production domains before shipping the embed.
Honeypot
Hidden company_website field. Bots that fill it get a fake 200 with no persistence.
CORS
Set ALLOWED_ORIGINS on the Worker to dashboard, portal, and customer app origins. Avoid * with credentials in production.
Secrets
RESEND_API_KEY— Worker secret- Future
SUPABASE_SERVICE_ROLE_KEY— Worker only, never in widget
Later
Turnstile (risk-triggered), Cloudflare for SaaS custom domains, and real IdP sessions are intentionally out of V1 but fit the Cloudflare surface map.