rbac-ui

Role-Driven UI & EPS Framework

A lightweight, tree-based RBAC framework for predictable, explicit, and
flexible access control in frontend applications.

#rbac-ui

Resource-Based Access Control for modern frontend apps.

A lightweight, tree-based, zero-dependency RBAC framework for frontend applications: predictable, explicit, and flexible access control.

  • Fast tree-based permission evaluation.
  • Intuitive permission grammar like ui:dashboard:checklist.
  • Nested hierarchical permissions.
  • Negation rules like !ui:settings.
  • Backend-agnostic design.
  • Framework-agnostic core with optional framework bindings.

#The Problem We're Solving

Frontend applications need to control what users can see and do, but traditional approaches have limitations:

  • Role-based checks scattered throughout code become hard to maintain.
  • String comparisons and role lists don't scale as features grow.
  • No clear way to represent hierarchical permissions (e.g., 'dashboard' but not 'dashboard:checklist').
  • Difficult to let non-developers manage access without code changes.
  • No standard way to express 'deny this specific thing' while allowing the parent.

This framework solves UI role access by providing a tree-based permission system that's fast, explicit, and manageable.

#Why Use This Approach

  • Tree-based evaluation means O(depth) complexity—fast even with thousands of permissions.
  • Explicit permission tokens make it clear what each UI element requires.
  • Hierarchical structure matches how products are organized (pages → sections → controls).
  • Negation rules let you grant broad access and surgically remove specific features.
  • Simple string-based tokens work with any backend—just pass an array of strings.
  • Admin dashboards can manage permissions without developer intervention.

#Core Principles

  • Treat the server as the source of truth for authorization and the client as a guide for visibility.
  • Prefer capability permissions over role names in every interface decision.
  • Use a single readable token language for both UI visibility and API enforcement.
  • Adopt a compact signed Effective Permission Set (EPS) per user and context.
  • Keep the vocabulary human-readable, documented, and guessable.
  • Favor small primitives composed well over complex policy tools.

#Framework Use Cases

#Product Managers Managing Access via Dashboard

This is one of the most valuable real-world use cases: PMs/Ops/Support manage access in a dashboard while devs implement the permission model once and reuse it forever.

Why this is powerful:

  • PMs/Ops/Support can grant access instantly, revoke features without deployments, and run experiments (feature flags via RBAC).
  • Developers don't get interrupted for every access change and only implement the system once.

Your RBAC grammar maps directly to checkboxes and toggles in an admin UI:

Example tokens

ui:dashboard
ui:billing
!ui:billing:refund
  • ui:dashboard grants access to all dashboard features (reports, analytics, widgets, etc.).
  • ui:billing grants access to all billing features.
  • !ui:billing:refund denies the refund feature specifically, while keeping other billing features accessible.

This evolves naturally into RBAC as a feature management system: feature gating, audience control, gradual rollouts, permissions, and admin overrides.

#Feature Flags & Experimentation

RBAC tokens can double as feature flags, enabling product teams to control feature visibility and access without code deployments.

  • Use permission tokens to gate new features during development and testing.
  • Gradually roll out features to specific user segments using permission assignments.
  • Run A/B tests by granting different permission sets to different user groups.
  • Quickly disable features by revoking permissions without code changes.

#Framework Features

#Smart Permission Grammar

  • ui:dashboard grants access.
  • ui:dashboard:reports grants nested access.
  • !ui:dashboard:checklist denies a child path.
  • * can represent wildcard top-level access (if you enable it).

#Tree-Based Permission Engine

  • Permissions compile into a static permission tree.
  • No repeated looping over role strings.
  • Ultra-fast access checks with complexity proportional to depth (O(depth)).

#Deny Semantics

  • Treat deny as removal of a node and its descendants unless a more specific allow exists.
  • Reserve deep wildcards and broad denies for administrative bundles and audits.

#Framework Usage

#Permission Language

Use permission tokens as the contract between product intent (what a user can see and do) and implementation (what the UI shows).

Token grammar

namespace:resource[:segment...][:action]

ui:dashboard
ui:billing:refunds
ui:invoice:toolbar:export
ui:settings:profile:edit
  • Use the ui namespace for UI visibility and feature access.
  • Use hierarchy with intent; keep depth reasonable for clarity.
  • Granting a parent permission (e.g., ui:dashboard) gives access to all child paths (e.g., ui:dashboard:reports, ui:dashboard:analytics) until a specific child is denied.
  • Use negation for surgical pruning: deny specific children while keeping parent access (e.g., ui:dashboard with !ui:dashboard:checklist grants all dashboard features except the checklist).
  • Use wildcards carefully: single-level *.

#Naming Guidance

  • Prefer intent-based names such as ui:invoice:toolbar:export over implementation labels.
  • Keep segments lowercase and use kebab-case where needed.
  • Limit token depth to a practical range that matches the product shape.

#Admin / PM Dashboard Workflow

At runtime the system can stay simple: permissions are just strings stored in a DB, managed by a dashboard, and issued to clients as a signed EPS.

How it looks in storage

ui:dashboard
ui:billing
!ui:billing:refund
ui:invoice:export
  • Represent tokens as a catalog-driven tree (so the UI is generated, not hardcoded).
  • Persist changes as token lists (or diffs) in the database.
  • Mint a fresh EPS at login (and on tenant switch) and ship it to the client.
  • Always validate permissions on the server; UI gates are for visibility, not security.

#Developer Experience (Enums / Typed Tokens)

From a developer-experience standpoint, raw strings are risky: typos become silent access bugs. Enums/typed tokens give autocomplete, refactor safety, and eliminate a whole class of mistakes.

Enums instead of raw strings

hasAccess("ui:dashbord"); // typo -> silent bug

export enum UIResources {
  Dashboard = "ui:dashboard",
  DashboardChecklist = "ui:dashboard:checklist",
  Settings = "ui:settings",
}

hasAccess(UIResources.DashboardChecklist);
  • Typed tokens are best for application code and internal tools.
  • Runtime payloads (DB/EPS) can remain strings; types are a build-time safety layer.

#Support BOTH (Runtime Strings + Typed Tokens)

The same RBAC engine can support both admin-managed strings and developer-friendly types, because at runtime everything is still a string[].

  • For admins/PMs: store and edit plain strings in a DB; ship strings in EPS.
  • For developers: use generated enums/constants for autocomplete and safe refactors.
  • Both feed the same matcher because the runtime engine operates on tokens (strings).

#Catalog, Linting & Conventions

  • Maintain a permission catalog in both markdown and JSON for teams and tools.
  • Describe each token with one sentence stating what it unlocks and where.
  • Generate diffs for role changes and review them like code changes.
  • Enforce naming lint rules in CI to prevent mistakes.
  • Disallow deep wildcard by default; allow only when explicitly configured.
  • Resolve aliases to canonical tokens at build time for consistency.
  • Fail builds on unknown namespaces, malformed tokens, and invalid catalog entries.

#Strategic Takeaway

This is not just a frontend RBAC library. It becomes an engine layer for access control, feature flags, permission management, no-code access configuration, and product experimentation.

  • Tree-based matching, wildcards, and negation make the language expressive.
  • Framework-agnostic design means it works with any frontend stack.
  • Admin dashboard management makes access self-serve without deployments.
  • Type-safe tokens make it safe and scalable for large teams.
  • Simple string-based API means easy integration with any backend system.