Skip to content

Permissions & Roles #75

Description

@dunnbot

Summary

Database-backed RBAC system. Every gateable action in the app is defined as a permission. Roles bundle permissions. Both roles and direct permissions can be assigned to users. Negations supersede grants.

Scope

  • Permissions — stored in DB. Each represents a discrete gateable action. Permissions have a scope: global (app-wide) or team (resolved within a team context). Registered/synced from a canonical source so the codebase and DB stay aligned.
  • Roles — named bundles of permissions stored in DB. Roles have a scope (global or team) and a tier:
    • System global roles — Administrator, Staff, Member, Banned. Apply app-wide. Locked: only Administrators can modify.
    • System team roles — e.g., Owner. Apply within a team context. Locked: only Staff or above (global) can modify.
    • Team custom roles — defined by team admins within their own team. Manageable by users with appropriate team-level permissions.
  • Direct user permissions — users can be granted (or denied) individual permissions independent of any role. Optionally scoped to a specific team.
  • Negation — any permission assignment (on a role or directly on a user) can be a grant or a negation. Negations always win, regardless of scope or source.
  • Resolution$user->can($permission, $team = null):
    • Global checks: union of global permissions from all global roles + direct global grants, minus negations.
    • Team-scoped checks: above ∪ team-scoped permissions from team role assignments for that team + direct team-scoped grants for that team, minus negations.
  • Authorization integration — every authorization check in the app (policies, gates, middleware) resolves through this system. No hardcoded role string checks.
  • Replaces the existing UserRole enum — the God/User enum is removed; equivalent access is expressed as roles.

Seeded roles

System global roles:

  • Administrator — full access (all global permissions granted).
  • Staff — basic staff access for internal team members handling support/operations. Can manage system team roles.
  • Member — default global role assigned to every user on sign-up.
  • Banned — negates all permissions globally and across all teams.

System team roles:

  • Owner — full team-scoped permissions for a team. Assigned automatically to the team creator. Cannot be modified by anyone below Staff (global). Re-assignable only via the explicit ownership transfer flow.

Acceptance criteria

  • Permissions and all seeded roles (Administrator, Staff, Member, Banned, Owner) exist after seeding
  • New users are auto-assigned the Member global role on sign-up
  • Team creators are auto-assigned the Owner team role for their team
  • Effective permission set is correctly computed (grants minus negations) for both global and team-scoped checks
  • Negations from any source override grants from any source and any scope
  • Banned global role blocks all access regardless of any other roles or permissions
  • System roles (global or team) cannot be modified except by users with sufficient tier authority
  • Team admins can create and manage custom team roles within their own team
  • All app authorization flows through this system — no hardcoded role string checks remain
  • Admins can manage roles, role-permission assignments, and user-role/permission assignments (UI lives in the Admin Panel)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions