Return a custom role's permissions in an array as a list vs top level boolean attributes for the REST/GraphQL payload

Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.

Custom roles (in our db, the table is called Member roles) use jsonb_accessor which automatically sets permissions as attributes of the model. This affects our REST and GraphQL API because permissions are returned are fields instead of values in the permissions field.

The way we are defining our APIs is also complicating our code base because of the way we use dynamic feature flags to roll out new custom abilities. We push feature flag checks into the Member model because we are unable to perform database queries during initialization which is were we are defining API attributes. Redefining our APIs to return a permissions field that contain the enabled permissions (saying that just makes too much sense) will greatly simplify our application code and will make more sense for our API consumers.

For context, this is what a member role model looks like.

[8] pry(main)> MemberRole.last
=> #<MemberRole:0x000074761678f0b8
 id: 14,
 namespace_id: 95,
 created_at: Fri, 31 Oct 2025 17:12:48.587058000 UTC +00:00,
 updated_at: Fri, 31 Oct 2025 17:18:54.737250000 UTC +00:00,
 base_access_level: 5,
 name: "min + create tokens",
 description: "min + create tokens",
 occupies_seat: true,
 permissions:
  {"read_code"=>true,
   "read_runners"=>true,
   "remove_group"=>true,
   "admin_runners"=>true,
   "admin_web_hook"=>true,
   "remove_project"=>true,
   "archive_project"=>true,
   "read_dependency"=>true,
   "admin_push_rules"=>true,
   "read_crm_contact"=>true,
   "admin_group_member"=>true,
   "admin_integrations"=>true,
   "read_vulnerability"=>true,
   "admin_merge_request"=>true,
   "admin_vulnerability"=>true,
   "admin_cicd_variables"=>true,
   "manage_deploy_tokens"=>true,
   "admin_terraform_state"=>true,
   "admin_protected_branch"=>true,
   "read_compliance_dashboard"=>true,
   "admin_compliance_framework"=>true,
   "manage_group_access_tokens"=>true,
   "manage_security_policy_link"=>true,
   "admin_protected_environments"=>true,
   "manage_project_access_tokens"=>true,
   "manage_merge_request_settings"=>true},
 organization_id: nil,
 admin_merge_request: true,
 archive_project: true,
 remove_group: true,
 remove_project: true,
 manage_security_policy_link: true,
 admin_compliance_framework: true,
 admin_cicd_variables: true,
 manage_deploy_tokens: true,
 manage_group_access_tokens: true,
 admin_group_member: true,
 admin_integrations: true,
 manage_merge_request_settings: true,
 manage_project_access_tokens: true,
 admin_protected_branch: true,
 admin_protected_environments: true,
 manage_protected_tags: nil,
 admin_push_rules: true,
 admin_runners: true,
 admin_security_attributes: nil,
 admin_security_testing: nil,
 admin_terraform_state: true,
 admin_vulnerability: true,
 admin_web_hook: true,
 read_compliance_dashboard: true,
 read_admin_cicd: nil,
 read_crm_contact: true,
 read_dependency: true,
 read_admin_groups: nil,
 read_admin_projects: nil,
 read_code: true,
 read_runners: true,
 read_security_attribute: nil,
 read_admin_subscription: nil,
 read_admin_monitoring: nil,
 read_admin_users: nil,
 read_vulnerability: true>
Edited by 🤖 GitLab Bot 🤖