Skip to main content

Authentication (Clerk)

Clerk issues JWTs on the frontend. The web app’s ApiProvider wraps createApi(getToken) so every request includes a Bearer token. On the server, clerkMiddleware() runs globally and decodes the token.

Authorization (CASL)

Authorization is enforced in two layers:
1

Server resolves ability

The requireStudioAbility(action, subject) middleware looks up the current user’s studio membership, builds a CASL ability, and attaches req.studioMembership and req.ability to the request before any protected route runs.
2

UI mirrors ability

The web app builds an ability from studio.currentUserRole in AbilityProvider and consumes it via useAbility() for UI-level permission checks (showing or hiding actions).
UI checks are for display only. The server is the source of truth — every protected route must go through requireStudioAbility.

Roles

MemberRole is one of OWNER, ADMIN, or MEMBER, defined on the StudioMember that links a User to a Studio.