@solongate/policy-engine 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -353,23 +353,33 @@ function extractFilenames(args) {
353
353
  const trimmed = value.trim();
354
354
  if (!trimmed) return;
355
355
  if (/^https?:\/\//i.test(trimmed)) return;
356
+ _deepShellScanImpl(trimmed, addFilename);
356
357
  if (trimmed.includes("/") || trimmed.includes("\\")) {
357
358
  const normalized = trimmed.replace(/\\/g, "/");
358
359
  const parts = normalized.split("/");
359
360
  const basename = parts[parts.length - 1];
360
361
  if (basename && basename.length > 0) {
361
362
  addFilename(basename);
363
+ if (basename.includes("*") || basename.includes("?")) {
364
+ for (const expanded of expandSensitiveGlob(basename)) {
365
+ addFilename(expanded);
366
+ }
367
+ }
362
368
  }
363
- return;
364
369
  }
365
370
  if (trimmed.includes(" ")) {
366
371
  for (const rawToken of trimmed.split(/\s+/)) {
367
- const token = rawToken.replace(/^['"`]+|['"`]+$/g, "");
372
+ const token = rawToken.replace(/^['"`$({]+|['"`})]+$/g, "");
368
373
  if (!token) continue;
369
374
  if (token.includes("/") || token.includes("\\")) {
370
375
  const parts = token.replace(/\\/g, "/").split("/");
371
376
  const basename = parts[parts.length - 1];
372
377
  if (basename && looksLikeFilename(basename)) addFilename(basename);
378
+ if (basename && (basename.includes("*") || basename.includes("?"))) {
379
+ for (const expanded of expandSensitiveGlob(basename)) {
380
+ addFilename(expanded);
381
+ }
382
+ }
373
383
  } else if (looksLikeFilename(token)) {
374
384
  addFilename(token);
375
385
  }
@@ -384,6 +394,11 @@ function extractFilenames(args) {
384
394
  if (looksLikeFilename(trimmed)) {
385
395
  addFilename(trimmed);
386
396
  }
397
+ if (trimmed.includes("*") || trimmed.includes("?")) {
398
+ for (const expanded of expandSensitiveGlob(trimmed)) {
399
+ addFilename(expanded);
400
+ }
401
+ }
387
402
  return;
388
403
  }
389
404
  if (Array.isArray(value)) {
@@ -401,6 +416,69 @@ function extractFilenames(args) {
401
416
  }
402
417
  return filenames;
403
418
  }
419
+ function _deepShellScanImpl(value, addFn) {
420
+ const cmdSubMatches = value.matchAll(/\$\(([^)]+)\)/g);
421
+ for (const m of cmdSubMatches) {
422
+ const inner = m[1] ?? "";
423
+ for (const token of inner.split(/\s+/)) {
424
+ const clean = token.replace(/^['"`]+|['"`]+$/g, "");
425
+ if (looksLikeFilename(clean)) addFn(clean);
426
+ }
427
+ }
428
+ const backtickMatches = value.matchAll(/`([^`]+)`/g);
429
+ for (const m of backtickMatches) {
430
+ const inner = m[1] ?? "";
431
+ for (const token of inner.split(/\s+/)) {
432
+ const clean = token.replace(/^['"`]+|['"`]+$/g, "");
433
+ if (looksLikeFilename(clean)) addFn(clean);
434
+ }
435
+ }
436
+ const assignMatches = value.matchAll(/\b\w+=["']?([^"'&;\s]+)["']?/g);
437
+ for (const m of assignMatches) {
438
+ const val = m[1] ?? "";
439
+ if (looksLikeFilename(val)) addFn(val);
440
+ }
441
+ const quotedParts = [];
442
+ const quotedMatches = value.matchAll(/['"]([^'"]*)['"]/g);
443
+ for (const m of quotedMatches) {
444
+ if (m[1]) quotedParts.push(m[1]);
445
+ }
446
+ if (quotedParts.length >= 2) {
447
+ for (let i = 0; i < quotedParts.length - 1; i++) {
448
+ const concat = quotedParts[i] + quotedParts[i + 1];
449
+ if (looksLikeFilename(concat)) addFn(concat);
450
+ if (i + 2 < quotedParts.length) {
451
+ const concat3 = concat + quotedParts[i + 2];
452
+ if (looksLikeFilename(concat3)) addFn(concat3);
453
+ }
454
+ }
455
+ }
456
+ const braceMatches = value.matchAll(/\{([^}]+)\}/g);
457
+ for (const m of braceMatches) {
458
+ const alternatives = (m[1] ?? "").split(",");
459
+ const prefix = value.slice(0, m.index ?? 0).split(/\s+/).pop() ?? "";
460
+ const suffix = value.slice((m.index ?? 0) + m[0].length).split(/\s+/)[0] ?? "";
461
+ for (const alt of alternatives) {
462
+ const expanded = prefix + alt.trim() + suffix;
463
+ const clean = expanded.replace(/^['"`$({./]+/, "");
464
+ if (looksLikeFilename(clean)) addFn(clean);
465
+ if (clean.includes("*") || clean.includes("?")) {
466
+ for (const globExpanded of expandSensitiveGlob(clean)) {
467
+ addFn(globExpanded);
468
+ }
469
+ }
470
+ }
471
+ }
472
+ const redirectMatches = value.matchAll(/<?<\s*['"]?([^\s'";&|]+)['"]?/g);
473
+ for (const m of redirectMatches) {
474
+ const file = m[1] ?? "";
475
+ if (looksLikeFilename(file)) addFn(file);
476
+ }
477
+ const mapfileMatch = value.match(/\b(?:mapfile|readarray)\b.*<\s*['"]?([^\s'";&|]+)['"]?/i);
478
+ if (mapfileMatch && mapfileMatch[1]) {
479
+ if (looksLikeFilename(mapfileMatch[1])) addFn(mapfileMatch[1]);
480
+ }
481
+ }
404
482
  var SENSITIVE_FILENAMES = [
405
483
  ".env",
406
484
  ".env.local",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/path-matcher.ts","../src/command-matcher.ts","../src/filename-matcher.ts","../src/url-matcher.ts","../src/matcher.ts","../src/evaluator.ts","../src/validator.ts","../src/warnings.ts","../src/defaults.ts","../src/engine.ts","../src/policy-store.ts"],"names":["endTime","UNSAFE_CONFIGURATION_WARNINGS","TrustLevel"],"mappings":"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","file":"index.js","sourcesContent":["import type { PolicyRule } from '@solongate/core';\n\ntype PathConstraints = NonNullable<PolicyRule['pathConstraints']>;\n\n/**\n * Normalizes a file path for consistent matching.\n * Resolves . and .. segments, normalizes separators.\n */\nexport function normalizePath(path: string): string {\n // Normalize separators to forward slash\n let normalized = path.replace(/\\\\/g, '/');\n\n // Remove trailing slash (except for root)\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n\n // Resolve . and .. segments\n const parts = normalized.split('/');\n const resolved: string[] = [];\n\n for (const part of parts) {\n if (part === '.' || part === '') {\n if (resolved.length === 0) resolved.push('');\n continue;\n }\n if (part === '..') {\n if (resolved.length > 1) {\n resolved.pop();\n }\n continue;\n }\n resolved.push(part);\n }\n\n return resolved.join('/') || '/';\n}\n\n/**\n * Checks if a path is within a root directory (sandbox boundary).\n * Prevents escaping via .., symlinks, etc.\n */\nexport function isWithinRoot(path: string, root: string): boolean {\n const normalizedPath = normalizePath(path);\n const normalizedRoot = normalizePath(root);\n\n // Path must start with root\n if (normalizedPath === normalizedRoot) return true;\n return normalizedPath.startsWith(normalizedRoot + '/');\n}\n\n/**\n * Glob-style path pattern matching.\n * Supports:\n * - * matches any single path segment (not /)\n * - ** matches any number of path segments\n * - Exact match\n *\n * Does NOT support regex (ReDoS prevention).\n */\nexport function matchPathPattern(path: string, pattern: string): boolean {\n const normalizedPath = normalizePath(path);\n const normalizedPattern = normalizePath(pattern);\n\n if (normalizedPattern === '*') return true;\n if (normalizedPattern === normalizedPath) return true;\n\n const patternParts = normalizedPattern.split('/');\n const pathParts = normalizedPath.split('/');\n\n return matchParts(pathParts, 0, patternParts, 0);\n}\n\nfunction matchParts(\n pathParts: string[],\n pi: number,\n patternParts: string[],\n qi: number,\n): boolean {\n while (pi < pathParts.length && qi < patternParts.length) {\n const pattern = patternParts[qi]!;\n\n if (pattern === '**') {\n // ** can match zero or more path segments\n if (qi === patternParts.length - 1) return true;\n\n // Try matching ** against 0, 1, 2, ... path segments\n for (let i = pi; i <= pathParts.length; i++) {\n if (matchParts(pathParts, i, patternParts, qi + 1)) {\n return true;\n }\n }\n return false;\n }\n\n if (pattern === '*') {\n // * matches exactly one path segment\n pi++;\n qi++;\n continue;\n }\n\n // Support intra-segment globs: *.txt, file.*, test-*-data, etc.\n if (pattern.includes('*')) {\n if (!matchSegmentGlob(pathParts[pi]!, pattern)) {\n return false;\n }\n pi++;\n qi++;\n continue;\n }\n\n if (pattern !== pathParts[pi]) {\n return false;\n }\n\n pi++;\n qi++;\n }\n\n // Skip trailing ** patterns\n while (qi < patternParts.length && patternParts[qi] === '**') {\n qi++;\n }\n\n return pi === pathParts.length && qi === patternParts.length;\n}\n\n/**\n * Checks if a path is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If rootDirectory is set, path must be within it\n * 2. If denied list exists, path must NOT match any denied pattern\n * 3. If allowed list exists, path must match at least one allowed pattern\n * 4. If neither list exists, path is allowed (constraints are optional)\n */\nexport function isPathAllowed(\n path: string,\n constraints: PathConstraints,\n): boolean {\n // 1. Root directory check (sandbox)\n if (constraints.rootDirectory) {\n if (!isWithinRoot(path, constraints.rootDirectory)) {\n return false;\n }\n }\n\n // 2. Denied list - any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchPathPattern(path, pattern)) {\n return false;\n }\n }\n }\n\n // 3. Allowed list - must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchPathPattern(path, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n\n/**\n * Matches a single path segment against a glob pattern containing *.\n * Examples: *.txt matches safe.txt, file.* matches file.js, *secret* matches my-secret-key\n */\nfunction matchSegmentGlob(segment: string, pattern: string): boolean {\n const startsWithStar = pattern.startsWith('*');\n const endsWithStar = pattern.endsWith('*');\n\n if (pattern === '*') return true;\n\n if (startsWithStar && endsWithStar) {\n // *infix* — contains\n const infix = pattern.slice(1, -1);\n return segment.toLowerCase().includes(infix.toLowerCase());\n }\n if (startsWithStar) {\n // *suffix — ends with\n const suffix = pattern.slice(1);\n return segment.toLowerCase().endsWith(suffix.toLowerCase());\n }\n if (endsWithStar) {\n // prefix* — starts with\n const prefix = pattern.slice(0, -1);\n return segment.toLowerCase().startsWith(prefix.toLowerCase());\n }\n\n // Single * in middle: split on * and check prefix+suffix\n const starIdx = pattern.indexOf('*');\n if (starIdx !== -1) {\n const prefix = pattern.slice(0, starIdx);\n const suffix = pattern.slice(starIdx + 1);\n const seg = segment.toLowerCase();\n return seg.startsWith(prefix.toLowerCase()) && seg.endsWith(suffix.toLowerCase()) && seg.length >= prefix.length + suffix.length;\n }\n\n return segment === pattern;\n}\n\n/**\n * Known argument field names that typically contain file paths.\n */\nconst PATH_FIELDS = new Set([\n 'path',\n 'file',\n 'file_path',\n 'filepath',\n 'filename',\n 'directory',\n 'dir',\n 'folder',\n 'source',\n 'destination',\n 'dest',\n 'target',\n 'input',\n 'output',\n 'cwd',\n 'root',\n 'notebook_path',\n]);\n\n/**\n * Extracts path-like arguments from tool call arguments.\n * Uses multiple heuristics:\n * 1. Known path field names — always extract\n * 2. Strings containing / or \\ (original heuristic)\n * 3. Strings starting with . (.env, ./foo)\n */\nexport function extractPathArguments(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const paths: string[] = [];\n const seen = new Set<string>();\n\n function addPath(value: string): void {\n const trimmed = value.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n paths.push(trimmed);\n }\n }\n\n for (const [key, value] of Object.entries(args)) {\n if (typeof value !== 'string') continue;\n\n // Known path field names\n if (PATH_FIELDS.has(key.toLowerCase())) {\n addPath(value);\n continue;\n }\n\n // Contains path separators\n if (value.includes('/') || value.includes('\\\\')) {\n addPath(value);\n continue;\n }\n\n // Starts with . (.env, ./config, ../secret)\n if (value.startsWith('.')) {\n addPath(value);\n continue;\n }\n }\n\n return paths;\n}\n","import type { PolicyRule } from '@solongate/core';\n\ntype CommandConstraints = NonNullable<PolicyRule['commandConstraints']>;\n\n/**\n * Known argument field names that typically contain commands or shell-like content.\n * Used to extract commands from tool call arguments for constraint matching.\n */\nconst COMMAND_FIELDS = new Set([\n 'command',\n 'cmd',\n 'query',\n 'code',\n 'script',\n 'shell',\n 'exec',\n 'sql',\n 'expression',\n 'function',\n]);\n\n/**\n * Heuristic patterns that indicate a string value is likely a command/shell expression,\n * even when the field name is not in COMMAND_FIELDS.\n */\nconst COMMAND_HEURISTICS = [\n /^(sh|bash|cmd|powershell|zsh|fish)\\s+-c\\s+/i, // shell -c \"...\"\n /^(sudo|doas)\\s+/i, // privilege escalation\n /^\\w+\\s+&&\\s+/, // cmd1 && cmd2\n /^\\w+\\s*\\|\\s*\\w+/, // cmd1 | cmd2\n /^\\w+\\s*;\\s*\\w+/, // cmd1; cmd2\n /^(curl|wget|nc|ncat)\\s+/i, // network commands\n /^(rm|del|rmdir)\\s+/i, // destructive commands\n /^(cat|type|more|less)\\s+.*[/\\\\]/i, // file read commands with paths\n /^(eval|source)\\s+/i, // eval/source wrappers\n /^(printenv|env|set)\\b/i, // environment variable leak\n /^(cat|head|tail|more|less|strings|xxd|od|hexdump|bat)\\s+/i, // file read commands\n];\n\n/**\n * Regex to match subshell wrapper patterns like `bash -c '...'`, `sh -c \"...\"`, `eval \"...\"`.\n * Extracts the inner command for recursive constraint checking.\n */\nconst SUBSHELL_WRAPPERS = [\n /^(?:sh|bash|zsh|fish|dash|ksh)\\s+-c\\s+['\"](.+?)['\"]\\s*$/i,\n /^(?:sh|bash|zsh|fish|dash|ksh)\\s+-c\\s+(.+)$/i,\n /^eval\\s+['\"](.+?)['\"]\\s*$/i,\n /^eval\\s+(.+)$/i,\n /^(?:sh|bash|zsh|fish|dash|ksh)\\s+<<\\s*['\"]?(\\w+)['\"]?\\n([\\s\\S]+?)\\n\\1$/i,\n];\n\n/**\n * Extracts inner commands from subshell wrappers (bash -c, eval, etc.)\n * Returns the original command plus any extracted inner commands.\n */\nexport function extractInnerCommands(command: string): string[] {\n const results = [command];\n const trimmed = command.trim();\n\n for (const pattern of SUBSHELL_WRAPPERS) {\n const match = trimmed.match(pattern);\n if (match) {\n // For heredoc pattern, inner command is in group 2\n const inner = (match[2] ?? match[1] ?? '').trim();\n if (inner) {\n results.push(inner);\n // Recurse: inner command might also be a wrapper\n const nested = extractInnerCommands(inner);\n for (const n of nested) {\n if (n !== inner) results.push(n);\n }\n }\n break;\n }\n }\n\n // Also handle string concatenation patterns that build commands:\n // variable=value && ... && command \"$variable\"\n // Look for the final command after the last && or ;\n const chainParts = trimmed.split(/\\s*(?:&&|;)\\s*/);\n if (chainParts.length > 1) {\n for (const part of chainParts) {\n const p = part.trim();\n if (p && p !== trimmed && !p.includes('=')) {\n results.push(p);\n }\n }\n }\n\n return [...new Set(results)];\n}\n\n/**\n * Extracts command-like arguments from tool call arguments.\n * Uses known field names plus heuristic detection for command-like strings\n * in any field, and recurses into nested objects/arrays.\n */\nexport function extractCommandArguments(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const commands: string[] = [];\n const seen = new Set<string>();\n\n function addCommand(value: string): void {\n const trimmed = value.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n commands.push(trimmed);\n }\n }\n\n function scanValue(key: string, value: unknown): void {\n if (typeof value === 'string') {\n // Known command field names — always extract\n if (COMMAND_FIELDS.has(key.toLowerCase())) {\n addCommand(value);\n return;\n }\n // Deep scan: heuristic detection of command-like strings\n for (const pattern of COMMAND_HEURISTICS) {\n if (pattern.test(value)) {\n addCommand(value);\n return;\n }\n }\n }\n // Recurse into arrays and objects\n if (Array.isArray(value)) {\n for (const item of value) {\n scanValue(key, item);\n }\n } else if (typeof value === 'object' && value !== null) {\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n scanValue(k, v);\n }\n }\n }\n\n for (const [key, value] of Object.entries(args)) {\n scanValue(key, value);\n }\n\n // Extract inner commands from subshell wrappers (bash -c, eval, etc.)\n const expanded: string[] = [];\n for (const cmd of commands) {\n for (const inner of extractInnerCommands(cmd)) {\n if (!seen.has(inner)) {\n seen.add(inner);\n expanded.push(inner);\n }\n }\n }\n commands.push(...expanded);\n\n return commands;\n}\n\n/**\n * Glob-style command pattern matching.\n * Matches against the command string (first word) or full command line.\n *\n * Patterns:\n * 'ls' → exact match on command name\n * 'git*' → command starts with 'git'\n * '*sql*' → command contains 'sql'\n * 'rm -rf *' → full command line starts with 'rm -rf '\n */\nexport function matchCommandPattern(command: string, pattern: string): boolean {\n if (pattern === '*') return true;\n\n const normalizedCommand = command.trim().toLowerCase();\n const normalizedPattern = pattern.trim().toLowerCase();\n\n if (normalizedPattern === normalizedCommand) return true;\n\n const startsWithStar = normalizedPattern.startsWith('*');\n const endsWithStar = normalizedPattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = normalizedPattern.slice(1, -1);\n return infix.length > 0 && normalizedCommand.includes(infix);\n }\n if (endsWithStar) {\n const prefix = normalizedPattern.slice(0, -1);\n return normalizedCommand.startsWith(prefix);\n }\n if (startsWithStar) {\n const suffix = normalizedPattern.slice(1);\n return normalizedCommand.endsWith(suffix);\n }\n\n // Also try matching just the command name (first word)\n const commandName = normalizedCommand.split(/\\s+/)[0] ?? '';\n return commandName === normalizedPattern;\n}\n\n/**\n * Checks if a command is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If denied list exists, command must NOT match any denied pattern\n * 2. If allowed list exists, command must match at least one allowed pattern\n * 3. If neither list exists, command is allowed (constraints are optional)\n */\nexport function isCommandAllowed(\n command: string,\n constraints: CommandConstraints,\n): boolean {\n // 1. Denied list — any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchCommandPattern(command, pattern)) {\n return false;\n }\n }\n }\n\n // 2. Allowed list — must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchCommandPattern(command, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n","import type { PolicyRule } from '@solongate/core';\n\ntype FilenameConstraints = NonNullable<PolicyRule['filenameConstraints']>;\n\n/**\n * Extracts filenames from ALL string arguments (deep scan).\n * For path-like values, extracts the basename.\n * For non-path values, uses the string itself if it looks like a filename.\n */\nexport function extractFilenames(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const filenames: string[] = [];\n const seen = new Set<string>();\n\n function addFilename(name: string): void {\n const trimmed = name.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n filenames.push(trimmed);\n }\n }\n\n function scanValue(value: unknown): void {\n if (typeof value === 'string') {\n const trimmed = value.trim();\n if (!trimmed) return;\n\n // Skip URLs\n if (/^https?:\\/\\//i.test(trimmed)) return;\n\n // If it contains a path separator, extract the basename\n if (trimmed.includes('/') || trimmed.includes('\\\\')) {\n const normalized = trimmed.replace(/\\\\/g, '/');\n const parts = normalized.split('/');\n const basename = parts[parts.length - 1];\n if (basename && basename.length > 0) {\n addFilename(basename);\n }\n return;\n }\n\n // Multi-word strings: split by whitespace and check each token\n // Catches: \"SELECT * FROM .env\", \"echo .env.local\", \"bash -c 'cat .env'\", etc.\n if (trimmed.includes(' ')) {\n for (const rawToken of trimmed.split(/\\s+/)) {\n // Strip surrounding quotes and trailing punctuation from tokens\n const token = rawToken.replace(/^['\"`]+|['\"`]+$/g, '');\n if (!token) continue;\n if (token.includes('/') || token.includes('\\\\')) {\n const parts = token.replace(/\\\\/g, '/').split('/');\n const basename = parts[parts.length - 1];\n if (basename && looksLikeFilename(basename)) addFilename(basename);\n } else if (looksLikeFilename(token)) {\n addFilename(token);\n }\n // Expand shell glob wildcards that could match sensitive files\n // e.g., \"cred*\" could match \"credentials.json\", \"sec*\" → \"secrets.json\"\n if (token.includes('*') || token.includes('?')) {\n for (const expanded of expandSensitiveGlob(token)) {\n addFilename(expanded);\n }\n }\n }\n return;\n }\n\n // Single token: if it looks like a filename (has a dot extension or starts with dot)\n if (looksLikeFilename(trimmed)) {\n addFilename(trimmed);\n }\n return;\n }\n // Recurse into arrays and objects\n if (Array.isArray(value)) {\n for (const item of value) {\n scanValue(item);\n }\n } else if (typeof value === 'object' && value !== null) {\n for (const v of Object.values(value)) {\n scanValue(v);\n }\n }\n }\n\n for (const value of Object.values(args)) {\n scanValue(value);\n }\n\n return filenames;\n}\n\n/**\n * Known sensitive filenames that glob patterns in commands might target.\n * When a wildcard like \"cred*\" or \"sec*\" is used, we check if it could\n * match any of these sensitive files to prevent wildcard-based bypass.\n */\nconst SENSITIVE_FILENAMES = [\n '.env', '.env.local', '.env.production', '.env.development',\n 'credentials.json', 'secrets.json', 'secrets.yaml', 'secrets.yml',\n '.npmrc', '.pypirc', '.netrc',\n 'id_rsa', 'id_ed25519', 'id_ecdsa',\n 'policy.json', '.mcp.json', 'guard.mjs', 'audit.mjs',\n 'settings.json',\n];\n\n/**\n * Expands a glob-like pattern against known sensitive filenames.\n * Returns sensitive filenames that the glob would match.\n * e.g., \"cred*\" → [\"credentials.json\"], \"sec*\" → [\"secrets.json\", \"secrets.yaml\"]\n */\nfunction expandSensitiveGlob(pattern: string): string[] {\n const p = pattern.toLowerCase();\n const matches: string[] = [];\n\n for (const filename of SENSITIVE_FILENAMES) {\n const f = filename.toLowerCase();\n\n if (p === '*') {\n // Don't expand bare wildcard to everything\n continue;\n }\n\n const startsWithStar = p.startsWith('*');\n const endsWithStar = p.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = p.slice(1, -1);\n if (infix && f.includes(infix)) matches.push(filename);\n } else if (endsWithStar) {\n const prefix = p.slice(0, -1);\n if (f.startsWith(prefix)) matches.push(filename);\n } else if (startsWithStar) {\n const suffix = p.slice(1);\n if (f.endsWith(suffix)) matches.push(filename);\n } else if (p.includes('?')) {\n // Simple ? glob: replace ? with regex .\n const regex = new RegExp('^' + p.replace(/\\?/g, '.').replace(/\\*/g, '.*') + '$', 'i');\n if (regex.test(f)) matches.push(filename);\n }\n }\n\n return matches;\n}\n\n/**\n * Checks if a string looks like a filename.\n * Matches: .env, .env.local, config.json, id_rsa, Makefile, etc.\n */\nfunction looksLikeFilename(s: string): boolean {\n // Starts with dot (.env, .gitignore, .env.local)\n if (s.startsWith('.')) return true;\n // Has a file extension (foo.txt, package.json)\n if (/\\.\\w+$/.test(s)) return true;\n // Known extensionless filenames\n const knownFiles = new Set([\n 'id_rsa', 'id_dsa', 'id_ecdsa', 'id_ed25519',\n 'authorized_keys', 'known_hosts',\n 'makefile', 'dockerfile', 'vagrantfile',\n 'gemfile', 'rakefile', 'procfile',\n ]);\n if (knownFiles.has(s.toLowerCase())) return true;\n return false;\n}\n\n/**\n * Glob-style filename pattern matching (case-insensitive).\n *\n * Patterns:\n * '.env' → exact match\n * '*.pem' → ends with .pem\n * '.env.*' → starts with .env.\n * '*secret*' → contains \"secret\"\n */\nexport function matchFilenamePattern(filename: string, pattern: string): boolean {\n if (pattern === '*') return true;\n\n const normalizedFilename = filename.toLowerCase();\n const normalizedPattern = pattern.toLowerCase();\n\n if (normalizedFilename === normalizedPattern) return true;\n\n const startsWithStar = normalizedPattern.startsWith('*');\n const endsWithStar = normalizedPattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = normalizedPattern.slice(1, -1);\n return infix.length > 0 && normalizedFilename.includes(infix);\n }\n if (startsWithStar) {\n const suffix = normalizedPattern.slice(1);\n return normalizedFilename.endsWith(suffix);\n }\n if (endsWithStar) {\n const prefix = normalizedPattern.slice(0, -1);\n return normalizedFilename.startsWith(prefix);\n }\n\n // Single * in middle: .env.* → split on * and check prefix+suffix\n const starIdx = normalizedPattern.indexOf('*');\n if (starIdx !== -1) {\n const prefix = normalizedPattern.slice(0, starIdx);\n const suffix = normalizedPattern.slice(starIdx + 1);\n return (\n normalizedFilename.startsWith(prefix) &&\n normalizedFilename.endsWith(suffix) &&\n normalizedFilename.length >= prefix.length + suffix.length\n );\n }\n\n return false;\n}\n\n/**\n * Checks if a filename is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If denied list exists, filename must NOT match any denied pattern\n * 2. If allowed list exists, filename must match at least one allowed pattern\n * 3. If neither list exists, filename is allowed\n */\nexport function isFilenameAllowed(\n filename: string,\n constraints: FilenameConstraints,\n): boolean {\n // 1. Denied list — any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchFilenamePattern(filename, pattern)) {\n return false;\n }\n }\n }\n\n // 2. Allowed list — must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchFilenamePattern(filename, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n","import type { PolicyRule } from '@solongate/core';\n\ntype UrlConstraints = NonNullable<PolicyRule['urlConstraints']>;\n\n/**\n * Known argument field names that typically contain URLs.\n */\nconst URL_FIELDS = new Set([\n 'url',\n 'href',\n 'uri',\n 'endpoint',\n 'link',\n 'src',\n 'source',\n 'target',\n 'redirect',\n 'callback',\n 'webhook',\n]);\n\n/**\n * Extracts URL arguments from tool call arguments.\n * Scans ALL string values — not just known field names.\n * Any string containing http:// or https:// is treated as a URL.\n */\nexport function extractUrlArguments(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const urls: string[] = [];\n const seen = new Set<string>();\n\n function addUrl(value: string): void {\n const trimmed = value.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n urls.push(trimmed);\n }\n }\n\n function scanValue(key: string, value: unknown): void {\n if (typeof value === 'string') {\n const lower = key.toLowerCase();\n // Known URL fields — always extract\n if (URL_FIELDS.has(lower)) {\n addUrl(value);\n return;\n }\n // Deep scan: any string containing a URL protocol\n if (/https?:\\/\\//i.test(value)) {\n addUrl(value);\n return;\n }\n // Bare domain patterns (e.g. \"instagram.com\", \"foo.onion\")\n // Require known TLD suffix to avoid false positives on version strings like \"1.0.abc\"\n if (/^[a-zA-Z0-9]([a-zA-Z0-9-]*\\.)+(?:com|net|org|io|dev|app|co|me|info|biz|gov|edu|mil|onion|xyz|ai|cloud|sh|run|so|to|cc|tv|fm|am|gg|id)(\\/.*)?$/.test(value)) {\n addUrl(value);\n return;\n }\n }\n // Recurse into arrays and objects\n if (Array.isArray(value)) {\n for (const item of value) {\n scanValue(key, item);\n }\n } else if (typeof value === 'object' && value !== null) {\n for (const [k, v] of Object.entries(value)) {\n scanValue(k, v);\n }\n }\n }\n\n for (const [key, value] of Object.entries(args)) {\n scanValue(key, value);\n }\n\n return urls;\n}\n\n/**\n * Glob-style URL pattern matching.\n * Normalizes both URL and pattern to lowercase for comparison.\n *\n * Patterns:\n * '*instagram.com*' → URL contains instagram.com\n * 'https://api.example.com/*' → URL starts with prefix\n * '*.onion' → URL ends with .onion\n * '*' → matches everything\n */\nexport function matchUrlPattern(url: string, pattern: string): boolean {\n if (pattern === '*') return true;\n\n const normalizedUrl = url.trim().toLowerCase();\n const normalizedPattern = pattern.trim().toLowerCase();\n\n if (normalizedPattern === normalizedUrl) return true;\n\n const startsWithStar = normalizedPattern.startsWith('*');\n const endsWithStar = normalizedPattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = normalizedPattern.slice(1, -1);\n return infix.length > 0 && normalizedUrl.includes(infix);\n }\n if (endsWithStar) {\n const prefix = normalizedPattern.slice(0, -1);\n return normalizedUrl.startsWith(prefix);\n }\n if (startsWithStar) {\n const suffix = normalizedPattern.slice(1);\n return normalizedUrl.endsWith(suffix);\n }\n\n return false;\n}\n\n/**\n * Checks if a URL is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If denied list exists, URL must NOT match any denied pattern\n * 2. If allowed list exists, URL must match at least one allowed pattern\n * 3. If neither list exists, URL is allowed\n */\nexport function isUrlAllowed(\n url: string,\n constraints: UrlConstraints,\n): boolean {\n // 1. Denied list — any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchUrlPattern(url, pattern)) {\n return false;\n }\n }\n }\n\n // 2. Allowed list — must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchUrlPattern(url, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n","import type { PolicyRule, ExecutionRequest } from '@solongate/core';\nimport { TrustLevel } from '@solongate/core';\nimport { isPathAllowed, extractPathArguments } from './path-matcher.js';\nimport { isCommandAllowed, extractCommandArguments } from './command-matcher.js';\nimport { isFilenameAllowed, extractFilenames } from './filename-matcher.js';\nimport { isUrlAllowed, extractUrlArguments } from './url-matcher.js';\n\n/**\n * Pure function: determines if a policy rule matches an execution request.\n * No side effects. No I/O. Fully deterministic.\n */\nexport function ruleMatchesRequest(\n rule: PolicyRule,\n request: ExecutionRequest,\n): boolean {\n if (!rule.enabled) return false;\n if (rule.permission && rule.permission !== request.requiredPermission) return false;\n if (!toolPatternMatches(rule.toolPattern, request.toolName)) return false;\n if (!trustLevelMeetsMinimum(request.context.trustLevel, rule.minimumTrustLevel)) {\n return false;\n }\n if (rule.argumentConstraints) {\n if (!argumentConstraintsMatch(rule.argumentConstraints, request.arguments)) {\n return false;\n }\n }\n if (rule.pathConstraints) {\n const satisfied = pathConstraintsMatch(rule.pathConstraints, request.arguments);\n // For DENY rules: match when constraints are VIOLATED (path is dangerous)\n // For ALLOW rules: match when constraints are SATISFIED (path is safe)\n if (rule.effect === 'DENY') {\n if (satisfied) return false; // path is safe → don't deny\n } else {\n if (!satisfied) return false; // path is dangerous → don't allow\n }\n }\n if (rule.commandConstraints) {\n const satisfied = commandConstraintsMatch(rule.commandConstraints, request.arguments);\n if (rule.effect === 'DENY') {\n if (satisfied) return false;\n } else {\n if (!satisfied) return false;\n }\n }\n if (rule.filenameConstraints) {\n const satisfied = filenameConstraintsMatch(rule.filenameConstraints, request.arguments);\n if (rule.effect === 'DENY') {\n if (satisfied) return false; // filename is safe → don't deny\n } else {\n if (!satisfied) return false; // filename is dangerous → don't allow\n }\n }\n if (rule.urlConstraints) {\n const satisfied = urlConstraintsMatch(rule.urlConstraints, request.arguments);\n if (rule.effect === 'DENY') {\n if (satisfied) return false; // URL is safe → don't deny\n } else {\n if (!satisfied) return false; // URL is dangerous → don't allow\n }\n }\n return true;\n}\n\n/**\n * Glob-style tool name pattern matching.\n * Supports:\n * '*' → match all\n * 'prefix*' → starts with prefix\n * '*suffix' → ends with suffix\n * '*infix*' → contains infix\n * Does NOT support regex (ReDoS prevention).\n */\nexport function toolPatternMatches(pattern: string, toolName: string): boolean {\n if (pattern === '*') return true;\n\n const startsWithStar = pattern.startsWith('*');\n const endsWithStar = pattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n // *infix* → contains\n const infix = pattern.slice(1, -1);\n return infix.length > 0 && toolName.includes(infix);\n }\n if (endsWithStar) {\n // prefix* → starts with\n const prefix = pattern.slice(0, -1);\n return toolName.startsWith(prefix);\n }\n if (startsWithStar) {\n // *suffix → ends with\n const suffix = pattern.slice(1);\n return toolName.endsWith(suffix);\n }\n\n return pattern === toolName;\n}\n\nconst TRUST_LEVEL_ORDER: Record<string, number> = {\n [TrustLevel.UNTRUSTED]: 0,\n [TrustLevel.VERIFIED]: 1,\n [TrustLevel.TRUSTED]: 2,\n};\n\nexport function trustLevelMeetsMinimum(\n actual: TrustLevel,\n minimum: TrustLevel,\n): boolean {\n return (TRUST_LEVEL_ORDER[actual] ?? -1) >= (TRUST_LEVEL_ORDER[minimum] ?? Infinity);\n}\n\n/**\n * Condition operators for argument constraints.\n * When constraint value is a plain string → exact match (or '*' for any).\n * When constraint value is an object → operator-based matching:\n * { $contains: \"str\" } — value includes substring\n * { $notContains: \"str\" } — value does NOT include substring\n * { $startsWith: \"str\" } — value starts with prefix\n * { $endsWith: \"str\" } — value ends with suffix\n * { $in: [\"a\",\"b\"] } — value is one of the listed values\n * { $notIn: [\"a\",\"b\"] } — value is NOT one of the listed values\n * { $gt: 5 } — numeric greater than\n * { $lt: 5 } — numeric less than\n * { $gte: 5 } — numeric greater than or equal\n * { $lte: 5 } — numeric less than or equal\n */\nfunction argumentConstraintsMatch(\n constraints: Record<string, unknown>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n for (const [key, constraint] of Object.entries(constraints)) {\n if (!(key in args)) return false;\n const argValue = args[key];\n\n // Plain string: exact match (backward compatible)\n if (typeof constraint === 'string') {\n if (constraint === '*') continue;\n if (typeof argValue === 'string') {\n if (argValue !== constraint) return false;\n } else {\n return false;\n }\n continue;\n }\n\n // Object with operators\n if (typeof constraint === 'object' && constraint !== null && !Array.isArray(constraint)) {\n const ops = constraint as Record<string, unknown>;\n const strValue = typeof argValue === 'string' ? argValue : undefined;\n const numValue = typeof argValue === 'number' ? argValue : undefined;\n\n if ('$contains' in ops && typeof ops.$contains === 'string') {\n if (!strValue || !strValue.includes(ops.$contains)) return false;\n }\n if ('$notContains' in ops && typeof ops.$notContains === 'string') {\n if (strValue && strValue.includes(ops.$notContains)) return false;\n }\n if ('$startsWith' in ops && typeof ops.$startsWith === 'string') {\n if (!strValue || !strValue.startsWith(ops.$startsWith)) return false;\n }\n if ('$endsWith' in ops && typeof ops.$endsWith === 'string') {\n if (!strValue || !strValue.endsWith(ops.$endsWith)) return false;\n }\n if ('$in' in ops && Array.isArray(ops.$in)) {\n if (!ops.$in.includes(argValue)) return false;\n }\n if ('$notIn' in ops && Array.isArray(ops.$notIn)) {\n if (ops.$notIn.includes(argValue)) return false;\n }\n if ('$gt' in ops && typeof ops.$gt === 'number') {\n if (numValue === undefined || numValue <= ops.$gt) return false;\n }\n if ('$lt' in ops && typeof ops.$lt === 'number') {\n if (numValue === undefined || numValue >= ops.$lt) return false;\n }\n if ('$gte' in ops && typeof ops.$gte === 'number') {\n if (numValue === undefined || numValue < ops.$gte) return false;\n }\n if ('$lte' in ops && typeof ops.$lte === 'number') {\n if (numValue === undefined || numValue > ops.$lte) return false;\n }\n\n continue;\n }\n }\n return true;\n}\n\nfunction pathConstraintsMatch(\n constraints: NonNullable<PolicyRule['pathConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const paths = extractPathArguments(args);\n\n // If no path arguments found, constraints don't apply\n if (paths.length === 0) return true;\n\n // ALL path arguments must satisfy constraints\n return paths.every((path) => isPathAllowed(path, constraints));\n}\n\nfunction commandConstraintsMatch(\n constraints: NonNullable<PolicyRule['commandConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const commands = extractCommandArguments(args);\n\n // If no command arguments found, constraints don't apply\n if (commands.length === 0) return true;\n\n // ALL command arguments must satisfy constraints\n return commands.every((cmd) => isCommandAllowed(cmd, constraints));\n}\n\nfunction filenameConstraintsMatch(\n constraints: NonNullable<PolicyRule['filenameConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const filenames = extractFilenames(args);\n\n // If no filename arguments found, constraints don't apply\n if (filenames.length === 0) return true;\n\n // ALL filenames must satisfy constraints\n return filenames.every((name) => isFilenameAllowed(name, constraints));\n}\n\nfunction urlConstraintsMatch(\n constraints: NonNullable<PolicyRule['urlConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const urls = extractUrlArguments(args);\n\n // If no URL arguments found, constraints don't apply\n if (urls.length === 0) return true;\n\n // ALL URLs must satisfy constraints\n return urls.every((url) => isUrlAllowed(url, constraints));\n}\n","import type {\n PolicySet,\n PolicyDecision,\n ExecutionRequest,\n PolicyEffect,\n} from '@solongate/core';\nimport { DEFAULT_POLICY_EFFECT } from '@solongate/core';\nimport { ruleMatchesRequest } from './matcher.js';\n\n/**\n * Evaluates a policy set against an execution request.\n *\n * Pure function: no side effects, no I/O, fully deterministic.\n *\n * Algorithm:\n * 1. Sort rules by priority (ascending - lower number = higher priority)\n * 2. Find the first matching rule\n * 3. If a rule matches, return its effect\n * 4. If no rule matches, return DENY (default-deny)\n */\nexport function evaluatePolicy(\n policySet: PolicySet,\n request: ExecutionRequest,\n): PolicyDecision {\n const startTime = performance.now();\n\n const sortedRules = [...policySet.rules].sort(\n (a, b) => a.priority - b.priority,\n );\n\n for (const rule of sortedRules) {\n if (ruleMatchesRequest(rule, request)) {\n const endTime = performance.now();\n return {\n effect: rule.effect,\n matchedRule: rule,\n reason: `Matched rule \"${rule.id}\": ${rule.description}`,\n timestamp: new Date().toISOString(),\n evaluationTimeMs: endTime - startTime,\n };\n }\n }\n\n const endTime = performance.now();\n return {\n effect: DEFAULT_POLICY_EFFECT as PolicyEffect,\n matchedRule: null,\n reason: 'No matching policy rule found. Default action: DENY.',\n timestamp: new Date().toISOString(),\n evaluationTimeMs: endTime - startTime,\n metadata: {\n evaluatedRules: sortedRules.length,\n ruleIds: sortedRules.map((r) => r.id),\n requestContext: {\n tool: request.toolName,\n arguments: Object.keys(request.arguments ?? {}),\n },\n },\n };\n}\n","import { PolicyRuleSchema, PolicySetSchema } from '@solongate/core';\nimport {\n MAX_RULES_PER_POLICY_SET,\n UNSAFE_CONFIGURATION_WARNINGS,\n} from '@solongate/core';\n\nexport interface ValidationResult {\n readonly valid: boolean;\n readonly errors: readonly string[];\n readonly warnings: readonly string[];\n}\n\nexport function validatePolicyRule(input: unknown): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n const result = PolicyRuleSchema.safeParse(input);\n if (!result.success) {\n return {\n valid: false,\n errors: result.error.errors.map(\n (e) => `${e.path.join('.')}: ${e.message}`,\n ),\n warnings: [],\n };\n }\n\n const rule = result.data;\n\n if (rule.toolPattern === '*' && rule.effect === 'ALLOW') {\n warnings.push(UNSAFE_CONFIGURATION_WARNINGS.WILDCARD_ALLOW);\n }\n\n if (rule.minimumTrustLevel === 'TRUSTED') {\n warnings.push(UNSAFE_CONFIGURATION_WARNINGS.TRUSTED_LEVEL_EXTERNAL);\n }\n\n if (!rule.permission || rule.permission === 'EXECUTE') {\n warnings.push(UNSAFE_CONFIGURATION_WARNINGS.EXECUTE_WITHOUT_REVIEW);\n }\n\n return { valid: true, errors, warnings };\n}\n\nexport function validatePolicySet(input: unknown): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n const result = PolicySetSchema.safeParse(input);\n if (!result.success) {\n return {\n valid: false,\n errors: result.error.errors.map(\n (e) => `${e.path.join('.')}: ${e.message}`,\n ),\n warnings: [],\n };\n }\n\n const policySet = result.data;\n\n if (policySet.rules.length > MAX_RULES_PER_POLICY_SET) {\n errors.push(\n `Policy set exceeds maximum of ${MAX_RULES_PER_POLICY_SET} rules`,\n );\n }\n\n const ruleIds = new Set<string>();\n for (const rule of policySet.rules) {\n if (ruleIds.has(rule.id)) {\n errors.push(`Duplicate rule ID: \"${rule.id}\"`);\n }\n ruleIds.add(rule.id);\n }\n\n for (const rule of policySet.rules) {\n const ruleResult = validatePolicyRule(rule);\n warnings.push(...ruleResult.warnings);\n }\n\n const hasDenyRule = policySet.rules.some((r) => r.effect === 'DENY');\n if (!hasDenyRule && policySet.rules.length > 0) {\n warnings.push(\n 'Policy set contains only ALLOW rules. The default-deny fallback is the only protection.',\n );\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n","import type { PolicyRule, PolicySet } from '@solongate/core';\nimport { UNSAFE_CONFIGURATION_WARNINGS } from '@solongate/core';\n\nexport interface SecurityWarning {\n readonly level: 'WARNING' | 'CRITICAL';\n readonly code: string;\n readonly message: string;\n readonly ruleId?: string;\n readonly recommendation: string;\n}\n\n/** Analyzes a policy set and returns security warnings. Pure function. */\nexport function analyzeSecurityWarnings(\n policySet: PolicySet,\n): readonly SecurityWarning[] {\n const warnings: SecurityWarning[] = [];\n\n for (const rule of policySet.rules) {\n warnings.push(...analyzeRuleWarnings(rule));\n }\n\n const allowRules = policySet.rules.filter(\n (r) => r.effect === 'ALLOW' && r.enabled,\n );\n const wildcardAllows = allowRules.filter((r) => r.toolPattern === '*');\n\n if (wildcardAllows.length > 0) {\n warnings.push({\n level: 'CRITICAL',\n code: 'WILDCARD_ALLOW',\n message: UNSAFE_CONFIGURATION_WARNINGS.WILDCARD_ALLOW,\n recommendation:\n 'Replace wildcard ALLOW rules with specific tool patterns.',\n });\n }\n\n return warnings;\n}\n\nfunction analyzeRuleWarnings(rule: PolicyRule): SecurityWarning[] {\n const warnings: SecurityWarning[] = [];\n\n if (rule.effect === 'ALLOW' && rule.minimumTrustLevel === 'UNTRUSTED') {\n warnings.push({\n level: 'CRITICAL',\n code: 'ALLOW_UNTRUSTED',\n message: `Rule \"${rule.id}\" allows execution for UNTRUSTED requests. Unverified LLM requests can execute tools.`,\n ruleId: rule.id,\n recommendation:\n 'Set minimumTrustLevel to VERIFIED or higher for ALLOW rules.',\n });\n }\n\n if (rule.effect === 'ALLOW' && (!rule.permission || rule.permission === 'EXECUTE')) {\n warnings.push({\n level: 'WARNING',\n code: 'ALLOW_EXECUTE',\n message: UNSAFE_CONFIGURATION_WARNINGS.EXECUTE_WITHOUT_REVIEW,\n ruleId: rule.id,\n recommendation:\n 'Ensure EXECUTE permissions are intentional and scoped to specific tools.',\n });\n }\n\n return warnings;\n}\n","import type { PolicySet } from '@solongate/core';\nimport { PolicyEffect, Permission, TrustLevel } from '@solongate/core';\n\n/**\n * Creates the default \"deny all\" policy set.\n * This is the starting policy for any new SolonGate deployment.\n */\nexport function createDefaultDenyPolicySet(): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: 'default-deny',\n name: 'Default Deny All',\n description:\n 'Denies all tool executions. Add explicit ALLOW rules to grant access to specific tools.',\n version: 1,\n rules: [\n {\n id: 'deny-all-execute',\n description: 'Explicitly deny all tool executions',\n effect: PolicyEffect.DENY,\n priority: 10000,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'deny-all-write',\n description: 'Explicitly deny all write operations',\n effect: PolicyEffect.DENY,\n priority: 10000,\n toolPattern: '*',\n permission: Permission.WRITE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'deny-all-read',\n description: 'Explicitly deny all read operations',\n effect: PolicyEffect.DENY,\n priority: 10000,\n toolPattern: '*',\n permission: Permission.READ,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n\n/**\n * Creates a permissive \"allow all\" policy set.\n * Allows all tool executions — useful for development or when\n * using SolonGate only for monitoring and audit logging.\n */\nexport function createPermissivePolicySet(): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: 'permissive',\n name: 'Permissive (Allow All)',\n description: 'Allows all tool executions. SolonGate still provides input validation, rate limiting, and audit logging.',\n version: 1,\n rules: [\n {\n id: 'allow-all-execute',\n description: 'Allow all tool executions',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-all-read',\n description: 'Allow all read operations',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.READ,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-all-write',\n description: 'Allow all write operations',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.WRITE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n\n/**\n * Creates a read-only policy set for a specific tool pattern.\n * Allows reads for VERIFIED requests only.\n */\nexport function createReadOnlyPolicySet(toolPattern: string): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: `read-only-${toolPattern}`,\n name: `Read-Only: ${toolPattern}`,\n description: `Allows read access to tools matching \"${toolPattern}\". Denies write and execute.`,\n version: 1,\n rules: [\n {\n id: `allow-read-${toolPattern}`,\n description: `Allow read access to ${toolPattern}`,\n effect: PolicyEffect.ALLOW,\n priority: 100,\n toolPattern,\n permission: Permission.READ,\n minimumTrustLevel: TrustLevel.VERIFIED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n\n/**\n * Creates a sandboxed policy set for a given root directory.\n * Allows file operations within rootDir, blocks dangerous commands,\n * denies access to sensitive files.\n */\nexport function createSandboxedPolicySet(rootDir: string): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: `sandbox-${rootDir.replace(/\\//g, '-')}`,\n name: `Sandbox: ${rootDir}`,\n description: `Allows operations within ${rootDir}. Blocks dangerous commands and sensitive file access.`,\n version: 1,\n rules: [\n {\n id: 'deny-dangerous-commands',\n description: 'Block dangerous shell commands',\n effect: PolicyEffect.DENY,\n priority: 50,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n commandConstraints: {\n denied: [\n 'rm -rf *', 'rm -r /*', 'mkfs*', 'dd if=*',\n 'curl*|*bash*', 'wget*|*sh*',\n 'shutdown*', 'reboot*', 'chmod*777*',\n ],\n },\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'deny-sensitive-paths',\n description: 'Block access to sensitive files',\n effect: PolicyEffect.DENY,\n priority: 51,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n pathConstraints: {\n denied: [\n '**/.env*', '**/.ssh/**', '**/.aws/**',\n '**/credentials*', '**/*.pem', '**/*.key',\n ],\n },\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-sandboxed-files',\n description: `Allow file operations within ${rootDir}`,\n effect: PolicyEffect.ALLOW,\n priority: 100,\n toolPattern: 'file_*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n pathConstraints: {\n rootDirectory: rootDir,\n allowed: [`${rootDir}/**`],\n },\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-all-execute',\n description: 'Allow all other tool executions',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n","import type {\n PolicySet,\n PolicyDecision,\n ExecutionRequest,\n} from '@solongate/core';\nimport { POLICY_EVALUATION_TIMEOUT_MS } from '@solongate/core';\nimport { evaluatePolicy } from './evaluator.js';\nimport { validatePolicySet, type ValidationResult } from './validator.js';\nimport { analyzeSecurityWarnings, type SecurityWarning } from './warnings.js';\nimport { createDefaultDenyPolicySet } from './defaults.js';\nimport { PolicyStore, type PolicyVersion } from './policy-store.js';\n\n/**\n * PolicyEngine is the primary interface for policy evaluation.\n *\n * Wraps pure evaluation functions with:\n * - Policy set management (load, validate, swap)\n * - Timeout protection\n * - Warning aggregation\n * - Optional versioned policy store\n */\nexport class PolicyEngine {\n private policySet: PolicySet;\n private readonly timeoutMs: number;\n private readonly store: PolicyStore | null;\n\n constructor(options?: {\n policySet?: PolicySet;\n timeoutMs?: number;\n store?: PolicyStore;\n }) {\n this.policySet = options?.policySet ?? createDefaultDenyPolicySet();\n this.timeoutMs = options?.timeoutMs ?? POLICY_EVALUATION_TIMEOUT_MS;\n this.store = options?.store ?? null;\n }\n\n /**\n * Evaluates an execution request against the current policy set.\n * Never throws for denials - denial is a normal outcome, not an error.\n */\n evaluate(request: ExecutionRequest): PolicyDecision {\n const startTime = performance.now();\n const decision = evaluatePolicy(this.policySet, request);\n const elapsed = performance.now() - startTime;\n\n if (elapsed > this.timeoutMs) {\n console.warn(\n `[SolonGate] Policy evaluation took ${elapsed.toFixed(1)}ms ` +\n `(limit: ${this.timeoutMs}ms) for tool \"${request.toolName}\"`,\n );\n }\n\n return decision;\n }\n\n /**\n * Loads a new policy set, replacing the current one.\n * Validates before accepting. Auto-saves version when store is present.\n */\n loadPolicySet(\n policySet: PolicySet,\n options?: { reason?: string; createdBy?: string },\n ): ValidationResult {\n const validation = validatePolicySet(policySet);\n if (!validation.valid) {\n return validation;\n }\n this.policySet = policySet;\n\n if (this.store) {\n this.store.saveVersion(\n policySet,\n options?.reason ?? 'Policy updated',\n options?.createdBy ?? 'system',\n );\n }\n\n return validation;\n }\n\n /**\n * Rolls back to a previous policy version.\n * Only available when a PolicyStore is configured.\n */\n rollback(version: number): PolicyVersion {\n if (!this.store) {\n throw new Error('PolicyStore not configured - cannot rollback');\n }\n\n const policyVersion = this.store.rollback(this.policySet.id, version);\n this.policySet = policyVersion.policySet;\n return policyVersion;\n }\n\n getPolicySet(): Readonly<PolicySet> {\n return this.policySet;\n }\n\n getSecurityWarnings(): readonly SecurityWarning[] {\n return analyzeSecurityWarnings(this.policySet);\n }\n\n getStore(): PolicyStore | null {\n return this.store;\n }\n\n reset(): void {\n this.policySet = createDefaultDenyPolicySet();\n }\n}\n","import type { PolicySet, PolicyRule } from '@solongate/core';\nimport { createHash } from 'node:crypto';\n\n/**\n * A versioned snapshot of a policy set.\n * Immutable once created - modifications create new versions.\n */\nexport interface PolicyVersion {\n readonly version: number;\n readonly policySet: PolicySet;\n readonly hash: string;\n readonly reason: string;\n readonly createdBy: string;\n readonly createdAt: string;\n}\n\n/**\n * Diff between two policy versions.\n */\nexport interface PolicyDiff {\n readonly added: readonly PolicyRule[];\n readonly removed: readonly PolicyRule[];\n readonly modified: readonly { readonly old: PolicyRule; readonly new: PolicyRule }[];\n}\n\n/**\n * In-memory versioned policy store.\n * Stores complete history of policy changes with cryptographic hashes.\n *\n * Security properties:\n * - Immutable versions: once saved, a version cannot be modified\n * - Hash chain: each version includes SHA256 of the policy content\n * - Full history: no version is ever deleted\n */\nexport class PolicyStore {\n private readonly versions = new Map<string, PolicyVersion[]>();\n\n /**\n * Saves a new version of a policy set.\n * The version number auto-increments.\n */\n saveVersion(\n policySet: PolicySet,\n reason: string,\n createdBy: string,\n ): PolicyVersion {\n const id = policySet.id;\n const history = this.versions.get(id) ?? [];\n\n const latestVersion = history.length > 0 ? history[history.length - 1]!.version : 0;\n\n const version: PolicyVersion = {\n version: latestVersion + 1,\n policySet: Object.freeze({ ...policySet }),\n hash: this.computeHash(policySet),\n reason,\n createdBy,\n createdAt: new Date().toISOString(),\n };\n\n const newHistory = [...history, version];\n this.versions.set(id, newHistory);\n\n return version;\n }\n\n /**\n * Gets a specific version of a policy set.\n */\n getVersion(id: string, version: number): PolicyVersion | null {\n const history = this.versions.get(id);\n if (!history) return null;\n return history.find((v) => v.version === version) ?? null;\n }\n\n /**\n * Gets the latest version of a policy set.\n */\n getLatest(id: string): PolicyVersion | null {\n const history = this.versions.get(id);\n if (!history || history.length === 0) return null;\n return history[history.length - 1]!;\n }\n\n /**\n * Gets the full version history of a policy set.\n */\n getHistory(id: string): readonly PolicyVersion[] {\n return this.versions.get(id) ?? [];\n }\n\n /**\n * Rolls back to a previous version by creating a new version\n * with the same content as the target version.\n */\n rollback(id: string, toVersion: number): PolicyVersion {\n const target = this.getVersion(id, toVersion);\n if (!target) {\n throw new Error(`Version ${toVersion} not found for policy \"${id}\"`);\n }\n\n return this.saveVersion(\n target.policySet,\n `Rollback to version ${toVersion}`,\n 'system',\n );\n }\n\n /**\n * Computes a diff between two policy versions.\n */\n diff(v1: PolicyVersion, v2: PolicyVersion): PolicyDiff {\n const oldRulesMap = new Map(v1.policySet.rules.map((r) => [r.id, r]));\n const newRulesMap = new Map(v2.policySet.rules.map((r) => [r.id, r]));\n\n const added: PolicyRule[] = [];\n const removed: PolicyRule[] = [];\n const modified: { old: PolicyRule; new: PolicyRule }[] = [];\n\n // Find added and modified rules\n for (const [id, newRule] of newRulesMap) {\n const oldRule = oldRulesMap.get(id);\n if (!oldRule) {\n added.push(newRule);\n } else if (JSON.stringify(oldRule) !== JSON.stringify(newRule)) {\n modified.push({ old: oldRule, new: newRule });\n }\n }\n\n // Find removed rules\n for (const [id, oldRule] of oldRulesMap) {\n if (!newRulesMap.has(id)) {\n removed.push(oldRule);\n }\n }\n\n return { added, removed, modified };\n }\n\n /**\n * Computes SHA256 hash of a policy set for integrity verification.\n */\n computeHash(policySet: PolicySet): string {\n const serialized = JSON.stringify(policySet, Object.keys(policySet).sort());\n return createHash('sha256').update(serialized).digest('hex');\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/path-matcher.ts","../src/command-matcher.ts","../src/filename-matcher.ts","../src/url-matcher.ts","../src/matcher.ts","../src/evaluator.ts","../src/validator.ts","../src/warnings.ts","../src/defaults.ts","../src/engine.ts","../src/policy-store.ts"],"names":["endTime","UNSAFE_CONFIGURATION_WARNINGS","TrustLevel"],"mappings":"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","file":"index.js","sourcesContent":["import type { PolicyRule } from '@solongate/core';\n\ntype PathConstraints = NonNullable<PolicyRule['pathConstraints']>;\n\n/**\n * Normalizes a file path for consistent matching.\n * Resolves . and .. segments, normalizes separators.\n */\nexport function normalizePath(path: string): string {\n // Normalize separators to forward slash\n let normalized = path.replace(/\\\\/g, '/');\n\n // Remove trailing slash (except for root)\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n\n // Resolve . and .. segments\n const parts = normalized.split('/');\n const resolved: string[] = [];\n\n for (const part of parts) {\n if (part === '.' || part === '') {\n if (resolved.length === 0) resolved.push('');\n continue;\n }\n if (part === '..') {\n if (resolved.length > 1) {\n resolved.pop();\n }\n continue;\n }\n resolved.push(part);\n }\n\n return resolved.join('/') || '/';\n}\n\n/**\n * Checks if a path is within a root directory (sandbox boundary).\n * Prevents escaping via .., symlinks, etc.\n */\nexport function isWithinRoot(path: string, root: string): boolean {\n const normalizedPath = normalizePath(path);\n const normalizedRoot = normalizePath(root);\n\n // Path must start with root\n if (normalizedPath === normalizedRoot) return true;\n return normalizedPath.startsWith(normalizedRoot + '/');\n}\n\n/**\n * Glob-style path pattern matching.\n * Supports:\n * - * matches any single path segment (not /)\n * - ** matches any number of path segments\n * - Exact match\n *\n * Does NOT support regex (ReDoS prevention).\n */\nexport function matchPathPattern(path: string, pattern: string): boolean {\n const normalizedPath = normalizePath(path);\n const normalizedPattern = normalizePath(pattern);\n\n if (normalizedPattern === '*') return true;\n if (normalizedPattern === normalizedPath) return true;\n\n const patternParts = normalizedPattern.split('/');\n const pathParts = normalizedPath.split('/');\n\n return matchParts(pathParts, 0, patternParts, 0);\n}\n\nfunction matchParts(\n pathParts: string[],\n pi: number,\n patternParts: string[],\n qi: number,\n): boolean {\n while (pi < pathParts.length && qi < patternParts.length) {\n const pattern = patternParts[qi]!;\n\n if (pattern === '**') {\n // ** can match zero or more path segments\n if (qi === patternParts.length - 1) return true;\n\n // Try matching ** against 0, 1, 2, ... path segments\n for (let i = pi; i <= pathParts.length; i++) {\n if (matchParts(pathParts, i, patternParts, qi + 1)) {\n return true;\n }\n }\n return false;\n }\n\n if (pattern === '*') {\n // * matches exactly one path segment\n pi++;\n qi++;\n continue;\n }\n\n // Support intra-segment globs: *.txt, file.*, test-*-data, etc.\n if (pattern.includes('*')) {\n if (!matchSegmentGlob(pathParts[pi]!, pattern)) {\n return false;\n }\n pi++;\n qi++;\n continue;\n }\n\n if (pattern !== pathParts[pi]) {\n return false;\n }\n\n pi++;\n qi++;\n }\n\n // Skip trailing ** patterns\n while (qi < patternParts.length && patternParts[qi] === '**') {\n qi++;\n }\n\n return pi === pathParts.length && qi === patternParts.length;\n}\n\n/**\n * Checks if a path is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If rootDirectory is set, path must be within it\n * 2. If denied list exists, path must NOT match any denied pattern\n * 3. If allowed list exists, path must match at least one allowed pattern\n * 4. If neither list exists, path is allowed (constraints are optional)\n */\nexport function isPathAllowed(\n path: string,\n constraints: PathConstraints,\n): boolean {\n // 1. Root directory check (sandbox)\n if (constraints.rootDirectory) {\n if (!isWithinRoot(path, constraints.rootDirectory)) {\n return false;\n }\n }\n\n // 2. Denied list - any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchPathPattern(path, pattern)) {\n return false;\n }\n }\n }\n\n // 3. Allowed list - must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchPathPattern(path, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n\n/**\n * Matches a single path segment against a glob pattern containing *.\n * Examples: *.txt matches safe.txt, file.* matches file.js, *secret* matches my-secret-key\n */\nfunction matchSegmentGlob(segment: string, pattern: string): boolean {\n const startsWithStar = pattern.startsWith('*');\n const endsWithStar = pattern.endsWith('*');\n\n if (pattern === '*') return true;\n\n if (startsWithStar && endsWithStar) {\n // *infix* — contains\n const infix = pattern.slice(1, -1);\n return segment.toLowerCase().includes(infix.toLowerCase());\n }\n if (startsWithStar) {\n // *suffix — ends with\n const suffix = pattern.slice(1);\n return segment.toLowerCase().endsWith(suffix.toLowerCase());\n }\n if (endsWithStar) {\n // prefix* — starts with\n const prefix = pattern.slice(0, -1);\n return segment.toLowerCase().startsWith(prefix.toLowerCase());\n }\n\n // Single * in middle: split on * and check prefix+suffix\n const starIdx = pattern.indexOf('*');\n if (starIdx !== -1) {\n const prefix = pattern.slice(0, starIdx);\n const suffix = pattern.slice(starIdx + 1);\n const seg = segment.toLowerCase();\n return seg.startsWith(prefix.toLowerCase()) && seg.endsWith(suffix.toLowerCase()) && seg.length >= prefix.length + suffix.length;\n }\n\n return segment === pattern;\n}\n\n/**\n * Known argument field names that typically contain file paths.\n */\nconst PATH_FIELDS = new Set([\n 'path',\n 'file',\n 'file_path',\n 'filepath',\n 'filename',\n 'directory',\n 'dir',\n 'folder',\n 'source',\n 'destination',\n 'dest',\n 'target',\n 'input',\n 'output',\n 'cwd',\n 'root',\n 'notebook_path',\n]);\n\n/**\n * Extracts path-like arguments from tool call arguments.\n * Uses multiple heuristics:\n * 1. Known path field names — always extract\n * 2. Strings containing / or \\ (original heuristic)\n * 3. Strings starting with . (.env, ./foo)\n */\nexport function extractPathArguments(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const paths: string[] = [];\n const seen = new Set<string>();\n\n function addPath(value: string): void {\n const trimmed = value.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n paths.push(trimmed);\n }\n }\n\n for (const [key, value] of Object.entries(args)) {\n if (typeof value !== 'string') continue;\n\n // Known path field names\n if (PATH_FIELDS.has(key.toLowerCase())) {\n addPath(value);\n continue;\n }\n\n // Contains path separators\n if (value.includes('/') || value.includes('\\\\')) {\n addPath(value);\n continue;\n }\n\n // Starts with . (.env, ./config, ../secret)\n if (value.startsWith('.')) {\n addPath(value);\n continue;\n }\n }\n\n return paths;\n}\n","import type { PolicyRule } from '@solongate/core';\n\ntype CommandConstraints = NonNullable<PolicyRule['commandConstraints']>;\n\n/**\n * Known argument field names that typically contain commands or shell-like content.\n * Used to extract commands from tool call arguments for constraint matching.\n */\nconst COMMAND_FIELDS = new Set([\n 'command',\n 'cmd',\n 'query',\n 'code',\n 'script',\n 'shell',\n 'exec',\n 'sql',\n 'expression',\n 'function',\n]);\n\n/**\n * Heuristic patterns that indicate a string value is likely a command/shell expression,\n * even when the field name is not in COMMAND_FIELDS.\n */\nconst COMMAND_HEURISTICS = [\n /^(sh|bash|cmd|powershell|zsh|fish)\\s+-c\\s+/i, // shell -c \"...\"\n /^(sudo|doas)\\s+/i, // privilege escalation\n /^\\w+\\s+&&\\s+/, // cmd1 && cmd2\n /^\\w+\\s*\\|\\s*\\w+/, // cmd1 | cmd2\n /^\\w+\\s*;\\s*\\w+/, // cmd1; cmd2\n /^(curl|wget|nc|ncat)\\s+/i, // network commands\n /^(rm|del|rmdir)\\s+/i, // destructive commands\n /^(cat|type|more|less)\\s+.*[/\\\\]/i, // file read commands with paths\n /^(eval|source)\\s+/i, // eval/source wrappers\n /^(printenv|env|set)\\b/i, // environment variable leak\n /^(cat|head|tail|more|less|strings|xxd|od|hexdump|bat)\\s+/i, // file read commands\n];\n\n/**\n * Regex to match subshell wrapper patterns like `bash -c '...'`, `sh -c \"...\"`, `eval \"...\"`.\n * Extracts the inner command for recursive constraint checking.\n */\nconst SUBSHELL_WRAPPERS = [\n /^(?:sh|bash|zsh|fish|dash|ksh)\\s+-c\\s+['\"](.+?)['\"]\\s*$/i,\n /^(?:sh|bash|zsh|fish|dash|ksh)\\s+-c\\s+(.+)$/i,\n /^eval\\s+['\"](.+?)['\"]\\s*$/i,\n /^eval\\s+(.+)$/i,\n /^(?:sh|bash|zsh|fish|dash|ksh)\\s+<<\\s*['\"]?(\\w+)['\"]?\\n([\\s\\S]+?)\\n\\1$/i,\n];\n\n/**\n * Extracts inner commands from subshell wrappers (bash -c, eval, etc.)\n * Returns the original command plus any extracted inner commands.\n */\nexport function extractInnerCommands(command: string): string[] {\n const results = [command];\n const trimmed = command.trim();\n\n for (const pattern of SUBSHELL_WRAPPERS) {\n const match = trimmed.match(pattern);\n if (match) {\n // For heredoc pattern, inner command is in group 2\n const inner = (match[2] ?? match[1] ?? '').trim();\n if (inner) {\n results.push(inner);\n // Recurse: inner command might also be a wrapper\n const nested = extractInnerCommands(inner);\n for (const n of nested) {\n if (n !== inner) results.push(n);\n }\n }\n break;\n }\n }\n\n // Also handle string concatenation patterns that build commands:\n // variable=value && ... && command \"$variable\"\n // Look for the final command after the last && or ;\n const chainParts = trimmed.split(/\\s*(?:&&|;)\\s*/);\n if (chainParts.length > 1) {\n for (const part of chainParts) {\n const p = part.trim();\n if (p && p !== trimmed && !p.includes('=')) {\n results.push(p);\n }\n }\n }\n\n return [...new Set(results)];\n}\n\n/**\n * Extracts command-like arguments from tool call arguments.\n * Uses known field names plus heuristic detection for command-like strings\n * in any field, and recurses into nested objects/arrays.\n */\nexport function extractCommandArguments(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const commands: string[] = [];\n const seen = new Set<string>();\n\n function addCommand(value: string): void {\n const trimmed = value.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n commands.push(trimmed);\n }\n }\n\n function scanValue(key: string, value: unknown): void {\n if (typeof value === 'string') {\n // Known command field names — always extract\n if (COMMAND_FIELDS.has(key.toLowerCase())) {\n addCommand(value);\n return;\n }\n // Deep scan: heuristic detection of command-like strings\n for (const pattern of COMMAND_HEURISTICS) {\n if (pattern.test(value)) {\n addCommand(value);\n return;\n }\n }\n }\n // Recurse into arrays and objects\n if (Array.isArray(value)) {\n for (const item of value) {\n scanValue(key, item);\n }\n } else if (typeof value === 'object' && value !== null) {\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n scanValue(k, v);\n }\n }\n }\n\n for (const [key, value] of Object.entries(args)) {\n scanValue(key, value);\n }\n\n // Extract inner commands from subshell wrappers (bash -c, eval, etc.)\n const expanded: string[] = [];\n for (const cmd of commands) {\n for (const inner of extractInnerCommands(cmd)) {\n if (!seen.has(inner)) {\n seen.add(inner);\n expanded.push(inner);\n }\n }\n }\n commands.push(...expanded);\n\n return commands;\n}\n\n/**\n * Glob-style command pattern matching.\n * Matches against the command string (first word) or full command line.\n *\n * Patterns:\n * 'ls' → exact match on command name\n * 'git*' → command starts with 'git'\n * '*sql*' → command contains 'sql'\n * 'rm -rf *' → full command line starts with 'rm -rf '\n */\nexport function matchCommandPattern(command: string, pattern: string): boolean {\n if (pattern === '*') return true;\n\n const normalizedCommand = command.trim().toLowerCase();\n const normalizedPattern = pattern.trim().toLowerCase();\n\n if (normalizedPattern === normalizedCommand) return true;\n\n const startsWithStar = normalizedPattern.startsWith('*');\n const endsWithStar = normalizedPattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = normalizedPattern.slice(1, -1);\n return infix.length > 0 && normalizedCommand.includes(infix);\n }\n if (endsWithStar) {\n const prefix = normalizedPattern.slice(0, -1);\n return normalizedCommand.startsWith(prefix);\n }\n if (startsWithStar) {\n const suffix = normalizedPattern.slice(1);\n return normalizedCommand.endsWith(suffix);\n }\n\n // Also try matching just the command name (first word)\n const commandName = normalizedCommand.split(/\\s+/)[0] ?? '';\n return commandName === normalizedPattern;\n}\n\n/**\n * Checks if a command is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If denied list exists, command must NOT match any denied pattern\n * 2. If allowed list exists, command must match at least one allowed pattern\n * 3. If neither list exists, command is allowed (constraints are optional)\n */\nexport function isCommandAllowed(\n command: string,\n constraints: CommandConstraints,\n): boolean {\n // 1. Denied list — any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchCommandPattern(command, pattern)) {\n return false;\n }\n }\n }\n\n // 2. Allowed list — must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchCommandPattern(command, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n","import type { PolicyRule } from '@solongate/core';\n\ntype FilenameConstraints = NonNullable<PolicyRule['filenameConstraints']>;\n\n/**\n * Extracts filenames from ALL string arguments (deep scan).\n * For path-like values, extracts the basename.\n * For non-path values, uses the string itself if it looks like a filename.\n */\nexport function extractFilenames(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const filenames: string[] = [];\n const seen = new Set<string>();\n\n function addFilename(name: string): void {\n const trimmed = name.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n filenames.push(trimmed);\n }\n }\n\n function scanValue(value: unknown): void {\n if (typeof value === 'string') {\n const trimmed = value.trim();\n if (!trimmed) return;\n\n // Skip URLs\n if (/^https?:\\/\\//i.test(trimmed)) return;\n\n // Deep shell-aware scan: extract filenames from shell constructs\n // before normal tokenization. This catches:\n // cat $(echo .env) → .env\n // cat `echo .env` → .env\n // a='.env' && cat \"$a\" → .env\n // cat ./{c,s}e* → brace expansion\n _deepShellScanImpl(trimmed, addFilename);\n\n // If it contains a path separator, extract the basename\n if (trimmed.includes('/') || trimmed.includes('\\\\')) {\n const normalized = trimmed.replace(/\\\\/g, '/');\n const parts = normalized.split('/');\n const basename = parts[parts.length - 1];\n if (basename && basename.length > 0) {\n addFilename(basename);\n // Also expand globs in basename\n if (basename.includes('*') || basename.includes('?')) {\n for (const expanded of expandSensitiveGlob(basename)) {\n addFilename(expanded);\n }\n }\n }\n // Don't return — also do multi-word scan below for paths in commands\n }\n\n // Multi-word strings: split by whitespace and check each token\n // Catches: \"SELECT * FROM .env\", \"echo .env.local\", \"bash -c 'cat .env'\", etc.\n if (trimmed.includes(' ')) {\n for (const rawToken of trimmed.split(/\\s+/)) {\n // Strip surrounding quotes, backticks, and shell metacharacters from tokens\n const token = rawToken.replace(/^['\"`$({]+|['\"`})]+$/g, '');\n if (!token) continue;\n if (token.includes('/') || token.includes('\\\\')) {\n const parts = token.replace(/\\\\/g, '/').split('/');\n const basename = parts[parts.length - 1];\n if (basename && looksLikeFilename(basename)) addFilename(basename);\n // Expand globs in path basenames\n if (basename && (basename.includes('*') || basename.includes('?'))) {\n for (const expanded of expandSensitiveGlob(basename)) {\n addFilename(expanded);\n }\n }\n } else if (looksLikeFilename(token)) {\n addFilename(token);\n }\n // Expand shell glob wildcards that could match sensitive files\n // e.g., \"cred*\" could match \"credentials.json\", \"sec*\" → \"secrets.json\"\n if (token.includes('*') || token.includes('?')) {\n for (const expanded of expandSensitiveGlob(token)) {\n addFilename(expanded);\n }\n }\n }\n return;\n }\n\n // Single token: if it looks like a filename (has a dot extension or starts with dot)\n if (looksLikeFilename(trimmed)) {\n addFilename(trimmed);\n }\n // Single token with glob\n if (trimmed.includes('*') || trimmed.includes('?')) {\n for (const expanded of expandSensitiveGlob(trimmed)) {\n addFilename(expanded);\n }\n }\n return;\n }\n // Recurse into arrays and objects\n if (Array.isArray(value)) {\n for (const item of value) {\n scanValue(item);\n }\n } else if (typeof value === 'object' && value !== null) {\n for (const v of Object.values(value)) {\n scanValue(v);\n }\n }\n }\n\n for (const value of Object.values(args)) {\n scanValue(value);\n }\n\n return filenames;\n}\n\n/**\n * Deep shell-aware scan: extracts filenames hidden inside shell constructs.\n * Handles command substitution, backtick substitution, variable assignment,\n * brace expansion, input redirection, and string concatenation.\n */\nfunction _deepShellScanImpl(value: string, addFn: (s: string) => void): void {\n // 1. Command substitution: $(echo .env) → extract inner arguments\n const cmdSubMatches = value.matchAll(/\\$\\(([^)]+)\\)/g);\n for (const m of cmdSubMatches) {\n const inner = m[1] ?? '';\n for (const token of inner.split(/\\s+/)) {\n const clean = token.replace(/^['\"`]+|['\"`]+$/g, '');\n if (looksLikeFilename(clean)) addFn(clean);\n }\n }\n\n // 2. Backtick substitution: `echo .env` → extract inner arguments\n const backtickMatches = value.matchAll(/`([^`]+)`/g);\n for (const m of backtickMatches) {\n const inner = m[1] ?? '';\n for (const token of inner.split(/\\s+/)) {\n const clean = token.replace(/^['\"`]+|['\"`]+$/g, '');\n if (looksLikeFilename(clean)) addFn(clean);\n }\n }\n\n // 3. Variable assignment with sensitive filenames:\n // a='.env' OR file=\".env\" OR a='.en' (partial — check concat patterns)\n const assignMatches = value.matchAll(/\\b\\w+=[\"']?([^\"'&;\\s]+)[\"']?/g);\n for (const m of assignMatches) {\n const val = m[1] ?? '';\n if (looksLikeFilename(val)) addFn(val);\n }\n\n // 4. String concatenation detection: collect all quoted string literals\n // and check if any combination forms a sensitive filename\n const quotedParts: string[] = [];\n const quotedMatches = value.matchAll(/['\"]([^'\"]*)['\"]/g);\n for (const m of quotedMatches) {\n if (m[1]) quotedParts.push(m[1]);\n }\n // Try concatenating consecutive parts\n if (quotedParts.length >= 2) {\n for (let i = 0; i < quotedParts.length - 1; i++) {\n const concat = quotedParts[i]! + quotedParts[i + 1]!;\n if (looksLikeFilename(concat)) addFn(concat);\n // Try 3-part concat\n if (i + 2 < quotedParts.length) {\n const concat3 = concat + quotedParts[i + 2]!;\n if (looksLikeFilename(concat3)) addFn(concat3);\n }\n }\n }\n\n // 5. Brace expansion: ./{c,s}e* → expand to ./ce*, ./se*\n const braceMatches = value.matchAll(/\\{([^}]+)\\}/g);\n for (const m of braceMatches) {\n const alternatives = (m[1] ?? '').split(',');\n const prefix = value.slice(0, m.index ?? 0).split(/\\s+/).pop() ?? '';\n const suffix = value.slice((m.index ?? 0) + m[0].length).split(/\\s+/)[0] ?? '';\n for (const alt of alternatives) {\n const expanded = prefix + alt.trim() + suffix;\n const clean = expanded.replace(/^['\"`$({./]+/, '');\n if (looksLikeFilename(clean)) addFn(clean);\n if (clean.includes('*') || clean.includes('?')) {\n for (const globExpanded of expandSensitiveGlob(clean)) {\n addFn(globExpanded);\n }\n }\n }\n }\n\n // 6. Input redirection: < .env, <<< .env\n const redirectMatches = value.matchAll(/<?<\\s*['\"]?([^\\s'\";&|]+)['\"]?/g);\n for (const m of redirectMatches) {\n const file = m[1] ?? '';\n if (looksLikeFilename(file)) addFn(file);\n }\n\n // 7. mapfile/readarray with redirection: mapfile -t lines < .env\n const mapfileMatch = value.match(/\\b(?:mapfile|readarray)\\b.*<\\s*['\"]?([^\\s'\";&|]+)['\"]?/i);\n if (mapfileMatch && mapfileMatch[1]) {\n if (looksLikeFilename(mapfileMatch[1])) addFn(mapfileMatch[1]);\n }\n}\n\n/**\n * Known sensitive filenames that glob patterns in commands might target.\n * When a wildcard like \"cred*\" or \"sec*\" is used, we check if it could\n * match any of these sensitive files to prevent wildcard-based bypass.\n */\nconst SENSITIVE_FILENAMES = [\n '.env', '.env.local', '.env.production', '.env.development',\n 'credentials.json', 'secrets.json', 'secrets.yaml', 'secrets.yml',\n '.npmrc', '.pypirc', '.netrc',\n 'id_rsa', 'id_ed25519', 'id_ecdsa',\n 'policy.json', '.mcp.json', 'guard.mjs', 'audit.mjs',\n 'settings.json',\n];\n\n/**\n * Expands a glob-like pattern against known sensitive filenames.\n * Returns sensitive filenames that the glob would match.\n * e.g., \"cred*\" → [\"credentials.json\"], \"sec*\" → [\"secrets.json\", \"secrets.yaml\"]\n */\nfunction expandSensitiveGlob(pattern: string): string[] {\n const p = pattern.toLowerCase();\n const matches: string[] = [];\n\n for (const filename of SENSITIVE_FILENAMES) {\n const f = filename.toLowerCase();\n\n if (p === '*') {\n // Don't expand bare wildcard to everything\n continue;\n }\n\n const startsWithStar = p.startsWith('*');\n const endsWithStar = p.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = p.slice(1, -1);\n if (infix && f.includes(infix)) matches.push(filename);\n } else if (endsWithStar) {\n const prefix = p.slice(0, -1);\n if (f.startsWith(prefix)) matches.push(filename);\n } else if (startsWithStar) {\n const suffix = p.slice(1);\n if (f.endsWith(suffix)) matches.push(filename);\n } else if (p.includes('?')) {\n // Simple ? glob: replace ? with regex .\n const regex = new RegExp('^' + p.replace(/\\?/g, '.').replace(/\\*/g, '.*') + '$', 'i');\n if (regex.test(f)) matches.push(filename);\n }\n }\n\n return matches;\n}\n\n/**\n * Checks if a string looks like a filename.\n * Matches: .env, .env.local, config.json, id_rsa, Makefile, etc.\n */\nfunction looksLikeFilename(s: string): boolean {\n // Starts with dot (.env, .gitignore, .env.local)\n if (s.startsWith('.')) return true;\n // Has a file extension (foo.txt, package.json)\n if (/\\.\\w+$/.test(s)) return true;\n // Known extensionless filenames\n const knownFiles = new Set([\n 'id_rsa', 'id_dsa', 'id_ecdsa', 'id_ed25519',\n 'authorized_keys', 'known_hosts',\n 'makefile', 'dockerfile', 'vagrantfile',\n 'gemfile', 'rakefile', 'procfile',\n ]);\n if (knownFiles.has(s.toLowerCase())) return true;\n return false;\n}\n\n/**\n * Glob-style filename pattern matching (case-insensitive).\n *\n * Patterns:\n * '.env' → exact match\n * '*.pem' → ends with .pem\n * '.env.*' → starts with .env.\n * '*secret*' → contains \"secret\"\n */\nexport function matchFilenamePattern(filename: string, pattern: string): boolean {\n if (pattern === '*') return true;\n\n const normalizedFilename = filename.toLowerCase();\n const normalizedPattern = pattern.toLowerCase();\n\n if (normalizedFilename === normalizedPattern) return true;\n\n const startsWithStar = normalizedPattern.startsWith('*');\n const endsWithStar = normalizedPattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = normalizedPattern.slice(1, -1);\n return infix.length > 0 && normalizedFilename.includes(infix);\n }\n if (startsWithStar) {\n const suffix = normalizedPattern.slice(1);\n return normalizedFilename.endsWith(suffix);\n }\n if (endsWithStar) {\n const prefix = normalizedPattern.slice(0, -1);\n return normalizedFilename.startsWith(prefix);\n }\n\n // Single * in middle: .env.* → split on * and check prefix+suffix\n const starIdx = normalizedPattern.indexOf('*');\n if (starIdx !== -1) {\n const prefix = normalizedPattern.slice(0, starIdx);\n const suffix = normalizedPattern.slice(starIdx + 1);\n return (\n normalizedFilename.startsWith(prefix) &&\n normalizedFilename.endsWith(suffix) &&\n normalizedFilename.length >= prefix.length + suffix.length\n );\n }\n\n return false;\n}\n\n/**\n * Checks if a filename is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If denied list exists, filename must NOT match any denied pattern\n * 2. If allowed list exists, filename must match at least one allowed pattern\n * 3. If neither list exists, filename is allowed\n */\nexport function isFilenameAllowed(\n filename: string,\n constraints: FilenameConstraints,\n): boolean {\n // 1. Denied list — any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchFilenamePattern(filename, pattern)) {\n return false;\n }\n }\n }\n\n // 2. Allowed list — must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchFilenamePattern(filename, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n","import type { PolicyRule } from '@solongate/core';\n\ntype UrlConstraints = NonNullable<PolicyRule['urlConstraints']>;\n\n/**\n * Known argument field names that typically contain URLs.\n */\nconst URL_FIELDS = new Set([\n 'url',\n 'href',\n 'uri',\n 'endpoint',\n 'link',\n 'src',\n 'source',\n 'target',\n 'redirect',\n 'callback',\n 'webhook',\n]);\n\n/**\n * Extracts URL arguments from tool call arguments.\n * Scans ALL string values — not just known field names.\n * Any string containing http:// or https:// is treated as a URL.\n */\nexport function extractUrlArguments(\n args: Readonly<Record<string, unknown>>,\n): string[] {\n const urls: string[] = [];\n const seen = new Set<string>();\n\n function addUrl(value: string): void {\n const trimmed = value.trim();\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed);\n urls.push(trimmed);\n }\n }\n\n function scanValue(key: string, value: unknown): void {\n if (typeof value === 'string') {\n const lower = key.toLowerCase();\n // Known URL fields — always extract\n if (URL_FIELDS.has(lower)) {\n addUrl(value);\n return;\n }\n // Deep scan: any string containing a URL protocol\n if (/https?:\\/\\//i.test(value)) {\n addUrl(value);\n return;\n }\n // Bare domain patterns (e.g. \"instagram.com\", \"foo.onion\")\n // Require known TLD suffix to avoid false positives on version strings like \"1.0.abc\"\n if (/^[a-zA-Z0-9]([a-zA-Z0-9-]*\\.)+(?:com|net|org|io|dev|app|co|me|info|biz|gov|edu|mil|onion|xyz|ai|cloud|sh|run|so|to|cc|tv|fm|am|gg|id)(\\/.*)?$/.test(value)) {\n addUrl(value);\n return;\n }\n }\n // Recurse into arrays and objects\n if (Array.isArray(value)) {\n for (const item of value) {\n scanValue(key, item);\n }\n } else if (typeof value === 'object' && value !== null) {\n for (const [k, v] of Object.entries(value)) {\n scanValue(k, v);\n }\n }\n }\n\n for (const [key, value] of Object.entries(args)) {\n scanValue(key, value);\n }\n\n return urls;\n}\n\n/**\n * Glob-style URL pattern matching.\n * Normalizes both URL and pattern to lowercase for comparison.\n *\n * Patterns:\n * '*instagram.com*' → URL contains instagram.com\n * 'https://api.example.com/*' → URL starts with prefix\n * '*.onion' → URL ends with .onion\n * '*' → matches everything\n */\nexport function matchUrlPattern(url: string, pattern: string): boolean {\n if (pattern === '*') return true;\n\n const normalizedUrl = url.trim().toLowerCase();\n const normalizedPattern = pattern.trim().toLowerCase();\n\n if (normalizedPattern === normalizedUrl) return true;\n\n const startsWithStar = normalizedPattern.startsWith('*');\n const endsWithStar = normalizedPattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n const infix = normalizedPattern.slice(1, -1);\n return infix.length > 0 && normalizedUrl.includes(infix);\n }\n if (endsWithStar) {\n const prefix = normalizedPattern.slice(0, -1);\n return normalizedUrl.startsWith(prefix);\n }\n if (startsWithStar) {\n const suffix = normalizedPattern.slice(1);\n return normalizedUrl.endsWith(suffix);\n }\n\n return false;\n}\n\n/**\n * Checks if a URL is allowed by the given constraints.\n *\n * Evaluation order:\n * 1. If denied list exists, URL must NOT match any denied pattern\n * 2. If allowed list exists, URL must match at least one allowed pattern\n * 3. If neither list exists, URL is allowed\n */\nexport function isUrlAllowed(\n url: string,\n constraints: UrlConstraints,\n): boolean {\n // 1. Denied list — any match means denied\n if (constraints.denied && constraints.denied.length > 0) {\n for (const pattern of constraints.denied) {\n if (matchUrlPattern(url, pattern)) {\n return false;\n }\n }\n }\n\n // 2. Allowed list — must match at least one\n if (constraints.allowed && constraints.allowed.length > 0) {\n let matchesAllowed = false;\n for (const pattern of constraints.allowed) {\n if (matchUrlPattern(url, pattern)) {\n matchesAllowed = true;\n break;\n }\n }\n if (!matchesAllowed) return false;\n }\n\n return true;\n}\n","import type { PolicyRule, ExecutionRequest } from '@solongate/core';\nimport { TrustLevel } from '@solongate/core';\nimport { isPathAllowed, extractPathArguments } from './path-matcher.js';\nimport { isCommandAllowed, extractCommandArguments } from './command-matcher.js';\nimport { isFilenameAllowed, extractFilenames } from './filename-matcher.js';\nimport { isUrlAllowed, extractUrlArguments } from './url-matcher.js';\n\n/**\n * Pure function: determines if a policy rule matches an execution request.\n * No side effects. No I/O. Fully deterministic.\n */\nexport function ruleMatchesRequest(\n rule: PolicyRule,\n request: ExecutionRequest,\n): boolean {\n if (!rule.enabled) return false;\n if (rule.permission && rule.permission !== request.requiredPermission) return false;\n if (!toolPatternMatches(rule.toolPattern, request.toolName)) return false;\n if (!trustLevelMeetsMinimum(request.context.trustLevel, rule.minimumTrustLevel)) {\n return false;\n }\n if (rule.argumentConstraints) {\n if (!argumentConstraintsMatch(rule.argumentConstraints, request.arguments)) {\n return false;\n }\n }\n if (rule.pathConstraints) {\n const satisfied = pathConstraintsMatch(rule.pathConstraints, request.arguments);\n // For DENY rules: match when constraints are VIOLATED (path is dangerous)\n // For ALLOW rules: match when constraints are SATISFIED (path is safe)\n if (rule.effect === 'DENY') {\n if (satisfied) return false; // path is safe → don't deny\n } else {\n if (!satisfied) return false; // path is dangerous → don't allow\n }\n }\n if (rule.commandConstraints) {\n const satisfied = commandConstraintsMatch(rule.commandConstraints, request.arguments);\n if (rule.effect === 'DENY') {\n if (satisfied) return false;\n } else {\n if (!satisfied) return false;\n }\n }\n if (rule.filenameConstraints) {\n const satisfied = filenameConstraintsMatch(rule.filenameConstraints, request.arguments);\n if (rule.effect === 'DENY') {\n if (satisfied) return false; // filename is safe → don't deny\n } else {\n if (!satisfied) return false; // filename is dangerous → don't allow\n }\n }\n if (rule.urlConstraints) {\n const satisfied = urlConstraintsMatch(rule.urlConstraints, request.arguments);\n if (rule.effect === 'DENY') {\n if (satisfied) return false; // URL is safe → don't deny\n } else {\n if (!satisfied) return false; // URL is dangerous → don't allow\n }\n }\n return true;\n}\n\n/**\n * Glob-style tool name pattern matching.\n * Supports:\n * '*' → match all\n * 'prefix*' → starts with prefix\n * '*suffix' → ends with suffix\n * '*infix*' → contains infix\n * Does NOT support regex (ReDoS prevention).\n */\nexport function toolPatternMatches(pattern: string, toolName: string): boolean {\n if (pattern === '*') return true;\n\n const startsWithStar = pattern.startsWith('*');\n const endsWithStar = pattern.endsWith('*');\n\n if (startsWithStar && endsWithStar) {\n // *infix* → contains\n const infix = pattern.slice(1, -1);\n return infix.length > 0 && toolName.includes(infix);\n }\n if (endsWithStar) {\n // prefix* → starts with\n const prefix = pattern.slice(0, -1);\n return toolName.startsWith(prefix);\n }\n if (startsWithStar) {\n // *suffix → ends with\n const suffix = pattern.slice(1);\n return toolName.endsWith(suffix);\n }\n\n return pattern === toolName;\n}\n\nconst TRUST_LEVEL_ORDER: Record<string, number> = {\n [TrustLevel.UNTRUSTED]: 0,\n [TrustLevel.VERIFIED]: 1,\n [TrustLevel.TRUSTED]: 2,\n};\n\nexport function trustLevelMeetsMinimum(\n actual: TrustLevel,\n minimum: TrustLevel,\n): boolean {\n return (TRUST_LEVEL_ORDER[actual] ?? -1) >= (TRUST_LEVEL_ORDER[minimum] ?? Infinity);\n}\n\n/**\n * Condition operators for argument constraints.\n * When constraint value is a plain string → exact match (or '*' for any).\n * When constraint value is an object → operator-based matching:\n * { $contains: \"str\" } — value includes substring\n * { $notContains: \"str\" } — value does NOT include substring\n * { $startsWith: \"str\" } — value starts with prefix\n * { $endsWith: \"str\" } — value ends with suffix\n * { $in: [\"a\",\"b\"] } — value is one of the listed values\n * { $notIn: [\"a\",\"b\"] } — value is NOT one of the listed values\n * { $gt: 5 } — numeric greater than\n * { $lt: 5 } — numeric less than\n * { $gte: 5 } — numeric greater than or equal\n * { $lte: 5 } — numeric less than or equal\n */\nfunction argumentConstraintsMatch(\n constraints: Record<string, unknown>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n for (const [key, constraint] of Object.entries(constraints)) {\n if (!(key in args)) return false;\n const argValue = args[key];\n\n // Plain string: exact match (backward compatible)\n if (typeof constraint === 'string') {\n if (constraint === '*') continue;\n if (typeof argValue === 'string') {\n if (argValue !== constraint) return false;\n } else {\n return false;\n }\n continue;\n }\n\n // Object with operators\n if (typeof constraint === 'object' && constraint !== null && !Array.isArray(constraint)) {\n const ops = constraint as Record<string, unknown>;\n const strValue = typeof argValue === 'string' ? argValue : undefined;\n const numValue = typeof argValue === 'number' ? argValue : undefined;\n\n if ('$contains' in ops && typeof ops.$contains === 'string') {\n if (!strValue || !strValue.includes(ops.$contains)) return false;\n }\n if ('$notContains' in ops && typeof ops.$notContains === 'string') {\n if (strValue && strValue.includes(ops.$notContains)) return false;\n }\n if ('$startsWith' in ops && typeof ops.$startsWith === 'string') {\n if (!strValue || !strValue.startsWith(ops.$startsWith)) return false;\n }\n if ('$endsWith' in ops && typeof ops.$endsWith === 'string') {\n if (!strValue || !strValue.endsWith(ops.$endsWith)) return false;\n }\n if ('$in' in ops && Array.isArray(ops.$in)) {\n if (!ops.$in.includes(argValue)) return false;\n }\n if ('$notIn' in ops && Array.isArray(ops.$notIn)) {\n if (ops.$notIn.includes(argValue)) return false;\n }\n if ('$gt' in ops && typeof ops.$gt === 'number') {\n if (numValue === undefined || numValue <= ops.$gt) return false;\n }\n if ('$lt' in ops && typeof ops.$lt === 'number') {\n if (numValue === undefined || numValue >= ops.$lt) return false;\n }\n if ('$gte' in ops && typeof ops.$gte === 'number') {\n if (numValue === undefined || numValue < ops.$gte) return false;\n }\n if ('$lte' in ops && typeof ops.$lte === 'number') {\n if (numValue === undefined || numValue > ops.$lte) return false;\n }\n\n continue;\n }\n }\n return true;\n}\n\nfunction pathConstraintsMatch(\n constraints: NonNullable<PolicyRule['pathConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const paths = extractPathArguments(args);\n\n // If no path arguments found, constraints don't apply\n if (paths.length === 0) return true;\n\n // ALL path arguments must satisfy constraints\n return paths.every((path) => isPathAllowed(path, constraints));\n}\n\nfunction commandConstraintsMatch(\n constraints: NonNullable<PolicyRule['commandConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const commands = extractCommandArguments(args);\n\n // If no command arguments found, constraints don't apply\n if (commands.length === 0) return true;\n\n // ALL command arguments must satisfy constraints\n return commands.every((cmd) => isCommandAllowed(cmd, constraints));\n}\n\nfunction filenameConstraintsMatch(\n constraints: NonNullable<PolicyRule['filenameConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const filenames = extractFilenames(args);\n\n // If no filename arguments found, constraints don't apply\n if (filenames.length === 0) return true;\n\n // ALL filenames must satisfy constraints\n return filenames.every((name) => isFilenameAllowed(name, constraints));\n}\n\nfunction urlConstraintsMatch(\n constraints: NonNullable<PolicyRule['urlConstraints']>,\n args: Readonly<Record<string, unknown>>,\n): boolean {\n const urls = extractUrlArguments(args);\n\n // If no URL arguments found, constraints don't apply\n if (urls.length === 0) return true;\n\n // ALL URLs must satisfy constraints\n return urls.every((url) => isUrlAllowed(url, constraints));\n}\n","import type {\n PolicySet,\n PolicyDecision,\n ExecutionRequest,\n PolicyEffect,\n} from '@solongate/core';\nimport { DEFAULT_POLICY_EFFECT } from '@solongate/core';\nimport { ruleMatchesRequest } from './matcher.js';\n\n/**\n * Evaluates a policy set against an execution request.\n *\n * Pure function: no side effects, no I/O, fully deterministic.\n *\n * Algorithm:\n * 1. Sort rules by priority (ascending - lower number = higher priority)\n * 2. Find the first matching rule\n * 3. If a rule matches, return its effect\n * 4. If no rule matches, return DENY (default-deny)\n */\nexport function evaluatePolicy(\n policySet: PolicySet,\n request: ExecutionRequest,\n): PolicyDecision {\n const startTime = performance.now();\n\n const sortedRules = [...policySet.rules].sort(\n (a, b) => a.priority - b.priority,\n );\n\n for (const rule of sortedRules) {\n if (ruleMatchesRequest(rule, request)) {\n const endTime = performance.now();\n return {\n effect: rule.effect,\n matchedRule: rule,\n reason: `Matched rule \"${rule.id}\": ${rule.description}`,\n timestamp: new Date().toISOString(),\n evaluationTimeMs: endTime - startTime,\n };\n }\n }\n\n const endTime = performance.now();\n return {\n effect: DEFAULT_POLICY_EFFECT as PolicyEffect,\n matchedRule: null,\n reason: 'No matching policy rule found. Default action: DENY.',\n timestamp: new Date().toISOString(),\n evaluationTimeMs: endTime - startTime,\n metadata: {\n evaluatedRules: sortedRules.length,\n ruleIds: sortedRules.map((r) => r.id),\n requestContext: {\n tool: request.toolName,\n arguments: Object.keys(request.arguments ?? {}),\n },\n },\n };\n}\n","import { PolicyRuleSchema, PolicySetSchema } from '@solongate/core';\nimport {\n MAX_RULES_PER_POLICY_SET,\n UNSAFE_CONFIGURATION_WARNINGS,\n} from '@solongate/core';\n\nexport interface ValidationResult {\n readonly valid: boolean;\n readonly errors: readonly string[];\n readonly warnings: readonly string[];\n}\n\nexport function validatePolicyRule(input: unknown): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n const result = PolicyRuleSchema.safeParse(input);\n if (!result.success) {\n return {\n valid: false,\n errors: result.error.errors.map(\n (e) => `${e.path.join('.')}: ${e.message}`,\n ),\n warnings: [],\n };\n }\n\n const rule = result.data;\n\n if (rule.toolPattern === '*' && rule.effect === 'ALLOW') {\n warnings.push(UNSAFE_CONFIGURATION_WARNINGS.WILDCARD_ALLOW);\n }\n\n if (rule.minimumTrustLevel === 'TRUSTED') {\n warnings.push(UNSAFE_CONFIGURATION_WARNINGS.TRUSTED_LEVEL_EXTERNAL);\n }\n\n if (!rule.permission || rule.permission === 'EXECUTE') {\n warnings.push(UNSAFE_CONFIGURATION_WARNINGS.EXECUTE_WITHOUT_REVIEW);\n }\n\n return { valid: true, errors, warnings };\n}\n\nexport function validatePolicySet(input: unknown): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n const result = PolicySetSchema.safeParse(input);\n if (!result.success) {\n return {\n valid: false,\n errors: result.error.errors.map(\n (e) => `${e.path.join('.')}: ${e.message}`,\n ),\n warnings: [],\n };\n }\n\n const policySet = result.data;\n\n if (policySet.rules.length > MAX_RULES_PER_POLICY_SET) {\n errors.push(\n `Policy set exceeds maximum of ${MAX_RULES_PER_POLICY_SET} rules`,\n );\n }\n\n const ruleIds = new Set<string>();\n for (const rule of policySet.rules) {\n if (ruleIds.has(rule.id)) {\n errors.push(`Duplicate rule ID: \"${rule.id}\"`);\n }\n ruleIds.add(rule.id);\n }\n\n for (const rule of policySet.rules) {\n const ruleResult = validatePolicyRule(rule);\n warnings.push(...ruleResult.warnings);\n }\n\n const hasDenyRule = policySet.rules.some((r) => r.effect === 'DENY');\n if (!hasDenyRule && policySet.rules.length > 0) {\n warnings.push(\n 'Policy set contains only ALLOW rules. The default-deny fallback is the only protection.',\n );\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n","import type { PolicyRule, PolicySet } from '@solongate/core';\nimport { UNSAFE_CONFIGURATION_WARNINGS } from '@solongate/core';\n\nexport interface SecurityWarning {\n readonly level: 'WARNING' | 'CRITICAL';\n readonly code: string;\n readonly message: string;\n readonly ruleId?: string;\n readonly recommendation: string;\n}\n\n/** Analyzes a policy set and returns security warnings. Pure function. */\nexport function analyzeSecurityWarnings(\n policySet: PolicySet,\n): readonly SecurityWarning[] {\n const warnings: SecurityWarning[] = [];\n\n for (const rule of policySet.rules) {\n warnings.push(...analyzeRuleWarnings(rule));\n }\n\n const allowRules = policySet.rules.filter(\n (r) => r.effect === 'ALLOW' && r.enabled,\n );\n const wildcardAllows = allowRules.filter((r) => r.toolPattern === '*');\n\n if (wildcardAllows.length > 0) {\n warnings.push({\n level: 'CRITICAL',\n code: 'WILDCARD_ALLOW',\n message: UNSAFE_CONFIGURATION_WARNINGS.WILDCARD_ALLOW,\n recommendation:\n 'Replace wildcard ALLOW rules with specific tool patterns.',\n });\n }\n\n return warnings;\n}\n\nfunction analyzeRuleWarnings(rule: PolicyRule): SecurityWarning[] {\n const warnings: SecurityWarning[] = [];\n\n if (rule.effect === 'ALLOW' && rule.minimumTrustLevel === 'UNTRUSTED') {\n warnings.push({\n level: 'CRITICAL',\n code: 'ALLOW_UNTRUSTED',\n message: `Rule \"${rule.id}\" allows execution for UNTRUSTED requests. Unverified LLM requests can execute tools.`,\n ruleId: rule.id,\n recommendation:\n 'Set minimumTrustLevel to VERIFIED or higher for ALLOW rules.',\n });\n }\n\n if (rule.effect === 'ALLOW' && (!rule.permission || rule.permission === 'EXECUTE')) {\n warnings.push({\n level: 'WARNING',\n code: 'ALLOW_EXECUTE',\n message: UNSAFE_CONFIGURATION_WARNINGS.EXECUTE_WITHOUT_REVIEW,\n ruleId: rule.id,\n recommendation:\n 'Ensure EXECUTE permissions are intentional and scoped to specific tools.',\n });\n }\n\n return warnings;\n}\n","import type { PolicySet } from '@solongate/core';\nimport { PolicyEffect, Permission, TrustLevel } from '@solongate/core';\n\n/**\n * Creates the default \"deny all\" policy set.\n * This is the starting policy for any new SolonGate deployment.\n */\nexport function createDefaultDenyPolicySet(): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: 'default-deny',\n name: 'Default Deny All',\n description:\n 'Denies all tool executions. Add explicit ALLOW rules to grant access to specific tools.',\n version: 1,\n rules: [\n {\n id: 'deny-all-execute',\n description: 'Explicitly deny all tool executions',\n effect: PolicyEffect.DENY,\n priority: 10000,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'deny-all-write',\n description: 'Explicitly deny all write operations',\n effect: PolicyEffect.DENY,\n priority: 10000,\n toolPattern: '*',\n permission: Permission.WRITE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'deny-all-read',\n description: 'Explicitly deny all read operations',\n effect: PolicyEffect.DENY,\n priority: 10000,\n toolPattern: '*',\n permission: Permission.READ,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n\n/**\n * Creates a permissive \"allow all\" policy set.\n * Allows all tool executions — useful for development or when\n * using SolonGate only for monitoring and audit logging.\n */\nexport function createPermissivePolicySet(): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: 'permissive',\n name: 'Permissive (Allow All)',\n description: 'Allows all tool executions. SolonGate still provides input validation, rate limiting, and audit logging.',\n version: 1,\n rules: [\n {\n id: 'allow-all-execute',\n description: 'Allow all tool executions',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-all-read',\n description: 'Allow all read operations',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.READ,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-all-write',\n description: 'Allow all write operations',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.WRITE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n\n/**\n * Creates a read-only policy set for a specific tool pattern.\n * Allows reads for VERIFIED requests only.\n */\nexport function createReadOnlyPolicySet(toolPattern: string): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: `read-only-${toolPattern}`,\n name: `Read-Only: ${toolPattern}`,\n description: `Allows read access to tools matching \"${toolPattern}\". Denies write and execute.`,\n version: 1,\n rules: [\n {\n id: `allow-read-${toolPattern}`,\n description: `Allow read access to ${toolPattern}`,\n effect: PolicyEffect.ALLOW,\n priority: 100,\n toolPattern,\n permission: Permission.READ,\n minimumTrustLevel: TrustLevel.VERIFIED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n\n/**\n * Creates a sandboxed policy set for a given root directory.\n * Allows file operations within rootDir, blocks dangerous commands,\n * denies access to sensitive files.\n */\nexport function createSandboxedPolicySet(rootDir: string): PolicySet {\n const now = new Date().toISOString();\n\n return {\n id: `sandbox-${rootDir.replace(/\\//g, '-')}`,\n name: `Sandbox: ${rootDir}`,\n description: `Allows operations within ${rootDir}. Blocks dangerous commands and sensitive file access.`,\n version: 1,\n rules: [\n {\n id: 'deny-dangerous-commands',\n description: 'Block dangerous shell commands',\n effect: PolicyEffect.DENY,\n priority: 50,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n commandConstraints: {\n denied: [\n 'rm -rf *', 'rm -r /*', 'mkfs*', 'dd if=*',\n 'curl*|*bash*', 'wget*|*sh*',\n 'shutdown*', 'reboot*', 'chmod*777*',\n ],\n },\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'deny-sensitive-paths',\n description: 'Block access to sensitive files',\n effect: PolicyEffect.DENY,\n priority: 51,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n pathConstraints: {\n denied: [\n '**/.env*', '**/.ssh/**', '**/.aws/**',\n '**/credentials*', '**/*.pem', '**/*.key',\n ],\n },\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-sandboxed-files',\n description: `Allow file operations within ${rootDir}`,\n effect: PolicyEffect.ALLOW,\n priority: 100,\n toolPattern: 'file_*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n pathConstraints: {\n rootDirectory: rootDir,\n allowed: [`${rootDir}/**`],\n },\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n {\n id: 'allow-all-execute',\n description: 'Allow all other tool executions',\n effect: PolicyEffect.ALLOW,\n priority: 1000,\n toolPattern: '*',\n permission: Permission.EXECUTE,\n minimumTrustLevel: TrustLevel.UNTRUSTED,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n },\n ],\n createdAt: now,\n updatedAt: now,\n };\n}\n","import type {\n PolicySet,\n PolicyDecision,\n ExecutionRequest,\n} from '@solongate/core';\nimport { POLICY_EVALUATION_TIMEOUT_MS } from '@solongate/core';\nimport { evaluatePolicy } from './evaluator.js';\nimport { validatePolicySet, type ValidationResult } from './validator.js';\nimport { analyzeSecurityWarnings, type SecurityWarning } from './warnings.js';\nimport { createDefaultDenyPolicySet } from './defaults.js';\nimport { PolicyStore, type PolicyVersion } from './policy-store.js';\n\n/**\n * PolicyEngine is the primary interface for policy evaluation.\n *\n * Wraps pure evaluation functions with:\n * - Policy set management (load, validate, swap)\n * - Timeout protection\n * - Warning aggregation\n * - Optional versioned policy store\n */\nexport class PolicyEngine {\n private policySet: PolicySet;\n private readonly timeoutMs: number;\n private readonly store: PolicyStore | null;\n\n constructor(options?: {\n policySet?: PolicySet;\n timeoutMs?: number;\n store?: PolicyStore;\n }) {\n this.policySet = options?.policySet ?? createDefaultDenyPolicySet();\n this.timeoutMs = options?.timeoutMs ?? POLICY_EVALUATION_TIMEOUT_MS;\n this.store = options?.store ?? null;\n }\n\n /**\n * Evaluates an execution request against the current policy set.\n * Never throws for denials - denial is a normal outcome, not an error.\n */\n evaluate(request: ExecutionRequest): PolicyDecision {\n const startTime = performance.now();\n const decision = evaluatePolicy(this.policySet, request);\n const elapsed = performance.now() - startTime;\n\n if (elapsed > this.timeoutMs) {\n console.warn(\n `[SolonGate] Policy evaluation took ${elapsed.toFixed(1)}ms ` +\n `(limit: ${this.timeoutMs}ms) for tool \"${request.toolName}\"`,\n );\n }\n\n return decision;\n }\n\n /**\n * Loads a new policy set, replacing the current one.\n * Validates before accepting. Auto-saves version when store is present.\n */\n loadPolicySet(\n policySet: PolicySet,\n options?: { reason?: string; createdBy?: string },\n ): ValidationResult {\n const validation = validatePolicySet(policySet);\n if (!validation.valid) {\n return validation;\n }\n this.policySet = policySet;\n\n if (this.store) {\n this.store.saveVersion(\n policySet,\n options?.reason ?? 'Policy updated',\n options?.createdBy ?? 'system',\n );\n }\n\n return validation;\n }\n\n /**\n * Rolls back to a previous policy version.\n * Only available when a PolicyStore is configured.\n */\n rollback(version: number): PolicyVersion {\n if (!this.store) {\n throw new Error('PolicyStore not configured - cannot rollback');\n }\n\n const policyVersion = this.store.rollback(this.policySet.id, version);\n this.policySet = policyVersion.policySet;\n return policyVersion;\n }\n\n getPolicySet(): Readonly<PolicySet> {\n return this.policySet;\n }\n\n getSecurityWarnings(): readonly SecurityWarning[] {\n return analyzeSecurityWarnings(this.policySet);\n }\n\n getStore(): PolicyStore | null {\n return this.store;\n }\n\n reset(): void {\n this.policySet = createDefaultDenyPolicySet();\n }\n}\n","import type { PolicySet, PolicyRule } from '@solongate/core';\nimport { createHash } from 'node:crypto';\n\n/**\n * A versioned snapshot of a policy set.\n * Immutable once created - modifications create new versions.\n */\nexport interface PolicyVersion {\n readonly version: number;\n readonly policySet: PolicySet;\n readonly hash: string;\n readonly reason: string;\n readonly createdBy: string;\n readonly createdAt: string;\n}\n\n/**\n * Diff between two policy versions.\n */\nexport interface PolicyDiff {\n readonly added: readonly PolicyRule[];\n readonly removed: readonly PolicyRule[];\n readonly modified: readonly { readonly old: PolicyRule; readonly new: PolicyRule }[];\n}\n\n/**\n * In-memory versioned policy store.\n * Stores complete history of policy changes with cryptographic hashes.\n *\n * Security properties:\n * - Immutable versions: once saved, a version cannot be modified\n * - Hash chain: each version includes SHA256 of the policy content\n * - Full history: no version is ever deleted\n */\nexport class PolicyStore {\n private readonly versions = new Map<string, PolicyVersion[]>();\n\n /**\n * Saves a new version of a policy set.\n * The version number auto-increments.\n */\n saveVersion(\n policySet: PolicySet,\n reason: string,\n createdBy: string,\n ): PolicyVersion {\n const id = policySet.id;\n const history = this.versions.get(id) ?? [];\n\n const latestVersion = history.length > 0 ? history[history.length - 1]!.version : 0;\n\n const version: PolicyVersion = {\n version: latestVersion + 1,\n policySet: Object.freeze({ ...policySet }),\n hash: this.computeHash(policySet),\n reason,\n createdBy,\n createdAt: new Date().toISOString(),\n };\n\n const newHistory = [...history, version];\n this.versions.set(id, newHistory);\n\n return version;\n }\n\n /**\n * Gets a specific version of a policy set.\n */\n getVersion(id: string, version: number): PolicyVersion | null {\n const history = this.versions.get(id);\n if (!history) return null;\n return history.find((v) => v.version === version) ?? null;\n }\n\n /**\n * Gets the latest version of a policy set.\n */\n getLatest(id: string): PolicyVersion | null {\n const history = this.versions.get(id);\n if (!history || history.length === 0) return null;\n return history[history.length - 1]!;\n }\n\n /**\n * Gets the full version history of a policy set.\n */\n getHistory(id: string): readonly PolicyVersion[] {\n return this.versions.get(id) ?? [];\n }\n\n /**\n * Rolls back to a previous version by creating a new version\n * with the same content as the target version.\n */\n rollback(id: string, toVersion: number): PolicyVersion {\n const target = this.getVersion(id, toVersion);\n if (!target) {\n throw new Error(`Version ${toVersion} not found for policy \"${id}\"`);\n }\n\n return this.saveVersion(\n target.policySet,\n `Rollback to version ${toVersion}`,\n 'system',\n );\n }\n\n /**\n * Computes a diff between two policy versions.\n */\n diff(v1: PolicyVersion, v2: PolicyVersion): PolicyDiff {\n const oldRulesMap = new Map(v1.policySet.rules.map((r) => [r.id, r]));\n const newRulesMap = new Map(v2.policySet.rules.map((r) => [r.id, r]));\n\n const added: PolicyRule[] = [];\n const removed: PolicyRule[] = [];\n const modified: { old: PolicyRule; new: PolicyRule }[] = [];\n\n // Find added and modified rules\n for (const [id, newRule] of newRulesMap) {\n const oldRule = oldRulesMap.get(id);\n if (!oldRule) {\n added.push(newRule);\n } else if (JSON.stringify(oldRule) !== JSON.stringify(newRule)) {\n modified.push({ old: oldRule, new: newRule });\n }\n }\n\n // Find removed rules\n for (const [id, oldRule] of oldRulesMap) {\n if (!newRulesMap.has(id)) {\n removed.push(oldRule);\n }\n }\n\n return { added, removed, modified };\n }\n\n /**\n * Computes SHA256 hash of a policy set for integrity verification.\n */\n computeHash(policySet: PolicySet): string {\n const serialized = JSON.stringify(policySet, Object.keys(policySet).sort());\n return createHash('sha256').update(serialized).digest('hex');\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/policy-engine",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",