Adding a New Role
This guide explains how to add a new role to Arc's IAM (Identity and Access Management) system. Our role-based access control system uses YAML configuration files to define permissions for each role.
Prerequisites
Before creating a role policy, the role must be defined in the application's role system:
- Role Definition: The role must exist in
app/models/concerns/roles.rb
in theRoles::Role
module - Display Name: The role should have an entry in the
DISPLAY_NAMES
hash - System Role Arrays: Add the role to appropriate system role arrays (e.g.,
ECM_SYSTEM_ROLES
,CHW_SYSTEM_ROLES
)
Overview
Adding a new role involves three main steps:
- Define the role in the Roles module (prerequisite)
- Create a role policy file defining the role's permissions
- Add tests to ensure the role has the correct permissions
All permissions must already exist in the inventory (modules/iam/app/permissions/inventory.yml
) before they can be assigned to roles.
Step 1: Define the Role in the Roles Module
Before creating a policy file, ensure the role is defined in the application's role system.
Add Role Constant
Add your role to app/models/concerns/roles.rb
:
module Roles
module Role
# ... existing roles ...
SUPERVISOR = "supervisor".freeze
# ... more roles ...
end
# Add to appropriate system role array
ECM_SYSTEM_ROLES = [
# ... existing roles ...
Role::SUPERVISOR,
].freeze
# Update SYSTEM_ROLES array automatically includes the role through category arrays
# Add display name
DISPLAY_NAMES = {
# ... existing mappings ...
Role::SUPERVISOR => "Supervisor",
}.freeze
# Add role acronym if needed
ROLE_ACRONYMS = {
# ... existing mappings ...
Role::SUPERVISOR => "SUP",
}.freeze
end
Step 2: Create the Role Policy File
Create a new YAML file in modules/iam/app/permissions/
for your role. The filename should match the role identifier.
File Structure
# modules/iam/app/permissions/new_role_name.yml
# yaml-language-server: $schema=./schemas/role_policy.json
name: Display Name for Role
id: role_identifier_used_in_code
permissions:
resource_name:
action_name: {}
another_action: {}
another_resource:
action_name: {}
Example: Creating a "Supervisor" Role
# modules/iam/app/permissions/supervisor.yml
# yaml-language-server: $schema=./schemas/role_policy.json
name: Supervisor
id: supervisor
permissions:
chart:
read: {}
create: {}
update: {}
care_plan:
update: {}
review: {}
care_pod:
read: {}
create: {}
update: {}
document:
read: {}
create: {}
update: {}
delete: {}
user:
read: {}
update: {}
Key Guidelines
- Schema Validation: Include the schema comment for IDE validation
- Descriptive Name: Use a human-readable name for the
name
field - Consistent ID: Use snake_case for the
id
field that matches the filename - Empty Permission Objects: Each permission uses an empty hash
{}
(this will change in future versions) - Available Permissions: Only use permissions that exist in
inventory.yml
Step 3: Add Tests
Add comprehensive tests to ensure your role has the correct permissions and no unintended access.
Test Structure
Add a new test block in modules/iam/spec/permissions/policies_spec.rb
:
describe 'supervisor' do
include_examples 'Policy with the right permissions', role: :supervisor do
let(:expected_permissions) do
{
chart: [:read, :create, :update],
care_plan: [:update, :review],
care_pod: [:read, :create, :update],
document: [:read, :create, :update, :delete],
user: [:read, :update],
}.as_json
end
end
end
What the Tests Verify
The shared test example 'Policy with the right permissions'
verifies:
- Policy Exists: The role policy file is properly loaded
- No Extra Permissions: The role doesn't have permissions not listed in
expected_permissions
- No Missing Permissions: All permissions in
expected_permissions
are granted to the role - Permission Validity: All permissions exist in the inventory
Running Tests
# Run all policy tests
bundle exec rspec modules/iam/spec/permissions/policies_spec.rb
Validation and Debugging
Common Issues
- Role Not Found: Check that the
id
field matches the role identifier in the code - Permission Not Found: Ensure all permissions exist in
inventory.yml
- Test Failures: Ensure
expected_permissions
exactly matches the YAML file
Best Practices
1. Principle of Least Privilege
Grant only the minimum permissions necessary for the role's responsibilities:
# Good: Specific permissions for role needs
permissions:
chart:
read: {}
update: {}
document:
read: {}
# Avoid: Granting unnecessary permissions
permissions:
chart:
read: {}
create: {}
update: {}
delete: {} # Probably not needed for most roles
2. Consistent Naming
Use descriptive, consistent names:
# Good
name: Clinical Care Coordinator
id: clinical_coordinator
# Avoid
name: CCC
id: ccc_role