# Fire Shield RBAC — Complete Documentation
> Version 3.1.1
> Repository: https://github.com/khapu2906/fire-shield
> Compact version: https://fire-shield.dev/llms-small.txt
> Index: https://fire-shield.dev/llms.txt
========================================================================
# SECTION: Guide
========================================================================
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/guide/what-is-fire-shield
────────────────────────────────────────────────────────────────────────
# What is Fire Shield?
Fire Shield is a modern, type-safe RBAC (Role-Based Access Control) library for JavaScript and TypeScript applications.
## Overview
Fire Shield provides a flexible and performant way to manage permissions and roles in your applications. Whether you're building a web app, API, or full-stack application, Fire Shield has you covered with framework-specific adapters for Vue, React, Next.js, Express, and more.
## Key Features
### Type-Safe
Written in TypeScript with comprehensive type definitions. Catch permission errors at compile-time, not runtime.
```typescript
// Full type inference and safety
const rbac = new RBAC()
rbac.createRole('admin', ['posts:*'])
rbac.hasPermission(user, 'posts:write') // Type-checked
```
### Zero Dependencies
The core library has zero dependencies, keeping your bundle size small. Framework adapters only depend on their respective frameworks.
### Framework-Agnostic
Use Fire Shield anywhere JavaScript runs:
- **Frontend**: Vue, React, Next.js, Nuxt, Angular, Svelte
- **Backend**: Express, Fastify, Hono
- **Runtime**: Node.js, Deno, Bun, Edge Runtime
### Blazing Fast
Optimized with:
- Bit-level permission checking
- Efficient role hierarchy resolution
- Minimal memory footprint
- Tree-shakeable code
### Flexible Permission Patterns
Support for wildcard permissions:
```typescript
rbac.createRole('admin', ['posts:*', 'users:*'])
rbac.hasPermission(admin, 'posts:write') // ✅
rbac.hasPermission(admin, 'posts:delete') // ✅
rbac.hasPermission(admin, 'users:create') // ✅
```
### Role Hierarchy
Define role inheritance chains:
```typescript
rbac.setRoleHierarchy({
admin: ['editor', 'viewer'],
editor: ['viewer']
})
// Admin automatically inherits editor and viewer permissions
```
### Audit Logging
Built-in audit logging for compliance:
```typescript
const rbac = new RBAC({
auditLogger: new BufferedAuditLogger(async (logs) => {
await saveToDatabase(logs)
})
})
```
## Why Fire Shield?
### Compared to Other Libraries
| Feature | Fire Shield | accesscontrol | casl | casbin |
|---------|------------|---------------|------|--------|
| TypeScript | ✅ Full | ⚠️ Partial | ✅ Full | ⚠️ Partial |
| Zero Dependencies | ✅ | ❌ | ❌ | ❌ |
| Bundle Size | 🎯 3.2KB | 5.8KB | 12KB | 45KB |
| Framework Adapters | ✅ 9+ | ❌ | ⚠️ Limited | ⚠️ Limited |
| Role Hierarchy | ✅ | ❌ | ❌ | ✅ |
| Performance | ⚡ Fastest | Fast | Medium | Slow |
### Use Cases
Fire Shield is perfect for:
- 🏢 **Enterprise Applications** - Multi-tenant SaaS with complex permission requirements
- 📱 **Web Applications** - User dashboards with role-based features
- 🔐 **APIs** - Protecting endpoints with permission-based middleware
- 🎮 **Content Management** - Managing content creation, editing, and publishing workflows
- 👥 **User Management** - Admin panels with granular access control
## Architecture
Fire Shield is built with a modular architecture:
```
@fire-shield/core # Core RBAC engine
├── @fire-shield/vue # Vue.js adapter
├── @fire-shield/react # React adapter
├── @fire-shield/next # Next.js adapter
└── ... # Other framework adapters
```
Each adapter is:
- **Optional** - Only install what you need
- **Tree-shakeable** - Only import what you use
- **Type-safe** - Full TypeScript support
- **Well-tested** - 100% test coverage
## Getting Started
Ready to add Fire Shield to your project?
- [Installation Guide →](/guide/installation)
- [Quick Start →](/guide/getting-started)
- [Framework Integrations →](/frameworks/vue)
## Community & Support
- 📖 [Documentation](/)
- 🐛 [Issue Tracker](https://github.com/khapu2906/fire-shield/issues)
- 💬 [Discussions](https://github.com/khapu2906/fire-shield/discussions)
- 📦 [NPM](https://www.npmjs.com/package/@fire-shield/core)
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/guide/getting-started
────────────────────────────────────────────────────────────────────────
# Getting Started
Get up and running with Fire Shield in minutes.
## Installation
Install the core package:
::: code-group
```bash [npm]
npm install @fire-shield/core
```
```bash [yarn]
yarn add @fire-shield/core
```
```bash [pnpm]
pnpm add @fire-shield/core
```
:::
## Your First RBAC Setup
### 1. Create an RBAC Instance
```typescript
import { RBAC } from '@fire-shield/core'
const rbac = new RBAC()
```
### 2. Define Roles and Permissions
```typescript
// Create roles with permissions
rbac.createRole('admin', [
'posts:*', // All post operations
'users:*', // All user operations
'settings:*' // All settings operations
])
rbac.createRole('editor', [
'posts:read',
'posts:write',
'posts:publish'
])
rbac.createRole('viewer', [
'posts:read'
])
```
### 3. Check Permissions
```typescript
const user = {
id: 'user-123',
roles: ['editor']
}
// Check if user has permission
if (rbac.hasPermission(user, 'posts:write')) {
// Allow user to write posts
console.log('✅ User can write posts')
} else {
console.log('❌ Access denied')
}
// Check multiple permissions
const canEdit = rbac.hasPermission(user, 'posts:write') // ✅ true
const canDelete = rbac.hasPermission(user, 'posts:delete') // ❌ false
const canRead = rbac.hasPermission(user, 'posts:read') // ✅ true
```
## Role Hierarchy
Set up role inheritance for cleaner permission management:
```typescript
// Admin inherits all editor and viewer permissions
rbac.setRoleHierarchy({
admin: ['editor', 'viewer'],
editor: ['viewer']
})
// Now admins automatically have editor and viewer permissions
const admin = { id: 'admin-1', roles: ['admin'] }
rbac.hasPermission(admin, 'posts:read') // ✅ true (inherited from viewer)
rbac.hasPermission(admin, 'posts:write') // ✅ true (inherited from editor)
rbac.hasPermission(admin, 'users:delete') // ✅ true (admin's own permission)
```
## Wildcard Permissions
Use wildcards for flexible permission patterns:
```typescript
rbac.createRole('admin', [
'posts:*', // All post operations
'users:*', // All user operations
'admin:*' // All admin operations
])
const admin = { id: 'admin-1', roles: ['admin'] }
// All these checks return true
rbac.hasPermission(admin, 'posts:read')
rbac.hasPermission(admin, 'posts:write')
rbac.hasPermission(admin, 'posts:delete')
rbac.hasPermission(admin, 'users:create')
rbac.hasPermission(admin, 'admin:settings:write')
```
## Framework Integration
Fire Shield provides adapters for popular frameworks. Choose your framework to continue:
- [Vue.js](/frameworks/vue) - Directives, composables, and router guards
- [React](/frameworks/react) - Hooks and components
- [Next.js](/frameworks/next) - Server and client components
- [Nuxt](/frameworks/nuxt) - Auto-imports and middleware
- [Angular](/frameworks/angular) - Services and guards
- [Svelte](/frameworks/svelte) - Stores and actions
- [Express](/frameworks/express) - Middleware
- [Fastify](/frameworks/fastify) - Plugins and hooks
- [Hono](/frameworks/hono) - Middleware
## Next Steps
- Learn about [Permissions](/guide/permissions)
- Understand [Roles](/guide/roles)
- Explore [Role Hierarchy](/guide/role-hierarchy)
- Master [Wildcards](/guide/wildcards)
- Set up [Audit Logging](/guide/audit-logging)
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/guide/installation
────────────────────────────────────────────────────────────────────────
# Installation
Install Fire Shield in your project with your preferred package manager.
## Core Package
All Fire Shield integrations require the core package:
::: code-group
```bash [npm]
npm install @fire-shield/core
```
```bash [yarn]
yarn add @fire-shield/core
```
```bash [pnpm]
pnpm add @fire-shield/core
```
:::
## Framework Adapters
Install the adapter for your framework:
### Vue.js
```bash
npm install @fire-shield/vue @fire-shield/core
```
### React
```bash
npm install @fire-shield/react @fire-shield/core
```
### Next.js
```bash
npm install @fire-shield/next @fire-shield/core
```
### Nuxt
```bash
npm install @fire-shield/nuxt @fire-shield/core
```
### Angular
```bash
npm install @fire-shield/angular @fire-shield/core
```
### Svelte
```bash
npm install @fire-shield/svelte @fire-shield/core
```
### Express
```bash
npm install @fire-shield/express @fire-shield/core
```
### Fastify
```bash
npm install @fire-shield/fastify @fire-shield/core
```
### Hono
```bash
npm install @fire-shield/hono @fire-shield/core
```
## Requirements
- Node.js 18.0.0 or higher
- TypeScript 5.0 or higher (for TypeScript projects)
## CDN Usage
For quick prototyping or demos, you can use Fire Shield via CDN:
```html
```
::: warning
CDN usage is not recommended for production applications. Use a package manager instead.
:::
## Next Steps
- [Getting Started Guide](/guide/getting-started)
- [Framework Integration](/frameworks/vue)
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/guide/permissions
────────────────────────────────────────────────────────────────────────
# Permissions
Permissions are the foundation of Fire Shield's access control system.
## What are Permissions?
A permission is a string that represents an action a user can perform on a resource. Permissions typically follow a `resource:action` pattern:
```typescript
'posts:read' // Read posts
'posts:write' // Write/create posts
'posts:delete' // Delete posts
'users:manage' // Manage users
```
## Permission Format
### Basic Format
```
resource:action
```
Examples:
- `posts:read`
- `comments:write`
- `settings:update`
### Nested Resources
Use colons to create hierarchical permissions:
```
admin:users:read
admin:users:write
admin:users:delete
admin:settings:write
```
### Wildcard Permissions
Use `*` to grant all actions on a resource:
```typescript
'posts:*' // All post actions
'admin:*' // All admin actions
'*:read' // Read all resources
'*' // All permissions (superuser)
```
[Learn more about wildcards →](/guide/wildcards)
## Checking Permissions
### Basic Check
```typescript
import { RBAC } from '@fire-shield/core'
const rbac = new RBAC()
rbac.createRole('editor', ['posts:read', 'posts:write'])
const user = { id: '1', roles: ['editor'] }
// Check single permission
if (rbac.hasPermission(user, 'posts:write')) {
console.log('User can write posts')
}
// Returns boolean
const canDelete = rbac.hasPermission(user, 'posts:delete') // false
const canRead = rbac.hasPermission(user, 'posts:read') // true
```
### Multiple Permissions
Check if user has all required permissions:
```typescript
const permissions = ['posts:read', 'posts:write', 'posts:publish']
const hasAll = permissions.every(permission =>
rbac.hasPermission(user, permission)
)
```
Check if user has any of the permissions:
```typescript
const hasAny = permissions.some(permission =>
rbac.hasPermission(user, permission)
)
```
## Permission Naming Conventions
### Recommended Patterns
**CRUD Operations:**
```typescript
'posts:create'
'posts:read'
'posts:update'
'posts:delete'
```
**Domain-Specific Actions:**
```typescript
'posts:publish'
'posts:archive'
'posts:restore'
'comments:approve'
'comments:moderate'
```
**Administrative Actions:**
```typescript
'users:manage'
'roles:assign'
'settings:configure'
'system:admin'
```
### Best Practices
1. **Be Specific**
```typescript
// ✅ Good
'posts:publish'
'posts:archive'
// ❌ Avoid
'posts:action1'
'posts:action2'
```
2. **Use Consistent Naming**
```typescript
// ✅ Good - consistent pattern
'posts:read'
'posts:write'
'posts:delete'
// ❌ Avoid - inconsistent
'posts:read'
'posts:create'
'posts:remove'
```
3. **Keep Hierarchy Logical**
```typescript
// ✅ Good - clear hierarchy
'admin:users:read'
'admin:users:write'
'admin:settings:read'
// ❌ Avoid - confusing hierarchy
'users:admin:read'
'settings:read:admin'
```
## Permission Matching
Fire Shield uses exact matching for permissions:
```typescript
rbac.createRole('editor', ['posts:write'])
const user = { id: '1', roles: ['editor'] }
// Exact match - works
rbac.hasPermission(user, 'posts:write') // ✅ true
// Different action - doesn't match
rbac.hasPermission(user, 'posts:read') // ❌ false
// Different resource - doesn't match
rbac.hasPermission(user, 'comments:write') // ❌ false
```
### Wildcard Matching
Wildcards provide flexible matching:
```typescript
rbac.createRole('admin', ['posts:*'])
const admin = { id: '1', roles: ['admin'] }
// All of these match
rbac.hasPermission(admin, 'posts:read') // ✅ true
rbac.hasPermission(admin, 'posts:write') // ✅ true
rbac.hasPermission(admin, 'posts:delete') // ✅ true
rbac.hasPermission(admin, 'posts:anything') // ✅ true
```
## Dynamic Permissions
Permissions can be granted dynamically at runtime:
```typescript
const rbac = new RBAC()
// Start with basic role
rbac.createRole('user', ['posts:read'])
// Add more permissions later
rbac.grant('user', ['comments:read', 'comments:write'])
// Remove permissions
rbac.revoke('user', ['comments:write'])
```
## Permission Objects
For advanced use cases, you can use permission objects:
```typescript
interface Permission {
resource: string
action: string
conditions?: {
ownerId?: string
status?: string
// Custom conditions
}
}
```
## Common Patterns
### Content Management
```typescript
rbac.createRole('author', [
'posts:create',
'posts:read',
'posts:update:own', // Can only update own posts
])
rbac.createRole('editor', [
'posts:create',
'posts:read',
'posts:update',
'posts:publish',
])
rbac.createRole('admin', [
'posts:*',
'users:*',
'settings:*',
])
```
### Multi-tenant Applications
```typescript
rbac.createRole('tenant-admin', [
'tenant:settings:write',
'tenant:users:manage',
'tenant:billing:view',
])
rbac.createRole('tenant-member', [
'tenant:data:read',
'tenant:data:write',
])
```
### API Access
```typescript
rbac.createRole('api-consumer', [
'api:read',
'api:ratelimit:standard',
])
rbac.createRole('api-premium', [
'api:read',
'api:write',
'api:ratelimit:premium',
])
```
## Next Steps
- Learn about [Roles](/guide/roles)
- Master [Wildcards](/guide/wildcards)
- Explore [Role Hierarchy](/guide/role-hierarchy)
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/guide/roles
────────────────────────────────────────────────────────────────────────
# Roles
Roles group permissions together and can be assigned to users.
## What are Roles?
A role is a collection of permissions that can be assigned to users. Instead of granting permissions individually, you assign roles to users.
```typescript
// Without roles - tedious
user.permissions = ['posts:read', 'posts:write', 'comments:read', 'comments:write']
// With roles - clean
user.roles = ['editor']
rbac.createRole('editor', ['posts:read', 'posts:write', 'comments:read', 'comments:write'])
```
## Creating Roles
### Basic Role Creation
```typescript
import { RBAC } from '@fire-shield/core'
const rbac = new RBAC()
// Create role with permissions
rbac.createRole('viewer', [
'posts:read',
'comments:read'
])
rbac.createRole('editor', [
'posts:read',
'posts:write',
'posts:publish',
'comments:read',
'comments:write'
])
rbac.createRole('admin', [
'posts:*',
'comments:*',
'users:*',
'settings:*'
])
```
### Role with Wildcards
```typescript
// All post permissions
rbac.createRole('post-admin', ['posts:*'])
// All permissions (superuser)
rbac.createRole('superuser', ['*'])
```
## Assigning Roles to Users
```typescript
const user = {
id: 'user-123',
roles: ['editor']
}
// Check permissions
rbac.hasPermission(user, 'posts:write') // ✅ true
rbac.hasPermission(user, 'users:delete') // ❌ false
```
### Multiple Roles
Users can have multiple roles:
```typescript
const user = {
id: 'user-123',
roles: ['editor', 'moderator']
}
// Has permissions from both roles
rbac.createRole('editor', ['posts:write'])
rbac.createRole('moderator', ['comments:moderate'])
rbac.hasPermission(user, 'posts:write') // ✅ true
rbac.hasPermission(user, 'comments:moderate') // ✅ true
```
## Modifying Roles
### Adding Permissions
```typescript
// Grant additional permissions to a role
rbac.grant('editor', ['posts:delete'])
// Now editors can delete posts
rbac.hasPermission({ roles: ['editor'] }, 'posts:delete') // ✅ true
```
### Removing Permissions
```typescript
// Revoke permissions from a role
rbac.revoke('editor', ['posts:delete'])
// Editors can no longer delete posts
rbac.hasPermission({ roles: ['editor'] }, 'posts:delete') // ❌ false
```
### Deleting Roles
```typescript
// Remove a role completely
rbac.deleteRole('editor')
```
## Role Hierarchy
Create inheritance chains between roles:
```typescript
rbac.setRoleHierarchy({
admin: ['editor', 'moderator'],
editor: ['viewer'],
moderator: ['viewer']
})
// Admin inherits all permissions from editor, moderator, and viewer
const admin = { id: '1', roles: ['admin'] }
rbac.hasPermission(admin, 'posts:read') // ✅ true (from viewer)
rbac.hasPermission(admin, 'posts:write') // ✅ true (from editor)
```
[Learn more about Role Hierarchy →](/guide/role-hierarchy)
## Common Role Patterns
### Content Management System
```typescript
// Viewer - can only read
rbac.createRole('viewer', [
'posts:read',
'comments:read'
])
// Author - can create and edit own content
rbac.createRole('author', [
'posts:read',
'posts:create',
'posts:update:own',
'comments:read',
'comments:create'
])
// Editor - can edit all content
rbac.createRole('editor', [
'posts:read',
'posts:create',
'posts:update',
'posts:publish',
'comments:read',
'comments:write',
'comments:moderate'
])
// Admin - full control
rbac.createRole('admin', [
'posts:*',
'comments:*',
'users:*',
'settings:*'
])
```
### SaaS Application
```typescript
// Free tier
rbac.createRole('free', [
'projects:read',
'projects:create:limited',
'api:read:ratelimited'
])
// Pro tier
rbac.createRole('pro', [
'projects:*',
'teams:read',
'api:read',
'api:write:limited'
])
// Enterprise tier
rbac.createRole('enterprise', [
'projects:*',
'teams:*',
'api:*',
'billing:manage',
'support:priority'
])
```
### Organization Structure
```typescript
// Team member
rbac.createRole('member', [
'team:read',
'projects:read',
'tasks:read',
'tasks:write:assigned'
])
// Team lead
rbac.createRole('lead', [
'team:read',
'projects:*',
'tasks:*',
'reports:read'
])
// Department manager
rbac.createRole('manager', [
'department:read',
'teams:*',
'projects:*',
'budgets:read',
'reports:*'
])
```
## Dynamic Role Assignment
Roles can be assigned/removed at runtime:
```typescript
const user = {
id: 'user-123',
roles: ['viewer']
}
// Promote user
function promoteUser(user, newRole) {
if (!user.roles.includes(newRole)) {
user.roles.push(newRole)
}
}
promoteUser(user, 'editor')
// user.roles = ['viewer', 'editor']
// Demote user
function demoteUser(user, role) {
user.roles = user.roles.filter(r => r !== role)
}
demoteUser(user, 'viewer')
// user.roles = ['editor']
```
## Role Checking
Check if user has a specific role:
```typescript
const user = { id: '1', roles: ['editor', 'moderator'] }
// Check single role
function hasRole(user, role) {
return user.roles.includes(role)
}
hasRole(user, 'editor') // ✅ true
hasRole(user, 'admin') // ❌ false
// Check any of multiple roles
function hasAnyRole(user, roles) {
return roles.some(role => user.roles.includes(role))
}
hasAnyRole(user, ['admin', 'editor']) // ✅ true
// Check all roles
function hasAllRoles(user, roles) {
return roles.every(role => user.roles.includes(role))
}
hasAllRoles(user, ['editor', 'moderator']) // ✅ true
hasAllRoles(user, ['editor', 'admin']) // ❌ false
```
## Best Practices
### 1. Use Descriptive Names
```typescript
// ✅ Good - clear purpose
rbac.createRole('content-editor', [...])
rbac.createRole('billing-admin', [...])
// ❌ Avoid - unclear
rbac.createRole('role1', [...])
rbac.createRole('special-user', [...])
```
### 2. Keep Roles Focused
```typescript
// ✅ Good - focused roles
rbac.createRole('post-editor', ['posts:*'])
rbac.createRole('user-manager', ['users:*'])
// ❌ Avoid - too broad
rbac.createRole('everything', ['*'])
```
### 3. Use Role Hierarchy
```typescript
// ✅ Good - clear hierarchy
rbac.createRole('viewer', ['read:*'])
rbac.createRole('editor', ['read:*', 'write:*'])
rbac.createRole('admin', ['*'])
rbac.setRoleHierarchy({
admin: ['editor'],
editor: ['viewer']
})
// ❌ Avoid - duplicate permissions
rbac.createRole('viewer', ['read:*'])
rbac.createRole('editor', ['read:*', 'write:*']) // Duplicates viewer permissions
```
### 4. Plan for Growth
```typescript
// ✅ Good - extensible
rbac.createRole('basic-user', ['app:read'])
rbac.createRole('power-user', ['app:read', 'app:advanced'])
rbac.createRole('admin', ['app:*'])
// Easy to add new tiers later
rbac.createRole('premium-user', ['app:read', 'app:advanced', 'app:premium'])
```
## TypeScript Support
Full type safety for roles:
```typescript
// Define role types
type Role = 'admin' | 'editor' | 'viewer'
interface User {
id: string
roles: Role[]
}
const user: User = {
id: '123',
roles: ['editor'] // ✅ Type-safe
// roles: ['invalid'] // ❌ Type error
}
```
## Next Steps
- Learn about [Role Hierarchy](/guide/role-hierarchy)
- Master [Permissions](/guide/permissions)
- Explore [Wildcards](/guide/wildcards)
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/guide/role-hierarchy
────────────────────────────────────────────────────────────────────────
# Role Hierarchy
Understanding and implementing role hierarchies in Fire Shield.
## What is Role Hierarchy?
Role hierarchy is a level-based system where higher-level roles can perform actions on behalf of lower-level roles. This creates a natural organizational structure that mirrors real-world authority relationships.
## Key Concepts
**Level-Based System:**
- Each role is assigned a numeric level
- Higher numbers = more privileged
- Level determines if a role can "act as" another role
**Use Cases:**
- Organizational hierarchies (CEO > Manager > Employee)
- Permission delegation (Admin can act as any lower role)
- Resource access control (only higher roles can manage lower-role resources)
- Approval workflows (requires someone of higher level)
## Setting Up Hierarchy
### Basic Setup
```typescript
import { RBAC } from '@fire-shield/core';
const rbac = new RBAC();
// Create roles
rbac.createRole('employee', ['document:read', 'document:create']);
rbac.createRole('manager', ['document:*', 'team:view']);
rbac.createRole('admin', ['*']);
// Set hierarchy levels
const hierarchy = rbac.getRoleHierarchy();
hierarchy.setRoleLevel('employee', 1);
hierarchy.setRoleLevel('manager', 5);
hierarchy.setRoleLevel('admin', 10);
```
### With RBAC Builder
```typescript
import { RBACBuilder } from '@fire-shield/core';
const rbac = new RBACBuilder()
.addRole('employee', ['document:read'], { level: 1 })
.addRole('manager', ['document:*'], { level: 5 })
.addRole('admin', ['*'], { level: 10 })
.build();
```
## Checking Hierarchy
### canActAs
Check if a role can act as another role:
```typescript
// Can admin act as manager?
rbac.canActAsRole('admin', 'manager'); // true (10 >= 5)
// Can manager act as admin?
rbac.canActAsRole('manager', 'admin'); // false (5 < 10)
// Can manager act as employee?
rbac.canActAsRole('manager', 'employee'); // true (5 >= 1)
```
### Direct Hierarchy Access
```typescript
const hierarchy = rbac.getRoleHierarchy();
// Check if role1 can act as role2
hierarchy.canActAs('admin', 'manager'); // true
// Check if role1 has higher level than role2
hierarchy.hasHigherLevel('admin', 'employee'); // true
// Get role level
const adminLevel = hierarchy.getRoleLevel('admin'); // 10
```
## Real-World Examples
### Corporate Hierarchy
```typescript
const rbac = new RBACBuilder()
// C-Level
.addRole('ceo', ['*'], {
level: 100,
description: 'Chief Executive Officer'
})
.addRole('cto', ['technology:*', 'team:*'], {
level: 90,
description: 'Chief Technology Officer'
})
// Management
.addRole('director', ['department:*', 'team:manage'], {
level: 50,
description: 'Department Director'
})
.addRole('manager', ['team:*', 'project:*'], {
level: 30,
description: 'Team Manager'
})
// Individual Contributors
.addRole('senior-engineer', ['project:*', 'code:*'], {
level: 20,
description: 'Senior Engineer'
})
.addRole('engineer', ['code:read', 'code:write'], {
level: 10,
description: 'Engineer'
})
.addRole('intern', ['code:read'], {
level: 1,
description: 'Intern'
})
.build();
// CEO can act as anyone
rbac.canActAsRole('ceo', 'intern'); // true
// Manager can act as engineers
rbac.canActAsRole('manager', 'engineer'); // true
// Engineer cannot act as manager
rbac.canActAsRole('engineer', 'manager'); // false
```
### Permission Delegation
```typescript
function canDelegatePermission(
delegator: RBACUser,
delegatee: RBACUser,
permission: string
): boolean {
// Check if delegator has the permission
if (!rbac.hasPermission(delegator, permission)) {
return false;
}
// Check if delegator can act as delegatee (higher level)
const delegatorRoles = delegator.roles;
const delegateeRoles = delegatee.roles;
for (const delegatorRole of delegatorRoles) {
for (const delegateeRole of delegateeRoles) {
if (rbac.canActAsRole(delegatorRole, delegateeRole)) {
return true;
}
}
}
return false;
}
// Usage
const admin = { id: 'admin-1', roles: ['admin'] };
const manager = { id: 'mgr-1', roles: ['manager'] };
canDelegatePermission(admin, manager, 'team:manage'); // true
```
### Resource Access Control
```typescript
interface Document {
id: string;
ownerId: string;
ownerRole: string;
content: string;
}
function canAccessDocument(
user: RBACUser,
document: Document
): boolean {
// Owner can always access
if (user.id === document.ownerId) {
return true;
}
// Check if user's role is higher than document owner's role
for (const userRole of user.roles) {
const userLevel = rbac.getRoleHierarchy().getRoleLevel(userRole);
const ownerLevel = rbac.getRoleHierarchy().getRoleLevel(document.ownerRole);
if (userLevel > ownerLevel) {
return true;
}
}
return false;
}
// Usage
const manager = { id: 'mgr-1', roles: ['manager'] };
const employeeDoc = {
id: 'doc-1',
ownerId: 'emp-1',
ownerRole: 'employee',
content: 'Employee document'
};
canAccessDocument(manager, employeeDoc); // true (manager > employee)
```
### Approval Workflows
```typescript
interface ApprovalRequest {
id: string;
requesterId: string;
requesterRole: string;
action: string;
status: 'pending' | 'approved' | 'rejected';
}
function canApproveRequest(
approver: RBACUser,
request: ApprovalRequest
): boolean {
// Must have approval permission
if (!rbac.hasPermission(approver, 'approval:grant')) {
return false;
}
// Approver must be higher level than requester
const hierarchy = rbac.getRoleHierarchy();
for (const approverRole of approver.roles) {
const approverLevel = hierarchy.getRoleLevel(approverRole);
const requesterLevel = hierarchy.getRoleLevel(request.requesterRole);
if (approverLevel > requesterLevel) {
return true;
}
}
return false;
}
// Usage
const manager = { id: 'mgr-1', roles: ['manager'] };
const employeeRequest: ApprovalRequest = {
id: 'req-1',
requesterId: 'emp-1',
requesterRole: 'employee',
action: 'vacation',
status: 'pending'
};
canApproveRequest(manager, employeeRequest); // true
```
## Advanced Patterns
### Multi-Role Users
```typescript
const user = {
id: 'user-1',
roles: ['engineer', 'team-lead'] // Multiple roles
};
// Check if user can act as any role
function canActAsAnyRole(user: RBACUser, targetRole: string): boolean {
return user.roles.some(role => rbac.canActAsRole(role, targetRole));
}
canActAsAnyRole(user, 'intern'); // true if either engineer or team-lead can
```
### Cross-Department Hierarchy
```typescript
const rbac = new RBACBuilder()
// Engineering
.addRole('engineering-director', ['engineering:*'], { level: 50 })
.addRole('engineering-manager', ['engineering:team:*'], { level: 30 })
.addRole('engineer', ['engineering:code:*'], { level: 10 })
// Sales
.addRole('sales-director', ['sales:*'], { level: 50 })
.addRole('sales-manager', ['sales:team:*'], { level: 30 })
.addRole('sales-rep', ['sales:deal:*'], { level: 10 })
// Executive (above all departments)
.addRole('ceo', ['*'], { level: 100 })
.build();
// CEO can act as any role
rbac.canActAsRole('ceo', 'engineering-director'); // true
rbac.canActAsRole('ceo', 'sales-director'); // true
// Directors cannot cross departments
rbac.canActAsRole('engineering-director', 'sales-director'); // false (same level)
```
### Dynamic Level Assignment
```typescript
function assignRoleLevel(role: string, departmentSize: number): number {
const baseLevel = {
'ceo': 100,
'director': 50,
'manager': 30,
'lead': 20,
'member': 10
};
// Adjust level based on department size
const sizeMultiplier = Math.log10(departmentSize);
return Math.floor(baseLevel[role] * (1 + sizeMultiplier * 0.1));
}
// Large department managers get slightly higher level
const largeTeamManager = assignRoleLevel('manager', 100); // ~33
const smallTeamManager = assignRoleLevel('manager', 10); // ~30
```
## Best Practices
### 1. Use Meaningful Levels
```typescript
// ✅ Good: Clear hierarchy
.addRole('ceo', ['*'], { level: 100 })
.addRole('director', ['department:*'], { level: 50 })
.addRole('manager', ['team:*'], { level: 30 })
.addRole('employee', ['task:*'], { level: 10 })
// ❌ Avoid: Random numbers
.addRole('admin', ['*'], { level: 42 })
.addRole('user', ['read'], { level: 7 })
```
### 2. Leave Room for Growth
```typescript
// ✅ Good: Spacing allows insertions
.addRole('ceo', ['*'], { level: 100 })
.addRole('vp', ['division:*'], { level: 80 })
.addRole('director', ['department:*'], { level: 60 })
.addRole('manager', ['team:*'], { level: 40 })
// Now you can add 'senior-manager' at level 50
```
### 3. Document Hierarchy
```typescript
// ✅ Good: Clear descriptions
.addRole('admin', ['*'], {
level: 100,
description: 'System administrator - can manage all resources',
metadata: {
canDelegate: true,
maxDelegationLevel: 90
}
})
```
### 4. Validate Hierarchy
```typescript
// Validate hierarchy on startup
function validateHierarchy(rbac: RBAC) {
const hierarchy = rbac.getRoleHierarchy();
const roles = hierarchy.getAllRoles();
for (const role of roles) {
const level = hierarchy.getRoleLevel(role);
console.log(`${role}: level ${level}`);
if (level === 0) {
console.warn(`⚠️ Role ${role} has no level set`);
}
}
}
```
## Common Pitfalls
### 1. Circular Dependencies
```typescript
// ❌ Avoid: Same levels can cause issues
rbac.getRoleHierarchy().setRoleLevel('admin', 10);
rbac.getRoleHierarchy().setRoleLevel('manager', 10);
// Who can act as who?
rbac.canActAsRole('admin', 'manager'); // false (10 >= 10 is false)
```
### 2. Forgetting to Set Levels
```typescript
// ❌ Avoid: Roles without levels
rbac.createRole('admin', ['*']); // No level set!
// ✅ Good: Always set levels
rbac.createRole('admin', ['*']);
rbac.getRoleHierarchy().setRoleLevel('admin', 10);
```
## Next Steps
- Learn about [Permissions](/guide/permissions)
- Explore [Roles](/guide/roles)
- Check out [Examples](/examples/basic-usage)
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/guide/wildcards
────────────────────────────────────────────────────────────────────────
# Wildcards
Wildcards provide flexible and powerful permission patterns.
## What are Wildcards?
Wildcards use the `*` symbol to match multiple permissions with a single pattern. Instead of granting each permission individually, you can use wildcards to grant groups of permissions.
```typescript
// Without wildcards - tedious
rbac.createRole('admin', [
'posts:read',
'posts:write',
'posts:delete',
'posts:publish',
'posts:archive'
// ... many more
])
// With wildcards - clean
rbac.createRole('admin', ['posts:*'])
```
## Wildcard Patterns
### Resource Wildcard
Grant all actions on a specific resource:
```typescript
rbac.createRole('post-admin', ['posts:*'])
const admin = { id: '1', roles: ['post-admin'] }
// All post actions are allowed
rbac.hasPermission(admin, 'posts:read') // ✅ true
rbac.hasPermission(admin, 'posts:write') // ✅ true
rbac.hasPermission(admin, 'posts:delete') // ✅ true
rbac.hasPermission(admin, 'posts:anything') // ✅ true
```
### Action Wildcard
Grant specific action across all resources:
```typescript
rbac.createRole('reader', ['*:read'])
const reader = { id: '1', roles: ['reader'] }
// Can read all resources
rbac.hasPermission(reader, 'posts:read') // ✅ true
rbac.hasPermission(reader, 'comments:read') // ✅ true
rbac.hasPermission(reader, 'users:read') // ✅ true
// Cannot perform other actions
rbac.hasPermission(reader, 'posts:write') // ❌ false
```
### Full Wildcard
Grant all permissions (superuser):
```typescript
rbac.createRole('superuser', ['*'])
const superuser = { id: '1', roles: ['superuser'] }
// Everything is allowed
rbac.hasPermission(superuser, 'posts:read') // ✅ true
rbac.hasPermission(superuser, 'posts:delete') // ✅ true
rbac.hasPermission(superuser, 'users:manage') // ✅ true
rbac.hasPermission(superuser, 'anything:goes') // ✅ true
```
### Nested Wildcards
Use wildcards with hierarchical permissions:
```typescript
rbac.createRole('admin', ['admin:*'])
const admin = { id: '1', roles: ['admin'] }
// All admin actions are allowed
rbac.hasPermission(admin, 'admin:users:read') // ✅ true
rbac.hasPermission(admin, 'admin:users:write') // ✅ true
rbac.hasPermission(admin, 'admin:settings:write') // ✅ true
rbac.hasPermission(admin, 'admin:logs:view') // ✅ true
// Non-admin actions are not allowed
rbac.hasPermission(admin, 'posts:read') // ❌ false
```
## Wildcard Matching Rules
### Exact Match Priority
Explicit permissions take priority over wildcards:
```typescript
rbac.createRole('editor', [
'posts:*',
'!posts:delete' // Explicitly deny delete
])
// Note: Explicit denials are handled at application level
// Fire Shield returns true for posts:delete due to posts:*
// You need to check denials separately
```
### Partial Wildcards
Wildcards only match the segment they're in:
```typescript
rbac.createRole('role', ['admin:users:*'])
const user = { id: '1', roles: ['role'] }
// Matches within admin:users namespace
rbac.hasPermission(user, 'admin:users:read') // ✅ true
rbac.hasPermission(user, 'admin:users:write') // ✅ true
// Doesn't match other namespaces
rbac.hasPermission(user, 'admin:settings:read') // ❌ false
rbac.hasPermission(user, 'users:read') // ❌ false
```
## Common Patterns
### Admin Roles
```typescript
// Full system admin
rbac.createRole('system-admin', ['*'])
// Module-specific admins
rbac.createRole('user-admin', ['users:*'])
rbac.createRole('content-admin', ['posts:*', 'comments:*'])
rbac.createRole('billing-admin', ['billing:*', 'invoices:*'])
```
### Read-Only Access
```typescript
// Read everything
rbac.createRole('auditor', ['*:read'])
// Read specific modules
rbac.createRole('reporter', [
'analytics:*:read',
'reports:*:read',
'logs:read'
])
```
### Tiered Access
```typescript
// Basic tier - limited access
rbac.createRole('basic', [
'app:read',
'profile:write:own'
])
// Pro tier - more features
rbac.createRole('pro', [
'app:read',
'app:advanced:*',
'profile:*',
'export:*'
])
// Enterprise tier - full access
rbac.createRole('enterprise', ['*'])
```
## Combining Wildcards and Specific Permissions
Mix wildcards with specific permissions:
```typescript
rbac.createRole('moderator', [
'posts:read',
'posts:write',
'comments:*', // All comment actions
'users:read'
])
const moderator = { id: '1', roles: ['moderator'] }
// Specific post permissions
rbac.hasPermission(moderator, 'posts:read') // ✅ true
rbac.hasPermission(moderator, 'posts:write') // ✅ true
rbac.hasPermission(moderator, 'posts:delete') // ❌ false
// All comment permissions
rbac.hasPermission(moderator, 'comments:read') // ✅ true
rbac.hasPermission(moderator, 'comments:moderate') // ✅ true
rbac.hasPermission(moderator, 'comments:delete') // ✅ true
```
## Performance Considerations
Wildcards are highly optimized:
```typescript
// ✅ Efficient - single wildcard
rbac.createRole('admin', ['posts:*'])
// ✅ Also efficient - few specific permissions
rbac.createRole('editor', [
'posts:read',
'posts:write',
'posts:publish'
])
// ⚠️ Consider wildcard - many similar permissions
rbac.createRole('admin', [
'posts:read',
'posts:write',
'posts:delete',
'posts:publish',
'posts:archive',
'posts:restore',
// ... 20 more post permissions
])
// Better: rbac.createRole('admin', ['posts:*'])
```
## Best Practices
### 1. Use Wildcards for Admin Roles
```typescript
// ✅ Good - clear admin intent
rbac.createRole('admin', ['posts:*'])
// ❌ Avoid - tedious and error-prone
rbac.createRole('admin', [
'posts:read',
'posts:write',
// ... might miss some permissions
])
```
### 2. Be Specific When Needed
```typescript
// ✅ Good - specific access
rbac.createRole('editor', [
'posts:read',
'posts:write',
'posts:publish'
// Deliberately excludes posts:delete
])
// ❌ Avoid - too broad
rbac.createRole('editor', ['posts:*'])
// Includes delete, which editors shouldn't have
```
### 3. Document Wildcard Usage
```typescript
// ✅ Good - documented
rbac.createRole('content-moderator', [
'posts:*', // Full post management
'comments:*' // Full comment management
// Note: Cannot manage users
])
// ❌ Avoid - unclear scope
rbac.createRole('moderator', ['*'])
// What does this role actually do?
```
### 4. Combine with Role Hierarchy
```typescript
// ✅ Good - clear progression
rbac.createRole('viewer', ['posts:read'])
rbac.createRole('editor', ['posts:read', 'posts:write'])
rbac.createRole('admin', ['posts:*'])
rbac.setRoleHierarchy({
admin: ['editor'],
editor: ['viewer']
})
```
## Advanced Patterns
### Namespace-Based Access
```typescript
// Organize permissions by namespace
rbac.createRole('api-full', ['api:*'])
rbac.createRole('api-read', ['api:*:read'])
const apiUser = { id: '1', roles: ['api-full'] }
rbac.hasPermission(apiUser, 'api:v1:read') // ✅ true
rbac.hasPermission(apiUser, 'api:v2:write') // ✅ true
```
### Multi-Tenant Wildcards
```typescript
// Tenant-scoped permissions
rbac.createRole('tenant-admin', [
'tenant:*', // All tenant operations
'tenant:users:*', // All tenant user operations
'tenant:billing:read' // Can only read billing
])
```
### Feature Flags
```typescript
// Feature-based permissions
rbac.createRole('beta-tester', [
'app:*',
'features:beta:*', // All beta features
'features:experimental:read' // Can view experimental features
])
```
## Testing Wildcards
Always test wildcard permissions thoroughly:
```typescript
describe('Admin permissions', () => {
it('should allow all post actions', () => {
rbac.createRole('admin', ['posts:*'])
const admin = { id: '1', roles: ['admin'] }
expect(rbac.hasPermission(admin, 'posts:read')).toBe(true)
expect(rbac.hasPermission(admin, 'posts:write')).toBe(true)
expect(rbac.hasPermission(admin, 'posts:delete')).toBe(true)
})
it('should not allow non-post actions', () => {
rbac.createRole('admin', ['posts:*'])
const admin = { id: '1', roles: ['admin'] }
expect(rbac.hasPermission(admin, 'users:delete')).toBe(false)
})
})
```
## Next Steps
- Learn about [Role Hierarchy](/guide/role-hierarchy)
- Understand [Permissions](/guide/permissions)
- Explore [API Reference](/api/core)
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/guide/deny-permissions
────────────────────────────────────────────────────────────────────────
# Deny Permissions
Learn how to explicitly deny permissions to override role-based grants.
## Overview
Deny Permissions is a powerful feature in Fire Shield that allows you to explicitly revoke specific permissions from users, overriding their role-based permissions.
**Key Concepts:**
- **Deny > Allow**: Denied permissions ALWAYS take precedence over granted permissions
- **User-Specific**: Denies are applied per user, not per role
- **Temporary Revocation**: Great for temporary access restrictions without changing roles
- **Wildcard Support**: Can deny entire permission groups with wildcards
## Why Use Deny Permissions?
### Use Cases
1. **Temporary Restrictions**
- Suspend user's write access during investigation
- Revoke specific permissions temporarily without role change
2. **Fine-Grained Control**
- Remove one permission from a role without creating a new role
- Override role permissions for specific users
3. **Security Incidents**
- Quickly revoke access when user account is compromised
- Disable dangerous permissions immediately
4. **Feature Flags**
- Disable beta features for specific users
- Roll out features gradually
5. **Compliance**
- Enforce regulatory restrictions on specific users
- Implement separation of duties
## Basic Usage
### Deny a Permission
```typescript
import { RBAC } from '@fire-shield/core';
const rbac = new RBAC();
rbac.createRole('editor', ['post:read', 'post:write', 'post:delete']);
const user = { id: 'user-123', roles: ['editor'] };
// User has all editor permissions initially
rbac.hasPermission(user, 'post:delete'); // ✅ true
// Deny delete permission for this specific user
rbac.denyPermission('user-123', 'post:delete');
// Now they can't delete, even though their role allows it
rbac.hasPermission(user, 'post:delete'); // ❌ false
rbac.hasPermission(user, 'post:write'); // ✅ true (still works)
```
### Allow Permission (Remove Deny)
```typescript
// Restore the denied permission
rbac.allowPermission('user-123', 'post:delete');
// Permission restored to role default
rbac.hasPermission(user, 'post:delete'); // ✅ true
```
### Check If Permission Is Denied
```typescript
// Check if a specific permission is denied for a user
const isDenied = rbac.isDenied('user-123', 'post:delete');
if (isDenied) {
console.log('This permission is explicitly denied');
}
```
### Get All Denied Permissions
```typescript
// Get list of all denied permissions for a user
const deniedPermissions = rbac.getDeniedPermissions('user-123');
console.log('Denied permissions:', deniedPermissions);
// ['post:delete', 'user:write']
```
## Wildcard Denies
You can use wildcards to deny entire groups of permissions.
### Deny All Permissions in a Resource
```typescript
const rbac = new RBAC({ enableWildcards: true });
rbac.createRole('admin', ['user:*', 'post:*']);
const user = { id: 'admin-123', roles: ['admin'] };
// Deny all user-related permissions
rbac.denyPermission('admin-123', 'user:*');
// Admin can no longer access user operations
rbac.hasPermission(user, 'user:read'); // ❌ false
rbac.hasPermission(user, 'user:write'); // ❌ false
rbac.hasPermission(user, 'user:delete'); // ❌ false
// But can still access posts
rbac.hasPermission(user, 'post:read'); // ✅ true
rbac.hasPermission(user, 'post:write'); // ✅ true
```
### Deny Specific Action Across Resources
```typescript
// Deny all delete operations
rbac.denyPermission('user-123', '*:delete');
rbac.hasPermission(user, 'post:delete'); // ❌ false
rbac.hasPermission(user, 'user:delete'); // ❌ false
rbac.hasPermission(user, 'comment:delete'); // ❌ false
// Other actions still work
rbac.hasPermission(user, 'post:write'); // ✅ true
rbac.hasPermission(user, 'user:read'); // ✅ true
```
## Priority Rules
### Deny Always Wins
Denied permissions ALWAYS take precedence, regardless of how permissions are granted.
```typescript
const rbac = new RBAC();
rbac.createRole('admin', ['*']); // Admin has ALL permissions
const user = {
id: 'admin-123',
roles: ['admin'],
permissions: ['super:admin'] // Even with direct permission
};
// Deny one permission
rbac.denyPermission('admin-123', 'delete:database');
// Deny overrides role AND direct permissions
rbac.hasPermission(user, 'delete:database'); // ❌ false
rbac.hasPermission(user, 'create:user'); // ✅ true
```
**Priority Order:**
1. 🔴 **Deny** (highest priority)
2. 🟡 **Direct User Permissions**
3. 🟢 **Role Permissions** (lowest priority)
### Multiple Denies
You can deny multiple permissions for the same user:
```typescript
// Deny multiple permissions
rbac.denyPermission('user-123', 'post:delete');
rbac.denyPermission('user-123', 'user:delete');
rbac.denyPermission('user-123', 'comment:delete');
// Check all denies
const denied = rbac.getDeniedPermissions('user-123');
// ['post:delete', 'user:delete', 'comment:delete']
```
## Advanced Patterns
### Temporary Suspension
```typescript
function suspendUserWrites(userId: string) {
// Deny all write operations
rbac.denyPermission(userId, '*:write');
rbac.denyPermission(userId, '*:delete');
rbac.denyPermission(userId, '*:create');
console.log(`User ${userId} suspended from write operations`);
}
function restoreUserAccess(userId: string) {
// Remove all denies
const denied = rbac.getDeniedPermissions(userId);
for (const permission of denied) {
rbac.allowPermission(userId, permission);
}
console.log(`User ${userId} access restored`);
}
// Use it
suspendUserWrites('suspicious-user-123');
// Later, after investigation
restoreUserAccess('suspicious-user-123');
```
### Feature Flags
```typescript
class FeatureFlags {
constructor(private rbac: RBAC) {}
disableFeature(userId: string, feature: string) {
this.rbac.denyPermission(userId, `feature:${feature}`);
}
enableFeature(userId: string, feature: string) {
this.rbac.allowPermission(userId, `feature:${feature}`);
}
isFeatureEnabled(user: RBACUser, feature: string): boolean {
return this.rbac.hasPermission(user, `feature:${feature}`);
}
}
// Usage
const flags = new FeatureFlags(rbac);
// Beta features are denied by default for some users
flags.disableFeature('user-123', 'ai-assistant');
flags.disableFeature('user-123', 'advanced-analytics');
// Enable for specific users
flags.enableFeature('beta-tester-456', 'ai-assistant');
```
### Compliance Enforcement
```typescript
class ComplianceManager {
private rbac: RBAC;
enforceSODPolicy(userId: string) {
// Separation of Duties: Users can't approve their own requests
if (this.userCreatesRequests(userId)) {
// Deny approval permission
this.rbac.denyPermission(userId, 'request:approve');
}
}
enforceDataResidency(userId: string, region: string) {
// GDPR: EU users can only access EU data
if (region === 'EU') {
this.rbac.denyPermission(userId, 'data:us:*');
this.rbac.denyPermission(userId, 'data:asia:*');
}
}
}
```
### Emergency Lockdown
```typescript
function emergencyLockdown(userId: string, reason: string) {
// Deny ALL permissions
rbac.denyPermission(userId, '*');
// Log the event
console.log(`EMERGENCY: User ${userId} locked down. Reason: ${reason}`);
// Send alert
sendSecurityAlert({
type: 'LOCKDOWN',
userId,
reason,
timestamp: new Date()
});
}
// Usage
emergencyLockdown('compromised-user-789', 'Suspected account breach');
```
## Framework Integration
### React
```tsx
import { useRBAC, useDenyPermission, useIsDenied } from '@fire-shield/react';
function UserManagement() {
const { can } = useRBAC();
const denyPermission = useDenyPermission();
const isDeniedDelete = useIsDenied('user:delete');
const handleSuspendUser = (userId: string) => {
// Deny critical permissions
denyPermission('user:delete');
denyPermission('user:write');
toast.success('User suspended');
};
return (
{isDeniedDelete && (
Delete permission is currently denied
)}
{can('user:suspend') && (
)}
);
}
```
### Vue
```vue
Delete permission is currently denied
```
### Express
```typescript
import { createExpressRBAC } from '@fire-shield/express';
const rbacMiddleware = createExpressRBAC(rbac, {
getUser: (req) => req.user
});
// Endpoint to deny permission
app.post('/admin/deny-permission', async (req, res) => {
const { userId, permission } = req.body;
// Verify admin
if (!rbac.hasPermission(req.user, 'admin:permissions')) {
return res.status(403).json({ error: 'Forbidden' });
}
// Deny permission
rbac.denyPermission(userId, permission);
res.json({ success: true });
});
// Check denied permissions
app.get('/users/:id/denied-permissions', async (req, res) => {
const denied = rbac.getDeniedPermissions(req.params.id);
res.json({ deniedPermissions: denied });
});
```
## API Reference
### `denyPermission(userId, permission)`
Deny a specific permission for a user.
```typescript
rbac.denyPermission(
userId: string, // User ID
permission: string // Permission to deny (supports wildcards)
): void
```
**Example:**
```typescript
rbac.denyPermission('user-123', 'post:delete');
rbac.denyPermission('admin-456', 'user:*');
```
### `allowPermission(userId, permission)`
Remove a denied permission (restore to role default).
```typescript
rbac.allowPermission(
userId: string, // User ID
permission: string // Permission to allow back
): void
```
**Example:**
```typescript
rbac.allowPermission('user-123', 'post:delete');
```
### `isDenied(userId, permission)`
Check if a specific permission is denied for a user.
```typescript
rbac.isDenied(
userId: string, // User ID
permission: string // Permission to check
): boolean
```
**Returns:** `true` if permission is explicitly denied, `false` otherwise
**Example:**
```typescript
if (rbac.isDenied('user-123', 'post:delete')) {
console.log('This permission is denied');
}
```
### `getDeniedPermissions(userId)`
Get all denied permissions for a user.
```typescript
rbac.getDeniedPermissions(
userId: string // User ID
): string[]
```
**Returns:** Array of denied permission strings
**Example:**
```typescript
const denied = rbac.getDeniedPermissions('user-123');
// ['post:delete', 'user:write']
```
## Best Practices
### 1. Document Denies
Always document why a permission was denied:
```typescript
interface PermissionDeny {
userId: string;
permission: string;
reason: string;
deniedAt: Date;
deniedBy: string;
}
class AuditedRBAC {
private denies: PermissionDeny[] = [];
denyWithReason(
userId: string,
permission: string,
reason: string,
deniedBy: string
) {
this.rbac.denyPermission(userId, permission);
this.denies.push({
userId,
permission,
reason,
deniedAt: new Date(),
deniedBy
});
}
getDenyReason(userId: string, permission: string): string | null {
const deny = this.denies.find(d =>
d.userId === userId && d.permission === permission
);
return deny?.reason || null;
}
}
```
### 2. Time-Limited Denies
Implement automatic expiration:
```typescript
class TemporaryDenies {
private rbac: RBAC;
private expirations = new Map();
denyUntil(userId: string, permission: string, until: Date) {
this.rbac.denyPermission(userId, permission);
const key = `${userId}:${permission}`;
this.expirations.set(key, until);
// Schedule removal
const timeout = until.getTime() - Date.now();
setTimeout(() => {
this.rbac.allowPermission(userId, permission);
this.expirations.delete(key);
}, timeout);
}
}
// Usage
const temp = new TemporaryDenies(rbac);
// Deny for 24 hours
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
temp.denyUntil('user-123', 'post:delete', tomorrow);
```
### 3. Notify Users
Inform users when permissions are denied:
```typescript
function denyWithNotification(
userId: string,
permission: string,
reason: string
) {
rbac.denyPermission(userId, permission);
// Send notification
sendEmail({
to: getUserEmail(userId),
subject: 'Permission Revoked',
body: `Your ${permission} permission has been revoked. Reason: ${reason}`
});
}
```
### 4. Bulk Operations
Provide helpers for common deny scenarios:
```typescript
function suspendAllWrites(userId: string) {
const writePermissions = ['*:write', '*:delete', '*:create', '*:update'];
for (const permission of writePermissions) {
rbac.denyPermission(userId, permission);
}
}
function removeAllDenies(userId: string) {
const denied = rbac.getDeniedPermissions(userId);
for (const permission of denied) {
rbac.allowPermission(userId, permission);
}
}
```
### 5. Integration with Audit Logs
Track all deny operations:
```typescript
const rbac = new RBAC({
auditLogger: {
log: (event) => {
if (event.action === 'deny_permission') {
console.log('Permission denied:', event);
database.logSecurityEvent(event);
}
}
}
});
```
## Common Patterns
### Role Downgrade Without Role Change
```typescript
// Temporarily reduce admin to read-only without changing their role
function downgradeToReadOnly(userId: string) {
rbac.denyPermission(userId, '*:write');
rbac.denyPermission(userId, '*:delete');
rbac.denyPermission(userId, '*:create');
rbac.denyPermission(userId, '*:update');
// They keep their role but can only read
}
```
### Progressive Access
```typescript
// Start with minimal access, gradually enable features
function onboardNewUser(userId: string) {
// Deny advanced features initially
rbac.denyPermission(userId, 'feature:analytics');
rbac.denyPermission(userId, 'feature:export');
rbac.denyPermission(userId, 'feature:api');
// After 30 days, enable analytics
setTimeout(() => {
rbac.allowPermission(userId, 'feature:analytics');
}, 30 * 24 * 60 * 60 * 1000);
}
```
### Context-Based Restrictions
```typescript
// Deny permissions based on context
function enforceWorkHours(userId: string) {
const hour = new Date().getHours();
// Deny sensitive operations outside work hours (9 AM - 5 PM)
if (hour < 9 || hour >= 17) {
rbac.denyPermission(userId, 'financial:*');
rbac.denyPermission(userId, 'user:delete');
} else {
rbac.allowPermission(userId, 'financial:*');
rbac.allowPermission(userId, 'user:delete');
}
}
```
## Comparison with Other Approaches
### vs. Removing from Role
**Deny Permission:**
- ✅ Temporary and reversible
- ✅ Doesn't affect role definition
- ✅ User-specific
- ✅ Faster to implement
**Remove from Role:**
- ❌ Changes role structure
- ❌ Affects all users with that role
- ❌ Requires role management
- ✅ More permanent solution
### vs. Creating New Role
**Deny Permission:**
- ✅ No role proliferation
- ✅ Easy to manage
- ✅ Quick to apply/remove
**New Role:**
- ❌ Role explosion
- ❌ Hard to maintain
- ✅ Better for permanent changes
## Next Steps
- [Wildcards](/guide/wildcards) - Pattern matching in permissions
- [Audit Logging](/guide/audit-logging) - Track permission changes
- [Role Hierarchy](/guide/role-hierarchy) - Organize roles effectively
- [API Reference](/api/core) - Complete API documentation
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/guide/audit-logging
────────────────────────────────────────────────────────────────────────
# Audit Logging
Complete guide to implementing audit logging for security, compliance, and debugging.
## Why Audit Logging?
Audit logging provides:
- **Security**: Track unauthorized access attempts
- **Compliance**: Meet GDPR, SOC2, HIPAA requirements
- **Debugging**: Identify permission configuration issues
- **Analytics**: Understand user behavior patterns
- **Forensics**: Investigate security incidents
## Quick Start
```typescript
import { RBAC, ConsoleAuditLogger } from '@fire-shield/core';
const rbac = new RBAC({
auditLogger: new ConsoleAuditLogger()
});
// All permission checks are automatically logged
rbac.hasPermission(user, 'post:delete');
// [AUDIT] ✓ ALLOWED: User user-123 - post:delete
```
## Built-in Loggers
### ConsoleAuditLogger
Development logger that outputs to console:
```typescript
import { ConsoleAuditLogger } from '@fire-shield/core';
const logger = new ConsoleAuditLogger();
const rbac = new RBAC({ auditLogger: logger });
```
**Output Example:**
```
[AUDIT 2025-01-15T10:30:00.000Z] ✓ ALLOWED: User user-123 - post:read
[AUDIT 2025-01-15T10:30:01.000Z] ✗ DENIED: User user-123 - admin:delete
Reason: User lacks permission: admin:delete
```
### BufferedAuditLogger
Production logger with batching:
```typescript
import { BufferedAuditLogger } from '@fire-shield/core';
const logger = new BufferedAuditLogger(
async (events) => {
await database.auditLogs.insertMany(events);
},
{
maxBufferSize: 100, // Flush after 100 events
flushIntervalMs: 5000 // Or every 5 seconds
}
);
const rbac = new RBAC({ auditLogger: logger });
```
### MultiAuditLogger
Log to multiple destinations:
```typescript
import { MultiAuditLogger, ConsoleAuditLogger, BufferedAuditLogger } from '@fire-shield/core';
const logger = new MultiAuditLogger([
new ConsoleAuditLogger(), // Development
new BufferedAuditLogger(async (events) => {
await database.save(events); // Production
})
]);
const rbac = new RBAC({ auditLogger: logger });
```
## Custom Loggers
### Basic Custom Logger
```typescript
import type { AuditLogger, AuditEvent } from '@fire-shield/core';
class FileAuditLogger implements AuditLogger {
async log(event: AuditEvent): Promise {
const logEntry = `${new Date(event.timestamp).toISOString()} - ${event.userId} - ${event.permission} - ${event.allowed ? 'ALLOW' : 'DENY'}\n`;
await fs.appendFile('audit.log', logEntry);
}
}
const rbac = new RBAC({ auditLogger: new FileAuditLogger() });
```
### Database Logger
```typescript
class DatabaseLogger implements AuditLogger {
async log(event: AuditEvent): Promise {
await db.auditLogs.insert({
userId: event.userId,
permission: event.permission,
allowed: event.allowed,
reason: event.reason,
timestamp: new Date(event.timestamp),
context: event.context
});
}
}
```
### Security Monitoring Logger
```typescript
class SecurityMonitorLogger implements AuditLogger {
private failedAttempts = new Map();
private readonly threshold = 5;
log(event: AuditEvent): void {
if (!event.allowed) {
const count = (this.failedAttempts.get(event.userId) || 0) + 1;
this.failedAttempts.set(event.userId, count);
if (count >= this.threshold) {
this.alertSecurityTeam({
userId: event.userId,
attempts: count,
permission: event.permission,
timestamp: event.timestamp
});
}
} else {
// Reset on successful check
this.failedAttempts.delete(event.userId);
}
}
private alertSecurityTeam(alert: any) {
console.warn('🚨 Security Alert:', alert);
// Send to monitoring service
}
}
```
## Real-World Examples
### E-Commerce Compliance
```typescript
class ComplianceLogger implements AuditLogger {
async log(event: AuditEvent): Promise {
await db.auditLogs.insert({
...event,
// Compliance metadata
retentionPeriod: 7 * 365, // 7 years
encrypted: true,
compliance: {
gdpr: true,
pciDss: event.permission.includes('payment'),
hipaa: event.permission.includes('health')
}
});
// Also send to compliance monitoring
await fetch('https://compliance.example.com/audit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(event)
});
}
}
```
### Analytics Logger
```typescript
class AnalyticsLogger implements AuditLogger {
private buffer: AuditEvent[] = [];
log(event: AuditEvent): void {
this.buffer.push(event);
if (this.buffer.length >= 100) {
this.sendAnalytics();
}
}
private sendAnalytics() {
const stats = {
total: this.buffer.length,
allowed: this.buffer.filter(e => e.allowed).length,
denied: this.buffer.filter(e => !e.allowed).length,
byPermission: this.groupByPermission(),
byUser: this.groupByUser()
};
console.log('📊 Permission Analytics:', stats);
this.buffer = [];
}
private groupByPermission() {
return this.buffer.reduce((acc, event) => {
acc[event.permission] = (acc[event.permission] || 0) + 1;
return acc;
}, {} as Record);
}
private groupByUser() {
return this.buffer.reduce((acc, event) => {
acc[event.userId] = (acc[event.userId] || 0) + 1;
return acc;
}, {} as Record);
}
}
```
### Rotating Logger
```typescript
class RotatingFileLogger implements AuditLogger {
private currentDate = new Date().toISOString().split('T')[0];
private buffer: string[] = [];
async log(event: AuditEvent): Promise {
const logDate = new Date(event.timestamp).toISOString().split('T')[0];
// Rotate log file if date changed
if (logDate !== this.currentDate) {
await this.flush();
await this.rotateOldLogs();
this.currentDate = logDate;
}
const entry = JSON.stringify(event);
this.buffer.push(entry);
if (this.buffer.length >= 100) {
await this.flush();
}
}
async flush(): Promise {
if (this.buffer.length === 0) return;
const filename = `audit-${this.currentDate}.log`;
await fs.appendFile(filename, this.buffer.join('\n') + '\n');
this.buffer = [];
}
private async rotateOldLogs() {
const maxAge = 90 * 24 * 60 * 60 * 1000; // 90 days
const cutoff = Date.now() - maxAge;
const files = await fs.readdir('.');
for (const file of files) {
if (file.startsWith('audit-') && file.endsWith('.log')) {
const stats = await fs.stat(file);
if (stats.mtimeMs < cutoff) {
await fs.unlink(file);
}
}
}
}
}
```
## Querying Audit Logs
### By User
```typescript
// Find all logs for a specific user
const userLogs = await db.auditLogs.find({
userId: 'user-123'
}).sort({ timestamp: -1 }).limit(100);
// Find denied attempts for user
const deniedLogs = await db.auditLogs.find({
userId: 'user-123',
allowed: false
});
```
### By Permission
```typescript
// Find all attempts for a permission
const permissionLogs = await db.auditLogs.find({
permission: 'admin:delete'
});
// Find denied admin permission attempts
const deniedAdminLogs = await db.auditLogs.find({
permission: { $regex: '^admin:' },
allowed: false
});
```
### By Time Range
```typescript
// Last 24 hours
const recentLogs = await db.auditLogs.find({
timestamp: {
$gte: Date.now() - 24 * 60 * 60 * 1000
}
});
// Specific date range
const rangeLogs = await db.auditLogs.find({
timestamp: {
$gte: new Date('2025-01-01').getTime(),
$lte: new Date('2025-01-31').getTime()
}
});
```
### Aggregation
```typescript
// Count by permission
const permissionCounts = await db.auditLogs.aggregate([
{
$group: {
_id: '$permission',
count: { $sum: 1 },
deniedCount: {
$sum: { $cond: ['$allowed', 0, 1] }
}
}
},
{ $sort: { count: -1 } }
]);
// Failed attempts by user
const userFailures = await db.auditLogs.aggregate([
{ $match: { allowed: false } },
{
$group: {
_id: '$userId',
failures: { $sum: 1 },
permissions: { $addToSet: '$permission' }
}
},
{ $sort: { failures: -1 } }
]);
```
## Best Practices
### 1. Always Buffer in Production
```typescript
// ✅ Good: Buffered logging
const logger = new BufferedAuditLogger(
async (events) => await db.insert(events),
{ maxBufferSize: 100 }
);
// ❌ Avoid: Synchronous logging on every check
const logger = {
log: (event) => db.insert(event) // Blocks!
};
```
### 2. Include Context
```typescript
// ✅ Good: Rich context
const context = {
roles: user.roles,
ip: request.ip,
userAgent: request.headers['user-agent'],
resource: 'document',
resourceId: docId
};
rbac.authorize(user, 'document:edit', context);
// Logs will include all context
```
### 3. Rotate Old Logs
```typescript
// Schedule log rotation
setInterval(async () => {
const cutoff = Date.now() - 90 * 24 * 60 * 60 * 1000;
await db.auditLogs.deleteMany({
timestamp: { $lt: cutoff }
});
}, 24 * 60 * 60 * 1000);
```
### 4. Monitor Failed Attempts
```typescript
// Alert on suspicious activity
async function checkForSuspiciousActivity() {
const recentFailures = await db.auditLogs.countDocuments({
userId: user.id,
allowed: false,
timestamp: { $gte: Date.now() - 60 * 60 * 1000 }
});
if (recentFailures > 10) {
await alertSecurityTeam({
userId: user.id,
failures: recentFailures
});
}
}
```
### 5. Sampling for High Traffic
```typescript
class SamplingLogger implements AuditLogger {
private sampleRate = 0.1; // 10%
log(event: AuditEvent): void {
// Always log denied events
if (!event.allowed) {
this.saveLog(event);
return;
}
// Sample allowed events
if (Math.random() < this.sampleRate) {
this.saveLog(event);
}
}
private saveLog(event: AuditEvent) {
// Save to database
}
}
```
## Performance Optimization
### Async Logging
```typescript
class AsyncLogger implements AuditLogger {
async log(event: AuditEvent): Promise {
// Fire and forget
this.saveToDatabase(event).catch(err => {
console.error('Audit log error:', err);
});
}
private async saveToDatabase(event: AuditEvent) {
await db.auditLogs.insert(event);
}
}
```
### Batch Processing
```typescript
class BatchLogger implements AuditLogger {
private queue: AuditEvent[] = [];
private processing = false;
log(event: AuditEvent): void {
this.queue.push(event);
if (!this.processing && this.queue.length >= 50) {
this.processBatch();
}
}
private async processBatch() {
if (this.processing || this.queue.length === 0) return;
this.processing = true;
const batch = this.queue.splice(0, 50);
try {
await db.auditLogs.insertMany(batch);
} catch (error) {
console.error('Batch insert failed:', error);
// Re-queue failed events
this.queue.unshift(...batch);
} finally {
this.processing = false;
}
}
}
```
## Compliance Requirements
### GDPR
```typescript
class GDPRCompliantLogger implements AuditLogger {
async log(event: AuditEvent): Promise {
await db.auditLogs.insert({
...event,
// GDPR metadata
dataSubject: event.userId,
processingPurpose: 'access_control',
legalBasis: 'legitimate_interest',
retentionPeriod: 90, // days
consentId: event.context?.consentId
});
}
// Implement right to erasure
async eraseUserData(userId: string) {
await db.auditLogs.updateMany(
{ userId },
{ $set: { userId: 'REDACTED', anonymized: true } }
);
}
}
```
### SOC 2
```typescript
class SOC2Logger implements AuditLogger {
async log(event: AuditEvent): Promise {
await db.auditLogs.insert({
...event,
// SOC 2 requirements
immutable: true, // Cannot be modified
signed: this.signEvent(event),
controlId: 'AC-2', // Access control
severity: event.allowed ? 'info' : 'warning'
});
}
private signEvent(event: AuditEvent): string {
// Digital signature for integrity
return crypto
.createHmac('sha256', SECRET_KEY)
.update(JSON.stringify(event))
.digest('hex');
}
}
```
## Next Steps
- Explore [Core API](/api/core)
- Learn about [Performance](/guide/performance)
- Check out [API Reference](/api/audit)
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/guide/performance
────────────────────────────────────────────────────────────────────────
# Performance Optimization
Guide to optimizing Fire Shield RBAC for maximum performance.
## Performance Overview
Fire Shield is designed for high performance:
- **O(1)** bit-based permission checks
- **O(n)** string-based permission checks
- Built-in caching
- Minimal memory footprint
- Zero dependencies
## Bit-Based vs String-Based
### Bit-Based (Recommended)
Ultra-fast permission checks using bitwise operations:
```typescript
const rbac = new RBAC({ useBitSystem: true }); // Default
// O(1) permission check
rbac.hasPermission(user, 'post:read'); // ~0.001ms
```
**Pros:**
- Extremely fast (bitwise AND operation)
- Low memory usage
- Built-in caching
**Cons:**
- Maximum 31 permissions
- Requires bit assignment
### String-Based
Flexible but slower permission checks:
```typescript
const rbac = new RBAC({ useBitSystem: false });
// O(n) permission check
rbac.hasPermission(user, 'post:read'); // ~0.1ms
```
**Pros:**
- Unlimited permissions
- No bit management
- More flexible
**Cons:**
- Slower than bit-based
- Higher memory usage
## Benchmarks
### Permission Check Performance
```typescript
// Bit-based system
// 1,000,000 checks: ~100ms (0.0001ms per check)
// String-based system
// 1,000,000 checks: ~1000ms (0.001ms per check)
// 10x faster with bit-based
```
### Memory Usage
```typescript
// 10 roles, 20 permissions
// Bit-based: ~2KB
// String-based: ~5KB
// 100 roles, 200 permissions
// Bit-based: ~20KB
// String-based: ~150KB
```
## Optimization Techniques
### 1. Use Bit-Based System
```typescript
// ✅ Good: Fast bit-based checks
const rbac = new RBAC({ useBitSystem: true });
rbac.registerPermission('user:read', 1);
rbac.registerPermission('user:write', 2);
rbac.registerPermission('user:delete', 4);
// Lightning fast
rbac.hasPermission(user, 'user:read');
```
### 2. Pre-compute Permission Masks
```typescript
// ✅ Good: Pre-compute and store mask
const user = {
id: 'user-1',
roles: ['editor'],
permissionMask: rbac.createPermissionMask(['post:read', 'post:write'])
};
// Fast permission check using mask
rbac.hasPermission(user, 'post:read');
// ❌ Avoid: Computing on every request
const user = {
id: 'user-1',
roles: ['editor']
// No mask - computed every time
};
```
### 3. Cache User Permissions
```typescript
// ✅ Good: Cache permissions per session
class UserCache {
private cache = new Map();
getUser(userId: string): RBACUser | undefined {
return this.cache.get(userId);
}
setUser(userId: string, user: RBACUser) {
this.cache.set(userId, {
...user,
permissionMask: rbac.getUserPermissionMask(user)
});
}
clearUser(userId: string) {
this.cache.delete(userId);
}
}
const cache = new UserCache();
// Cache on login
cache.setUser(user.id, user);
// Fast lookups
const cachedUser = cache.getUser(user.id);
rbac.hasPermission(cachedUser, 'post:read');
```
### 4. Batch Permission Checks
```typescript
// ✅ Good: Single check for multiple permissions
const permissions = ['post:read', 'post:write', 'post:delete'];
const hasAll = rbac.hasAllPermissions(user, permissions);
// ❌ Avoid: Multiple individual checks
const canRead = rbac.hasPermission(user, 'post:read');
const canWrite = rbac.hasPermission(user, 'post:write');
const canDelete = rbac.hasPermission(user, 'post:delete');
```
### 5. Minimize Wildcard Usage
```typescript
// ✅ Good: Specific permissions for frequent checks
rbac.createRole('editor', ['post:read', 'post:write', 'post:publish']);
// ❌ Avoid: Wildcards for frequently checked permissions
rbac.createRole('editor', ['post:*']); // Slower pattern matching
```
### 6. Optimize Role Hierarchy
```typescript
// ✅ Good: Shallow hierarchy (2-3 levels)
rbac.getRoleHierarchy().setRoleLevel('admin', 10);
rbac.getRoleHierarchy().setRoleLevel('editor', 5);
rbac.getRoleHierarchy().setRoleLevel('user', 1);
// ❌ Avoid: Deep hierarchy (many levels)
// Each level adds overhead
```
## Caching Strategies
### Session-Based Caching
```typescript
class SessionCache {
private sessions = new Map;
expires: number;
}>();
set(sessionId: string, user: RBACUser, ttl: number = 3600000) {
this.sessions.set(sessionId, {
user,
permissions: new Set(rbac.getUserPermissions(user)),
expires: Date.now() + ttl
});
}
get(sessionId: string): RBACUser | null {
const session = this.sessions.get(sessionId);
if (!session) return null;
if (Date.now() > session.expires) {
this.sessions.delete(sessionId);
return null;
}
return session.user;
}
hasPermission(sessionId: string, permission: string): boolean {
const session = this.sessions.get(sessionId);
return session?.permissions.has(permission) || false;
}
}
```
### LRU Cache
```typescript
class LRUPermissionCache {
private cache: Map;
private maxSize: number;
constructor(maxSize: number = 1000) {
this.cache = new Map();
this.maxSize = maxSize;
}
check(userId: string, permission: string): boolean | undefined {
const key = `${userId}:${permission}`;
const cached = this.cache.get(key);
if (cached !== undefined) {
// Move to end (most recently used)
this.cache.delete(key);
this.cache.set(key, cached);
}
return cached;
}
set(userId: string, permission: string, allowed: boolean) {
const key = `${userId}:${permission}`;
// Remove oldest if at capacity
if (this.cache.size >= this.maxSize) {
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, allowed);
}
}
const cache = new LRUPermissionCache(1000);
// Check cache first
const userId = 'user-1';
const permission = 'post:read';
let allowed = cache.check(userId, permission);
if (allowed === undefined) {
// Not in cache, check RBAC
allowed = rbac.hasPermission(user, permission);
cache.set(userId, permission, allowed);
}
```
## Database Optimization
### Store Permission Masks
```typescript
// Store pre-computed permission mask in database
interface UserDocument {
id: string;
email: string;
roles: string[];
permissionMask: number; // Store computed mask
updatedAt: Date;
}
// On user update, recompute mask
async function updateUserRoles(userId: string, roles: string[]) {
const mask = rbac.createPermissionMask(
roles.flatMap(role => rbac.getRolePermissions(role))
);
await db.users.updateOne(
{ id: userId },
{
$set: {
roles,
permissionMask: mask,
updatedAt: new Date()
}
}
);
}
// Fast permission checks
const user = await db.users.findOne({ id: userId });
rbac.hasPermission(user, 'post:read'); // Uses cached mask
```
### Index Audit Logs
```typescript
// Create indexes for fast queries
await db.auditLogs.createIndex({ userId: 1, timestamp: -1 });
await db.auditLogs.createIndex({ permission: 1, allowed: 1 });
await db.auditLogs.createIndex({ timestamp: 1 }, { expireAfterSeconds: 7776000 }); // 90 days
```
## Load Testing
### Basic Load Test
```typescript
import { performance } from 'perf_hooks';
function loadTest(iterations: number = 1000000) {
const rbac = new RBAC({ useBitSystem: true });
rbac.registerPermission('test:read', 1);
rbac.createRole('tester', ['test:read']);
const user = { id: 'test-1', roles: ['tester'] };
const start = performance.now();
for (let i = 0; i < iterations; i++) {
rbac.hasPermission(user, 'test:read');
}
const end = performance.now();
const duration = end - start;
console.log(`${iterations} checks in ${duration.toFixed(2)}ms`);
console.log(`Average: ${(duration / iterations).toFixed(6)}ms per check`);
}
loadTest(); // 1,000,000 checks in ~100ms
```
### Concurrent Load Test
```typescript
async function concurrentLoadTest(
users: number = 100,
checksPerUser: number = 10000
) {
const rbac = new RBAC({ useBitSystem: true });
rbac.registerPermission('test:read', 1);
rbac.createRole('tester', ['test:read']);
const start = performance.now();
const promises = Array.from({ length: users }, (_, i) => {
const user = { id: `user-${i}`, roles: ['tester'] };
return Promise.resolve().then(() => {
for (let j = 0; j < checksPerUser; j++) {
rbac.hasPermission(user, 'test:read');
}
});
});
await Promise.all(promises);
const end = performance.now();
const total = users * checksPerUser;
console.log(`${total} checks with ${users} users in ${(end - start).toFixed(2)}ms`);
}
concurrentLoadTest(); // 1,000,000 checks in ~150ms
```
## Production Recommendations
### 1. Always Use Bit-Based System
```typescript
// ✅ Production
const rbac = new RBAC({ useBitSystem: true });
```
### 2. Buffer Audit Logging
```typescript
// ✅ Production: Buffered logging
const logger = new BufferedAuditLogger(
async (events) => await db.insert(events),
{ maxBufferSize: 100, flushIntervalMs: 5000 }
);
```
### 3. Cache User Sessions
```typescript
// ✅ Production: Session cache
const cache = new SessionCache();
cache.set(sessionId, user, 3600000); // 1 hour
```
### 4. Monitor Performance
```typescript
// ✅ Production: Performance monitoring
const start = performance.now();
const result = rbac.hasPermission(user, permission);
const duration = performance.now() - start;
if (duration > 1) {
console.warn(`Slow permission check: ${duration}ms`);
}
```
### 5. Optimize Database Queries
```typescript
// ✅ Production: Indexed queries
await db.users.createIndex({ id: 1 });
await db.users.createIndex({ 'roles': 1 });
await db.auditLogs.createIndex({ userId: 1, timestamp: -1 });
```
## Common Bottlenecks
### 1. Database Round-Trips
```typescript
// ❌ Slow: Multiple queries
const user = await db.users.findOne({ id: userId });
const roles = await db.roles.find({ name: { $in: user.roles } });
// ✅ Fast: Single query with join
const user = await db.users.findOne({ id: userId })
.populate('roles');
```
### 2. Synchronous Audit Logging
```typescript
// ❌ Slow: Synchronous logging
const logger = {
log: (event) => fs.appendFileSync('audit.log', JSON.stringify(event))
};
// ✅ Fast: Async buffered logging
const logger = new BufferedAuditLogger(async (events) => {
await fs.appendFile('audit.log', events.map(e => JSON.stringify(e)).join('\n'));
});
```
### 3. Wildcard Overuse
```typescript
// ❌ Slow: Many wildcard checks
rbac.createRole('user', ['resource:*']);
rbac.hasPermission(user, 'resource:specific:action'); // Pattern matching
// ✅ Fast: Specific permissions
rbac.createRole('user', ['resource:read', 'resource:write']);
rbac.hasPermission(user, 'resource:read'); // Direct lookup
```
## Next Steps
- Learn about [TypeScript](/guide/typescript)
- Explore [Core API](/api/core)
- Check out [Audit Logging](/guide/audit-logging)
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/guide/typescript
────────────────────────────────────────────────────────────────────────
# TypeScript Guide
Complete guide to using Fire Shield with TypeScript for maximum type safety.
## Why TypeScript?
TypeScript provides:
- **Type Safety**: Catch errors at compile time
- **IntelliSense**: Better IDE autocomplete
- **Documentation**: Self-documenting code
- **Refactoring**: Safe code changes
- **Maintainability**: Easier to understand and modify
## Basic Types
### RBACUser
The core user type with roles and permissions:
```typescript
import type { RBACUser } from '@fire-shield/core';
const user: RBACUser = {
id: 'user-123',
roles: ['editor'],
permissions: ['beta:feature'], // Optional
permissionMask: 3 // Optional
};
```
### Extending RBACUser
Add custom fields to the user type:
```typescript
interface AppUser extends RBACUser {
email: string;
name: string;
department: string;
createdAt: Date;
}
const user: AppUser = {
id: 'user-123',
roles: ['editor'],
email: 'user@example.com',
name: 'John Doe',
department: 'Engineering',
createdAt: new Date()
};
// Still works with RBAC
rbac.hasPermission(user, 'post:write');
```
## Type-Safe Permissions
### Using Const Assertions
```typescript
const PERMISSIONS = {
// User permissions
USER_READ: 'user:read',
USER_WRITE: 'user:write',
USER_DELETE: 'user:delete',
// Post permissions
POST_READ: 'post:read',
POST_WRITE: 'post:write',
POST_DELETE: 'post:delete',
// Admin permissions
ADMIN_ACCESS: 'admin:access',
} as const;
// Type-safe permission type
type Permission = typeof PERMISSIONS[keyof typeof PERMISSIONS];
// Type-safe permission check
function checkPermission(user: RBACUser, permission: Permission): boolean {
return rbac.hasPermission(user, permission);
}
// ✅ Valid
checkPermission(user, PERMISSIONS.USER_READ);
// ❌ TypeScript error
checkPermission(user, 'invalid:permission');
```
### Using String Literal Types
```typescript
type Permission =
| 'user:read'
| 'user:write'
| 'user:delete'
| 'post:read'
| 'post:write'
| 'post:delete';
function hasPermission(user: RBACUser, permission: Permission): boolean {
return rbac.hasPermission(user, permission);
}
// ✅ Type-safe
hasPermission(user, 'user:read');
// ❌ TypeScript error
hasPermission(user, 'invalid:permission');
```
## Type-Safe Roles
### String Literal Types
```typescript
type Role = 'admin' | 'editor' | 'viewer';
function hasRole(user: RBACUser, role: Role): boolean {
return user.roles.includes(role);
}
// ✅ Type-safe
hasRole(user, 'admin');
// ❌ TypeScript error
hasRole(user, 'invalid-role');
```
### Role Configuration
```typescript
interface RoleConfig {
name: Role;
permissions: Permission[];
level: number;
description: string;
}
const roles: RoleConfig[] = [
{
name: 'admin',
permissions: ['user:read', 'user:write', 'post:read', 'post:write'],
level: 10,
description: 'Administrator'
},
{
name: 'editor',
permissions: ['post:read', 'post:write'],
level: 5,
description: 'Content Editor'
},
{
name: 'viewer',
permissions: ['post:read'],
level: 1,
description: 'Viewer'
}
];
```
## Generic Functions
### Type-Safe Permission Checker
```typescript
function createPermissionChecker(
rbac: RBAC,
user: RBACUser
) {
return {
can: (permission: T): boolean => {
return rbac.hasPermission(user, permission);
},
canAll: (permissions: T[]): boolean => {
return rbac.hasAllPermissions(user, permissions);
},
canAny: (permissions: T[]): boolean => {
return rbac.hasAnyPermission(user, permissions);
}
};
}
// Usage
const checker = createPermissionChecker(rbac, user);
checker.can('user:read'); // Type-safe ✅
checker.can('invalid'); // Type error ❌
```
### Type-Safe User Factory
```typescript
function createUser(
id: string,
roles: Role[],
additional?: Omit
): T {
return {
id,
roles,
...additional
} as T;
}
// Usage
interface CustomUser extends RBACUser {
email: string;
name: string;
}
const user = createUser('user-1', ['editor'], {
email: 'user@example.com',
name: 'John Doe'
});
```
## Discriminated Unions
### Authorization Results
```typescript
type AuthorizationSuccess = {
allowed: true;
user: RBACUser;
};
type AuthorizationFailure = {
allowed: false;
reason: string;
};
type AuthResult = AuthorizationSuccess | AuthorizationFailure;
function authorize(user: RBACUser, permission: Permission): AuthResult {
const result = rbac.authorize(user, permission);
if (result.allowed) {
return {
allowed: true,
user: result.user!
};
} else {
return {
allowed: false,
reason: result.reason || 'Permission denied'
};
}
}
// Type-safe usage
const result = authorize(user, 'user:read');
if (result.allowed) {
console.log(result.user); // Type: RBACUser
} else {
console.log(result.reason); // Type: string
}
```
## Type Guards
### Custom Type Guards
```typescript
function isRBACUser(value: unknown): value is RBACUser {
return (
typeof value === 'object' &&
value !== null &&
'id' in value &&
typeof (value as any).id === 'string' &&
'roles' in value &&
Array.isArray((value as any).roles)
);
}
// Usage
function checkUser(maybeUser: unknown) {
if (isRBACUser(maybeUser)) {
// TypeScript knows this is an RBACUser
rbac.hasPermission(maybeUser, 'post:read');
}
}
```
### Advanced Type Guards
```typescript
function hasPermissions(
user: RBACUser,
permissions: T
): user is RBACUser & { permissions: T } {
return permissions.every(p => rbac.hasPermission(user, p));
}
// Usage
if (hasPermissions(user, ['post:read', 'post:write'] as const)) {
// TypeScript knows user has these permissions
}
```
## Utility Types
### WithMetadata
```typescript
type WithMetadata = T & {
metadata?: Record;
};
type UserWithMetadata = WithMetadata;
const user: UserWithMetadata = {
id: 'user-1',
roles: ['editor'],
metadata: {
department: 'Engineering',
hireDate: '2025-01-01'
}
};
```
### Partial Permissions
```typescript
type PartialPermissions = {
[K in Permission]?: boolean;
};
function checkPermissions(user: RBACUser): PartialPermissions {
const perms: PartialPermissions = {};
for (const perm of Object.values(PERMISSIONS)) {
perms[perm] = rbac.hasPermission(user, perm);
}
return perms;
}
// Usage
const userPermissions = checkPermissions(user);
console.log(userPermissions['user:read']); // boolean | undefined
```
## Namespaced Permissions
```typescript
namespace Permissions {
export namespace User {
export const READ = 'user:read';
export const WRITE = 'user:write';
export const DELETE = 'user:delete';
}
export namespace Post {
export const READ = 'post:read';
export const WRITE = 'post:write';
export const DELETE = 'post:delete';
}
}
// Usage
rbac.hasPermission(user, Permissions.User.READ);
rbac.hasPermission(user, Permissions.Post.WRITE);
```
## Configuration Types
### Strongly Typed Configuration
```typescript
interface RBACConfigTyped {
roles: {
name: Role;
permissions: Permission[];
level: number;
}[];
permissions: {
name: Permission;
bit: number;
}[];
}
const config: RBACConfigTyped = {
roles: [
{ name: 'admin', permissions: ['user:read', 'user:write'], level: 10 }
],
permissions: [
{ name: 'user:read', bit: 1 },
{ name: 'user:write', bit: 2 }
]
};
```
## Best Practices
### 1. Define Types Early
```typescript
// ✅ Good: Define at the start
type Permission = 'user:read' | 'user:write';
type Role = 'admin' | 'editor';
interface AppUser extends RBACUser {
email: string;
}
// Use throughout the app
```
### 2. Use Const Assertions
```typescript
// ✅ Good: Type-safe constants
const PERMISSIONS = {
USER_READ: 'user:read',
USER_WRITE: 'user:write'
} as const;
type Permission = typeof PERMISSIONS[keyof typeof PERMISSIONS];
```
### 3. Avoid Any
```typescript
// ❌ Avoid
function checkPermission(user: any, permission: any) {
return rbac.hasPermission(user, permission);
}
// ✅ Good
function checkPermission(user: RBACUser, permission: Permission) {
return rbac.hasPermission(user, permission);
}
```
### 4. Use Generics
```typescript
// ✅ Good: Generic type-safe wrapper
function withPermission(
user: T,
permission: Permission,
action: (user: T) => void
) {
if (rbac.hasPermission(user, permission)) {
action(user);
}
}
```
### 5. Strict Mode
Enable strict mode in `tsconfig.json`:
```json
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true
}
}
```
## Framework-Specific Types
### React
```typescript
import type { RBACUser } from '@fire-shield/react';
interface Props {
user: RBACUser;
permission: Permission;
}
const ProtectedButton: React.FC = ({ user, permission }) => {
const { can } = useRBAC();
if (!can(permission)) {
return null;
}
return ;
};
```
### Vue
```typescript
import type { RBACUser } from '@fire-shield/vue';
interface UserState {
user: RBACUser | null;
isAuthenticated: boolean;
}
const userState = reactive({
user: null,
isAuthenticated: false
});
```
### Express
```typescript
import type { Request, Response } from 'express';
import type { RBACUser } from '@fire-shield/core';
// Extend Express Request type
declare global {
namespace Express {
interface Request {
user?: RBACUser;
}
}
}
// Type-safe middleware
function requirePermission(permission: Permission) {
return (req: Request, res: Response, next: Function) => {
if (!req.user || !rbac.hasPermission(req.user, permission)) {
return res.status(403).json({ error: 'Forbidden' });
}
next();
};
}
```
## Testing with TypeScript
### Type-Safe Tests
```typescript
import { describe, it, expect } from 'vitest';
import type { RBACUser } from '@fire-shield/core';
describe('RBAC', () => {
const admin: RBACUser = {
id: 'admin-1',
roles: ['admin']
};
const viewer: RBACUser = {
id: 'viewer-1',
roles: ['viewer']
};
it('should allow admin to delete', () => {
expect(rbac.hasPermission(admin, 'post:delete')).toBe(true);
});
it('should deny viewer to delete', () => {
expect(rbac.hasPermission(viewer, 'post:delete')).toBe(false);
});
});
```
## Next Steps
- Explore [Core API](/api/core)
- Learn about [TypeScript Types](/api/types)
- Check out [Performance Guide](/guide/performance)
========================================================================
# SECTION: API Reference
========================================================================
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/api/core
────────────────────────────────────────────────────────────────────────
# Core API Reference
Complete API reference for `@fire-shield/core`.
## RBAC Class
The main class for managing roles, permissions, and access control.
### Constructor
```typescript
new RBAC(options?: RBACOptions)
```
#### Parameters
- `options` (optional): Configuration options
- `config?: RBACConfigSchema` - Config-based initialization
- `preset?: PresetConfig` - Preset configuration
- `useBitSystem?: boolean` - Enable bit-level permission checking (default: true)
- `strictMode?: boolean` - Enable strict mode for bit permissions
- `auditLogger?: AuditLogger` - Custom audit logger
- `enableWildcards?: boolean` - Enable wildcard permission matching (default: true)
- `enableCache?: boolean` - Enable permission caching (default: false)
- `cacheOptions?: PermissionCacheOptions` - Cache configuration
- `lazyRoles?: boolean` - Enable lazy role evaluation (default: false)
- `optimizeMemory?: boolean` - Enable memory optimization (default: false)
#### Example
```typescript
import { RBAC, BufferedAuditLogger } from '@fire-shield/core'
// Basic usage
const rbac = new RBAC({
auditLogger: new BufferedAuditLogger(async (logs) => {
console.log('Audit logs:', logs)
}),
useBitSystem: true
})
// With performance features
const rbacOptimized = new RBAC({
enableCache: true,
cacheOptions: {
ttl: 60000, // 1 minute
maxSize: 10000
},
lazyRoles: true,
optimizeMemory: true
})
```
### Static Methods
#### fromJSONConfig
Create RBAC instance from JSON configuration.
```typescript
static fromJSONConfig(json: string, options?: RBACOptions): RBAC
```
**Parameters:**
- `json` - JSON string containing PresetConfig
- `options` - Additional RBAC options
**Returns:** New RBAC instance
**Example:**
```typescript
const configJson = JSON.stringify({
permissions: [
{ name: 'posts:read' },
{ name: 'posts:write' }
],
roles: [
{ name: 'editor', permissions: ['posts:read', 'posts:write'] }
]
})
const rbac = RBAC.fromJSONConfig(configJson, {
enableCache: true
})
```
#### validateConfig
Validate PresetConfig structure.
```typescript
static validateConfig(config: PresetConfig): void
```
**Throws:** Error if config is invalid
**Example:**
```typescript
try {
RBAC.validateConfig(myConfig)
console.log('Config is valid')
} catch (error) {
console.error('Invalid config:', error.message)
}
```
### Instance Methods
#### createRole
Create a new role with permissions.
```typescript
createRole(roleName: string, permissions: string[]): void
```
**Parameters:**
- `roleName` - Name of the role
- `permissions` - Array of permission strings
**Example:**
```typescript
rbac.createRole('admin', ['posts:*', 'users:*'])
rbac.createRole('editor', ['posts:read', 'posts:write'])
```
#### deleteRole
Delete a role.
```typescript
deleteRole(roleName: string): void
```
**Example:**
```typescript
rbac.deleteRole('editor')
```
#### grant
Grant additional permissions to an existing role.
```typescript
grant(roleName: string, permissions: string[]): void
```
**Example:**
```typescript
rbac.grant('editor', ['posts:delete'])
```
#### revoke
Revoke permissions from a role.
```typescript
revoke(roleName: string, permissions: string[]): void
```
**Example:**
```typescript
rbac.revoke('editor', ['posts:delete'])
```
#### hasPermission
Check if a user has a specific permission.
```typescript
hasPermission(user: RBACUser, permission: string): boolean
```
**Parameters:**
- `user` - User object with roles
- `permission` - Permission string to check
**Returns:** `true` if user has permission, `false` otherwise
**Example:**
```typescript
const user = { id: '1', roles: ['editor'] }
const canWrite = rbac.hasPermission(user, 'posts:write') // true
const canDelete = rbac.hasPermission(user, 'posts:delete') // false
```
#### setRoleHierarchy
Define role inheritance chains.
```typescript
setRoleHierarchy(hierarchy: Record): void
```
**Parameters:**
- `hierarchy` - Object mapping roles to their parent roles
**Example:**
```typescript
rbac.setRoleHierarchy({
admin: ['editor', 'moderator'],
editor: ['viewer'],
moderator: ['viewer']
})
```
#### getRolePermissions
Get all permissions for a role (including inherited).
```typescript
getRolePermissions(roleName: string): string[]
```
**Returns:** Array of permission strings
**Example:**
```typescript
const permissions = rbac.getRolePermissions('editor')
// ['posts:read', 'posts:write']
```
#### getUserPermissions
Get all permissions for a user (across all roles).
```typescript
getUserPermissions(user: RBACUser): string[]
```
**Returns:** Array of permission strings
**Example:**
```typescript
const user = { id: '1', roles: ['editor', 'moderator'] }
const permissions = rbac.getUserPermissions(user)
```
#### hasAnyPermission
Check if user has any of the specified permissions.
```typescript
hasAnyPermission(user: RBACUser, permissions: string[]): boolean
```
**Example:**
```typescript
const user = { id: '1', roles: ['editor'] }
const canEdit = rbac.hasAnyPermission(user, ['posts:write', 'posts:delete'])
```
#### hasAllPermissions
Check if user has all of the specified permissions.
```typescript
hasAllPermissions(user: RBACUser, permissions: string[]): boolean
```
**Example:**
```typescript
const user = { id: '1', roles: ['admin'] }
const hasFullAccess = rbac.hasAllPermissions(user, ['posts:read', 'posts:write', 'posts:delete'])
```
### Deny Permissions
Deny permissions allow you to explicitly revoke specific permissions for individual users, even if their roles grant them. Denies always take precedence over allows.
#### denyPermission
Deny a specific permission for a user.
```typescript
denyPermission(userId: string, permission: string): void
```
**Parameters:**
- `userId` - User ID to deny permission for
- `permission` - Permission to deny (supports wildcards)
**Example:**
```typescript
// Deny specific permission
rbac.denyPermission('user-123', 'posts:delete')
// Deny with wildcard
rbac.denyPermission('user-456', 'admin:*')
// User will now be denied even if their role grants the permission
const user = { id: 'user-123', roles: ['admin'] }
rbac.hasPermission(user, 'posts:delete') // false
```
#### allowPermission
Remove a denied permission for a user.
```typescript
allowPermission(userId: string, permission: string): void
```
**Example:**
```typescript
// Remove the deny
rbac.allowPermission('user-123', 'posts:delete')
// User can now use the permission again
rbac.hasPermission(user, 'posts:delete') // true (if role grants it)
```
#### getDeniedPermissions
Get all denied permissions for a user.
```typescript
getDeniedPermissions(userId: string): string[]
```
**Returns:** Array of denied permission strings
**Example:**
```typescript
const deniedPerms = rbac.getDeniedPermissions('user-123')
console.log(deniedPerms) // ['posts:delete', 'users:ban']
```
#### clearDeniedPermissions
Clear all denied permissions for a user.
```typescript
clearDeniedPermissions(userId: string): void
```
**Example:**
```typescript
rbac.clearDeniedPermissions('user-123')
// All denies removed, user permissions back to role-based
```
### Cache Management
When `enableCache: true` is set, permission checks are cached for better performance.
#### invalidateUserCache
Invalidate all cached permission checks for a specific user.
```typescript
invalidateUserCache(userId: string): void
```
**Example:**
```typescript
// User's roles changed, clear their cache
rbac.invalidateUserCache('user-123')
```
#### invalidatePermissionCache
Invalidate cached checks for a specific permission across all users.
```typescript
invalidatePermissionCache(permission: string): void
```
**Example:**
```typescript
// Permission definition changed, clear all caches for it
rbac.invalidatePermissionCache('posts:delete')
```
#### getCacheStats
Get cache statistics.
```typescript
getCacheStats(): CacheStats | undefined
```
**Returns:** Cache statistics or undefined if cache is disabled
**Example:**
```typescript
const stats = rbac.getCacheStats()
console.log(stats)
// {
// hits: 1250,
// misses: 50,
// hitRate: 0.96,
// size: 450,
// maxSize: 10000
// }
```
### Lazy Role Evaluation
When `lazyRoles: true` is set, roles are only evaluated when first accessed, reducing initial load time and memory usage.
#### getEvaluatedRoles
Get list of roles that have been evaluated.
```typescript
getEvaluatedRoles(): string[]
```
**Example:**
```typescript
const evaluated = rbac.getEvaluatedRoles()
console.log(evaluated) // ['admin', 'editor']
```
#### getPendingRoles
Get list of roles not yet evaluated.
```typescript
getPendingRoles(): string[]
```
**Example:**
```typescript
const pending = rbac.getPendingRoles()
console.log(pending) // ['viewer', 'guest', 'moderator']
```
#### getLazyRoleStats
Get lazy role evaluation statistics.
```typescript
getLazyRoleStats(): LazyRoleStats
```
**Returns:** Object with lazy role statistics
**Example:**
```typescript
const stats = rbac.getLazyRoleStats()
console.log(stats)
// {
// enabled: true,
// pending: 5,
// evaluated: 2,
// total: 7
// }
```
#### isRolePending
Check if a role is pending evaluation.
```typescript
isRolePending(roleName: string): boolean
```
**Example:**
```typescript
if (rbac.isRolePending('viewer')) {
console.log('Viewer role not yet loaded')
}
```
#### evaluateAllRoles
Force evaluation of all pending roles.
```typescript
evaluateAllRoles(): void
```
**Example:**
```typescript
// Load all roles immediately
rbac.evaluateAllRoles()
```
### Memory Optimization
When `optimizeMemory: true` is set, Fire Shield uses string interning and other techniques to reduce memory usage.
#### getMemoryStats
Get memory optimization statistics.
```typescript
getMemoryStats(): MemoryStats
```
**Returns:** Object with memory statistics
**Example:**
```typescript
const stats = rbac.getMemoryStats()
console.log(stats)
// {
// enabled: true,
// stringPoolSize: 150,
// roleMaskCacheSize: 25,
// wildcardPatternCacheSize: 10,
// estimatedMemorySaved: 45000 // bytes
// }
```
#### compactMemory
Compact memory by cleaning up unused resources.
```typescript
compactMemory(): { stringsRemoved: number; cacheEntriesRemoved: number }
```
**Returns:** Object with cleanup statistics
**Example:**
```typescript
const result = rbac.compactMemory()
console.log(`Removed ${result.stringsRemoved} strings and ${result.cacheEntriesRemoved} cache entries`)
```
## Types
### RBACUser
User object with role assignments.
```typescript
interface RBACUser {
id: string
roles: string[]
[key: string]: any // Additional user properties
}
```
**Example:**
```typescript
const user: RBACUser = {
id: 'user-123',
roles: ['editor', 'moderator'],
email: 'user@example.com',
name: 'John Doe'
}
```
### RBACOptions
Configuration options for RBAC instance.
```typescript
interface RBACOptions {
auditLogger?: AuditLogger
bitPermissions?: boolean
}
```
### AuditLogger
Interface for custom audit loggers.
```typescript
interface AuditLogger {
log(event: AuditEvent): void | Promise
}
```
### AuditEvent
Audit log event structure.
```typescript
interface AuditEvent {
timestamp: Date
userId: string
action: 'permission_check' | 'role_grant' | 'role_revoke'
resource: string
permission?: string
result: boolean
metadata?: Record
}
```
## Audit Logging
### BufferedAuditLogger
Built-in audit logger with buffering.
```typescript
new BufferedAuditLogger(
handler: (logs: AuditEvent[]) => Promise,
options?: BufferedAuditLoggerOptions
)
```
#### Parameters
- `handler` - Function to process buffered logs
- `options` (optional):
- `maxBufferSize?: number` - Max buffer size (default: 100)
- `flushIntervalMs?: number` - Flush interval (default: 5000)
#### Example
```typescript
import { BufferedAuditLogger } from '@fire-shield/core'
const auditLogger = new BufferedAuditLogger(
async (logs) => {
await saveLogsToDatabase(logs)
},
{
maxBufferSize: 50,
flushIntervalMs: 3000
}
)
const rbac = new RBAC({ auditLogger })
```
#### Methods
##### flush
Manually flush buffered logs.
```typescript
flush(): Promise
```
**Example:**
```typescript
await auditLogger.flush()
```
### Custom Audit Logger
Implement custom audit logger:
```typescript
class CustomAuditLogger implements AuditLogger {
async log(event: AuditEvent) {
console.log('Audit event:', event)
// Send to logging service
await fetch('/api/audit', {
method: 'POST',
body: JSON.stringify(event)
})
}
}
const rbac = new RBAC({
auditLogger: new CustomAuditLogger()
})
```
## RBAC Builder
Fluent API for building RBAC configurations.
```typescript
import { RBACBuilder } from '@fire-shield/core'
const rbac = new RBACBuilder()
.role('admin')
.grant(['posts:*', 'users:*'])
.role('editor')
.grant(['posts:read', 'posts:write'])
.role('viewer')
.grant(['posts:read'])
.hierarchy({
admin: ['editor'],
editor: ['viewer']
})
.build()
```
### Methods
#### role
Start defining a role.
```typescript
role(name: string): RBACBuilder
```
#### grant
Grant permissions to current role.
```typescript
grant(permissions: string[]): RBACBuilder
```
#### hierarchy
Set role hierarchy.
```typescript
hierarchy(hierarchy: Record): RBACBuilder
```
#### build
Build and return RBAC instance.
```typescript
build(): RBAC
```
## Utilities
### matchPermission
Check if permission matches pattern (including wildcards).
```typescript
import { matchPermission } from '@fire-shield/core'
matchPermission('posts:write', 'posts:*') // true
matchPermission('posts:write', 'posts:read') // false
matchPermission('admin:users:delete', 'admin:*') // true
```
### parsePermission
Parse permission string into parts.
```typescript
import { parsePermission } from '@fire-shield/core'
const parts = parsePermission('posts:write')
// { resource: 'posts', action: 'write' }
const nested = parsePermission('admin:users:delete')
// { resource: 'admin:users', action: 'delete' }
```
## Error Handling
### RBACError
Base error class for RBAC errors.
```typescript
class RBACError extends Error {
constructor(message: string, public code: string) {
super(message)
this.name = 'RBACError'
}
}
```
### Common Errors
```typescript
// Permission denied
throw new RBACError('Insufficient permissions', 'PERMISSION_DENIED')
// Role not found
throw new RBACError('Role does not exist', 'ROLE_NOT_FOUND')
// Invalid permission format
throw new RBACError('Invalid permission format', 'INVALID_PERMISSION')
```
## Performance
Fire Shield includes several performance optimizations for large-scale applications.
### Bit-Level Permissions
Enable bit-level permission checking for better performance:
```typescript
const rbac = new RBAC({ useBitSystem: true }) // Default: true
// Permissions are stored as bits
// Much faster for large permission sets
rbac.createRole('admin', ['posts:*'])
const user = { id: '1', roles: ['admin'] }
rbac.hasPermission(user, 'posts:write') // Optimized bit check
```
### Permission Caching
Fire Shield includes explicit permission caching with TTL and size limits:
```typescript
const rbac = new RBAC({
enableCache: true,
cacheOptions: {
ttl: 60000, // Cache for 1 minute
maxSize: 10000, // Max 10k entries
cleanupInterval: 30000 // Cleanup every 30 seconds
}
})
// First call - computes and caches
rbac.hasPermission(user, 'posts:write')
// Subsequent calls - served from cache (very fast)
rbac.hasPermission(user, 'posts:write') // < 1ms
// Monitor cache performance
const stats = rbac.getCacheStats()
console.log(`Hit rate: ${stats.hitRate * 100}%`)
```
### Lazy Role Evaluation
Fire Shield supports lazy role evaluation for faster startup:
```typescript
const rbac = new RBAC({
lazyRoles: true,
config: largeConfig // Config with 1000+ roles
})
// Only loads roles when first accessed
const stats = rbac.getLazyRoleStats()
console.log(`Loaded: ${stats.evaluated}/${stats.total} roles`)
// Force load all roles when needed
rbac.evaluateAllRoles()
```
### Memory Optimization
Fire Shield includes memory optimization through string interning:
```typescript
const rbac = new RBAC({
optimizeMemory: true,
config: largeConfig
})
// Monitor memory savings
const stats = rbac.getMemoryStats()
console.log(`Memory saved: ${stats.estimatedMemorySaved} bytes`)
console.log(`String pool: ${stats.stringPoolSize} unique strings`)
// Cleanup unused resources
const result = rbac.compactMemory()
console.log(`Cleaned up ${result.stringsRemoved} strings`)
```
### Performance Best Practices
For optimal performance in production:
```typescript
const rbac = new RBAC({
useBitSystem: true, // Fast bit-based checks
enableCache: true, // Cache permission checks
cacheOptions: {
ttl: 300000, // 5 minute cache
maxSize: 50000 // Large cache for many users
},
lazyRoles: true, // Load roles on demand
optimizeMemory: true, // Reduce memory footprint
enableWildcards: true // Support flexible permissions
})
// Clear cache when roles change
rbac.createRole('newRole', ['posts:*'])
rbac.invalidatePermissionCache('posts:write')
// Monitor performance
setInterval(() => {
const cacheStats = rbac.getCacheStats()
const memoryStats = rbac.getMemoryStats()
console.log('Cache hit rate:', cacheStats.hitRate)
console.log('Memory saved:', memoryStats.estimatedMemorySaved)
}, 60000)
```
## Next Steps
- Learn about [Permissions](/guide/permissions)
- Understand [Deny Permissions](/guide/deny-permissions)
- Explore [Framework Integrations](/frameworks/vue)
- Use [CLI Tool](/frameworks/cli) for config validation
- Integrate with [AI Agents via MCP](/frameworks/mcp)
- Check out [Examples](/examples/basic-usage)
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/api/builder
────────────────────────────────────────────────────────────────────────
# RBAC Builder
Fluent API for building RBAC configurations with a chainable interface.
## Overview
RBACBuilder provides a convenient way to construct RBAC instances with a fluent, chainable API that makes configuration more readable and maintainable.
## Basic Usage
```typescript
import { RBACBuilder } from '@fire-shield/core';
const rbac = new RBACBuilder()
.useBitSystem()
.addPermission('user:read', 1)
.addPermission('user:write', 2)
.addPermission('user:delete', 4)
.addRole('user', ['user:read'], { level: 1 })
.addRole('admin', ['user:read', 'user:write', 'user:delete'], { level: 10 })
.build();
```
## API Reference
### Constructor
```typescript
new RBACBuilder()
```
Creates a new RBAC builder instance.
**Example:**
```typescript
const builder = new RBACBuilder();
```
### useBitSystem()
Enable bit-based permission system (default).
```typescript
useBitSystem(): RBACBuilder
```
**Returns:** The builder instance for chaining
**Example:**
```typescript
const rbac = new RBACBuilder()
.useBitSystem()
.build();
```
### useLegacySystem()
Use string-based permission system instead of bit-based.
```typescript
useLegacySystem(): RBACBuilder
```
**Returns:** The builder instance for chaining
**Example:**
```typescript
const rbac = new RBACBuilder()
.useLegacySystem()
.build();
```
**When to use:**
- Need more than 31 permissions
- Permissions change frequently
- Debugging/development
### withPreset(preset)
Load from a preset configuration.
```typescript
withPreset(preset: PresetConfig): RBACBuilder
```
**Parameters:**
- `preset` - Preset configuration object
**Returns:** The builder instance for chaining
**Example 1: Using Built-in Preset**
```typescript
import { defaultPreset } from '@fire-shield/core';
const rbac = new RBACBuilder()
.withPreset(defaultPreset)
.build();
```
**Example 2: Loading from JSON Config File**
```typescript
import fs from 'fs';
import { RBACBuilder } from '@fire-shield/core';
// Read config file
const configFile = fs.readFileSync('./rbac.config.json', 'utf-8');
const config = JSON.parse(configFile);
// Build RBAC from config
const rbac = new RBACBuilder()
.withPreset(config)
.build();
```
**Example 3: Async File Loading**
```typescript
import { promises as fs } from 'fs';
import { RBACBuilder } from '@fire-shield/core';
async function loadRBAC() {
const configFile = await fs.readFile('./rbac.config.json', 'utf-8');
const config = JSON.parse(configFile);
return new RBACBuilder()
.withPreset(config)
.build();
}
const rbac = await loadRBAC();
```
**Example Config File (rbac.config.json):**
```json
{
"name": "my-app-rbac",
"version": "1.0.0",
"permissions": [
{
"name": "user:read",
"bit": 1,
"resource": "user",
"action": "read",
"description": "Read user data"
},
{
"name": "user:write",
"bit": 2,
"resource": "user",
"action": "write",
"description": "Create/update users"
},
{
"name": "post:read",
"bit": 4,
"resource": "post",
"action": "read"
},
{
"name": "post:write",
"bit": 8,
"resource": "post",
"action": "write"
}
],
"roles": [
{
"name": "admin",
"permissions": ["user:read", "user:write", "post:read", "post:write"],
"level": 10,
"description": "Administrator with full access"
},
{
"name": "editor",
"permissions": ["post:read", "post:write"],
"level": 5,
"description": "Content editor"
},
{
"name": "viewer",
"permissions": ["user:read", "post:read"],
"level": 1,
"description": "Read-only access"
}
],
"options": {
"autoBitAssignment": true,
"startBitValue": 1
}
}
```
**Benefits of Config Files:**
- ✅ Separate configuration from code
- ✅ Easy to version control
- ✅ Share configs across team
- ✅ Hot reload in development
- ✅ Validate before loading
### addPermission(name, bit?, options?)
Add a permission to the system.
```typescript
addPermission(
name: string,
bit?: number,
options?: {
resource?: string;
action?: string;
description?: string;
metadata?: Record;
}
): RBACBuilder
```
**Parameters:**
- `name` - Permission name (e.g., 'user:read')
- `bit` - Optional manual bit value (must be power of 2)
- `options` - Optional metadata
**Returns:** The builder instance for chaining
**Example:**
```typescript
const rbac = new RBACBuilder()
.addPermission('user:read', 1, {
resource: 'user',
action: 'read',
description: 'Read user information'
})
.addPermission('user:write', 2, {
resource: 'user',
action: 'write',
description: 'Write user information'
})
.build();
```
### addRole(name, permissions, options?)
Add a role with permissions.
```typescript
addRole(
name: string,
permissions: string[],
options?: {
level?: number;
description?: string;
metadata?: Record;
}
): RBACBuilder
```
**Parameters:**
- `name` - Role name
- `permissions` - Array of permission names
- `options` - Optional metadata
**Returns:** The builder instance for chaining
**Example:**
```typescript
const rbac = new RBACBuilder()
.addRole('admin', ['user:*', 'post:*'], {
level: 10,
description: 'System administrator'
})
.addRole('editor', ['post:read', 'post:write'], {
level: 5,
description: 'Content editor'
})
.build();
```
### enableWildcards(enabled?)
Enable or disable wildcard permission matching.
```typescript
enableWildcards(enabled: boolean = true): RBACBuilder
```
**Parameters:**
- `enabled` - Whether to enable wildcards (default: true)
**Returns:** The builder instance for chaining
**Example:**
```typescript
const rbac = new RBACBuilder()
.enableWildcards(true)
.addRole('admin', ['*'])
.build();
```
### withAuditLogger(logger)
Add an audit logger to the RBAC instance.
```typescript
withAuditLogger(logger: AuditLogger): RBACBuilder
```
**Parameters:**
- `logger` - Audit logger instance
**Returns:** The builder instance for chaining
**Example:**
```typescript
import { ConsoleAuditLogger } from '@fire-shield/core';
const rbac = new RBACBuilder()
.withAuditLogger(new ConsoleAuditLogger())
.build();
```
### build()
Build and return the RBAC instance.
```typescript
build(): RBAC
```
**Returns:** Configured RBAC instance
**Example:**
```typescript
const rbac = new RBACBuilder()
.addRole('user', ['post:read'])
.build();
```
## Complete Examples
### Blog System
```typescript
import { RBACBuilder } from '@fire-shield/core';
const rbac = new RBACBuilder()
.useBitSystem()
// Add permissions
.addPermission('post:read', 1)
.addPermission('post:write', 2)
.addPermission('post:delete', 4)
.addPermission('post:publish', 8)
.addPermission('comment:read', 16)
.addPermission('comment:write', 32)
.addPermission('comment:moderate', 64)
// Add roles
.addRole('viewer', ['post:read', 'comment:read'], {
level: 1,
description: 'Can only view content'
})
.addRole('author', ['post:read', 'post:write', 'comment:read', 'comment:write'], {
level: 5,
description: 'Can create and edit own posts'
})
.addRole('editor', ['post:*', 'comment:*'], {
level: 8,
description: 'Can manage all posts and comments'
})
.addRole('admin', ['*'], {
level: 10,
description: 'Full system access'
})
.build();
```
### E-Commerce System
```typescript
import { RBACBuilder, BufferedAuditLogger } from '@fire-shield/core';
const auditLogger = new BufferedAuditLogger(async (logs) => {
await database.auditLogs.insertMany(logs);
});
const rbac = new RBACBuilder()
.useBitSystem()
.withAuditLogger(auditLogger)
// Customer permissions
.addPermission('product:view', 1)
.addPermission('cart:manage', 2)
.addPermission('order:create', 4)
.addPermission('order:view:own', 8)
// Admin permissions
.addPermission('product:manage', 16)
.addPermission('order:view:all', 32)
.addPermission('order:update', 64)
.addPermission('inventory:manage', 128)
// Roles
.addRole('customer', ['product:view', 'cart:manage', 'order:create', 'order:view:own'], {
level: 1
})
.addRole('manager', ['product:manage', 'order:view:all', 'order:update', 'inventory:manage'], {
level: 5
})
.addRole('admin', ['*'], {
level: 10
})
.build();
```
### Multi-Tenant SaaS
```typescript
import { RBACBuilder } from '@fire-shield/core';
const rbac = new RBACBuilder()
.useBitSystem()
.enableWildcards(true)
// Workspace permissions
.addPermission('workspace:read')
.addPermission('workspace:update')
.addPermission('workspace:delete')
.addPermission('workspace:invite')
.addPermission('data:read')
.addPermission('data:write')
.addPermission('billing:view')
.addPermission('billing:update')
// Roles
.addRole('workspace-guest', ['workspace:read', 'data:read'], {
level: 1,
description: 'Read-only guest access'
})
.addRole('workspace-member', ['workspace:read', 'data:*'], {
level: 3,
description: 'Regular team member'
})
.addRole('workspace-admin', ['workspace:*', 'data:*', 'workspace:invite'], {
level: 7,
description: 'Workspace administrator'
})
.addRole('workspace-owner', ['*'], {
level: 10,
description: 'Workspace owner with full access'
})
.build();
```
## Method Chaining
All builder methods return the builder instance, allowing you to chain calls:
```typescript
const rbac = new RBACBuilder()
.useBitSystem() // 1. Choose system
.enableWildcards(true) // 2. Enable wildcards
.withAuditLogger(logger) // 3. Add audit logging
.addPermission('user:read', 1) // 4. Add permissions
.addPermission('user:write', 2)
.addRole('user', ['user:read']) // 5. Add roles
.addRole('admin', ['*'])
.build(); // 6. Build RBAC instance
```
## TypeScript Support
Full TypeScript support with type inference:
```typescript
import { RBACBuilder, type RBACUser } from '@fire-shield/core';
const rbac = new RBACBuilder()
.addRole('admin', ['user:*'])
.build();
const user: RBACUser = {
id: 'user-1',
roles: ['admin']
};
rbac.hasPermission(user, 'user:read'); // Type-safe
```
## Best Practices
### 1. Group Related Configuration
```typescript
// ✅ Good: Logical grouping
const rbac = new RBACBuilder()
// System configuration
.useBitSystem()
.enableWildcards(true)
// Permissions
.addPermission('user:read', 1)
.addPermission('user:write', 2)
// Roles
.addRole('user', ['user:read'])
.addRole('admin', ['*'])
.build();
```
### 2. Use Descriptive Options
```typescript
// ✅ Good: Include descriptions
const rbac = new RBACBuilder()
.addRole('moderator', ['comment:moderate', 'post:flag'], {
level: 6,
description: 'Community moderator with content moderation powers',
metadata: {
department: 'Community',
maxActions: 100
}
})
.build();
```
### 3. Separate Configuration
```typescript
// config/rbac.ts
import { RBACBuilder } from '@fire-shield/core';
import { auditLogger } from './audit';
export function createRBAC() {
return new RBACBuilder()
.withAuditLogger(auditLogger)
.addPermission('user:read', 1)
.addPermission('user:write', 2)
.addRole('user', ['user:read'])
.addRole('admin', ['*'])
.build();
}
```
## Next Steps
- Learn about [Audit Logging](/api/audit)
- Explore [TypeScript Types](/api/types)
- Check out [Core API](/api/core)
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/api/audit
────────────────────────────────────────────────────────────────────────
# Audit Logging
Comprehensive audit logging system for tracking permission checks, authorization events, and compliance.
## Overview
Fire Shield provides built-in audit logging to track all permission checks, helping with:
- **Security**: Track unauthorized access attempts
- **Compliance**: GDPR, SOC2, HIPAA requirements
- **Debugging**: Find permission logic errors
- **Analytics**: Understand user behavior patterns
## Audit Loggers
### ConsoleAuditLogger
Logs events to console (ideal for development).
```typescript
import { RBAC, ConsoleAuditLogger } from '@fire-shield/core';
const rbac = new RBAC({
auditLogger: new ConsoleAuditLogger()
});
```
**Output:**
```
[AUDIT 2025-01-15T10:30:00.000Z] ✓ ALLOWED: User user-123 - post:read
[AUDIT 2025-01-15T10:30:01.000Z] ✗ DENIED: User user-123 - admin:delete
Reason: User lacks permission: admin:delete
```
### BufferedAuditLogger
Buffers events and flushes in batches (recommended for production).
```typescript
import { BufferedAuditLogger } from '@fire-shield/core';
const logger = new BufferedAuditLogger(
async (events) => {
// Save to database
await db.auditLogs.insertMany(events);
},
{
maxBufferSize: 100, // Flush after 100 events
flushIntervalMs: 5000 // Or every 5 seconds
}
);
const rbac = new RBAC({ auditLogger: logger });
```
**Options:**
```typescript
interface BufferedAuditLoggerOptions {
maxBufferSize?: number; // Default: 100
flushIntervalMs?: number; // Default: 5000
}
```
### MultiAuditLogger
Log to multiple destinations simultaneously.
```typescript
import { MultiAuditLogger, ConsoleAuditLogger, BufferedAuditLogger } from '@fire-shield/core';
const logger = new MultiAuditLogger([
new ConsoleAuditLogger(),
new BufferedAuditLogger(async (events) => {
await db.auditLogs.insertMany(events);
})
]);
const rbac = new RBAC({ auditLogger: logger });
```
## Audit Event Structure
```typescript
interface AuditEvent {
// Event type
type: 'permission_check' | 'authorization' | 'role_check';
// User information
userId: string;
// Permission being checked
permission: string;
// Result
allowed: boolean;
// Reason for denial (if denied)
reason?: string;
// Additional context
context?: {
roles?: string[];
ip?: string;
userAgent?: string;
resource?: string;
action?: string;
metadata?: Record;
};
// Timestamp (milliseconds since epoch)
timestamp: number;
}
```
**Example:**
```typescript
{
type: 'permission_check',
userId: 'user-123',
permission: 'post:write',
allowed: false,
reason: 'User lacks permission: post:write',
context: {
roles: ['viewer'],
ip: '192.168.1.1',
userAgent: 'Mozilla/5.0...'
},
timestamp: 1642345678901
}
```
## Custom Audit Logger
Implement your own audit logger:
```typescript
import type { AuditLogger, AuditEvent } from '@fire-shield/core';
class DatabaseAuditLogger implements AuditLogger {
async log(event: AuditEvent): Promise {
await database.auditLogs.insert({
type: event.type,
userId: event.userId,
permission: event.permission,
allowed: event.allowed,
reason: event.reason,
context: event.context,
createdAt: new Date(event.timestamp)
});
}
}
const rbac = new RBAC({
auditLogger: new DatabaseAuditLogger()
});
```
## Real-World Examples
### Security Monitoring
Track failed authorization attempts and alert on suspicious activity:
```typescript
class SecurityMonitorLogger implements AuditLogger {
private failedAttempts = new Map();
log(event: AuditEvent): void {
if (!event.allowed) {
// Track failed attempts
const count = (this.failedAttempts.get(event.userId) || 0) + 1;
this.failedAttempts.set(event.userId, count);
// Alert after 5 failed attempts
if (count >= 5) {
this.alertSecurityTeam({
userId: event.userId,
failedAttempts: count,
lastPermission: event.permission,
timestamp: event.timestamp
});
}
} else {
// Reset on successful check
this.failedAttempts.delete(event.userId);
}
}
private alertSecurityTeam(alert: any) {
console.warn('⚠️ Security Alert:', alert);
// Send to monitoring service
}
}
```
### Compliance Logging
Store audit logs for compliance (GDPR, HIPAA, SOC2):
```typescript
class ComplianceLogger implements AuditLogger {
async log(event: AuditEvent): Promise {
// Store with encryption
await database.auditLogs.insert({
...event,
encrypted: true,
retentionPeriod: '7years', // Compliance requirement
compliance: {
gdpr: true,
hipaa: event.permission.includes('medical'),
soc2: true
}
});
// Also send to compliance monitoring service
await fetch('https://compliance.example.com/audit', {
method: 'POST',
body: JSON.stringify(event)
});
}
}
```
### Analytics Logger
Track permission usage patterns:
```typescript
class AnalyticsLogger implements AuditLogger {
private analytics = new Map();
log(event: AuditEvent): void {
// Track permission usage
const key = `${event.permission}:${event.allowed ? 'allowed' : 'denied'}`;
const count = (this.analytics.get(key) || 0) + 1;
this.analytics.set(key, count);
// Send to analytics service every 100 events
if (this.getTotalCount() % 100 === 0) {
this.sendAnalytics();
}
}
private getTotalCount(): number {
return Array.from(this.analytics.values()).reduce((a, b) => a + b, 0);
}
private sendAnalytics() {
const stats = Object.fromEntries(this.analytics);
console.log('📊 Permission Analytics:', stats);
}
}
```
### Database Logger with Rotation
Store logs in database with automatic rotation:
```typescript
class RotatingDatabaseLogger implements AuditLogger {
private buffer: AuditEvent[] = [];
private readonly maxAge = 90 * 24 * 60 * 60 * 1000; // 90 days
async log(event: AuditEvent): Promise {
this.buffer.push(event);
// Flush every 50 events
if (this.buffer.length >= 50) {
await this.flush();
}
}
async flush(): Promise {
if (this.buffer.length === 0) return;
// Insert new logs
await db.auditLogs.insertMany(this.buffer);
this.buffer = [];
// Delete old logs
const cutoff = Date.now() - this.maxAge;
await db.auditLogs.deleteMany({
timestamp: { $lt: cutoff }
});
}
}
```
## Querying Audit Logs
### Filter by User
```typescript
const userLogs = await db.auditLogs.find({
userId: 'user-123'
}).sort({ timestamp: -1 }).limit(100);
```
### Filter by Permission
```typescript
const permissionLogs = await db.auditLogs.find({
permission: 'admin:delete'
}).sort({ timestamp: -1 });
```
### Failed Attempts
```typescript
const failedAttempts = await db.auditLogs.find({
allowed: false
}).sort({ timestamp: -1 });
```
### Time Range
```typescript
const recentLogs = await db.auditLogs.find({
timestamp: {
$gte: Date.now() - 24 * 60 * 60 * 1000 // Last 24 hours
}
});
```
## Performance Considerations
### Buffering
Always use BufferedAuditLogger in production:
```typescript
// ✅ Good: Buffered for performance
const logger = new BufferedAuditLogger(async (events) => {
await db.auditLogs.insertMany(events);
}, { maxBufferSize: 100 });
// ❌ Avoid: Synchronous logging on every check
const logger = {
log: (event) => db.auditLogs.insert(event) // Blocks on every check!
};
```
### Async Logging
Make logging operations async:
```typescript
class AsyncLogger implements AuditLogger {
async log(event: AuditEvent): Promise {
// Don't await - fire and forget
this.saveToDatabase(event).catch(err => {
console.error('Failed to save audit log:', err);
});
}
private async saveToDatabase(event: AuditEvent) {
await db.auditLogs.insert(event);
}
}
```
### Sampling
For high-traffic applications, sample logs:
```typescript
class SamplingLogger implements AuditLogger {
private sampleRate = 0.1; // Log 10% of events
log(event: AuditEvent): void {
// Always log denied events
if (!event.allowed) {
this.saveLog(event);
return;
}
// Sample allowed events
if (Math.random() < this.sampleRate) {
this.saveLog(event);
}
}
private saveLog(event: AuditEvent) {
// Save to database
}
}
```
## Best Practices
### 1. Use Buffered Logging in Production
```typescript
// ✅ Good: Buffered logging
const logger = new BufferedAuditLogger(
async (events) => await db.auditLogs.insertMany(events),
{ maxBufferSize: 100, flushIntervalMs: 5000 }
);
```
### 2. Include Context
```typescript
// ✅ Good: Rich context
const result = rbac.authorize(user, 'admin:delete', {
ip: request.ip,
userAgent: request.headers['user-agent'],
resource: 'user',
resourceId: userId
});
```
### 3. Rotate Old Logs
```typescript
// Scheduled job to delete old logs
setInterval(async () => {
const cutoff = Date.now() - 90 * 24 * 60 * 60 * 1000; // 90 days
await db.auditLogs.deleteMany({ timestamp: { $lt: cutoff } });
}, 24 * 60 * 60 * 1000); // Run daily
```
### 4. Monitor Failed Attempts
```typescript
// Alert on repeated failures
const failures = await db.auditLogs.countDocuments({
userId: user.id,
allowed: false,
timestamp: { $gte: Date.now() - 60 * 60 * 1000 } // Last hour
});
if (failures > 10) {
await alertSecurityTeam(user.id);
}
```
## Next Steps
- Learn about [Core API](/api/core)
- Explore [TypeScript Types](/api/types)
- Check out [Performance Guide](/guide/performance)
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/api/types
────────────────────────────────────────────────────────────────────────
# TypeScript Types
Complete TypeScript type definitions for Fire Shield RBAC library.
## Core Types
### IRBAC
**v3.0.0** - Core interface for RBAC implementations. Enables polymorphic usage of RBAC and RBACAggregator.
```typescript
interface IRBAC {
/**
* Register a new permission
*/
registerPermission(permissionName: string): void;
/**
* Create a new role with permissions
*/
createRole(roleName: string, permissions: string[]): void;
/**
* Check if user has a specific permission
*/
hasPermission(user: RBACUser, permission: string): boolean;
/**
* Check if user has all specified permissions
*/
hasAllPermissions(user: RBACUser, permissions: string[]): boolean;
/**
* Check if user has any of the specified permissions
*/
hasAnyPermission(user: RBACUser, permissions: string[]): boolean;
/**
* Authorize user with detailed result
*/
authorize(user: RBACUser, permission: string): AuthorizationResult;
/**
* Grant permission to role
*/
grantPermission(roleName: string, permission: string): void;
/**
* Revoke permission from role
*/
revokePermission(roleName: string, permission: string): void;
/**
* Get all registered permissions
*/
getPermissions(): string[];
/**
* Get all registered roles
*/
getRoles(): string[];
/**
* Get all permissions for a user
*/
getUserPermissions(user: RBACUser): string[];
/**
* Deny permission for user
*/
denyPermission(userId: string, permission: string): void;
/**
* Remove denied permission for user
*/
allowPermission(userId: string, permission: string): void;
/**
* Get denied permissions for user
*/
getDeniedPermissions(userId: string): string[];
}
```
**Purpose:** The `IRBAC` interface defines the contract that all RBAC implementations must follow. It enables polymorphic usage, allowing you to use `RBAC` and `RBACAggregator` interchangeably.
**Implementations:**
- `RBAC` - Standard RBAC implementation
- `RBACAggregator` - Multi-domain RBAC aggregator
**Example - Polymorphic Usage:**
```typescript
import { RBAC, RBACAggregator, type IRBAC } from '@fire-shield/core';
function setupPermissions(instance: IRBAC) {
instance.registerPermission('posts:read');
instance.registerPermission('posts:write');
instance.createRole('editor', ['posts:read', 'posts:write']);
}
// Works with RBAC
const rbac = new RBAC();
setupPermissions(rbac);
// Also works with RBACAggregator
const aggregator = new RBACAggregator();
aggregator.addInstance('default', new RBAC());
setupPermissions(aggregator); // ✅ Polymorphic!
```
**Example - Framework Adaptor Integration:**
```typescript
import { type IRBAC } from '@fire-shield/core';
import { RBACProvider } from '@fire-shield/react';
// Accept any IRBAC implementation
function createRBACAdapter(rbacInstance: IRBAC) {
return (
);
}
// Can use RBAC or RBACAggregator
const rbac = new RBAC();
const aggregator = new RBACAggregator();
createRBACAdapter(rbac); // ✅ Works
createRBACAdapter(aggregator); // ✅ Also works
```
### RBACUser
Represents a user in the RBAC system.
```typescript
interface RBACUser {
/**
* Unique identifier for the user
*/
id: string;
/**
* Array of role names assigned to the user
*/
roles: string[];
/**
* Optional direct permissions (additive to role permissions)
*/
permissions?: string[];
/**
* Optional permission bitmask (for bit-based system)
*/
permissionMask?: number;
}
```
**Example:**
```typescript
const user: RBACUser = {
id: 'user-123',
roles: ['editor', 'moderator'],
permissions: ['beta:feature'],
permissionMask: 127
};
```
### AuthorizationResult
Result of an authorization check with detailed information.
```typescript
interface AuthorizationResult {
/**
* Whether the permission is allowed
*/
allowed: boolean;
/**
* Reason for denial (only present when allowed = false)
*/
reason?: string;
/**
* The user object that was checked
*/
user?: RBACUser;
}
```
**Example:**
```typescript
const result: AuthorizationResult = rbac.authorize(user, 'admin:delete');
if (!result.allowed) {
console.log(result.reason); // "User lacks permission: admin:delete"
}
```
### AuthorizationContext
Context for authorization with additional metadata.
```typescript
interface AuthorizationContext {
/**
* User to check authorization for
*/
user: RBACUser;
/**
* Resource being accessed
*/
resource: string;
/**
* Action being performed
*/
action: string;
/**
* Optional additional context
*/
metadata?: Record<string, any>;
}
```
**Example:**
```typescript
const context: AuthorizationContext = {
user: currentUser,
resource: 'document',
action: 'edit',
metadata: {
documentId: 'doc-123',
ownerId: 'user-456'
}
};
const result = rbac.authorizeWithContext(context);
```
## Configuration Types
### RBACConfig
Main configuration object for RBAC instance.
```typescript
interface RBACConfig {
/**
* Use bit-based permission system
* @default true
*/
useBitSystem?: boolean;
/**
* Enable strict mode (throws errors on invalid operations)
* @default false
*/
strictMode?: boolean;
/**
* Enable wildcard permission matching
* @default true
*/
enableWildcards?: boolean;
/**
* Preset configuration to load
*/
preset?: PresetConfig;
/**
* Configuration schema
*/
config?: RBACConfigSchema;
/**
* Optional audit logger
*/
auditLogger?: AuditLogger;
}
```
**Example:**
```typescript
const config: RBACConfig = {
useBitSystem: true,
strictMode: true,
enableWildcards: true,
auditLogger: new ConsoleAuditLogger()
};
const rbac = new RBAC(config);
```
### RBACConfigSchema
Schema for defining permissions and roles.
```typescript
interface RBACConfigSchema {
/**
* Permission definitions
*/
permissions: Array<{
name: string;
bit?: number;
resource?: string;
action?: string;
description?: string;
metadata?: Record<string, any>;
}>;
/**
* Role definitions
*/
roles: Array<{
name: string;
permissions: string[];
level?: number;
description?: string;
metadata?: Record<string, any>;
}>;
/**
* Optional configuration options
*/
options?: {
autoBitAssignment?: boolean;
validatePermissions?: boolean;
};
}
```
**Example:**
```typescript
const schema: RBACConfigSchema = {
permissions: [
{ name: 'user:read', bit: 1, resource: 'user', action: 'read' },
{ name: 'user:write', bit: 2, resource: 'user', action: 'write' }
],
roles: [
{
name: 'admin',
permissions: ['user:read', 'user:write'],
level: 10,
description: 'Administrator role'
}
]
};
```
### PresetConfig
Preset configuration with permissions and roles.
```typescript
interface PresetConfig {
/**
* Preset name
*/
name: string;
/**
* Preset description
*/
description?: string;
/**
* Permission definitions
*/
permissions: Array<{
name: string;
bit?: number;
resource?: string;
action?: string;
}>;
/**
* Role definitions
*/
roles: Array<{
name: string;
permissions: string[];
level?: number;
}>;
/**
* Configuration options
*/
options?: {
autoBitAssignment?: boolean;
};
}
```
## Audit Types
### AuditEvent
Event logged during permission checks.
```typescript
interface AuditEvent {
/**
* Type of event
*/
type: 'permission_check' | 'authorization' | 'role_check';
/**
* User ID that triggered the event
*/
userId: string;
/**
* Permission being checked
*/
permission: string;
/**
* Whether permission was allowed
*/
allowed: boolean;
/**
* Reason for denial (if denied)
*/
reason?: string;
/**
* Additional context
*/
context?: AuditEventContext;
/**
* Timestamp (milliseconds since epoch)
*/
timestamp: number;
}
```
### AuditEventContext
Additional context for audit events.
```typescript
interface AuditEventContext {
/**
* User roles at time of check
*/
roles?: string[];
/**
* IP address of request
*/
ip?: string;
/**
* User agent string
*/
userAgent?: string;
/**
* Resource being accessed
*/
resource?: string;
/**
* Action being performed
*/
action?: string;
/**
* Additional metadata
*/
metadata?: Record<string, any>;
}
```
### AuditLogger
Interface for audit logging implementations.
```typescript
interface AuditLogger {
/**
* Log an audit event
* Can be sync or async
*/
log(event: AuditEvent): void | Promise<void>;
/**
* Optional flush method for buffered loggers
*/
flush?(): void | Promise<void>;
}
```
**Example:**
```typescript
class CustomAuditLogger implements AuditLogger {
log(event: AuditEvent): void {
console.log(`[AUDIT] ${event.userId} - ${event.permission}: ${event.allowed}`);
}
flush(): void {
// Flush buffered events
}
}
```
## Role Types
### UserRole
Represents a role with permissions and metadata.
```typescript
interface UserRole {
/**
* Role name
*/
name: string;
/**
* Permission names assigned to this role
*/
permissions: string[];
/**
* Permission bitmask (bit-based system only)
*/
permissionMask?: number;
/**
* Optional role description
*/
description?: string;
/**
* Optional metadata
*/
metadata?: Record<string, any>;
}
```
### PermissionMask
Type alias for permission bitmask.
```typescript
type PermissionMask = number;
```
**Usage:**
```typescript
const readMask: PermissionMask = 1; // 2^0
const writeMask: PermissionMask = 2; // 2^1
const combinedMask: PermissionMask = readMask | writeMask; // 3
```
## Permission Types
### PermissionDefinition
Definition for a permission.
```typescript
interface PermissionDefinition {
/**
* Permission name
*/
name: string;
/**
* Optional manual bit value (must be power of 2)
*/
bit?: number;
/**
* Optional resource name
*/
resource?: string;
/**
* Optional action name
*/
action?: string;
/**
* Optional description
*/
description?: string;
/**
* Optional metadata
*/
metadata?: Record<string, any>;
}
```
### RoleDefinition
Definition for a role.
```typescript
interface RoleDefinition {
/**
* Role name
*/
name: string;
/**
* Permission names
*/
permissions: string[];
/**
* Optional hierarchy level
*/
level?: number;
/**
* Optional description
*/
description?: string;
/**
* Optional metadata
*/
metadata?: Record<string, any>;
}
```
## State Types
### RBACSystemState
Serialized state of RBAC system.
```typescript
interface RBACSystemState {
/**
* Bit-based system enabled
*/
useBitSystem: boolean;
/**
* Wildcards enabled
*/
enableWildcards: boolean;
/**
* All registered permissions
*/
permissions: Array<{
name: string;
bit?: number;
}>;
/**
* All registered roles
*/
roles: Array<{
name: string;
permissions: string[];
permissionMask?: number;
}>;
/**
* Role hierarchy levels
*/
hierarchy: Record<string, number>;
/**
* Denied permissions by user ID
*/
denyList: Record<string, string[]>;
}
```
**Example:**
```typescript
// Serialize
const state: RBACSystemState = rbac.serialize();
// Save to storage
localStorage.setItem('rbac-state', JSON.stringify(state));
// Restore
const savedState = JSON.parse(localStorage.getItem('rbac-state')!);
rbac.deserialize(savedState);
```
## Type Guards
Utility functions for type checking.
### isRBACUser
```typescript
function isRBACUser(obj: any): obj is RBACUser {
return (
typeof obj === 'object' &&
typeof obj.id === 'string' &&
Array.isArray(obj.roles)
);
}
```
**Usage:**
```typescript
if (isRBACUser(maybeUser)) {
// TypeScript knows this is an RBACUser
rbac.hasPermission(maybeUser, 'post:read');
}
```
### isAuditEvent
```typescript
function isAuditEvent(obj: any): obj is AuditEvent {
return (
typeof obj === 'object' &&
typeof obj.type === 'string' &&
typeof obj.userId === 'string' &&
typeof obj.permission === 'string' &&
typeof obj.allowed === 'boolean' &&
typeof obj.timestamp === 'number'
);
}
```
## Generic Types
### WithMetadata<T>
Add metadata to any type.
```typescript
type WithMetadata<T> = T & {
metadata?: Record<string, any>;
};
```
**Example:**
```typescript
type UserWithMetadata = WithMetadata<RBACUser>;
const user: UserWithMetadata = {
id: 'user-1',
roles: ['admin'],
metadata: {
department: 'Engineering',
hireDate: '2025-01-01'
}
};
```
## Const Enums
### PermissionCheckType
```typescript
const enum PermissionCheckType {
PERMISSION_CHECK = 'permission_check',
AUTHORIZATION = 'authorization',
ROLE_CHECK = 'role_check'
}
```
**Usage:**
```typescript
const event: AuditEvent = {
type: PermissionCheckType.PERMISSION_CHECK,
userId: 'user-1',
permission: 'post:read',
allowed: true,
timestamp: Date.now()
};
```
## Import Paths
```typescript
// Core types
import type {
RBACUser,
AuthorizationResult,
AuthorizationContext
} from '@fire-shield/core';
// Configuration types
import type {
RBACConfig,
RBACConfigSchema,
PresetConfig
} from '@fire-shield/core';
// Audit types
import type {
AuditEvent,
AuditEventContext,
AuditLogger
} from '@fire-shield/core';
// Role types
import type {
UserRole,
PermissionMask,
PermissionDefinition,
RoleDefinition
} from '@fire-shield/core';
// State types
import type {
RBACSystemState
} from '@fire-shield/core';
```
## Type Utilities
### Extending Types
```typescript
// Extend RBACUser with custom fields
interface AppUser extends RBACUser {
email: string;
name: string;
department: string;
}
const user: AppUser = {
id: 'user-1',
roles: ['editor'],
email: 'user@example.com',
name: 'John Doe',
department: 'Engineering'
};
```
### Type-Safe Permissions
```typescript
// Define allowed permissions as const
const PERMISSIONS = {
USER_READ: 'user:read',
USER_WRITE: 'user:write',
POST_READ: 'post:read',
POST_WRITE: 'post:write',
} as const;
type Permission = typeof PERMISSIONS[keyof typeof PERMISSIONS];
// Type-safe permission checks
function checkPermission(user: RBACUser, permission: Permission): boolean {
return rbac.hasPermission(user, permission);
}
// ✅ Valid
checkPermission(user, PERMISSIONS.USER_READ);
// ❌ Type error
checkPermission(user, 'invalid:permission');
```
### Type-Safe Roles
```typescript
// Define allowed roles
type Role = 'admin' | 'editor' | 'viewer';
function hasRole(user: RBACUser, role: Role): boolean {
return user.roles.includes(role);
}
// ✅ Valid
hasRole(user, 'admin');
// ❌ Type error
hasRole(user, 'invalid-role');
```
## Best Practices
### 1. Always Use TypeScript
```typescript
// ✅ Good: Full type safety
import type { RBACUser } from '@fire-shield/core';
const user: RBACUser = {
id: 'user-1',
roles: ['editor']
};
```
### 2. Define Custom Types
```typescript
// ✅ Good: Define app-specific types
interface AppUser extends RBACUser {
email: string;
name: string;
}
```
### 3. Use Type Guards
```typescript
// ✅ Good: Validate at runtime
if (isRBACUser(userData)) {
rbac.hasPermission(userData, 'post:read');
}
```
### 4. Const Assertions
```typescript
// ✅ Good: Type-safe constants
const ROLES = ['admin', 'editor', 'viewer'] as const;
type Role = typeof ROLES[number];
```
## Next Steps
- Learn about [Core API](/api/core)
- Explore [RBAC Builder](/api/builder)
- Check out [TypeScript Guide](/guide/typescript)
========================================================================
# SECTION: Frameworks — Frontend
========================================================================
────────────────────────────────────────────────────────────────────────
## Source: https://fire-shield.dev/frameworks/vue
────────────────────────────────────────────────────────────────────────
# Vue.js Integration
Fire Shield provides first-class support for Vue.js 3 with composables, directives, and router guards.
## Installation
```bash
npm install @fire-shield/vue@3.1.1 @fire-shield/core@3.1.1
```
## Setup
### Basic Setup
```typescript
// main.ts
import { createApp } from 'vue'
import { createVueRouterRBAC } from '@fire-shield/vue'
import { RBAC } from '@fire-shield/core'
import router from './router'
import App from './App.vue'
// Initialize RBAC
const rbac = new RBAC()
rbac.createRole('admin', ['posts:*', 'users:*'])
rbac.createRole('editor', ['posts:read', 'posts:write'])
rbac.createRole('viewer', ['posts:read'])
// Create user ref
const currentUser = ref({ id: '1', roles: ['editor'] })
// Create Vue RBAC plugin
const { install: installRBAC } = createVueRouterRBAC(router, {
rbac,
getUser: () => currentUser.value,
onUnauthorized: (to) => {
router.push('/unauthorized')
}
})
// Create and setup app
const app = createApp(App)
app.use(router)
app.use(installRBAC)
app.mount('#app')
```
## Directives
### v-can
Show elements only if user has permission:
```vue
User Management
```
### v-cannot
Hide elements if user has permission (inverse of v-can):
```vue
Upgrade to access premium features
```
### v-permission
Alias for v-can directive:
```vue
```
### v-role
Show elements only if user has specific role:
```vue
Admin Panel
Editor Tools
```
## Composables
### Composables
Access RBAC functionality in your components using the dedicated composables:
```vue
Current user: {{ user?.id }}
```
### API
```typescript
// Returns a ComputedRef - reactive permission check
useCan(permission: string): ComputedRef
// Returns a ComputedRef - reactive role check
useRole(role: string): ComputedRef
// Returns Ref - current user
useUser(): Ref
// Returns the RBAC instance directly
useRBAC(): RBAC
// Returns ComputedRef
useAuthorize(permission: string): ComputedRef
// Returns ComputedRef - checks all permissions
useAllPermissions(...permissions: string[]): ComputedRef
// Returns ComputedRef - checks any permission
useAnyPermission(...permissions: string[]): ComputedRef
// Returns a function to explicitly deny a permission for the current user
useDenyPermission(): (permission: string) => void
// Returns a function to remove a previously denied permission
useAllowPermission(): (permission: string) => void
// Returns ComputedRef - denied permissions for the current user
useDeniedPermissions(): ComputedRef
// Returns ComputedRef - whether a specific permission is explicitly denied
useIsDenied(permission: string): ComputedRef
```
## Components
### Can Component
Conditionally render content based on permissions:
```vue
You don't have permission to delete posts
```
### Cannot Component
Inverse of Can component:
```vue
)
}
```
### Hook API
```typescript
// Returns RBAC instance from context
useRBAC(): RBAC
// Check if current user has permission - returns boolean
usePermission(permission: string): boolean
// Check if current user has role - returns boolean
useRole(role: string): boolean
// Get current user from context
useUser(): RBACUser | null
// Get full authorization result
useAuthorize(permission: string): AuthorizationResult
// Check if user has ALL specified permissions
useAllPermissions(...permissions: string[]): boolean
// Check if user has ANY of the specified permissions
useAnyPermission(...permissions: string[]): boolean
// Returns a function to explicitly deny a permission for the current user
useDenyPermission(): (permission: string) => void
// Returns a function to remove a previously denied permission
useAllowPermission(): (permission: string) => void
// Returns array of explicitly denied permissions for the current user
useDeniedPermissions(): string[]
// Check if a specific permission is explicitly denied for the current user
useIsDenied(permission: string): boolean
```
## Components
### Can Component
Conditionally render content based on permissions:
```tsx
import { Can } from '@fire-shield/react'
function PostActions() {
return (
No permission}>
)
}
```
### Cannot Component
Inverse of Can component:
```tsx
import { Cannot } from '@fire-shield/react'
function UpgradePrompt() {
return (
Upgrade to unlock premium features
)
}
```
### RequirePermission Component
Throw error or show fallback if permission is missing:
```tsx
import { RequirePermission } from '@fire-shield/react'
function AdminPanel() {
return (
Access Denied}
>
Admin Panel
{/* Admin content */}
)
}
```
### Denied Component
Render if the user has the permission explicitly denied:
```tsx
import { Denied, NotDenied } from '@fire-shield/react'
function PostActions() {
return (
{/* Shows children only when permission is explicitly denied */}
Your delete access has been revoked.
{/* Shows children when permission is NOT explicitly denied */}
```
### hasRole(role)
Returns a derived store that checks if user has role:
```svelte
```
### authorize(permission)
Returns a derived store with full authorization result:
```svelte
{#if !$result.allowed}
Access denied: {$result.reason}
{:else}
{/if}
```
### canAll(permissions)
Check if user has all permissions:
```svelte
{#if $hasFullAccess}
{/if}
```
### canAny(permissions)
Check if user has any permission:
```svelte
{#if $canAccessPosts}
View Posts
{/if}
```
## Svelte Actions
### use:can
Conditionally render element based on permission:
```svelte
```
### use:role
Conditionally render element based on role:
```svelte
Admin Controls
Admin Controls
```
### use:cannot
Inverse conditional rendering (show when permission is NOT present):
```svelte
Upgrade to Premium for more features!
```
## Component Examples
### Navigation Menu
```svelte
```
### Post Actions
```svelte