4.2.3.2 Configure user roles
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.tsThis file contains all roles for your country, including the example roles used in the Farajaland configuration.
🧩 Role structure in roles.ts
roles.tsA role has three main properties: id, label, and scopes.
import { SCOPES, Scope } from '@opencrvs/toolkit/scopes'
import { MessageDescriptor } from 'react-intl'
type Role = {
id: string
label: MessageDescriptor
scopes: Scope[]
}
export const roles: 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.
🔑 id: Internal role identifier
id: Internal role identifierMust be unique for each role.
Is the canonical identifier used in:
default-employees.csv/prod-employees.csv(rolecolumn)The employee seeding process
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: What users see in the UIlabel.idis a react-intl / FormatJS key, used in translations.defaultMessageis the default English role name.descriptionhelps translators understand how the label is used.
ℹ️ Appropriate translations must exist in your
client.csvfile for eachlabel.id. For details, see the section “Managing Language Content”.
🎯 scopes: What the role is allowed to do
scopes: What the role is allowed to doThe
scopesarray defines all permissions assigned to this role.Supported scopes are imported from
@opencrvs/toolkitvia theSCOPESconstant.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:
✅ Page “user scopes ” is the source of truth.
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:
Last updated