Security

What we do, stated plainly — including what we don't do yet.

Relay handles payment references and traveller names. You should not have to take a vendor's word for how that is protected, so this page describes the actual mechanisms and is explicit about the gaps.

Tenant isolation

Every table carries a workspace_id and has PostgreSQL Row Level Security enabled. A signed-in user can only read rows belonging to a workspace they are a member of, and that is enforced by the database itself — not by front-end code, and not by an ORM that could be bypassed by a crafted request.

This is tested rather than asserted. A test suite creates two unrelated workspaces, signs in as each, and fails if either can see a single row belonging to the other — through any table, any view, or any function. It runs after every schema change, because a leak of this kind looks identical to a working system until someone checks.

API keys

Keys are stored as SHA-256 hashes with a short display prefix. The raw key is shown once, at creation, and is not recoverable afterwards — not by you, not by us, and not by anyone who obtains a copy of the database. If a key is lost, the only option is to revoke it and create a new one. Revocation takes effect immediately.

Test keys and live keys are separate. A sk_test_ key can never read live-mode orders; the scope is applied server-side on every request.

Provider credentials

Credentials for connected payment processors and suppliers are encrypted at rest with a key held in the database's vault, and the ciphertext never leaves PostgreSQL — decryption happens inside a function that the browser has no permission to call. The functions that can reach the vault are executable only by the service role, which is never present in any page we serve.

Moving money

Relay can issue refunds and cancel supplier orders. That is the one part of the system where a bug costs a customer real money, so the rules that govern it are database constraints, not application code. An Edge Function can be redeployed by anyone with dashboard access; a constraint in Postgres survives that.

These are asserted by an 18-check suite that runs against the schema, including a simulated double refund, an unapproved execution, and one tenant trying to approve another's fix.

Transport and infrastructure

Everything is served over HTTPS. The database and API run on Supabase (PostgreSQL) in a single region, currently US East. Backups are managed by Supabase. If your data must stay in a specific jurisdiction, tell us before you send anything — we would rather move the deployment than discover the constraint later.

Webhooks

Outbound deliveries carry an X-Relay-Signature header. Verify it before trusting a payload; the method is documented in the API reference. Inbound webhooks from providers are signature-verified with timestamp replay protection, and an unverified payload is recorded but never allowed to write orders or cash flow.

What is not in place yet

Relay is early, and pretending otherwise would be the least secure thing on this page.

Reporting a vulnerability

Email yduan2435@gmail.com with "security" in the subject, or use the contact form. We will acknowledge within two business days. Please give us a reasonable window to fix an issue before disclosing it publicly. We do not currently run a paid bounty programme, and we will not pursue anyone acting in good faith.

Last updated 1 September 2026. If something on this page stops being true, it is a bug — tell us.