Security

How your data is protected

Read-only by design

Institution access goes through Plaid (PCI-compliant, bank-grade links) and is read-only: we can read balances and transactions, never initiate a payment.

Tokens stay on the server

Plaid access tokens are stored in a table with no client-side access policies — only server-side, service-role code inside API routes can ever touch them. They never appear in a browser, a response body, or a log.

Per-user row isolation

The database enforces row-level security: every table query from your session is automatically filtered to your own rows at the Postgres layer. There is no code path where user A can read user B's accounts, transactions, goals, or insights.

Auth without passwords

Sign-in is magic-link only (Supabase Auth) — no passwords to store, leak, or reuse. Sessions are scoped cookies; sensitive writes additionally require the session to match the row owner.

Least-privilege writes

Settings save through a security-definer function that can only write your own display name — a blanket update policy would let anyone flip their own “paid” flag, so we don't have one.

Secrets

All credentials (Supabase, Plaid, Stripe, model APIs) live on the server as environment variables — none are in the repo, the client bundle, or the Vercel project's public config.

Report a concern

If you find something that looks off, email security@sharkfinsoup.cc and it gets personal attention.

Last updated: September 22, 2026