1 OAK MLS

Roles & Permissions

Complete reference for workspace roles, platform admin access, and permission enforcement across the 1 OAK MLS Platform

Roles & Permissions

Every workspace supports multiple members, each assigned one of four hierarchical roles. This page documents exactly what each role can access, how permissions are enforced, and the rules around member management.

Role Hierarchy

member → agent → admin → owner

Each role inherits all permissions of the roles below it. The hierarchy is enforced consistently across both apps (admin and web) using the same ordered comparison:

const ROLE_HIERARCHY: WorkspaceMemberRole[] = ['member', 'agent', 'admin', 'owner']

function hasMinimumRole(userRole, minRole): boolean {
  return ROLE_HIERARCHY.indexOf(userRole) >= ROLE_HIERARCHY.indexOf(minRole)
}

Role Definitions

Member

Typical persona: Transaction coordinator, assistant, or client with limited dashboard access.

  • View the dashboard, My Listings, and Browse MLS pages
  • View workspace members list
  • View workspace settings (read-only)
  • View sync run history and import task status
  • Cannot edit listings, branding, website pages, or settings

Agent

Typical persona: Junior agent, marketing team member, or the primary listing agent.

Everything a member can do, plus:

  • Create, edit, and manage listings and photos
  • Edit landing pages
  • Edit website pages (Home, Listings, About, Contact)
  • Edit branding (logos, colors, fonts), agent profile, and SEO settings
  • Manage service areas and compliance profiles
  • View and test the MLS data source connection
  • Upload assets (photos, videos, hero media)

Admin

Typical persona: Team lead, office manager, or tech-savvy operations person.

Everything an agent can do, plus:

  • Invite, update, and remove team members (agents and members only)
  • Edit workspace settings (name, slug, configuration)
  • Manage custom domains
  • Configure and run MLS sync operations
  • Create, edit, and run import tasks
  • Manage field mappings
  • Cancel sync runs
  • View system health
  • Manage featured listings

Owner

Typical persona: The primary agent or brokerage principal who owns the workspace.

Everything an admin can do, plus:

  • Modify or remove admins (admins cannot modify each other)
  • Only role that cannot be removed by other workspace members
  • Exactly one owner per workspace (set at creation time, transferred only by platform admins)

Dashboard Navigation Access

The web app sidebar filters navigation links based on the user's role. This table shows which sections are visible to each role:

Sectionmemberagentadminowner
Dashboardyesyesyesyes
My Listingsyesyesyesyes
Browse MLSyesyesyesyes
Landing Pages--yesyesyes
Import Data----yesyes
Website Pages (Home, Listings, About, Contact)--yesyesyes
Branding--yesyesyes
Agent Profile--yesyesyes
SEO & Tracking--yesyesyes
Service Areas--yesyesyes
Data Source--yesyesyes
Legal & Compliance--yesyesyes
Team----yesyes
Settings----yesyes
System Health----yesyes

Source: apps/web/src/components/dashboard/dashboard-shell.tsx (lines 60-103).

Admin API Permissions

All admin API routes enforce a minimum role via requireWorkspaceAccess(workspaceId, minRole). If the user does not meet the minimum role, the route returns 403 Forbidden.

Workspace Routes (minimum role: member)

These routes allow any workspace member to read data:

RouteMethodMin RoleDescription
/api/admin/workspaces/[id]GETmemberGet workspace details
/api/admin/workspaces/[id]/settingsGETmemberGet workspace settings
/api/admin/workspaces/[id]/membersGETmemberList workspace members
/api/admin/workspaces/[id]/invitationsGETmemberList invitations
/api/admin/workspaces/[id]/importsGETmemberList import tasks
/api/admin/workspaces/[id]/sync/runsGETmemberList sync runs
/api/admin/workspaces/[id]/sync/runs/[runId]GETmemberGet sync run details
/api/admin/workspaces/[id]/listings/lookupGETmemberLook up listing
/api/admin/workspaces/[id]/mls/testPOSTmemberTest MLS connection
/api/admin/workspaces/[id]/usageGETmemberGet workspace usage stats

Workspace Routes (minimum role: admin)

These routes require admin or owner for write operations:

RouteMethodMin RoleDescription
/api/admin/workspaces/[id]PATCHadminUpdate workspace
/api/admin/workspaces/[id]/settingsPATCHadminUpdate settings
/api/admin/workspaces/[id]/members/[memberId]PATCHadminUpdate member role
/api/admin/workspaces/[id]/members/[memberId]DELETEadminRemove member
/api/admin/workspaces/[id]/invitations/[invitationId]DELETEadminCancel invitation
/api/admin/workspaces/[id]/domainsPOSTadminAdd domain
/api/admin/workspaces/[id]/domains/[domainId]DELETEadminRemove domain
/api/admin/workspaces/[id]/mlsGETadminGet MLS connection details
/api/admin/workspaces/[id]/mlsPOSTadminCreate/update MLS connection
/api/admin/workspaces/[id]/sync/runPOSTadminTrigger sync run
/api/admin/workspaces/[id]/sync/runs/[runId]/cancelPOSTadminCancel sync run
/api/admin/workspaces/[id]/imports/[taskId]/runPOSTadminRun import task
/api/admin/workspaces/[id]/imports/[taskId]/togglePOSTadminEnable/disable import task
/api/admin/workspaces/[id]/mappingPOSTadminUpdate field mapping
/api/admin/workspaces/[id]/mapping/validatePOSTadminValidate field mapping
/api/admin/workspaces/[id]/mapping/[versionId]/restorePOSTadminRestore field mapping version

Web App Dashboard API Permissions

The web app uses canWrite() (agent+), isAgent() (agent+), and isAdmin() (admin+) for write operations:

OperationRequired CheckMinimum Role
Edit listings, photos, reorder photoscanWriteagent
Edit branding, upload logoscanWriteagent
Edit compliance profile, MLS logocanWriteagent
Edit service areas, reordercanWriteagent
Edit hero media, upload videoscanWriteagent
Edit website pages (hero sections)canWriteagent
Upload agent avatarcanWriteagent
Create/edit import taskscanWriteagent
Edit landing pagesisAgentagent
Configure MLS connectionisAgentagent
Test MLS connectionisAgentagent
Manage members (list, update, remove)isAdminadmin
Manage invitations (create, cancel)isAdminadmin
Manage domains (add, remove)isAdminadmin
Update system settings (features, comingSoon, mapbox)isAdminadmin
Update content settings (pages, branding, profile, SEO)canWriteagent
Delete import tasksisAdminadmin
Toggle featured listingsisAdminadmin

Platform Admin Routes

These routes are entirely separate from workspace membership and require platform admin status:

RouteMethodMin Platform RoleDescription
/api/admin/platform-adminsGETadminList platform admins
/api/admin/platform-adminsPOSTsuper_adminAdd platform admin
/api/admin/platform-admins/[adminId]PATCHsuper_adminUpdate platform admin role
/api/admin/platform-admins/[adminId]DELETEsuper_adminRemove platform admin
/api/admin/usersGETadminList all users
/api/admin/users/[userId]GETadminGet user details
/api/admin/workspaces/[id]/transfer-ownershipPOSTadminTransfer workspace ownership
/api/admin/compliance-logosGET, POSTadminManage shared compliance logos
/api/admin/settingsGET, PUTadminPlatform-wide settings
/api/admin/demo/seedPOSTadminSeed demo data

Member Management Rules

Who Can Invite

Only admin and owner roles can send invitations, enforced by the canManageMembers() check:

function canManageMembers(role: WorkspaceMemberRole): boolean {
  return role === 'owner' || role === 'admin'
}

Invitable Roles

The owner role cannot be assigned via invitation. The invitation role constraint in the database enforces this:

CHECK (role IN ('admin', 'agent', 'member'))

Role Modification Rules

The canModifyMember() function controls who can change or remove whom:

ActorCan Modify
owneradmin, agent, member
adminagent, member
agentnobody
membernobody

Key constraints:

  • Owners cannot modify other owners -- prevents removing the workspace owner
  • Admins cannot modify other admins -- prevents lateral privilege escalation
  • Nobody can self-demote below their target's role -- enforced by the actor/target comparison

Owner Protection

  • There is exactly one owner per workspace (set during workspace creation)
  • Owners cannot be removed or demoted through the member management API
  • Ownership can only be transferred by a platform admin via the /transfer-ownership endpoint

Platform Admin

Platform admin is a separate access system, independent of workspace membership.

How It Works

  • Platform admins are stored in the platform_admins table (not workspace_members)
  • When a platform admin accesses any workspace, they receive owner-level permissions regardless of whether they are a workspace member
  • The isPlatformAdmin flag on the auth result distinguishes platform admin access from actual workspace membership

Platform Role Hierarchy

admin < super_admin
Platform RoleCapabilities
adminAccess all workspaces as owner, manage users, view platform settings, transfer workspace ownership
super_adminEverything above, plus grant/revoke platform admin access to other users

Granting Platform Admin

Only a super_admin can grant or revoke platform admin status via the platform admins API. This prevents privilege escalation -- a platform admin cannot promote themselves to super_admin.

On this page