Personas, Roles & Permissions
Authentication
Human Users
- Provider: Supabase Auth with Google OAuth (for @epokadvice.com workspace accounts) and magic link email invites (for clients and associates)
- Email delivery: Resend (for invites, magic links, questionnaire requests, document sharing notifications)
- Session: Supabase handles JWT sessions via
@supabase/ssrcookie-based auth; RLS policies enforce access at the database layer - Route protection:
app/lib/require-auth.server.tsguards all admin routes
AI Agents & External Clients
- API Keys:
epok_sk_...format, SHA-256 hashed inapi_keystable. Created from admin UI (/admin/api-keys) or via OAuth flow. - OAuth 2.1: Full authorization server with dynamic client registration, PKCE support. Endpoints:
/api/oauth/authorize,/api/oauth/token,/api/oauth/register. Metadata at/.well-known/oauth-authorization-serverand/.well-known/oauth-protected-resource. - Connected clients: ChatGPT (via Actions + OAuth), Claude (via MCP + OAuth)
- Auth middleware:
app/lib/api-auth.server.tsvalidates API keys for all/api/v1/*and/api/mcproutes
Role Hierarchy
super_admin
└── associate
└── client_primary
└── client_member
1. Super Admin
Who: Kendra Thompson (kendra.thompson@epokadvice.com), Ben Unsworth (ben.unsworth@epokadvice.com)
What they can do:
- Full access to everything in the system
- Create and manage engagements (client projects)
- Create, edit, and version all content (themes, templates, prompts, reports)
- Manage the knowledge base (folders, documents, tags)
- Create and manage questionnaire templates
- Run AI analyses on engagement documents
- Export content to Google Docs and Gamma
- Invite and manage all users
- Create and manage API keys
- Activate/deactivate engagement milestones
- Assign work to associates
What they see:
- Admin sidebar: Dashboard, Engagements, Knowledge Base (with inbox badge count), Questionnaires, Users & Team
- AI Chat Panel: Slide-out panel available on every admin page
- Engagement detail: Tabbed view (Overview, Documents, Questionnaires, Analysis)
2. Associate
Who: Future Epok team members, Atlas Point coaches (if given access)
What they can do:
- View and edit engagements they are assigned to
- Work on report drafts, process workshop notes, finalize presentations
- Cannot create new engagements or manage users
- Cannot access engagements they are not assigned to
- Read-only access to the knowledge base
What they see:
- List of their assigned engagements with tasks
- Engagement detail for assigned engagements
3. Client Primary (The Advisor)
Who: The financial advisor who paid for the engagement
What they can do:
- Access their own client portal only
- Fill out questionnaires
- Upload documents
- View their engagement progress (milestone tracker)
- View published report drafts (when made visible via content_visibility)
- Invite client members (e.g., their assistant)
What they see:
- Their engagement progress, questionnaires, published content
- Nothing from other clients, the knowledge base, or internal workspaces
4. Client Member
Who: The advisor's assistant, operations manager, or other team member they invite
What they can do:
- Same view as Client Primary for that engagement
- Fill out questionnaires, upload documents
- Cannot invite other members
5. AI Agents
Who: ChatGPT (via REST API / Actions), Claude (via MCP), Zapier (via ingest API)
What they can do (via agent tools):
- Search the knowledge base semantically
- Read, create, and update documents
- List engagements and their documents
- Execute any tool defined in
app/lib/agent-tools.server.ts
Auth: API key (Authorization: Bearer epok_sk_...) validated per-request
RLS Strategy Summary
| Content | Super Admin | Associate | Client Primary | Client Member | API (service role) |
|---|---|---|---|---|---|
| Knowledge base (folders, docs, tags) | Full CRUD | Read only | No access | No access | Full CRUD |
| Engagement metadata | Full CRUD | Read (assigned) | Read (own) | Read (own) | Full CRUD |
| Engagement content (notes, drafts) | Full CRUD | CRUD (assigned) | Read (published+visible) | Read (published+visible) | Full CRUD |
| Questionnaire templates | Full CRUD | Read | Read | Read | Full CRUD |
| Questionnaire responses | Full CRUD | Read (assigned) | CRUD (own) | CRUD (own) | Full CRUD |
| Analyses | Full CRUD | Read (assigned) | No access | No access | Full CRUD |
| Chat messages | Own messages | Own messages | N/A | N/A | Full CRUD |
| API keys | Own keys | Own keys | N/A | N/A | N/A |
| User management | Full CRUD | No access | Invite members | No access | Read |
Note: External API routes (/api/v1/*, /api/mcp) use the Supabase service role key, bypassing RLS. Access control is enforced at the application layer via API key validation.