Skip to main content

RBAC Simulator Guide

The RBAC Simulator lets you test how your policies behave under different user roles and permissions. Define roles like Admin, User, and Guest, run policy evaluations with each role’s context injected, and compare results side-by-side to verify your access control logic works as expected.
The simulator runs entirely in the browser using your workspace’s role definitions stored in Supabase.

Overview

The RBAC Simulator is available inside any policy view in your workspace. It has three tabs:
TabPurpose
RolesCreate, edit, and manage role definitions
SimulateRun a policy evaluation with a selected role
CompareView simulation results across multiple roles side-by-side
Open the simulator from the policy editor — it appears below the code editor when you select a policy.

1. Defining Roles

A role represents a user type in your system. Each role has a name, a set of permissions, custom attributes, and metadata.

Role Structure

interface RoleDefinition {
  id: string;            // Unique identifier (e.g., "admin")
  name: string;          // Display name (e.g., "Administrator")
  permissions: string[]; // Permission strings (e.g., ["read", "write", "delete"])
  attributes: Record<string, any>; // Custom attributes injected into policy context
  metadata: {
    description: string;
    groups: string[];
    level: number;
    customFields: Record<string, any>;
  };
}

Creating a Role

  1. Open the RBAC Simulator and go to the Roles tab
  2. Click ”+ New Role”
  3. Fill in the role definition form
  4. Click Save

Built-in Example Roles

RolePermissionsLevelKey Attributes
Administratorread, write, delete, approve, manage_users10clearanceLevel: high, canAccessPII: true
Standard Userread, write5clearanceLevel: medium, canAccessPII: false
Guestread1clearanceLevel: low, canAccessPII: false

2. Running Simulations

Simulations execute your policy code with a specific role’s context injected, so you can see exactly what decision the policy makes for each user type.

How It Works

  1. Go to the Simulate tab
  2. Select one or more roles from the role list
  3. Configure an evaluation scenario (prompt, provider, model, parameters)
  4. Click Run Simulation
The simulator calls simulateWithRole() for each selected role. Your policy’s evaluate() function receives a context object containing the role:
{
  role: {
    id: "admin",
    name: "Administrator",
    permissions: ["read", "write", "delete", "approve", "manage_users"],
    attributes: { department: "IT", clearanceLevel: "high", canAccessPII: true },
    metadata: { ... }
  },
  user: {
    id: "sim-user-admin",
    attributes: { department: "IT", clearanceLevel: "high", canAccessPII: true }
  },
  environment: {
    timestamp: "2026-03-15T10:30:00Z",
    simulation: true
  }
}

3. Comparing Role Results

The Compare tab shows simulation results side-by-side and highlights where roles produce different outcomes.
DimensionFlagged When
DecisionOne role gets ALLOW, another gets DENY
ReasonThe policy returns different reason strings
Execution TimeDifference exceeds 100ms between roles

4. Importing and Exporting Roles

Role definitions can be shared across workspaces or teams using JSON import/export.

Exporting Roles

Click the Export button in the simulator header. All roles are exported as a JSON file.

Importing Roles

Click the Import button, select a JSON file, and the simulator validates each role’s structure before adding them.

5. Examples

Example 1: PII Access Control Policy

function evaluate(context, scenario) {
  const containsPII = scenario.parameters.containsPII || false;

  if (containsPII && !context.role.attributes.canAccessPII) {
    return {
      allowed: false,
      reason: `Role "${context.role.name}" does not have PII access`,
      metadata: { blockedField: 'canAccessPII' }
    };
  }

  return { allowed: true, reason: 'Access granted', metadata: {} };
}
RoleDecisionReason
AdministratorALLOWAccess granted
Standard UserDENYRole “Standard User” does not have PII access
GuestDENYRole “Guest” does not have PII access

Example 2: Permission-Based Write Guard

function evaluate(context, scenario) {
  if (!context.role.permissions.includes('write')) {
    return {
      allowed: false,
      reason: `Role "${context.role.name}" lacks write permission`,
      metadata: { requiredPermission: 'write' }
    };
  }
  return { allowed: true, reason: 'Write access confirmed', metadata: {} };
}

Example 3: Clearance-Level Gating

function evaluate(context, scenario) {
  const sensitiveModels = ['gpt-4', 'claude-3-opus'];
  const requiredLevel = 5;

  if (sensitiveModels.includes(scenario.model) && context.role.metadata.level < requiredLevel) {
    return {
      allowed: false,
      reason: `Level ${context.role.metadata.level} insufficient for ${scenario.model} (requires ${requiredLevel})`,
      metadata: { requiredLevel, actualLevel: context.role.metadata.level }
    };
  }
  return { allowed: true, reason: 'Model access granted', metadata: {} };
}

6. Tips and Best Practices

  • Start with the built-in roles. Admin, User, and Guest cover the most common access patterns.
  • Use attributes for business logic. Permissions control actions; attributes let policies make context-aware decisions.
  • Test edge cases. Create a role with zero permissions to verify graceful handling.
  • Export roles to version control. Keep role definitions alongside policies for CI/CD testing.
  • Check the simulation: true flag. Use it to skip side effects during test runs.
  • Compare after every policy change. Run a quick simulation across all roles to catch unintended access changes.