{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/types.ts","../src/log.ts","../src/failures/latency.ts","../src/failures/exception.ts","../src/failures/statuscode.ts","../src/failures/diskspace.ts","../src/failures/denylist.ts","../src/failures/timeout.ts","../src/failures/corruption.ts","../src/matching.ts","../src/orchestration.ts"],"sourcesContent":["import type { Context, Callback } from \"aws-lambda\";\nimport type { FailureFlagsConfig, LambdaHandler, FailureLambdaOptions } from \"./types.js\";\nimport { getConfig, resolveFailures } from \"./config.js\";\nimport { error as logError } from \"./log.js\";\nimport { clearDenylist, clearDiskSpace } from \"./failures/index.js\";\nimport { runPreHandlerInjections, runPostHandlerInjections } from \"./orchestration.js\";\n\n// Re-export types for consumers\nexport type {\n  FailureMode,\n  FlagValue,\n  FailureFlagsConfig,\n  ResolvedFailure,\n  LambdaHandler,\n  FailureLambdaOptions,\n  ConfigValidationError,\n  MatchCondition,\n  MatchOperator,\n} from \"./types.js\";\nexport { getConfig, clearConfigCache, validateFlagValue, parseFlags, resolveFailures } from \"./config.js\";\nexport { getNestedValue, matchesConditions } from \"./matching.js\";\n\n/**\n * Wraps a Lambda handler with failure injection.\n *\n * Each failure mode is an independent feature flag. Multiple failures can\n * be active simultaneously. Pre-handler modes run before the handler\n * (latency, timeout, diskspace, denylist, statuscode, exception).\n * Post-handler modes (corruption) run after the handler returns.\n *\n * Flags with `match` conditions only fire when the event satisfies all conditions.\n *\n * @example\n * ```ts\n * import failureLambda from \"failure-lambda\";\n *\n * export const handler = failureLambda(async (event, context) => {\n *   // your handler logic\n * });\n * ```\n */\nfunction injectFailure<TEvent = unknown, TResult = unknown>(\n  handler: LambdaHandler<TEvent, TResult>,\n  options?: FailureLambdaOptions,\n): LambdaHandler<TEvent, TResult> {\n  return async function wrappedHandler(\n    event: TEvent,\n    context: Context,\n    callback: Callback<TResult>,\n  ): Promise<TResult> {\n    if (process.env.FAILURE_LAMBDA_DISABLED === \"true\") {\n      return await handler(event, context, callback) as TResult;\n    }\n\n    try {\n      const configProvider = options?.configProvider ?? getConfig;\n      const flagsConfig: FailureFlagsConfig = await configProvider();\n      const failures = resolveFailures(flagsConfig);\n\n      // Fast path: skip the async pre-handler call entirely when there are no\n      // active failures. The await of the async runPreHandlerInjections forces\n      // a microtask yield that lets background extensions (e.g. AppConfig)\n      // block the event loop for hundreds of milliseconds.\n      if (failures.length === 0) {\n        return await handler(event, context, callback) as TResult;\n      }\n\n      const dryRun = options?.dryRun === true;\n      const preResult = await runPreHandlerInjections<TEvent, TResult>(failures, event, context, dryRun);\n      if (preResult) {\n        return preResult.shortCircuit;\n      }\n\n      const result = await handler(event, context, callback) as TResult;\n\n      return runPostHandlerInjections(failures, event, result, dryRun);\n    } catch (err) {\n      logError({ action: \"error\", message: err instanceof Error ? err.message : String(err) });\n      clearDenylist();\n      clearDiskSpace();\n      throw err;\n    }\n  };\n}\n\n// Default export for backwards compatibility: failureLambda(handler)\nexport default injectFailure;\n\n// Named export for explicit imports\nexport { injectFailure };\n","import { SSMClient, GetParameterCommand } from \"@aws-sdk/client-ssm\";\nimport type {\n  FailureMode,\n  FlagValue,\n  FailureFlagsConfig,\n  ResolvedFailure,\n  CachedConfig,\n  ConfigValidationError,\n} from \"./types.js\";\nimport { DEFAULT_FLAGS_CONFIG, FAILURE_MODE_ORDER } from \"./types.js\";\nimport { log, warn, error } from \"./log.js\";\n\nconst KNOWN_FLAGS: ReadonlySet<string> = new Set(FAILURE_MODE_ORDER);\n\nconst MAX_DISK_SPACE_MB = 10240;\nconst MAX_REGEX_LENGTH = 512;\n\n/**\n * Detect regex patterns vulnerable to catastrophic backtracking (ReDoS).\n * Checks for nested quantifiers like (a+)+, (a*)+, (a+)*, etc.\n * Also rejects overly long patterns as a general safety measure.\n */\nexport function isUnsafeRegex(pattern: string): boolean {\n  if (pattern.length > MAX_REGEX_LENGTH) return true;\n\n  let depth = 0;\n  const hasQuantifierInGroup: boolean[] = [false];\n\n  for (let i = 0; i < pattern.length; i++) {\n    const ch = pattern[i];\n\n    if (ch === \"\\\\\") {\n      i++;\n      continue;\n    }\n\n    if (ch === \"[\") {\n      i++;\n      while (i < pattern.length) {\n        if (pattern[i] === \"\\\\\") i++;\n        else if (pattern[i] === \"]\") break;\n        i++;\n      }\n      continue;\n    }\n\n    if (ch === \"(\") {\n      depth++;\n      hasQuantifierInGroup[depth] = false;\n      continue;\n    }\n\n    if (ch === \")\") {\n      const groupHadQuantifier = hasQuantifierInGroup[depth] ?? false;\n      depth = Math.max(0, depth - 1);\n\n      if (groupHadQuantifier && i + 1 < pattern.length) {\n        const next = pattern[i + 1];\n        if (next === \"+\" || next === \"*\" || next === \"{\") {\n          return true;\n        }\n      }\n      if (depth > 0 && groupHadQuantifier) {\n        hasQuantifierInGroup[depth] = true;\n      }\n      continue;\n    }\n\n    if (depth > 0 && (ch === \"+\" || ch === \"*\")) {\n      hasQuantifierInGroup[depth] = true;\n    }\n    if (depth > 0 && ch === \"{\") {\n      const rest = pattern.slice(i);\n      if (/^\\{\\d+,/.test(rest)) {\n        hasQuantifierInGroup[depth] = true;\n      }\n    }\n  }\n\n  return false;\n}\n\nconst DEFAULT_CACHE_TTL_SECONDS = 60;\n\n/** Module-level cache. Resets naturally on Lambda cold start. */\nlet configCache: CachedConfig | null = null;\n\n/** Lazy-initialized SSM client. Created on first use to avoid cold start penalty when using AppConfig. */\nlet ssmClient: SSMClient | null = null;\n\n/** Whether we've logged the config source yet (once per cold start) */\nlet hasLoggedSource = false;\n\nfunction getSSMClient(): SSMClient {\n  if (ssmClient === null) {\n    ssmClient = new SSMClient({});\n  }\n  return ssmClient;\n}\n\nfunction isAppConfigSource(): boolean {\n  return Boolean(process.env.FAILURE_APPCONFIG_CONFIGURATION);\n}\n\nfunction getCacheTtlMs(): number {\n  const envValue = process.env.FAILURE_CACHE_TTL;\n  if (envValue === undefined || envValue === \"\") {\n    // Auto-disable library cache for AppConfig — the extension already caches\n    // at its poll interval (AWS_APPCONFIG_EXTENSION_POLL_INTERVAL_SECONDS).\n    // Double-caching adds unnecessary staleness when changing config.\n    if (isAppConfigSource()) {\n      return 0;\n    }\n    return DEFAULT_CACHE_TTL_SECONDS * 1000;\n  }\n  const parsed = Number(envValue);\n  if (Number.isNaN(parsed) || parsed < 0) {\n    warn({ action: \"config\", message: `invalid FAILURE_CACHE_TTL=\"${envValue}\", using default ${DEFAULT_CACHE_TTL_SECONDS}s` });\n    return DEFAULT_CACHE_TTL_SECONDS * 1000;\n  }\n  if (parsed > 0 && isAppConfigSource()) {\n    warn({\n      action: \"config\",\n      message: `FAILURE_CACHE_TTL=${parsed}s with AppConfig — the AppConfig extension already caches at its poll interval; library caching adds staleness`,\n    });\n  }\n  return parsed * 1000;\n}\n\nfunction isCacheValid(): boolean {\n  if (configCache === null) {\n    return false;\n  }\n  const ttlMs = getCacheTtlMs();\n  if (ttlMs === 0) {\n    return false;\n  }\n  return Date.now() - configCache.fetchedAt < ttlMs;\n}\n\n/** Validate a single flag value. Returns array of errors (empty = valid). */\nexport function validateFlagValue(\n  mode: string,\n  raw: Record<string, unknown>,\n): ConfigValidationError[] {\n  const errors: ConfigValidationError[] = [];\n\n  if (typeof raw.enabled !== \"boolean\") {\n    errors.push({\n      field: `${mode}.enabled`,\n      message: \"must be a boolean\",\n      value: raw.enabled,\n    });\n  }\n\n  if (raw.percentage !== undefined) {\n    if (typeof raw.percentage !== \"number\" || !Number.isInteger(raw.percentage) || raw.percentage < 0 || raw.percentage > 100) {\n      errors.push({\n        field: `${mode}.percentage`,\n        message: \"must be an integer between 0 and 100\",\n        value: raw.percentage,\n      });\n    }\n  }\n\n  if (mode === \"latency\") {\n    if (raw.min_latency !== undefined) {\n      if (typeof raw.min_latency !== \"number\" || raw.min_latency < 0) {\n        errors.push({\n          field: `${mode}.min_latency`,\n          message: \"must be a non-negative number\",\n          value: raw.min_latency,\n        });\n      }\n    }\n    if (raw.max_latency !== undefined) {\n      if (typeof raw.max_latency !== \"number\" || raw.max_latency < 0) {\n        errors.push({\n          field: `${mode}.max_latency`,\n          message: \"must be a non-negative number\",\n          value: raw.max_latency,\n        });\n      }\n    }\n    if (\n      typeof raw.min_latency === \"number\" &&\n      typeof raw.max_latency === \"number\" &&\n      raw.min_latency > raw.max_latency\n    ) {\n      errors.push({\n        field: `${mode}.max_latency`,\n        message: \"max_latency must be >= min_latency\",\n        value: raw.max_latency,\n      });\n    }\n  }\n\n  if (mode === \"exception\") {\n    if (raw.exception_msg !== undefined && typeof raw.exception_msg !== \"string\") {\n      errors.push({\n        field: `${mode}.exception_msg`,\n        message: \"must be a string\",\n        value: raw.exception_msg,\n      });\n    }\n  }\n\n  if (mode === \"statuscode\") {\n    if (raw.status_code !== undefined) {\n      if (typeof raw.status_code !== \"number\" || raw.status_code < 100 || raw.status_code > 599) {\n        errors.push({\n          field: `${mode}.status_code`,\n          message: \"must be an HTTP status code (100-599)\",\n          value: raw.status_code,\n        });\n      }\n    }\n  }\n\n  if (mode === \"diskspace\") {\n    if (raw.disk_space !== undefined) {\n      if (typeof raw.disk_space !== \"number\" || raw.disk_space <= 0 || raw.disk_space > MAX_DISK_SPACE_MB) {\n        errors.push({\n          field: `${mode}.disk_space`,\n          message: `must be between 1 and ${MAX_DISK_SPACE_MB} (MB)`,\n          value: raw.disk_space,\n        });\n      }\n    }\n  }\n\n  if (mode === \"denylist\") {\n    if (raw.deny_list !== undefined) {\n      if (\n        !Array.isArray(raw.deny_list) ||\n        !raw.deny_list.every((item: unknown) => typeof item === \"string\")\n      ) {\n        errors.push({\n          field: `${mode}.deny_list`,\n          message: \"must be an array of strings\",\n          value: raw.deny_list,\n        });\n      } else {\n        for (let i = 0; i < raw.deny_list.length; i++) {\n          const pattern = raw.deny_list[i] as string;\n          try {\n            new RegExp(pattern);\n          } catch {\n            errors.push({\n              field: `${mode}.deny_list[${i}]`,\n              message: \"invalid regular expression\",\n              value: pattern,\n            });\n            continue;\n          }\n          if (isUnsafeRegex(pattern)) {\n            errors.push({\n              field: `${mode}.deny_list[${i}]`,\n              message: \"potentially unsafe pattern (nested quantifiers may cause excessive backtracking)\",\n              value: pattern,\n            });\n          }\n        }\n      }\n    }\n  }\n\n  if (mode === \"timeout\") {\n    if (raw.timeout_buffer_ms !== undefined) {\n      if (typeof raw.timeout_buffer_ms !== \"number\" || raw.timeout_buffer_ms < 0) {\n        errors.push({\n          field: `${mode}.timeout_buffer_ms`,\n          message: \"must be a non-negative number\",\n          value: raw.timeout_buffer_ms,\n        });\n      }\n    }\n  }\n\n  if (mode === \"corruption\") {\n    if (raw.body !== undefined && typeof raw.body !== \"string\") {\n      errors.push({\n        field: `${mode}.body`,\n        message: \"must be a string\",\n        value: raw.body,\n      });\n    }\n  }\n\n  if (raw.match !== undefined) {\n    if (!Array.isArray(raw.match)) {\n      errors.push({\n        field: `${mode}.match`,\n        message: \"must be an array of match condition objects\",\n        value: raw.match,\n      });\n    } else {\n      const VALID_OPERATORS = new Set([\"eq\", \"exists\", \"startsWith\", \"regex\"]);\n      for (let i = 0; i < raw.match.length; i++) {\n        const condition = raw.match[i] as unknown;\n        if (typeof condition !== \"object\" || condition === null) {\n          errors.push({\n            field: `${mode}.match[${i}]`,\n            message: \"must be an object with a string path field\",\n            value: condition,\n          });\n          continue;\n        }\n        const cond = condition as Record<string, unknown>;\n        if (typeof cond.path !== \"string\") {\n          errors.push({\n            field: `${mode}.match[${i}].path`,\n            message: \"must be a string\",\n            value: cond.path,\n          });\n        }\n        const operator = (cond.operator as string) ?? \"eq\";\n        if (cond.operator !== undefined && !VALID_OPERATORS.has(operator)) {\n          errors.push({\n            field: `${mode}.match[${i}].operator`,\n            message: `must be one of: eq, exists, startsWith, regex`,\n            value: cond.operator,\n          });\n        }\n        if (operator !== \"exists\" && typeof cond.value !== \"string\") {\n          errors.push({\n            field: `${mode}.match[${i}].value`,\n            message: \"must be a string (required for all operators except 'exists')\",\n            value: cond.value,\n          });\n        }\n        if (operator === \"regex\" && typeof cond.value === \"string\") {\n          try {\n            new RegExp(cond.value);\n          } catch {\n            errors.push({\n              field: `${mode}.match[${i}].value`,\n              message: \"invalid regular expression\",\n              value: cond.value,\n            });\n            continue;\n          }\n          if (isUnsafeRegex(cond.value)) {\n            errors.push({\n              field: `${mode}.match[${i}].value`,\n              message: \"potentially unsafe pattern (nested quantifiers may cause excessive backtracking)\",\n              value: cond.value,\n            });\n          }\n        }\n      }\n    }\n  }\n\n  return errors;\n}\n\n/** Parse raw JSON into FailureFlagsConfig. Validates each known flag key. */\nexport function parseFlags(raw: Record<string, unknown>): FailureFlagsConfig {\n  if (\"isEnabled\" in raw || \"failureMode\" in raw) {\n    warn({\n      action: \"config\",\n      message: \"detected 0.x configuration format — this version requires the v1.0 feature-flag format. See https://github.com/gunnargrosch/failure-lambda#migration-from-0x\",\n    });\n  }\n\n  const config: FailureFlagsConfig = {};\n\n  for (const key of Object.keys(raw)) {\n    if (!KNOWN_FLAGS.has(key)) {\n      continue;\n    }\n\n    const mode = key as FailureMode;\n    const flagRaw = raw[mode];\n\n    if (typeof flagRaw !== \"object\" || flagRaw === null || Array.isArray(flagRaw)) {\n      warn({ action: \"config\", mode, message: \"must be an object, skipping\" });\n      continue;\n    }\n\n    const flagObj = flagRaw as Record<string, unknown>;\n    const validationErrors = validateFlagValue(mode, flagObj);\n\n    if (validationErrors.length > 0) {\n      for (const validationError of validationErrors) {\n        warn({ action: \"config\", field: validationError.field, message: validationError.message, value: validationError.value });\n      }\n      warn({ action: \"config\", mode, message: \"skipping flag due to validation errors\" });\n      continue;\n    }\n\n    config[mode] = flagObj as unknown as FlagValue;\n  }\n\n  return config;\n}\n\n/**\n * Resolve enabled flags into an ordered array of failures to inject.\n * Order: latency, diskspace, denylist (non-terminating), then statuscode, exception (terminating).\n * Defaults percentage to 100 when omitted.\n */\nexport function resolveFailures(config: FailureFlagsConfig): ResolvedFailure[] {\n  const failures: ResolvedFailure[] = [];\n\n  for (const mode of FAILURE_MODE_ORDER) {\n    const flag = config[mode];\n    if (flag === undefined || !flag.enabled) {\n      continue;\n    }\n\n    failures.push({\n      mode,\n      percentage: Math.max(0, Math.min(100, flag.percentage ?? 100)),\n      flag,\n    });\n  }\n\n  return failures;\n}\n\nasync function fetchFromAppConfig(): Promise<FailureFlagsConfig> {\n  const appConfigPort = process.env.AWS_APPCONFIG_EXTENSION_HTTP_PORT ?? \"2772\";\n  const application = process.env.FAILURE_APPCONFIG_APPLICATION;\n  const environment = process.env.FAILURE_APPCONFIG_ENVIRONMENT;\n  const configuration = process.env.FAILURE_APPCONFIG_CONFIGURATION;\n\n  const url =\n    `http://localhost:${appConfigPort}` +\n    `/applications/${application}` +\n    `/environments/${environment}` +\n    `/configurations/${configuration}`;\n\n  const response = await fetch(url);\n\n  if (!response.ok) {\n    throw new Error(\n      `AppConfig fetch failed: ${response.status} ${response.statusText}`\n    );\n  }\n\n  const json = (await response.json()) as Record<string, unknown>;\n  return parseFlags(json);\n}\n\nasync function fetchFromSSM(): Promise<FailureFlagsConfig> {\n  const parameterName = process.env.FAILURE_INJECTION_PARAM as string;\n  const client = getSSMClient();\n  const command = new GetParameterCommand({ Name: parameterName });\n  const response = await client.send(command);\n\n  const rawValue = response.Parameter?.Value;\n  if (rawValue === undefined) {\n    throw new Error(`SSM parameter \"${parameterName}\" has no value`);\n  }\n\n  const json = JSON.parse(rawValue) as Record<string, unknown>;\n  return parseFlags(json);\n}\n\n/** Fetch config from AppConfig or SSM, with caching. */\nexport async function getConfig(): Promise<FailureFlagsConfig> {\n  if (isCacheValid() && configCache !== null) {\n    return configCache.config;\n  }\n\n  try {\n    let config: FailureFlagsConfig;\n    let source: string;\n\n    if (process.env.FAILURE_APPCONFIG_CONFIGURATION) {\n      config = await fetchFromAppConfig();\n      source = \"appconfig\";\n    } else if (process.env.FAILURE_INJECTION_PARAM) {\n      config = await fetchFromSSM();\n      source = \"ssm\";\n    } else {\n      return { ...DEFAULT_FLAGS_CONFIG };\n    }\n\n    if (!hasLoggedSource) {\n      const cacheTtlMs = getCacheTtlMs();\n      log({\n        action: \"config\",\n        config_source: source,\n        cache_ttl_seconds: cacheTtlMs / 1000,\n        enabled_flags: Object.keys(config).filter(\n          (k) => (config as Record<string, { enabled?: boolean }>)[k]?.enabled,\n        ),\n      });\n      hasLoggedSource = true;\n    }\n\n    configCache = {\n      config,\n      fetchedAt: Date.now(),\n    };\n\n    return config;\n  } catch (err) {\n    error({ action: \"config\", message: \"error fetching config\", error: String(err) });\n    return { ...DEFAULT_FLAGS_CONFIG };\n  }\n}\n\n/** Clear the config cache. Useful for testing. @internal */\nexport function clearConfigCache(): void {\n  configCache = null;\n  hasLoggedSource = false;\n}\n\n/** Replace the SSM client instance. For testing with mocks. @internal */\nexport function setSSMClient(client: SSMClient): void {\n  ssmClient = client;\n}\n","import type { Context, Callback } from \"aws-lambda\";\n\n/** The supported failure injection modes */\nexport type FailureMode =\n  | \"latency\"\n  | \"exception\"\n  | \"statuscode\"\n  | \"diskspace\"\n  | \"denylist\"\n  | \"timeout\"\n  | \"corruption\";\n\n/**\n * Ordered list of all failure modes.\n * Non-terminating pre-handler first, then terminating, then post-handler (corruption) last.\n */\nexport const FAILURE_MODE_ORDER: readonly FailureMode[] = [\n  \"latency\",\n  \"timeout\",\n  \"diskspace\",\n  \"denylist\",\n  \"statuscode\",\n  \"exception\",\n  \"corruption\",\n];\n\n/** Match operators for event-based targeting */\nexport type MatchOperator = \"eq\" | \"exists\" | \"startsWith\" | \"regex\";\n\n/** Condition for event-based targeting */\nexport interface MatchCondition {\n  /** Dot-separated path into the event object (e.g. \"requestContext.http.method\") */\n  path: string;\n  /** Expected string value at the path. Required for all operators except \"exists\". */\n  value?: string;\n  /** Comparison operator. Defaults to \"eq\". */\n  operator?: MatchOperator;\n}\n\n/** A single feature flag's value */\nexport interface FlagValue {\n  enabled: boolean;\n  /** Percentage of invocations to inject (0 to 100, integer). Defaults to 100. */\n  percentage?: number;\n  /** Minimum latency in ms (latency mode) */\n  min_latency?: number;\n  /** Maximum latency in ms (latency mode) */\n  max_latency?: number;\n  /** Error message to throw (exception mode) */\n  exception_msg?: string;\n  /** HTTP status code to return (statuscode mode) */\n  status_code?: number;\n  /** MB of disk to fill in /tmp (diskspace mode) */\n  disk_space?: number;\n  /** Array of regex patterns for hosts to block (denylist mode) */\n  deny_list?: string[];\n  /** Buffer in ms before Lambda timeout (timeout mode). Default: 0 */\n  timeout_buffer_ms?: number;\n  /** Replacement body string (corruption mode) */\n  body?: string;\n  /** Event-based targeting conditions. All conditions must match for the flag to fire. */\n  match?: MatchCondition[];\n}\n\n/** The full config: a map of failure mode names to their flag values */\nexport type FailureFlagsConfig = Partial<Record<FailureMode, FlagValue>>;\n\n/** A failure resolved and ready to inject */\nexport interface ResolvedFailure {\n  mode: FailureMode;\n  percentage: number;\n  flag: FlagValue;\n}\n\n/** Default: empty config, all modes disabled */\nexport const DEFAULT_FLAGS_CONFIG: FailureFlagsConfig = {};\n\n/**\n * Generic Lambda handler type. Intentionally broad to support any\n * event source (API Gateway, SQS, SNS, EventBridge, etc.).\n */\nexport type LambdaHandler<TEvent = unknown, TResult = unknown> = (\n  event: TEvent,\n  context: Context,\n  callback: Callback<TResult>,\n  // eslint-disable-next-line @typescript-eslint/no-invalid-void-type -- Lambda handlers may return void or Promise\n) => void | Promise<TResult>;\n\n/** Options for the injectFailure wrapper */\nexport interface FailureLambdaOptions {\n  /** Override the config source (useful for testing or custom config backends) */\n  configProvider?: () => Promise<FailureFlagsConfig>;\n  /** Log which failures would fire without actually injecting them */\n  dryRun?: boolean;\n}\n\n/** Internal: cached config entry */\nexport interface CachedConfig {\n  config: FailureFlagsConfig;\n  fetchedAt: number;\n}\n\n/** Validation error detail */\nexport interface ConfigValidationError {\n  field: string;\n  message: string;\n  value: unknown;\n}\n","const SOURCE = \"failure-lambda\";\n\nexport function log(data: Record<string, unknown>): void {\n  console.log(JSON.stringify({ source: SOURCE, level: \"info\", ...data }));\n}\n\nexport function warn(data: Record<string, unknown>): void {\n  console.warn(JSON.stringify({ source: SOURCE, level: \"warn\", ...data }));\n}\n\nexport function error(data: Record<string, unknown>): void {\n  console.error(JSON.stringify({ source: SOURCE, level: \"error\", ...data }));\n}\n","import type { FlagValue } from \"../types.js\";\nimport { log } from \"../log.js\";\n\nexport async function injectLatency(flag: FlagValue): Promise<void> {\n  const minLatency = flag.min_latency ?? 0;\n  const maxLatency = flag.max_latency ?? 0;\n  const latencyRange = Math.max(0, maxLatency - minLatency);\n  const injectedLatency = Math.floor(minLatency + Math.random() * latencyRange);\n\n  log({ mode: \"latency\", action: \"inject\", latency_ms: injectedLatency, min_latency: minLatency, max_latency: maxLatency });\n  await new Promise<void>((resolve) => setTimeout(resolve, injectedLatency));\n}\n","import type { FlagValue } from \"../types.js\";\nimport { log } from \"../log.js\";\n\nexport function injectException(flag: FlagValue): never {\n  const message = flag.exception_msg ?? \"Injected exception\";\n  log({ mode: \"exception\", action: \"inject\", exception_msg: message });\n  throw new Error(message);\n}\n","import type { FlagValue } from \"../types.js\";\nimport { log } from \"../log.js\";\n\nexport interface StatusCodeResponse {\n  statusCode: number;\n  headers: Record<string, string>;\n  body: string;\n}\n\nexport function injectStatusCode(flag: FlagValue): StatusCodeResponse {\n  const statusCode = flag.status_code ?? 500;\n  log({ mode: \"statuscode\", action: \"inject\", status_code: statusCode });\n  return {\n    statusCode,\n    headers: { \"Content-Type\": \"application/json\" },\n    body: JSON.stringify({ message: `Injected status code ${statusCode}` }),\n  };\n}\n","import { spawnSync } from \"node:child_process\";\nimport { readdirSync, unlinkSync } from \"node:fs\";\nimport type { FlagValue } from \"../types.js\";\nimport { log, warn, error } from \"../log.js\";\n\nconst DISKSPACE_PREFIX = \"diskspace-failure-\";\n\n/** Fill /tmp with data using dd. Only works on Linux (Lambda runtime); not available on Windows/macOS. */\nexport function injectDiskSpace(flag: FlagValue): void {\n  const diskSpaceMB = flag.disk_space ?? 100;\n  log({ mode: \"diskspace\", action: \"inject\", disk_space_mb: diskSpaceMB });\n\n  // bs=diskSpaceMB*1024 bytes per block, count=1024 blocks → diskSpaceMB * 1024 * 1024 = exact MB\n  const result = spawnSync(\"dd\", [\n    \"if=/dev/zero\",\n    `of=/tmp/${DISKSPACE_PREFIX}${Date.now()}.tmp`,\n    \"count=1024\",\n    `bs=${diskSpaceMB * 1024}`,\n  ]);\n\n  if (result.error) {\n    error({ mode: \"diskspace\", action: \"error\", message: result.error.message });\n  } else if (result.status !== 0) {\n    const stderr = result.stderr?.toString().trim();\n    error({ mode: \"diskspace\", action: \"error\", message: `dd exited with status ${result.status}`, stderr });\n  }\n}\n\n/** Remove diskspace failure files from /tmp. */\nexport function clearDiskSpace(): void {\n  try {\n    const files = readdirSync(\"/tmp\").filter((f) => f.startsWith(DISKSPACE_PREFIX));\n    for (const file of files) {\n      unlinkSync(`/tmp/${file}`);\n    }\n    if (files.length > 0) {\n      log({ mode: \"diskspace\", action: \"clear\", files_removed: files.length });\n    }\n  } catch (e) {\n    warn({ mode: \"diskspace\", action: \"clear_error\", message: (e as Error).message });\n  }\n}\n","import dns from \"node:dns\";\nimport type { FlagValue } from \"../types.js\";\nimport { log, warn } from \"../log.js\";\n\n/** Capture the original dns.lookup once at module load (once per Lambda cold start) */\nconst originalLookup = dns.lookup;\n\n/** Whether our wrapper is currently installed on dns.lookup */\nlet isActive = false;\n\n/** Current compiled regex patterns (replaced on each injectDenylist call) */\nlet activePatterns: RegExp[] = [];\n\n/** Restore dns.lookup and clear denylist patterns */\nexport function clearDenylist(): void {\n  if (isActive) {\n    dns.lookup = originalLookup;\n    isActive = false;\n    activePatterns = [];\n  }\n}\n\nexport function injectDenylist(flag: FlagValue): void {\n  const denylistPatterns = flag.deny_list ?? [];\n  log({ mode: \"denylist\", action: \"inject\", patterns: denylistPatterns });\n\n  activePatterns = [];\n  for (const pattern of denylistPatterns) {\n    try {\n      activePatterns.push(new RegExp(pattern));\n    } catch (e) {\n      warn({ mode: \"denylist\", action: \"error\", message: `invalid regex \"${pattern}\"`, error: (e as Error).message });\n    }\n  }\n\n  if (!isActive) {\n    // dns.lookup has multiple overloads: (hostname, cb), (hostname, options, cb).\n    // The options.all flag changes the callback signature to return an array,\n    // but we extract the callback generically as the last arg and pass through\n    // to the original for non-blocked hosts. AWS SDK calls don't use all: true.\n    dns.lookup = function blockedLookup(\n      hostname: string,\n      ...args: unknown[]\n    ): void {\n      const callback = args[args.length - 1] as (\n        err: NodeJS.ErrnoException | null,\n        address?: string,\n        family?: number,\n      ) => void;\n      const rest = args.slice(0, -1);\n\n      if (activePatterns.some((regex) => regex.test(hostname))) {\n        log({ mode: \"denylist\", action: \"block\", hostname });\n        const err = new Error(\n          `getaddrinfo ENOTFOUND ${hostname}`,\n        ) as NodeJS.ErrnoException & { hostname?: string };\n        err.code = \"ENOTFOUND\";\n        err.hostname = hostname;\n        err.syscall = \"getaddrinfo\";\n        process.nextTick(() => callback(err));\n        return;\n      }\n\n      (originalLookup as (...args: unknown[]) => void).call(dns, hostname, ...rest, callback);\n    } as typeof dns.lookup;\n\n    isActive = true;\n  }\n}\n\n/** Reset denylist state entirely. For testing. @internal */\nexport function resetDenylist(): void {\n  dns.lookup = originalLookup;\n  isActive = false;\n  activePatterns = [];\n}\n","import type { Context } from \"aws-lambda\";\nimport type { FlagValue } from \"../types.js\";\nimport { log } from \"../log.js\";\n\nexport async function injectTimeout(flag: FlagValue, context: Context): Promise<void> {\n  const bufferMs = flag.timeout_buffer_ms ?? 0;\n  const remaining = context.getRemainingTimeInMillis();\n  const sleepMs = Math.max(0, remaining - bufferMs);\n\n  log({ mode: \"timeout\", action: \"inject\", sleep_ms: sleepMs, buffer_ms: bufferMs, remaining_ms: remaining });\n  await new Promise<void>((resolve) => setTimeout(resolve, sleepMs));\n}\n","import type { FlagValue } from \"../types.js\";\nimport { log, warn } from \"../log.js\";\n\nexport function corruptResponse(flag: FlagValue, result: unknown): unknown {\n  if (flag.body !== undefined) {\n    log({ mode: \"corruption\", action: \"inject\", method: \"replace\" });\n    if (typeof result === \"object\" && result !== null && \"body\" in result) {\n      return { ...result, body: flag.body };\n    }\n    warn({ mode: \"corruption\", message: \"response has no body field; wrapping in { body }\" });\n    return { body: flag.body };\n  }\n\n  log({ mode: \"corruption\", action: \"inject\", method: \"mangle\" });\n  if (typeof result === \"object\" && result !== null && \"body\" in result) {\n    const obj = result as Record<string, unknown>;\n    if (typeof obj.body === \"string\") {\n      return { ...obj, body: mangleString(obj.body) };\n    }\n  }\n\n  warn({ mode: \"corruption\", message: \"response has no string body field to mangle; returning unchanged\" });\n  return result;\n}\n\nfunction mangleString(input: string): string {\n  if (input.length === 0) return input;\n  const truncatePoint = Math.floor(input.length * (0.3 + Math.random() * 0.5));\n  return input.slice(0, truncatePoint) + \"\\uFFFD\".repeat(3);\n}\n","import type { MatchCondition, MatchOperator } from \"./types.js\";\n\n/** Cache compiled regexes to avoid recompiling on every invocation */\nconst regexCache = new Map<string, RegExp>();\n\nfunction getCachedRegex(pattern: string): RegExp {\n  let cached = regexCache.get(pattern);\n  if (cached === undefined) {\n    cached = new RegExp(pattern);\n    regexCache.set(pattern, cached);\n  }\n  return cached;\n}\n\n/** Resolve a dot-separated path against a nested object */\nexport function getNestedValue(obj: unknown, path: string): unknown {\n  let current = obj;\n  for (const part of path.split(\".\")) {\n    if (current === null || current === undefined || typeof current !== \"object\") return undefined;\n    current = (current as Record<string, unknown>)[part];\n  }\n  return current;\n}\n\n/** Evaluate a single match operator against an actual value */\nfunction matchOperator(actual: unknown, operator: MatchOperator, value?: string): boolean {\n  switch (operator) {\n    case \"exists\":\n      return actual !== null && actual !== undefined;\n    case \"startsWith\":\n      if (actual === null || actual === undefined) return false;\n      return String(actual).startsWith(value ?? \"\");\n    case \"regex\":\n      if (actual === null || actual === undefined) return false;\n      return getCachedRegex(value ?? \"\").test(String(actual));\n    case \"eq\":\n    default:\n      if (actual === null || actual === undefined) return false;\n      return String(actual) === value;\n  }\n}\n\n/** Check whether all match conditions are satisfied by the event */\nexport function matchesConditions(event: unknown, conditions: MatchCondition[]): boolean {\n  return conditions.every((condition) => {\n    const actual = getNestedValue(event, condition.path);\n    const operator = condition.operator ?? \"eq\";\n    return matchOperator(actual, operator, condition.value);\n  });\n}\n","import type { Context } from \"aws-lambda\";\nimport type { ResolvedFailure } from \"./types.js\";\nimport {\n  injectLatency,\n  injectException,\n  injectStatusCode,\n  injectDiskSpace,\n  clearDiskSpace,\n  injectDenylist,\n  clearDenylist,\n  injectTimeout,\n  corruptResponse,\n} from \"./failures/index.js\";\nimport { matchesConditions } from \"./matching.js\";\nimport { log } from \"./log.js\";\n\nexport interface ShortCircuitResult<TResult = unknown> {\n  shortCircuit: TResult;\n}\n\n/**\n * Run pre-handler failure injections.\n *\n * Returns `{ shortCircuit }` if a terminating mode (statuscode/exception) fires,\n * or `undefined` if the handler should proceed normally.\n */\nexport async function runPreHandlerInjections<TEvent = unknown, TResult = unknown>(\n  failures: ResolvedFailure[],\n  event: TEvent,\n  context: Context,\n  dryRun = false,\n): Promise<ShortCircuitResult<TResult> | undefined> {\n  // Always clear previous invocation's side effects before re-evaluating.\n  // Without this, a denylist/diskspace injection from a prior invocation persists\n  // even when the percentage check fails on the current invocation.\n  if (!dryRun) {\n    clearDenylist();\n    clearDiskSpace();\n  }\n\n  for (const failure of failures) {\n    if (failure.mode === \"corruption\") continue;\n    if (failure.flag.match && !matchesConditions(event, failure.flag.match)) continue;\n    const roll = Math.random() * 100;\n    if (roll >= failure.percentage) continue;\n\n    if (dryRun) {\n      log({ mode: failure.mode, action: \"dryrun\", percentage: failure.percentage, roll });\n      continue;\n    }\n\n    switch (failure.mode) {\n      case \"latency\":\n        await injectLatency(failure.flag);\n        break;\n      case \"timeout\":\n        await injectTimeout(failure.flag, context);\n        break;\n      case \"diskspace\":\n        injectDiskSpace(failure.flag);\n        break;\n      case \"denylist\":\n        injectDenylist(failure.flag);\n        break;\n      case \"statuscode\":\n        return { shortCircuit: injectStatusCode(failure.flag) as unknown as TResult };\n      case \"exception\":\n        injectException(failure.flag);\n    }\n  }\n\n  return undefined;\n}\n\n/**\n * Run post-handler failure injections (corruption).\n *\n * Returns the (potentially modified) result.\n */\nexport function runPostHandlerInjections<TEvent = unknown, TResult = unknown>(\n  failures: ResolvedFailure[],\n  event: TEvent,\n  result: TResult,\n  dryRun = false,\n): TResult {\n  let current: unknown = result;\n\n  for (const failure of failures) {\n    if (failure.mode !== \"corruption\") continue;\n    if (failure.flag.match && !matchesConditions(event, failure.flag.match)) continue;\n    const roll = Math.random() * 100;\n    if (roll >= failure.percentage) continue;\n\n    if (dryRun) {\n      log({ mode: failure.mode, action: \"dryrun\", percentage: failure.percentage, roll });\n      continue;\n    }\n\n    current = corruptResponse(failure.flag, current);\n  }\n\n  return current as TResult;\n}\n"],"mappings":"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","names":["dns"]}