{"version":3,"file":"core-Ca921OyC.cjs","names":["matchesAction","matchesResourceHierarchical","matchesResource","evalConditionGroup","matchesAction","matchesResourceHierarchical","matchesResource","evalConditionGroup","resolveEffectiveRoles","rolesToPolicy","iamBuildPermissionKey","statsSnapshotHelper","RoleBuilder","PolicyBuilder","RuleBuilder","When","validateRoles","validatePolicy"],"sources":["../src/shared/cache.ts","../src/core/evaluate/evaluate.libs.ts","../src/core/evaluate/evaluate.ts","../src/core/engine/engine.hooks.ts","../src/core/engine/engine.invalidation.ts","../src/core/engine/engine.libs.ts","../src/core/engine/engine.stats.ts","../src/core/engine/engine.lifecycle.ts","../src/core/engine/engine.loaders.ts","../src/core/engine/engine.ts","../src/core/config/config.ts","../src/core/types/caches.ts"],"sourcesContent":["import type { IamEngine } from '../core'\n/**\n * LRU cache with TTL expiration; relies on `Map` insertion order. Used by {@link IamEngine} for policies/roles/subjects.\n *\n * @template V - Type of cached values.\n */\nexport class IamLRUCache<V> {\n  private _map = new Map<string, { value: V; expiresAt: number }>()\n  private _maxSize: number\n  private _ttl: number\n  private _hits = 0\n  private _misses = 0\n\n  /**\n   * @param maxSize - Sets the maximum number of entries before LRU eviction.\n   * @param ttlMs - Sets time-to-live in milliseconds for each entry.\n   * @throws `RangeError` when `maxSize < 1` or `ttlMs < 0`.\n   */\n  constructor(maxSize: number, ttlMs: number) {\n    if (!Number.isFinite(maxSize) || maxSize < 1)\n      throw new RangeError('IamLRUCache maxSize must be a finite number >= 1')\n    if (!Number.isFinite(ttlMs) || ttlMs < 0) throw new RangeError('IamLRUCache ttlMs must be a finite number >= 0')\n    this._maxSize = maxSize\n    this._ttl = ttlMs\n  }\n\n  /**\n   * Get + refresh LRU; `undefined` when missing or expired.\n   *\n   * @param key - Looks up the entry under this cache key.\n   * @returns The stored value, or `undefined` when missing or expired.\n   */\n  get(key: string): V | undefined {\n    const entry = this._map.get(key)\n    if (!entry) {\n      this._misses++\n      return undefined\n    }\n    if (Date.now() > entry.expiresAt) {\n      this._map.delete(key)\n      this._misses++\n      return undefined\n    }\n    // Move to end (most recently used)\n    this._map.delete(key)\n    this._map.set(key, entry)\n    this._hits++\n    return entry.value\n  }\n\n  /** Hit/miss counters + current size. */\n  get stats(): { hits: number; misses: number; size: number } {\n    return { hits: this._hits, misses: this._misses, size: this._map.size }\n  }\n\n  /** Zeroes the hit and miss counters without clearing stored entries. */\n  resetStats(): void {\n    this._hits = 0\n    this._misses = 0\n  }\n\n  /**\n   * Set + TTL refresh; evicts the oldest at capacity.\n   *\n   * @param key - Stores the entry under this cache key.\n   * @param value - Associates this value with the key.\n   */\n  set(key: string, value: V): void {\n    this._map.delete(key)\n    if (this._map.size >= this._maxSize) {\n      const first = this._map.keys().next().value\n      if (first !== undefined) this._map.delete(first)\n    }\n    this._map.set(key, { value, expiresAt: Date.now() + this._ttl })\n  }\n\n  /**\n   * Remove a single entry.\n   *\n   * @param key - Removes the entry stored under this cache key.\n   * @returns `true` when the entry existed and was deleted.\n   */\n  delete(key: string): boolean {\n    return this._map.delete(key)\n  }\n\n  /** Clears entries without resetting stat counters. */\n  clear(): void {\n    this._map.clear()\n  }\n\n  get size(): number {\n    return this._map.size\n  }\n\n  /** Iterate non-expired entries; does NOT refresh LRU order. */\n  *entries(): IterableIterator<[string, V]> {\n    const now = Date.now()\n    for (const [key, entry] of this._map) {\n      if (now > entry.expiresAt) continue\n      yield [key, entry.value]\n    }\n  }\n}\n","/** biome-ignore-all lint/style/noNonNullAssertion: hot-path index iteration is guarded by `i < arr.length`. */\nimport { evalConditionGroup } from '../conditions'\nimport { matchesAction, matchesResource, matchesResourceHierarchical } from '../resolve'\nimport type { AccessControl, IamRequest } from '../types'\nimport type { Evaluate } from './evaluate.types'\n/**\n * Checks whether a single rule applies to the given access request.\n *\n * A rule applies when its action patterns match the requested action,\n * its resource patterns match the requested resource type, and all\n * conditions (if any) evaluate to true.\n *\n * @param rule - The rule to test\n * @param req  - The incoming access request\n * @returns `true` if the rule matches the request\n */\nexport function ruleApplies(\n  rule: AccessControl.IRule,\n  req: IamRequest.IAccessRequest,\n  caches?: { regex?: Map<string, RegExp>; path?: Map<string, string[] | null> },\n): boolean {\n  const actionMatch = rule.actions.some((a) => matchesAction(a, req.action))\n  if (!actionMatch) return false\n\n  // Hoist the dot check - compute once before the .some() loop\n  const resourceHasDot = req.resource.type.includes('.')\n\n  const resourceMatch = rule.resources.some((r) => {\n    // Use dot-based matching if either pattern or resource type contains a dot\n    if (resourceHasDot || r.includes('.')) {\n      return matchesResourceHierarchical(r, req.resource.type)\n    }\n    return matchesResource(r, req.resource.type)\n  })\n  if (!resourceMatch) return false\n\n  return evalConditionGroup(req, rule.conditions, 0, caches)\n}\n\n/**\n * Checks whether a policy's target constraints match the given access request.\n *\n * If the policy has no targets defined, it applies to all requests.\n * Otherwise, each target dimension (actions, resources, roles) is checked\n * independently - all specified dimensions must match.\n *\n * @param policy - The policy whose targets to check\n * @param req    - The incoming access request\n * @returns `true` if the policy should be evaluated for this request\n */\nexport function policyApplies(policy: AccessControl.IPolicy, req: IamRequest.IAccessRequest): boolean {\n  if (!policy.targets) return true\n\n  const { actions, resources, roles } = policy.targets\n\n  if (actions?.length && !actions.some((a) => matchesAction(a, req.action))) {\n    return false\n  }\n\n  if (resources?.length && !resources.some((r) => matchesResource(r, req.resource.type))) {\n    return false\n  }\n\n  if (roles?.length) {\n    const subjectRoles = Array.isArray(req.subject.roles) ? req.subject.roles : []\n    if (!roles.some((role) => subjectRoles.includes(role))) {\n      return false\n    }\n  }\n\n  return true\n}\n\n/**\n * Combining-algorithm implementations. Each picks one matched rule's effect:\n *\n * - `deny-overrides`   - any deny wins; otherwise first allow wins.\n * - `allow-overrides`  - any allow wins; otherwise first deny wins.\n * - `first-match`      - highest-priority match wins; ties resolved by source order.\n * - `highest-priority` - highest-priority match wins (alias of `first-match` once ties tie-break by priority alone).\n */\nexport const combiners: Record<AccessControl.CombiningAlgorithm, Evaluate.Combiner> = {\n  'deny-overrides': (matched, defaultEffect) => {\n    const deny = matched.find((m) => m.effect === 'deny')\n    if (deny) {\n      return {\n        rule: deny.rule,\n        effect: 'deny',\n        reason: `Denied by rule \"${deny.rule.id}\"`,\n      }\n    }\n    const allow = matched.find((m) => m.effect === 'allow')\n    if (allow) {\n      return {\n        rule: allow.rule,\n        effect: 'allow',\n        reason: `Allowed by rule \"${allow.rule.id}\"`,\n      }\n    }\n    return { effect: defaultEffect, reason: `No matching rules. Defaulted to ${defaultEffect}` }\n  },\n\n  'allow-overrides': (matched, defaultEffect) => {\n    const allow = matched.find((m) => m.effect === 'allow')\n    if (allow) {\n      return {\n        rule: allow.rule,\n        effect: 'allow',\n        reason: `Allowed by rule \"${allow.rule.id}\"`,\n      }\n    }\n    const deny = matched.find((m) => m.effect === 'deny')\n    if (deny) {\n      return {\n        rule: deny.rule,\n        effect: 'deny',\n        reason: `Denied by rule \"${deny.rule.id}\"`,\n      }\n    }\n    return { effect: defaultEffect, reason: `No matching rules. Defaulted to ${defaultEffect}` }\n  },\n\n  'first-match': (matched, defaultEffect) => {\n    if (matched.length === 0) {\n      return { effect: defaultEffect, reason: `No matching rules. Defaulted to ${defaultEffect}` }\n    }\n    // Highest priority first; stable on ties preserves source order\n    let first = matched[0]!\n    for (let i = 1; i < matched.length; i++) {\n      const cur = matched[i]!\n      if (cur.rule.priority > first.rule.priority) first = cur\n    }\n    return {\n      rule: first.rule,\n      effect: first.effect,\n      reason: `First match: rule \"${first.rule.id}\" (${first.effect})`,\n    }\n  },\n\n  'highest-priority': (matched, defaultEffect) => {\n    if (matched.length > 0) {\n      const top = matched.reduce((best, cur) => (cur.rule.priority > best.rule.priority ? cur : best))\n      return {\n        rule: top.rule,\n        effect: top.effect,\n        reason: `Highest priority: rule \"${top.rule.id}\" (p=${top.rule.priority})`,\n      }\n    }\n    return { effect: defaultEffect, reason: `No matching rules. Defaulted to ${defaultEffect}` }\n  },\n}\n\n/**\n * True when a pattern matches more than its own literal value (`'*'`, `'foo:*'`,\n * `'foo.*'`). Such patterns can't be served by the literal-keyed `byActionResource`\n * map and must be checked via the wildcardAny scan.\n */\nfunction isExpansivePattern(p: string): boolean {\n  return p.includes('*')\n}\n\n/** WeakMap so indexes are GC'd when the policy is no longer referenced. */\nconst indexCache = new WeakMap<AccessControl.IPolicy, Evaluate.IPolicyRuleIndex>()\n\n/**\n * Build (or retrieve from cache) a rule index for a policy.\n *\n * @param policy - The policy whose rules should be indexed.\n * @returns The cached or freshly built {@link Evaluate.IPolicyRuleIndex}.\n */\nexport function indexPolicy(policy: AccessControl.IPolicy): Evaluate.IPolicyRuleIndex {\n  const cached = indexCache.get(policy)\n  if (cached) return cached\n\n  const byActionResource = new Map<string, Evaluate.IIndexedRule[]>()\n  const wildcardAny: Evaluate.IIndexedRule[] = []\n\n  for (const rule of policy.rules) {\n    const actions = new Set(rule.actions as string[])\n    const resources = new Set(rule.resources as string[])\n    let hasWildcardAction = false\n    for (const a of actions) {\n      if (isExpansivePattern(a)) {\n        hasWildcardAction = true\n        break\n      }\n    }\n    let hasWildcardResource = false\n    for (const r of resources) {\n      if (isExpansivePattern(r)) {\n        hasWildcardResource = true\n        break\n      }\n    }\n    const c = rule.conditions\n    const hasConditions = !!c && ('all' in c || 'any' in c || 'none' in c)\n    const entry: Evaluate.IIndexedRule = {\n      rule,\n      actions,\n      resources,\n      hasWildcardAction,\n      hasWildcardResource,\n      hasConditions,\n    }\n\n    if (hasWildcardAction || hasWildcardResource) wildcardAny.push(entry)\n\n    // Only rules with literal actions AND resources go into the exact-key index;\n    // expansive patterns (`*`, `foo:*`, `foo.*`) are handled by the wildcardAny scan.\n    if (!hasWildcardAction && !hasWildcardResource) {\n      for (const a of actions) {\n        for (const r of resources) {\n          const key = `${a}\\0${r}`\n          let bucket = byActionResource.get(key)\n          if (!bucket) {\n            bucket = []\n            byActionResource.set(key, bucket)\n          }\n          bucket.push(entry)\n        }\n      }\n    }\n  }\n\n  // Pre-compute results for unconditional exact-match rules (CASL-like O(1)).\n  // Only when no wildcard rules exist (they could override the result).\n  const precomputed = new Map<string, Map<string, boolean>>()\n  const algo = policy.algorithm\n\n  if (wildcardAny.length === 0 && (algo === 'deny-overrides' || algo === 'allow-overrides' || algo === 'first-match')) {\n    for (const rule of policy.rules) {\n      const c = rule.conditions\n      if ('all' in c || 'any' in c || 'none' in c) continue\n      if (rule.actions.some(isExpansivePattern) || rule.resources.some(isExpansivePattern)) continue\n\n      for (const a of rule.actions) {\n        for (const r of rule.resources) {\n          const arKey = `${a}\\0${r}`\n          const entries = byActionResource.get(arKey)\n          if (!entries) continue\n\n          // Only precompute when every entry in this bucket is unconditional  -\n          // otherwise the result depends on the request and can't be cached.\n          let allUnconditional = true\n          for (const e of entries) {\n            const ec = e.rule.conditions\n            if ('all' in ec || 'any' in ec || 'none' in ec) {\n              allUnconditional = false\n              break\n            }\n          }\n          if (!allUnconditional) continue\n\n          // Simulate combining algorithm\n          let result: boolean | undefined\n          if (algo === 'deny-overrides') {\n            let hasAllow = false\n            for (const e of entries) {\n              if (e.rule.effect === 'deny') {\n                result = false\n                break\n              }\n              if (e.rule.effect === 'allow') hasAllow = true\n            }\n            if (result === undefined && hasAllow) result = true\n          } else if (algo === 'allow-overrides') {\n            let hasDeny = false\n            for (const e of entries) {\n              if (e.rule.effect === 'allow') {\n                result = true\n                break\n              }\n              if (e.rule.effect === 'deny') hasDeny = true\n            }\n            if (result === undefined && hasDeny) result = false\n          } else if (algo === 'first-match' && entries.length > 0) {\n            let best = entries[0]!\n            for (let i = 1; i < entries.length; i++) {\n              const cur = entries[i]!\n              if (cur.rule.priority > best.rule.priority) best = cur\n            }\n            result = best.rule.effect === 'allow'\n          }\n\n          if (result !== undefined) {\n            let actionMap = precomputed.get(a)\n            if (!actionMap) {\n              actionMap = new Map()\n              precomputed.set(a, actionMap)\n            }\n            actionMap.set(r, result)\n          }\n        }\n      }\n    }\n  }\n\n  const idx: Evaluate.IPolicyRuleIndex = { byActionResource, wildcardAny, precomputed }\n  indexCache.set(policy, idx)\n  return idx\n}\n","/** biome-ignore-all lint/style/noNonNullAssertion: hot-path index iteration is guarded by `i < arr.length`. */\n\nimport { evalConditionGroup } from '../conditions'\nimport { matchesAction, matchesResource, matchesResourceHierarchical } from '../resolve'\nimport type { AccessControl, IamRequest } from '../types'\nimport { combiners, indexPolicy, policyApplies, ruleApplies } from './evaluate.libs'\nimport type { Evaluate } from './evaluate.types'\n\n// Literal resource patterns match only the exact resource type; recursive\n// grants require the explicit `:*` / `.*` suffix and are handled by\n// `wildcardAny`.\n\n/**\n * Inline candidate matching - checks resource + conditions without allocating.\n * Action is already narrowed by the index lookup.\n */\nfunction matchCandidate(\n  entry: Evaluate.IIndexedRule,\n  action: string,\n  resType: string,\n  resHasDot: boolean,\n  req: IamRequest.IAccessRequest,\n  caches?: { regex?: Map<string, RegExp>; path?: Map<string, string[] | null> },\n): boolean {\n  // Action - already narrowed by index, but handle prefix patterns\n  if (!entry.hasWildcardAction && !entry.actions.has(action)) {\n    let ok = false\n    for (const a of entry.rule.actions) {\n      if (matchesAction(a, action)) {\n        ok = true\n        break\n      }\n    }\n    if (!ok) return false\n  }\n\n  // Resource\n  if (!entry.hasWildcardResource) {\n    let ok = false\n    for (const r of entry.rule.resources) {\n      if (resHasDot || r.includes('.')) {\n        if (matchesResourceHierarchical(r, resType)) {\n          ok = true\n          break\n        }\n      } else {\n        if (matchesResource(r, resType)) {\n          ok = true\n          break\n        }\n      }\n    }\n    if (!ok) return false\n  }\n\n  if (!entry.hasConditions) return true\n  return evalConditionGroup(req, entry.rule.conditions, 0, caches)\n}\n\n/**\n * Evaluates a single policy against an access request.\n *\n * Pure function with no side effects. Checks policy targets first, then\n * evaluates matching rules using the policy's combining algorithm.\n *\n * @param policy        - The policy to evaluate\n * @param request       - The access request to evaluate against\n * @param defaultEffect - Effect to use when no rules match (defaults to `'deny'`)\n * @returns An {@link AccessControl.IDecision} with the evaluation result\n */\nexport function evaluatePolicy(\n  policy: AccessControl.IPolicy,\n  request: IamRequest.IAccessRequest,\n  defaultEffect: AccessControl.Effect = 'deny',\n  caches?: { regex?: Map<string, RegExp>; path?: Map<string, string[] | null> },\n): AccessControl.IDecision {\n  const start = performance.now()\n\n  if (!policyApplies(policy, request)) {\n    // NotApplicable: policy is neutral - the cross-policy combine must skip it,\n    // not fold it as the default effect.\n    return {\n      allowed: defaultEffect === 'allow',\n      effect: defaultEffect,\n      policy: policy.id,\n      reason: `Policy \"${policy.id}\" targets do not match. Not applicable.`,\n      duration: performance.now() - start,\n      timestamp: Date.now(),\n      applicable: false,\n    }\n  }\n\n  const matched: Array<{ rule: AccessControl.IRule; effect: AccessControl.Effect }> = []\n\n  for (const rule of policy.rules) {\n    if (ruleApplies(rule, request, caches)) {\n      matched.push({ rule, effect: rule.effect })\n    }\n  }\n\n  const combiner = combiners[policy.algorithm]\n  const result = combiner(matched, defaultEffect)\n\n  return {\n    allowed: result.effect === 'allow',\n    effect: result.effect,\n    rule: result.rule,\n    policy: policy.id,\n    reason: result.reason,\n    duration: performance.now() - start,\n    timestamp: Date.now(),\n  }\n}\n\n/**\n * Combine decisions across multiple policies per `combine` (`'and'` | `'allow-overrides'` | `'first-applicable'`).\n *\n * @param policies      All policies to evaluate.\n * @param request       The access request.\n * @param defaultEffect Effect when no rule fires within a policy.\n * @param combine       Cross-policy combine strategy (defaults to `'and'`).\n * @param onPolicyError Invoked when a single policy throws; offender treated as NotApplicable.\n * @returns The merged {@link AccessControl.IDecision} across all policies.\n */\nexport function evaluate(\n  policies: AccessControl.IPolicy[],\n  request: IamRequest.IAccessRequest,\n  defaultEffect: AccessControl.Effect = 'deny',\n  combine: AccessControl.PolicyCombine = 'and',\n  onPolicyError?: (err: Error, policy: AccessControl.IPolicy) => void,\n  signals?: IEvalSignals,\n  caches?: { regex?: Map<string, RegExp>; path?: Map<string, string[] | null> },\n): AccessControl.IDecision {\n  const start = performance.now()\n\n  if (policies.length === 0) {\n    if (signals && defaultEffect === 'allow') signals.failOpen = true\n    return {\n      allowed: defaultEffect === 'allow',\n      effect: defaultEffect,\n      reason: 'No policies configured',\n      duration: performance.now() - start,\n      timestamp: Date.now(),\n    }\n  }\n\n  /**\n   * Same fail-skip contract as {@link evaluateFast}: one rotten policy must\n   * not break the whole evaluation. Synthesise a NotApplicable decision so\n   * the combiner skips it cleanly.\n   */\n  const safeEval = (policy: AccessControl.IPolicy): AccessControl.IDecision => {\n    try {\n      return evaluatePolicy(policy, request, defaultEffect, caches)\n    } catch (err) {\n      onPolicyError?.(err instanceof Error ? err : new Error(String(err)), policy)\n      return {\n        allowed: defaultEffect === 'allow',\n        effect: defaultEffect,\n        reason: 'Policy evaluation error - skipped',\n        applicable: false,\n        duration: 0,\n        timestamp: Date.now(),\n      }\n    }\n  }\n\n  if (combine === 'and') {\n    let lastAllow: AccessControl.IDecision | null = null\n    for (const policy of policies) {\n      const decision = safeEval(policy)\n      if (decision.applicable === false) continue\n      if (!decision.allowed) return { ...decision, duration: performance.now() - start }\n      lastAllow = decision\n    }\n    if (lastAllow === null) {\n      if (signals && defaultEffect === 'allow') signals.failOpen = true\n      return {\n        allowed: defaultEffect === 'allow',\n        effect: defaultEffect,\n        reason: `No policy applicable. Defaulted to ${defaultEffect}`,\n        duration: performance.now() - start,\n        timestamp: Date.now(),\n      }\n    }\n    return { ...lastAllow, duration: performance.now() - start }\n  }\n\n  if (combine === 'allow-overrides') {\n    let lastDeny: AccessControl.IDecision | null = null\n    for (const policy of policies) {\n      const decision = safeEval(policy)\n      if (decision.applicable === false) continue\n      if (decision.allowed) return { ...decision, duration: performance.now() - start }\n      lastDeny = decision\n    }\n    if (lastDeny === null) {\n      if (signals && defaultEffect === 'allow') signals.failOpen = true\n      return {\n        allowed: defaultEffect === 'allow',\n        effect: defaultEffect,\n        reason: `No policy applicable. Defaulted to ${defaultEffect}`,\n        duration: performance.now() - start,\n        timestamp: Date.now(),\n      }\n    }\n    return { ...lastDeny, duration: performance.now() - start }\n  }\n\n  for (const policy of policies) {\n    const decision = safeEval(policy)\n    if (decision.applicable === false) continue\n    if (decision.rule !== undefined) return { ...decision, duration: performance.now() - start }\n  }\n  if (signals && defaultEffect === 'allow') signals.failOpen = true\n  return {\n    allowed: defaultEffect === 'allow',\n    effect: defaultEffect,\n    reason: `No policy was applicable. Defaulted to ${defaultEffect}`,\n    duration: performance.now() - start,\n    timestamp: Date.now(),\n  }\n}\n\n/**\n * Fast (production-mode) single-policy evaluation; allocation-light combiner shell.\n *\n * @param policy        The policy to evaluate.\n * @param request       The access request.\n * @param defaultEffect Effect to use when no rules match (defaults to `'deny'`).\n * @returns `true` / `false` for an applicable allow / deny, `null` when NotApplicable.\n */\nexport function evaluatePolicyFast(\n  policy: AccessControl.IPolicy,\n  request: IamRequest.IAccessRequest,\n  defaultEffect: AccessControl.Effect = 'deny',\n  caches?: { regex?: Map<string, RegExp>; path?: Map<string, string[] | null> },\n): boolean | null {\n  // Inline policyApplies - avoid function call overhead\n  const targets = policy.targets\n  if (targets) {\n    if (targets.actions?.length && !targets.actions.some((a) => matchesAction(a, request.action))) return null\n    if (targets.resources?.length && !targets.resources.some((r) => matchesResource(r, request.resource.type))) {\n      return null\n    }\n    if (targets.roles?.length) {\n      const subjectRoles = Array.isArray(request.subject.roles) ? request.subject.roles : []\n      if (!targets.roles.some((role) => subjectRoles.includes(role))) return null\n    }\n  }\n\n  const idx = indexPolicy(policy)\n  const action = request.action\n  const resType = request.resource.type\n\n  // Fastest path: pre-computed result for unconditional rules (CASL-like O(1)).\n  // Literal resource patterns match only the exact resource type - do NOT\n  // probe parent prefixes here.\n  const actionMap = idx.precomputed.get(action)\n  if (actionMap) {\n    const precomputed = actionMap.get(resType)\n    if (precomputed !== undefined) return precomputed\n  }\n\n  // Literal buckets are matched by exact key only. Rules with `:*` / `.*`\n  // suffixes live in `wildcardAny` and are checked there via `matchCandidate`\n  // -> `matchesResource(Hierarchical)`.\n  const literalBuckets: Evaluate.IIndexedRule[][] = []\n  const exactAR = idx.byActionResource.get(`${action}\\0${resType}`)\n  if (exactAR) literalBuckets.push(exactAR)\n  const wildcardAny = idx.wildcardAny\n  const resHasDot = resType.includes('.')\n  const algo = policy.algorithm\n\n  if (algo === 'deny-overrides') {\n    let hasAllow = false\n    for (let bi = 0; bi < literalBuckets.length; bi++) {\n      const bucket = literalBuckets[bi]!\n      for (let i = 0; i < bucket.length; i++) {\n        const entry = bucket[i]!\n        if (entry.hasConditions && !evalConditionGroup(request, entry.rule.conditions, 0, caches)) continue\n        if (entry.rule.effect === 'deny') return false\n        hasAllow = true\n      }\n    }\n    for (let i = 0; i < wildcardAny.length; i++) {\n      const entry = wildcardAny[i]!\n      if (!matchCandidate(entry, action, resType, resHasDot, request, caches)) continue\n      if (entry.rule.effect === 'deny') return false\n      hasAllow = true\n    }\n    return hasAllow ? true : defaultEffect === 'allow'\n  }\n\n  if (algo === 'allow-overrides') {\n    let hasDeny = false\n    for (let bi = 0; bi < literalBuckets.length; bi++) {\n      const bucket = literalBuckets[bi]!\n      for (let i = 0; i < bucket.length; i++) {\n        const entry = bucket[i]!\n        if (entry.hasConditions && !evalConditionGroup(request, entry.rule.conditions, 0, caches)) continue\n        if (entry.rule.effect === 'allow') return true\n        hasDeny = true\n      }\n    }\n    for (let i = 0; i < wildcardAny.length; i++) {\n      const entry = wildcardAny[i]!\n      if (!matchCandidate(entry, action, resType, resHasDot, request, caches)) continue\n      if (entry.rule.effect === 'allow') return true\n      hasDeny = true\n    }\n    return hasDeny ? false : defaultEffect === 'allow'\n  }\n\n  // first-match (priority-aware) + highest-priority share the scan loop.\n  let bestPriority = -Infinity\n  let bestEffect: AccessControl.Effect | null = null\n  for (let bi = 0; bi < literalBuckets.length; bi++) {\n    const bucket = literalBuckets[bi]!\n    for (let i = 0; i < bucket.length; i++) {\n      const entry = bucket[i]!\n      if (entry.hasConditions && !evalConditionGroup(request, entry.rule.conditions)) continue\n      if (entry.rule.priority > bestPriority) {\n        bestPriority = entry.rule.priority\n        bestEffect = entry.rule.effect\n      }\n    }\n  }\n  for (let i = 0; i < wildcardAny.length; i++) {\n    const entry = wildcardAny[i]!\n    if (!matchCandidate(entry, action, resType, resHasDot, request)) continue\n    if (entry.rule.priority > bestPriority) {\n      bestPriority = entry.rule.priority\n      bestEffect = entry.rule.effect\n    }\n  }\n  return bestEffect !== null ? bestEffect === 'allow' : defaultEffect === 'allow'\n}\n\n/**\n * Fast multi-policy evaluation returning a boolean; mirrors {@link evaluate}'s `combine` modes (no `first-applicable`).\n *\n * @param policies      All policies to evaluate.\n * @param request       The access request.\n * @param defaultEffect Effect to use when no rules fire (defaults to `'deny'`).\n * @param combine       Cross-policy combine strategy (defaults to `'and'`).\n * @param onPolicyError Invoked when a single policy throws; offender treated as NotApplicable.\n * @returns `true` when the final verdict is allow, `false` otherwise.\n */\nexport function evaluateFast(\n  policies: AccessControl.IPolicy[],\n  request: IamRequest.IAccessRequest,\n  defaultEffect: AccessControl.Effect = 'deny',\n  combine: AccessControl.PolicyCombine = 'and',\n  onPolicyError?: (err: Error, policy: AccessControl.IPolicy) => void,\n  signals?: IEvalSignals,\n  caches?: { regex?: Map<string, RegExp>; path?: Map<string, string[] | null> },\n): boolean {\n  if (policies.length === 0) {\n    const allowed = defaultEffect === 'allow'\n    if (signals && allowed) signals.failOpen = true\n    return allowed\n  }\n\n  /**\n   * A single rotten row (NaN priority, malformed condition, etc.) must not\n   * poison the whole evaluation - treat the offending policy as NotApplicable\n   * and route the error to `onPolicyError` so the operator can alert.\n   */\n  const safeEval = (policy: AccessControl.IPolicy): boolean | null => {\n    try {\n      return evaluatePolicyFast(policy, request, defaultEffect, caches)\n    } catch (err) {\n      onPolicyError?.(err instanceof Error ? err : new Error(String(err)), policy)\n      return null\n    }\n  }\n\n  if (combine === 'allow-overrides') {\n    let anyApplicable = false\n    for (const policy of policies) {\n      const r = safeEval(policy)\n      if (r === null) continue\n      anyApplicable = true\n      if (r) return true\n    }\n    if (!anyApplicable) {\n      const allowed = defaultEffect === 'allow'\n      if (signals && allowed) signals.failOpen = true\n      return allowed\n    }\n    return false\n  }\n\n  // 'and' (and 'first-applicable' fall-through, which Engine ctor blocks for prod).\n  let anyApplicable = false\n  for (const policy of policies) {\n    const r = safeEval(policy)\n    if (r === null) continue\n    anyApplicable = true\n    if (!r) return false\n  }\n  if (!anyApplicable) {\n    const allowed = defaultEffect === 'allow'\n    if (signals && allowed) signals.failOpen = true\n    return allowed\n  }\n  return true\n}\n\n/**\n * Out-parameter shape for {@link evaluateFast}. Callers pass an empty object;\n * the evaluator mutates fields as side-effects are observed. Useful for\n * metrics that need details the boolean return cannot carry.\n */\nexport interface IEvalSignals {\n  /**\n   * Set to `true` only when the engine returned `allow` because the\n   * `defaultEffect` fallback was triggered - i.e. no applicable policy fired.\n   * Never set when an explicit allow rule matched. Operators chart this to\n   * detect silent failures of the policy set (broken adapter, mass deletion,\n   * etc.) that the boolean verdict alone hides.\n   */\n  failOpen?: boolean\n}\n","/**\n * Hook fire-and-forget helpers. Both wrap user-provided callbacks so a\n * throw never escapes the call site. `console.error` itself can throw\n * (closed stdout in a daemon, a broken pipe, a buggy user-replaced\n * Console), so the diagnostic write is also wrapped.\n */\n\nimport type { AccessControl, IamRequest } from '../types'\nimport type { IamEngineTypes } from './engine.types'\n\nexport async function safeHookCall(fn: () => unknown, hookName: string): Promise<void> {\n  try {\n    await fn()\n  } catch (err) {\n    try {\n      console.error(`[@gentleduck/iam:engine] ${hookName} hook threw - swallowed to preserve decision`, err)\n    } catch {\n      /* last-resort: give up logging; decision is more important than diagnostics */\n    }\n  }\n}\n\nexport function emitMetrics<TAction extends string, TResource extends string, TScope extends string>(\n  hooks: IamEngineTypes.IHooks<TAction, TResource, TScope>,\n  req: IamRequest.IAccessRequest<TAction, TResource, TScope>,\n  allowed: boolean,\n  t0: number,\n  failOpen: boolean,\n  mode: AccessControl.Mode,\n): void {\n  const hook = hooks.onMetrics\n  if (!hook) return\n  try {\n    hook({\n      subjectId: req.subject.id,\n      action: req.action,\n      resource: req.resource.type,\n      allowed,\n      durationMs: performance.now() - t0,\n      mode,\n      failOpen,\n    })\n  } catch (err) {\n    try {\n      console.error('[@gentleduck/iam:engine] onMetrics hook threw - swallowed to preserve decision', err)\n    } catch {\n      /* last-resort: give up logging */\n    }\n  }\n}\n","/**\n * Cache + in-flight invalidation logic, extracted from the Engine class\n * so the class file stays focused on the eval pipeline. Every function\n * here takes the caches + invalidator explicitly so it can be unit-tested\n * without standing up a full Engine.\n */\n\nimport type { IamLRUCache } from '../../shared/cache'\nimport type { AccessControl, IamRequest } from '../types'\nimport type { IamEngineTypes } from './engine.types'\n\nexport interface IEngineCacheBag<TRole extends string = string> {\n  policyCache: IamLRUCache<AccessControl.IPolicy[]>\n  roleCache: IamLRUCache<AccessControl.IRole[]>\n  rbacPolicyCache: IamLRUCache<AccessControl.IPolicy>\n  mergedPolicyCache: IamLRUCache<AccessControl.IPolicy[]>\n  subjectCache: IamLRUCache<IamRequest.ISubject>\n  inFlight: IEngineInFlightBag\n  invalidator?: IamEngineTypes.IInvalidator<TRole>\n}\n\nexport interface IEngineInFlightBag {\n  policies: { value: Promise<AccessControl.IPolicy[]> | null }\n  roles: { value: Promise<AccessControl.IRole[]> | null }\n  rbac: { value: Promise<AccessControl.IPolicy> | null }\n  merged: { value: Promise<AccessControl.IPolicy[]> | null }\n  subjects: Map<string, Promise<IamRequest.ISubject>>\n}\n\nexport function invalidateAll<TRole extends string>(bag: IEngineCacheBag<TRole>, opts: { broadcast?: boolean }): void {\n  bag.policyCache.clear()\n  bag.roleCache.clear()\n  bag.rbacPolicyCache.clear()\n  bag.subjectCache.clear()\n  bag.inFlight.policies.value = null\n  bag.inFlight.roles.value = null\n  bag.inFlight.rbac.value = null\n  bag.inFlight.merged.value = null\n  bag.mergedPolicyCache.clear()\n  bag.inFlight.subjects.clear()\n  if (opts.broadcast !== false && bag.invalidator) {\n    void bag.invalidator.publish({ kind: 'all' })\n  }\n}\n\nexport function invalidateSubject<TRole extends string>(\n  bag: IEngineCacheBag<TRole>,\n  subjectId: string,\n  opts: { broadcast?: boolean },\n): void {\n  if (typeof subjectId !== 'string' || subjectId.length === 0 || subjectId.length > 1024) return\n  bag.subjectCache.delete(subjectId)\n  bag.inFlight.subjects.delete(subjectId)\n  if (opts.broadcast !== false && bag.invalidator) {\n    void bag.invalidator.publish({ kind: 'subject', subjectId })\n  }\n}\n\nexport function invalidatePolicies<TRole extends string>(\n  bag: IEngineCacheBag<TRole>,\n  opts: { broadcast?: boolean },\n): void {\n  bag.policyCache.clear()\n  bag.inFlight.policies.value = null\n  bag.inFlight.merged.value = null\n  bag.mergedPolicyCache.clear()\n  if (opts.broadcast !== false && bag.invalidator) {\n    void bag.invalidator.publish({ kind: 'policies' })\n  }\n}\n\nexport function invalidateRoles<TRole extends string>(\n  bag: IEngineCacheBag<TRole>,\n  roleIdInput: TRole | undefined,\n  opts: { broadcast?: boolean },\n): void {\n  let roleId = roleIdInput\n  if (roleId !== undefined && (typeof roleId !== 'string' || roleId.length === 0 || roleId.length > 1024)) {\n    roleId = undefined\n  }\n  bag.roleCache.clear()\n  bag.rbacPolicyCache.clear()\n  bag.inFlight.roles.value = null\n  bag.inFlight.rbac.value = null\n  bag.inFlight.merged.value = null\n  bag.mergedPolicyCache.clear()\n  if (roleId === undefined) {\n    bag.subjectCache.clear()\n    bag.inFlight.subjects.clear()\n  } else {\n    for (const [subjectId, subject] of bag.subjectCache.entries()) {\n      const inRoles = subject.roles.includes(roleId)\n      const inScoped = subject.scopedRoles?.some((sr) => sr.role === roleId) ?? false\n      if (inRoles || inScoped) {\n        bag.subjectCache.delete(subjectId)\n        bag.inFlight.subjects.delete(subjectId)\n      }\n    }\n  }\n  if (opts.broadcast !== false && bag.invalidator) {\n    void bag.invalidator.publish({ kind: 'roles', roleId })\n  }\n}\n\nexport function applyInvalidateEvent<TRole extends string>(\n  bag: IEngineCacheBag<TRole>,\n  event: IamEngineTypes.IInvalidateEvent<TRole>,\n): void {\n  switch (event.kind) {\n    case 'all':\n      invalidateAll(bag, { broadcast: false })\n      return\n    case 'policies':\n      invalidatePolicies(bag, { broadcast: false })\n      return\n    case 'roles':\n      invalidateRoles(bag, event.roleId, { broadcast: false })\n      return\n    case 'subject':\n      invalidateSubject(bag, event.subjectId, { broadcast: false })\n      return\n  }\n}\n","import type { AccessControl, IamAdapter, IamPrimitives, IamRequest } from '../types'\nimport type { IamValidate } from '../validate/validate.types'\nimport type { IamEngineTypes } from './engine.types'\n\n/**\n * Lazy validator binding. The `../validate` module is ~12 KB gzipped; users who\n * never call `engine.admin.savePolicy/saveRole/import` shouldn't pay for it at\n * import time. Loaded on first admin write and memoised.\n */\nlet _validateBindings: {\n  validatePolicy: typeof import('../validate').validatePolicy\n  validateRole: typeof import('../validate').validateRole\n} | null = null\nasync function _getValidate() {\n  if (!_validateBindings) {\n    const v = await import('../validate')\n    _validateBindings = { validatePolicy: v.validatePolicy, validateRole: v.validateRole }\n  }\n  return _validateBindings\n}\n\n/**\n * Single-flight helper for single-slot in-flight promises.\n *\n * Encapsulates the sentinel-compare pattern used by `_loadPolicies`,\n * `_loadRoles`, `_loadRbacPolicy`, `_loadAllPolicies`. A concurrent caller\n * sees the same `pending` promise; an `invalidate*()` mid-await nulls the\n * slot, and the sentinel check prevents the late resolver from writing\n * stale data into the now-cleared cache.\n *\n * @template T - Resolved value type.\n * @param getSlot - Reads the current in-flight slot (returns `null` if empty).\n * @param setSlot - Writes the in-flight slot (`null` clears it).\n * @param produce - Async producer for the value.\n * @param onResolve - Called only when the slot still holds the original\n *   pending promise. Use this to populate the cache.\n * @returns The pending promise (also stored in the slot until resolved).\n */\nexport function runSingleFlight<T>(\n  getSlot: () => Promise<T> | null,\n  setSlot: (p: Promise<T> | null) => void,\n  produce: () => Promise<T>,\n  onResolve: (value: T) => void,\n): Promise<T> {\n  let pending!: Promise<T>\n  pending = (async () => {\n    try {\n      const value = await produce()\n      if (getSlot() === pending) onResolve(value)\n      return value\n    } finally {\n      if (getSlot() === pending) setSlot(null)\n    }\n  })()\n  setSlot(pending)\n  return pending\n}\n\n/**\n * Keyed single-flight for per-key in-flight maps (subjects).\n *\n * Same shape as {@link runSingleFlight} but keyed on a Map entry. Identity\n * equality on the Promise reference disambiguates concurrent callers.\n */\nexport function runSingleFlightKeyed<K, T>(\n  map: Map<K, Promise<T>>,\n  key: K,\n  produce: () => Promise<T>,\n  onResolve: (value: T) => void,\n): Promise<T> {\n  let pending!: Promise<T>\n  pending = (async () => {\n    try {\n      const value = await produce()\n      if (map.get(key) === pending) onResolve(value)\n      return value\n    } finally {\n      if (map.get(key) === pending) map.delete(key)\n    }\n  })()\n  map.set(key, pending)\n  return pending\n}\n\n/** Throw if the validate result has any `error`-type issue. */\nfunction assertValidOrThrow(kind: 'policy' | 'role', result: IamValidate.IResult): void {\n  if (result.valid) return\n  const errs = result.issues\n    .filter((i) => i.type === 'error')\n    .map((i) => (i.path ? `${i.code} at \"${i.path}\"` : i.code))\n  throw new Error(`[@gentleduck/iam:engine] ${kind} rejected by validator - ${errs.join('; ')}`)\n}\n\nfunction assertNonEmptyStringParam(name: string, value: unknown): asserts value is string {\n  if (typeof value !== 'string' || value.length === 0) {\n    const got = value === null ? 'null' : typeof value\n    throw new Error(`[@gentleduck/iam:engine] ${name} must be a non-empty string (got ${got})`)\n  }\n  // 1024-char cap so a hostile caller cannot bloat the adapter call (URL\n  // length on HTTP adapter, key length on Redis, JSON column size on SQL).\n  if (value.length > 1024) {\n    throw new Error(`[@gentleduck/iam:engine] ${name} exceeds 1024-char cap (got length ${value.length})`)\n  }\n}\n\nfunction assertOptionalNonEmptyStringParam(name: string, value: unknown): asserts value is string | undefined {\n  if (value === undefined) return\n  assertNonEmptyStringParam(name, value)\n}\n\nfunction assertAttributesParam(value: unknown): asserts value is IamPrimitives.Attributes {\n  if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n    const got = value === null ? 'null' : Array.isArray(value) ? 'array' : typeof value\n    throw new Error(`[@gentleduck/iam:engine] attributes must be a plain object (got ${got})`)\n  }\n  // 256 own-key cap so a hostile caller cannot push an unbounded attributes\n  // bag through setSubjectAttributes (would bloat the JSON column / Redis\n  // string + every downstream resolve()).\n  const keyCount = Object.keys(value).length\n  if (keyCount > 256) {\n    throw new Error(`[@gentleduck/iam:engine] attributes must have <=256 keys (got ${keyCount})`)\n  }\n  // Reject deep nesting: resolve() walks dot-paths to depth ~8 in practice.\n  // 16 is a safe ceiling that defends against stack-overflow when the\n  // walker recurses (and rejects pathological `{a:{a:{...}}}` shapes).\n  const depth = _measureDepth(value)\n  if (depth > 16) {\n    throw new Error(`[@gentleduck/iam:engine] attributes nesting depth ${depth} exceeds cap (16)`)\n  }\n}\n\nfunction _measureDepth(node: unknown, current = 0): number {\n  if (current > 32) return current\n  if (typeof node !== 'object' || node === null) return current\n  let max = current\n  if (Array.isArray(node)) {\n    for (const v of node) {\n      const d = _measureDepth(v, current + 1)\n      if (d > max) max = d\n      if (max > 32) return max\n    }\n  } else {\n    for (const v of Object.values(node)) {\n      const d = _measureDepth(v, current + 1)\n      if (d > max) max = d\n      if (max > 32) return max\n    }\n  }\n  return max\n}\n\nfunction formatErrInterp(value: unknown, maxLen = 64): string {\n  if (value === null) return 'null'\n  if (value === undefined) return 'undefined'\n  const t = typeof value\n  if (t === 'string') {\n    const s = value as string\n    if (s.length <= maxLen) return `string '${s}'`\n    return `string '${s.slice(0, maxLen)}...' (length ${s.length})`\n  }\n  if (t === 'number' || t === 'boolean' || t === 'bigint') return `${t} ${String(value)}`\n  if (Array.isArray(value)) return `array (length ${value.length})`\n  return t\n}\n\n/** Recursively freeze a policy's rules, condition groups, and condition leaves. */\nexport function deepFreezePolicy<TPolicy extends AccessControl.IPolicy>(policy: TPolicy): TPolicy {\n  for (const rule of policy.rules) {\n    if (Array.isArray(rule.actions)) Object.freeze(rule.actions)\n    if (Array.isArray(rule.resources)) Object.freeze(rule.resources)\n    if (rule.conditions) freezeConditionGroup(rule.conditions)\n    Object.freeze(rule)\n  }\n  Object.freeze(policy.rules)\n  return Object.freeze(policy)\n}\n\nfunction freezeConditionGroup(group: AccessControl.IConditionGroup): void {\n  if ('all' in group) freezeConditionArray(group.all)\n  if ('any' in group) freezeConditionArray(group.any)\n  if ('none' in group) freezeConditionArray(group.none)\n  Object.freeze(group)\n}\n\nfunction freezeConditionArray(arr: ReadonlyArray<AccessControl.ICondition | AccessControl.IConditionGroup>): void {\n  for (const item of arr) {\n    if ('field' in item) Object.freeze(item)\n    else freezeConditionGroup(item)\n  }\n  Object.freeze(arr)\n}\n/**\n * Enrich a subject's roles with scoped role assignments matching the request scope.\n *\n * If a user has role `'editor'` scoped to `'org-1'` and the request scope is `'org-1'`,\n * `'editor'` is added to `subject.roles` for this evaluation. Returns the original\n * subject unchanged when no scoped roles match.\n *\n * @template TScope - Union of valid scope strings.\n *\n * @param subject - The resolved subject with potential scoped role assignments\n * @param scope   - The scope to match against scoped role assignments\n * @returns A new subject with merged roles, or the original subject if no matches\n */\nexport function enrichSubjectWithScopedRoles<TScope extends string = string>(\n  subject: IamRequest.ISubject,\n  scope: TScope | undefined,\n): IamRequest.ISubject {\n  if (scope == null || !subject.scopedRoles?.length) return subject\n\n  const extraRoles = subject.scopedRoles.filter((sr) => sr.scope === scope).map((sr) => sr.role)\n\n  if (extraRoles.length === 0) return subject\n\n  const mergedRoles = [...new Set([...subject.roles, ...extraRoles])]\n  return { ...subject, roles: mergedRoles }\n}\n\n/**\n * Create an {@link IamEngineTypes.IAdmin} instance that delegates storage operations to the\n * given adapter and invalidates the engine's caches after mutations.\n *\n * @template TAction   - Union of valid action strings.\n * @template TResource - Union of valid resource strings.\n * @template TRole     - Union of valid role IDs.\n * @template TScope    - Union of valid scope strings.\n *\n * @param adapter - The storage adapter for policies, roles, and subject data\n * @param engine  - The engine instance whose caches should be invalidated on writes\n * @returns An {@link IamEngineTypes.IAdmin} object wired to the adapter and engine\n */\nexport function createAdmin<\n  TAction extends string = string,\n  TResource extends string = string,\n  TRole extends string = string,\n  TScope extends string = string,\n>(\n  adapter: IamAdapter.IAdapter<TAction, TResource, TRole, TScope>,\n  engine: {\n    cache: {\n      invalidatePolicies(): void\n      invalidateRoles(roleId?: TRole): void\n      invalidateSubject(subjectId: string): void\n    }\n  },\n): IamEngineTypes.IAdmin<TAction, TResource, TRole, TScope> {\n  return {\n    async listPolicies() {\n      return adapter.listPolicies()\n    },\n    async getPolicy(id: string) {\n      assertNonEmptyStringParam('id', id)\n      return adapter.getPolicy(id)\n    },\n    async savePolicy(policy: AccessControl.IPolicy<TAction, TResource, TRole>) {\n      const { validatePolicy } = await _getValidate()\n      assertValidOrThrow('policy', validatePolicy(policy))\n      await adapter.savePolicy(policy)\n      engine.cache.invalidatePolicies()\n    },\n    async deletePolicy(id: string) {\n      assertNonEmptyStringParam('id', id)\n      await adapter.deletePolicy(id)\n      engine.cache.invalidatePolicies()\n    },\n    async listRoles() {\n      return adapter.listRoles()\n    },\n    async getRole(id: string) {\n      assertNonEmptyStringParam('id', id)\n      return adapter.getRole(id)\n    },\n    async saveRole(role: AccessControl.IRole<TAction, TResource, TRole, TScope>) {\n      const { validateRole } = await _getValidate()\n      assertValidOrThrow('role', validateRole(role))\n      await adapter.saveRole(role)\n      engine.cache.invalidateRoles(role.id)\n    },\n    async deleteRole(id: string) {\n      assertNonEmptyStringParam('id', id)\n      await adapter.deleteRole(id)\n      engine.cache.invalidateRoles(id as TRole)\n    },\n    async assignRole(subjectId: string, roleId: TRole, scope?: TScope) {\n      assertNonEmptyStringParam('subjectId', subjectId)\n      assertNonEmptyStringParam('roleId', roleId)\n      assertOptionalNonEmptyStringParam('scope', scope)\n      await adapter.assignRole(subjectId, roleId, scope)\n      engine.cache.invalidateSubject(subjectId)\n    },\n    async revokeRole(subjectId: string, roleId: TRole, scope?: TScope) {\n      assertNonEmptyStringParam('subjectId', subjectId)\n      assertNonEmptyStringParam('roleId', roleId)\n      assertOptionalNonEmptyStringParam('scope', scope)\n      await adapter.revokeRole(subjectId, roleId, scope)\n      engine.cache.invalidateSubject(subjectId)\n    },\n    async setAttributes(subjectId: string, attrs: IamPrimitives.Attributes) {\n      assertNonEmptyStringParam('subjectId', subjectId)\n      assertAttributesParam(attrs)\n      await adapter.setSubjectAttributes(subjectId, attrs)\n      engine.cache.invalidateSubject(subjectId)\n    },\n    async getAttributes(subjectId: string) {\n      assertNonEmptyStringParam('subjectId', subjectId)\n      return adapter.getSubjectAttributes(subjectId)\n    },\n    async export(): Promise<IamEngineTypes.ISnapshot<TAction, TResource, TRole, TScope>> {\n      const [policies, roles] = await Promise.all([adapter.listPolicies(), adapter.listRoles()])\n      return {\n        schemaVersion: 1 as const,\n        exportedAt: new Date().toISOString(),\n        policies,\n        roles,\n      }\n    },\n    async import(\n      snapshot: IamEngineTypes.ISnapshot<TAction, TResource, TRole, TScope>,\n      options: IamEngineTypes.IImportOptions = {},\n    ): Promise<IamEngineTypes.IImportResult> {\n      if (snapshot?.schemaVersion !== 1) {\n        const incoming =\n          snapshot !== null && typeof snapshot === 'object' ? Reflect.get(snapshot, 'schemaVersion') : snapshot\n        throw new Error(\n          `[@gentleduck/iam:engine] unsupported snapshot schemaVersion ${formatErrInterp(incoming)}; expected 1`,\n        )\n      }\n      const mode = options.mode ?? 'merge'\n      let policiesDeleted = 0\n      let rolesDeleted = 0\n      if (mode === 'replace') {\n        const [existingPolicies, existingRoles] = await Promise.all([adapter.listPolicies(), adapter.listRoles()])\n        const incomingPolicyIds = new Set(snapshot.policies.map((p) => p.id))\n        const incomingRoleIds = new Set(snapshot.roles.map((r) => r.id))\n        for (const p of existingPolicies) {\n          if (!incomingPolicyIds.has(p.id)) {\n            await adapter.deletePolicy(p.id)\n            policiesDeleted++\n          }\n        }\n        for (const r of existingRoles) {\n          if (!incomingRoleIds.has(r.id)) {\n            await adapter.deleteRole(r.id)\n            rolesDeleted++\n          }\n        }\n      }\n      const { validatePolicy, validateRole } = await _getValidate()\n      for (const p of snapshot.policies) {\n        assertValidOrThrow('policy', validatePolicy(p))\n        await adapter.savePolicy(p)\n      }\n      for (const r of snapshot.roles) {\n        assertValidOrThrow('role', validateRole(r))\n        await adapter.saveRole(r)\n      }\n      // Bulk write touched every cache; invalidate once instead of per-row.\n      engine.cache.invalidatePolicies()\n      engine.cache.invalidateRoles()\n      return {\n        policiesAdded: snapshot.policies.length,\n        policiesDeleted,\n        rolesAdded: snapshot.roles.length,\n        rolesDeleted,\n      }\n    },\n  }\n}\n","/**\n * Stats snapshot/reset, extracted from Engine. Pure plumbing over the\n * five caches.\n */\n\nimport type { IamLRUCache } from '../../shared/cache'\nimport type { AccessControl, IamRequest } from '../types'\n\nexport interface IIamCachesForStats {\n  policyCache: IamLRUCache<AccessControl.IPolicy[]>\n  roleCache: IamLRUCache<AccessControl.IRole[]>\n  rbacPolicyCache: IamLRUCache<AccessControl.IPolicy>\n  mergedPolicyCache: IamLRUCache<AccessControl.IPolicy[]>\n  subjectCache: IamLRUCache<IamRequest.ISubject>\n}\n\nexport interface IStatsSnapshot {\n  policies: { hits: number; misses: number; size: number }\n  roles: { hits: number; misses: number; size: number }\n  rbacPolicy: { hits: number; misses: number; size: number }\n  mergedPolicies: { hits: number; misses: number; size: number }\n  subjects: { hits: number; misses: number; size: number }\n}\n\nexport function statsSnapshot(c: IIamCachesForStats): IStatsSnapshot {\n  return {\n    policies: c.policyCache.stats,\n    roles: c.roleCache.stats,\n    rbacPolicy: c.rbacPolicyCache.stats,\n    mergedPolicies: c.mergedPolicyCache.stats,\n    subjects: c.subjectCache.stats,\n  }\n}\n\nexport function resetStats(c: IIamCachesForStats): void {\n  c.policyCache.resetStats()\n  c.roleCache.resetStats()\n  c.rbacPolicyCache.resetStats()\n  c.mergedPolicyCache.resetStats()\n  c.subjectCache.resetStats()\n}\n\nexport function aggregateCacheHitRate(s: IStatsSnapshot): { total: number; hits: number; rate: number } {\n  const total =\n    s.policies.hits +\n    s.policies.misses +\n    s.roles.hits +\n    s.roles.misses +\n    s.rbacPolicy.hits +\n    s.rbacPolicy.misses +\n    s.mergedPolicies.hits +\n    s.mergedPolicies.misses +\n    s.subjects.hits +\n    s.subjects.misses\n  const hits = s.policies.hits + s.roles.hits + s.rbacPolicy.hits + s.mergedPolicies.hits + s.subjects.hits\n  return { total, hits, rate: total === 0 ? 0 : hits / total }\n}\n","/**\n * Boot/health/dispose helpers. The healthCheck logic is a pure\n * function of (adapter probe, stats snapshot) so it's trivially\n * unit-testable.\n */\n\nimport { aggregateCacheHitRate, type IIamCachesForStats, statsSnapshot } from './engine.stats'\nimport type { IamEngineTypes } from './engine.types'\n\nexport async function runHealthCheck(\n  caches: IIamCachesForStats,\n  probe: () => Promise<void>,\n): Promise<IamEngineTypes.IHealth> {\n  const t0 = performance.now()\n  let adapter: 'ok' | 'fail' = 'ok'\n  let lastError: string | undefined\n  try {\n    await probe()\n  } catch (err) {\n    adapter = 'fail'\n    lastError = err instanceof Error ? err.message : String(err)\n  }\n  const s = statsSnapshot(caches)\n  const { rate } = aggregateCacheHitRate(s)\n  return {\n    ok: adapter === 'ok',\n    adapter,\n    cacheHitRate: rate,\n    adapterLatencyMs: Math.round(performance.now() - t0),\n    ...(lastError !== undefined && { lastError }),\n  }\n}\n\nexport async function preloadEngine(args: {\n  loadAllPolicies: () => Promise<unknown>\n  loadValidator: boolean\n}): Promise<void> {\n  const tasks: Array<Promise<unknown>> = [args.loadAllPolicies()]\n  if (args.loadValidator) tasks.push(import('../validate'))\n  await Promise.all(tasks)\n}\n\nexport function disposeInvalidator(invalidatorUnsub: (() => void) | null): { unsub: (() => void) | null } {\n  if (invalidatorUnsub) {\n    try {\n      invalidatorUnsub()\n    } catch {\n      /* last-resort: drop the throw, we're already tearing down */\n    }\n  }\n  return { unsub: null }\n}\n","/**\n * Cache-fronted loaders pulled out of the Engine class. Each takes a\n * minimal dependency bag so the single-flight + adapter-timeout +\n * max-rows guard logic is testable in isolation.\n */\n\nimport type { IamLRUCache } from '../../shared/cache'\nimport { resolveEffectiveRoles, rolesToPolicy } from '../rbac'\nimport type { AccessControl, IamAdapter, IamRequest } from '../types'\nimport type { IEngineInFlightBag } from './engine.invalidation'\nimport { deepFreezePolicy, runSingleFlight, runSingleFlightKeyed } from './engine.libs'\n\nexport interface IIamLoaderDeps<\n  TAction extends string,\n  TResource extends string,\n  TRole extends string,\n  TScope extends string,\n> {\n  adapter: IamAdapter.IAdapter<TAction, TResource, TRole, TScope>\n  policyCache: IamLRUCache<AccessControl.IPolicy[]>\n  roleCache: IamLRUCache<AccessControl.IRole[]>\n  rbacPolicyCache: IamLRUCache<AccessControl.IPolicy>\n  mergedPolicyCache: IamLRUCache<AccessControl.IPolicy[]>\n  subjectCache: IamLRUCache<IamRequest.ISubject>\n  inFlight: IEngineInFlightBag\n  maxPolicies: number\n  maxRoles: number\n  withTimeout: <T>(fn: (opts: { signal: AbortSignal }) => Promise<T>, label: string) => Promise<T>\n}\n\nexport async function loadPolicies<\n  TAction extends string,\n  TResource extends string,\n  TRole extends string,\n  TScope extends string,\n>(deps: IIamLoaderDeps<TAction, TResource, TRole, TScope>): Promise<AccessControl.IPolicy[]> {\n  const cached = deps.policyCache.get('all')\n  if (cached) return cached\n  if (deps.inFlight.policies.value) return deps.inFlight.policies.value\n  return runSingleFlight(\n    () => deps.inFlight.policies.value,\n    (p) => {\n      deps.inFlight.policies.value = p\n    },\n    async () => {\n      const policies = await deps.withTimeout((opts) => deps.adapter.listPolicies(opts), 'listPolicies')\n      if (policies.length > deps.maxPolicies) {\n        throw new Error(\n          `[@gentleduck/iam:engine] adapter returned ${policies.length} policies; maxPolicies is ${deps.maxPolicies}. Raise the limit or fix the adapter.`,\n        )\n      }\n      return policies\n    },\n    (policies) => {\n      deps.policyCache.set('all', policies)\n    },\n  )\n}\n\nexport async function loadRoles<\n  TAction extends string,\n  TResource extends string,\n  TRole extends string,\n  TScope extends string,\n>(deps: IIamLoaderDeps<TAction, TResource, TRole, TScope>): Promise<AccessControl.IRole[]> {\n  const cached = deps.roleCache.get('all')\n  if (cached) return cached\n  if (deps.inFlight.roles.value) return deps.inFlight.roles.value\n  return runSingleFlight(\n    () => deps.inFlight.roles.value,\n    (p) => {\n      deps.inFlight.roles.value = p\n    },\n    async () => {\n      const roles = await deps.withTimeout((opts) => deps.adapter.listRoles(opts), 'listRoles')\n      if (roles.length > deps.maxRoles) {\n        throw new Error(\n          `[@gentleduck/iam:engine] adapter returned ${roles.length} roles; maxRoles is ${deps.maxRoles}. Raise the limit or fix the adapter.`,\n        )\n      }\n      return roles\n    },\n    (roles) => {\n      deps.roleCache.set('all', roles)\n    },\n  )\n}\n\nexport async function resolveSubject<\n  TAction extends string,\n  TResource extends string,\n  TRole extends string,\n  TScope extends string,\n>(deps: IIamLoaderDeps<TAction, TResource, TRole, TScope>, subjectId: string): Promise<IamRequest.ISubject> {\n  const cached = deps.subjectCache.get(subjectId)\n  if (cached) return cached\n  const inFlight = deps.inFlight.subjects.get(subjectId)\n  if (inFlight) return inFlight\n  return runSingleFlightKeyed(\n    deps.inFlight.subjects,\n    subjectId,\n    async () => {\n      const [assignedRoles, attributes, allRoles] = await Promise.all([\n        deps.withTimeout((opts) => deps.adapter.getSubjectRoles(subjectId, opts), 'getSubjectRoles'),\n        deps.withTimeout((opts) => deps.adapter.getSubjectAttributes(subjectId, opts), 'getSubjectAttributes'),\n        loadRoles(deps),\n      ])\n      const roles = resolveEffectiveRoles(assignedRoles, allRoles)\n      const scopedRolesFn = deps.adapter.getSubjectScopedRoles\n      const scopedRoles = scopedRolesFn\n        ? await deps.withTimeout((opts) => scopedRolesFn.call(deps.adapter, subjectId, opts), 'getSubjectScopedRoles')\n        : undefined\n      const subject: IamRequest.ISubject = { id: subjectId, roles, scopedRoles, attributes }\n      return subject\n    },\n    (subject) => {\n      deps.subjectCache.set(subjectId, subject)\n    },\n  )\n}\n\nexport async function loadRbacPolicy<\n  TAction extends string,\n  TResource extends string,\n  TRole extends string,\n  TScope extends string,\n>(deps: IIamLoaderDeps<TAction, TResource, TRole, TScope>): Promise<AccessControl.IPolicy> {\n  const cached = deps.rbacPolicyCache.get('rbac')\n  if (cached) return cached\n  if (deps.inFlight.rbac.value) return deps.inFlight.rbac.value\n  return runSingleFlight(\n    () => deps.inFlight.rbac.value,\n    (p) => {\n      deps.inFlight.rbac.value = p\n    },\n    async () => {\n      const roles = await loadRoles(deps)\n      return deepFreezePolicy(rolesToPolicy(roles))\n    },\n    (built) => {\n      deps.rbacPolicyCache.set('rbac', built)\n    },\n  )\n}\n\nexport async function loadAllPolicies<\n  TAction extends string,\n  TResource extends string,\n  TRole extends string,\n  TScope extends string,\n>(deps: IIamLoaderDeps<TAction, TResource, TRole, TScope>): Promise<AccessControl.IPolicy[]> {\n  const cached = deps.mergedPolicyCache.get('merged')\n  if (cached) return cached\n  if (deps.inFlight.merged.value) return deps.inFlight.merged.value\n  return runSingleFlight(\n    () => deps.inFlight.merged.value,\n    (p) => {\n      deps.inFlight.merged.value = p\n    },\n    async () => {\n      const [policies, rbacPolicy] = await Promise.all([loadPolicies(deps), loadRbacPolicy(deps)])\n      return rbacPolicy.rules.length === 0 ? policies : [rbacPolicy, ...policies]\n    },\n    (merged) => {\n      deps.mergedPolicyCache.set('merged', merged)\n    },\n  )\n}\n","import { IamLRUCache } from '../../shared/cache'\nimport { iamBuildPermissionKey } from '../../shared/keys'\nimport { clearRegexCache } from '../conditions/conditions.libs'\nimport { evaluate, evaluateFast } from '../evaluate'\nimport type { Explain } from '../explain'\nimport { clearPathCache } from '../resolve/resolve'\nimport type { AccessControl, IamAdapter, IamClient, IamRequest } from '../types'\nimport { emitMetrics, safeHookCall } from './engine.hooks'\nimport {\n  applyInvalidateEvent,\n  type IEngineCacheBag,\n  invalidateAll,\n  invalidatePolicies,\n  invalidateRoles,\n  invalidateSubject,\n} from './engine.invalidation'\nimport { createAdmin, enrichSubjectWithScopedRoles } from './engine.libs'\nimport { disposeInvalidator, preloadEngine, runHealthCheck } from './engine.lifecycle'\nimport { type IIamLoaderDeps, loadAllPolicies, resolveSubject } from './engine.loaders'\nimport { resetStats as resetStatsHelper, statsSnapshot as statsSnapshotHelper } from './engine.stats'\nimport type { IamEngineTypes } from './engine.types'\n\n/** Flush process-wide regex + dot-path caches; schedule periodically in multi-tenant deployments. */\nexport function iamFlushSharedCaches(): void {\n  clearRegexCache()\n  clearPathCache()\n}\n/**\n * Central runtime that evaluates access requests against RBAC roles and ABAC\n * policies.\n *\n * Loads roles + policies from its adapter, caches them with configurable TTL,\n * converts RBAC roles into ABAC rules via {@link rolesToPolicy}, and merges\n * decisions across all policies according to its `policyCombine` setting\n * (default `'and'`; see {@link AccessControl.PolicyCombine}).\n *\n * @template TAction   - Union of valid action strings.\n * @template TResource - Union of valid resource strings.\n * @template TRole     - Union of valid role IDs.\n * @template TScope    - Union of valid scope strings.\n * @template TMode     - Engine mode (`'development'` or `'production'`) that\n *   determines whether return types are `IDecision` or plain `boolean`.\n *\n * @example\n * ```ts\n * const engine = new IamEngine({ adapter, defaultEffect: 'deny' })\n *\n * const allowed = await engine.can('user-1', 'read', { type: 'post', attributes: {} })\n * const decision = await engine.check('user-1', 'update', post)\n * const trace = await engine.explain('user-1', 'delete', post)\n * ```\n */\nexport class IamEngine<\n  TAction extends string = string,\n  TResource extends string = string,\n  TRole extends string = string,\n  TScope extends string = string,\n  TMode extends AccessControl.Mode = 'development',\n> {\n  private _adapter: IamAdapter.IAdapter<TAction, TResource, TRole, TScope>\n  private _defaultEffect: AccessControl.Effect\n  private _mode: AccessControl.Mode\n  private _policyCombine: AccessControl.PolicyCombine\n  private _hooks: IamEngineTypes.IHooks<TAction, TResource, TScope>\n  private _maxPolicies: number\n  private _maxRoles: number\n  private _adapterTimeoutMs: number\n  private _invalidator?: IamEngineTypes.IInvalidator<TRole>\n  private _invalidatorUnsub: (() => void) | null = null\n  private _policyCache: IamLRUCache<AccessControl.IPolicy[]>\n  private _roleCache: IamLRUCache<AccessControl.IRole[]>\n  private _rbacPolicyCache: IamLRUCache<AccessControl.IPolicy>\n  private _mergedPolicyCache: IamLRUCache<AccessControl.IPolicy[]>\n  private _subjectCache: IamLRUCache<IamRequest.ISubject>\n  // Single-flight: coalesce concurrent cache-misses so a cold start under load\n  // doesn't fan out N identical adapter calls. Cleared once the promise settles.\n  private _inFlight = {\n    policies: { value: null as Promise<AccessControl.IPolicy[]> | null },\n    roles: { value: null as Promise<AccessControl.IRole[]> | null },\n    rbac: { value: null as Promise<AccessControl.IPolicy> | null },\n    merged: { value: null as Promise<AccessControl.IPolicy[]> | null },\n    subjects: new Map<string, Promise<IamRequest.ISubject>>(),\n  }\n  /**\n   * Per-instance evaluation caches. Multi-tenant deployments instantiate\n   * one Engine per tenant; each owns its own regex + path caches and\n   * cannot be evicted by hostile-tenant pattern flooding.\n   */\n  private _caches: { regex: Map<string, RegExp>; path: Map<string, string[] | null> } = {\n    regex: new Map(),\n    path: new Map(),\n  }\n\n  /**\n   * Cache invalidation facet. Groups the five cache-management calls so the\n   * Engine API surface stays focused on evaluation. Use after policy/role/\n   * subject mutations to drop stale entries; pass `{ broadcast: false }`\n   * when applying an event received from another instance.\n   *\n   * @since 3.0.0 - replaces the flat `engine.invalidate*` methods.\n   */\n  readonly cache = {\n    /** Clear every cache + in-flight resolver. */\n    invalidate: (opts: { broadcast?: boolean } = {}): void => this._invalidateAll(opts),\n    /** Clear one subject's cached resolved roles + attributes. */\n    invalidateSubject: (subjectId: string, opts: { broadcast?: boolean } = {}): void =>\n      this._invalidateSubject(subjectId, opts),\n    /** Clear cached policies (after policy CRUD). */\n    invalidatePolicies: (opts: { broadcast?: boolean } = {}): void => this._invalidatePolicies(opts),\n    /** Clear cached roles + RBAC policy; selectively drops affected subjects. */\n    invalidateRoles: (roleId?: TRole, opts: { broadcast?: boolean } = {}): void => this._invalidateRoles(roleId, opts),\n  }\n\n  /**\n   * Observability facet. Cache hit/miss/size counters plus a zero op.\n   *\n   * @since 3.0.0 - replaces the flat `engine.stats()` / `engine.resetStats()`.\n   */\n  readonly stats = {\n    /** Snapshot per-cache counters. Counters accumulate from construction. */\n    get: (): {\n      policies: { hits: number; misses: number; size: number }\n      roles: { hits: number; misses: number; size: number }\n      rbacPolicy: { hits: number; misses: number; size: number }\n      mergedPolicies: { hits: number; misses: number; size: number }\n      subjects: { hits: number; misses: number; size: number }\n    } => this._statsSnapshot(),\n    /** Zero the counters returned by {@link stats.get}. */\n    reset: (): void => this._resetStats(),\n  }\n\n  /**\n   * Constructs a new engine wired to the given adapter and configuration.\n   *\n   * @param config - Engine configuration (adapter, mode, caches, hooks).\n   */\n  constructor(config: IamEngineTypes.IConfig<TAction, TResource, TRole, TScope, TMode>) {\n    this._adapter = config.adapter\n    this._defaultEffect = config.defaultEffect ?? 'deny'\n    this._mode = config.mode ?? 'development'\n    this._policyCombine = config.policyCombine ?? 'and'\n    this._hooks = config.hooks ?? {}\n\n    // evaluateFast can't represent first-applicable; fail at construction.\n    if (this._mode === 'production' && this._policyCombine === 'first-applicable') {\n      throw new Error(\n        \"[@gentleduck/iam:engine] policyCombine 'first-applicable' requires mode 'development'; the production fast path cannot represent it correctly.\",\n      )\n    }\n\n    // `defaultEffect: 'allow'` is a fail-open footgun; require explicit opt-in.\n    if (this._defaultEffect === 'allow' && !config.allowFailOpen) {\n      throw new Error(\n        \"[@gentleduck/iam:engine] defaultEffect 'allow' is a fail-open footgun. Pass `allowFailOpen: true` to confirm intent.\",\n      )\n    }\n    // Even with the opt-in, emit a loud startup warning so an operator\n    // grep'ing logs for fail-open configurations always finds it.\n    if (this._defaultEffect === 'allow') {\n      // eslint-disable-next-line no-console\n      console.warn(\n        \"[@gentleduck/iam:engine] engine configured with defaultEffect: 'allow' (fail-open). Every request with no applicable policy will be allowed.\",\n      )\n    }\n\n    this._maxPolicies = config.maxPolicies ?? 10_000\n    this._maxRoles = config.maxRoles ?? 10_000\n    this._adapterTimeoutMs = config.adapterTimeoutMs ?? 5_000\n\n    // Reject non-finite caps; `NaN > x` is always false so a NaN limit\n    // silently disables the bound.\n    if (!Number.isFinite(this._maxPolicies) || this._maxPolicies < 1) {\n      throw new RangeError('[@gentleduck/iam:engine] maxPolicies must be a finite number >= 1')\n    }\n    if (!Number.isFinite(this._maxRoles) || this._maxRoles < 1) {\n      throw new RangeError('[@gentleduck/iam:engine] maxRoles must be a finite number >= 1')\n    }\n    if (!Number.isFinite(this._adapterTimeoutMs) || this._adapterTimeoutMs < 0) {\n      throw new RangeError('[@gentleduck/iam:engine] adapterTimeoutMs must be a finite number >= 0')\n    }\n\n    const ttl = (config.cacheTTL ?? 60) * 1000\n    const maxSize = config.maxCacheSize ?? 1000\n\n    this._policyCache = new IamLRUCache(1, ttl) // single entry\n    this._roleCache = new IamLRUCache(1, ttl)\n    this._rbacPolicyCache = new IamLRUCache(1, ttl)\n    this._mergedPolicyCache = new IamLRUCache(1, ttl)\n    this._subjectCache = new IamLRUCache(maxSize, ttl)\n\n    if (config.invalidator) {\n      this._invalidator = config.invalidator\n      this._invalidatorUnsub = config.invalidator.subscribe((event) => this._applyInvalidateEvent(event))\n    }\n  }\n\n  /**\n   * Wrap an adapter read with the engine's configured timeout. Creates a\n   * fresh `AbortController` per call so a slow upstream gets hard-cancelled\n   * once `adapterTimeoutMs` elapses; the timeout error routes through\n   * `authorize`'s catch and produces a fail-closed deny.\n   *\n   * Returns the adapter call result. Throws on timeout. Adapters that don't\n   * honor `signal` still get their result discarded - the engine just\n   * doesn't wait for them.\n   */\n  private _withTimeout<T>(fn: (opts: { signal: AbortSignal }) => Promise<T>, label: string): Promise<T> {\n    if (this._adapterTimeoutMs <= 0) {\n      return fn({ signal: new AbortController().signal })\n    }\n    const ctrl = new AbortController()\n    let timer: ReturnType<typeof setTimeout> | null = null\n    const timeout = new Promise<never>((_, reject) => {\n      timer = setTimeout(() => {\n        ctrl.abort()\n        reject(new Error(`[@gentleduck/iam:engine] ${label} timed out after ${this._adapterTimeoutMs}ms`))\n      }, this._adapterTimeoutMs)\n    })\n    return Promise.race<T>([fn({ signal: ctrl.signal }), timeout]).finally(() => {\n      if (timer) clearTimeout(timer)\n    })\n  }\n\n  /** @internal Build the cache-bag the helper modules use to mutate state. */\n  private _cacheBag(): IEngineCacheBag<TRole> {\n    return {\n      policyCache: this._policyCache,\n      roleCache: this._roleCache,\n      rbacPolicyCache: this._rbacPolicyCache,\n      mergedPolicyCache: this._mergedPolicyCache,\n      subjectCache: this._subjectCache,\n      inFlight: this._inFlight,\n      ...(this._invalidator !== undefined && { invalidator: this._invalidator }),\n    }\n  }\n\n  /** Apply a cross-instance invalidate event to local caches. */\n  private _applyInvalidateEvent(event: IamEngineTypes.IInvalidateEvent<TRole>): void {\n    applyInvalidateEvent(this._cacheBag(), event)\n  }\n\n  /** Release the invalidator subscription. Call when discarding the engine. */\n  dispose(): void {\n    this._invalidatorUnsub = disposeInvalidator(this._invalidatorUnsub).unsub\n  }\n\n  /** Load all policies from the adapter, using the cache if available. */\n  /** @internal Build the loader deps. */\n  private _loaderDeps(): IIamLoaderDeps<TAction, TResource, TRole, TScope> {\n    return {\n      adapter: this._adapter,\n      policyCache: this._policyCache,\n      roleCache: this._roleCache,\n      rbacPolicyCache: this._rbacPolicyCache,\n      mergedPolicyCache: this._mergedPolicyCache,\n      subjectCache: this._subjectCache,\n      inFlight: this._inFlight,\n      maxPolicies: this._maxPolicies,\n      maxRoles: this._maxRoles,\n      withTimeout: (fn, label) => this._withTimeout(fn, label),\n    }\n  }\n\n  private _resolveSubject(subjectId: string): Promise<IamRequest.ISubject> {\n    return resolveSubject(this._loaderDeps(), subjectId)\n  }\n\n  private _loadAllPolicies(): Promise<AccessControl.IPolicy[]> {\n    return loadAllPolicies(this._loaderDeps())\n  }\n\n  /**\n   * Bridges the runtime `this._mode` branch to the static `AccessControl.ModeResult<TMode>`\n   * conditional type. Centralized so the assertion is named and grep-able\n   * instead of scattered across each return statement.\n   */\n  private _asResult(value: boolean | AccessControl.IDecision): AccessControl.ModeResult<TMode> {\n    return value as AccessControl.ModeResult<TMode>\n  }\n\n  /**\n   * Full authorization check with a complete {@link IamRequest.IAccessRequest}.\n   *\n   * In `'production'` mode, returns a plain `boolean`.\n   * In `'development'` mode, returns a full {@link AccessControl.IDecision}.\n   *\n   * @param request - The access request to evaluate.\n   * @returns The decision shape determined by the engine's mode.\n   */\n  async authorize(\n    request: IamRequest.IAccessRequest<TAction, TResource, TScope>,\n  ): Promise<AccessControl.ModeResult<TMode>> {\n    let req = request\n    const t0 = this._hooks.onMetrics ? performance.now() : 0\n\n    // Trailing hooks run outside the evaluation try; a thrown hook must not\n    // rewrite an allow into deny via the catch.\n    let result: AccessControl.ModeResult<TMode>\n    let decisionForHooks: AccessControl.IDecision | null = null\n    let allowedForMetrics = false\n    let failOpenForMetrics = false\n    try {\n      // Normalise non-array roles; string would substring-match `contains <role>`.\n      if (req.subject && !Array.isArray(req.subject.roles)) {\n        req = { ...req, subject: { ...req.subject, roles: [] } }\n      }\n      if (req.scope && req.subject.scopedRoles?.length) {\n        const enriched = enrichSubjectWithScopedRoles(req.subject, req.scope)\n        if (enriched !== req.subject) req = { ...req, subject: enriched }\n      }\n\n      if (this._hooks.beforeEvaluate) {\n        req = await this._hooks.beforeEvaluate(req)\n      }\n\n      const allPolicies = await this._loadAllPolicies()\n\n      const onPolicyErrorHook = this._hooks.onPolicyError\n      const onPolicyError = onPolicyErrorHook\n        ? (err: Error, policy: AccessControl.IPolicy) => onPolicyErrorHook(err, policy.id)\n        : undefined\n\n      const signals: { failOpen?: boolean } = {}\n      if (this._mode === 'production') {\n        const allowed = evaluateFast(\n          allPolicies,\n          req,\n          this._defaultEffect,\n          this._policyCombine,\n          onPolicyError,\n          signals,\n          this._caches,\n        )\n        allowedForMetrics = allowed\n        failOpenForMetrics = signals.failOpen === true\n        result = this._asResult(allowed)\n      } else {\n        const decision = evaluate(\n          allPolicies,\n          req,\n          this._defaultEffect,\n          this._policyCombine,\n          onPolicyError,\n          signals,\n          this._caches,\n        )\n        decisionForHooks = decision\n        allowedForMetrics = decision.allowed\n        failOpenForMetrics = signals.failOpen === true\n        result = this._asResult(decision)\n      }\n    } catch (error) {\n      const err = error instanceof Error ? error : new Error(String(error))\n      // onError can itself throw. Don't let an operator's onError bug\n      // propagate over the engine's fail-closed behaviour.\n      await this._safeHookCall(() => this._hooks.onError?.(err, req), 'onError')\n      this._emitMetrics(req, false, t0, false)\n      if (this._mode === 'production') return this._asResult(false)\n      return this._asResult({\n        allowed: false,\n        effect: 'deny',\n        reason: 'Evaluation error',\n        duration: 0,\n        timestamp: Date.now(),\n      })\n    }\n\n    // Trailing hook block - runs OUTSIDE the evaluation try so a hook throw\n    // cannot rewrite the decision. Each hook is individually wrapped so a\n    // bug in one doesn't suppress the others.\n    if (decisionForHooks !== null) {\n      const d = decisionForHooks\n      await this._safeHookCall(() => this._hooks.afterEvaluate?.(req, d), 'afterEvaluate')\n      if (!d.allowed) {\n        await this._safeHookCall(() => this._hooks.onDeny?.(req, d), 'onDeny')\n      }\n    }\n    this._emitMetrics(req, allowedForMetrics, t0, failOpenForMetrics)\n    return result\n  }\n\n  /**\n   * Invoke a hook safely. Sync or async throws are caught and routed to\n   * console.error so a buggy operator hook cannot escape into the caller's\n   * path or rewrite a finalised decision. Returning void is intentional -\n   * the engine never surfaces hook bugs as authz failures.\n   */\n  private async _safeHookCall(fn: () => unknown, hookName: string): Promise<void> {\n    await safeHookCall(fn, hookName)\n  }\n\n  /**\n   * Fires the `onMetrics` hook if configured. Synchronous; takes the start\n   * timestamp captured at the top of `authorize` so the caller doesn't pay\n   * `performance.now()` cost when no hook is wired.\n   */\n  private _emitMetrics(\n    req: IamRequest.IAccessRequest<TAction, TResource, TScope>,\n    allowed: boolean,\n    t0: number,\n    failOpen: boolean,\n  ): void {\n    emitMetrics(this._hooks, req, allowed, t0, failOpen, this._mode)\n  }\n\n  /**\n   * Simple boolean check: can this user do this action on this resource?\n   * Always returns a plain `boolean` regardless of engine mode.\n   *\n   * @param subjectId   - Subject ID to resolve via the adapter.\n   * @param action      - Action the subject wants to perform.\n   * @param resource    - Target resource.\n   * @param environment - Optional request-time environment.\n   * @param scope       - Optional scope for multi-tenant checks.\n   * @returns `true` when the subject is authorized to perform the action.\n   */\n  async can(\n    subjectId: string,\n    action: TAction,\n    resource: IamRequest.IResource<TResource>,\n    environment?: IamRequest.IAccessRequest<TAction, TResource, TScope>['environment'],\n    scope?: TScope,\n  ): Promise<boolean> {\n    if (typeof subjectId !== 'string' || subjectId.length === 0 || subjectId.length > 1024) return false\n    try {\n      const subject = await this._resolveSubject(subjectId)\n      const result = await this.authorize({ subject, action, resource, environment, scope })\n      return typeof result === 'boolean' ? result : result.allowed\n    } catch (error) {\n      // Subject-resolution errors (adapter down, listRoles limit hit) escape\n      // authorize()'s try/catch. Translate to a fail-closed deny so callers\n      // never see an unhandled rejection from the entry-point methods.\n      const err = error instanceof Error ? error : new Error(String(error))\n      // _safeHookCall so a throwing onError cannot bypass fail-closed `return false`.\n      const errReq: IamRequest.IAccessRequest<TAction, TResource, TScope> = {\n        subject: { id: subjectId, roles: [], attributes: {} },\n        action,\n        resource,\n        environment,\n        scope,\n      }\n      await this._safeHookCall(() => this._hooks.onError?.(err, errReq), 'onError')\n      return false\n    }\n  }\n\n  /**\n   * Same as `can` but returns the full {@link AccessControl.IDecision} in development mode,\n   * or a plain boolean in production mode.\n   *\n   * @param subjectId   - Subject ID to resolve via the adapter.\n   * @param action      - Action the subject wants to perform.\n   * @param resource    - Target resource.\n   * @param environment - Optional request-time environment.\n   * @param scope       - Optional scope for multi-tenant checks.\n   * @returns Mode-dependent result: `boolean` in production, `IDecision` in development.\n   */\n  async check(\n    subjectId: string,\n    action: TAction,\n    resource: IamRequest.IResource<TResource>,\n    environment?: IamRequest.IAccessRequest<TAction, TResource, TScope>['environment'],\n    scope?: TScope,\n  ): Promise<AccessControl.ModeResult<TMode>> {\n    if (typeof subjectId !== 'string' || subjectId.length === 0 || subjectId.length > 1024) {\n      // Fail-closed: in production mode return false; otherwise a synthesized deny.\n      return (\n        this._mode === 'production' ? false : { allowed: false, reason: 'invalid subjectId' }\n      ) as AccessControl.ModeResult<TMode>\n    }\n    try {\n      const subject = await this._resolveSubject(subjectId)\n      return await this.authorize({ subject, action, resource, environment, scope })\n    } catch (error) {\n      const err = error instanceof Error ? error : new Error(String(error))\n      const req: IamRequest.IAccessRequest<TAction, TResource, TScope> = {\n        subject: { id: subjectId, roles: [], attributes: {} },\n        action,\n        resource,\n        environment,\n        scope,\n      }\n      // Wrap so a throwing operator onError cannot escape the documented\n      // fail-closed behaviour.\n      await this._safeHookCall(() => this._hooks.onError?.(err, req), 'onError')\n      if (this._mode === 'production') return this._asResult(false)\n      return this._asResult({\n        allowed: false,\n        effect: 'deny',\n        reason: 'Subject resolution error',\n        duration: 0,\n        timestamp: Date.now(),\n      })\n    }\n  }\n\n  /**\n   * Returns a full evaluation trace showing why a permission was granted or\n   * denied. Shows which policies matched, which rules fired, which conditions\n   * passed/failed with actual vs expected values, and a human-readable summary.\n   *\n   * Only available in `'development'` mode. Throws in `'production'` mode.\n   *\n   * Does NOT trigger afterEvaluate/onDeny/onError hooks (read-only).\n   * Does apply beforeEvaluate hook since it affects the evaluation.\n   *\n   * @param subjectId   - Subject ID to resolve via the adapter.\n   * @param action      - Action the subject wants to perform.\n   * @param resource    - Target resource.\n   * @param environment - Optional request-time environment.\n   * @param scope       - Optional scope for multi-tenant checks.\n   * @returns A full {@link Explain.IResult} describing the evaluation.\n   */\n  async explain(\n    this: IamEngine<TAction, TResource, TRole, TScope, 'development'>,\n    subjectId: string,\n    action: TAction,\n    resource: IamRequest.IResource<TResource>,\n    environment?: IamRequest.IAccessRequest<TAction, TResource, TScope>['environment'],\n    scope?: TScope,\n  ): Promise<Explain.IResult> {\n    if (this._mode === 'production') {\n      throw new Error('explain() is not available in production mode')\n    }\n    if (typeof subjectId !== 'string' || subjectId.length === 0 || subjectId.length > 1024) {\n      throw new Error('[@gentleduck/iam:engine] explain(): subjectId must be a non-empty string <=1024 chars')\n    }\n    const subject = await this._resolveSubject(subjectId)\n    const originalRoles = [...subject.roles]\n\n    let enrichedSubject = subject\n    if (scope && subject.scopedRoles?.length) {\n      enrichedSubject = enrichSubjectWithScopedRoles(subject, scope)\n    }\n\n    const scopedRolesApplied = enrichedSubject.roles.filter((r) => !originalRoles.includes(r))\n\n    let req: IamRequest.IAccessRequest<TAction, TResource, TScope> = {\n      subject: enrichedSubject,\n      action,\n      resource,\n      environment,\n      scope,\n    }\n\n    // Apply beforeEvaluate hook (it may modify the request)\n    if (this._hooks.beforeEvaluate) {\n      req = await this._hooks.beforeEvaluate(req)\n    }\n\n    const allPolicies = await this._loadAllPolicies()\n\n    // Lazy import: production mode users (which throw before this point)\n    // pay zero bytes for the explain chunk. Bundlers split this into its\n    // own chunk.\n    const { explainEvaluation } = await import('../explain')\n\n    return explainEvaluation(\n      allPolicies,\n      req,\n      this._defaultEffect,\n      { subjectId, originalRoles, scopedRolesApplied },\n      this._policyCombine,\n    )\n  }\n\n  /**\n   * Batch check: evaluate many permissions at once for a single subject.\n   * Returns a map keyed by \"action:resource\" or \"scope:action:resource\".\n   * Loads adapter data once, then evaluates each check.\n   * Each check goes through scoped role enrichment and hooks, consistent with authorize().\n   *\n   * In `'production'` mode, returns `Record<string, boolean>`.\n   * In `'development'` mode, returns the full typed {@link IamClient.PermissionMap}.\n   *\n   * @param subjectId   - Subject ID to resolve via the adapter.\n   * @param checks      - Array of {@link IamClient.IPermissionCheck} descriptors.\n   * @param environment - Optional request-time environment shared by all checks.\n   * @returns Mode-dependent permission map.\n   */\n  async permissions(\n    subjectId: string,\n    checks: readonly IamClient.IPermissionCheck<TAction, TResource, TScope>[],\n    environment?: IamRequest.IAccessRequest<TAction, TResource, TScope>['environment'],\n    opts: { telemetry?: boolean } = {},\n  ): Promise<AccessControl.ModePermissionMap<TMode, TAction, TResource, TScope>> {\n    if (typeof subjectId !== 'string' || subjectId.length === 0 || subjectId.length > 1024) {\n      throw new Error('[@gentleduck/iam:engine] permissions(): subjectId must be a non-empty string <=1024 chars')\n    }\n    // Defensive cap: prevents an unbounded batch (e.g. attacker-driven UI gate\n    // that floods checks) from running into thousands of per-check evaluations.\n    // 1024 covers any plausible legitimate batch.\n    if (checks.length > 1024) {\n      throw new Error('[@gentleduck/iam:engine] permissions() refuses batches >1024 checks')\n    }\n    // `telemetry: false` skips per-check onMetrics for hot UI gates (~2x throughput).\n    const telemetry = opts.telemetry !== false\n    // Outer try synthesises all-deny on subject/policy load failure.\n    let subject: IamRequest.ISubject\n    let allPolicies: AccessControl.IPolicy[]\n    try {\n      ;[subject, allPolicies] = await Promise.all([this._resolveSubject(subjectId), this._loadAllPolicies()])\n    } catch (error) {\n      const err = error instanceof Error ? error : new Error(String(error))\n      const failClosed: Record<string, boolean> = {}\n      for (const c of checks) {\n        failClosed[iamBuildPermissionKey(c.action, c.resource, c.resourceId, c.scope)] = false\n      }\n      const errReq: IamRequest.IAccessRequest<TAction, TResource, TScope> = {\n        subject: { id: subjectId, roles: [], attributes: {} },\n        action: checks[0]?.action ?? ('' as TAction),\n        resource: { type: checks[0]?.resource ?? ('' as TResource), attributes: {} },\n        environment,\n      }\n      await this._safeHookCall(() => this._hooks.onError?.(err, errReq), 'onError')\n      return failClosed as AccessControl.ModePermissionMap<TMode, TAction, TResource, TScope>\n    }\n\n    const map: Record<string, boolean> = {}\n    // Memo per scope: N checks sharing a scope must not rebuild the merged role list N times.\n    const enrichedByScope = new Map<TScope, IamRequest.ISubject>()\n\n    // Forward onPolicyError to evaluate* so batch checks surface per-policy\n    // throws instead of silently dropping them.\n    const onPolicyErrorHook = this._hooks.onPolicyError\n    const onPolicyError = onPolicyErrorHook\n      ? (err: Error, policy: AccessControl.IPolicy) => onPolicyErrorHook(err, policy.id)\n      : undefined\n\n    for (const c of checks) {\n      const key = iamBuildPermissionKey(c.action, c.resource, c.resourceId, c.scope)\n      // Per-check metrics: onMetrics fires once per check with failOpen signal\n      // (unless `telemetry: false`).\n      const t0 = telemetry && this._hooks.onMetrics ? performance.now() : 0\n\n      // Trailing-hooks block runs OUTSIDE the evaluation try so a throwing\n      // afterEvaluate/onDeny cannot rewrite the per-check verdict.\n      let decisionForHooks: AccessControl.IDecision | null = null\n      let allowedForCheck = false\n      let failOpenForCheck = false\n      let evalReq: IamRequest.IAccessRequest<TAction, TResource, TScope> | null = null\n\n      try {\n        let enrichedSubject = subject\n        if (c.scope && subject.scopedRoles?.length) {\n          const cached = enrichedByScope.get(c.scope)\n          if (cached) {\n            enrichedSubject = cached\n          } else {\n            enrichedSubject = enrichSubjectWithScopedRoles(subject, c.scope)\n            enrichedByScope.set(c.scope, enrichedSubject)\n          }\n        }\n\n        let req: IamRequest.IAccessRequest<TAction, TResource, TScope> = {\n          subject: enrichedSubject,\n          action: c.action,\n          resource: { type: c.resource, id: c.resourceId, attributes: {} },\n          environment,\n          scope: c.scope,\n        }\n\n        if (this._hooks.beforeEvaluate) {\n          req = await this._hooks.beforeEvaluate(req)\n        }\n\n        const signals: { failOpen?: boolean } = {}\n\n        if (this._mode === 'production') {\n          const allowed = evaluateFast(\n            allPolicies,\n            req,\n            this._defaultEffect,\n            this._policyCombine,\n            onPolicyError,\n            signals,\n            this._caches,\n          )\n          map[key] = allowed\n          allowedForCheck = allowed\n          failOpenForCheck = signals.failOpen === true\n          evalReq = req\n        } else {\n          const decision = evaluate(\n            allPolicies,\n            req,\n            this._defaultEffect,\n            this._policyCombine,\n            onPolicyError,\n            signals,\n            this._caches,\n          )\n          map[key] = decision.allowed\n          decisionForHooks = decision\n          allowedForCheck = decision.allowed\n          failOpenForCheck = signals.failOpen === true\n          evalReq = req\n        }\n      } catch (error) {\n        const err = error instanceof Error ? error : new Error(String(error))\n        const errReq: IamRequest.IAccessRequest<TAction, TResource, TScope> = {\n          subject,\n          action: c.action,\n          resource: { type: c.resource, id: c.resourceId, attributes: {} },\n          environment,\n          scope: c.scope,\n        }\n        await this._safeHookCall(() => this._hooks.onError?.(err, errReq), 'onError')\n        if (telemetry) this._emitMetrics(errReq, false, t0, false)\n        map[key] = false\n        continue\n      }\n\n      // Trailing-hooks block (outside try) - keeps hook throws from\n      // rewriting the per-check verdict; mirrors authorize().\n      if (decisionForHooks !== null && evalReq !== null) {\n        const d = decisionForHooks\n        const r = evalReq\n        await this._safeHookCall(() => this._hooks.afterEvaluate?.(r, d), 'afterEvaluate')\n        if (!d.allowed) {\n          await this._safeHookCall(() => this._hooks.onDeny?.(r, d), 'onDeny')\n        }\n      }\n      if (telemetry && evalReq !== null) this._emitMetrics(evalReq, allowedForCheck, t0, failOpenForCheck)\n    }\n\n    return map as AccessControl.ModePermissionMap<TMode, TAction, TResource, TScope>\n  }\n\n  private _admin?: IamEngineTypes.IAdmin<TAction, TResource, TRole, TScope>\n\n  /** Lazily-built admin interface for CRUD operations on policies, roles, subjects. */\n  get admin(): IamEngineTypes.IAdmin<TAction, TResource, TRole, TScope> {\n    this._admin ??= createAdmin<TAction, TResource, TRole, TScope>(this._adapter, this)\n    return this._admin\n  }\n\n  /** @internal Cache references for the stats helper. */\n  private _cachesForStats() {\n    return {\n      policyCache: this._policyCache,\n      roleCache: this._roleCache,\n      rbacPolicyCache: this._rbacPolicyCache,\n      mergedPolicyCache: this._mergedPolicyCache,\n      subjectCache: this._subjectCache,\n    }\n  }\n\n  /** @internal Snapshot per-cache counters. Reached via {@link stats.get}. */\n  private _statsSnapshot(): {\n    policies: { hits: number; misses: number; size: number }\n    roles: { hits: number; misses: number; size: number }\n    rbacPolicy: { hits: number; misses: number; size: number }\n    mergedPolicies: { hits: number; misses: number; size: number }\n    subjects: { hits: number; misses: number; size: number }\n  } {\n    return statsSnapshotHelper(this._cachesForStats())\n  }\n\n  /** @internal Zero per-cache counters. Reached via {@link stats.reset}. */\n  private _resetStats(): void {\n    resetStatsHelper(this._cachesForStats())\n  }\n\n  /** @internal Clear all caches + in-flight resolvers. Reached via {@link cache.invalidate}. */\n  private _invalidateAll(opts: { broadcast?: boolean } = {}): void {\n    invalidateAll(this._cacheBag(), opts)\n  }\n\n  /** @internal Clear one subject's cached data. Reached via {@link cache.invalidateSubject}. */\n  private _invalidateSubject(subjectId: string, opts: { broadcast?: boolean } = {}): void {\n    invalidateSubject(this._cacheBag(), subjectId, opts)\n  }\n\n  /** @internal Clear cached policies. Reached via {@link cache.invalidatePolicies}. */\n  private _invalidatePolicies(opts: { broadcast?: boolean } = {}): void {\n    invalidatePolicies(this._cacheBag(), opts)\n  }\n\n  /** @internal Clear cached roles + selectively drop affected subjects. Reached via {@link cache.invalidateRoles}. */\n  private _invalidateRoles(roleId?: TRole, opts: { broadcast?: boolean } = {}): void {\n    invalidateRoles(this._cacheBag(), roleId, opts)\n  }\n\n  /**\n   * Warm `mergedPolicyCache` so the first request after boot doesn't pay the\n   * full load + index cost. Bench shows ~15x speedup on the first call vs\n   * cold. Recommended to call once at app startup.\n   *\n   * Pass `{ validator: true }` to also eagerly load the lazy validator\n   * chunk (12 KB gzipped). Useful for operators who want to front-load\n   * every cost at boot instead of paying it on first admin write. Read-only\n   * services can leave it off.\n   */\n  async preload(opts: { validator?: boolean } = {}): Promise<void> {\n    await preloadEngine({\n      loadAllPolicies: () => this._loadAllPolicies(),\n      loadValidator: opts.validator === true,\n    })\n  }\n\n  /**\n   * Liveness + readiness probe. Performs one timed-out adapter round-trip\n   * (`listPolicies`) and snapshots cache hit rates. Cheap enough to wire to\n   * a `/healthz` route at the configured interval; returns `ok: false` if the\n   * adapter is unreachable so an orchestrator can pull the instance out of\n   * rotation.\n   *\n   * @returns A {@link IamEngineTypes.IHealth} snapshot.\n   */\n  async healthCheck(): Promise<IamEngineTypes.IHealth> {\n    return runHealthCheck(this._cachesForStats(), async () => {\n      await this._withTimeout((opts) => this._adapter.listPolicies(opts), 'healthCheck.listPolicies')\n    })\n  }\n}\n","import { PolicyBuilder, RoleBuilder, RuleBuilder, When } from '../builder'\nimport type { IamEngineTypes } from '../engine'\nimport { IamEngine } from '../engine'\nimport type { AccessControl, DotPath, IamClient } from '../types'\nimport { validatePolicy, validateRoles } from '../validate'\nimport type { IamConfig } from './config.types'\n\n/**\n * Creates a type-safe access configuration for your application.\n *\n * The primary entry point for duck-iam. Pass your permission schema\n * using `as const` arrays and get back an {@link IamConfig.IAccessConfig} with fully typed\n * builder methods.\n *\n * @template TActions   - Tuple of action strings, declared `as const`.\n * @template TResources - Tuple of resource strings, declared `as const`.\n * @template TScopes    - Tuple of scope strings, declared `as const`.\n * @template TRoles     - Tuple of role ID strings, declared `as const`.\n * @template TContext   - Shape of the evaluation context for typed dot-paths.\n *\n * @param input - Your permission schema: actions, resources, and optionally scopes, roles, and context.\n * @returns A typed {@link IamConfig.IAccessConfig} with constrained builder methods.\n *\n * @example\n * ```ts\n * const iam = createIam({\n *   actions: ['create', 'read', 'update', 'delete'] as const,\n *   resources: ['post', 'comment', 'user'] as const,\n *   roles: ['viewer', 'editor', 'admin'] as const,\n *   context: {} as unknown as AppContext,\n * })\n *\n * // All builders are now type-safe:\n * iam.defineRole('viewer').grant('read', 'post')   // OK\n * iam.defineRole('viewer').grant('raed', 'post')   // compile error\n * ```\n */\nexport function createIam<\n  const TActions extends readonly string[],\n  const TResources extends readonly string[],\n  const TRoles extends readonly string[] = readonly string[],\n  const TScopes extends readonly string[] = readonly string[],\n  TContext extends object = DotPath.IDefaultContext,\n>(\n  input: IamConfig.IAccessConfigInput<TActions, TResources, TRoles, TScopes, TContext>,\n): IamConfig.IAccessConfig<TActions[number], TResources[number], TRoles[number], TScopes[number], TContext> {\n  type TAction = TActions[number]\n  type TResource = TResources[number]\n  type TRole = TRoles[number]\n  type TScope = TScopes[number]\n\n  return {\n    actions: input.actions,\n    resources: input.resources,\n    scopes: input.scopes ?? [],\n    roles: input.roles ?? [],\n\n    defineRole: (id: TRole) => new RoleBuilder<TAction, TResource, TRole, TScope, TContext>(id),\n\n    definePolicy: (id: string) => new PolicyBuilder<TAction, TResource, TRole, TScope, TContext>(id),\n\n    defineRule: (id: string) => new RuleBuilder<TAction, TResource, TScope, TRole, TContext>(id),\n\n    when: () => new When<TAction, TResource, TRole, TScope, TContext>(),\n\n    createEngine: <TMode extends AccessControl.Mode = 'development'>(\n      config: IamEngineTypes.IConfig<TAction, TResource, TRole, TScope, TMode>,\n    ) => new IamEngine<TAction, TResource, TRole, TScope, TMode>(config),\n\n    checks: <const T extends readonly IamClient.IPermissionCheck<TAction, TResource, TScope>[]>(checks: T) => checks,\n\n    validateRoles: (roles: readonly AccessControl.IRole<TAction, TResource, string, TScope>[]) => validateRoles(roles),\n\n    validatePolicy: (input: unknown) => validatePolicy(input),\n  }\n}\n","/** Per-Engine evaluation caches; evaluators accept `caches?` to scope regex/path caches per instance. */\nexport interface IamEvalCaches {\n  /** Compiled-regex LRU shared by the `matches` operator. */\n  regex: Map<string, RegExp>\n  /** Resolved dot-path segment FIFO. */\n  path: Map<string, string[] | null>\n}\n\n/**\n * Construct a fresh pair of evaluation caches.\n *\n * @returns A new {@link IamEvalCaches} with empty maps.\n */\nexport function iamCreateEvalCaches(): IamEvalCaches {\n  return { regex: new Map(), path: new Map() }\n}\n"],"mappings":";;;;;;;;;;;;AAMA,IAAa,cAAb,MAA4B;CAC1B,AAAQ,uBAAO,IAAI,IAA6C;CAChE,AAAQ;CACR,AAAQ;CACR,AAAQ,QAAQ;CAChB,AAAQ,UAAU;;;;;;CAOlB,YAAY,SAAiB,OAAe;EAC1C,IAAI,CAAC,OAAO,SAAS,OAAO,KAAK,UAAU,GACzC,MAAM,IAAI,WAAW,kDAAkD;EACzE,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,GAAG,MAAM,IAAI,WAAW,gDAAgD;EAC/G,KAAK,WAAW;EAChB,KAAK,OAAO;CACd;;;;;;;CAQA,IAAI,KAA4B;EAC9B,MAAM,QAAQ,KAAK,KAAK,IAAI,GAAG;EAC/B,IAAI,CAAC,OAAO;GACV,KAAK;GACL;EACF;EACA,IAAI,KAAK,IAAI,IAAI,MAAM,WAAW;GAChC,KAAK,KAAK,OAAO,GAAG;GACpB,KAAK;GACL;EACF;EAEA,KAAK,KAAK,OAAO,GAAG;EACpB,KAAK,KAAK,IAAI,KAAK,KAAK;EACxB,KAAK;EACL,OAAO,MAAM;CACf;;CAGA,IAAI,QAAwD;EAC1D,OAAO;GAAE,MAAM,KAAK;GAAO,QAAQ,KAAK;GAAS,MAAM,KAAK,KAAK;EAAK;CACxE;;CAGA,aAAmB;EACjB,KAAK,QAAQ;EACb,KAAK,UAAU;CACjB;;;;;;;CAQA,IAAI,KAAa,OAAgB;EAC/B,KAAK,KAAK,OAAO,GAAG;EACpB,IAAI,KAAK,KAAK,QAAQ,KAAK,UAAU;GACnC,MAAM,QAAQ,KAAK,KAAK,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;GACtC,IAAI,UAAU,QAAW,KAAK,KAAK,OAAO,KAAK;EACjD;EACA,KAAK,KAAK,IAAI,KAAK;GAAE;GAAO,WAAW,KAAK,IAAI,IAAI,KAAK;EAAK,CAAC;CACjE;;;;;;;CAQA,OAAO,KAAsB;EAC3B,OAAO,KAAK,KAAK,OAAO,GAAG;CAC7B;;CAGA,QAAc;EACZ,KAAK,KAAK,MAAM;CAClB;CAEA,IAAI,OAAe;EACjB,OAAO,KAAK,KAAK;CACnB;;CAGA,CAAC,UAAyC;EACxC,MAAM,MAAM,KAAK,IAAI;EACrB,KAAK,MAAM,CAAC,KAAK,UAAU,KAAK,MAAM;GACpC,IAAI,MAAM,MAAM,WAAW;GAC3B,MAAM,CAAC,KAAK,MAAM,KAAK;EACzB;CACF;AACF;;;;;;;;;;;;;;;;ACvFA,SAAgB,YACd,MACA,KACA,QACS;CAET,IAAI,CADgB,KAAK,QAAQ,MAAM,MAAMA,sCAAc,GAAG,IAAI,MAAM,CACzD,GAAG,OAAO;CAGzB,MAAM,iBAAiB,IAAI,SAAS,KAAK,SAAS,GAAG;CASrD,IAAI,CAPkB,KAAK,UAAU,MAAM,MAAM;EAE/C,IAAI,kBAAkB,EAAE,SAAS,GAAG,GAClC,OAAOC,oDAA4B,GAAG,IAAI,SAAS,IAAI;EAEzD,OAAOC,wCAAgB,GAAG,IAAI,SAAS,IAAI;CAC7C,CACiB,GAAG,OAAO;CAE3B,OAAOC,mCAAmB,KAAK,KAAK,YAAY,GAAG,MAAM;AAC3D;;;;;;;;;;;;AAaA,SAAgB,cAAc,QAA+B,KAAyC;CACpG,IAAI,CAAC,OAAO,SAAS,OAAO;CAE5B,MAAM,EAAE,SAAS,WAAW,UAAU,OAAO;CAE7C,IAAI,SAAS,UAAU,CAAC,QAAQ,MAAM,MAAMH,sCAAc,GAAG,IAAI,MAAM,CAAC,GACtE,OAAO;CAGT,IAAI,WAAW,UAAU,CAAC,UAAU,MAAM,MAAME,wCAAgB,GAAG,IAAI,SAAS,IAAI,CAAC,GACnF,OAAO;CAGT,IAAI,OAAO,QAAQ;EACjB,MAAM,eAAe,MAAM,QAAQ,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,QAAQ,CAAC;EAC7E,IAAI,CAAC,MAAM,MAAM,SAAS,aAAa,SAAS,IAAI,CAAC,GACnD,OAAO;CAEX;CAEA,OAAO;AACT;;;;;;;;;AAUA,MAAa,YAAyE;CACpF,mBAAmB,SAAS,kBAAkB;EAC5C,MAAM,OAAO,QAAQ,MAAM,MAAM,EAAE,WAAW,MAAM;EACpD,IAAI,MACF,OAAO;GACL,MAAM,KAAK;GACX,QAAQ;GACR,QAAQ,mBAAmB,KAAK,KAAK,GAAG;EAC1C;EAEF,MAAM,QAAQ,QAAQ,MAAM,MAAM,EAAE,WAAW,OAAO;EACtD,IAAI,OACF,OAAO;GACL,MAAM,MAAM;GACZ,QAAQ;GACR,QAAQ,oBAAoB,MAAM,KAAK,GAAG;EAC5C;EAEF,OAAO;GAAE,QAAQ;GAAe,QAAQ,mCAAmC;EAAgB;CAC7F;CAEA,oBAAoB,SAAS,kBAAkB;EAC7C,MAAM,QAAQ,QAAQ,MAAM,MAAM,EAAE,WAAW,OAAO;EACtD,IAAI,OACF,OAAO;GACL,MAAM,MAAM;GACZ,QAAQ;GACR,QAAQ,oBAAoB,MAAM,KAAK,GAAG;EAC5C;EAEF,MAAM,OAAO,QAAQ,MAAM,MAAM,EAAE,WAAW,MAAM;EACpD,IAAI,MACF,OAAO;GACL,MAAM,KAAK;GACX,QAAQ;GACR,QAAQ,mBAAmB,KAAK,KAAK,GAAG;EAC1C;EAEF,OAAO;GAAE,QAAQ;GAAe,QAAQ,mCAAmC;EAAgB;CAC7F;CAEA,gBAAgB,SAAS,kBAAkB;EACzC,IAAI,QAAQ,WAAW,GACrB,OAAO;GAAE,QAAQ;GAAe,QAAQ,mCAAmC;EAAgB;EAG7F,IAAI,QAAQ,QAAQ;EACpB,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;GACvC,MAAM,MAAM,QAAQ;GACpB,IAAI,IAAI,KAAK,WAAW,MAAM,KAAK,UAAU,QAAQ;EACvD;EACA,OAAO;GACL,MAAM,MAAM;GACZ,QAAQ,MAAM;GACd,QAAQ,sBAAsB,MAAM,KAAK,GAAG,KAAK,MAAM,OAAO;EAChE;CACF;CAEA,qBAAqB,SAAS,kBAAkB;EAC9C,IAAI,QAAQ,SAAS,GAAG;GACtB,MAAM,MAAM,QAAQ,QAAQ,MAAM,QAAS,IAAI,KAAK,WAAW,KAAK,KAAK,WAAW,MAAM,IAAK;GAC/F,OAAO;IACL,MAAM,IAAI;IACV,QAAQ,IAAI;IACZ,QAAQ,2BAA2B,IAAI,KAAK,GAAG,OAAO,IAAI,KAAK,SAAS;GAC1E;EACF;EACA,OAAO;GAAE,QAAQ;GAAe,QAAQ,mCAAmC;EAAgB;CAC7F;AACF;;;;;;AAOA,SAAS,mBAAmB,GAAoB;CAC9C,OAAO,EAAE,SAAS,GAAG;AACvB;;AAGA,MAAM,6BAAa,IAAI,QAA0D;;;;;;;AAQjF,SAAgB,YAAY,QAA0D;CACpF,MAAM,SAAS,WAAW,IAAI,MAAM;CACpC,IAAI,QAAQ,OAAO;CAEnB,MAAM,mCAAmB,IAAI,IAAqC;CAClE,MAAM,cAAuC,CAAC;CAE9C,KAAK,MAAM,QAAQ,OAAO,OAAO;EAC/B,MAAM,UAAU,IAAI,IAAI,KAAK,OAAmB;EAChD,MAAM,YAAY,IAAI,IAAI,KAAK,SAAqB;EACpD,IAAI,oBAAoB;EACxB,KAAK,MAAM,KAAK,SACd,IAAI,mBAAmB,CAAC,GAAG;GACzB,oBAAoB;GACpB;EACF;EAEF,IAAI,sBAAsB;EAC1B,KAAK,MAAM,KAAK,WACd,IAAI,mBAAmB,CAAC,GAAG;GACzB,sBAAsB;GACtB;EACF;EAEF,MAAM,IAAI,KAAK;EACf,MAAM,gBAAgB,CAAC,CAAC,MAAM,SAAS,KAAK,SAAS,KAAK,UAAU;EACpE,MAAM,QAA+B;GACnC;GACA;GACA;GACA;GACA;GACA;EACF;EAEA,IAAI,qBAAqB,qBAAqB,YAAY,KAAK,KAAK;EAIpE,IAAI,CAAC,qBAAqB,CAAC,qBACzB,KAAK,MAAM,KAAK,SACd,KAAK,MAAM,KAAK,WAAW;GACzB,MAAM,MAAM,GAAG,EAAE,IAAI;GACrB,IAAI,SAAS,iBAAiB,IAAI,GAAG;GACrC,IAAI,CAAC,QAAQ;IACX,SAAS,CAAC;IACV,iBAAiB,IAAI,KAAK,MAAM;GAClC;GACA,OAAO,KAAK,KAAK;EACnB;CAGN;CAIA,MAAM,8BAAc,IAAI,IAAkC;CAC1D,MAAM,OAAO,OAAO;CAEpB,IAAI,YAAY,WAAW,MAAM,SAAS,oBAAoB,SAAS,qBAAqB,SAAS,gBACnG,KAAK,MAAM,QAAQ,OAAO,OAAO;EAC/B,MAAM,IAAI,KAAK;EACf,IAAI,SAAS,KAAK,SAAS,KAAK,UAAU,GAAG;EAC7C,IAAI,KAAK,QAAQ,KAAK,kBAAkB,KAAK,KAAK,UAAU,KAAK,kBAAkB,GAAG;EAEtF,KAAK,MAAM,KAAK,KAAK,SACnB,KAAK,MAAM,KAAK,KAAK,WAAW;GAC9B,MAAM,QAAQ,GAAG,EAAE,IAAI;GACvB,MAAM,UAAU,iBAAiB,IAAI,KAAK;GAC1C,IAAI,CAAC,SAAS;GAId,IAAI,mBAAmB;GACvB,KAAK,MAAM,KAAK,SAAS;IACvB,MAAM,KAAK,EAAE,KAAK;IAClB,IAAI,SAAS,MAAM,SAAS,MAAM,UAAU,IAAI;KAC9C,mBAAmB;KACnB;IACF;GACF;GACA,IAAI,CAAC,kBAAkB;GAGvB,IAAI;GACJ,IAAI,SAAS,kBAAkB;IAC7B,IAAI,WAAW;IACf,KAAK,MAAM,KAAK,SAAS;KACvB,IAAI,EAAE,KAAK,WAAW,QAAQ;MAC5B,SAAS;MACT;KACF;KACA,IAAI,EAAE,KAAK,WAAW,SAAS,WAAW;IAC5C;IACA,IAAI,WAAW,UAAa,UAAU,SAAS;GACjD,OAAO,IAAI,SAAS,mBAAmB;IACrC,IAAI,UAAU;IACd,KAAK,MAAM,KAAK,SAAS;KACvB,IAAI,EAAE,KAAK,WAAW,SAAS;MAC7B,SAAS;MACT;KACF;KACA,IAAI,EAAE,KAAK,WAAW,QAAQ,UAAU;IAC1C;IACA,IAAI,WAAW,UAAa,SAAS,SAAS;GAChD,OAAO,IAAI,SAAS,iBAAiB,QAAQ,SAAS,GAAG;IACvD,IAAI,OAAO,QAAQ;IACnB,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;KACvC,MAAM,MAAM,QAAQ;KACpB,IAAI,IAAI,KAAK,WAAW,KAAK,KAAK,UAAU,OAAO;IACrD;IACA,SAAS,KAAK,KAAK,WAAW;GAChC;GAEA,IAAI,WAAW,QAAW;IACxB,IAAI,YAAY,YAAY,IAAI,CAAC;IACjC,IAAI,CAAC,WAAW;KACd,4BAAY,IAAI,IAAI;KACpB,YAAY,IAAI,GAAG,SAAS;IAC9B;IACA,UAAU,IAAI,GAAG,MAAM;GACzB;EACF;CAEJ;CAGF,MAAM,MAAiC;EAAE;EAAkB;EAAa;CAAY;CACpF,WAAW,IAAI,QAAQ,GAAG;CAC1B,OAAO;AACT;;;;;;;;;AC5RA,SAAS,eACP,OACA,QACA,SACA,WACA,KACA,QACS;CAET,IAAI,CAAC,MAAM,qBAAqB,CAAC,MAAM,QAAQ,IAAI,MAAM,GAAG;EAC1D,IAAI,KAAK;EACT,KAAK,MAAM,KAAK,MAAM,KAAK,SACzB,IAAIE,sCAAc,GAAG,MAAM,GAAG;GAC5B,KAAK;GACL;EACF;EAEF,IAAI,CAAC,IAAI,OAAO;CAClB;CAGA,IAAI,CAAC,MAAM,qBAAqB;EAC9B,IAAI,KAAK;EACT,KAAK,MAAM,KAAK,MAAM,KAAK,WACzB,IAAI,aAAa,EAAE,SAAS,GAAG,GAC7B;OAAIC,oDAA4B,GAAG,OAAO,GAAG;IAC3C,KAAK;IACL;GACF;SAEA,IAAIC,wCAAgB,GAAG,OAAO,GAAG;GAC/B,KAAK;GACL;EACF;EAGJ,IAAI,CAAC,IAAI,OAAO;CAClB;CAEA,IAAI,CAAC,MAAM,eAAe,OAAO;CACjC,OAAOC,mCAAmB,KAAK,MAAM,KAAK,YAAY,GAAG,MAAM;AACjE;;;;;;;;;;;;AAaA,SAAgB,eACd,QACA,SACA,gBAAsC,QACtC,QACyB;CACzB,MAAM,QAAQ,YAAY,IAAI;CAE9B,IAAI,CAAC,cAAc,QAAQ,OAAO,GAGhC,OAAO;EACL,SAAS,kBAAkB;EAC3B,QAAQ;EACR,QAAQ,OAAO;EACf,QAAQ,WAAW,OAAO,GAAG;EAC7B,UAAU,YAAY,IAAI,IAAI;EAC9B,WAAW,KAAK,IAAI;EACpB,YAAY;CACd;CAGF,MAAM,UAA8E,CAAC;CAErF,KAAK,MAAM,QAAQ,OAAO,OACxB,IAAI,YAAY,MAAM,SAAS,MAAM,GACnC,QAAQ,KAAK;EAAE;EAAM,QAAQ,KAAK;CAAO,CAAC;CAI9C,MAAM,WAAW,UAAU,OAAO;CAClC,MAAM,SAAS,SAAS,SAAS,aAAa;CAE9C,OAAO;EACL,SAAS,OAAO,WAAW;EAC3B,QAAQ,OAAO;EACf,MAAM,OAAO;EACb,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,UAAU,YAAY,IAAI,IAAI;EAC9B,WAAW,KAAK,IAAI;CACtB;AACF;;;;;;;;;;;AAYA,SAAgB,SACd,UACA,SACA,gBAAsC,QACtC,UAAuC,OACvC,eACA,SACA,QACyB;CACzB,MAAM,QAAQ,YAAY,IAAI;CAE9B,IAAI,SAAS,WAAW,GAAG;EACzB,IAAI,WAAW,kBAAkB,SAAS,QAAQ,WAAW;EAC7D,OAAO;GACL,SAAS,kBAAkB;GAC3B,QAAQ;GACR,QAAQ;GACR,UAAU,YAAY,IAAI,IAAI;GAC9B,WAAW,KAAK,IAAI;EACtB;CACF;;;;;;CAOA,MAAM,YAAY,WAA2D;EAC3E,IAAI;GACF,OAAO,eAAe,QAAQ,SAAS,eAAe,MAAM;EAC9D,SAAS,KAAK;GACZ,gBAAgB,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM;GAC3E,OAAO;IACL,SAAS,kBAAkB;IAC3B,QAAQ;IACR,QAAQ;IACR,YAAY;IACZ,UAAU;IACV,WAAW,KAAK,IAAI;GACtB;EACF;CACF;CAEA,IAAI,YAAY,OAAO;EACrB,IAAI,YAA4C;EAChD,KAAK,MAAM,UAAU,UAAU;GAC7B,MAAM,WAAW,SAAS,MAAM;GAChC,IAAI,SAAS,eAAe,OAAO;GACnC,IAAI,CAAC,SAAS,SAAS,OAAO;IAAE,GAAG;IAAU,UAAU,YAAY,IAAI,IAAI;GAAM;GACjF,YAAY;EACd;EACA,IAAI,cAAc,MAAM;GACtB,IAAI,WAAW,kBAAkB,SAAS,QAAQ,WAAW;GAC7D,OAAO;IACL,SAAS,kBAAkB;IAC3B,QAAQ;IACR,QAAQ,sCAAsC;IAC9C,UAAU,YAAY,IAAI,IAAI;IAC9B,WAAW,KAAK,IAAI;GACtB;EACF;EACA,OAAO;GAAE,GAAG;GAAW,UAAU,YAAY,IAAI,IAAI;EAAM;CAC7D;CAEA,IAAI,YAAY,mBAAmB;EACjC,IAAI,WAA2C;EAC/C,KAAK,MAAM,UAAU,UAAU;GAC7B,MAAM,WAAW,SAAS,MAAM;GAChC,IAAI,SAAS,eAAe,OAAO;GACnC,IAAI,SAAS,SAAS,OAAO;IAAE,GAAG;IAAU,UAAU,YAAY,IAAI,IAAI;GAAM;GAChF,WAAW;EACb;EACA,IAAI,aAAa,MAAM;GACrB,IAAI,WAAW,kBAAkB,SAAS,QAAQ,WAAW;GAC7D,OAAO;IACL,SAAS,kBAAkB;IAC3B,QAAQ;IACR,QAAQ,sCAAsC;IAC9C,UAAU,YAAY,IAAI,IAAI;IAC9B,WAAW,KAAK,IAAI;GACtB;EACF;EACA,OAAO;GAAE,GAAG;GAAU,UAAU,YAAY,IAAI,IAAI;EAAM;CAC5D;CAEA,KAAK,MAAM,UAAU,UAAU;EAC7B,MAAM,WAAW,SAAS,MAAM;EAChC,IAAI,SAAS,eAAe,OAAO;EACnC,IAAI,SAAS,SAAS,QAAW,OAAO;GAAE,GAAG;GAAU,UAAU,YAAY,IAAI,IAAI;EAAM;CAC7F;CACA,IAAI,WAAW,kBAAkB,SAAS,QAAQ,WAAW;CAC7D,OAAO;EACL,SAAS,kBAAkB;EAC3B,QAAQ;EACR,QAAQ,0CAA0C;EAClD,UAAU,YAAY,IAAI,IAAI;EAC9B,WAAW,KAAK,IAAI;CACtB;AACF;;;;;;;;;AAUA,SAAgB,mBACd,QACA,SACA,gBAAsC,QACtC,QACgB;CAEhB,MAAM,UAAU,OAAO;CACvB,IAAI,SAAS;EACX,IAAI,QAAQ,SAAS,UAAU,CAAC,QAAQ,QAAQ,MAAM,MAAMH,sCAAc,GAAG,QAAQ,MAAM,CAAC,GAAG,OAAO;EACtG,IAAI,QAAQ,WAAW,UAAU,CAAC,QAAQ,UAAU,MAAM,MAAME,wCAAgB,GAAG,QAAQ,SAAS,IAAI,CAAC,GACvG,OAAO;EAET,IAAI,QAAQ,OAAO,QAAQ;GACzB,MAAM,eAAe,MAAM,QAAQ,QAAQ,QAAQ,KAAK,IAAI,QAAQ,QAAQ,QAAQ,CAAC;GACrF,IAAI,CAAC,QAAQ,MAAM,MAAM,SAAS,aAAa,SAAS,IAAI,CAAC,GAAG,OAAO;EACzE;CACF;CAEA,MAAM,MAAM,YAAY,MAAM;CAC9B,MAAM,SAAS,QAAQ;CACvB,MAAM,UAAU,QAAQ,SAAS;CAKjC,MAAM,YAAY,IAAI,YAAY,IAAI,MAAM;CAC5C,IAAI,WAAW;EACb,MAAM,cAAc,UAAU,IAAI,OAAO;EACzC,IAAI,gBAAgB,QAAW,OAAO;CACxC;CAKA,MAAM,iBAA4C,CAAC;CACnD,MAAM,UAAU,IAAI,iBAAiB,IAAI,GAAG,OAAO,IAAI,SAAS;CAChE,IAAI,SAAS,eAAe,KAAK,OAAO;CACxC,MAAM,cAAc,IAAI;CACxB,MAAM,YAAY,QAAQ,SAAS,GAAG;CACtC,MAAM,OAAO,OAAO;CAEpB,IAAI,SAAS,kBAAkB;EAC7B,IAAI,WAAW;EACf,KAAK,IAAI,KAAK,GAAG,KAAK,eAAe,QAAQ,MAAM;GACjD,MAAM,SAAS,eAAe;GAC9B,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;IACtC,MAAM,QAAQ,OAAO;IACrB,IAAI,MAAM,iBAAiB,CAACC,mCAAmB,SAAS,MAAM,KAAK,YAAY,GAAG,MAAM,GAAG;IAC3F,IAAI,MAAM,KAAK,WAAW,QAAQ,OAAO;IACzC,WAAW;GACb;EACF;EACA,KAAK,IAAI,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;GAC3C,MAAM,QAAQ,YAAY;GAC1B,IAAI,CAAC,eAAe,OAAO,QAAQ,SAAS,WAAW,SAAS,MAAM,GAAG;GACzE,IAAI,MAAM,KAAK,WAAW,QAAQ,OAAO;GACzC,WAAW;EACb;EACA,OAAO,WAAW,OAAO,kBAAkB;CAC7C;CAEA,IAAI,SAAS,mBAAmB;EAC9B,IAAI,UAAU;EACd,KAAK,IAAI,KAAK,GAAG,KAAK,eAAe,QAAQ,MAAM;GACjD,MAAM,SAAS,eAAe;GAC9B,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;IACtC,MAAM,QAAQ,OAAO;IACrB,IAAI,MAAM,iBAAiB,CAACA,mCAAmB,SAAS,MAAM,KAAK,YAAY,GAAG,MAAM,GAAG;IAC3F,IAAI,MAAM,KAAK,WAAW,SAAS,OAAO;IAC1C,UAAU;GACZ;EACF;EACA,KAAK,IAAI,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;GAC3C,MAAM,QAAQ,YAAY;GAC1B,IAAI,CAAC,eAAe,OAAO,QAAQ,SAAS,WAAW,SAAS,MAAM,GAAG;GACzE,IAAI,MAAM,KAAK,WAAW,SAAS,OAAO;GAC1C,UAAU;EACZ;EACA,OAAO,UAAU,QAAQ,kBAAkB;CAC7C;CAGA,IAAI,eAAe;CACnB,IAAI,aAA0C;CAC9C,KAAK,IAAI,KAAK,GAAG,KAAK,eAAe,QAAQ,MAAM;EACjD,MAAM,SAAS,eAAe;EAC9B,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;GACtC,MAAM,QAAQ,OAAO;GACrB,IAAI,MAAM,iBAAiB,CAACA,mCAAmB,SAAS,MAAM,KAAK,UAAU,GAAG;GAChF,IAAI,MAAM,KAAK,WAAW,cAAc;IACtC,eAAe,MAAM,KAAK;IAC1B,aAAa,MAAM,KAAK;GAC1B;EACF;CACF;CACA,KAAK,IAAI,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;EAC3C,MAAM,QAAQ,YAAY;EAC1B,IAAI,CAAC,eAAe,OAAO,QAAQ,SAAS,WAAW,OAAO,GAAG;EACjE,IAAI,MAAM,KAAK,WAAW,cAAc;GACtC,eAAe,MAAM,KAAK;GAC1B,aAAa,MAAM,KAAK;EAC1B;CACF;CACA,OAAO,eAAe,OAAO,eAAe,UAAU,kBAAkB;AAC1E;;;;;;;;;;;AAYA,SAAgB,aACd,UACA,SACA,gBAAsC,QACtC,UAAuC,OACvC,eACA,SACA,QACS;CACT,IAAI,SAAS,WAAW,GAAG;EACzB,MAAM,UAAU,kBAAkB;EAClC,IAAI,WAAW,SAAS,QAAQ,WAAW;EAC3C,OAAO;CACT;;;;;;CAOA,MAAM,YAAY,WAAkD;EAClE,IAAI;GACF,OAAO,mBAAmB,QAAQ,SAAS,eAAe,MAAM;EAClE,SAAS,KAAK;GACZ,gBAAgB,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM;GAC3E,OAAO;EACT;CACF;CAEA,IAAI,YAAY,mBAAmB;EACjC,IAAI,gBAAgB;EACpB,KAAK,MAAM,UAAU,UAAU;GAC7B,MAAM,IAAI,SAAS,MAAM;GACzB,IAAI,MAAM,MAAM;GAChB,gBAAgB;GAChB,IAAI,GAAG,OAAO;EAChB;EACA,IAAI,CAAC,eAAe;GAClB,MAAM,UAAU,kBAAkB;GAClC,IAAI,WAAW,SAAS,QAAQ,WAAW;GAC3C,OAAO;EACT;EACA,OAAO;CACT;CAGA,IAAI,gBAAgB;CACpB,KAAK,MAAM,UAAU,UAAU;EAC7B,MAAM,IAAI,SAAS,MAAM;EACzB,IAAI,MAAM,MAAM;EAChB,gBAAgB;EAChB,IAAI,CAAC,GAAG,OAAO;CACjB;CACA,IAAI,CAAC,eAAe;EAClB,MAAM,UAAU,kBAAkB;EAClC,IAAI,WAAW,SAAS,QAAQ,WAAW;EAC3C,OAAO;CACT;CACA,OAAO;AACT;;;;AC9YA,eAAsB,aAAa,IAAmB,UAAiC;CACrF,IAAI;EACF,MAAM,GAAG;CACX,SAAS,KAAK;EACZ,IAAI;GACF,QAAQ,MAAM,4BAA4B,SAAS,+CAA+C,GAAG;EACvG,QAAQ,CAER;CACF;AACF;AAEA,SAAgB,YACd,OACA,KACA,SACA,IACA,UACA,MACM;CACN,MAAM,OAAO,MAAM;CACnB,IAAI,CAAC,MAAM;CACX,IAAI;EACF,KAAK;GACH,WAAW,IAAI,QAAQ;GACvB,QAAQ,IAAI;GACZ,UAAU,IAAI,SAAS;GACvB;GACA,YAAY,YAAY,IAAI,IAAI;GAChC;GACA;EACF,CAAC;CACH,SAAS,KAAK;EACZ,IAAI;GACF,QAAQ,MAAM,kFAAkF,GAAG;EACrG,QAAQ,CAER;CACF;AACF;;;;ACpBA,SAAgB,cAAoC,KAA6B,MAAqC;CACpH,IAAI,YAAY,MAAM;CACtB,IAAI,UAAU,MAAM;CACpB,IAAI,gBAAgB,MAAM;CAC1B,IAAI,aAAa,MAAM;CACvB,IAAI,SAAS,SAAS,QAAQ;CAC9B,IAAI,SAAS,MAAM,QAAQ;CAC3B,IAAI,SAAS,KAAK,QAAQ;CAC1B,IAAI,SAAS,OAAO,QAAQ;CAC5B,IAAI,kBAAkB,MAAM;CAC5B,IAAI,SAAS,SAAS,MAAM;CAC5B,IAAI,KAAK,cAAc,SAAS,IAAI,aAClC,AAAK,IAAI,YAAY,QAAQ,EAAE,MAAM,MAAM,CAAC;AAEhD;AAEA,SAAgB,kBACd,KACA,WACA,MACM;CACN,IAAI,OAAO,cAAc,YAAY,UAAU,WAAW,KAAK,UAAU,SAAS,MAAM;CACxF,IAAI,aAAa,OAAO,SAAS;CACjC,IAAI,SAAS,SAAS,OAAO,SAAS;CACtC,IAAI,KAAK,cAAc,SAAS,IAAI,aAClC,AAAK,IAAI,YAAY,QAAQ;EAAE,MAAM;EAAW;CAAU,CAAC;AAE/D;AAEA,SAAgB,mBACd,KACA,MACM;CACN,IAAI,YAAY,MAAM;CACtB,IAAI,SAAS,SAAS,QAAQ;CAC9B,IAAI,SAAS,OAAO,QAAQ;CAC5B,IAAI,kBAAkB,MAAM;CAC5B,IAAI,KAAK,cAAc,SAAS,IAAI,aAClC,AAAK,IAAI,YAAY,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErD;AAEA,SAAgB,gBACd,KACA,aACA,MACM;CACN,IAAI,SAAS;CACb,IAAI,WAAW,WAAc,OAAO,WAAW,YAAY,OAAO,WAAW,KAAK,OAAO,SAAS,OAChG,SAAS;CAEX,IAAI,UAAU,MAAM;CACpB,IAAI,gBAAgB,MAAM;CAC1B,IAAI,SAAS,MAAM,QAAQ;CAC3B,IAAI,SAAS,KAAK,QAAQ;CAC1B,IAAI,SAAS,OAAO,QAAQ;CAC5B,IAAI,kBAAkB,MAAM;CAC5B,IAAI,WAAW,QAAW;EACxB,IAAI,aAAa,MAAM;EACvB,IAAI,SAAS,SAAS,MAAM;CAC9B,OACE,KAAK,MAAM,CAAC,WAAW,YAAY,IAAI,aAAa,QAAQ,GAAG;EAC7D,MAAM,UAAU,QAAQ,MAAM,SAAS,MAAM;EAC7C,MAAM,WAAW,QAAQ,aAAa,MAAM,OAAO,GAAG,SAAS,MAAM,KAAK;EAC1E,IAAI,WAAW,UAAU;GACvB,IAAI,aAAa,OAAO,SAAS;GACjC,IAAI,SAAS,SAAS,OAAO,SAAS;EACxC;CACF;CAEF,IAAI,KAAK,cAAc,SAAS,IAAI,aAClC,AAAK,IAAI,YAAY,QAAQ;EAAE,MAAM;EAAS;CAAO,CAAC;AAE1D;AAEA,SAAgB,qBACd,KACA,OACM;CACN,QAAQ,MAAM,MAAd;EACE,KAAK;GACH,cAAc,KAAK,EAAE,WAAW,MAAM,CAAC;GACvC;EACF,KAAK;GACH,mBAAmB,KAAK,EAAE,WAAW,MAAM,CAAC;GAC5C;EACF,KAAK;GACH,gBAAgB,KAAK,MAAM,QAAQ,EAAE,WAAW,MAAM,CAAC;GACvD;EACF,KAAK;GACH,kBAAkB,KAAK,MAAM,WAAW,EAAE,WAAW,MAAM,CAAC;GAC5D;CACJ;AACF;;;;;;;;;ACjHA,IAAI,oBAGO;AACX,eAAe,eAAe;CAC5B,IAAI,CAAC,mBAAmB;EACtB,MAAM,IAAI,2CAAM;EAChB,oBAAoB;GAAE,gBAAgB,EAAE;GAAgB,cAAc,EAAE;EAAa;CACvF;CACA,OAAO;AACT;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,gBACd,SACA,SACA,SACA,WACY;CACZ,IAAI;CACJ,WAAW,YAAY;EACrB,IAAI;GACF,MAAM,QAAQ,MAAM,QAAQ;GAC5B,IAAI,QAAQ,MAAM,SAAS,UAAU,KAAK;GAC1C,OAAO;EACT,UAAU;GACR,IAAI,QAAQ,MAAM,SAAS,QAAQ,IAAI;EACzC;CACF,EAAC,CAAE;CACH,QAAQ,OAAO;CACf,OAAO;AACT;;;;;;;AAQA,SAAgB,qBACd,KACA,KACA,SACA,WACY;CACZ,IAAI;CACJ,WAAW,YAAY;EACrB,IAAI;GACF,MAAM,QAAQ,MAAM,QAAQ;GAC5B,IAAI,IAAI,IAAI,GAAG,MAAM,SAAS,UAAU,KAAK;GAC7C,OAAO;EACT,UAAU;GACR,IAAI,IAAI,IAAI,GAAG,MAAM,SAAS,IAAI,OAAO,GAAG;EAC9C;CACF,EAAC,CAAE;CACH,IAAI,IAAI,KAAK,OAAO;CACpB,OAAO;AACT;;AAGA,SAAS,mBAAmB,MAAyB,QAAmC;CACtF,IAAI,OAAO,OAAO;CAClB,MAAM,OAAO,OAAO,OACjB,QAAQ,MAAM,EAAE,SAAS,OAAO,CAAC,CACjC,KAAK,MAAO,EAAE,OAAO,GAAG,EAAE,KAAK,OAAO,EAAE,KAAK,KAAK,EAAE,IAAK;CAC5D,MAAM,IAAI,MAAM,4BAA4B,KAAK,2BAA2B,KAAK,KAAK,IAAI,GAAG;AAC/F;AAEA,SAAS,0BAA0B,MAAc,OAAyC;CACxF,IAAI,OAAO,UAAU,YAAY,MAAM,WAAW,GAEhD,MAAM,IAAI,MAAM,4BAA4B,KAAK,mCADrC,UAAU,OAAO,SAAS,OAAO,MAC2C,EAAE;CAI5F,IAAI,MAAM,SAAS,MACjB,MAAM,IAAI,MAAM,4BAA4B,KAAK,qCAAqC,MAAM,OAAO,EAAE;AAEzG;AAEA,SAAS,kCAAkC,MAAc,OAAqD;CAC5G,IAAI,UAAU,QAAW;CACzB,0BAA0B,MAAM,KAAK;AACvC;AAEA,SAAS,sBAAsB,OAA2D;CACxF,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAEpE,MAAM,IAAI,MAAM,mEADJ,UAAU,OAAO,SAAS,MAAM,QAAQ,KAAK,IAAI,UAAU,OAAO,MACS,EAAE;CAK3F,MAAM,WAAW,OAAO,KAAK,KAAK,CAAC,CAAC;CACpC,IAAI,WAAW,KACb,MAAM,IAAI,MAAM,iEAAiE,SAAS,EAAE;CAK9F,MAAM,QAAQ,cAAc,KAAK;CACjC,IAAI,QAAQ,IACV,MAAM,IAAI,MAAM,qDAAqD,MAAM,kBAAkB;AAEjG;AAEA,SAAS,cAAc,MAAe,UAAU,GAAW;CACzD,IAAI,UAAU,IAAI,OAAO;CACzB,IAAI,OAAO,SAAS,YAAY,SAAS,MAAM,OAAO;CACtD,IAAI,MAAM;CACV,IAAI,MAAM,QAAQ,IAAI,GACpB,KAAK,MAAM,KAAK,MAAM;EACpB,MAAM,IAAI,cAAc,GAAG,UAAU,CAAC;EACtC,IAAI,IAAI,KAAK,MAAM;EACnB,IAAI,MAAM,IAAI,OAAO;CACvB;MAEA,KAAK,MAAM,KAAK,OAAO,OAAO,IAAI,GAAG;EACnC,MAAM,IAAI,cAAc,GAAG,UAAU,CAAC;EACtC,IAAI,IAAI,KAAK,MAAM;EACnB,IAAI,MAAM,IAAI,OAAO;CACvB;CAEF,OAAO;AACT;AAEA,SAAS,gBAAgB,OAAgB,SAAS,IAAY;CAC5D,IAAI,UAAU,MAAM,OAAO;CAC3B,IAAI,UAAU,QAAW,OAAO;CAChC,MAAM,IAAI,OAAO;CACjB,IAAI,MAAM,UAAU;EAClB,MAAM,IAAI;EACV,IAAI,EAAE,UAAU,QAAQ,OAAO,WAAW,EAAE;EAC5C,OAAO,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,eAAe,EAAE,OAAO;CAC/D;CACA,IAAI,MAAM,YAAY,MAAM,aAAa,MAAM,UAAU,OAAO,GAAG,EAAE,GAAG,OAAO,KAAK;CACpF,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,iBAAiB,MAAM,OAAO;CAC/D,OAAO;AACT;;AAGA,SAAgB,iBAAwD,QAA0B;CAChG,KAAK,MAAM,QAAQ,OAAO,OAAO;EAC/B,IAAI,MAAM,QAAQ,KAAK,OAAO,GAAG,OAAO,OAAO,KAAK,OAAO;EAC3D,IAAI,MAAM,QAAQ,KAAK,SAAS,GAAG,OAAO,OAAO,KAAK,SAAS;EAC/D,IAAI,KAAK,YAAY,qBAAqB,KAAK,UAAU;EACzD,OAAO,OAAO,IAAI;CACpB;CACA,OAAO,OAAO,OAAO,KAAK;CAC1B,OAAO,OAAO,OAAO,MAAM;AAC7B;AAEA,SAAS,qBAAqB,OAA4C;CACxE,IAAI,SAAS,OAAO,qBAAqB,MAAM,GAAG;CAClD,IAAI,SAAS,OAAO,qBAAqB,MAAM,GAAG;CAClD,IAAI,UAAU,OAAO,qBAAqB,MAAM,IAAI;CACpD,OAAO,OAAO,KAAK;AACrB;AAEA,SAAS,qBAAqB,KAAoF;CAChH,KAAK,MAAM,QAAQ,KACjB,IAAI,WAAW,MAAM,OAAO,OAAO,IAAI;MAClC,qBAAqB,IAAI;CAEhC,OAAO,OAAO,GAAG;AACnB;;;;;;;;;;;;;;AAcA,SAAgB,6BACd,SACA,OACqB;CACrB,IAAI,SAAS,QAAQ,CAAC,QAAQ,aAAa,QAAQ,OAAO;CAE1D,MAAM,aAAa,QAAQ,YAAY,QAAQ,OAAO,GAAG,UAAU,KAAK,CAAC,CAAC,KAAK,OAAO,GAAG,IAAI;CAE7F,IAAI,WAAW,WAAW,GAAG,OAAO;CAEpC,MAAM,cAAc,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAG,QAAQ,OAAO,GAAG,UAAU,CAAC,CAAC;CAClE,OAAO;EAAE,GAAG;EAAS,OAAO;CAAY;AAC1C;;;;;;;;;;;;;;AAeA,SAAgB,YAMd,SACA,QAO0D;CAC1D,OAAO;EACL,MAAM,eAAe;GACnB,OAAO,QAAQ,aAAa;EAC9B;EACA,MAAM,UAAU,IAAY;GAC1B,0BAA0B,MAAM,EAAE;GAClC,OAAO,QAAQ,UAAU,EAAE;EAC7B;EACA,MAAM,WAAW,QAA0D;GACzE,MAAM,EAAE,mBAAmB,MAAM,aAAa;GAC9C,mBAAmB,UAAU,eAAe,MAAM,CAAC;GACnD,MAAM,QAAQ,WAAW,MAAM;GAC/B,OAAO,MAAM,mBAAmB;EAClC;EACA,MAAM,aAAa,IAAY;GAC7B,0BAA0B,MAAM,EAAE;GAClC,MAAM,QAAQ,aAAa,EAAE;GAC7B,OAAO,MAAM,mBAAmB;EAClC;EACA,MAAM,YAAY;GAChB,OAAO,QAAQ,UAAU;EAC3B;EACA,MAAM,QAAQ,IAAY;GACxB,0BAA0B,MAAM,EAAE;GAClC,OAAO,QAAQ,QAAQ,EAAE;EAC3B;EACA,MAAM,SAAS,MAA8D;GAC3E,MAAM,EAAE,iBAAiB,MAAM,aAAa;GAC5C,mBAAmB,QAAQ,aAAa,IAAI,CAAC;GAC7C,MAAM,QAAQ,SAAS,IAAI;GAC3B,OAAO,MAAM,gBAAgB,KAAK,EAAE;EACtC;EACA,MAAM,WAAW,IAAY;GAC3B,0BAA0B,MAAM,EAAE;GAClC,MAAM,QAAQ,WAAW,EAAE;GAC3B,OAAO,MAAM,gBAAgB,EAAW;EAC1C;EACA,MAAM,WAAW,WAAmB,QAAe,OAAgB;GACjE,0BAA0B,aAAa,SAAS;GAChD,0BAA0B,UAAU,MAAM;GAC1C,kCAAkC,SAAS,KAAK;GAChD,MAAM,QAAQ,WAAW,WAAW,QAAQ,KAAK;GACjD,OAAO,MAAM,kBAAkB,SAAS;EAC1C;EACA,MAAM,WAAW,WAAmB,QAAe,OAAgB;GACjE,0BAA0B,aAAa,SAAS;GAChD,0BAA0B,UAAU,MAAM;GAC1C,kCAAkC,SAAS,KAAK;GAChD,MAAM,QAAQ,WAAW,WAAW,QAAQ,KAAK;GACjD,OAAO,MAAM,kBAAkB,SAAS;EAC1C;EACA,MAAM,cAAc,WAAmB,OAAiC;GACtE,0BAA0B,aAAa,SAAS;GAChD,sBAAsB,KAAK;GAC3B,MAAM,QAAQ,qBAAqB,WAAW,KAAK;GACnD,OAAO,MAAM,kBAAkB,SAAS;EAC1C;EACA,MAAM,cAAc,WAAmB;GACrC,0BAA0B,aAAa,SAAS;GAChD,OAAO,QAAQ,qBAAqB,SAAS;EAC/C;EACA,MAAM,SAA+E;GACnF,MAAM,CAAC,UAAU,SAAS,MAAM,QAAQ,IAAI,CAAC,QAAQ,aAAa,GAAG,QAAQ,UAAU,CAAC,CAAC;GACzF,OAAO;IACL,eAAe;IACf,6BAAY,IAAI,KAAK,EAAC,CAAC,YAAY;IACnC;IACA;GACF;EACF;EACA,MAAM,OACJ,UACA,UAAyC,CAAC,GACH;GACvC,IAAI,UAAU,kBAAkB,GAAG;IACjC,MAAM,WACJ,aAAa,QAAQ,OAAO,aAAa,WAAW,QAAQ,IAAI,UAAU,eAAe,IAAI;IAC/F,MAAM,IAAI,MACR,+DAA+D,gBAAgB,QAAQ,EAAE,aAC3F;GACF;GACA,MAAM,OAAO,QAAQ,QAAQ;GAC7B,IAAI,kBAAkB;GACtB,IAAI,eAAe;GACnB,IAAI,SAAS,WAAW;IACtB,MAAM,CAAC,kBAAkB,iBAAiB,MAAM,QAAQ,IAAI,CAAC,QAAQ,aAAa,GAAG,QAAQ,UAAU,CAAC,CAAC;IACzG,MAAM,oBAAoB,IAAI,IAAI,SAAS,SAAS,KAAK,MAAM,EAAE,EAAE,CAAC;IACpE,MAAM,kBAAkB,IAAI,IAAI,SAAS,MAAM,KAAK,MAAM,EAAE,EAAE,CAAC;IAC/D,KAAK,MAAM,KAAK,kBACd,IAAI,CAAC,kBAAkB,IAAI,EAAE,EAAE,GAAG;KAChC,MAAM,QAAQ,aAAa,EAAE,EAAE;KAC/B;IACF;IAEF,KAAK,MAAM,KAAK,eACd,IAAI,CAAC,gBAAgB,IAAI,EAAE,EAAE,GAAG;KAC9B,MAAM,QAAQ,WAAW,EAAE,EAAE;KAC7B;IACF;GAEJ;GACA,MAAM,EAAE,gBAAgB,iBAAiB,MAAM,aAAa;GAC5D,KAAK,MAAM,KAAK,SAAS,UAAU;IACjC,mBAAmB,UAAU,eAAe,CAAC,CAAC;IAC9C,MAAM,QAAQ,WAAW,CAAC;GAC5B;GACA,KAAK,MAAM,KAAK,SAAS,OAAO;IAC9B,mBAAmB,QAAQ,aAAa,CAAC,CAAC;IAC1C,MAAM,QAAQ,SAAS,CAAC;GAC1B;GAEA,OAAO,MAAM,mBAAmB;GAChC,OAAO,MAAM,gBAAgB;GAC7B,OAAO;IACL,eAAe,SAAS,SAAS;IACjC;IACA,YAAY,SAAS,MAAM;IAC3B;GACF;EACF;CACF;AACF;;;;ACvVA,SAAgB,cAAc,GAAuC;CACnE,OAAO;EACL,UAAU,EAAE,YAAY;EACxB,OAAO,EAAE,UAAU;EACnB,YAAY,EAAE,gBAAgB;EAC9B,gBAAgB,EAAE,kBAAkB;EACpC,UAAU,EAAE,aAAa;CAC3B;AACF;AAEA,SAAgB,WAAW,GAA6B;CACtD,EAAE,YAAY,WAAW;CACzB,EAAE,UAAU,WAAW;CACvB,EAAE,gBAAgB,WAAW;CAC7B,EAAE,kBAAkB,WAAW;CAC/B,EAAE,aAAa,WAAW;AAC5B;AAEA,SAAgB,sBAAsB,GAAkE;CACtG,MAAM,QACJ,EAAE,SAAS,OACX,EAAE,SAAS,SACX,EAAE,MAAM,OACR,EAAE,MAAM,SACR,EAAE,WAAW,OACb,EAAE,WAAW,SACb,EAAE,eAAe,OACjB,EAAE,eAAe,SACjB,EAAE,SAAS,OACX,EAAE,SAAS;CACb,MAAM,OAAO,EAAE,SAAS,OAAO,EAAE,MAAM,OAAO,EAAE,WAAW,OAAO,EAAE,eAAe,OAAO,EAAE,SAAS;CACrG,OAAO;EAAE;EAAO;EAAM,MAAM,UAAU,IAAI,IAAI,OAAO;CAAM;AAC7D;;;;;;;;;AC/CA,eAAsB,eACpB,QACA,OACiC;CACjC,MAAM,KAAK,YAAY,IAAI;CAC3B,IAAI,UAAyB;CAC7B,IAAI;CACJ,IAAI;EACF,MAAM,MAAM;CACd,SAAS,KAAK;EACZ,UAAU;EACV,YAAY,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;CAC7D;CAEA,MAAM,EAAE,SAAS,sBADP,cAAc,MACe,CAAC;CACxC,OAAO;EACL,IAAI,YAAY;EAChB;EACA,cAAc;EACd,kBAAkB,KAAK,MAAM,YAAY,IAAI,IAAI,EAAE;EACnD,GAAI,cAAc,UAAa,EAAE,UAAU;CAC7C;AACF;AAEA,eAAsB,cAAc,MAGlB;CAChB,MAAM,QAAiC,CAAC,KAAK,gBAAgB,CAAC;CAC9D,IAAI,KAAK,eAAe,MAAM,0CAAK,6BAAqB;CACxD,MAAM,QAAQ,IAAI,KAAK;AACzB;AAEA,SAAgB,mBAAmB,kBAAuE;CACxG,IAAI,kBACF,IAAI;EACF,iBAAiB;CACnB,QAAQ,CAER;CAEF,OAAO,EAAE,OAAO,KAAK;AACvB;;;;ACrBA,eAAsB,aAKpB,MAA2F;CAC3F,MAAM,SAAS,KAAK,YAAY,IAAI,KAAK;CACzC,IAAI,QAAQ,OAAO;CACnB,IAAI,KAAK,SAAS,SAAS,OAAO,OAAO,KAAK,SAAS,SAAS;CAChE,OAAO,sBACC,KAAK,SAAS,SAAS,QAC5B,MAAM;EACL,KAAK,SAAS,SAAS,QAAQ;CACjC,GACA,YAAY;EACV,MAAM,WAAW,MAAM,KAAK,aAAa,SAAS,KAAK,QAAQ,aAAa,IAAI,GAAG,cAAc;EACjG,IAAI,SAAS,SAAS,KAAK,aACzB,MAAM,IAAI,MACR,6CAA6C,SAAS,OAAO,4BAA4B,KAAK,YAAY,sCAC5G;EAEF,OAAO;CACT,IACC,aAAa;EACZ,KAAK,YAAY,IAAI,OAAO,QAAQ;CACtC,CACF;AACF;AAEA,eAAsB,UAKpB,MAAyF;CACzF,MAAM,SAAS,KAAK,UAAU,IAAI,KAAK;CACvC,IAAI,QAAQ,OAAO;CACnB,IAAI,KAAK,SAAS,MAAM,OAAO,OAAO,KAAK,SAAS,MAAM;CAC1D,OAAO,sBACC,KAAK,SAAS,MAAM,QACzB,MAAM;EACL,KAAK,SAAS,MAAM,QAAQ;CAC9B,GACA,YAAY;EACV,MAAM,QAAQ,MAAM,KAAK,aAAa,SAAS,KAAK,QAAQ,UAAU,IAAI,GAAG,WAAW;EACxF,IAAI,MAAM,SAAS,KAAK,UACtB,MAAM,IAAI,MACR,6CAA6C,MAAM,OAAO,sBAAsB,KAAK,SAAS,sCAChG;EAEF,OAAO;CACT,IACC,UAAU;EACT,KAAK,UAAU,IAAI,OAAO,KAAK;CACjC,CACF;AACF;AAEA,eAAsB,eAKpB,MAAyD,WAAiD;CAC1G,MAAM,SAAS,KAAK,aAAa,IAAI,SAAS;CAC9C,IAAI,QAAQ,OAAO;CACnB,MAAM,WAAW,KAAK,SAAS,SAAS,IAAI,SAAS;CACrD,IAAI,UAAU,OAAO;CACrB,OAAO,qBACL,KAAK,SAAS,UACd,WACA,YAAY;EACV,MAAM,CAAC,eAAe,YAAY,YAAY,MAAM,QAAQ,IAAI;GAC9D,KAAK,aAAa,SAAS,KAAK,QAAQ,gBAAgB,WAAW,IAAI,GAAG,iBAAiB;GAC3F,KAAK,aAAa,SAAS,KAAK,QAAQ,qBAAqB,WAAW,IAAI,GAAG,sBAAsB;GACrG,UAAU,IAAI;EAChB,CAAC;EACD,MAAM,QAAQC,uCAAsB,eAAe,QAAQ;EAC3D,MAAM,gBAAgB,KAAK,QAAQ;EAKnC,OAAO;GADgC,IAAI;GAAW;GAAO,aAHzC,gBAChB,MAAM,KAAK,aAAa,SAAS,cAAc,KAAK,KAAK,SAAS,WAAW,IAAI,GAAG,uBAAuB,IAC3G;GACsE;EAC7D;CACf,IACC,YAAY;EACX,KAAK,aAAa,IAAI,WAAW,OAAO;CAC1C,CACF;AACF;AAEA,eAAsB,eAKpB,MAAyF;CACzF,MAAM,SAAS,KAAK,gBAAgB,IAAI,MAAM;CAC9C,IAAI,QAAQ,OAAO;CACnB,IAAI,KAAK,SAAS,KAAK,OAAO,OAAO,KAAK,SAAS,KAAK;CACxD,OAAO,sBACC,KAAK,SAAS,KAAK,QACxB,MAAM;EACL,KAAK,SAAS,KAAK,QAAQ;CAC7B,GACA,YAAY;EAEV,OAAO,iBAAiBC,+BAAc,MADlB,UAAU,IAAI,CACS,CAAC;CAC9C,IACC,UAAU;EACT,KAAK,gBAAgB,IAAI,QAAQ,KAAK;CACxC,CACF;AACF;AAEA,eAAsB,gBAKpB,MAA2F;CAC3F,MAAM,SAAS,KAAK,kBAAkB,IAAI,QAAQ;CAClD,IAAI,QAAQ,OAAO;CACnB,IAAI,KAAK,SAAS,OAAO,OAAO,OAAO,KAAK,SAAS,OAAO;CAC5D,OAAO,sBACC,KAAK,SAAS,OAAO,QAC1B,MAAM;EACL,KAAK,SAAS,OAAO,QAAQ;CAC/B,GACA,YAAY;EACV,MAAM,CAAC,UAAU,cAAc,MAAM,QAAQ,IAAI,CAAC,aAAa,IAAI,GAAG,eAAe,IAAI,CAAC,CAAC;EAC3F,OAAO,WAAW,MAAM,WAAW,IAAI,WAAW,CAAC,YAAY,GAAG,QAAQ;CAC5E,IACC,WAAW;EACV,KAAK,kBAAkB,IAAI,UAAU,MAAM;CAC7C,CACF;AACF;;;;;AChJA,SAAgB,uBAA6B;CAC3C,wCAAgB;CAChB,uCAAe;AACjB;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,IAAa,YAAb,MAME;CACA,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ,oBAAyC;CACjD,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CAGR,AAAQ,YAAY;EAClB,UAAU,EAAE,OAAO,KAAgD;EACnE,OAAO,EAAE,OAAO,KAA8C;EAC9D,MAAM,EAAE,OAAO,KAA8C;EAC7D,QAAQ,EAAE,OAAO,KAAgD;EACjE,0BAAU,IAAI,IAA0C;CAC1D;;;;;;CAMA,AAAQ,UAA8E;EACpF,uBAAO,IAAI,IAAI;EACf,sBAAM,IAAI,IAAI;CAChB;;;;;;;;;CAUA,AAAS,QAAQ;;EAEf,aAAa,OAAgC,CAAC,MAAY,KAAK,eAAe,IAAI;;EAElF,oBAAoB,WAAmB,OAAgC,CAAC,MACtE,KAAK,mBAAmB,WAAW,IAAI;;EAEzC,qBAAqB,OAAgC,CAAC,MAAY,KAAK,oBAAoB,IAAI;;EAE/F,kBAAkB,QAAgB,OAAgC,CAAC,MAAY,KAAK,iBAAiB,QAAQ,IAAI;CACnH;;;;;;CAOA,AAAS,QAAQ;;EAEf,WAMK,KAAK,eAAe;;EAEzB,aAAmB,KAAK,YAAY;CACtC;;;;;;CAOA,YAAY,QAA0E;EACpF,KAAK,WAAW,OAAO;EACvB,KAAK,iBAAiB,OAAO,iBAAiB;EAC9C,KAAK,QAAQ,OAAO,QAAQ;EAC5B,KAAK,iBAAiB,OAAO,iBAAiB;EAC9C,KAAK,SAAS,OAAO,SAAS,CAAC;EAG/B,IAAI,KAAK,UAAU,gBAAgB,KAAK,mBAAmB,oBACzD,MAAM,IAAI,MACR,gJACF;EAIF,IAAI,KAAK,mBAAmB,WAAW,CAAC,OAAO,eAC7C,MAAM,IAAI,MACR,sHACF;EAIF,IAAI,KAAK,mBAAmB,SAE1B,QAAQ,KACN,8IACF;EAGF,KAAK,eAAe,OAAO,eAAe;EAC1C,KAAK,YAAY,OAAO,YAAY;EACpC,KAAK,oBAAoB,OAAO,oBAAoB;EAIpD,IAAI,CAAC,OAAO,SAAS,KAAK,YAAY,KAAK,KAAK,eAAe,GAC7D,MAAM,IAAI,WAAW,mEAAmE;EAE1F,IAAI,CAAC,OAAO,SAAS,KAAK,SAAS,KAAK,KAAK,YAAY,GACvD,MAAM,IAAI,WAAW,gEAAgE;EAEvF,IAAI,CAAC,OAAO,SAAS,KAAK,iBAAiB,KAAK,KAAK,oBAAoB,GACvE,MAAM,IAAI,WAAW,wEAAwE;EAG/F,MAAM,OAAO,OAAO,YAAY,MAAM;EACtC,MAAM,UAAU,OAAO,gBAAgB;EAEvC,KAAK,eAAe,IAAI,YAAY,GAAG,GAAG;EAC1C,KAAK,aAAa,IAAI,YAAY,GAAG,GAAG;EACxC,KAAK,mBAAmB,IAAI,YAAY,GAAG,GAAG;EAC9C,KAAK,qBAAqB,IAAI,YAAY,GAAG,GAAG;EAChD,KAAK,gBAAgB,IAAI,YAAY,SAAS,GAAG;EAEjD,IAAI,OAAO,aAAa;GACtB,KAAK,eAAe,OAAO;GAC3B,KAAK,oBAAoB,OAAO,YAAY,WAAW,UAAU,KAAK,sBAAsB,KAAK,CAAC;EACpG;CACF;;;;;;;;;;;CAYA,AAAQ,aAAgB,IAAmD,OAA2B;EACpG,IAAI,KAAK,qBAAqB,GAC5B,OAAO,GAAG,EAAE,QAAQ,IAAI,gBAAgB,CAAC,CAAC,OAAO,CAAC;EAEpD,MAAM,OAAO,IAAI,gBAAgB;EACjC,IAAI,QAA8C;EAClD,MAAM,UAAU,IAAI,SAAgB,GAAG,WAAW;GAChD,QAAQ,iBAAiB;IACvB,KAAK,MAAM;IACX,uBAAO,IAAI,MAAM,4BAA4B,MAAM,mBAAmB,KAAK,kBAAkB,GAAG,CAAC;GACnG,GAAG,KAAK,iBAAiB;EAC3B,CAAC;EACD,OAAO,QAAQ,KAAQ,CAAC,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,cAAc;GAC3E,IAAI,OAAO,aAAa,KAAK;EAC/B,CAAC;CACH;;CAGA,AAAQ,YAAoC;EAC1C,OAAO;GACL,aAAa,KAAK;GAClB,WAAW,KAAK;GAChB,iBAAiB,KAAK;GACtB,mBAAmB,KAAK;GACxB,cAAc,KAAK;GACnB,UAAU,KAAK;GACf,GAAI,KAAK,iBAAiB,UAAa,EAAE,aAAa,KAAK,aAAa;EAC1E;CACF;;CAGA,AAAQ,sBAAsB,OAAqD;EACjF,qBAAqB,KAAK,UAAU,GAAG,KAAK;CAC9C;;CAGA,UAAgB;EACd,KAAK,oBAAoB,mBAAmB,KAAK,iBAAiB,CAAC,CAAC;CACtE;;;CAIA,AAAQ,cAAiE;EACvE,OAAO;GACL,SAAS,KAAK;GACd,aAAa,KAAK;GAClB,WAAW,KAAK;GAChB,iBAAiB,KAAK;GACtB,mBAAmB,KAAK;GACxB,cAAc,KAAK;GACnB,UAAU,KAAK;GACf,aAAa,KAAK;GAClB,UAAU,KAAK;GACf,cAAc,IAAI,UAAU,KAAK,aAAa,IAAI,KAAK;EACzD;CACF;CAEA,AAAQ,gBAAgB,WAAiD;EACvE,OAAO,eAAe,KAAK,YAAY,GAAG,SAAS;CACrD;CAEA,AAAQ,mBAAqD;EAC3D,OAAO,gBAAgB,KAAK,YAAY,CAAC;CAC3C;;;;;;CAOA,AAAQ,UAAU,OAA2E;EAC3F,OAAO;CACT;;;;;;;;;;CAWA,MAAM,UACJ,SAC0C;EAC1C,IAAI,MAAM;EACV,MAAM,KAAK,KAAK,OAAO,YAAY,YAAY,IAAI,IAAI;EAIvD,IAAI;EACJ,IAAI,mBAAmD;EACvD,IAAI,oBAAoB;EACxB,IAAI,qBAAqB;EACzB,IAAI;GAEF,IAAI,IAAI,WAAW,CAAC,MAAM,QAAQ,IAAI,QAAQ,KAAK,GACjD,MAAM;IAAE,GAAG;IAAK,SAAS;KAAE,GAAG,IAAI;KAAS,OAAO,CAAC;IAAE;GAAE;GAEzD,IAAI,IAAI,SAAS,IAAI,QAAQ,aAAa,QAAQ;IAChD,MAAM,WAAW,6BAA6B,IAAI,SAAS,IAAI,KAAK;IACpE,IAAI,aAAa,IAAI,SAAS,MAAM;KAAE,GAAG;KAAK,SAAS;IAAS;GAClE;GAEA,IAAI,KAAK,OAAO,gBACd,MAAM,MAAM,KAAK,OAAO,eAAe,GAAG;GAG5C,MAAM,cAAc,MAAM,KAAK,iBAAiB;GAEhD,MAAM,oBAAoB,KAAK,OAAO;GACtC,MAAM,gBAAgB,qBACjB,KAAY,WAAkC,kBAAkB,KAAK,OAAO,EAAE,IAC/E;GAEJ,MAAM,UAAkC,CAAC;GACzC,IAAI,KAAK,UAAU,cAAc;IAC/B,MAAM,UAAU,aACd,aACA,KACA,KAAK,gBACL,KAAK,gBACL,eACA,SACA,KAAK,OACP;IACA,oBAAoB;IACpB,qBAAqB,QAAQ,aAAa;IAC1C,SAAS,KAAK,UAAU,OAAO;GACjC,OAAO;IACL,MAAM,WAAW,SACf,aACA,KACA,KAAK,gBACL,KAAK,gBACL,eACA,SACA,KAAK,OACP;IACA,mBAAmB;IACnB,oBAAoB,SAAS;IAC7B,qBAAqB,QAAQ,aAAa;IAC1C,SAAS,KAAK,UAAU,QAAQ;GAClC;EACF,SAAS,OAAO;GACd,MAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;GAGpE,MAAM,KAAK,oBAAoB,KAAK,OAAO,UAAU,KAAK,GAAG,GAAG,SAAS;GACzE,KAAK,aAAa,KAAK,OAAO,IAAI,KAAK;GACvC,IAAI,KAAK,UAAU,cAAc,OAAO,KAAK,UAAU,KAAK;GAC5D,OAAO,KAAK,UAAU;IACpB,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,WAAW,KAAK,IAAI;GACtB,CAAC;EACH;EAKA,IAAI,qBAAqB,MAAM;GAC7B,MAAM,IAAI;GACV,MAAM,KAAK,oBAAoB,KAAK,OAAO,gBAAgB,KAAK,CAAC,GAAG,eAAe;GACnF,IAAI,CAAC,EAAE,SACL,MAAM,KAAK,oBAAoB,KAAK,OAAO,SAAS,KAAK,CAAC,GAAG,QAAQ;EAEzE;EACA,KAAK,aAAa,KAAK,mBAAmB,IAAI,kBAAkB;EAChE,OAAO;CACT;;;;;;;CAQA,MAAc,cAAc,IAAmB,UAAiC;EAC9E,MAAM,aAAa,IAAI,QAAQ;CACjC;;;;;;CAOA,AAAQ,aACN,KACA,SACA,IACA,UACM;EACN,YAAY,KAAK,QAAQ,KAAK,SAAS,IAAI,UAAU,KAAK,KAAK;CACjE;;;;;;;;;;;;CAaA,MAAM,IACJ,WACA,QACA,UACA,aACA,OACkB;EAClB,IAAI,OAAO,cAAc,YAAY,UAAU,WAAW,KAAK,UAAU,SAAS,MAAM,OAAO;EAC/F,IAAI;GACF,MAAM,UAAU,MAAM,KAAK,gBAAgB,SAAS;GACpD,MAAM,SAAS,MAAM,KAAK,UAAU;IAAE;IAAS;IAAQ;IAAU;IAAa;GAAM,CAAC;GACrF,OAAO,OAAO,WAAW,YAAY,SAAS,OAAO;EACvD,SAAS,OAAO;GAId,MAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;GAEpE,MAAM,SAAgE;IACpE,SAAS;KAAE,IAAI;KAAW,OAAO,CAAC;KAAG,YAAY,CAAC;IAAE;IACpD;IACA;IACA;IACA;GACF;GACA,MAAM,KAAK,oBAAoB,KAAK,OAAO,UAAU,KAAK,MAAM,GAAG,SAAS;GAC5E,OAAO;EACT;CACF;;;;;;;;;;;;CAaA,MAAM,MACJ,WACA,QACA,UACA,aACA,OAC0C;EAC1C,IAAI,OAAO,cAAc,YAAY,UAAU,WAAW,KAAK,UAAU,SAAS,MAEhF,OACE,KAAK,UAAU,eAAe,QAAQ;GAAE,SAAS;GAAO,QAAQ;EAAoB;EAGxF,IAAI;GACF,MAAM,UAAU,MAAM,KAAK,gBAAgB,SAAS;GACpD,OAAO,MAAM,KAAK,UAAU;IAAE;IAAS;IAAQ;IAAU;IAAa;GAAM,CAAC;EAC/E,SAAS,OAAO;GACd,MAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;GACpE,MAAM,MAA6D;IACjE,SAAS;KAAE,IAAI;KAAW,OAAO,CAAC;KAAG,YAAY,CAAC;IAAE;IACpD;IACA;IACA;IACA;GACF;GAGA,MAAM,KAAK,oBAAoB,KAAK,OAAO,UAAU,KAAK,GAAG,GAAG,SAAS;GACzE,IAAI,KAAK,UAAU,cAAc,OAAO,KAAK,UAAU,KAAK;GAC5D,OAAO,KAAK,UAAU;IACpB,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,WAAW,KAAK,IAAI;GACtB,CAAC;EACH;CACF;;;;;;;;;;;;;;;;;;CAmBA,MAAM,QAEJ,WACA,QACA,UACA,aACA,OAC0B;EAC1B,IAAI,KAAK,UAAU,cACjB,MAAM,IAAI,MAAM,+CAA+C;EAEjE,IAAI,OAAO,cAAc,YAAY,UAAU,WAAW,KAAK,UAAU,SAAS,MAChF,MAAM,IAAI,MAAM,uFAAuF;EAEzG,MAAM,UAAU,MAAM,KAAK,gBAAgB,SAAS;EACpD,MAAM,gBAAgB,CAAC,GAAG,QAAQ,KAAK;EAEvC,IAAI,kBAAkB;EACtB,IAAI,SAAS,QAAQ,aAAa,QAChC,kBAAkB,6BAA6B,SAAS,KAAK;EAG/D,MAAM,qBAAqB,gBAAgB,MAAM,QAAQ,MAAM,CAAC,cAAc,SAAS,CAAC,CAAC;EAEzF,IAAI,MAA6D;GAC/D,SAAS;GACT;GACA;GACA;GACA;EACF;EAGA,IAAI,KAAK,OAAO,gBACd,MAAM,MAAM,KAAK,OAAO,eAAe,GAAG;EAG5C,MAAM,cAAc,MAAM,KAAK,iBAAiB;EAKhD,MAAM,EAAE,sBAAsB,2CAAM;EAEpC,OAAO,kBACL,aACA,KACA,KAAK,gBACL;GAAE;GAAW;GAAe;EAAmB,GAC/C,KAAK,cACP;CACF;;;;;;;;;;;;;;;CAgBA,MAAM,YACJ,WACA,QACA,aACA,OAAgC,CAAC,GAC4C;EAC7E,IAAI,OAAO,cAAc,YAAY,UAAU,WAAW,KAAK,UAAU,SAAS,MAChF,MAAM,IAAI,MAAM,2FAA2F;EAK7G,IAAI,OAAO,SAAS,MAClB,MAAM,IAAI,MAAM,qEAAqE;EAGvF,MAAM,YAAY,KAAK,cAAc;EAErC,IAAI;EACJ,IAAI;EACJ,IAAI;GACD,CAAC,SAAS,eAAe,MAAM,QAAQ,IAAI,CAAC,KAAK,gBAAgB,SAAS,GAAG,KAAK,iBAAiB,CAAC,CAAC;EACxG,SAAS,OAAO;GACd,MAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;GACpE,MAAM,aAAsC,CAAC;GAC7C,KAAK,MAAM,KAAK,QACd,WAAWC,mCAAsB,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,KAAK;GAEnF,MAAM,SAAgE;IACpE,SAAS;KAAE,IAAI;KAAW,OAAO,CAAC;KAAG,YAAY,CAAC;IAAE;IACpD,QAAQ,OAAO,EAAE,EAAE,UAAW;IAC9B,UAAU;KAAE,MAAM,OAAO,EAAE,EAAE,YAAa;KAAkB,YAAY,CAAC;IAAE;IAC3E;GACF;GACA,MAAM,KAAK,oBAAoB,KAAK,OAAO,UAAU,KAAK,MAAM,GAAG,SAAS;GAC5E,OAAO;EACT;EAEA,MAAM,MAA+B,CAAC;EAEtC,MAAM,kCAAkB,IAAI,IAAiC;EAI7D,MAAM,oBAAoB,KAAK,OAAO;EACtC,MAAM,gBAAgB,qBACjB,KAAY,WAAkC,kBAAkB,KAAK,OAAO,EAAE,IAC/E;EAEJ,KAAK,MAAM,KAAK,QAAQ;GACtB,MAAM,MAAMA,mCAAsB,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK;GAG7E,MAAM,KAAK,aAAa,KAAK,OAAO,YAAY,YAAY,IAAI,IAAI;GAIpE,IAAI,mBAAmD;GACvD,IAAI,kBAAkB;GACtB,IAAI,mBAAmB;GACvB,IAAI,UAAwE;GAE5E,IAAI;IACF,IAAI,kBAAkB;IACtB,IAAI,EAAE,SAAS,QAAQ,aAAa,QAAQ;KAC1C,MAAM,SAAS,gBAAgB,IAAI,EAAE,KAAK;KAC1C,IAAI,QACF,kBAAkB;UACb;MACL,kBAAkB,6BAA6B,SAAS,EAAE,KAAK;MAC/D,gBAAgB,IAAI,EAAE,OAAO,eAAe;KAC9C;IACF;IAEA,IAAI,MAA6D;KAC/D,SAAS;KACT,QAAQ,EAAE;KACV,UAAU;MAAE,MAAM,EAAE;MAAU,IAAI,EAAE;MAAY,YAAY,CAAC;KAAE;KAC/D;KACA,OAAO,EAAE;IACX;IAEA,IAAI,KAAK,OAAO,gBACd,MAAM,MAAM,KAAK,OAAO,eAAe,GAAG;IAG5C,MAAM,UAAkC,CAAC;IAEzC,IAAI,KAAK,UAAU,cAAc;KAC/B,MAAM,UAAU,aACd,aACA,KACA,KAAK,gBACL,KAAK,gBACL,eACA,SACA,KAAK,OACP;KACA,IAAI,OAAO;KACX,kBAAkB;KAClB,mBAAmB,QAAQ,aAAa;KACxC,UAAU;IACZ,OAAO;KACL,MAAM,WAAW,SACf,aACA,KACA,KAAK,gBACL,KAAK,gBACL,eACA,SACA,KAAK,OACP;KACA,IAAI,OAAO,SAAS;KACpB,mBAAmB;KACnB,kBAAkB,SAAS;KAC3B,mBAAmB,QAAQ,aAAa;KACxC,UAAU;IACZ;GACF,SAAS,OAAO;IACd,MAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;IACpE,MAAM,SAAgE;KACpE;KACA,QAAQ,EAAE;KACV,UAAU;MAAE,MAAM,EAAE;MAAU,IAAI,EAAE;MAAY,YAAY,CAAC;KAAE;KAC/D;KACA,OAAO,EAAE;IACX;IACA,MAAM,KAAK,oBAAoB,KAAK,OAAO,UAAU,KAAK,MAAM,GAAG,SAAS;IAC5E,IAAI,WAAW,KAAK,aAAa,QAAQ,OAAO,IAAI,KAAK;IACzD,IAAI,OAAO;IACX;GACF;GAIA,IAAI,qBAAqB,QAAQ,YAAY,MAAM;IACjD,MAAM,IAAI;IACV,MAAM,IAAI;IACV,MAAM,KAAK,oBAAoB,KAAK,OAAO,gBAAgB,GAAG,CAAC,GAAG,eAAe;IACjF,IAAI,CAAC,EAAE,SACL,MAAM,KAAK,oBAAoB,KAAK,OAAO,SAAS,GAAG,CAAC,GAAG,QAAQ;GAEvE;GACA,IAAI,aAAa,YAAY,MAAM,KAAK,aAAa,SAAS,iBAAiB,IAAI,gBAAgB;EACrG;EAEA,OAAO;CACT;CAEA,AAAQ;;CAGR,IAAI,QAAkE;EACpE,KAAK,WAAW,YAA+C,KAAK,UAAU,IAAI;EAClF,OAAO,KAAK;CACd;;CAGA,AAAQ,kBAAkB;EACxB,OAAO;GACL,aAAa,KAAK;GAClB,WAAW,KAAK;GAChB,iBAAiB,KAAK;GACtB,mBAAmB,KAAK;GACxB,cAAc,KAAK;EACrB;CACF;;CAGA,AAAQ,iBAMN;EACA,OAAOC,cAAoB,KAAK,gBAAgB,CAAC;CACnD;;CAGA,AAAQ,cAAoB;EAC1B,WAAiB,KAAK,gBAAgB,CAAC;CACzC;;CAGA,AAAQ,eAAe,OAAgC,CAAC,GAAS;EAC/D,cAAc,KAAK,UAAU,GAAG,IAAI;CACtC;;CAGA,AAAQ,mBAAmB,WAAmB,OAAgC,CAAC,GAAS;EACtF,kBAAkB,KAAK,UAAU,GAAG,WAAW,IAAI;CACrD;;CAGA,AAAQ,oBAAoB,OAAgC,CAAC,GAAS;EACpE,mBAAmB,KAAK,UAAU,GAAG,IAAI;CAC3C;;CAGA,AAAQ,iBAAiB,QAAgB,OAAgC,CAAC,GAAS;EACjF,gBAAgB,KAAK,UAAU,GAAG,QAAQ,IAAI;CAChD;;;;;;;;;;;CAYA,MAAM,QAAQ,OAAgC,CAAC,GAAkB;EAC/D,MAAM,cAAc;GAClB,uBAAuB,KAAK,iBAAiB;GAC7C,eAAe,KAAK,cAAc;EACpC,CAAC;CACH;;;;;;;;;;CAWA,MAAM,cAA+C;EACnD,OAAO,eAAe,KAAK,gBAAgB,GAAG,YAAY;GACxD,MAAM,KAAK,cAAc,SAAS,KAAK,SAAS,aAAa,IAAI,GAAG,0BAA0B;EAChG,CAAC;CACH;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC1wBA,SAAgB,UAOd,OAC0G;CAM1G,OAAO;EACL,SAAS,MAAM;EACf,WAAW,MAAM;EACjB,QAAQ,MAAM,UAAU,CAAC;EACzB,OAAO,MAAM,SAAS,CAAC;EAEvB,aAAa,OAAc,IAAIC,uCAAyD,EAAE;EAE1F,eAAe,OAAe,IAAIC,yCAA2D,EAAE;EAE/F,aAAa,OAAe,IAAIC,uCAAyD,EAAE;EAE3F,YAAY,IAAIC,gCAAkD;EAElE,eACE,WACG,IAAI,UAAoD,MAAM;EAEnE,SAA4F,WAAc;EAE1G,gBAAgB,UAA8EC,+BAAc,KAAK;EAEjH,iBAAiB,UAAmBC,gCAAe,KAAK;CAC1D;AACF;;;;;;;;;AC9DA,SAAgB,sBAAqC;CACnD,OAAO;EAAE,uBAAO,IAAI,IAAI;EAAG,sBAAM,IAAI,IAAI;CAAE;AAC7C"}