Skip to main content

Supabase Vault for Tenant Secrets

All tenant secrets are stored in Supabase Vault, a Postgres extension that encrypts secrets at the database level. Secrets are scoped per workspace and never stored in public schema tables.

Secret Kinds

Each workspace can store the following secret types in Vault:

Vault Access Pattern

Secrets are read from Vault only at the point of use, scoped to the requesting workspace:
Secrets from workspace A are structurally inaccessible to workspace B — the vault read function is parameterized by workspace ID, which is always derived from the authenticated session.

No Environment Variable Fallback in Production

Environment variable fallbacks for secrets are gated to non-production environments only:
This ensures that a misconfigured production deployment will fail loudly rather than silently fall back to a shared credential.
In production, if Vault returns no secret for a workspace, the operation fails with an error. There is no global fallback credential that could inadvertently be used by multiple tenants.

API Key Storage

API keys are never stored in plaintext. The storage scheme:
  1. Generation: A cryptographically random token is generated
  2. Hashing: The token is hashed with SHA-256 before database storage
  3. Prefix: The first 8 characters of the raw token are stored separately for display identification
  4. Display: The full raw token is shown to the user exactly once at creation time

Timing-Safe Validation

Key validation uses crypto.timingSafeEqual to prevent timing oracle attacks:

Security Headers

All HTTP responses from the Switchbord application include the following security headers:

Content Security Policy

HTTP Strict Transport Security

The preload directive submits the domain to browser HSTS preload lists, ensuring HTTPS-only connections even on first visit.

Additional Headers

CORS Policy

CORS is restricted to an explicit allowlist of known origins:
CORS restrictions prevent browser-based cross-origin requests from unauthorized domains. They do not prevent direct API calls (e.g., from curl or server-to-server). API authentication is the primary access control.

Encryption at Rest

Supabase provides transparent disk encryption for all data stored in its managed PostgreSQL instances. This covers the contacts, messages, workspace_members, audit_logs, and all other tables. Planned enhancement (BORD-171): Column-level encryption for PII fields (phone numbers, names, message bodies) using Supabase’s pgsodium extension. This would provide application-level encryption in addition to disk-level encryption, protecting against scenarios where database credentials are compromised.

TLS in Transit

All connections to and from Switchbord components are encrypted using TLS:
  • Vercel (web/API): TLS 1.2+ enforced by Vercel’s edge network
  • Supabase: TLS required for all database and API connections
  • Railway (worker): TLS enforced for all outbound HTTP calls
  • Meta Cloud API: All WhatsApp API calls made over HTTPS
  • AI providers: All API calls to OpenAI, Anthropic, OpenRouter made over HTTPS

Open Redirect Protection

The auth callback endpoint validates the next redirect parameter to prevent open redirect attacks:

Input Validation

All key API request bodies are validated with Zod schemas before processing:
Error responses are sanitized — raw Supabase or database errors are never returned to clients.

Compliance Mapping

For the full compliance control mapping, see the Compliance Matrix.