Hidden buttons are not security.
Crest stores contracts, statements of account, payment records, and audit evidence for a business. Its authorization model is built as if a regulator will read it: six layers, each one assuming the one above it might fail.
Six layers, one rule.
Authorization is checked again — and again — until it reaches the database itself.
01
Edge proxy
Every non-public page and API requires an authenticated session before rendering. Marketing and auth routes are the only public surfaces.
02
Session resolution
getSession() resolves workspace, role, and effective permissions on the server for every request.
03
Presentation filtering
Navigation and buttons hide what a role can't use — explicitly treated as presentation only, never as the control.
04
Action guards
Server Actions and route handlers re-check permission and domain-policy before any mutation runs.
05
Repository scoping
Every operation is scoped to its workspace_id at the data layer. Cross-tenant access has no code path.
06
Row-level security
In production, Postgres RLS and triggers enforce tenant, permission, ownership, append-only, and lifecycle constraints — independent of the application.
Evidence can't be deleted.
Financial, contractual, stock, document-version, and audit records reject hard deletion — even for Owners. Corrections travel through a lifecycle that keeps the story legible.
- Delete
- Unused drafts and dependency-free operational data, where explicitly allowed
- Archive
- Records that leave active lists but must stay traceable
- Void
- An incorrect issued record whose original must remain visible
- Reverse
- A transaction that already changed balances or stock
- Supersede
- A renewal, amendment, corrected price, or new population snapshot
Secrets behave like secrets.
Tokens and credentials live server-side — encrypted at rest when the field-encryption key is configured, and backed by a documented rotation path.
- +Service-role credentials never leave the server runtime
- +Google and Notion tokens stored server-side, AES-256-GCM at rest when configured
- +Documents in private buckets, served by short-lived signed URLs
- +Contracts, statements, payment and visit proof never use public URLs
- +Audit and access logs exclude passwords, secrets, and session tokens
Authentication without surprises.
Cookie sessions with safe post-auth redirects. Open public signup is not part of the model — people enter through workspace onboarding or an invitation. Production fails closed when Supabase isn't configured; the local SQLite mode is for development only and is rejected in production.
Invitation-first onboarding
Members are invited or created by the team — with the last active Owner protected from removal.
Password recovery
Full recovery and reset flows with safe redirect handling after authentication.
Role-gated metrics
Portfolio MRR, cash net revenue, and rankings stay with Owner and Administrator.
Audit it yourself.
Bring your compliance questions to the demo: permission catalogs, RLS policies, the audit trail format, and the lifecycle rules — reviewed against your checklist, on screen.
Invitation-only · Onboarding guided by the team that built it