Skip to main content

WF-108: Team Role Change

Overview

This workflow manages team member role changes within an organization. It handles promotions (member → admin → owner), demotions, role inheritance rules, permission propagation to child resources, and comprehensive audit logging for compliance.

Trigger: HTTP PATCH to /api/v1/organizations/{org_id}/members/{user_id}/role Duration: ~2-4 seconds Related Workflows: WF-005 (Invitation), WF-008 (Offboarding)


Prerequisites

Before changing a team member's role:

  • Requester must be organization owner (for admin changes) or admin (for member changes)
  • Target user must be active organization member
  • Cannot demote the last owner

Role Hierarchy

RoleLevelPermissions
Owner3Full access, billing, delete org, transfer ownership
Admin2Manage members, assign licenses, view billing
Member1Use assigned licenses, view own data
Viewer0Read-only access to shared resources

Workflow Diagram


Step-by-Step Narrative

Step 1: Validate Request Authorization

  • Node: Auth Check
  • Type: Middleware
  • Actions:
    • Extracts requester identity from JWT
    • Retrieves requester's role in organization
    • Validates permission hierarchy:
      • Owners can change any role
      • Admins can only change members/viewers
      • Members cannot change roles
    • Rejects with 403 if unauthorized

Step 2: Retrieve Current State

  • Node: Get Member Details
  • Type: PostgreSQL Select
  • Table: organization_memberships
  • Actions:
    • Fetches target user's current role
    • Retrieves user profile (name, email)
    • Gets list of assigned resources (licenses, projects)
    • Checks if user is the last owner

Step 3: Validate Role Transition

  • Node: Role Transition Rules
  • Type: Business Logic
  • Actions:
    • Validates transition is allowed:
      • Cannot demote last owner (409 Conflict)
      • Cannot promote to owner without owner permission
      • Cannot skip levels (member → owner requires intermediate)
    • Checks for conflicts:
      • Pending role change requests
      • Active sessions that need termination

Step 4: Apply Role Change

4a: Promotion Path

  • Node: Promote User
  • Actions:
    • Updates organization_memberships.role
    • Grants new permissions via Permission Service
    • Adds to admin notification lists
    • Enables access to admin-only features

4b: Demotion Path

  • Node: Demote User
  • Actions:
    • Updates organization_memberships.role
    • Revokes elevated permissions
    • Unassigns admin-only resources
    • Removes from admin notification lists
    • Invalidates admin-scoped sessions

4c: Owner Transfer Path

  • Node: Transfer Ownership
  • Actions:
    • Validates new owner meets requirements (2FA enabled, etc.)
    • Demotes current owner to admin
    • Promotes target user to owner
    • Transfers billing responsibility
    • Sends transfer confirmation emails to both parties

Step 5: Propagate Permission Changes

  • Node: Permission Propagation
  • Type: Permission Service
  • Actions:
    • Updates all child resource permissions
    • Recalculates effective permissions
    • Updates cached permission tokens
    • Triggers permission refresh for active sessions

Step 6: Audit & Notification

  • Node: Audit Trail
  • Type: Multi-Action
  • Actions:
    • Logs role change to audit_logs:
      • action: team.role.changed
      • old_role, new_role
      • changed_by, changed_at
    • Sends email notification to affected user
    • Sends notification to organization admins
    • Updates activity feed

Step 7: Return Response

  • Node: Response
  • Type: HTTP Response
  • Actions:
    • Returns updated member object with new role
    • Includes effective permissions list
    • Returns 200 OK on success

Error Handling

ErrorCodeResolution
Unauthorized401Provide valid JWT token
Forbidden403Insufficient role to make this change
Not Found404User not a member of organization
Conflict409Cannot demote last owner
Validation400Invalid role value

API Endpoints

MethodEndpointDescription
GET/api/v1/organizations/{id}/membersList all members with roles
GET/api/v1/organizations/{id}/members/{user_id}Get member details
PATCH/api/v1/organizations/{id}/members/{user_id}/roleChange member role
POST/api/v1/organizations/{id}/transfer-ownershipTransfer ownership