Security
Security model
What protects your data in nordenagent, and what you can verify yourself.
nordenagent is built on Supabase. The security story is therefore primarily a Postgres security story, and most of the controls you care about are enforced by the database, not the application.
Row Level Security everywhere
Every tenant-scoped table has RLS enabled with a policy that calls is_workspace_member(workspace_id). The function is SECURITY DEFINER, runs under a locked-down role, and checks that the current authenticated user is a member of the workspace. There is no way to read or write a row without passing through that check.
Integration secrets in Vault
Secrets such as Meta access tokens and Shopify admin tokens are stored in Supabase Vault and read only via SECURITY DEFINER RPCs that take a workspace id parameter. Application code never sees the plaintext. A second workspace cannot read your secret even if the application code asks for it — the RPC rejects the call at the database layer.
No service-role clients in request handlers
The one way to bypass RLS in Supabase is to use a service-role key. nordenagent treats that key like a nuclear option: it only exists in the Stripe webhook handler (authenticated by signed request bodies) and in background cron scripts that never serve a user request. Every route, page, and server action uses the cookie-scoped client that RLS enforces against.
Transport and headers
The app runs behind HTTPS with HSTS, X-Frame-Options: DENY, nosniff, Referrer-Policy: strict-origin-when-cross-origin, and a Content Security Policy that whitelists Supabase and the Meta Graph API. Rate limits on the login endpoint and the figma-sync webhook are enforced at the proxy layer before any handler runs.
What you can verify
- Export your workspace as JSON from Settings → Account at any time.
- Inspect the decisions log on the dashboard to see every action the agent took against your ad accounts.
- Delete your account in one step and confirm (via the Stripe portal, Meta ads audit log, etc.) that nothing remains.
- Read the data retention policy in docs/data-retention.md for the full cleanup schedule.