# 4.2.3.2 Configure user roles

Following the guidance explained regarding the possible authorization [user scopes ](/product-specifications/users.md)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`.

```ts
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

```ts
id: 'FIELD_AGENT'
```

* Must be **unique** for each role.
* Is the **canonical identifier** used in:
  * `default-employees.csv` / `prod-employees.csv` (`role` column)
  * 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

```ts
label: {
  id: 'userRole.fieldAgent',
  defaultMessage: 'Field Agent',
  description: 'Name for user role Field Agent'
}
```

* `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

```ts
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]',
  // ...
]
```

* 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:

```
performance.read-dashboards
performance.vital-statistics-export
search.birth:my-jurisdiction
search.birth
search.death:my-jurisdiction
search.death
search.marriage:my-jurisdiction
search.marriage
record.read
record.registration-print&issue-certified-copies
record.registration-request-correction
record.registration-correct
record.confirm-registration
record.reject-registration
record.declared.review-duplicates
record.declare-birth
record.declare-birth:my-jurisdiction
record.declare-death
record.declare-death:my-jurisdiction
record.declare-marriage
record.declare-marriage:my-jurisdiction
record.declaration-submit-incomplete
record.declaration-submit-for-review
record.unassign-others
record.declaration-submit-for-approval
record.declaration-submit-for-updates
record.declaration-edit
record.review-duplicates
record.declaration-archive
record.declaration-reinstate
```

> 🔴 **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 ](/product-specifications/users.md)**” is the source of truth.**

* Always follow the guidance on page **“**[user scopes ](/product-specifications/users.md)**”** 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.

{% hint style="danger" %}
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:

```dynamic
event.history.role,Label for the role in event history,"{role, select, LOCAL_REGISTRAR {Local Registrar} FIELD_AGENT {Field Agent} POLICE_OFFICER {Police Officer} REGISTRATION_AGENT {Registration Agent} HEALTHCARE_WORKER {Healthcare Worker} HOSPITAL_CLERK {Hospital Clerk} LOCAL_SYSTEM_ADMIN {Administrator} NATIONAL_REGISTRAR {Registrar General} PERFORMANCE_MANAGER {Operations Manager} NATIONAL_SYSTEM_ADMIN {National Administrator} COMMUNITY_LEADER {Community Leader} HEALTH {Health integration} IMPORT {Import integration} NATIONAL_ID {National ID integration} RECORD_SEARCH {Record search integration} WEBHOOK {Webhook} other {Unknown}}","{role, select, LOCAL_REGISTRAR {Officier d'état civil local} POLICE_OFFICER {Agent de police} FIELD_AGENT {Agent de terrain} REGISTRATION_AGENT {Agent d'enregistrement} HEALTHCARE_WORKER {Professionnel de santé} PERFORMANCE_MANAGER {Responsable des opérations} LOCAL_SYSTEM_ADMIN {Administrateur} NATIONAL_SYSTEM_ADMIN {Administrateur national} NATIONAL_REGISTRAR {Registraire général} HOSPITAL_CLERK {Employé administratif à l'hôpital} HEALTH {Intégration santé} IMPORT {Intégration d'importation} NATIONAL_ID {Intégration ID nationale} RECORD_SEARCH {Intégration de recherche d'enregistrements} WEBHOOK {Webhook} COMMUNITY_LEADER {Responsable communautaire} other {Inconnu}}"

```

{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://documentation.opencrvs.org/setup/3.-installation/3.2-set-up-your-own-country-configuration/3.2.4-set-up-employees-for-testing-or-production/4.2.3.2-configure-role-titles.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
