{"version":3,"file":"evaluate.mjs","names":[],"sources":["../src/evaluate.ts"],"sourcesContent":["/**\n * Permission evaluator — deny-first rule matching.\n *\n * All permission rules are unified into a single `rules` array.\n * Each rule has a `tier` (deny/ask/allow), an optional `pattern`,\n * and optional `when` conditions.\n *\n * Evaluation order:\n *   1. All deny-tier rules (any match → \"deny\")\n *   2. All ask-tier rules (any match → \"ask\")\n *   3. All allow-tier rules (any match → \"allow\")\n *   4. defaultMode fallback\n *\n * Deny always short-circuits — a deny from any source cannot be overridden\n * by an allow from any source.\n *\n * Pattern syntax (Claude Code compatible):\n *   - Exact: `git status` — string equality\n *   - Prefix: `prefix:*` — word-boundary enforced prefix match\n *   - Wildcard: `pattern * middle *` — regex with `.*` for `*`\n *   - Bare tool (no pattern): matches any invocation\n *   - Domain: `domain:example.com` — substring match on hostname\n *\n * Plus extensions:\n *   - Case-insensitive tool name matching\n *   - `when.cwd` / `when.branch` conditions (AND logic)\n */\n\nimport type { Rule, RuleCondition } from \"./schema.ts\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport type PermissionDecision = \"deny\" | \"ask\" | \"allow\";\n\nexport type PermissionTier = \"deny\" | \"ask\" | \"allow\";\n\nexport interface PermissionPolicy {\n  defaultMode: \"autonomous\" | \"standard\" | \"restricted\" | \"readonly\";\n  rules?: Rule[];\n}\n\n/** Context for conditional rule evaluation (cwd, branch, etc.). */\nexport interface EvaluationContext {\n  cwd?: string;\n  branch?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Rule normalisation — convert string rules to structured rules\n// ---------------------------------------------------------------------------\n\n/**\n * Normalise a string rule from `permissions.allow/deny/ask` into a structured Rule.\n *\n * String rule syntax:\n *   - `\"Read\"` → `{ tool: \"Read\", tier }`\n *   - `\"Bash(git status)\"` → `{ tool: \"Bash\", pattern: \"git status\", tier }`\n *   - `\"Bash(npm:*)\"` → `{ tool: \"Bash\", pattern: \"npm:*\", tier }`\n *   - `\"Bash()\"` → `{ tool: \"Bash\", tier }` (match all)\n *   - `\"mcp__github__*\"` → `{ tool: \"mcp__github__*\", tier }`\n */\nexport function normaliseStringRule(rule: string, tier: PermissionTier): Rule {\n  const openIdx = findFirstUnescaped(rule, \"(\");\n  if (openIdx === -1) {\n    return { tool: rule, tier };\n  }\n  const closeIdx = findLastUnescaped(rule, \")\");\n  if (closeIdx === -1 || closeIdx <= openIdx || closeIdx !== rule.length - 1) {\n    return { tool: rule, tier };\n  }\n  const tool = rule.slice(0, openIdx);\n  if (!tool) {\n    return { tool: rule, tier };\n  }\n  const rawContent = rule.slice(openIdx + 1, closeIdx);\n  if (rawContent === \"\" || rawContent === \"*\") {\n    return { tool, tier };\n  }\n  return { tool, pattern: rawContent, tier };\n}\n\n// ---------------------------------------------------------------------------\n// Rule parsing — pattern matching\n// ---------------------------------------------------------------------------\n\n/**\n * Parsed pattern — determines how a rule's pattern matches input.\n */\ntype ParsedPattern =\n  | { type: \"bare\" }\n  | { type: \"exact\"; content: string }\n  | { type: \"prefix\"; prefix: string }\n  | { type: \"wildcard\"; pattern: string };\n\n// Null-byte sentinels for safe wildcard escaping (compiled once).\nconst ESCAPED_STAR = \"\\x00STAR\\x00\";\nconst ESCAPED_BACKSLASH = \"\\x00BACKSLASH\\x00\";\nconst ESCAPED_STAR_RE = new RegExp(ESCAPED_STAR, \"g\");\nconst ESCAPED_BACKSLASH_RE = new RegExp(ESCAPED_BACKSLASH, \"g\");\n\n/**\n * Parse a pattern string as rule content (from `Rule.pattern`).\n * Determines rule type from the content.\n */\nfunction parsePattern(pattern: string): ParsedPattern {\n  // Domain pattern: \"domain:example.com\" — substring match on input\n  if (pattern.startsWith(\"domain:\")) {\n    return {\n      type: \"wildcard\",\n      pattern: \"*\" + pattern.slice(7) + \"*\",\n    };\n  }\n\n  // Prefix syntax: \"prefix:*\"\n  const prefixMatch = /^(.+):\\*$/.exec(pattern);\n  if (prefixMatch?.[1]) {\n    const prefix = unescapeContent(prefixMatch[1]);\n    return { type: \"prefix\", prefix };\n  }\n\n  // Wildcard: has unescaped * (check raw content before unescaping)\n  if (hasUnescapedWildcard(pattern)) {\n    return { type: \"wildcard\", pattern };\n  }\n\n  // Exact: unescape for the final comparison string\n  const content = unescapeContent(pattern);\n  return { type: \"exact\", content };\n}\n\n// ---------------------------------------------------------------------------\n// Pattern matching\n// ---------------------------------------------------------------------------\n\n/**\n * Match a parsed pattern against input.\n */\nfunction matchPattern(parsed: ParsedPattern, input: string): boolean {\n  switch (parsed.type) {\n    case \"bare\":\n      return true;\n    case \"exact\":\n      return parsed.content === input;\n    case \"prefix\":\n      return input === parsed.prefix || input.startsWith(parsed.prefix + \" \");\n    case \"wildcard\":\n      return matchWildcard(parsed.pattern, input);\n  }\n}\n\n/**\n * Simple glob for tool name matching.\n * Supports * (any chars) in pattern.\n */\nfunction globMatch(pattern: string, text: string): boolean {\n  if (pattern === text) return true;\n  if (!pattern.includes(\"*\")) return false;\n  const regexStr = pattern\n    .replace(/[.+?^${}()|[\\]\\\\'']/g, \"\\\\$&\")\n    .replace(/\\*/g, \".*\");\n  return new RegExp(`^${regexStr}$`).test(text);\n}\n\n/**\n * Tool name matching — case-insensitive, supports MCP server-level wildcards.\n *\n * - \"Bash\" matches \"bash\"\n * - \"mcp__server\" matches \"mcp__server__tool\"\n * - \"mcp__server__*\" matches all tools from server\n */\nfunction toolNamesMatch(ruleTool: string, eventTool: string): boolean {\n  const r = ruleTool.toLowerCase();\n  const e = eventTool.toLowerCase();\n\n  if (r === e) return true;\n\n  // MCP tool name matching\n  if (r.startsWith(\"mcp__\") && e.startsWith(\"mcp__\")) {\n    const rParts = r.split(\"__\");\n    const eParts = e.split(\"__\");\n\n    if (rParts.length === 2 && eParts.length >= 3) {\n      // \"mcp__server\" → all tools from that server\n      return rParts[1] === eParts[1];\n    }\n    if (rParts.length === 3 && eParts.length >= 3) {\n      // \"mcp__server__*\" → all tools from server\n      if (rParts[2] === \"*\") return rParts[1] === eParts[1];\n      // \"mcp__*__something\" → wildcard server name\n      if (rParts[1] === \"*\") {\n        const rTool = rParts[2];\n        const eTool = eParts[2];\n        if (rTool === undefined || eTool === undefined) return false;\n        return globMatch(rTool, eTool);\n      }\n    }\n  }\n\n  // Glob matching on bare tool names\n  return globMatch(r, e);\n}\n\n/**\n * Wildcard pattern matching — Claude Code compatible.\n *\n * - Unescaped `*` matches any character sequence\n * - `\\*` matches a literal asterisk\n * - `\\\\` matches a literal backslash\n * - Trailing ` *` (single wildcard) also matches bare command\n *   so \"git *\" matches both \"git add file\" and \"git\"\n */\nfunction matchWildcard(pattern: string, command: string): boolean {\n  const trimmed = pattern.trim();\n\n  // Phase 1: Process escape sequences into sentinels\n  let processed = \"\";\n  let i = 0;\n  while (i < trimmed.length) {\n    if (trimmed[i] === \"\\\\\" && i + 1 < trimmed.length) {\n      const next = trimmed[i + 1];\n      if (next === \"*\") {\n        processed += ESCAPED_STAR;\n        i += 2;\n        continue;\n      }\n      if (next === \"\\\\\") {\n        processed += ESCAPED_BACKSLASH;\n        i += 2;\n        continue;\n      }\n    }\n    const char = trimmed.charAt(i);\n    processed += char;\n    i++;\n  }\n\n  // Phase 2: Escape regex special chars (except *)\n  const escaped = processed.replace(/[.+?^${}()|[\\]\\\\'\"]/g, \"\\\\$&\");\n\n  // Phase 3: Unescaped * → .*\n  let regexStr = escaped.replace(/\\*/g, \".*\");\n\n  // Phase 4: Restore sentinels as escaped literals\n  regexStr = regexStr\n    .replace(ESCAPED_STAR_RE, \"\\\\*\")\n    .replace(ESCAPED_BACKSLASH_RE, \"\\\\\\\\\");\n\n  // Phase 5: Trailing \" *\" (single wildcard) → match bare command too\n  const unescapedStarCount = (processed.match(/\\*/g) ?? []).length;\n  if (regexStr.endsWith(\" .*\") && unescapedStarCount === 1) {\n    regexStr = regexStr.slice(0, -3) + \"( .*)?\";\n  }\n\n  const regex = new RegExp(`^${regexStr}$`, \"s\");\n  return regex.test(command);\n}\n\n// ---------------------------------------------------------------------------\n// Condition matching\n// ---------------------------------------------------------------------------\n\n/**\n * Check all `when` conditions — AND logic, all must match.\n */\nfunction matchConditions(when: RuleCondition, ctx: EvaluationContext): boolean {\n  if (when.cwd !== undefined && ctx.cwd !== undefined) {\n    if (!globMatchPath(when.cwd, ctx.cwd)) return false;\n  }\n  if (when.branch !== undefined && ctx.branch !== undefined) {\n    if (!globMatchPath(when.branch, ctx.branch)) return false;\n  }\n  return true;\n}\n\n/**\n * Simple glob matching for paths/branches.\n * `*` matches any characters, `**` matches across path separators.\n */\nfunction globMatchPath(pattern: string, text: string): boolean {\n  if (pattern === text) return true;\n  if (!pattern.includes(\"*\") && !pattern.includes(\"?\")) return false;\n\n  // Normalise ** → matches anything including /\n  const regexStr = pattern\n    .replace(/[.+^${}()|[\\]\\\\'\"]/g, \"\\\\$&\")\n    .replace(/\\*\\*/g, \"⟪DOUBLESTAR⟫\")\n    .replace(/\\*/g, \"[^/]*\")\n    .replace(/⟪DOUBLESTAR⟫/g, \".*\")\n    .replace(/\\?/g, \"[^/]\");\n\n  return new RegExp(`^${regexStr}$`).test(text);\n}\n\n// ---------------------------------------------------------------------------\n// Main evaluator\n// ---------------------------------------------------------------------------\n\nconst TIERS: readonly PermissionTier[] = [\"deny\", \"ask\", \"allow\"];\n\n/**\n * Evaluate a tool call against the permission policy.\n *\n * Order: deny rules → ask rules → allow rules → defaultMode\n */\nexport function evaluate(\n  policy: PermissionPolicy,\n  toolName: string,\n  input: string,\n  ctx: EvaluationContext = {},\n): PermissionDecision {\n  const { rules } = policy;\n  if (rules && rules.length > 0) {\n    for (const tier of TIERS) {\n      for (const rule of rules) {\n        if (rule.tier !== tier) continue;\n        if (!toolNamesMatch(rule.tool, toolName)) continue;\n        if (rule.when && !matchConditions(rule.when, ctx)) continue;\n        if (rule.pattern !== undefined) {\n          const parsed = parsePattern(rule.pattern);\n          if (!matchPattern(parsed, input)) continue;\n        }\n        // No pattern = match any input; pattern matched = match\n        return tier;\n      }\n    }\n  }\n  return defaultDecision(policy.defaultMode);\n}\n\nfunction defaultDecision(\n  mode: PermissionPolicy[\"defaultMode\"],\n): PermissionDecision {\n  switch (mode) {\n    case \"autonomous\":\n      return \"allow\";\n    case \"readonly\":\n      return \"deny\";\n    case \"restricted\":\n      return \"ask\";\n    default:\n      return \"ask\";\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Escape helpers (Claude Code compatible)\n// ---------------------------------------------------------------------------\n\n/** Find first unescaped occurrence of `char`. */\nfunction findFirstUnescaped(str: string, char: string): number {\n  for (let i = 0; i < str.length; i++) {\n    if (str[i] === char) {\n      let bs = 0;\n      let j = i - 1;\n      while (j >= 0 && str[j] === \"\\\\\") {\n        bs++;\n        j--;\n      }\n      if (bs % 2 === 0) return i;\n    }\n  }\n  return -1;\n}\n\n/** Find last unescaped occurrence of `char`. */\nfunction findLastUnescaped(str: string, char: string): number {\n  for (let i = str.length - 1; i >= 0; i--) {\n    if (str[i] === char) {\n      let bs = 0;\n      let j = i - 1;\n      while (j >= 0 && str[j] === \"\\\\\") {\n        bs++;\n        j--;\n      }\n      if (bs % 2 === 0) return i;\n    }\n  }\n  return -1;\n}\n\n/** Check if pattern has unescaped * (not :* suffix). */\nfunction hasUnescapedWildcard(pattern: string): boolean {\n  if (pattern.endsWith(\":*\")) return false;\n  for (let i = 0; i < pattern.length; i++) {\n    if (pattern[i] === \"*\") {\n      let bs = 0;\n      let j = i - 1;\n      while (j >= 0 && pattern[j] === \"\\\\\") {\n        bs++;\n        j--;\n      }\n      if (bs % 2 === 0) return true;\n    }\n  }\n  return false;\n}\n\n/** Unescape content: \\( → (, \\) → ), \\* → *, \\\\ → \\ */\nfunction unescapeContent(content: string): string {\n  return content\n    .replace(/\\\\\\(/g, \"(\")\n    .replace(/\\\\\\)/g, \")\")\n    .replace(/\\\\\\*/g, \"*\")\n    .replace(/\\\\\\\\/g, \"\\\\\");\n}\n\n// ---------------------------------------------------------------------------\n// Structured rule → string\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a structured Rule back to a string rule (e.g. `\"Bash(npm:*)\"`).\n *\n * Returns just the tool name for bare rules (no pattern).\n */\nexport function ruleToString(rule: Rule): string {\n  if (rule.pattern === undefined) return rule.tool;\n  return `${rule.tool}(${rule.pattern})`;\n}\n\n/**\n * Collect all rules from a canonical policy, normalising both\n * `rules[]` and `permissions.allow/deny/ask` into a single array.\n */\nexport function collectRules(policy: {\n  rules?: Rule[] | undefined;\n  permissions?:\n    | {\n        allow?: string[] | undefined;\n        deny?: string[] | undefined;\n        ask?: string[] | undefined;\n      }\n    | undefined;\n}): Rule[] {\n  const result: Rule[] = [];\n\n  if (policy.permissions) {\n    if (policy.permissions.deny) {\n      result.push(\n        ...policy.permissions.deny.map((r) => normaliseStringRule(r, \"deny\")),\n      );\n    }\n    if (policy.permissions.ask) {\n      result.push(\n        ...policy.permissions.ask.map((r) => normaliseStringRule(r, \"ask\")),\n      );\n    }\n    if (policy.permissions.allow) {\n      result.push(\n        ...policy.permissions.allow.map((r) => normaliseStringRule(r, \"allow\")),\n      );\n    }\n  }\n\n  if (policy.rules) {\n    result.push(...policy.rules);\n  }\n\n  return result;\n}\n\n// ---------------------------------------------------------------------------\n// Shared merge utilities\n// ---------------------------------------------------------------------------\n\n/** Most restrictive mode wins. */\nconst MODE_RESTRICTIVENESS: Record<string, number> = {\n  readonly: 4,\n  restricted: 3,\n  plan: 3,\n  standard: 2,\n  acceptEdits: 2,\n  default: 2,\n  auto: 2,\n  autonomous: 1,\n  dontAsk: 1,\n  bypassPermissions: 1,\n};\n\n/** Tier priority for deduplication — deny beats ask beats allow. */\nconst TIER_RANK: Record<PermissionTier, number> = {\n  deny: 3,\n  ask: 2,\n  allow: 1,\n};\n\n/**\n * Map a schema-mode string to a normalised evaluation mode.\n *\n * Agent-specific names (bypassPermissions, dontAsk, plan) are\n * mapped to their canonical equivalents.\n */\nexport function mapMode(mode: string): PermissionPolicy[\"defaultMode\"] {\n  switch (mode) {\n    case \"autonomous\":\n    case \"bypassPermissions\":\n    case \"dontAsk\":\n      return \"autonomous\";\n    case \"restricted\":\n    case \"plan\":\n      return \"restricted\";\n    case \"readonly\":\n      return \"readonly\";\n    default:\n      return \"standard\";\n  }\n}\n\n/**\n * Compare two mode strings by restrictiveness.\n * Returns the more restrictive of the two.\n */\nexport function mostRestrictiveMode(\n  a: string | undefined,\n  b: string | undefined,\n): string | undefined {\n  if (a === undefined) return b;\n  if (b === undefined) return a;\n  const rankA = MODE_RESTRICTIVENESS[a] ?? 2;\n  const rankB = MODE_RESTRICTIVENESS[b] ?? 2;\n  return rankB > rankA ? b : a;\n}\n\n/**\n * Rule identity key for deduplication (tool + pattern, excluding tier).\n */\nexport function ruleKey(rule: Rule): string {\n  return `${rule.tool}:${rule.pattern ?? \"\"}`;\n}\n\n/**\n * Deduplicate rules by tool+pattern, keeping the highest-priority tier.\n * Deny beats ask beats allow for the same tool+pattern combination.\n */\nexport function deduplicateRules(rules: Rule[]): Rule[] {\n  const map = new Map<string, Rule>();\n  for (const rule of rules) {\n    const key = ruleKey(rule);\n    const existing = map.get(key);\n    if (existing === undefined) {\n      map.set(key, rule);\n    } else if (TIER_RANK[rule.tier] > TIER_RANK[existing.tier]) {\n      map.set(key, rule);\n    }\n  }\n  return Array.from(map.values());\n}\n"],"mappings":"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"}