Following the guidance explained regarding the possible authorization user scopes that are available, now you can configure the user roles that are applied to each employee.
👥 Configuring User Roles
Once you understand the authorization scopes available in OpenCRVS, you can configure the user roles that are assigned to each employee.
Roles are defined in TypeScript in:
src/data-seeding/roles/roles.ts
This file contains all roles for your country, including the example roles used in the Farajaland configuration.
🧩 Role structure in roles.ts
A role has three main properties: id, label, and scopes.
import{SCOPES,Scope}from'@opencrvs/toolkit/scopes'import{MessageDescriptor}from'react-intl'typeRole={id:stringlabel:MessageDescriptorscopes:Scope[]}exportconstroles:Role[] = [{id:'FIELD_AGENT',label:{id:'userRole.fieldAgent',defaultMessage:'Field Agent',description:'Name for user role Field Agent'},scopes: [SCOPES.RECORD_DECLARE_BIRTH,SCOPES.RECORD_DECLARE_DEATH,SCOPES.RECORD_DECLARE_MARRIAGE,SCOPES.RECORD_SUBMIT_INCOMPLETE,SCOPES.RECORD_SUBMIT_FOR_REVIEW,SCOPES.SEARCH_BIRTH,SCOPES.SEARCH_DEATH,SCOPES.SEARCH_MARRIAGE,'search[event=birth,access=all]','search[event=death,access=my-jurisdiction]','search[event=tennis-club-membership,access=all]','workqueue[id=assigned-to-you|recent|requires-updates-self|sent-for-review]',`record.create[event=birth|death|tennis-club-membership]`,'record.declare[event=birth|death|tennis-club-membership]','record.notify[event=birth|death|tennis-club-membership]' ]}, // ... other roles (POLICE_OFFICER, HOSPITAL_CLERK, COMMUNITY_LEADER, etc.)]
The rest of the file follows this pattern, defining additional roles such as POLICE_OFFICER, HOSPITAL_CLERK, LOCAL_REGISTRAR, NATIONAL_SYSTEM_ADMIN, etc.
Once used in a real environment, do not rename or reuse this ID for a different role.
🏷 label: What users see in the UI
label.id is a react-intl / FormatJS key, used in translations.
defaultMessage is the default English role name.
description helps translators understand how the label is used.
ℹ️ Appropriate translations must exist in your client.csv file for each label.id.
For details, see the section “Managing Language Content”.
🎯 scopes: What the role is allowed to do
The scopes array defines all permissions assigned to this role.
Supported scopes are imported from @opencrvs/toolkit via the SCOPES constant.
You can also see some string-based scopes (e.g. search[...], workqueue[...]), which are used for dynamic or event-specific permissions.
You design which scopes belong to which roles in your Users & Scopes design (e.g. spreadsheet), then encode that mapping here in roles.ts.
⚠️ Deprecated scopes (still present in examples)
Some scopes used in the Farajaland example roles are deprecated. They are still present for backward compatibility, but should not be used as the reference for new configurations.
Deprecated scopes include:
🔴 Important
These scopes appear in our example configuration for legacy reasons, but they are considered deprecated.
We plan to remove or refactor them in a future release.
📘 Source of truth
For the authoritative, up-to-date list of scopes and how they should be used:
Always follow the guidance on page “user scopes ” when:
Designing new roles
Assigning scopes
Updating or cleaning up legacy roles
Treat the examples in roles.ts (especially those using deprecated scopes) as historical examples only, not the canonical model.
If you change user roles and scopes over time, you must ensure you make new roles or amend existing roles. Never delete an old role otherwise your audit trail will be broken. Ensure that this content key contians a list of ALL previously avalilable roles: