Skip to content

Permissions matrix

The single source of truth is packages/contracts/src/rbac.ts. This page is generated from that file: if you find a mismatch, the contract wins.

TwistCue has ~30 permissions in the form resource:action. * is a wildcard reserved for superadmin.

Legend: ✅ granted · – not granted · Wildcard * grants everything.

Permissionsuperadmincontent_managermoderatorsupportanalystfinance
catalog:read
catalog:write
catalog:delete
publishing:read
publishing:write
curation:read
curation:write
users:read
users:ban
users:anonymize
wallet:read
wallet:adjust✅¹
payments:read
payments:refund
payments:refund_request
pricing:read
pricing:write
moderation:read
moderation:write
push:read
push:write
analytics:read
admins:read
admins:write
roles:read
roles:manage
approvals:read
approvals:decide
audit:read
system:read
system:write

¹ support’s wallet:adjust is subject to the 500-coin-per-user-per-day cap: enforced in admin-users.service, not by the guard.

  • catalog:read: view series, episodes, taxonomy, cast, media metadata
  • catalog:write: create / edit series & episodes / taxonomy / cast
  • catalog:delete: delete series (two-person action) / episodes / taxonomy / cast
  • publishing:read: view schedule / status
  • publishing:write: schedule / publish / unpublish / archive
  • curation:read: view hero / rails / collections / free-today
  • curation:write: edit hero / rails / collections / free-today
  • users:read: search / view users, notes
  • users:ban: ban / suspend / reactivate; comp subscription
  • users:anonymize: GDPR delete (two-person action)
  • wallet:read: view ledger
  • wallet:adjust: grant / deduct coins. Support-capped at 500/user/day.
  • payments:read: view transactions / refunds / reconciliation
  • payments:refund_request: request refunds (routed to executor)
  • payments:refund: execute refunds (>$50 also requires approval)
  • pricing:read, pricing:write: pricing overrides, coin packages, promos, subscriptions
  • moderation:read, moderation:write: comments, reports, strikes
  • push:read, push:write: segments, campaigns, sending
  • analytics:read: every analytics dashboard
  • admins:read, admins:write: admin user CRUD
  • roles:read, roles:manage: role CRUD
  • approvals:read, approvals:decide: two-person queue
  • audit:read: audit log
  • system:read, system:write: feature flags, market settings
  • Server-side: PermissionsGuard on every route with @RequirePermission('resource:action'). OR semantics across multiple listed perms.
  • Client-side: sidebar hides routes you can’t reach; buttons hide actions you can’t perform.
  • Superadmin * short-circuits to true in hasPermission().

Not supported. Only the 30+ predefined resource:action combinations from rbac.ts are recognized. Adding a new permission requires:

  1. Adding it to PERMISSIONS in packages/contracts/src/rbac.ts.
  2. Adding it to a PERMISSION_GROUPS entry so the role editor shows it.
  3. Applying @RequirePermission('new:perm') on the target endpoint.
  4. Rebuilding contracts, api, admin.