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
- Core Application Roles
- Granular Permission Matrix
- Role Hierarchy & Delegation
- Multi-Store Capabilities
- Store Manager Role (Location-Level Operations)
- Implementation Details
- Access Review & Compliance Process
- Best Practices & Security Guidelines
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 |
Related Documents¶
- SECURITY.md - Detailed security architecture and policies
- DATA_MODELING.md - User, Role, Permission data models
- DEVELOPMENT_GUIDELINES.md - Implementation guidelines
- Solution Intent & Design - Project overview and business context