{"version":3,"file":"conditions.libs-Clxf4EBz.cjs","names":[],"sources":["../src/core/resolve/resolve.ts","../src/core/conditions/conditions.libs.ts"],"sourcesContent":["import type { IamPrimitives, IamRequest } from '../types'\n// Bare resource patterns (no `:*` / `.*` suffix) match ONLY the literal\n// resource; recursive matching requires the explicit `:*` / `.*` suffix.\n/** Top-level path prefixes accepted by {@link resolve}. */\nexport const ALLOWED_ROOTS = new Set(['subject', 'resource', 'environment'])\n\n/** Property names refused at any segment - blocks prototype-pollution lookups. */\nconst BLOCKED_SEGMENTS = new Set(['__proto__', 'constructor', 'prototype'])\n\n/**\n * Hard cap for path-segment caches. Each entry is at most ~200 bytes\n * (path string + segment array), so 10k entries ~ 2 MB worst case.\n * Insertion-order eviction (FIFO) when the cap is hit.\n */\nexport const PATH_CACHE_MAX = 10_000\n\n/**\n * Process-wide default path-segment cache. Used when a caller does not pass\n * a per-instance cache. Multi-tenant deployments should prefer per-Engine\n * caches to prevent cross-tenant eviction.\n */\nexport const pathCache = new Map<string, string[] | null>()\n\n/**\n * Drop every entry in the process-wide path cache. Intended for multi-tenant\n * operators who flush periodically to bound any single tenant's eviction\n * influence.\n */\nexport function clearPathCache(): void {\n  pathCache.clear()\n}\n\nfunction rememberPath(cache: Map<string, string[] | null>, path: string, value: string[] | null): string[] | null {\n  if (cache.size >= PATH_CACHE_MAX) {\n    const oldest = cache.keys().next().value\n    if (oldest !== undefined) cache.delete(oldest)\n  }\n  cache.set(path, value)\n  return value\n}\n\n/**\n * Splits and validates a dot-path, memoizing the result.\n * Returns `null` for paths with an unknown root or a blocked segment.\n */\nfunction getSegments(path: string, cache: Map<string, string[] | null> = pathCache): string[] | null {\n  const cached = cache.get(path)\n  if (cached !== undefined) return cached\n\n  const segments = path.split('.')\n\n  if (!segments[0] || !ALLOWED_ROOTS.has(segments[0])) return rememberPath(cache, path, null)\n\n  for (const seg of segments) {\n    if (BLOCKED_SEGMENTS.has(seg)) return rememberPath(cache, path, null)\n  }\n\n  return rememberPath(cache, path, segments)\n}\n\n/**\n * Resolve a dot-path field against an {@link IamRequest.IAccessRequest}; blocks `__proto__` / `constructor` / `prototype`.\n *\n * @param request - The access request providing root data.\n * @param path    - Dot-path string starting with an allowed root or shorthand.\n * @returns The resolved attribute value, or `null` when the path is invalid or missing.\n */\nexport function resolve(\n  request: IamRequest.IAccessRequest,\n  path: string,\n  caches?: { path?: Map<string, string[] | null> },\n): IamPrimitives.AttributeValue {\n  if (path === 'action') return request.action\n  if (path === 'scope') return request.scope ?? null\n\n  // Per-Engine path cache when supplied, module-global fallback otherwise.\n  const segments = getSegments(path, caches?.path)\n  if (!segments) return null\n\n  let node: unknown = request\n\n  for (const seg of segments) {\n    if (node == null || typeof node !== 'object') return null\n    node = Reflect.get(node, seg)\n  }\n\n  return node === undefined ? null : (node as IamPrimitives.AttributeValue)\n}\n\n/**\n * Tests if an action matches a pattern.\n * Supports wildcards: \"*\" matches all, \"posts:*\" matches \"posts:read\", \"posts:write\"\n *\n * @param pattern - Action pattern from a rule (may include `'*'` or `'foo:*'`).\n * @param action  - The literal action from the request.\n * @returns `true` when the request action matches the pattern.\n */\nexport function matchesAction(pattern: string, action: string): boolean {\n  if (pattern === '*') return true\n  if (pattern === action) return true\n\n  if (pattern.endsWith(':*')) {\n    const prefix = pattern.slice(0, -1)\n    return action.startsWith(prefix)\n  }\n\n  return false\n}\n\n/**\n * Match a resource type against a pattern. Bare = literal; `:*` / `.*` suffixes match recursively under the separator.\n *\n * @param pattern      - Resource pattern from a rule.\n * @param resourceType - The literal resource type from the request.\n * @returns `true` when the request resource type matches the pattern.\n */\nexport function matchesResource(pattern: string, resourceType: string): boolean {\n  if (pattern === '*') return true\n  if (pattern === resourceType) return true\n\n  // Recognise both `:*` and `.*` as recursive suffixes. The separator is\n  // taken from the pattern, so a dot-pattern only matches dot-style request\n  // resources and vice versa.\n  if (pattern.endsWith(':*') || pattern.endsWith('.*')) {\n    const prefix = pattern.slice(0, -1) // includes the trailing separator\n    return resourceType.startsWith(prefix)\n  }\n\n  return false\n}\n\n/**\n * Match a resource type against a dot-notation hierarchical pattern; `*` global, `prefix.*` recursive subtree.\n *\n * @param pattern      - Resource pattern from a rule (dot-notation).\n * @param resourceType - The literal resource type from the request.\n * @returns `true` when the request resource type matches the pattern.\n */\nexport function matchesResourceHierarchical(pattern: string, resourceType: string): boolean {\n  if (pattern === '*') return true\n  if (pattern === resourceType) return true\n\n  // Only an explicit `.*` suffix enables recursive prefix match.\n  if (pattern.endsWith('.*')) {\n    const prefix = pattern.slice(0, -1) // includes trailing '.'\n    return resourceType.startsWith(prefix)\n  }\n\n  return false\n}\n\n/**\n * Tests if a scope matches a pattern.\n *\n * - undefined/null pattern or \"*\" matches any scope (global permission)\n * - If request has no scope, only global patterns match\n * - Otherwise exact match\n *\n * @param pattern - Scope pattern from a rule (may be `undefined`, `null`, or `'*'`).\n * @param scope   - The request's scope (may be `undefined` or `null`).\n * @returns `true` when the request scope matches the pattern.\n */\nexport function matchesScope(pattern: string | undefined | null, scope: string | undefined | null): boolean {\n  if (!pattern || pattern === '*') return true\n  if (!scope) return false\n  return pattern === scope\n}\n","import { resolve } from '../resolve'\nimport type { AccessControl, IamPrimitives, IamRequest } from '../types'\n\n/**\n * Max allowed regex pattern length to mitigate ReDoS. Catastrophic\n * backtracking patterns are tiny (e.g. `(a+)+$`), so a tight bound here is\n * appropriate - larger patterns only give attackers more rope.\n */\nexport const MAX_REGEX_LENGTH = 128\n\n/**\n * Hard cap on the candidate input string handed to `RegExp.test()`.\n *\n * Even if a catastrophic pattern slips past static detection, capping the\n * input length bounds worst-case backtracking work. Strings longer than this\n * cause the `matches` operator to throw {@link RegexInputTooLargeError}, which\n * the evaluator catches and treats as a policy error (NotApplicable). Returning\n * `false` instead would flip `deny`-when-`matches` rules to allow on\n * adversarially-long input.\n */\nexport const MAX_REGEX_INPUT_LENGTH = 2048\n\n/**\n * Thrown by the `matches` operator when the candidate string exceeds\n * {@link MAX_REGEX_INPUT_LENGTH}.\n *\n * Carried as a tagged error so the evaluator's `safeEval` can route it through\n * `onPolicyError` and mark the entire policy as NotApplicable. Critically, we\n * do NOT silently return `false`: a `false` result from a `matches` operator\n * inside a `deny` rule would flip the rule's effect to \"condition not met ->\n * allow\". By throwing, the whole policy drops out of the decision instead of\n * silently becoming permissive.\n */\nexport class RegexInputTooLargeError extends Error {\n  readonly name = 'RegexInputTooLargeError'\n  readonly tag = 'duck-iam/regex-input-too-large'\n  readonly field: string\n  readonly length: number\n  constructor(field: string, length: number) {\n    super(\n      `[@gentleduck/iam:conditions] matches input on field \"${field}\" is ${length} bytes (> MAX_REGEX_INPUT_LENGTH=${MAX_REGEX_INPUT_LENGTH}); policy dropped as NotApplicable.`,\n    )\n    this.field = field\n    this.length = length\n  }\n}\n\n/**\n * LRU cache capacity for compiled regex patterns. Shared by both the\n * process-wide default cache and per-instance caches an engine may pass in.\n */\nexport const REGEX_CACHE_MAX = 256\n\n/**\n * Default process-wide LRU cache for compiled regex patterns. Used when a\n * caller does not pass a per-instance cache. Multi-tenant deployments should\n * prefer per-Engine caches to prevent cross-tenant eviction.\n */\nexport const regexCache = new Map<string, RegExp>()\n\n/**\n * Retrieve a cached compiled regex, or compile and cache it.\n * Returns `null` if the pattern is invalid.\n *\n * On a cache hit the entry is re-inserted so iteration order becomes recency\n * order; eviction then drops the *least recently used* pattern instead of\n * the oldest-inserted one. Without this, a hot pattern compiled early gets\n * evicted as soon as REGEX_CACHE_MAX cold patterns roll through.\n *\n * @param pattern - Regex source string.\n * @param cache - Optional per-instance Map. Falls back to the module-global\n *   `regexCache` when omitted. Engine instances pass their own cache to\n *   prevent cross-tenant eviction.\n * @returns The compiled `RegExp`, or `null` when the pattern fails to compile.\n */\n/**\n * Drop every entry in the process-wide regex cache. Intended for multi-tenant\n * operators who flush periodically to bound any single tenant's eviction\n * influence. Per-instance caches passed via the optional `cache` argument to\n * {@link getCachedRegex} are NOT affected.\n */\nexport function clearRegexCache(): void {\n  regexCache.clear()\n}\n\n// Patterns containing nested quantifiers — `(a+)+`, `(a*)*`, `(a|aa)+` — are\n// the textbook ReDoS shape that turns into super-linear backtracking. The cheap\n// detection here rejects the obvious forms before they reach `new RegExp`.\n// It is not a complete catastrophic-backtracking analyser; the length cap in\n// `matches` keeps the residual risk bounded.\nconst NESTED_QUANTIFIER_RE = /\\([^)]*[*+?][^)]*\\)[*+?{]/\n\nexport function getCachedRegex(pattern: string, cache: Map<string, RegExp> = regexCache): RegExp | null {\n  if (NESTED_QUANTIFIER_RE.test(pattern)) return null\n  const cached = cache.get(pattern)\n  if (cached) {\n    cache.delete(pattern)\n    cache.set(pattern, cached)\n    return cached\n  }\n  try {\n    const re = new RegExp(pattern)\n    if (cache.size >= REGEX_CACHE_MAX) {\n      const first = cache.keys().next().value\n      if (first !== undefined) cache.delete(first)\n    }\n    cache.set(pattern, re)\n    return re\n  } catch {\n    return null\n  }\n}\n\nfunction isScalar(v: IamPrimitives.AttributeValue | undefined): v is IamPrimitives.Scalar {\n  return v === null || typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean'\n}\n\n/** Record mapping every supported operator to its implementation function. */\nexport const ops: Record<AccessControl.Operator, AccessControl.OpFn> = {\n  eq: (f, v) => f === v,\n  neq: (f, v) => f !== v,\n\n  gt: (f, v) => typeof f === 'number' && typeof v === 'number' && f > v,\n  gte: (f, v) => typeof f === 'number' && typeof v === 'number' && f >= v,\n  lt: (f, v) => typeof f === 'number' && typeof v === 'number' && f < v,\n  lte: (f, v) => typeof f === 'number' && typeof v === 'number' && f <= v,\n\n  in: (f, v) => {\n    if (!Array.isArray(v)) return false\n    if (Array.isArray(f)) return f.some((i) => isScalar(i) && v.includes(i))\n    return isScalar(f) && v.includes(f)\n  },\n  nin: (f, v) => {\n    if (!Array.isArray(v)) return true\n    if (Array.isArray(f)) return !f.some((i) => isScalar(i) && v.includes(i))\n    return !isScalar(f) || !v.includes(f)\n  },\n\n  contains: (f, v) => {\n    if (Array.isArray(f)) return isScalar(v) && f.includes(v)\n    if (typeof f === 'string' && typeof v === 'string') return f.includes(v)\n    return false\n  },\n  not_contains: (f, v) => {\n    if (Array.isArray(f)) return !isScalar(v) || !f.includes(v)\n    if (typeof f === 'string' && typeof v === 'string') return !f.includes(v)\n    return true\n  },\n\n  starts_with: (f, v) => typeof f === 'string' && typeof v === 'string' && f.startsWith(v),\n  ends_with: (f, v) => typeof f === 'string' && typeof v === 'string' && f.endsWith(v),\n\n  matches: (f, v) => {\n    if (typeof f !== 'string' || typeof v !== 'string') return false\n    if (v.length > MAX_REGEX_LENGTH) return false\n    // Throw on oversize input so `deny`-when-`matches` rules do not flip\n    // to allow on adversarial inputs; evalCondition() routes it through\n    // onPolicyError.\n    if (f.length > MAX_REGEX_INPUT_LENGTH) {\n      throw new RegexInputTooLargeError('<unknown>', f.length)\n    }\n    const re = getCachedRegex(v)\n    return re ? re.test(f) : false\n  },\n\n  exists: (f) => f !== null && f !== undefined,\n  not_exists: (f) => f === null || f === undefined,\n\n  subset_of: (f, v) => {\n    if (!Array.isArray(f) || !Array.isArray(v)) return false\n    return f.every((i) => v.includes(i))\n  },\n  superset_of: (f, v) => {\n    if (!Array.isArray(f) || !Array.isArray(v)) return false\n    return v.every((i) => f.includes(i))\n  },\n}\n\n/** Maximum nesting depth for condition groups to prevent stack overflow. */\nexport const MAX_CONDITION_DEPTH = 10\n\n/**\n * Type guard that distinguishes a flat {@link AccessControl.ICondition} from a nested {@link AccessControl.IConditionGroup}.\n *\n * @param item - Either a leaf condition or a group node.\n * @returns `true` when `item` is a leaf `ICondition`.\n */\nexport function isCondition(\n  item: AccessControl.ICondition | AccessControl.IConditionGroup,\n): item is AccessControl.ICondition {\n  return 'field' in item\n}\n\n/**\n * Resolve a condition value, handling `$`-prefixed variable references.\n * e.g. `$subject.id` resolves to the request's subject.id at eval time.\n *\n * @param req   - The access request providing resolution roots.\n * @param value - Raw condition value (possibly `$`-prefixed reference).\n * @returns The resolved value, or `value` unchanged when no `$` prefix is present.\n */\nexport function resolveValue(\n  req: IamRequest.IAccessRequest,\n  value: IamPrimitives.AttributeValue,\n  caches?: { path?: Map<string, string[] | null> },\n): IamPrimitives.AttributeValue {\n  if (typeof value === 'string' && value.startsWith('$')) {\n    return resolve(req, value.slice(1), caches)\n  }\n  return value\n}\n\n/**\n * The `matches` operator compiles the value into a regex. Allowing a\n * `$`-prefixed value to resolve from request attributes would let any\n * attacker who controls a subject/resource/env attribute pin in a\n * catastrophic regex (ReDoS). We refuse `$`-resolved patterns for\n * `matches` regardless of where the attribute came from.\n *\n * @param value - Candidate operand value to inspect.\n * @returns `true` when the value is a `$`-prefixed string reference.\n */\nexport function isUserSourcedValue(value: IamPrimitives.AttributeValue): boolean {\n  return typeof value === 'string' && value.startsWith('$')\n}\n\n/**\n * Evaluate a single flat condition against an access request.\n *\n * @param req  - The access request providing field values.\n * @param cond - The condition to test.\n * @returns `true` when the operator predicate holds against the resolved field.\n */\nexport function evalCondition(\n  req: IamRequest.IAccessRequest,\n  cond: AccessControl.ICondition,\n  caches?: { regex?: Map<string, RegExp>; path?: Map<string, string[] | null> },\n): boolean {\n  if (cond.operator === 'matches' && isUserSourcedValue(cond.value ?? null)) return false\n  const fieldVal = resolve(req, cond.field, caches)\n  const condVal = resolveValue(req, cond.value ?? null, caches)\n  try {\n    // Per-Engine regex cache when supplied, module-global fallback.\n    if (cond.operator === 'matches') return evalMatchesOp(fieldVal, condVal, caches?.regex)\n    return ops[cond.operator](fieldVal, condVal)\n  } catch (err) {\n    if (err instanceof RegexInputTooLargeError && err.field === '<unknown>') {\n      throw new RegexInputTooLargeError(cond.field, err.length)\n    }\n    throw err\n  }\n}\n\n/**\n * Per-instance-cache-aware `matches` operator. The module-global `ops.matches`\n * uses the process-wide regex cache; this variant accepts an optional cache\n * override so multi-tenant Engine instances can isolate compile pools.\n */\nexport function evalMatchesOp(\n  f: IamPrimitives.AttributeValue,\n  v: IamPrimitives.AttributeValue,\n  cache?: Map<string, RegExp>,\n): boolean {\n  if (typeof f !== 'string' || typeof v !== 'string') return false\n  if (v.length > MAX_REGEX_LENGTH) return false\n  if (f.length > MAX_REGEX_INPUT_LENGTH) {\n    throw new RegexInputTooLargeError('<unknown>', f.length)\n  }\n  const re = getCachedRegex(v, cache ?? regexCache)\n  return re ? re.test(f) : false\n}\n"],"mappings":"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"}