Trust

Security

A plain-English account of how RouteForms is built, the controls we have in place today, and what we're improving next.

Last updated: May 30, 2026

In transit and at rest

  • All traffic to RouteForms — dashboard, API, and the public form webhook — is served over HTTPS. We do not accept plain-text HTTP.
  • Our database, managed by Supabase on AWS in Singapore, is encrypted at rest.
  • Application servers and serverless functions run on Vercel and are pinned to the Singapore region (sin1).

Authentication

  • You sign in with Google through Supabase Auth. We never see or store your password; Google does the authentication and Supabase issues us a session.
  • Sessions are stored in HTTP-only, secure cookies and refreshed on every server request.
  • There is no separate username/password system to steal credentials from.

Webhook security

  • Each form gets a unique, unguessable webhook secret (16 random characters with a fr_ prefix). The URL is the credential — anyone with it can post a submission, so treat it like a password.
  • The webhook is idempotent. Apps Script retries on transient errors; we dedupe on the Google Forms response ID so a retried submission can't become two Slack posts.
  • Paused forms reject all incoming submissions with HTTP 403, and over-quota accounts reject with HTTP 429 — neither path stores partial data.

Slack credentials

  • Slack incoming-webhook URLs you paste in are stored in our database and used only to deliver responses you receive.
  • In the dashboard, we always display Slack URLs masked (only the workspace prefix and the last four characters are visible) so a shoulder-surfer can't lift them.
  • We never display the full webhook URL once it's been saved, and we never share Slack URLs with any third party.

Account isolation

  • Every form, rule, submission, and delivery log row is scoped to a single user ID in the database.
  • Every server endpoint that returns data validates that the row belongs to the signed-in user before returning anything.
  • Cross-tenant access via crafted IDs returns a 404 — the same response you'd see for a row that doesn't exist.

Billing

Payments are processed by Lemon Squeezy, our merchant of record. RouteForms never sees or stores your card number, CVC, or bank details. We store only the subscription metadata Lemon Squeezy returns (customer ID, subscription ID, plan, renewal date).

Lemon Squeezy webhook events are verified against an HMAC-SHA256 signature using Node's constant-time comparison, so an attacker can't forge plan changes.

What we explicitly don't do

  • We do not sell your data or share it for advertising.
  • We do not use third-party analytics that profile individual users — we use Vercel Analytics, which is cookieless and aggregated.
  • We do not read your Slack messages or the contents of your other Slack channels.
  • We do not read your other Google data — only the Google Forms submissions your Apps Script forwards to us.

Known gaps and what we're working on

  • Self-serve account deletion (today: by email, within 24 hours).
  • Configurable per-plan retention windows for submissions and delivery logs.
  • A formal SOC 2 / ISO 27001 audit — none today; we're a small team and have prioritised correctness, signed in by an external auditor as we grow.
  • A bug bounty programme — for now, please email the address below for responsible disclosure.

Reporting a vulnerability

If you believe you've found a security issue in RouteForms, please email routeforms@gmail.com with steps to reproduce. We'll respond within 2 business days, keep you informed on the fix, and credit you publicly if you'd like.

Please don't exfiltrate other customers' data, run automated scans against our production endpoints, or perform denial-of-service tests.

See also