Skip to content

REDCap to Metricis Role Mapping

This document maps REDCap's conceptual user roles to Metricis's RBAC implementation, identifies gaps, and recommends modifications.


Role Mapping Matrix

REDCap Role Metricis Role Mapping Status Notes
Project Administrator owner ✅ Mapped Full control, can delete study
Principal Investigator (PI) admin ✅ Mapped Broad visibility, manage users
Study Coordinator / Data Manager coordinator ✅ Mapped Operational control, edit participants
Data Entry User data_entry ⚠️ NEW Can edit, cannot export
Read-Only / Monitor viewer ✅ Mapped View only, no editing or export
Statistician / Analyst researcher ✅ Mapped Export data, no editing
Survey-Only User N/A ℹ️ External Participants (external, no portal access)
API / Integration User System-level ℹ️ Separate API tokens, not study-role based

Detailed Role Comparison

1. Project Administrator → owner

REDCap Permissions: - Create and modify instruments - Enable production mode - Manage users and roles - Configure data access groups (DAGs) - Export data (including identifiers)

Metricis owner Permissions: - VIEW_STUDY, EDIT_STUDY, DELETE_STUDY - VIEW_PARTICIPANTS, EDIT_PARTICIPANTS - VIEW_SESSIONS, EXPORT_DATA - MANAGE_BATTERIES, MANAGE_USERS, VIEW_AUDIT_LOG

Full match - Owner has all permissions.


2. Principal Investigator (PI) → admin

REDCap Permissions: - View all data - Export data (often with identifiers) - Review project status and logs - Limited design permissions

Metricis admin Permissions: - All permissions except DELETE_STUDY - Can manage users - Can view audit log

Good match - Admin role fits PI oversight needs.


3. Study Coordinator / Data Manager → coordinator

REDCap Permissions: - Enter and edit data - Resolve queries - Lock/unlock records - Import/export data - Monitor completeness

Metricis coordinator Permissions: - VIEW_STUDY, VIEW_PARTICIPANTS, EDIT_PARTICIPANTS - VIEW_SESSIONS, EXPORT_DATA - MANAGE_BATTERIES

Good match - Coordinator has operational control.


4. Data Entry User → data_entry (NEW)

REDCap Permissions: - Enter and edit data - View assigned records - No exports - No design or user management

Current Gap: - Metricis has no role with edit capability but export restriction - coordinator has both edit AND export - viewer has no edit capability

Proposed data_entry Permissions: - VIEW_STUDY - VIEW_PARTICIPANTS, EDIT_PARTICIPANTS - VIEW_SESSIONS - ❌ EXPORT_DATA (explicitly denied)

⚠️ NEW ROLE NEEDED - See implementation below.


5. Read-Only / Monitor → viewer

REDCap Permissions: - View data only - Access reports and dashboards - No editing or exporting

Metricis viewer Permissions: - VIEW_STUDY, VIEW_PARTICIPANTS, VIEW_SESSIONS - No export, no edit

Exact match


6. Statistician / Analyst → researcher

REDCap Permissions: - Export data (often de-identified) - View reports - No data entry or editing

Metricis researcher Permissions: - VIEW_STUDY, VIEW_PARTICIPANTS, VIEW_SESSIONS - EXPORT_DATA - No edit permissions

Exact match - Researcher can view and export but not edit.


7. Survey-Only User → External (Participants)

REDCap Permissions: - Complete surveys via public/authenticated links - No access to project backend

Metricis Implementation: - Handled via participant assessment sessions - No portal access required - Authentication via session tokens, not user accounts

ℹ️ Not a portal role - Participants use the assessment client, not the researcher portal.


8. API / Integration User → System-Level

REDCap Permissions: - API read/write access (scoped) - Often no UI access

Metricis Implementation: - API tokens are generated per-user - Could add is_api_user flag to User model - API permissions inherit from user's study roles

ℹ️ Handled differently - API access is token-based, not a separate role.


Gap Analysis

Gap 1: Missing data_entry Role

Problem: No way to give a user edit permissions without export permissions.

Solution: Add DATA_ENTRY to StudyRole enum:

class StudyRole(str, Enum):
    OWNER = "owner"
    ADMIN = "admin"
    COORDINATOR = "coordinator"
    DATA_ENTRY = "data_entry"      # NEW
    RESEARCHER = "researcher"
    VIEWER = "viewer"

Permissions for data_entry:

StudyRole.DATA_ENTRY: {
    Permission.VIEW_STUDY,
    Permission.VIEW_PARTICIPANTS,
    Permission.EDIT_PARTICIPANTS,
    Permission.VIEW_SESSIONS,
    # No EXPORT_DATA
    # No MANAGE_BATTERIES
    # No MANAGE_USERS
},

Gap 2: Role Hierarchy Update

Current hierarchy: VIEWER < RESEARCHER < COORDINATOR < ADMIN < OWNER

New hierarchy: VIEWER < DATA_ENTRY < RESEARCHER < COORDINATOR < ADMIN < OWNER

Rationale: - DATA_ENTRY has edit but no export → more trusted than VIEWER but less than RESEARCHER - RESEARCHER has export but no edit → parallel concern but more access to data - In clinical research, data entry is often done by less senior staff while statisticians need export


Implementation Plan

Step 1: Add DATA_ENTRY Role

File: server/app/services/access_control.py

class StudyRole(str, Enum):
    OWNER = "owner"
    ADMIN = "admin"
    COORDINATOR = "coordinator"
    DATA_ENTRY = "data_entry"      # ADD
    RESEARCHER = "researcher"
    VIEWER = "viewer"

ROLE_PERMISSIONS: dict[StudyRole, set[Permission]] = {
    # ... existing ...
    StudyRole.DATA_ENTRY: {
        Permission.VIEW_STUDY,
        Permission.VIEW_PARTICIPANTS,
        Permission.EDIT_PARTICIPANTS,
        Permission.VIEW_SESSIONS,
    },
}

Step 2: Update Role Hierarchy

role_hierarchy = [
    StudyRole.VIEWER,
    StudyRole.DATA_ENTRY,     # INSERT
    StudyRole.RESEARCHER,
    StudyRole.COORDINATOR,
    StudyRole.ADMIN,
    StudyRole.OWNER,
]

Step 3: Database Migration

The role field in user_studies table accepts any string, so no migration needed. The new role value will work immediately.


Test Users Matrix

Test User Global Role Study Role Use Case
admin@test.com admin N/A System admin (sees all studies)
pi@test.com researcher admin PI with admin access to specific study
coordinator@test.com researcher coordinator Study coordinator
data_entry@test.com researcher data_entry Research assistant doing data entry
analyst@test.com researcher researcher Biostatistician needing export
monitor@test.com researcher viewer Clinical monitor (read-only)

Endpoint Permission Requirements

Endpoint Required Permission Roles with Access
GET /api/studies N/A (filtered by access) All authenticated
GET /api/studies/{id} VIEW_STUDY All study roles
PATCH /api/studies/{id} EDIT_STUDY owner, admin
DELETE /api/studies/{id} DELETE_STUDY owner only
GET /api/studies/{id}/participants VIEW_PARTICIPANTS All study roles
POST /api/studies/{id}/participants EDIT_PARTICIPANTS owner, admin, coordinator, data_entry
GET /api/studies/{id}/sessions VIEW_SESSIONS All study roles
GET /api/exports/* EXPORT_DATA owner, admin, coordinator, researcher
GET /api/batteries MANAGE_BATTERIES owner, admin, coordinator
POST /api/studies/{id}/users MANAGE_USERS owner, admin

Data Access Groups (DAGs)

Metricis implements REDCap-style Data Access Groups (DAGs) to restrict users to specific sites in multi-site studies. This is controlled via the site_id field in the UserStudy association.

How DAG Filtering Works

UserStudy.site_id Behavior
NULL User can access all sites in the study
<uuid> User can only access participants at that site

Endpoints with DAG Filtering

The following endpoints enforce DAG filtering:

Participants Router: - GET /api/studies/{id}/participants - List filtered by user's site - GET /api/studies/{id}/participants/{id} - Returns 404 if outside user's site - POST /api/studies/{id}/participants - Creates at user's site by default - PATCH /api/studies/{id}/participants/{id} - Cannot move to different site - DELETE /api/studies/{id}/participants/{id} - Returns 404 if outside user's site

Exports Router: - GET /api/exports/studies/{id}/participants - Filtered by user's site - GET /api/exports/studies/{id}/sessions - Filtered by user's site - GET /api/exports/studies/{id}/responses - Filtered by user's site - GET /api/exports/studies/{id}/scheduled-visits - Filtered by user's site - GET /api/exports/studies/{id}/consent-records - Filtered by user's site - GET /api/exports/studies/{id}/full - Filtered by user's site - GET /api/exports/studies/{id}/wide - Filtered by user's site - GET /api/exports/studies/{id}/long - Filtered by user's site

Security Behavior

Scenario Response
Access participant outside DAG 404 Not Found (not 403, to prevent enumeration)
Create participant at different site 403 Forbidden
Move participant to different site 403 Forbidden
Export with DAG restriction Data filtered to user's site only

System Admin Bypass

Users with global role='admin' bypass DAG filtering and see all sites in all studies.

Example: Multi-Site Study Setup

# Site A coordinator - can only see Site A participants
UserStudy(
    user_id=coordinator_a_id,
    study_id=study_id,
    role="coordinator",
    site_id=site_a_id,  # DAG restriction
)

# Central PI - can see all sites
UserStudy(
    user_id=pi_id,
    study_id=study_id,
    role="admin",
    site_id=None,  # No DAG restriction
)

Security Considerations (Per REDCap Best Practices)

  1. Separate design authority from data entry - Implemented via role separation
  2. Limit identifier exports - EXPORT_DATA permission controls this
  3. Use DAGs for multi-site - Implemented via site_id filtering in participants and exports
  4. Create dedicated API users - Supported via API token system
  5. Document role templates - This document serves that purpose