Security Architecture
Current documented release:
0.3.3
Eryxon Flow uses a layered security model built around Supabase Auth, Postgres Row Level Security, tenant-scoped data access, and hardened edge-function helpers.
Security Model
Section titled “Security Model”The core rule is simple:
- client-side role checks improve UX
- server-side authorization decides access
- tenant isolation is enforced in the database
Frontend guards and role-aware UI are convenience features only. The authoritative boundary is the database and edge-function layer.
Authentication
Section titled “Authentication”Browser Sessions
Section titled “Browser Sessions”The application uses Supabase Auth for browser sessions:
- email/password sign-in
- invitation-based onboarding
- optional Turnstile CAPTCHA on public auth forms
- persisted JWT sessions with automatic refresh
On sign-in, the app resolves the signed-in user, loads the matching profile, and then fetches the active tenant context. When the session disappears, the app now clears both profile and tenant state immediately to avoid stale tenant context.
API Authentication
Section titled “API Authentication”External REST integrations use API keys in the Authorization header:
Authorization: Bearer ery_live_xxxxxxxxxxery_live_*keys are production keysery_test_*keys are test keys- keys are hashed with SHA-256 before storage
- comparisons use constant-time matching in the edge auth helper
API keys are tenant-bound and authenticated in supabase/functions/_shared/auth.ts.
Authorization
Section titled “Authorization”Database-First Enforcement
Section titled “Database-First Enforcement”Eryxon Flow relies on Postgres Row Level Security for real authorization:
- tenant-scoped tables are filtered through
tenant_id - edge functions set active tenant context before querying
- browser-only route guards do not grant access on their own
This means an attacker can bypass UI checks in the browser, but still cannot read or mutate data without a valid session, valid API key, and matching RLS permissions.
Role Handling
Section titled “Role Handling”The frontend uses profile role data for routing and interface decisions:
- admins can access planning, configuration, and integration screens
- operators get a narrower production-floor experience
That role field is not treated as the source of truth for security. It exists to shape the UI, while server-side enforcement remains authoritative.
Tenant Isolation
Section titled “Tenant Isolation”Tenant isolation is enforced at multiple levels:
- RLS on tenant-owned tables
- tenant-aware storage paths
- tenant-bound API keys
- tenant-scoped realtime subscriptions
- tenant context initialization through RPC helpers
This is especially important for a multi-customer manufacturing system where jobs, drawings, routing, and quality data must never bleed between organizations.
Edge Function Hardening
Section titled “Edge Function Hardening”The integrated security work delivered through 0.3.2 and packaged in 0.3.3 tightened the edge-function layer in several ways:
- shared validation and sanitization helpers are used more consistently
- wildcard CORS was replaced by environment-driven origin handling
- internal-only functions such as webhook dispatch and MQTT publish now expect a shared secret token
- error handling is sanitized before responses are returned
For production, set ALLOWED_ORIGIN explicitly so browser calls are restricted to the intended app origin.
File and Upload Security
Section titled “File and Upload Security”Files are stored in private Supabase buckets and exposed through signed URLs.
Current protections include:
- tenant-scoped storage paths
- signed URL access instead of public buckets
- content-type validation for uploads
- filename sanitization and safer upload handling
This matters for STEP files, PDFs, issue attachments, and other shop-floor artifacts that should remain tenant-private.
Webhooks and Internal Event Paths
Section titled “Webhooks and Internal Event Paths”Release 0.3.3 keeps the same deployment model and clarifies the difference between public integration endpoints and internal automation paths:
- public API endpoints use API key auth
- signup notification delivery uses an explicit Supabase Database Webhook
- internal dispatch functions should be wired with environment secrets, not open public access
This keeps deployment-specific wiring out of SQL and makes hosted and self-hosted environments more portable.
Practical Deployment Guidance
Section titled “Practical Deployment Guidance”For a secure deployment:
- Set
ALLOWED_ORIGINfor edge functions. - Keep service-role keys only in server-side secrets.
- Configure the
notify-new-signupDatabase Webhook explicitly in Supabase. - Use private storage buckets with signed URLs.
- Revalidate RLS policies whenever you add new tenant-owned tables.