{"version":3,"file":"rbac-engine.mjs","sources":["../../../../src/lib/auth/rbac/rbac-engine.ts"],"sourcesContent":["/**\n * RBAC Engine\n *\n * Core RBAC evaluation engine that handles permission checking,\n * role resolution, and access control decisions.\n *\n * @module auth/rbac/rbac-engine\n */\n\nimport type {\n  RBACConfig,\n  RoleDefinition,\n\n  PermissionAction,\n  PermissionScope,\n\n  AccessRequest,\n  EvaluationResult,\n  PolicyResult,\n  RBACAuditEvent,\n  RBACAuditHandler,\n} from './types';\n\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nconst DEFAULT_CACHE_TTL = 300000; // 5 minutes\nconst WILDCARD = '*';\n\n/**\n * Maximum length for user-provided patterns to prevent ReDoS attacks.\n *\n * SECURITY: Long patterns with certain structures can cause catastrophic\n * backtracking in regex engines, leading to denial of service.\n */\nconst MAX_PATTERN_LENGTH = 256;\n\n/**\n * Timeout for pattern matching operations in milliseconds.\n *\n * SECURITY: Limits execution time for regex operations to prevent DoS.\n */\n\n\n// =============================================================================\n// RBAC Engine Class\n// =============================================================================\n\n/**\n * RBAC Engine for permission evaluation.\n *\n * Provides comprehensive RBAC functionality including role inheritance,\n * permission resolution, and caching.\n *\n * @example\n * ```typescript\n * const engine = new RBACEngine({\n *   roles: [\n *     {\n *       id: 'admin',\n *       name: 'Administrator',\n *       permissions: ['*'],\n *       priority: 100,\n *     },\n *     {\n *       id: 'user',\n *       name: 'User',\n *       permissions: ['users:read:own', 'documents:*:own'],\n *       priority: 10,\n *     },\n *   ],\n *   defaultDecision: 'deny',\n * });\n *\n * // Initialize with user context\n * engine.setUserContext(['user'], { id: 'user-123' });\n *\n * // Check permissions\n * engine.hasPermission('users:read'); // true\n * engine.canAccess('documents', 'create'); // true\n * ```\n */\nexport class RBACEngine {\n  private config: RBACConfig;\n  private roleMap: Map<string, RoleDefinition>;\n  private permissionCache: Map<string, boolean>;\n  private evaluationCache: Map<string, EvaluationResult>;\n  private cacheExpiry: number = 0;\n  private userRoles: string[] = [];\n  private userAttributes: Record<string, unknown> = {};\n  private resolvedPermissions: Set<string> = new Set();\n  private auditHandlers: Set<RBACAuditHandler> = new Set();\n  private readonly debug: boolean;\n\n  /**\n   * Create a new RBAC engine.\n   *\n   * @param config - RBAC configuration\n   */\n  constructor(config: RBACConfig) {\n    this.config = config;\n    this.debug = config.debug ?? false;\n    this.roleMap = new Map();\n    this.permissionCache = new Map();\n    this.evaluationCache = new Map();\n\n    // Index roles for quick lookup\n    this.indexRoles(config.roles);\n  }\n\n  // ===========================================================================\n  // Configuration Methods\n  // ===========================================================================\n\n  /**\n   * Set the current user context.\n   *\n   * @param roles - User's assigned roles\n   * @param attributes - User attributes for ABAC\n   */\n  setUserContext(roles: string[], attributes: Record<string, unknown> = {}): void {\n    this.userRoles = roles;\n    this.userAttributes = attributes;\n    this.clearCache();\n    this.resolvePermissions();\n    this.log('User context set:', { roles, attributes });\n  }\n\n  /**\n   * Get the current user's roles.\n   */\n  getUserRoles(): string[] {\n    return [...this.userRoles];\n  }\n\n  /**\n   * Get the resolved permissions for current user.\n   */\n  getResolvedPermissions(): string[] {\n    return Array.from(this.resolvedPermissions);\n  }\n\n  /**\n   * Update configuration.\n   *\n   * @param config - Partial configuration update\n   */\n  updateConfig(config: Partial<RBACConfig>): void {\n    this.config = { ...this.config, ...config };\n\n    if (config.roles != null) {\n      this.roleMap.clear();\n      this.indexRoles(config.roles);\n    }\n\n    this.clearCache();\n    this.resolvePermissions();\n  }\n\n  /**\n   * Add a role definition.\n   *\n   * @param role - Role definition to add\n   */\n  addRole(role: RoleDefinition): void {\n    this.roleMap.set(role.id, role);\n    this.config.roles.push(role);\n    this.clearCache();\n    this.resolvePermissions();\n  }\n\n  /**\n   * Remove a role definition.\n   *\n   * @param roleId - Role ID to remove\n   */\n  removeRole(roleId: string): void {\n    this.roleMap.delete(roleId);\n    this.config.roles = this.config.roles.filter(r => r.id !== roleId);\n    this.clearCache();\n    this.resolvePermissions();\n  }\n\n  // ===========================================================================\n  // Permission Checking\n  // ===========================================================================\n\n  /**\n   * Check if user has a specific permission.\n   *\n   * @param permission - Permission string to check\n   * @returns Whether user has the permission\n   */\n  hasPermission(permission: string): boolean {\n    // Check cache first\n    const cacheKey = `perm:${permission}`;\n    if (this.isCacheValid() && this.permissionCache.has(cacheKey)) {\n      const cachedValue = this.permissionCache.get(cacheKey);\n      if (cachedValue != null) {\n        return cachedValue;\n      }\n    }\n\n    // Check super admin bypass\n    if (this.isSuperAdmin()) {\n      this.cachePermission(cacheKey, true);\n      return true;\n    }\n\n    // Check if user has wildcard permission\n    if (this.resolvedPermissions.has(WILDCARD)) {\n      this.cachePermission(cacheKey, true);\n      return true;\n    }\n\n    // Direct permission check\n    if (this.resolvedPermissions.has(permission)) {\n      this.cachePermission(cacheKey, true);\n      return true;\n    }\n\n    // Wildcard pattern matching\n    const result = this.matchPermissionPattern(permission);\n    this.cachePermission(cacheKey, result);\n\n    return result;\n  }\n\n  /**\n   * Check if user has any of the given permissions.\n   *\n   * @param permissions - Permissions to check\n   * @returns Whether user has any permission\n   */\n  hasAnyPermission(permissions: string[]): boolean {\n    return permissions.some(p => this.hasPermission(p));\n  }\n\n  /**\n   * Check if user has all of the given permissions.\n   *\n   * @param permissions - Permissions to check\n   * @returns Whether user has all permissions\n   */\n  hasAllPermissions(permissions: string[]): boolean {\n    return permissions.every(p => this.hasPermission(p));\n  }\n\n  /**\n   * Check if user has a specific role.\n   *\n   * @param roleId - Role ID to check\n   * @returns Whether user has the role\n   */\n  hasRole(roleId: string): boolean {\n    return this.userRoles.includes(roleId) || this.hasInheritedRole(roleId);\n  }\n\n  /**\n   * Check if user has any of the given roles.\n   *\n   * @param roleIds - Role IDs to check\n   * @returns Whether user has any role\n   */\n  hasAnyRole(roleIds: string[]): boolean {\n    return roleIds.some(r => this.hasRole(r));\n  }\n\n  /**\n   * Check if user has all of the given roles.\n   *\n   * @param roleIds - Role IDs to check\n   * @returns Whether user has all roles\n   */\n  hasAllRoles(roleIds: string[]): boolean {\n    return roleIds.every(r => this.hasRole(r));\n  }\n\n  /**\n   * Check if user can access a resource with an action.\n   *\n   * @param resource - Resource type\n   * @param action - Action to perform\n   * @param scope - Permission scope\n   * @returns Whether access is allowed\n   */\n  canAccess(\n    resource: string,\n    action: PermissionAction,\n    scope?: PermissionScope\n  ): boolean {\n    // Build permission strings to check\n    const permissionsToCheck = [\n      `${resource}:${action}`,\n      `${resource}:*`,\n      `*:${action}`,\n      WILDCARD,\n    ];\n\n    if (scope != null) {\n      permissionsToCheck.unshift(\n        `${resource}:${action}:${scope}`,\n        `${resource}:*:${scope}`\n      );\n    }\n\n    return permissionsToCheck.some(p => this.hasPermission(p));\n  }\n\n  /**\n   * Check resource-level permission.\n   *\n   * @param resourceType - Resource type\n   * @param _resourceId\n   * @param action - Action to perform\n   * @param context - Additional context\n   * @returns Whether access is allowed\n   */\n  checkResourcePermission(\n    resourceType: string,\n    _resourceId: string,\n    action: PermissionAction,\n    context?: Record<string, unknown>\n  ): boolean {\n    // First check type-level permission\n    if (this.canAccess(resourceType, action)) {\n      return true;\n    }\n\n    // Check if user has permission for own resources\n    if (this.canAccess(resourceType, action, 'own')) {\n      // Check if resource belongs to user\n      const ownerId = context?.ownerId ?? context?.userId;\n      if (ownerId != null && ownerId === this.userAttributes.id) {\n        return true;\n      }\n    }\n\n    // Check team-level permission\n    if (this.canAccess(resourceType, action, 'team')) {\n      const resourceTeam = context?.teamId;\n      const userTeam = this.userAttributes.teamId;\n      if (resourceTeam != null && userTeam != null && resourceTeam === userTeam) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  // ===========================================================================\n  // Access Evaluation (Full ABAC)\n  // ===========================================================================\n\n  /**\n   * Evaluate an access request using full ABAC evaluation.\n   *\n   * @param request - Access request to evaluate\n   * @returns Evaluation result\n   */\n  evaluate(request: AccessRequest): EvaluationResult {\n    const startTime = Date.now();\n    const cacheKey = this.getEvaluationCacheKey(request);\n\n    // Check cache\n    if (this.isCacheValid() && this.evaluationCache.has(cacheKey)) {\n      const cached = this.evaluationCache.get(cacheKey);\n      if (cached != null) {\n        this.auditCheck(request, cached);\n        return cached;\n      }\n    }\n\n    // Super admin bypass\n    if (this.isSuperAdmin()) {\n      const result = this.createResult(true, 'allow', 'super_admin_bypass');\n      this.cacheEvaluation(cacheKey, result);\n      this.auditCheck(request, result);\n      return result;\n    }\n\n    // Evaluate policies if configured\n    if ((this.config.policySets?.length ?? 0) > 0) {\n      const policyResult = this.evaluatePolicies(request);\n      if (policyResult.decision !== 'not-applicable') {\n        policyResult.evaluationTime = Date.now() - startTime;\n        this.cacheEvaluation(cacheKey, policyResult);\n        this.auditCheck(request, policyResult);\n        return policyResult;\n      }\n    }\n\n    // Evaluate using permission matrix if configured\n    if (this.config.permissionMatrix) {\n      const matrixResult = this.evaluatePermissionMatrix(request);\n      if (matrixResult.decision !== 'not-applicable') {\n        matrixResult.evaluationTime = Date.now() - startTime;\n        this.cacheEvaluation(cacheKey, matrixResult);\n        this.auditCheck(request, matrixResult);\n        return matrixResult;\n      }\n    }\n\n    // Fall back to basic permission check\n    const permission = `${request.resource.type}:${request.action}`;\n    const allowed = this.hasPermission(permission);\n\n    const result = this.createResult(\n      allowed,\n      allowed ? 'allow' : 'deny',\n      allowed ? 'permission_granted' : 'permission_denied'\n    );\n    result.evaluationTime = Date.now() - startTime;\n\n    this.cacheEvaluation(cacheKey, result);\n    this.auditCheck(request, result);\n\n    return result;\n  }\n\n  /**\n   * Clear all caches.\n   */\n  clearCache(): void {\n    this.permissionCache.clear();\n    this.evaluationCache.clear();\n    this.cacheExpiry = 0;\n  }\n\n  /**\n   * Register an audit handler.\n   */\n  onAudit(handler: RBACAuditHandler): () => void {\n    this.auditHandlers.add(handler);\n    return () => this.auditHandlers.delete(handler);\n  }\n\n  /**\n   * Evaluate policies for a request.\n   */\n  private evaluatePolicies(request: AccessRequest): EvaluationResult {\n    const matchingPolicies: string[] = [];\n    let decision: PolicyResult = 'not-applicable';\n\n    for (const policySet of this.config.policySets ?? []) {\n      // Check if policy set target matches\n      if (!this.matchesPolicyTarget(policySet.target, request)) {\n        continue;\n      }\n\n      // Evaluate each policy in the set\n      for (const policy of policySet.policies) {\n        if (!policy.enabled) continue;\n\n        const matches = this.evaluatePolicy(policy, request);\n        if (matches) {\n          matchingPolicies.push(policy.id);\n\n          // Apply combining algorithm\n          if (policy.effect === 'deny') {\n            if (\n              policySet.combiningAlgorithm === 'deny-overrides' ||\n              policySet.combiningAlgorithm === 'ordered-deny-overrides'\n            ) {\n              return this.createResult(false, 'deny', 'policy_deny', matchingPolicies);\n            }\n            decision = 'deny';\n          } else {\n            if (\n              policySet.combiningAlgorithm === 'permit-overrides' ||\n              policySet.combiningAlgorithm === 'ordered-permit-overrides'\n            ) {\n              return this.createResult(true, 'allow', 'policy_allow', matchingPolicies);\n            }\n            if (decision !== 'deny') {\n              decision = 'allow';\n            }\n          }\n\n          if (policySet.combiningAlgorithm === 'first-applicable') {\n            return this.createResult(\n              policy.effect === 'allow',\n              policy.effect === 'allow' ? 'allow' : 'deny',\n              'first_applicable_policy',\n              matchingPolicies\n            );\n          }\n        }\n      }\n    }\n\n    return this.createResult(\n      decision === 'allow',\n      decision,\n      'policy_evaluation',\n      matchingPolicies\n    );\n  }\n\n  /**\n   * Evaluate a single policy.\n   */\n  private evaluatePolicy(\n    policy: import('./types').Policy,\n    request: AccessRequest\n  ): boolean {\n    // Check subjects\n    if (policy.subjects != null && policy.subjects.length > 0) {\n      const subjectMatch = policy.subjects.some(subject =>\n        this.matchesPolicySubject(subject, request)\n      );\n      if (!subjectMatch) return false;\n    }\n\n    // Check resources\n    if (policy.resources != null && policy.resources.length > 0) {\n      const resourceMatch = policy.resources.some(resource =>\n        this.matchesPolicyResource(resource, request)\n      );\n      if (!resourceMatch) return false;\n    }\n\n    // Check actions\n    if (policy.actions != null && policy.actions.length > 0) {\n      const actionMatch = policy.actions.some(\n        action => action === WILDCARD || action === request.action\n      );\n      if (!actionMatch) return false;\n    }\n\n    // Check conditions\n    if (policy.conditions != null && policy.conditions.length > 0) {\n      const conditionsMatch = policy.conditions.every(condition =>\n        this.evaluatePolicyCondition(condition, request)\n      );\n      if (!conditionsMatch) return false;\n    }\n\n    return true;\n  }\n\n  /**\n   * Check if request matches policy target.\n   */\n  private matchesPolicyTarget(\n    targets: import('./types').PolicyResource[] | undefined,\n    request: AccessRequest\n  ): boolean {\n    if (targets == null || targets.length === 0) return true;\n    return targets.some(target => this.matchesPolicyResource(target, request));\n  }\n\n  /**\n   * Check if request matches policy subject.\n   */\n  private matchesPolicySubject(\n    subject: import('./types').PolicySubject,\n    request: AccessRequest\n  ): boolean {\n    switch (subject.type) {\n      case 'user':\n        return this.matchIdentifier(subject, request.subject.id);\n      case 'role':\n        return request.subject.roles?.includes(subject.identifier) === true;\n      case 'group':\n        // Check group membership (would need group info in subject)\n        return false;\n      case 'attribute': {\n        const attrValue = request.subject.attributes?.[subject.identifier];\n        return subject.value === undefined || attrValue === subject.value;\n      }\n      default:\n        return false;\n    }\n  }\n\n  /**\n   * Check if request matches policy resource.\n   */\n  private matchesPolicyResource(\n    resource: import('./types').PolicyResource,\n    request: AccessRequest\n  ): boolean {\n    if (resource.type !== WILDCARD && resource.type !== request.resource.type) {\n      return false;\n    }\n\n    if (resource.identifier != null && resource.identifier !== '' && resource.identifier !== WILDCARD) {\n      if (request.resource.id != null && resource.identifier !== request.resource.id) {\n        return false;\n      }\n    }\n\n    if (resource.attributes != null) {\n      for (const [key, value] of Object.entries(resource.attributes)) {\n        if (request.resource.attributes?.[key] !== value) {\n          return false;\n        }\n      }\n    }\n\n    return true;\n  }\n\n  /**\n   * Match identifier with support for wildcards and patterns.\n   *\n   * SECURITY: Implements multiple protections against ReDoS attacks:\n   * 1. Maximum pattern length limit (MAX_PATTERN_LENGTH)\n   * 2. Escaping of regex metacharacters before pattern conversion\n   * 3. Use of non-greedy quantifiers where possible\n   * 4. Simple string matching for exact matches (no regex)\n   * 5. For complex patterns, uses linear-time matching algorithm\n   */\n  private matchIdentifier(\n    subject: import('./types').PolicySubject,\n    value: string\n  ): boolean {\n    const { identifier, match = 'exact' } = subject;\n\n    switch (match) {\n      case 'any':\n        return true;\n\n      case 'pattern':\n        return this.safePatternMatch(identifier, value);\n\n      case 'exact':\n      default:\n        return identifier === value;\n    }\n  }\n\n  /**\n   * Safely matches a glob-like pattern against a value.\n   *\n   * SECURITY: Implements ReDoS-safe pattern matching:\n   * - Validates pattern length before processing\n   * - Escapes regex metacharacters to prevent injection\n   * - Uses non-greedy quantifiers (.*? instead of .*)\n   * - Falls back to simple string matching for overly complex patterns\n   *\n   * @param pattern - Glob-like pattern (supports * and ?)\n   * @param value - Value to match against\n   * @returns Whether the value matches the pattern\n   */\n  private safePatternMatch(pattern: string, value: string): boolean {\n    // SECURITY: Enforce maximum pattern length to prevent ReDoS\n    if (pattern.length > MAX_PATTERN_LENGTH) {\n      this.log(`Pattern exceeds maximum length (${MAX_PATTERN_LENGTH}), rejecting`);\n      return false;\n    }\n\n    // SECURITY: Validate value length as well\n    if (value.length > MAX_PATTERN_LENGTH * 4) {\n      this.log(`Value exceeds maximum length for pattern matching, rejecting`);\n      return false;\n    }\n\n    // For simple patterns without wildcards, use direct comparison\n    if (!pattern.includes('*') && !pattern.includes('?')) {\n      return pattern === value;\n    }\n\n    // SECURITY: Use linear-time matching algorithm for safety\n    // This avoids regex entirely, preventing ReDoS\n    return this.globMatch(pattern, value);\n  }\n\n  /**\n   * Linear-time glob matching algorithm.\n   *\n   * SECURITY: This implementation uses a non-regex approach that runs\n   * in O(n*m) worst case where n = pattern length and m = value length.\n   * This prevents the exponential backtracking that causes ReDoS.\n   *\n   * Supports:\n   * - * matches any sequence of characters (including empty)\n   * - ? matches exactly one character\n   *\n   * @param pattern - Glob pattern with * and ? wildcards\n   * @param value - String to match\n   * @returns Whether the pattern matches the value\n   */\n  private globMatch(pattern: string, value: string): boolean {\n    let pi = 0; // pattern index\n    let vi = 0; // value index\n    let starIdx = -1; // position of last * in pattern\n    let matchIdx = -1; // position in value where we matched *\n\n    while (vi < value.length) {\n      // Current characters match, or pattern has ?\n      if (pi < pattern.length && (pattern[pi] === value[vi] || pattern[pi] === '?')) {\n        pi++;\n        vi++;\n      }\n      // Pattern has *, remember position and try matching empty string\n      else if (pi < pattern.length && pattern[pi] === '*') {\n        starIdx = pi;\n        matchIdx = vi;\n        pi++;\n      }\n      // Mismatch, but we have a * to fall back to\n      else if (starIdx !== -1) {\n        pi = starIdx + 1;\n        matchIdx++;\n        vi = matchIdx;\n      }\n      // No match and no * to fall back to\n      else {\n        return false;\n      }\n    }\n\n    // Check remaining pattern characters (should all be *)\n    while (pi < pattern.length && pattern[pi] === '*') {\n      pi++;\n    }\n\n    return pi === pattern.length;\n  }\n\n  /**\n   * Evaluate a policy condition.\n   */\n  private evaluatePolicyCondition(\n    condition: import('./types').PolicyCondition,\n    request: AccessRequest\n  ): boolean {\n    switch (condition.type) {\n      case 'time':\n        return this.evaluateTimeCondition(condition, request);\n      case 'ip':\n        return this.evaluateIPCondition(condition, request);\n      case 'attribute':\n        return this.evaluateAttributeCondition(condition, request);\n      case 'context':\n        return this.evaluateContextCondition(condition, request);\n      default:\n        return true;\n    }\n  }\n\n  /**\n   * Evaluate time-based condition.\n   */\n  private evaluateTimeCondition(\n    condition: import('./types').PolicyCondition,\n    request: AccessRequest\n  ): boolean {\n    const now = request.context?.timestamp ?? Date.now();\n\n    switch (condition.operator) {\n      case 'between': {\n        const [start, end] = condition.value as [number, number];\n        return now >= start && now <= end;\n      }\n      case 'before':\n        return now < (condition.value as number);\n      case 'after':\n        return now > (condition.value as number);\n      default:\n        return true;\n    }\n  }\n\n  /**\n   * Evaluate IP-based condition.\n   */\n  private evaluateIPCondition(\n    condition: import('./types').PolicyCondition,\n    request: AccessRequest\n  ): boolean {\n    const clientIP = request.context?.ipAddress;\n    if (clientIP == null || clientIP === '') return condition.operator === 'notIn';\n\n    switch (condition.operator) {\n      case 'in':\n        return (condition.value as string[]).includes(clientIP);\n      case 'notIn':\n        return !(condition.value as string[]).includes(clientIP);\n      case 'cidr':\n        // Would need CIDR matching implementation\n        return true;\n      default:\n        return true;\n    }\n  }\n\n  /**\n   * Evaluate attribute-based condition.\n   */\n  private evaluateAttributeCondition(\n    condition: import('./types').PolicyCondition,\n    request: AccessRequest\n  ): boolean {\n    const {key} = condition;\n    if (key == null || key === '') return true;\n\n    const value = request.subject.attributes?.[key] ??\n                  request.resource.attributes?.[key];\n\n    switch (condition.operator) {\n      case 'equals':\n        return value === condition.value;\n      case 'notEquals':\n        return value !== condition.value;\n      case 'in':\n        return (condition.value as unknown[]).includes(value);\n      case 'notIn':\n        return !(condition.value as unknown[]).includes(value);\n      case 'exists':\n        return value !== undefined;\n      default:\n        return true;\n    }\n  }\n\n  // ===========================================================================\n  // Private Helper Methods\n  // ===========================================================================\n\n  /**\n   * Evaluate context-based condition.\n   */\n  private evaluateContextCondition(\n    condition: import('./types').PolicyCondition,\n    request: AccessRequest\n  ): boolean {\n    const {key} = condition;\n    if (key == null || key === '') return true;\n\n    const value = request.context?.attributes?.[key];\n\n    switch (condition.operator) {\n      case 'equals':\n        return value === condition.value;\n      case 'exists':\n        return value !== undefined;\n      default:\n        return true;\n    }\n  }\n\n  /**\n   * Evaluate using permission matrix.\n   */\n  private evaluatePermissionMatrix(request: AccessRequest): EvaluationResult {\n    const matrix = this.config.permissionMatrix;\n    if (matrix == null) {\n      return this.createResult(false, 'deny', 'no_permission_matrix');\n    }\n\n    // Find matching entries for user's roles\n    const matchingEntries = matrix.entries.filter(\n      entry =>\n        this.userRoles.includes(entry.roleId) &&\n        (entry.resource === WILDCARD || entry.resource === request.resource.type)\n    );\n\n    if (matchingEntries.length === 0) {\n      return this.createResult(\n        matrix.defaultBehavior === 'allow',\n        matrix.defaultBehavior === 'allow' ? 'allow' : 'deny',\n        'no_matching_matrix_entry'\n      );\n    }\n\n    // Check for explicit deny\n    const hasDeny = matchingEntries.some(\n      entry => entry.deniedActions?.includes(request.action as PermissionAction) === true ||\n               entry.deniedActions?.includes(WILDCARD as PermissionAction) === true\n    );\n\n    // Check for explicit allow\n    const hasAllow = matchingEntries.some(\n      entry => entry.allowedActions.includes(request.action as PermissionAction) ||\n               entry.allowedActions.includes(WILDCARD as PermissionAction)\n    );\n\n    // Apply conflict resolution\n    if (hasDeny && hasAllow) {\n      if (matrix.conflictResolution === 'deny-wins') {\n        return this.createResult(false, 'deny', 'conflict_deny_wins');\n      }\n      if (matrix.conflictResolution === 'allow-wins') {\n        return this.createResult(true, 'allow', 'conflict_allow_wins');\n      }\n      // Priority-based: use highest priority entry\n    }\n\n    if (hasDeny) {\n      return this.createResult(false, 'deny', 'matrix_deny');\n    }\n\n    if (hasAllow) {\n      return this.createResult(true, 'allow', 'matrix_allow');\n    }\n\n    return this.createResult(\n      matrix.defaultBehavior === 'allow',\n      'not-applicable',\n      'no_applicable_entry'\n    );\n  }\n\n  /**\n   * Index roles for quick lookup.\n   */\n  private indexRoles(roles: RoleDefinition[]): void {\n    for (const role of roles) {\n      this.roleMap.set(role.id, role);\n    }\n  }\n\n  /**\n   * Resolve all permissions for current user.\n   */\n  private resolvePermissions(): void {\n    this.resolvedPermissions.clear();\n\n    for (const roleId of this.userRoles) {\n      this.resolveRolePermissions(roleId);\n    }\n  }\n\n  /**\n   * Resolve permissions for a role including inheritance.\n   */\n  private resolveRolePermissions(roleId: string, visited = new Set<string>()): void {\n    if (visited.has(roleId)) return;\n    visited.add(roleId);\n\n    const role = this.roleMap.get(roleId);\n    if (role == null || role.isActive === false) return;\n\n    // Add role's permissions\n    for (const permission of role.permissions) {\n      this.resolvedPermissions.add(permission);\n    }\n\n    // Add structured permissions\n    if (role.structuredPermissions != null) {\n      for (const sp of role.structuredPermissions) {\n        if (sp.deny !== true) {\n          const permStr = sp.scope != null\n            ? `${sp.resource}:${sp.action}:${sp.scope}`\n            : `${sp.resource}:${sp.action}`;\n          this.resolvedPermissions.add(permStr);\n        }\n      }\n    }\n\n    // Resolve inherited role permissions\n    if (role.inherits != null) {\n      for (const parentRoleId of role.inherits) {\n        this.resolveRolePermissions(parentRoleId, visited);\n      }\n    }\n  }\n\n  /**\n   * Check if user has a role through inheritance.\n   */\n  private hasInheritedRole(roleId: string): boolean {\n    for (const userRoleId of this.userRoles) {\n      const role = this.roleMap.get(userRoleId);\n      if (role?.inherits?.includes(roleId) === true) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Match permission against patterns.\n   */\n  private matchPermissionPattern(permission: string): boolean {\n    const parts = permission.split(':');\n    const [resource, action, scope] = parts;\n\n    for (const resolved of this.resolvedPermissions) {\n      const resolvedParts = resolved.split(':');\n      const [resResource, resAction, resScope] = resolvedParts;\n\n      // Check resource match (with wildcard support)\n      if (resResource !== WILDCARD && resResource !== resource) continue;\n\n      // Check action match (with wildcard support)\n      if (resAction !== WILDCARD && resAction !== action) continue;\n\n      // Check scope match if specified\n      if (scope != null && resScope != null && resScope !== scope && resScope !== WILDCARD) continue;\n\n      return true;\n    }\n\n    return false;\n  }\n\n  /**\n   * Check if current user is a super admin.\n   */\n  private isSuperAdmin(): boolean {\n    const { superAdminRoles } = this.config;\n    if (superAdminRoles == null || superAdminRoles.length === 0) return false;\n    return this.userRoles.some(r => superAdminRoles.includes(r));\n  }\n\n  /**\n   * Create an evaluation result.\n   */\n  private createResult(\n    allowed: boolean,\n    decision: PolicyResult,\n    reason: string,\n    matchingPolicies?: string[]\n  ): EvaluationResult {\n    return {\n      allowed,\n      decision,\n      reason,\n      matchingPolicies,\n      evaluatedAt: Date.now(),\n    };\n  }\n\n  /**\n   * Generate cache key for evaluation.\n   */\n  private getEvaluationCacheKey(request: AccessRequest): string {\n    return `eval:${request.subject.id}:${request.resource.type}:${request.resource.id ?? ''}:${request.action}`;\n  }\n\n  /**\n   * Check if cache is still valid.\n   */\n  private isCacheValid(): boolean {\n    if (this.config.enableCaching !== true) return false;\n    return Date.now() < this.cacheExpiry;\n  }\n\n  /**\n   * Cache a permission check result.\n   */\n  private cachePermission(key: string, value: boolean): void {\n    if (this.config.enableCaching !== true) return;\n\n    this.permissionCache.set(key, value);\n\n    if (this.cacheExpiry === 0) {\n      this.cacheExpiry = Date.now() + (this.config.cacheTTL ?? DEFAULT_CACHE_TTL);\n    }\n  }\n\n  /**\n   * Cache an evaluation result.\n   */\n  private cacheEvaluation(key: string, result: EvaluationResult): void {\n    if (this.config.enableCaching !== true) return;\n\n    this.evaluationCache.set(key, result);\n\n    if (this.cacheExpiry === 0) {\n      this.cacheExpiry = Date.now() + (this.config.cacheTTL ?? DEFAULT_CACHE_TTL);\n    }\n  }\n\n  /**\n   * Emit an audit event.\n   */\n  private auditCheck(request: AccessRequest, result: EvaluationResult): void {\n    if (this.config.enableAudit !== true) return;\n\n    const event: RBACAuditEvent = {\n      id: crypto.randomUUID(),\n      timestamp: Date.now(),\n      type: 'access_check',\n      subject: {\n        id: request.subject.id,\n        type: request.subject.type,\n      },\n      resource: {\n        type: request.resource.type,\n        id: request.resource.id,\n      },\n      action: request.action,\n      result: result.allowed ? 'allowed' : 'denied',\n      reason: result.reason,\n    };\n\n    this.auditHandlers.forEach(handler => handler(event));\n  }\n\n  /**\n   * Log debug message.\n   */\n  private log(message: string, ...args: unknown[]): void {\n    if (this.debug) {\n      console.info(`[RBACEngine] ${message}`, ...args);\n    }\n  }\n}\n\n// =============================================================================\n// Factory Function\n// =============================================================================\n\n/**\n * Create a new RBAC engine.\n *\n * @param config - RBAC configuration\n * @returns Configured RBAC engine\n */\nexport function createRBACEngine(config: RBACConfig): RBACEngine {\n  return new RBACEngine(config);\n}\n"],"names":["RBACEngine","config","roles","attributes","role","roleId","r","permission","cacheKey","cachedValue","result","permissions","p","roleIds","resource","action","scope","permissionsToCheck","resourceType","_resourceId","context","ownerId","resourceTeam","userTeam","request","startTime","cached","policyResult","matrixResult","allowed","handler","matchingPolicies","decision","policySet","policy","subject","condition","targets","target","attrValue","key","value","identifier","match","pattern","pi","vi","starIdx","matchIdx","now","start","end","clientIP","matrix","matchingEntries","entry","hasDeny","hasAllow","visited","sp","permStr","parentRoleId","userRoleId","parts","resolved","resolvedParts","resResource","resAction","resScope","superAdminRoles","reason","event","message","args","createRBACEngine"],"mappings":"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"}