Inside Cooperate's authorization blueprint
Marketplaces live or die on trust. For Cooperate that means every table, API route, and server action starts with the question: who is allowed to read or change this record?
Our layered approach
- Contracts as SSOT. Each domain exposes Zod schemas in
packages/contracts/**, establishing the exact shape of payloads flowing through the system. - Domain-level guards. Server-only modules under
src/server/domains/**enforce role checks and emit audit events—no direct Supabase calls from UI components. - RLS everywhere. Tables never allow access without row-level policies that verify tenant membership or platform staff overrides.
Roles we recognise today
- Company roles (
company_admin,project_manager,member) define what tenant staff can publish or approve. - Platform staff (
platform_admin,compliance_reviewer,support) gain read access across tenants while mutations stay bound to audited admin flows. - Anonymous visitors only touch cached marketing endpoints with no personalised data.
How audits close the loop
Every privileged operation creates an audit log entry capturing actor, action, target, and justification. SQL tests under supabase/tests/** assert that RLS policies respect those distinctions, while Playwright scenarios confirm UI access matches server intent.
What’s coming next
- Automated policy diffing in CI to flag accidental privilege creep.
- A moderation console that overlays audit events with messaging history.
- Scoped API keys so trusted partners can integrate without bypassing RBAC.
Security questions? Reach us at security@cooperate.no.