Skip to content

Role-Based Access Control (RBAC) Framework

Overview

Pomp's Dispatch Center Application implements a comprehensive Role-Based Access Control (RBAC) system to manage access across 200+ stores, 200+ technicians, dispatchers, billers, customer service representatives, and system administrators. This document defines all system roles, granular permissions, delegation authority, multi-store permission scoping, and implementation patterns.

The RBAC framework is built on Azure Active Directory (Entra ID) for authentication via OpenID Connect, with JWT tokens and custom authorization policies for fine-grained access control. All administrative operations require Multi-Factor Authentication (MFA), and access is reviewed quarterly to ensure compliance with the principle of least privilege.


Table of Contents


Authentication Architecture

Identity Provider

Component Details
Provider Azure Active Directory (Entra ID)
Protocol OpenID Connect (OIDC)
Token Type JWT (JSON Web Tokens)
Token Expiration 8 hours (with refresh token support)
Session Management Sliding expiration with automatic refresh
MFA Required for Admin roles, sensitive operations, and privileged accounts

Authentication Flow

User Login
Azure AD Authentication
Token Request (OIDC)
JWT Token + Refresh Token Issued
Token Claims Include:
    - User ID
    - Email
    - Assigned Roles (e.g., ['Dispatcher', 'Store Manager'])
    - Permissions (e.g., ['service_requests.assign', 'technician_assignment'])
Application Validates Token & Enforces RBAC Policies

Multi-Factor Authentication Requirements

Scenario MFA Required Details
Admin role access All administrative operations
Payment processing Invoice processing, refunds, preauthorizations
Data exports & reports Sensitive financial or customer data
Configuration changes System settings, role management, security policies
Remote/VPN access Off-premises and remote access
Store Manager access Store-level administrative operations
Regular technician access Mobile app and standard operations
Customer Service reps Standard customer interactions

Core Application Roles

Role Overview Table

Role Platform Target Users Scope Default Store Access
Admin Web (Vue.js 3) System Administrators, Security Team Global All stores (with audit trail)
Dispatcher Web (Vue.js 3) Dispatchers, Operations Managers Regional/Area or Central Assigned region/area or all stores (role-dependent)
Store Manager Web (Vue.js 3) Store Managers, Operations Staff Store Single store (own location)
Technician React Native Mobile Field Service Technicians Store Single store (own location)
Billing Clerk Web (Vue.js 3) Finance Team, Billing Specialists Global All stores (read-only access to customer/invoice data)
Customer Service Web (Vue.js 3) Customer Service Reps, Account Managers Global All stores (read-only)

1. Admin Role

Purpose: Full system administration, user management, security configuration, and audit access.

Target Users: System Administrators, Security Team, IT Operations

Platform: Web Application (Vue.js 3)

Key Responsibilities: - User account creation, modification, and deactivation - Role assignment and permission management - System configuration and feature flags - Security policies and access control policies - Audit log review and compliance reporting - Backup and disaster recovery management - Integration setup and maintenance - Incident response and security investigations

Default Permissions: - users.create, users.read, users.update, users.delete - roles.manage, permissions.manage - system.configure, feature_flags.manage - audit.view, audit.export - security.manage, mfa.manage - integrations.manage - All other permissions (implicit superuser)

MFA: Required

Store Access: All stores (with comprehensive audit trail)

Delegation Authority: Can create, assign, or revoke any role to any user


2. Dispatcher Role

Purpose: Central dispatch operations, technician assignment, service request management, and real-time resource allocation.

Target Users: Dispatchers, Operations Managers, Scheduling Coordinators

Platform: Web Application (Vue.js 3) - Dispatch Portal

Key Responsibilities: - View and manage incoming service requests (phone, web, email, REACH) - Assign technicians to service requests based on skills, location, and availability - Real-time technician tracking and status management - Resource allocation and load balancing - Schedule optimization and route planning - Customer communication regarding technician ETAs and appointments - Exception handling (equipment shortages, skill gaps, SLA violations) - Escalation to Store Manager or Admin as needed - Performance monitoring and KPI tracking

Default Permissions: - service_requests.view, service_requests.create, service_requests.update, service_requests.assign - technician_assignment.view, technician_assignment.create, technician_assignment.update - schedule_management.view, schedule_management.update - customer_communication.send - work_orders.view, work_orders.update - inventory.view - reporting.dispatch - exception_handling.acknowledge, exception_handling.escalate

MFA: Not required for standard operations (but recommended)

Store Access: - Central Dispatcher: All stores - Regional Dispatcher: Assigned region/area only - Store Dispatcher: Single store only

Delegation Authority: Cannot delegate roles; can only assign service requests to technicians


3. Store Manager Role

Purpose: Location-level operations oversight, local technician management, inventory control, and store performance monitoring.

Target Users: Store Managers, Assistant Store Managers, Store Operations Staff

Platform: Web Application (Vue.js 3) - Store Portal

Key Responsibilities: - Supervise store operations and technician scheduling - Approve or reject technician work order submissions - Manage local inventory (tire stock, equipment, tools) - Monitor store-specific performance metrics and KPIs - Handle local customer escalations and service recovery - Coordinate with dispatchers on technician availability - Ensure compliance with SLA commitments at store level - Approve invoices for store-related expenses - Training and oversight of store staff - Quality assurance for work completed

Default Permissions: - service_requests.view - work_orders.view, work_orders.approve, work_orders.reject - technician_assignment.view - schedule_management.view - inventory.view, inventory.update (store-level only) - customer_communication.view - reporting.store_performance - expense_approval.view, expense_approval.approve (store-level) - time_tracking.view (store technicians only)

MFA: Required

Store Access: Single store only (own location)

Delegation Authority: Cannot delegate roles; can approve local work orders and expenses up to limit

Store-Level Approval Authority: - Approve technician work orders up to $2,500 - Approve local expense requests up to $1,000 - Cannot override dispatcher assignments - Must escalate to Dispatcher/Admin for exceptions


4. Technician Role

Purpose: Field service delivery, work order execution, documentation, and customer interaction.

Target Users: Field Service Technicians (Junior, Senior, Lead, Specialist)

Platform: Mobile Application (React Native) + Limited Web Access

Key Responsibilities: - Accept or decline assigned work orders - Manage real-time job status (On My Way → Arrived → Work Complete) - Capture photographic documentation per SLA requirements - Collect customer signatures and authorization - Time tracking for work performed - Report equipment issues or inventory shortages - Real-time GPS location tracking - Offline work order access and sync when online

Default Permissions: - work_orders.view (assigned orders only) - work_orders.update_status - photos.upload, photos.view (own photos only) - customer_interaction.view, customer_interaction.respond - time_tracking.create, time_tracking.update (own time) - equipment_reporting.create - customer_signatures.collect - offline_sync.execute

MFA: Not required

Store Access: Single store only (own location)

Delegation Authority: None

Skill Levels: - Junior Technician: Standard service requests, mentored by Senior/Lead - Senior Technician: Complex service requests, standard mentoring - Lead Technician: Complex requests, staff training, quality assurance - Specialist Technician: Specialized services (e.g., OEM work, mobile tire repair certifications)

Note: Skill levels determine work order routing, not permissions. All technicians have identical permissions; assignment rules enforce skill matching.


5. Billing Clerk Role

Purpose: Invoice generation, payment processing, billing reconciliation, and financial accuracy.

Target Users: Finance Team, Billing Specialists, Accounts Payable/Receivable Staff

Platform: Web Application (Vue.js 3) - Billing Portal

Key Responsibilities: - Generate invoices from completed service requests - Validate invoice data against service documentation - Process customer payments and apply credits - Manage refunds, reversals, and adjustments - Handle billing exceptions and discrepancies - Generate financial reports and aged receivables analysis - Manage customer billing information and contract terms - Coordinate with Customer Service on billing disputes - Ensure compliance with billing requirements per customer contract - Tax code validation and application

Default Permissions: - invoices.view, invoices.create, invoices.update, invoices.finalize - invoices.generate_batch - payments.process, payments.refund - billing_adjustments.create, billing_adjustments.approve - customers.view, customers.billing_info.view - service_requests.view (for invoice source validation) - reporting.financial, reporting.aged_receivables - billing_exceptions.view, billing_exceptions.escalate - contracts.view, billing_rules.view

MFA: Required

Store Access: All stores (read-only access to customer and service data)

Delegation Authority: Cannot delegate roles

Payment Authority: - Process refunds up to $2,500 - Escalate refunds > $2,500 to Admin - Apply credits without approval - Cannot override contract-specific billing rules


6. Customer Service Role

Purpose: Customer support, service request intake, communication management, and customer satisfaction.

Target Users: Customer Service Representatives, Account Managers, Support Specialists

Platform: Web Application (Vue.js 3) - Customer Service Portal

Key Responsibilities: - Create and manage incoming service requests - Provide customers with real-time service status updates - Manage customer contact information and communication preferences - Handle routine customer inquiries and escalations - Process customer feedback and quality reports - Coordinate with Dispatcher on urgent service requests - Manage customer communication history - Document resolution of customer concerns - Generate customer satisfaction and quality reports

Default Permissions: - service_requests.view, service_requests.create, service_requests.update - customers.view, customers.contact_info.update - customer_communication.view, customer_communication.send - work_orders.view (for status updates) - reporting.customer_satisfaction, reporting.quality - customer_feedback.view, customer_feedback.manage - escalations.view, escalations.create - communication_history.view

MFA: Not required

Store Access: All stores (read-only)

Delegation Authority: None


Granular Permission Matrix

All Permissions by Category

Permission Resource Action Admin Dispatcher Store Manager Technician Billing Clerk Customer Service
User Management
users.create Users Create
users.read Users Read
users.update Users Update
users.delete Users Delete
Role Management
roles.view Roles View
roles.manage Roles Create/Update/Delete
permissions.manage Permissions Manage
Service Request Management
service_requests.view Service Requests View
service_requests.create Service Requests Create
service_requests.update Service Requests Update
service_requests.assign Service Requests Assign to Technician
service_requests.cancel Service Requests Cancel
Technician Management
technician_assignment.view Technician Assignments View
technician_assignment.create Technician Assignments Create
technician_assignment.update Technician Assignments Update/Reassign
Schedule Management
schedule_management.view Schedules View
schedule_management.update Schedules Update
Work Order Management
work_orders.view Work Orders View
work_orders.update_status Work Orders Update Status
work_orders.approve Work Orders Approve
work_orders.reject Work Orders Reject
Photo/Documentation
photos.upload Photos Upload
photos.view Photos View
photos.manage Photos Delete/Archive
Invoice Management
invoices.view Invoices View
invoices.create Invoices Create
invoices.update Invoices Update
invoices.finalize Invoices Finalize
invoices.generate_batch Invoices Batch Generate
Payment Processing
payments.process Payments Process Payment
payments.refund Payments Issue Refund
Billing Adjustments
billing_adjustments.create Billing Adjustments Create
billing_adjustments.approve Billing Adjustments Approve
Customer Management
customers.view Customers View
customers.billing_info.view Customer Billing Info View
customers.contact_info.update Customer Contact Info Update
Communication
customer_communication.view Communications View
customer_communication.send Communications Send
Inventory Management
inventory.view Inventory View
inventory.update Inventory Update (Store-Level)
Equipment Reporting
equipment_reporting.create Equipment Reports Create
equipment_reporting.view Equipment Reports View
Time Tracking
time_tracking.create Time Tracking Create Own
time_tracking.view Time Tracking View (Store-Level)
Expense Approval
expense_approval.view Expenses View (Store-Level)
expense_approval.approve Expenses Approve (Store-Level)
Reporting
reporting.dispatch Reports Dispatch Metrics
reporting.financial Reports Financial Reports
reporting.store_performance Reports Store Performance
reporting.customer_satisfaction Reports Customer Satisfaction
Audit & Security
audit.view Audit Logs View
audit.export Audit Logs Export
security.manage Security Policies Manage
mfa.manage MFA Settings Manage
System Administration
system.configure System Settings Configure
feature_flags.manage Feature Flags Manage
integrations.manage Integrations Manage
Exception Handling
exception_handling.view Exceptions View
exception_handling.acknowledge Exceptions Acknowledge
exception_handling.escalate Exceptions Escalate

Role Hierarchy & Delegation

Role Authorization Hierarchy

flowchart TB
    admin["ADMIN<br/><br/>(Full System Access, All Permissions, All Stores)"]
    dispatcher["DISPATCHER<br/><br/>(Central, Regional,<br/>Store-level)"]
    billing["BILLING CLERK<br/><br/>(Finance, Global)"]
    store_mgr["STORE MANAGER<br/><br/>(Location Ops,<br/>Single Store)"]
    customer_svc["CUSTOMER SERVICE<br/><br/>(Support, Global)"]
    tech1["TECHNICIAN<br/><br/>(Field Ops,<br/>Single Store)"]
    tech2["TECHNICIAN<br/><br/>(Store-Level)"]

    admin --> dispatcher
    admin --> billing
    admin --> store_mgr
    admin --> customer_svc
    dispatcher --> tech1
    store_mgr --> tech2

Delegation Rules

Action Who Can Delegate To Whom Requirements Audit Trail
Create User Admin Anyone MFA ✅ Yes, 10 years
Assign Role Admin Any User MFA ✅ Yes, 10 years
Revoke Role Admin Any User MFA ✅ Yes, 10 years
Approve Work Order Store Manager, Dispatcher, Admin N/A (action, not delegation) Store-scoped Yes, 2 years
Approve Expense Store Manager, Admin N/A (action, not delegation) Up to $1,000 SM / Unlimited Admin Yes, 2 years
Process Payment Billing Clerk, Admin N/A (action, not delegation) Up to $2,500 BC / Unlimited Admin Yes, 2 years
Escalate Exception Dispatcher, Store Manager Admin Auto-escalate to Admin Yes, 2 years

Who Cannot Delegate

Role Why
Technician No delegation authority; field operations only
Customer Service Support role; no administrative delegation
Billing Clerk No user management or role delegation authority
Dispatcher Cannot assign/revoke roles; only assign work orders
Store Manager Cannot create users or assign roles; can approve local operations only

Authorization Policies (C# Implementation)

// Backend authorization policies defined in Startup.cs
services.AddAuthorization(options =>
{
    // Admin-only policy
    options.AddPolicy("RequireAdminRole", 
        policy => policy.RequireRole("Admin"));

    // Dispatcher or Admin policy
    options.AddPolicy("RequireDispatcherRole", 
        policy => policy.RequireRole("Dispatcher", "Admin"));

    // Store Manager or Admin (store-scoped)
    options.AddPolicy("RequireStoreManagerRole", 
        policy => policy.RequireRole("StoreManager", "Admin"));

    // Technician or Store-assigned
    options.AddPolicy("RequireTechnicianRole", 
        policy => policy.RequireRole("Technician", "Admin"));

    // Sensitive operations (MFA required)
    options.AddPolicy("RequireMFAForSensitiveOps", 
        policy => policy
            .RequireAuthenticatedUser()
            .AddRequirements(new MFARequirement()));
});

Multi-Store Capabilities

Store-Level Permission Scoping

The system implements multi-store support for 200+ locations with role-based permission scoping at the store level.

Data Isolation Patterns

Role Store Access Pattern Query Filtering Data Visibility
Admin All stores No filter (audit logged) Full visibility (all stores)
Dispatcher All stores (Central) / Assigned region (Regional) / Single store (Store-level) Filter by region/area/store Region/area/store scoped
Store Manager Single store (own location) Filter by store ID Own store only
Technician Single store (own location) Filter by store ID Own store only
Billing Clerk All stores No filter (all service requests/invoices) Global (all stores)
Customer Service All stores No filter (all customers/requests) Global (all stores)

SQL Row-Level Security Pattern

-- Example: Technician can only view own store's work orders
CREATE SECURITY POLICY WorkOrderAccessPolicy
ADD FILTER PREDICATE dbo.WorkOrderAccessPredicate(UserID)
ON dbo.WorkOrders;

-- Predicate function
CREATE FUNCTION dbo.WorkOrderAccessPredicate(@UserID int)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
    SELECT 1 AS FilterPredicate
    WHERE @UserID IN (
        -- Admin sees all work orders
        SELECT UserID FROM dbo.Users WHERE Role = 'Admin'
        UNION
        -- Dispatchers see work orders in their region
        SELECT u.UserID FROM dbo.Users u
        INNER JOIN dbo.Stores s ON u.DispatchRegion = s.Region
        INNER JOIN dbo.WorkOrders wo ON s.StoreID = wo.StoreID
        WHERE u.UserID = @UserID
        UNION
        -- Technicians see only their own work orders
        SELECT u.UserID FROM dbo.Users u
        INNER JOIN dbo.Technicians t ON u.UserID = t.UserID
        INNER JOIN dbo.WorkOrders wo ON t.TechnicianID = wo.TechnicianID
        WHERE u.UserID = @UserID
    );

Vue.js Component-Level Permission Filtering

// Frontend permission checking with store context
import { useAuthStore } from '@/stores/auth'

export default defineComponent({
  setup(props) {
    const authStore = useAuthStore()

    // Filter work orders visible to current user
    const visibleWorkOrders = computed(() => {
      const userStores = authStore.getUserStores() // Array of store IDs
      return workOrders.value.filter(wo => 
        userStores.includes(wo.storeID)
      )
    })

    // Check if user can approve this work order
    const canApproveWorkOrder = computed(() => {
      return authStore.hasPermission('work_orders.approve') && 
             authStore.getUserStores().includes(selectedOrder.value.storeID)
    })

    return {
      visibleWorkOrders,
      canApproveWorkOrder
    }
  }
})

Regional & Area Management Roles (For 200+ Stores)

For efficient management of 200+ stores, the system supports regional/hierarchical dispatch roles:

Regional Dispatcher Role

Scope: Multiple stores within a geographic region (e.g., 10-25 stores)

Responsibilities: - Dispatch service requests across assigned region - Load balance technicians across region - Regional resource allocation and scheduling - Escalation point for area-level issues - Regional performance monitoring

Default Permissions: - service_requests.view, service_requests.assign (regional stores only) - technician_assignment.create, technician_assignment.update (regional stores only) - schedule_management.view, schedule_management.update (regional stores only) - reporting.dispatch (regional metrics only) - exception_handling.acknowledge, exception_handling.escalate (regional issues)

Store Access: Assigned region (2-25 stores via geographic/territory grouping)

Delegation Authority: None


Area Manager Role

Scope: Multiple stores within a district/area (e.g., 2-5 stores)

Responsibilities: - Coordinate operations across assigned area - Manage store manager performance and scheduling - Local compliance and quality assurance - Budget and expense oversight - Area-level escalations and incident management

Default Permissions: - service_requests.view (area stores only) - work_orders.view, work_orders.approve (area stores only) - expense_approval.view, expense_approval.approve (area stores, $5,000 limit) - reporting.store_performance (area stores only) - schedule_management.view (area stores only) - exception_handling.view, exception_handling.escalate

Store Access: Assigned area (2-5 stores)

Delegation Authority: None

Approval Authority: - Approve expenses up to $5,000 - Approve store manager exceptions - Escalate to Regional Dispatcher or Admin as needed


Multi-Store Organizational Structure Example

CENTRAL OPERATIONS (Admin/Dispatcher)
├─ REGION 1 (Regional Dispatcher)
│  │
│  ├─ AREA 1A (Area Manager)
│  │  ├─ Store 101 (Store Manager + 5 Technicians)
│  │  ├─ Store 102 (Store Manager + 3 Technicians)
│  │  └─ Store 103 (Store Manager + 4 Technicians)
│  │
│  ├─ AREA 1B (Area Manager)
│  │  ├─ Store 104 (Store Manager + 6 Technicians)
│  │  ├─ Store 105 (Store Manager + 5 Technicians)
│  │  └─ Store 106 (Store Manager + 3 Technicians)
│  │
│  └─ [Additional Areas...]
├─ REGION 2 (Regional Dispatcher)
│  │
│  ├─ AREA 2A (Area Manager)
│  │  ├─ Store 201, 202, 203...
│  │
│  └─ [Additional Areas...]
├─ BILLING OPERATIONS (Billing Manager, N/A - centralized)
│  ├─ Billing Clerk 1
│  ├─ Billing Clerk 2
│  └─ Billing Clerk 3
├─ CUSTOMER SERVICE (Customer Service Manager, N/A - centralized)
│  ├─ CSR 1
│  ├─ CSR 2
│  ├─ CSR 3
│  └─ CSR 4
└─ SYSTEM ADMINISTRATION (IT/Security)
   └─ Admin (full access)

Store Manager Role (Location-Level Operations)

Detailed Responsibilities

The Store Manager role bridges operations between field technicians and regional/central dispatch. This role is critical for store-level performance and customer satisfaction.

Work Order Approval Workflow

Technician Completes Work Order
Uploads Photos & Documentation
System Validates Photo Requirements
Store Manager Receives Notification
Store Manager Reviews:
  - Completeness of work
  - Photo quality/requirements
  - Customer signature
  - Equipment/parts used
  - Time spent
Decision Point:
  ├─ APPROVE → Work Order finalized, ready for billing
  ├─ REJECT → Return to technician with comments
  └─ ESCALATE → Send to Dispatcher/Admin for review
Escalated Issues (if needed)
  - Equipment shortages
  - Quality concerns
  - Customer disputes
  - Billing discrepancies

Store Manager Approval Authority

Action Authority Limit
Approve work orders All approved work orders at store
Reject work orders With comments returned to technician
Approve store expenses Up to $1,000 per transaction
Approve technician time Store-level payroll review
Approve inventory adjustments Within standard variance thresholds
Escalate exceptions To Dispatcher/Admin
Modify technician schedules Within store scope only (coordinate with Dispatcher)
Approve refunds Billing Clerk/Admin only
Create new user accounts Admin only
Assign technician roles Admin only

Store Manager Cannot

  • Reassign work orders between stores
  • Override central dispatch assignments
  • Create or delete users
  • Assign or revoke roles
  • Process payments
  • Generate invoices
  • Access other stores' data
  • Export customer/financial data

Implementation Details

Backend Authorization Attributes (C#)

// Service Request Controller Example
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class ServiceRequestsController : ControllerBase
{
    // View service requests (Dispatcher, Admin, Store Manager, Billing, Customer Service)
    [HttpGet("{storeId}")]
    [Authorize(Policy = "CanViewServiceRequests")]
    public async Task<IActionResult> GetServiceRequests(int storeId)
    {
        var userContext = HttpContext.User;
        var userStores = await _authService.GetUserAuthorizedStores(userContext);

        if (!userStores.Contains(storeId) && !userContext.IsInRole("Admin"))
            return Forbid();

        return Ok(await _serviceRequestService.GetByStoreAsync(storeId));
    }

    // Create service request (Dispatcher, Admin, Customer Service)
    [HttpPost]
    [Authorize(Policy = "CanCreateServiceRequests")]
    public async Task<IActionResult> CreateServiceRequest(
        [FromBody] CreateServiceRequestDto dto)
    {
        if (!User.HasPermission("service_requests.create"))
            return Forbid();

        var request = await _serviceRequestService.CreateAsync(dto, User.GetUserId());
        return CreatedAtAction(nameof(GetServiceRequests), request);
    }

    // Assign technician (Dispatcher, Admin)
    [HttpPut("{id}/assign")]
    [Authorize(Policy = "CanAssignTechnicians")]
    [Authorize(Policy = "RequireMFAForSensitiveOps")] // Optional: MFA for critical ops
    public async Task<IActionResult> AssignTechnician(
        int id, 
        [FromBody] AssignTechnicianDto dto)
    {
        if (!User.HasPermission("service_requests.assign"))
            return Forbid();

        var serviceRequest = await _serviceRequestService.GetByIdAsync(id);
        var assigned = await _dispatchService.AssignTechnicianAsync(
            serviceRequest, 
            dto.TechnicianId, 
            User.GetUserId());

        await _auditService.LogAsync("ServiceRequest.Assigned", id, User.GetUserId());
        return Ok(assigned);
    }
}

// Work Order Controller Example
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class WorkOrdersController : ControllerBase
{
    // Approve work order (Store Manager, Dispatcher, Admin)
    [HttpPut("{id}/approve")]
    [Authorize(Policy = "CanApproveWorkOrders")]
    public async Task<IActionResult> ApproveWorkOrder(
        int id, 
        [FromBody] ApproveWorkOrderDto dto)
    {
        if (!User.HasPermission("work_orders.approve"))
            return Forbid();

        var workOrder = await _workOrderService.GetByIdAsync(id);

        // Store Manager can only approve work orders in their own store
        if (User.IsInRole("StoreManager"))
        {
            var managerStoreId = await _userService.GetStoreIdAsync(User.GetUserId());
            if (workOrder.StoreId != managerStoreId)
                return Forbid();
        }

        var approved = await _workOrderService.ApproveAsync(id, dto, User.GetUserId());
        await _auditService.LogAsync("WorkOrder.Approved", id, User.GetUserId());

        return Ok(approved);
    }
}

// Billing Clerk Controller Example
[ApiController]
[Route("api/[controller]")]
[Authorize(Policy = "RequireBillingClerkRole")]
public class InvoicesController : ControllerBase
{
    // Generate invoice (Billing Clerk, Admin)
    [HttpPost("generate")]
    [Authorize(Policy = "RequireMFAForSensitiveOps")] // MFA required for payments
    public async Task<IActionResult> GenerateInvoice(
        [FromBody] GenerateInvoiceDto dto)
    {
        if (!User.HasPermission("invoices.create"))
            return Forbid();

        var invoice = await _invoiceService.GenerateAsync(dto, User.GetUserId());
        await _auditService.LogAsync("Invoice.Generated", invoice.Id, User.GetUserId());

        return CreatedAtAction(nameof(GetInvoice), invoice);
    }

    // Process payment (Billing Clerk, Admin)
    [HttpPost("{id}/process-payment")]
    [Authorize(Policy = "RequireMFAForSensitiveOps")] // MFA required
    public async Task<IActionResult> ProcessPayment(
        int id, 
        [FromBody] ProcessPaymentDto dto)
    {
        if (!User.HasPermission("payments.process"))
            return Forbid();

        // Billing Clerks can only process payments up to $2,500
        if (User.IsInRole("BillingClerk") && dto.Amount > 2500m)
        {
            return BadRequest("Billing Clerks cannot process payments over $2,500");
        }

        var payment = await _paymentService.ProcessAsync(id, dto, User.GetUserId());
        await _auditService.LogAsync("Payment.Processed", id, User.GetUserId());

        return Ok(payment);
    }
}

Frontend Permission Guards (Vue.js 3)

// Composable for permission checking
import { useAuthStore } from '@/stores/auth'
import type { Router } from 'vue-router'

export function usePermissions(router: Router) {
  const authStore = useAuthStore()

  // Check if user has permission
  const hasPermission = (permission: string): boolean => {
    return authStore.permissions.includes(permission)
  }

  // Check if user has role
  const hasRole = (role: string): boolean => {
    return authStore.roles.includes(role)
  }

  // Check if user can access store
  const canAccessStore = (storeId: number): boolean => {
    if (authStore.hasRole('Admin')) return true // Admin sees all
    if (authStore.userStores.includes(storeId)) return true
    return false
  }

  // Route guard for protected pages
  const setupRouteGuards = () => {
    router.beforeEach((to, from, next) => {
      if (to.meta.requiresAuth && !authStore.isAuthenticated) {
        next('/login')
        return
      }

      if (to.meta.requiredPermission) {
        if (!hasPermission(to.meta.requiredPermission)) {
          next('/unauthorized')
          return
        }
      }

      if (to.meta.requiredRole) {
        if (!hasRole(to.meta.requiredRole)) {
          next('/unauthorized')
          return
        }
      }

      next()
    })
  }

  return {
    hasPermission,
    hasRole,
    canAccessStore,
    setupRouteGuards
  }
}

// Component-level permission checking
export default defineComponent({
  name: 'WorkOrderApproval',
  setup() {
    const authStore = useAuthStore()

    // Can only show approval button if user has permission AND can access store
    const canApproveOrder = computed(() => {
      return authStore.hasPermission('work_orders.approve') &&
             authStore.canAccessStore(selectedWorkOrder.value.storeId)
    })

    // Filter visible work orders based on user's store access
    const visibleWorkOrders = computed(() => {
      if (authStore.hasRole('Admin')) {
        return allWorkOrders.value // Admin sees all
      }

      return allWorkOrders.value.filter(wo => 
        authStore.userStores.includes(wo.storeId)
      )
    })

    // Dispatch assignment - Dispatcher only
    const canAssignTechnician = computed(() => {
      return authStore.hasPermission('service_requests.assign') &&
             (authStore.hasRole('Dispatcher') || authStore.hasRole('Admin'))
    })

    return {
      canApproveOrder,
      visibleWorkOrders,
      canAssignTechnician
    }
  }
})

JWT Token Claims Structure

{
  "sub": "user-id-12345",
  "email": "john.smith@pomps.com",
  "name": "John Smith",
  "roles": [
    "StoreManager"
  ],
  "permissions": [
    "service_requests.view",
    "work_orders.view",
    "work_orders.approve",
    "work_orders.reject",
    "technician_assignment.view",
    "schedule_management.view",
    "schedule_management.update",
    "inventory.view",
    "inventory.update",
    "customer_communication.view",
    "expense_approval.view",
    "expense_approval.approve",
    "reporting.store_performance",
    "exception_handling.view",
    "exception_handling.escalate"
  ],
  "storeIds": [
    101
  ],
  "storeRegion": "northeast",
  "mfaVerified": true,
  "aud": "pomps-dispatch-api",
  "iss": "https://login.microsoftonline.com/{tenant-id}",
  "iat": 1674520800,
  "exp": 1674556800
}

Access Review & Compliance Process

Quarterly Access Review

Pomp's Dispatch Center Application implements a quarterly access review process to ensure users retain only necessary permissions.

Review Schedule

Quarter Review Period Deadline Reviewers
Q1 Jan 1 - Mar 31 Apr 15 Line Managers, Security Team, App Owners
Q2 Apr 1 - Jun 30 Jul 15 Line Managers, Security Team, App Owners
Q3 Jul 1 - Sep 30 Oct 15 Line Managers, Security Team, App Owners
Q4 Oct 1 - Dec 31 Jan 15 (next year) Line Managers, Security Team, App Owners

Review Checklist

  • [ ] All user accounts are still active and assigned to current employees
  • [ ] Users retain only roles/permissions necessary for current job function
  • [ ] Inactive accounts (90+ days no login) are deactivated
  • [ ] Shared accounts are eliminated (each user has individual account)
  • [ ] Service accounts have documented owners and renewal dates
  • [ ] Admin users are minimized (principle of least privilege)
  • [ ] Store Manager users can only access assigned store
  • [ ] Technicians are assigned to correct store only
  • [ ] Billing Clerks have global read access but limited edit permissions
  • [ ] No users with conflicting roles (e.g., Technician + Admin)
  • [ ] MFA is enabled for all Admin users
  • [ ] Password policy compliance verified
  • [ ] Excessive permissions flagged for remediation

Automated Anomaly Detection

// Automated compliance checks run weekly
public class AccessComplianceService
{
    public async Task<AccessComplianceReport> GenerateWeeklyReportAsync()
    {
        var issues = new List<ComplianceIssue>();

        // Check 1: Inactive accounts (90+ days no login)
        var inactiveUsers = await _userService.GetInactiveUsersAsync(days: 90);
        issues.AddRange(inactiveUsers.Select(u => 
            new ComplianceIssue 
            { 
                Type = "InactiveAccount",
                Severity = "Medium",
                UserId = u.Id,
                Description = $"User {u.Email} inactive for {u.DaysInactive} days"
            }
        ));

        // Check 2: Shared accounts
        var sharedAccounts = await _userService.FindSharedAccountsAsync();
        issues.AddRange(sharedAccounts.Select(a => 
            new ComplianceIssue 
            { 
                Type = "SharedAccount",
                Severity = "High",
                UserId = a.Id,
                Description = $"Shared account detected: {a.Email}"
            }
        ));

        // Check 3: Service accounts without owners
        var orphanedServiceAccounts = await _userService
            .GetServiceAccountsWithoutOwnerAsync();
        issues.AddRange(orphanedServiceAccounts.Select(a => 
            new ComplianceIssue 
            { 
                Type = "OrphanedServiceAccount",
                Severity = "High",
                UserId = a.Id,
                Description = $"Service account {a.Email} has no documented owner"
            }
        ));

        // Check 4: Excessive permissions
        var excessivePermUsers = await _userService
            .GetUsersWithExcessivePermissionsAsync();
        issues.AddRange(excessivePermUsers.Select(u => 
            new ComplianceIssue 
            { 
                Type = "ExcessivePermissions",
                Severity = "High",
                UserId = u.Id,
                Description = $"User {u.Email} has {u.PermissionCount} permissions (threshold: 20)"
            }
        ));

        // Check 5: Admin users without MFA
        var adminNoMFA = await _userService.GetAdminUsersWithoutMFAAsync();
        issues.AddRange(adminNoMFA.Select(u => 
            new ComplianceIssue 
            { 
                Type = "AdminWithoutMFA",
                Severity = "Critical",
                UserId = u.Id,
                Description = $"Admin user {u.Email} does not have MFA enabled"
            }
        ));

        // Check 6: Store Manager accessing multiple stores
        var multiStoreManagers = await _userService
            .GetStoreManagersWithMultipleStoresAsync();
        issues.AddRange(multiStoreManagers.Select(u => 
            new ComplianceIssue 
            { 
                Type = "StoreManagerMultipleStores",
                Severity = "Medium",
                UserId = u.Id,
                Description = $"Store Manager {u.Email} assigned to {u.StoreCount} stores"
            }
        ));

        return new AccessComplianceReport 
        { 
            GeneratedDate = DateTime.UtcNow,
            TotalIssues = issues.Count,
            Issues = issues
        };
    }
}

Remediation Workflow

Compliance Issue Detected
Auto-Notification to Line Manager/Admin
Manager Reviews Issue
Decision Point:
  ├─ APPROVE (Keep Permission) → Document justification
  ├─ REVOKE → Remove permission, log in audit trail
  └─ ESCALATE → Send to Security Team for review
Remediation Completed
Audit Trail Updated
Quarterly Report Generated

Best Practices & Security Guidelines

1. Principle of Least Privilege (PoLP)

  • Assign only permissions required for job function
  • Minimize Admin roles (target: <2% of users)
  • Store Managers access only own store
  • Technicians access only own store
  • Quarterly reviews to remove unnecessary permissions

2. Role Assignment Best Practices

DO: - ✅ Assign roles based on job function - ✅ Use role inheritance (one role per user, default) - ✅ Document role change requests with business justification - ✅ Implement segregation of duties (Technician ≠ Billing Clerk) - ✅ Store assignment at hire/onboarding - ✅ Regular access reviews with managers

DON'T: - ❌ Create custom ad-hoc roles (use predefined roles) - ❌ Assign multiple conflicting roles (Technician + Admin) - ❌ Create shared accounts - ❌ Use default/generic passwords - ❌ Grant permissions without business justification - ❌ Assign Admin role to non-IT personnel - ❌ Skip MFA for admin operations

3. Sensitive Operation Handling

Operations Requiring MFA: - User creation / deletion - Role assignment / revocation - Payment processing (refunds, transfers) - Data exports (customer, financial) - System configuration changes - Security policy modifications - Integration setup

Operations NOT Requiring MFA: - Viewing data (read-only) - Creating service requests - Status updates - Routine invoice generation - Customer communication

4. Store-Level Data Isolation

  • Implement row-level security (RLS) in SQL Server
  • Filter all queries by user's authorized stores
  • Validate store access at API controller level
  • Log all cross-store access (Admin access)
  • Prevent Store Managers from accessing other stores
  • Audit all data access by location

5. Audit Logging Requirements

Event Retention Logs
User created, modified, deleted 10 years admin_audit
Role assigned, revoked 10 years admin_audit
Permission changed 10 years admin_audit
Sensitive data accessed 10 years data_audit
Payment processed 10 years financial_audit
Invoice finalized 10 years financial_audit
Work order approved 2 years operation_audit
Exception escalated 2 years operation_audit
Failed login attempts 2 years security_audit
MFA failures 2 years security_audit

6. Password & Authentication Policy

Policy Requirement
Minimum Length 12 characters
Complexity UPPERCASE + lowercase + number + special char
Expiration 90 days (configurable)
Reuse History Cannot reuse last 5 passwords
Account Lockout 5 failed attempts → 30-minute lockout
Session Timeout 30 minutes idle → re-authenticate
MFA Options Authenticator app, security key, SMS (MFA required)

7. Remote Access & VPN

  • VPN required for remote access
  • MFA mandatory for VPN + application
  • Geofence access (optional: block unusual locations)
  • Session logging and monitoring
  • Automatic logout after inactivity

8. Third-Party & Contractor Access

  • Limited roles (e.g., readonly Technician)
  • Time-limited access (contract period)
  • Segregated from core staff
  • Enhanced monitoring and audit logging
  • Separate approval workflow (not standard onboarding)

9. Service Account Management

Requirement Detail
Naming Prefix with 'svc_' (e.g., svc_billing_integration)
Owner Must have documented owner (team/person)
Password Stored in Azure Key Vault, rotated 90 days
Permissions Minimal, specific to service needs
Monitoring Logged daily for unusual activity
Renewal Annual review and renewal required
Deactivation Automatic if not renewed or service discontinued

10. Incident Response

Suspected Unauthorized Access: 1. Immediately deactivate user account 2. Force logout from all sessions 3. Change credentials/API keys 4. Review access logs for 90 days prior 5. Audit all actions performed by account 6. Notify affected stakeholders 7. Document incident in audit trail 8. Post-incident review and lessons learned


Summary

Component Details
Total Roles 6 core roles + 2 optional (Regional Dispatcher, Area Manager)
Total Permissions 45+ granular permissions
MFA Required Admin, Store Manager, Billing Clerk, + sensitive operations
Audit Retention 10 years (admin), 2 years (operational)
Store Support 200+ stores with role-based scoping
Review Frequency Quarterly with automated anomaly detection
Authorization Method Azure AD + RBAC + granular permissions
Token Expiration 8 hours with refresh token support
Delegation Authority Admin role only
Data Isolation Store-level via SQL RLS and API filtering