Feature Owner: scorevi (Sean Patrick Caintic)
Module: User Mgmt & Enrollment
Priority: P0
Sprint #12: Fully Implemented & Deployed
Date: 2026-06-29
EXECUTIVE SUMMARY
What is this feature?
Three-layer Role-Based Access Control system governing the entire platform: (1) Platform Roles (ADMIN, CREATOR, REVIEWER, LEARNER), (2) Agency Membership Roles (OWNER, CREATOR, REVIEWER), (3) Folder Permissions (view, edit, admin, owner). Central auth engine at lib/auth/authenticate.ts (885 lines) provides all authentication and authorization functions with circuit breaker, in-memory caching, and user sync fallback.
Why does it matter?
Without RBAC, every user would have the same permissions — a security and usability nightmare. RBAC ensures admins manage the platform, creators build content, reviewers QA content, and learners consume it. Agency ownership enables B2B self-service.
What's the MVP scope?
Fully deployed. 5 platform roles. 10 auth functions (authenticateUser, authenticateUserWithRole, authenticateRole, authenticateAnyRole, authenticateUserWithAgency, authenticateRoleWithAgency, authenticateAgencyAdmin, authenticateAgencyMember, getViewAsStatus, handleAuthError). View As role preview. 8-rule agency invitation validation. Folder-level permissions.
1. USER PAIN POINT & SOLUTION
Current State (Without Feature)
All users have the same access level. No role-based routing, no agency ownership, no content review. Everything is either "logged in" or "not logged in."
Pain Point
Emotional: "Why can learners see the admin panel? This feels insecure."
Functional: No granular access control.
Business Impact: Security vulnerability; impossible to operate as a platform.
Future State (With Feature)
Each user sees exactly the dashboard and features their role permits. Layout guards block unauthorized access. RLS policies enforce data isolation.
Marketing Hook
"Five roles. Three permission layers. Every feature, precisely gated."
2. 4D FRAMEWORK MAPPING
Diagnose
View As feature lets admins diagnose learner issues by previewing their experience.
Design
Folder permissions control who can edit shared content.
Develop
Agency membership controls who can produce content within an agency.
Deliver
Not directly applicable.
3. USER FLOWS
Entry Point
User signs in → role resolved → redirected to role-specific dashboard.
Success Criteria
User sees only their authorized routes. Sensitive actions checked against permission hierarchy.
Main Flow (Happy Path)
User signs in via Clerk
authenticateUser()resolves Clerk ID → internal UUID viaapp_usersauthenticateUserWithRole()fetches platform role fromapp_users.roleLayout guard (
authenticateRole('ADMIN')) verifies role matches routeAgency guard (
authenticateAgencyMember()) verifies agency membership if applicableAll API routes call appropriate
authenticate*()functionRLS policies enforce data-level access (Supabase-level)
Decision Points
IF user role != required →
AuthorizationError→ redirect or 403.IF DB outage → circuit breaker → 503 + cooldown.
IF user not in
app_users→syncUserIfNotExists()→ auto-create with LEARNER role.
4. INFORMATION ARCHITECTURE
N/A — infrastructure layer.
5. WIREFRAMES
N/A — infrastructure layer.
6. WIREFLOWS
N/A.
7. PROTOTYPE
N/A.
8. BACKEND SCHEMA
Three-Layer Model
Layer 1: Platform Roles (app_users.role)
Role | Access |
|---|---|
ADMIN | Full platform control: manage users, agencies, system config |
AGENCY | Legacy — functionally disabled (exists in CHECK but not in View As hierarchy) |
CREATOR | Content creation, editing, publishing |
REVIEWER | Content review QA pipeline |
LEARNER | Content consumption (default for new users) |
Layer 2: Agency Membership Roles (agency_members.role)
Role | Source | Notes |
|---|---|---|
OWNER |
| Virtual role — not in agency_members table |
CREATOR |
| Agency content creators |
REVIEWER |
| Agency reviewers |
ADMIN | DEPRECATED Jun 2026 | Rows converted to CREATOR; |
Layer 3: Folder Permissions (folder_permissions)
Level | Access |
|---|---|
| Read files in folder |
| Read + modify files |
| Invite users, modify permissions |
| Full control (assigned at creation) |
9. API ENDPOINTS
Auth Functions (All in lib/auth/authenticate.ts)
Function | Returns | Use Case |
|---|---|---|
|
| Any authenticated endpoint |
|
| Endpoints needing role context |
|
| Single-role dashboards |
|
| Multi-role layouts |
|
| Agency-scoped routes |
|
| Agency + platform role |
|
| Team mgmt, billing |
|
| Agency dashboard entry |
|
| Layout re-auth guards |
|
| Standard error → HTTP |
View As Hierarchy
ADMIN → AGENCY, CREATOR, REVIEWER, LEARNERAGENCY → (none — legacy disabled)CREATOR → REVIEWER, LEARNERREVIEWER → LEARNERLEARNER → (none)
Cookie: wyzquests_view_as_role (httpOnly, 4-hour TTL, secure in production).
Role-Based API Routes
GET /api/user/available-roles (all authenticated)POST /api/user/switch-role (set/clear View As cookie)GET /api/folder/permissions/[folder_id] (with folder permissions)
10. DATA REQUIREMENTS
Frontend Needs
rolefor sidebar navigation visibility (getNavGroups.ts).isViewingAsOtherfor View As indicator.Agency membership status for agency features.
Caching Strategy
userIdCache(5-min TTL) +roleCache(30-sec TTL) inauthenticate.ts.AgencyStatusContext(1-min TTL) for agency membership.
11. PERFORMANCE CONSIDERATIONS
Database Optimization
In-memory caches reduce DB lookups for repeated auth checks.
Circuit breaker prevents cascading failures during DB outages.
API Response Time
Target: <50ms for cached auth checks. <200ms for uncached.
Who can access this feature?
All authenticated users — each at their authorized level.
Circuit Breaker: Tracks consecutive DB failures; after 1 failure → 503 for 30s cooldown.
View As: Validated against
VIEW_AS_HIERARCHY— tampered cookies ignored.RLS: Supabase-level row filtering uses
auth.uid()(actual JWT, not View As).
Agency Invitation Validation (8 Rules)
No self-invite
Cannot invite platform ADMINS
Cannot invite AGENCY owners
Cannot invite LEARNERs
Role compatibility check
Single-agency constraint
Active-only (cannot invite suspended users)
Owner-only for admin invites
13. ERROR HANDLING
Error | How Handled |
|---|---|
| 401 Unauthorized |
| 403 Forbidden |
| 503 Service Unavailable (circuit breaker) |
Invalid View As cookie | Ignored, |
14. TESTING CHECKLIST
Happy Path
□ ADMIN accesses admin routes
□ CREATOR accesses creator routes, blocked from admin
□ LEARNER blocked from creator/admin/agency/reviewer
□ View As works within hierarchy
Edge Cases
□ Circuit breaker activates on DB failure
□ Tampered View As cookie → ignored
□ User without app_users row → auto-created
□ AGENCY platform role → functionally disabled
15. OPEN QUESTIONS
For Backend:
Should we remove the AGENCY platform role entirely from the CHECK constraint? It's been functionally disabled but still exists in the schema.
16. OUT OF SCOPE (v1.1+)
Dynamic per-agency role customization.
Role expiration / temporary role grants.
Multi-agency membership.
17. SUCCESS METRICS
0 unauthorized access incidents — achieved via layout guards + RLS.
Circuit breaker uptime >99.9%.
Auth check performance <50ms for cached lookups.
18. DEPENDENCIES
This feature depends on:
[0.1] Secure Login — Clerk integration.
app_users,agencies,agency_members,folder_permissionstables.
These features depend on this:
Every feature with a protected route or API endpoint.
[0.1.1] User Role Switching — View As cookie.
[0.5] Sensitive Action Re-Auth — re-auth tokens.
[5.1]/[5.2]/[5.4] — Dashboard layouts.
[11.1]/[11.3] — Folder permissions.
19. TIMELINE & OWNERSHIP
Sprint #12: Already deployed.
Backend: scorevi
Frontend: scorevi
QA: N/A
Estimated Completion: Complete.
Document Version
1.0 - Initial version - 2026-06-29 08:22 UTC
1.1 - Added Document Version section and update author to have full name - 2026-06-29 08:47 UTC