1. The three pillars
The product's trust posture rests on three things:
- Encryption at rest. Source credentials live in Supabase Vault (pgsodium · AES-256-GCM). Never in plaintext, anywhere.
- Tenant-scoped access. Every table is gated by Row-Level Security keyed on tenant membership. The web app holds the anon publishable key and cannot decrypt credentials.
- Audit trail. Every credential write, read, and revoke is logged with actor + timestamp. You can see the last six entries in each source's drawer.
2. Encryption
In transit
TLS 1.2+ everywhere. Worker → upstream API calls use the upstream's own TLS.
At rest — Postgres & Storage
Supabase encrypts Postgres data and Storage objects at rest by default (AES-256, managed keys).
At rest — credentials
Source tokens are stored via supabase_vault (pgsodium / libsodium) with AES-256-GCM and per-record nonces. The vault decrypt operation is privileged — it's callable only by the worker holding the service-role JWT, never from the browser.
After you save a credential, the UI immediately shows ••••a3b9 and a VAULT pill and discards the cleartext from React state. To replace a value you click Replace; unchanged fields are preserved server-side via a vault-merge so you never have to re-enter the rest.
3. Tenant isolation
- Every multi-tenant table (
tenants,memberships,sources,contact_events,kb_documents,insights,credential_audit_log) is gated by RLS keyed on the calling user's tenant membership. - Tenant creation goes through a
SECURITY DEFINERRPC (create_tenant_and_membership) rather than direct INSERTs — the naïve INSERT-with-check pattern would let a curious user join any tenant whose UUID they could guess. - Writes that affect Vault or the audit log run through SECURITY DEFINER RPCs as well:
save_source_credentials,disconnect_source,log_credential_access. - Storage uses the
kbbucket with RLS policies keyed on a path-encoded tenant prefix — a user cannot download or list another tenant's KB files.
4. Audit trail
The credential_audit_log table records:
- Action — write, read, revoke.
- Source — kind + source ID.
- Actor — the user UUID for web actions; the ingestor name for worker reads.
- Detail — a short note (e.g. which fields were replaced).
- Timestamp — UTC.
You can see the last six entries on any source drawer's Recent access panel. A full log export is available on request to hello@trythroughline.ai.
5. Operations
- Where data lives: Supabase project, ap-southeast-1 (Singapore).
- Hosting: Vercel (web app, stateless). The worker that reads your sources runs on Railway (stateless).
- Backups: Supabase's managed daily backups (point-in-time recovery available).
- Sub-processors: See Privacy §7.
- Breach notification: If we discover a confirmed breach affecting your data, we will notify you within 72 hours of confirmation with what happened, what data was affected, and what we're doing about it.
6. How we build and check it
- Sign-in by invitation. The app uses Google sign-in plus an allow list. An address that is not on the list is signed out at the door, and if the list is ever missing, nobody gets in.
- Every change is checked before it ships. Each code change runs a typecheck, a full build, the worker's test suite and a secret scan of the whole repository history. We merge only changes that pass.
- Strict headers on every response. HTTPS only, with HSTS preloaded for two years; a Content Security Policy that limits which scripts may run and where the page may send data; no framing by other sites; no content sniffing.
- Two-factor on the accounts that run the product. The hosting and worker accounts require a second factor to sign in.
- Mail that can't be spoofed easily. Our domain publishes SPF, DKIM and DMARC, so mail that claims to be from us and isn't can be rejected.
- A full security review on a schedule. We last reviewed twelve areas in October 2026: secrets, accounts, dependencies, headers, DNS and mail, logging, AI spend limits and more. The review repeats every six months.
7. Connection guide — seven habits
If you're wiring up sources for your team, treat these as defaults:
- Generate a dedicated token named “Throughline”. Don't reuse your personal admin login. A dedicated PAT / system user / service account can be revoked without breaking anyone.
- Use the exact scopes the drawer lists — no more. If we ever ask for more later, the change will be flagged before the next pull runs.
- Use a shared / business account for Meta, not personal. A personal Facebook token dies when the person leaves; a Business-Manager system-user token survives team changes.
- Rotate every ~90 days. Set a quarterly reminder. Open the drawer, click Replace, paste the new value, Save. Unchanged fields are preserved via vault merge.
- Revoke from both sides when someone leaves. Disconnect inside Throughline (clears the Vault entry + the
sourcesrow + writes a revoke audit entry), then revoke upstream via the Manage upstream ↗ link in the drawer. Throughline-side disconnect kills our access; upstream revoke kills the token globally. - Watch the audit log for unexpected reads. Worker reads happen on schedule (hourly / daily). A burst at an odd time is anomalous — open the source's Recent access panel. Web-side writes (you replacing a key) show as
user:entries. - Prefer OAuth over PAT/token where it exists. For Google sources (GSC, YouTube, GA4), OAuth means Throughline never sees your password and Google can revoke our access from their side any time. PAT/token-only tools (Calendly, Mailchimp, Amplitude) don't give us that option — pick OAuth where the choice exists.
8. Reporting an issue
Found a vulnerability? Email hello@trythroughline.ai. We commit to:
- Acknowledge receipt within 24 hours.
- Provide an initial assessment within 72 hours.
- Keep you posted while we work on a fix and credit you in our advisory if you want recognition.
- Not pursue legal action against good-faith research that respects user data and gives us a reasonable window to remediate.
Please don't run automated scans against the production environment without prior coordination — they page our oncall. For research purposes we can spin up a sandbox tenant; email first.