Skip to main content

Permissions & Scopes

What are permission scopes?​

A permission scope is a fine-grained string that controls access to a single action. Instead of checking a user's role, the system checks "does this user have scene_block:video:generate?". This lets admins grant or revoke individual capabilities without changing a user's overall role.

Scopes follow the pattern resource:action or resource:sub-resource:action.

Why fine-grained scopes?​

  • A user can be given a subset of capabilities without making them Admin.
  • An individual user can be given elevated access (e.g. episode:assign) without a role change.

All available scopes​

Admin​

ScopeDescription
admin:dashboardView the admin dashboard
admin:logs:viewView system logs
admin:logs:clearClear system logs
admin:permissions:viewView permission definitions
admin:permissions:editEdit permission definitions
admin:user:permissions:manageManage individual user permission overrides
admin:roles:viewView roles list
admin:roles:createCreate new roles
admin:roles:editEdit role names
admin:role:permissions:manageAssign/remove permissions from a role
admin:roles:deleteDelete roles
admin:analytics:editEdit analytics settings
admin:prompt_settings:editEdit LLM prompt settings
admin:preprocess_prompt_settings:editEdit prompt preprocessing settings
admin:users:viewView users list
admin:users:createCreate users
admin:users:editEdit user profiles
admin:users:deleteDelete users

Templates​

ScopeDescription
template:createCreate content templates
template:editEdit content templates
template:deleteDelete content templates

Projects​

ScopeDescription
project:createCreate projects
project:editEdit project details
project:deleteDelete projects

Episodes​

ScopeDescription
episode:createCreate episodes
episode:editEdit episode metadata
episode:deleteDelete episodes
episode:importImport an episode from another source
episode:assignManage creator assignments (roles → users)
episode:preview:uploadUpload episode preview image
episode:preview:deleteDelete episode preview image
episode:history:revertRevert episode to a previous state

Scenes​

ScopeDescription
scene:createCreate scenes in an episode
scene:editEdit scene metadata and content
scene:deleteDelete scenes
scene:emotional_arc:generateGenerate emotional arc analysis
scene:location:assignAssign a location to a scene
scene:history:revertRevert a scene to a previous state

Locations​

ScopeDescription
location:createAdd locations to the library
location:editEdit location metadata
location:deleteDelete locations
location:image:generateAI-generate a location image
location:image:uploadUpload a location image manually
location:image:deleteDelete a location image

Scene Blocks​

ScopeDescription
scene_block:createAdd blocks (dialog/action) to a scene
scene_block:editEdit block text, timing, emotion
scene_block:deleteDelete blocks
scene_block:frame:generateGenerate a start or end frame image
scene_block:frame:deleteDelete a generated frame
scene_block:video:generateGenerate a video from frames
scene_block:video:deleteDelete a generated video
scene_block:media:attachAttach media files to a block
scene_block:media:deleteRemove attached media from a block
scene_block:history:revertRevert a block to a previous state

Characters​

ScopeDescription
character:createAdd characters
character:editEdit character details
character:deleteDelete characters
character:image:generateAI-generate a character image
character:image:uploadUpload a character image manually
character:image:deleteDelete a character image

Comments​

ScopeDescription
comment:createPost comments on scene blocks
comment:resolveMark comments as resolved
comment:deleteDelete comments

Sounds​

ScopeDescription
sound:createGenerate and upload sound effects
sound:editRename sound effects
sound:deleteDelete sound effects

Voiceover​

ScopeDescription
voiceover:generateGenerate voiceover audio for a dialog block
voiceover:deleteDelete a saved voiceover

Emotions​

ScopeDescription
emotion:createCreate emotions
emotion:editEdit emotions
emotion:deleteDelete emotions
emotion:category:createCreate emotion categories
emotion:category:editEdit emotion categories
emotion:category:deleteDelete emotion categories

LLM​

ScopeDescription
llm:generateTrigger LLM text generation
llm:analyzeTrigger LLM analysis (e.g. emotional arc)
llm:approveApprove LLM-generated suggestions

World Rules​

ScopeDescription
world_rule:createCreate world rules
world_rule:editEdit world rules
world_rule:deleteDelete world rules

How permissions are checked​

Backend​

The requirePermission(scope) middleware reads the user's permissions (role permissions + individual overrides) from the JWT payload and returns 403 if the scope is missing.

router.put('/assignment-template', requireAuth, requirePermission('template:edit'), controller.save);

Frontend​

The <PermissionGate> component hides UI elements the user cannot access:

<PermissionGate permission={permissions.SCENE_BLOCK_VIDEO_GENERATE}>
<button onClick={handleGenerate}>Generate Video</button>
</PermissionGate>

It also supports mode="any" (union) and mode="all" (intersection) for multiple scopes:

// Show if user has EITHER permission
<PermissionGate permission={[permissions.VOICEOVER_GENERATE, permissions.VOICEOVER_DELETE]} mode="any">

// Show only if user has ALL permissions
<PermissionGate permission={[permissions.VOICEOVER_GENERATE, permissions.VOICEOVER_DELETE]} mode="all">

The usePermission(scope) hook returns a boolean for programmatic checks:

const canEdit = usePermission(permissions.SCENE_BLOCK_EDIT);