{"version":3,"sources":["../src/pulse-token.ts","../src/types.ts","../src/client.ts","../src/config.ts","../src/parsers/consistency.ts","../src/parsers/npm.ts","../src/parsers/node_modules.ts","../src/parsers/pnpm.ts","../src/parsers/yarn.ts","../src/parsers/index.ts","../src/normalize.ts","../src/protect/refresh-manifest.ts","../src/protect/runtime.js","../src/protect/safe-origin.js","../src/protect/engine/client.js","../src/protect/engine/request.js","../src/protect/engine/normalizer.js","../src/protect/engine/engine.js","../src/protect/engine/pulse-client.js","../src/protect/engine/fetch.js","../src/protect/engine/node.js","../src/protect/egress.js","../src/protect/defaults.js","../src/protect/block-page.js","../src/protect/rules/store.js","../src/protect/rules/validate.js","../src/protect/rules/source.js","../src/protect/rules/refresh.js","../src/protect/firewall-log.js","../src/protect/supabase-guard.js"],"sourcesContent":["import type { Config } from './types.js';\n\n/**\n * Bearer tokens for the authenticated Pulse endpoints (ADR-0018).\n *\n * Deliberately separate from the block-log token flow in\n * `src/protect/firewall-log.js`: that path talks to the auth/ Lambda's\n * /oauth/token and must keep working exactly as it does today.\n */\n\nconst TOKEN_SKEW_MS = 60_000;\n\n/** Build the Pulse token URL corresponding to a manifest endpoint override. */\nexport function buildTokenUrl(manifestEndpoint: string): string {\n  const url = new URL(manifestEndpoint);\n  const path = url.pathname.replace(/\\/$/, '');\n  url.pathname = path.endsWith('/manifest')\n    ? `${path.slice(0, -'/manifest'.length)}/token`\n    : '/monitor/pulse/token';\n  url.search = '';\n  url.hash = '';\n  return url.toString();\n}\n\n/** Split the WP-format `{secret}-{oauth.id}` credential on its last hyphen. */\nexport function parsePulseAuth(credential: string): { clientId: string; clientSecret: string } | null {\n  const index = credential.lastIndexOf('-');\n  if (index <= 0 || index === credential.length - 1) return null;\n\n  const clientId = credential.slice(index + 1);\n  if (!/^\\d+$/.test(clientId)) return null;\n\n  return { clientId, clientSecret: credential.slice(0, index) };\n}\n\nlet cached: { token: string; expiresAt: number } | null = null;\nlet inflight: Promise<string | null> | null = null;\n\n/** Drops the cached token. Exported for tests and for 401 handling. */\nexport function clearPulseToken(): void {\n  cached = null;\n}\n\n/**\n * Resolve a bearer token for `config.pulseAuth`, exchanging one if needed.\n *\n * Returns null whenever a token cannot be obtained — no credential, a rejected\n * exchange, a network failure. Callers then send the request unauthenticated,\n * which the server still accepts while it runs dual-accept.\n */\nexport async function getPulseToken(\n  config: Config,\n  fetchImpl: typeof fetch = fetch,\n): Promise<string | null> {\n  // Not `=== null`: Config is public, so callers can hand us an object that\n  // predates this field, and an unusable credential must never throw here.\n  if (typeof config.pulseAuth !== 'string' || config.pulseAuth.length === 0) return null;\n\n  if (cached !== null && Date.now() < cached.expiresAt - TOKEN_SKEW_MS) {\n    return cached.token;\n  }\n  if (inflight !== null) return inflight;\n\n  const credentials = parsePulseAuth(config.pulseAuth);\n  if (credentials === null) return null;\n\n  inflight = (async () => {\n    try {\n      const response = await fetchImpl(buildTokenUrl(config.endpoint), {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n          Accept: 'application/json',\n          'User-Agent': '@patchstack/connect',\n        },\n        body: JSON.stringify({\n          grant_type: 'client_credentials',\n          client_id: credentials.clientId,\n          client_secret: credentials.clientSecret,\n        }),\n        signal: AbortSignal.timeout(config.timeoutMs),\n      });\n\n      if (!response.ok) return null;\n\n      const body = (await response.json()) as { access_token?: unknown; expires_in?: unknown };\n      if (typeof body.access_token !== 'string' || body.access_token.length === 0) return null;\n\n      const expiresIn = Number(body.expires_in);\n      const ttlMs = Number.isFinite(expiresIn) && expiresIn > 0 ? expiresIn * 1000 : 3600_000;\n      cached = { token: body.access_token, expiresAt: Date.now() + ttlMs };\n\n      return body.access_token;\n    } catch {\n      return null;\n    } finally {\n      inflight = null;\n    }\n  })();\n\n  return inflight;\n}\n\n/**\n * `Authorization` header for a Pulse request, or `{}` when unauthenticated.\n * Spread into an existing header object so call sites stay one line.\n */\nexport async function pulseAuthHeader(\n  config: Config,\n  fetchImpl: typeof fetch = fetch,\n): Promise<Record<string, string>> {\n  const token = await getPulseToken(config, fetchImpl);\n  return token === null ? {} : { Authorization: `Bearer ${token}` };\n}\n\n/**\n * Send a Pulse request, attaching the bearer token and retrying once if the\n * server rejects it.\n *\n * A cached token can stop being valid before it expires — the credential may\n * have been rotated or revoked meanwhile — so the server's 401 is authoritative\n * over our own clock. Without this a long-running process would keep presenting\n * a dead token until its local expiry.\n *\n * Only 401 retries: a 403 is a scope or site mismatch, which a fresh token\n * would not fix.\n */\nexport async function pulseFetch(\n  config: Config,\n  url: string,\n  init: RequestInit,\n  fetchImpl: typeof fetch = fetch,\n): Promise<Response> {\n  const send = async () => {\n    const auth = await pulseAuthHeader(config, fetchImpl);\n    const response = await fetchImpl(url, {\n      ...init,\n      headers: { ...(init.headers as Record<string, string> | undefined), ...auth },\n    });\n\n    return { response, authenticated: auth.Authorization !== undefined };\n  };\n\n  const first = await send();\n\n  // Retrying an unauthenticated request would just repeat it: the 401 was\n  // about something other than our token.\n  if (first.response.status === 401 && first.authenticated) {\n    clearPulseToken();\n\n    return (await send()).response;\n  }\n\n  return first.response;\n}\n","export type Ecosystem = 'npm' | 'composer';\n\n/**\n * Which environment a manifest was captured in. The connector reports from real\n * builds (prebuild scan / build hooks), so it defaults to 'production'. Override\n * with PATCHSTACK_ENVIRONMENT=sandbox (or \"environment\" in .patchstackrc.json)\n * for test manifests.\n */\nexport type Environment = 'production' | 'sandbox';\n\nexport interface PackageEntry {\n  name: string;\n  version: string;\n  path?: string;\n  direct?: boolean;\n}\n\nexport interface Manifest {\n  ecosystem: Ecosystem;\n  packages: PackageEntry[];\n  /**\n   * Human-readable scan diagnostics — set when the preferred lockfile looked\n   * stale (missing dependencies declared in package.json) and another source\n   * was used, or when no fully-consistent source existed. Never fatal.\n   */\n  warnings?: string[];\n}\n\nexport interface Config {\n  /**\n   * The site UUID. `null` means we don't have one yet — `postManifest` will then\n   * post to the bare endpoint, the server will provision a fresh site, and the\n   * UUID it returns should be persisted via `persistSiteUuid()`.\n   */\n  siteUuid: string | null;\n  /**\n   * WP-format site API key (`{oauth.secret}-{oauth.id}`) for authenticated\n   * block-log reporting via connector `/api/logs/log`. Issued once as `api_key`\n   * on first provision. Prefer `PATCHSTACK_API_KEY` in production deploys.\n   */\n  apiKey: string | null;\n  /**\n   * Credential for the authenticated Pulse endpoints (ADR-0018). Exchanged for\n   * a short-lived bearer token at `monitor/pulse/token`; never sent directly.\n   * Falls back to `apiKey` when unset. Prefer `PATCHSTACK_PULSE_AUTH`.\n   */\n  pulseAuth: string | null;\n  endpoint: string;\n  timeoutMs: number;\n  /** Environment to report the manifest under. Defaults to 'production'. */\n  environment: Environment;\n  /**\n   * Whether the connector manages the disclosure-widget tag (source shell on\n   * `scan`, built HTML on `mark-build`). Defaults to true; persist\n   * `\"widget\": false` in .patchstackrc.json for dependency-scanning only.\n   */\n  widget: boolean;\n}\n\nexport interface StoreManifestResponse {\n  /** The UUID of the site the manifest was stored against. Always returned. */\n  uuid?: string;\n  /**\n   * WP-format API key for connector log ingest. Present only when oauth\n   * credentials are created in this request (first provision / backfill).\n   */\n  api_key?: string;\n  stored: boolean;\n  manifest_id?: number;\n  checksum?: string;\n  reason?: string;\n  message?: string;\n  error?: string;\n}\n\nexport class PatchstackError extends Error {\n  constructor(\n    message: string,\n    public readonly code:\n      | 'CONFIG_MISSING'\n      | 'CONFIG_INVALID'\n      | 'LOCKFILE_NOT_FOUND'\n      | 'LOCKFILE_UNSUPPORTED'\n      | 'LOCKFILE_PARSE_ERROR'\n      | 'NETWORK_ERROR'\n      | 'NETWORK_TIMEOUT'\n      | 'SITE_NOT_FOUND'\n      | 'VALIDATION_ERROR'\n      | 'SERVER_ERROR',\n    public readonly cause?: unknown,\n  ) {\n    super(message);\n    this.name = 'PatchstackError';\n  }\n}\n","import { PatchstackError, type Config, type StoreManifestResponse } from './types.js';\nimport type { WirePayload } from './normalize.js';\nimport { pulseFetch } from './pulse-token.js';\n\nexport const DEFAULT_ENDPOINT = 'https://api.patchstack.com/monitor/pulse/manifest';\nexport const DEFAULT_TIMEOUT_MS = 30_000;\n\nexport function buildEndpointUrl(base: string, siteUuid?: string | null): string {\n  const trimmed = base.replace(/\\/$/, '');\n  return siteUuid !== undefined && siteUuid !== null && siteUuid.length > 0\n    ? `${trimmed}/${encodeURIComponent(siteUuid)}`\n    : trimmed;\n}\n\n/** Build the live Pulse rules URL corresponding to a manifest endpoint override. */\nexport function buildRulesUrl(manifestEndpoint: string, siteUuid: string): string {\n  const url = new URL(manifestEndpoint);\n  const path = url.pathname.replace(/\\/$/, '');\n  url.pathname = path.endsWith('/manifest')\n    ? `${path.slice(0, -'/manifest'.length)}/rules/${encodeURIComponent(siteUuid)}`\n    : `/monitor/pulse/rules/${encodeURIComponent(siteUuid)}`;\n  url.search = '';\n  url.hash = '';\n  return url.toString();\n}\n\n/**\n * Build the claim URL for a site. The claim page lives on the same origin as\n * the API endpoint, at `/monitor/claim?site=<uuid>`. Using the API endpoint's\n * origin (rather than a hard-coded https://api.patchstack.com) means staging,\n * ngrok tunnels and local dev environments all produce a claim URL on the same\n * host the connector is already talking to.\n */\nexport function buildClaimUrl(endpoint: string, siteUuid: string): string {\n  const origin = new URL(endpoint).origin;\n  return `${origin}/monitor/claim?site=${encodeURIComponent(siteUuid)}`;\n}\n\n/**\n * Build the public widget-settings URL for a site. Like the claim URL, it\n * lives on the API endpoint's origin, at `/monitor/widget/settings/<uuid>`.\n */\nexport function buildSettingsUrl(endpoint: string, siteUuid: string): string {\n  const origin = new URL(endpoint).origin;\n  return `${origin}/monitor/widget/settings/${encodeURIComponent(siteUuid)}`;\n}\n\n/** Build the package-removed signal URL corresponding to a manifest endpoint override. */\nexport function buildPackageRemovedUrl(manifestEndpoint: string, siteUuid: string): string {\n  const url = new URL(manifestEndpoint);\n  const path = url.pathname.replace(/\\/$/, '');\n  url.pathname = path.endsWith('/manifest')\n    ? `${path.slice(0, -'/manifest'.length)}/package-removed/${encodeURIComponent(siteUuid)}`\n    : `/monitor/pulse/package-removed/${encodeURIComponent(siteUuid)}`;\n  url.search = '';\n  url.hash = '';\n  return url.toString();\n}\n\n/** Build the input-map ingest URL corresponding to a manifest endpoint override. */\nexport function buildInputMapUrl(manifestEndpoint: string, siteUuid: string): string {\n  const url = new URL(manifestEndpoint);\n  const path = url.pathname.replace(/\\/$/, '');\n  url.pathname = path.endsWith('/manifest')\n    ? `${path.slice(0, -'/manifest'.length)}/input-map/${encodeURIComponent(siteUuid)}`\n    : `/monitor/pulse/input-map/${encodeURIComponent(siteUuid)}`;\n  url.search = '';\n  url.hash = '';\n  return url.toString();\n}\n\n/**\n * Outcome of uploading an attack-surface map. `unchanged` is a first-class result, not a failure: most\n * builds do not change the surface, and the server keeps one revision per distinct surface rather than\n * one per deploy. `skipped` covers the cases where there is nothing to send or nowhere to send it.\n */\nexport type InputMapUploadOutcome =\n  | { result: 'stored'; revision: number }\n  | { result: 'unchanged'; revision: number }\n  | { result: 'skipped'; message: string }\n  | { result: 'failed'; message: string };\n\n/**\n * Upload an attack-surface map for this site.\n *\n * Fail-open by construction: every failure path returns a result rather than throwing, because this runs\n * during someone's build and a Patchstack outage must never break it. The caller decides what to print.\n */\nexport async function postInputMap(\n  config: Config,\n  map: { version: number; endpoints: unknown[] },\n): Promise<InputMapUploadOutcome> {\n  if (config.siteUuid === null) {\n    return { result: 'skipped', message: 'No site UUID configured — run `patchstack-connect scan` first.' };\n  }\n\n  const url = buildInputMapUrl(config.endpoint, config.siteUuid);\n  try {\n    const response = await pulseFetch(config, url, {\n      method: 'POST',\n      headers: {\n        Accept: 'application/json',\n        'Content-Type': 'application/json',\n        'User-Agent': '@patchstack/connect',\n      },\n      body: JSON.stringify(map),\n      signal: AbortSignal.timeout(config.timeoutMs),\n    });\n    if (response.status === 404) {\n      return { result: 'failed', message: 'Site not found — the configured site UUID is unknown to Patchstack.' };\n    }\n    if (response.status === 422) {\n      // The server implements a different map schema than this client emits. Say so plainly: it means\n      // one side is out of date, and guessing at compatibility is how a consumer misreads a document.\n      return { result: 'failed', message: `Patchstack does not accept this map schema (version ${map.version}). Update @patchstack/connect.` };\n    }\n    if (!response.ok) {\n      return { result: 'failed', message: `Patchstack returned ${response.status}.` };\n    }\n    const body = (await response.json()) as { result?: string; revision?: number };\n    // The revision is part of the contract, not decoration: \"stored, revision 0\" is not a state the server\n    // can be in, so accepting it would report a successful upload that cannot be pointed at afterwards.\n    const revision = Number(body.revision);\n    if ((body.result === 'stored' || body.result === 'unchanged') && Number.isInteger(revision) && revision > 0) {\n      return { result: body.result, revision };\n    }\n    return { result: 'failed', message: 'Patchstack returned an unexpected response.' };\n  } catch {\n    return { result: 'failed', message: `Could not reach Patchstack at ${url}.` };\n  }\n}\n\n/**\n * Outcome of the package-removed signal. 'deleted' — the site was unclaimed\n * and its record was removed; 'flagged' — the site is claimed, so it was only\n * marked for its owner to confirm removal in the dashboard; 'gone' — the\n * record no longer existed; 'failed' — Patchstack could not be reached or\n * returned an unexpected response.\n */\nexport interface PackageRemovedOutcome {\n  result: 'deleted' | 'flagged' | 'gone' | 'failed';\n  message: string | null;\n}\n\n/**\n * Tell Patchstack the @patchstack/connect package is being uninstalled from\n * this project. The site UUID is the only credential, so the server deletes\n * only unclaimed (anonymous) sites; claimed sites are merely flagged for\n * their owner. Never throws — an unreachable server must not block the local\n * uninstall.\n */\nexport async function postPackageRemoved(config: Config): Promise<PackageRemovedOutcome> {\n  if (config.siteUuid === null) {\n    return { result: 'failed', message: 'No site UUID configured.' };\n  }\n\n  const url = buildPackageRemovedUrl(config.endpoint, config.siteUuid);\n  try {\n    const response = await pulseFetch(config, url, {\n      method: 'POST',\n      headers: {\n        Accept: 'application/json',\n        'User-Agent': '@patchstack/connect',\n      },\n      signal: AbortSignal.timeout(config.timeoutMs),\n    });\n    if (response.status === 404) {\n      return { result: 'gone', message: null };\n    }\n    if (!response.ok) {\n      return { result: 'failed', message: `Patchstack returned ${response.status}.` };\n    }\n    const body = (await response.json()) as { status?: string; message?: string };\n    if (body.status === 'deleted' || body.status === 'flagged') {\n      return { result: body.status, message: body.message ?? null };\n    }\n    return { result: 'failed', message: 'Patchstack returned an unexpected response.' };\n  } catch {\n    return { result: 'failed', message: `Could not reach Patchstack at ${url}.` };\n  }\n}\n\n/**\n * Whether the site record still exists on Patchstack's side. Removing a site\n * (dashboard delete or the widget's uninstall flow) only deletes the remote\n * record — the local integration files stay in the project — so this is the\n * signal that distinguishes \"removed from Patchstack\" from \"still active\".\n */\nexport type SiteStatus = 'active' | 'removed' | 'unknown';\n\n/**\n * Check the remote site status via the public widget-settings endpoint:\n * 200 means the site record exists, 404 means it was removed. Any other\n * response or a network failure is 'unknown' — never throws. The endpoint's\n * 200 responses are cacheable for an hour, so a cache-busting query param\n * keeps intermediaries from reporting a just-removed site as active.\n */\nexport async function fetchSiteStatus(config: Config): Promise<SiteStatus> {\n  if (config.siteUuid === null) return 'unknown';\n\n  const url = new URL(buildSettingsUrl(config.endpoint, config.siteUuid));\n  url.searchParams.set('t', Date.now().toString());\n\n  try {\n    const response = await fetch(url.toString(), {\n      method: 'GET',\n      headers: {\n        Accept: 'application/json',\n        'Cache-Control': 'no-cache',\n        'User-Agent': '@patchstack/connect',\n      },\n      signal: AbortSignal.timeout(config.timeoutMs),\n    });\n    if (response.status === 404) return 'removed';\n    if (response.ok) return 'active';\n    return 'unknown';\n  } catch {\n    return 'unknown';\n  }\n}\n\nexport async function postManifest(\n  config: Config,\n  payload: WirePayload,\n): Promise<StoreManifestResponse> {\n  const url = buildEndpointUrl(config.endpoint, config.siteUuid);\n  const timeoutMs = config.timeoutMs;\n\n  let response: Response;\n  try {\n    // Unauthenticated on the bootstrap POST: there is no credential until this\n    // request issues one.\n    response = await pulseFetch(config, url, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        Accept: 'application/json',\n        'User-Agent': '@patchstack/connect',\n      },\n      body: JSON.stringify({ ...payload, environment: config.environment }),\n      signal: AbortSignal.timeout(timeoutMs),\n    });\n  } catch (cause) {\n    if (isTimeoutError(cause)) {\n      throw new PatchstackError(\n        `Patchstack request to ${url} timed out after ${timeoutMs}ms. Override with PATCHSTACK_TIMEOUT_MS.`,\n        'NETWORK_TIMEOUT',\n        cause,\n      );\n    }\n    throw new PatchstackError(\n      `Could not reach Patchstack at ${url}. Check your network connection.`,\n      'NETWORK_ERROR',\n      cause,\n    );\n  }\n\n  const text = await response.text();\n  let body: StoreManifestResponse | null = null;\n  try {\n    body = text.length > 0 ? (JSON.parse(text) as StoreManifestResponse) : null;\n  } catch {\n    body = null;\n  }\n\n  if (response.status === 404) {\n    throw new PatchstackError(\n      body?.error ?? 'Site not found. Check that your site UUID is correct and that the app is registered as a Pulse app in your Patchstack dashboard.',\n      'SITE_NOT_FOUND',\n    );\n  }\n\n  if (response.status === 422) {\n    throw new PatchstackError(\n      body?.message ?? 'Patchstack rejected the manifest payload (validation failed).',\n      'VALIDATION_ERROR',\n    );\n  }\n\n  if (response.status < 200 || response.status >= 300) {\n    throw new PatchstackError(\n      `Patchstack returned ${response.status}: ${text.slice(0, 200)}`,\n      'SERVER_ERROR',\n    );\n  }\n\n  if (body === null) {\n    throw new PatchstackError('Patchstack returned an empty response.', 'SERVER_ERROR');\n  }\n\n  return body;\n}\n\nfunction isTimeoutError(cause: unknown): boolean {\n  if (cause instanceof Error) {\n    return cause.name === 'TimeoutError' || cause.name === 'AbortError';\n  }\n  return false;\n}\n","import { readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { PatchstackError, type Config, type Environment } from './types.js';\nimport { DEFAULT_ENDPOINT, DEFAULT_TIMEOUT_MS } from './client.js';\n\nconst CONFIG_FILENAME = '.patchstackrc.json';\n\nexport const DEFAULT_ENVIRONMENT: Environment = 'production';\n\ninterface ConfigFile {\n  siteUuid?: string;\n  /** WP-format `{secret}-{oauth.id}` for connector /api/logs/log. Server-only. */\n  apiKey?: string;\n  /**\n   * Credential for the authenticated Pulse endpoints (ADR-0018). Same format as\n   * `apiKey` and today the same value, but kept as its own field so the Pulse\n   * and block-log paths can diverge without disturbing each other. Server-only.\n   */\n  pulseAuth?: string;\n  endpoint?: string;\n  timeoutMs?: number;\n  environment?: string;\n  widget?: boolean;\n}\n\nexport interface ResolveConfigOptions {\n  cwd: string;\n  cliSiteUuid?: string;\n  cliEndpoint?: string;\n  /**\n   * When true, resolveConfig throws CONFIG_MISSING if no site UUID is configured.\n   * Defaults to false: callers that can run without a UUID (the first `scan` after\n   * `npm install`) just get `siteUuid: null` back and learn the UUID from the\n   * server response.\n   */\n  requireSiteUuid?: boolean;\n}\n\nexport async function resolveConfig(options: ResolveConfigOptions): Promise<Config> {\n  const fromFile = await readConfigFile(options.cwd);\n  const fromEnv = readEnv();\n\n  const siteUuid =\n    options.cliSiteUuid ??\n    fromEnv.siteUuid ??\n    fromFile.siteUuid ??\n    null;\n\n  const endpoint =\n    options.cliEndpoint ??\n    fromEnv.endpoint ??\n    fromFile.endpoint ??\n    DEFAULT_ENDPOINT;\n\n  const timeoutMs = fromEnv.timeoutMs ?? fromFile.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n  const environmentRaw = fromEnv.environment ?? fromFile.environment;\n  if (environmentRaw !== undefined && !isEnvironment(environmentRaw)) {\n    throw new PatchstackError(\n      `Environment must be \"production\" or \"sandbox\"; got \"${environmentRaw}\".`,\n      'CONFIG_INVALID',\n    );\n  }\n  const environment: Environment = environmentRaw ?? DEFAULT_ENVIRONMENT;\n\n  if (siteUuid !== null && siteUuid.length > 0 && !isUuid(siteUuid)) {\n    throw new PatchstackError(\n      `Site UUID \"${siteUuid}\" does not look like a valid UUID.`,\n      'CONFIG_INVALID',\n    );\n  }\n\n  if (options.requireSiteUuid && (siteUuid === null || siteUuid.length === 0)) {\n    throw new PatchstackError(\n      'No site UUID configured. Run `patchstack-connect scan` to provision one, or set PATCHSTACK_SITE_UUID.',\n      'CONFIG_MISSING',\n    );\n  }\n\n  const apiKeyRaw = fromEnv.apiKey ?? fromFile.apiKey ?? null;\n  // Falls back to apiKey so sites provisioned before ADR-0018 authenticate\n  // without re-provisioning: today both hold the same credential.\n  const pulseAuthRaw = fromEnv.pulseAuth ?? fromFile.pulseAuth ?? apiKeyRaw;\n\n  return {\n    siteUuid: siteUuid === null || siteUuid.length === 0 ? null : siteUuid,\n    apiKey: apiKeyRaw === null || apiKeyRaw.length === 0 ? null : apiKeyRaw,\n    pulseAuth: pulseAuthRaw === null || pulseAuthRaw.length === 0 ? null : pulseAuthRaw,\n    endpoint,\n    timeoutMs,\n    environment,\n    widget: fromFile.widget !== false,\n  };\n}\n\nexport async function writeConfigFile(cwd: string, config: ConfigFile): Promise<string> {\n  const target = path.join(cwd, CONFIG_FILENAME);\n  const content = JSON.stringify(config, null, 2) + '\\n';\n  await writeFile(target, content, 'utf8');\n  return target;\n}\n\n/**\n * Merge a new siteUuid into the existing `.patchstackrc.json` (or create it).\n * Preserves any `endpoint` / `timeoutMs` / `apiKey` the user already wrote.\n */\nexport async function persistSiteUuid(cwd: string, siteUuid: string): Promise<string> {\n  const existing = await readConfigFile(cwd);\n  return writeConfigFile(cwd, { ...existing, siteUuid });\n}\n\n/**\n * Persist the WP-format api_key issued at provision (for connector log auth).\n * Never embed this value in the public disclosure widget.\n */\nexport async function persistApiKey(cwd: string, apiKey: string): Promise<string> {\n  const existing = await readConfigFile(cwd);\n  return writeConfigFile(cwd, { ...existing, apiKey });\n}\n\n/**\n * Persist the credential used for the authenticated Pulse endpoints.\n * Kept separate from `apiKey` so block-log auth is never disturbed.\n */\nexport async function persistPulseAuth(cwd: string, pulseAuth: string): Promise<string> {\n  const existing = await readConfigFile(cwd);\n  return writeConfigFile(cwd, { ...existing, pulseAuth });\n}\n\nasync function readConfigFile(cwd: string): Promise<ConfigFile> {\n  const target = path.join(cwd, CONFIG_FILENAME);\n  let raw: string;\n  try {\n    raw = await readFile(target, 'utf8');\n  } catch (err) {\n    if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n      return {};\n    }\n    throw new PatchstackError(\n      `Could not read ${target}: ${(err as Error).message}`,\n      'CONFIG_INVALID',\n      err,\n    );\n  }\n\n  try {\n    return JSON.parse(raw) as ConfigFile;\n  } catch (err) {\n    throw new PatchstackError(\n      `Config file ${target} contains invalid JSON.`,\n      'CONFIG_INVALID',\n      err,\n    );\n  }\n}\n\nfunction readEnv(): ConfigFile {\n  const timeoutRaw = process.env.PATCHSTACK_TIMEOUT_MS;\n  let timeoutMs: number | undefined;\n  if (timeoutRaw !== undefined && timeoutRaw.length > 0) {\n    const parsed = Number(timeoutRaw);\n    if (!Number.isFinite(parsed) || parsed <= 0) {\n      throw new PatchstackError(\n        `PATCHSTACK_TIMEOUT_MS must be a positive number; got \"${timeoutRaw}\".`,\n        'CONFIG_INVALID',\n      );\n    }\n    timeoutMs = parsed;\n  }\n  const environmentRaw = process.env.PATCHSTACK_ENVIRONMENT;\n  return {\n    siteUuid: process.env.PATCHSTACK_SITE_UUID ?? undefined,\n    apiKey: process.env.PATCHSTACK_API_KEY ?? undefined,\n    pulseAuth: process.env.PATCHSTACK_PULSE_AUTH ?? undefined,\n    endpoint: process.env.PATCHSTACK_ENDPOINT ?? undefined,\n    timeoutMs,\n    environment:\n      environmentRaw !== undefined && environmentRaw.length > 0 ? environmentRaw : undefined,\n  };\n}\n\nfunction isUuid(value: string): boolean {\n  return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);\n}\n\nfunction isEnvironment(value: string): value is Environment {\n  return value === 'production' || value === 'sandbox';\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { PackageEntry } from '../types.js';\n\n/**\n * Registry-installable dependency names declared in package.json\n * (dependencies + devDependencies). Non-registry specifiers (file:, link:,\n * workspace:, portal:) are excluded — lockfile parsers skip those too, so\n * their absence from a parsed set says nothing about staleness. Returns []\n * when package.json is missing or unreadable (nothing to validate against).\n */\nexport async function readDeclaredDependencyNames(cwd: string): Promise<string[]> {\n  let raw: string;\n  try {\n    raw = await readFile(path.join(cwd, 'package.json'), 'utf8');\n  } catch {\n    return [];\n  }\n\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(raw);\n  } catch {\n    return [];\n  }\n  if (typeof parsed !== 'object' || parsed === null) {\n    return [];\n  }\n\n  const names = new Set<string>();\n  for (const group of ['dependencies', 'devDependencies'] as const) {\n    const deps = (parsed as Record<string, unknown>)[group];\n    if (typeof deps !== 'object' || deps === null) {\n      continue;\n    }\n    for (const [name, spec] of Object.entries(deps as Record<string, unknown>)) {\n      if (typeof spec === 'string' && /^(file|link|workspace|portal):/.test(spec)) {\n        continue;\n      }\n      names.add(name);\n    }\n  }\n\n  return [...names];\n}\n\n/**\n * Declared names absent from a parsed package set. A non-empty result means\n * the source predates package.json — the fossil-lockfile failure mode where\n * e.g. `npm install` planted a package-lock.json once and the platform's\n * native package manager (bun on Lovable) never updates it again.\n */\nexport function missingDependencies(declared: string[], packages: PackageEntry[]): string[] {\n  const present = new Set(packages.map((entry) => entry.name));\n  return declared.filter((name) => !present.has(name));\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { PatchstackError, type PackageEntry } from '../types.js';\n\ninterface LockfileV2Package {\n  name?: string;\n  version?: string;\n  link?: boolean;\n  resolved?: string;\n}\n\ninterface LockfileV2 {\n  lockfileVersion: number;\n  packages?: Record<string, LockfileV2Package>;\n  dependencies?: Record<string, LockfileV1Dependency>;\n}\n\ninterface LockfileV1Dependency {\n  version: string;\n  dependencies?: Record<string, LockfileV1Dependency>;\n}\n\nexport async function parseNpmLockfile(lockfilePath: string): Promise<PackageEntry[]> {\n  let raw: string;\n  try {\n    raw = await readFile(lockfilePath, 'utf8');\n  } catch (cause) {\n    throw new PatchstackError(`Could not read lockfile at ${lockfilePath}`, 'LOCKFILE_NOT_FOUND', cause);\n  }\n\n  let parsed: LockfileV2;\n  try {\n    parsed = JSON.parse(raw) as LockfileV2;\n  } catch (cause) {\n    throw new PatchstackError(`Lockfile at ${lockfilePath} is not valid JSON`, 'LOCKFILE_PARSE_ERROR', cause);\n  }\n\n  if (parsed.packages) {\n    return extractFromV2(parsed.packages);\n  }\n\n  if (parsed.dependencies) {\n    return extractFromV1(parsed.dependencies);\n  }\n\n  throw new PatchstackError(\n    `Lockfile at ${lockfilePath} has no \"packages\" or \"dependencies\" key`,\n    'LOCKFILE_PARSE_ERROR',\n  );\n}\n\nfunction extractFromV2(packages: Record<string, LockfileV2Package>): PackageEntry[] {\n  const entries: PackageEntry[] = [];\n\n  for (const [pkgPath, pkg] of Object.entries(packages)) {\n    if (pkgPath === '') {\n      continue;\n    }\n    if (pkg.link === true) {\n      continue;\n    }\n    if (typeof pkg.version !== 'string' || pkg.version.length === 0) {\n      continue;\n    }\n\n    const name = pkg.name ?? extractNameFromPath(pkgPath);\n    if (name === null) {\n      continue;\n    }\n\n    entries.push({\n      name,\n      version: pkg.version,\n      path: pkgPath,\n      direct: isDirectV2(pkgPath),\n    });\n  }\n\n  return entries;\n}\n\nfunction extractFromV1(\n  deps: Record<string, LockfileV1Dependency>,\n  acc: PackageEntry[] = [],\n  depth = 0,\n): PackageEntry[] {\n  for (const [name, dep] of Object.entries(deps)) {\n    if (typeof dep.version === 'string' && dep.version.length > 0) {\n      acc.push({ name, version: dep.version, direct: depth === 0 });\n    }\n    if (dep.dependencies) {\n      extractFromV1(dep.dependencies, acc, depth + 1);\n    }\n  }\n  return acc;\n}\n\nfunction extractNameFromPath(pkgPath: string): string | null {\n  const segments = pkgPath.split('node_modules' + path.sep === pkgPath ? path.sep : '/');\n  const parts = pkgPath.split('/');\n  const nmIndex = parts.lastIndexOf('node_modules');\n  if (nmIndex === -1 || nmIndex >= parts.length - 1) {\n    return segments[segments.length - 1] ?? null;\n  }\n  const tail = parts.slice(nmIndex + 1);\n  if (tail.length === 0) {\n    return null;\n  }\n  const first = tail[0];\n  if (first !== undefined && first.startsWith('@') && tail.length >= 2) {\n    return `${first}/${tail[1]}`;\n  }\n  return first ?? null;\n}\n\nfunction isDirectV2(pkgPath: string): boolean {\n  const parts = pkgPath.split('/');\n  const nmCount = parts.filter((p) => p === 'node_modules').length;\n  return nmCount === 1;\n}\n","import { lstat, readFile, readdir, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { PatchstackError, type PackageEntry } from '../types.js';\n\nexport async function walkNodeModules(cwd: string): Promise<PackageEntry[]> {\n  const root = path.join(cwd, 'node_modules');\n\n  try {\n    const info = await stat(root);\n    if (!info.isDirectory()) {\n      throw new PatchstackError(\n        `${root} exists but is not a directory.`,\n        'LOCKFILE_NOT_FOUND',\n      );\n    }\n  } catch (cause) {\n    if (cause instanceof PatchstackError) {\n      throw cause;\n    }\n    throw new PatchstackError(\n      `node_modules/ not found at ${cwd}. Install dependencies first (e.g. \\`bun install\\` or \\`npm install\\`).`,\n      'LOCKFILE_NOT_FOUND',\n      cause,\n    );\n  }\n\n  const entries: PackageEntry[] = [];\n  await walk(root, entries, 0);\n  return entries;\n}\n\nasync function walk(dir: string, acc: PackageEntry[], depth: number): Promise<void> {\n  let names: string[];\n  try {\n    names = await readdir(dir);\n  } catch {\n    return;\n  }\n\n  for (const name of names) {\n    if (name.startsWith('.')) {\n      continue;\n    }\n\n    const fullPath = path.join(dir, name);\n    if (!(await isPlainDirectory(fullPath))) {\n      continue;\n    }\n\n    if (name.startsWith('@')) {\n      let subNames: string[];\n      try {\n        subNames = await readdir(fullPath);\n      } catch {\n        continue;\n      }\n      for (const sub of subNames) {\n        if (sub.startsWith('.')) {\n          continue;\n        }\n        const scopedDir = path.join(fullPath, sub);\n        if (!(await isPlainDirectory(scopedDir))) {\n          continue;\n        }\n        await readPackage(scopedDir, depth, acc);\n        await walkNested(scopedDir, acc, depth);\n      }\n      continue;\n    }\n\n    await readPackage(fullPath, depth, acc);\n    await walkNested(fullPath, acc, depth);\n  }\n}\n\nasync function readPackage(\n  pkgDir: string,\n  depth: number,\n  acc: PackageEntry[],\n): Promise<void> {\n  let raw: string;\n  try {\n    raw = await readFile(path.join(pkgDir, 'package.json'), 'utf8');\n  } catch {\n    return;\n  }\n\n  let parsed: { name?: unknown; version?: unknown };\n  try {\n    parsed = JSON.parse(raw) as { name?: unknown; version?: unknown };\n  } catch {\n    return;\n  }\n\n  if (typeof parsed.name !== 'string' || parsed.name.length === 0) {\n    return;\n  }\n  if (typeof parsed.version !== 'string' || parsed.version.length === 0) {\n    return;\n  }\n\n  acc.push({\n    name: parsed.name,\n    version: parsed.version,\n    direct: depth === 0,\n  });\n}\n\nasync function walkNested(\n  pkgDir: string,\n  acc: PackageEntry[],\n  depth: number,\n): Promise<void> {\n  const nested = path.join(pkgDir, 'node_modules');\n  if (!(await isPlainDirectory(nested))) {\n    return;\n  }\n  await walk(nested, acc, depth + 1);\n}\n\nasync function isPlainDirectory(dir: string): Promise<boolean> {\n  try {\n    const info = await lstat(dir);\n    return info.isDirectory() && !info.isSymbolicLink();\n  } catch {\n    return false;\n  }\n}\n","import { readFile } from 'node:fs/promises';\nimport { PatchstackError, type PackageEntry } from '../types.js';\n\n/**\n * Parses pnpm-lock.yaml without pulling in a YAML library. We don't need full\n * YAML semantics — only the `packages:` block (the canonical list of every\n * installed package) and, for direct-dep marking, the dependency sections under\n * `importers:` (v9+) or at the top level (v6-v8 single-project).\n *\n * Supported pnpm-lock key formats:\n *   v5:    /pkg/1.0.0                /@scope/pkg/1.0.0\n *   v6-v8: /pkg@1.0.0                /@scope/pkg@1.0.0     (optional `(peer@x)` suffix)\n *   v9:    pkg@1.0.0                 @scope/pkg@1.0.0      (optional `(peer@x)` suffix, may be quoted)\n */\nexport async function parsePnpmLockfile(lockfilePath: string): Promise<PackageEntry[]> {\n  let raw: string;\n  try {\n    raw = await readFile(lockfilePath, 'utf8');\n  } catch (cause) {\n    throw new PatchstackError(\n      `Could not read lockfile at ${lockfilePath}`,\n      'LOCKFILE_NOT_FOUND',\n      cause,\n    );\n  }\n\n  const lines = raw.split(/\\r?\\n/);\n  const directNames = collectDirectDepNames(lines);\n  const packageKeys = collectPackagesBlockKeys(lines);\n\n  if (packageKeys.length === 0) {\n    throw new PatchstackError(\n      `Lockfile at ${lockfilePath} has no \"packages\" entries`,\n      'LOCKFILE_PARSE_ERROR',\n    );\n  }\n\n  const entries: PackageEntry[] = [];\n  for (const key of packageKeys) {\n    const parsed = parsePackageKey(key);\n    if (parsed === null) {\n      continue;\n    }\n    entries.push({\n      name: parsed.name,\n      version: parsed.version,\n      direct: directNames.has(parsed.name),\n    });\n  }\n\n  return entries;\n}\n\ninterface ParsedKey {\n  name: string;\n  version: string;\n}\n\nexport function parsePackageKey(rawKey: string): ParsedKey | null {\n  let k = rawKey.trim();\n  if (k.length === 0) {\n    return null;\n  }\n\n  if (\n    (k.startsWith(\"'\") && k.endsWith(\"'\")) ||\n    (k.startsWith('\"') && k.endsWith('\"'))\n  ) {\n    k = k.slice(1, -1);\n  }\n\n  if (k.startsWith('/')) {\n    k = k.slice(1);\n  }\n\n  // Strip peer-dependency suffix used by v6+: `pkg@1.0.0(peer@1.0.0)(other@2)`.\n  const parenIdx = k.indexOf('(');\n  if (parenIdx >= 0) {\n    k = k.slice(0, parenIdx);\n  }\n\n  // Split off the optional `@scope/` prefix so the remaining \"body\" contains\n  // exactly one separator between the bare name and the version. npm forbids\n  // both `@` and `/` inside the bare-name portion, so the first occurrence of\n  // either character in the body is unambiguously the name/version separator.\n  let scopePrefix = '';\n  let body = k;\n  if (k.startsWith('@')) {\n    const firstSlash = k.indexOf('/');\n    if (firstSlash <= 0) {\n      return null;\n    }\n    scopePrefix = k.slice(0, firstSlash + 1);\n    body = k.slice(firstSlash + 1);\n  }\n\n  const slashIdx = body.indexOf('/');\n  const atIdx = body.indexOf('@');\n\n  let sepIdx: number;\n  if (slashIdx < 0 && atIdx < 0) {\n    return null;\n  } else if (slashIdx < 0) {\n    sepIdx = atIdx;\n  } else if (atIdx < 0) {\n    sepIdx = slashIdx;\n  } else {\n    sepIdx = Math.min(slashIdx, atIdx);\n  }\n\n  const name = scopePrefix + body.slice(0, sepIdx);\n  let version = body.slice(sepIdx + 1);\n\n  // v5 peer suffix uses `_`: `1.0.0_react@18.2.0`.\n  const underscoreIdx = version.indexOf('_');\n  if (underscoreIdx >= 0) {\n    version = version.slice(0, underscoreIdx);\n  }\n\n  if (name.length === 0 || version.length === 0) {\n    return null;\n  }\n\n  return { name, version };\n}\n\nfunction indentOf(line: string): number {\n  let i = 0;\n  while (i < line.length && line[i] === ' ') {\n    i++;\n  }\n  return i;\n}\n\nfunction isBlankOrComment(line: string): boolean {\n  const trimmed = line.trim();\n  return trimmed.length === 0 || trimmed.startsWith('#');\n}\n\n/**\n * Collects keys directly nested under the top-level `packages:` block. Stops\n * when another top-level key (e.g. `snapshots:`) appears.\n */\nfunction collectPackagesBlockKeys(lines: string[]): string[] {\n  const keys: string[] = [];\n  let inBlock = false;\n  let childIndent: number | null = null;\n\n  for (const line of lines) {\n    if (isBlankOrComment(line)) {\n      continue;\n    }\n\n    const indent = indentOf(line);\n\n    if (!inBlock) {\n      if (indent === 0 && line.trim() === 'packages:') {\n        inBlock = true;\n      }\n      continue;\n    }\n\n    if (indent === 0) {\n      break;\n    }\n\n    if (childIndent === null) {\n      childIndent = indent;\n    }\n\n    if (indent !== childIndent) {\n      continue;\n    }\n\n    const content = line.slice(indent);\n    if (!content.endsWith(':')) {\n      continue;\n    }\n\n    keys.push(content.slice(0, -1));\n  }\n\n  return keys;\n}\n\n/**\n * Collects direct dependency names. Looks in two places, since the format\n * differs across lockfile versions and workspaces:\n *\n *   1. `importers:` > `<importer>:` > `{dependencies,devDependencies,optionalDependencies}:`\n *      (v9 always, v6-v8 in workspaces)\n *   2. Top-level `{dependencies,devDependencies,optionalDependencies}:`\n *      (v6-v8 single-project lockfiles)\n *\n * Direct-dep marking is best-effort: a name absent from both is simply left as\n * not-direct, matching the npm parser's behaviour for transitive packages.\n */\nfunction collectDirectDepNames(lines: string[]): Set<string> {\n  const names = new Set<string>();\n  collectFromImporters(lines, names);\n  for (const section of ['dependencies', 'devDependencies', 'optionalDependencies']) {\n    collectFromTopLevelSection(lines, section, names);\n  }\n  return names;\n}\n\nconst DEP_SECTIONS = new Set([\n  'dependencies',\n  'devDependencies',\n  'optionalDependencies',\n]);\n\nfunction collectFromImporters(lines: string[], out: Set<string>): void {\n  let inImporters = false;\n  let importerIndent: number | null = null;\n  let inDepSection = false;\n  let depSectionIndent: number | null = null;\n  let leafIndent: number | null = null;\n\n  for (const line of lines) {\n    if (isBlankOrComment(line)) {\n      continue;\n    }\n    const indent = indentOf(line);\n    const trimmed = line.trim();\n\n    if (!inImporters) {\n      if (indent === 0 && trimmed === 'importers:') {\n        inImporters = true;\n      }\n      continue;\n    }\n\n    if (indent === 0) {\n      break;\n    }\n\n    // Track the indent at which importer entries (e.g. `.:`, `packages/foo:`) sit.\n    if (importerIndent === null) {\n      importerIndent = indent;\n    }\n\n    if (indent === importerIndent) {\n      inDepSection = false;\n      depSectionIndent = null;\n      leafIndent = null;\n      continue;\n    }\n\n    if (!inDepSection) {\n      const key = stripTrailingColon(trimmed);\n      if (key !== null && DEP_SECTIONS.has(key)) {\n        inDepSection = true;\n        depSectionIndent = indent;\n      }\n      continue;\n    }\n\n    if (depSectionIndent !== null && indent <= depSectionIndent) {\n      // Reset — we've exited the dep section. Reconsider this line.\n      inDepSection = false;\n      depSectionIndent = null;\n      leafIndent = null;\n      const key = stripTrailingColon(trimmed);\n      if (key !== null && DEP_SECTIONS.has(key)) {\n        inDepSection = true;\n        depSectionIndent = indent;\n      }\n      continue;\n    }\n\n    if (leafIndent === null) {\n      leafIndent = indent;\n    }\n\n    if (indent !== leafIndent) {\n      continue;\n    }\n\n    const name = extractLeafName(trimmed);\n    if (name !== null) {\n      out.add(name);\n    }\n  }\n}\n\nfunction collectFromTopLevelSection(\n  lines: string[],\n  section: string,\n  out: Set<string>,\n): void {\n  let inSection = false;\n  let leafIndent: number | null = null;\n\n  for (const line of lines) {\n    if (isBlankOrComment(line)) {\n      continue;\n    }\n    const indent = indentOf(line);\n    const trimmed = line.trim();\n\n    if (!inSection) {\n      if (indent === 0 && trimmed === `${section}:`) {\n        inSection = true;\n      }\n      continue;\n    }\n\n    if (indent === 0) {\n      break;\n    }\n\n    if (leafIndent === null) {\n      leafIndent = indent;\n    }\n\n    if (indent !== leafIndent) {\n      continue;\n    }\n\n    const name = extractLeafName(trimmed);\n    if (name !== null) {\n      out.add(name);\n    }\n  }\n}\n\nfunction stripTrailingColon(s: string): string | null {\n  if (!s.endsWith(':')) {\n    return null;\n  }\n  return s.slice(0, -1).trim();\n}\n\n/**\n * Extracts the package name from a dependency-section leaf, handling both the\n * short form (`pkg: 1.0.0`) and the v9 expanded form (`pkg:` followed by\n * `specifier:` / `version:` children). Quoted scoped names like `'@scope/pkg':`\n * are unquoted.\n */\nfunction extractLeafName(trimmed: string): string | null {\n  const colonIdx = trimmed.indexOf(':');\n  if (colonIdx < 0) {\n    return null;\n  }\n  let name = trimmed.slice(0, colonIdx).trim();\n  if (name.length === 0) {\n    return null;\n  }\n  if (\n    (name.startsWith(\"'\") && name.endsWith(\"'\")) ||\n    (name.startsWith('\"') && name.endsWith('\"'))\n  ) {\n    name = name.slice(1, -1);\n  }\n  return name.length > 0 ? name : null;\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { PatchstackError, type PackageEntry } from '../types.js';\n\n/**\n * Parses yarn.lock (yarn classic v1 and yarn berry v2+) without a YAML\n * dependency. Both generations share the same block structure — a top-level\n * mapping of comma-separated descriptor lists to a block containing a\n * `version` field — so we walk them with the same scanner and only branch on\n * the `version` syntax (`version \"x\"` for v1, `version: x` for berry).\n *\n * Direct vs transitive can't be derived from yarn.lock alone (yarn does not\n * record an importer manifest the way pnpm v9 does), so we cross-reference\n * the sibling `package.json` when present.\n */\nexport async function parseYarnLockfile(lockfilePath: string): Promise<PackageEntry[]> {\n  let raw: string;\n  try {\n    raw = await readFile(lockfilePath, 'utf8');\n  } catch (cause) {\n    throw new PatchstackError(\n      `Could not read lockfile at ${lockfilePath}`,\n      'LOCKFILE_NOT_FOUND',\n      cause,\n    );\n  }\n\n  const blocks = parseBlocks(raw);\n  if (blocks.length === 0) {\n    throw new PatchstackError(\n      `Lockfile at ${lockfilePath} contains no package entries`,\n      'LOCKFILE_PARSE_ERROR',\n    );\n  }\n\n  const directNames = await readDirectDepNames(path.dirname(lockfilePath));\n\n  const entries: PackageEntry[] = [];\n  const seen = new Set<string>();\n  for (const block of blocks) {\n    if (block.version.length === 0 || block.names.size === 0) {\n      continue;\n    }\n    for (const name of block.names) {\n      const dedupKey = `${name}@${block.version}`;\n      if (seen.has(dedupKey)) {\n        continue;\n      }\n      seen.add(dedupKey);\n      entries.push({\n        name,\n        version: block.version,\n        direct: directNames.has(name),\n      });\n    }\n  }\n\n  return entries;\n}\n\ninterface Block {\n  names: Set<string>;\n  version: string;\n}\n\nfunction parseBlocks(raw: string): Block[] {\n  const lines = raw.split(/\\r?\\n/);\n  const blocks: Block[] = [];\n  let current: Block | null = null;\n\n  const finalize = () => {\n    if (current !== null && current.version.length > 0 && current.names.size > 0) {\n      blocks.push(current);\n    }\n    current = null;\n  };\n\n  for (const line of lines) {\n    const trimmed = line.trim();\n    if (trimmed.length === 0 || trimmed.startsWith('#')) {\n      continue;\n    }\n\n    const indent = countLeadingSpaces(line);\n\n    if (indent === 0) {\n      finalize();\n      if (!trimmed.endsWith(':')) {\n        continue;\n      }\n      // `__metadata:` (yarn berry header) has no `@` in any descriptor and\n      // produces an empty names set, so it's naturally skipped on finalize.\n      const keyLine = trimmed.slice(0, -1);\n      const names = new Set<string>();\n      for (const spec of splitDescriptors(keyLine)) {\n        const name = extractName(spec);\n        if (name !== null) {\n          names.add(name);\n        }\n      }\n      current = { names, version: '' };\n      continue;\n    }\n\n    if (current === null) {\n      continue;\n    }\n\n    const version = parseVersionField(trimmed);\n    if (version !== null) {\n      current.version = version;\n    }\n  }\n\n  finalize();\n  return blocks;\n}\n\nfunction countLeadingSpaces(line: string): number {\n  let i = 0;\n  while (i < line.length && line[i] === ' ') {\n    i++;\n  }\n  return i;\n}\n\n/**\n * Splits a yarn descriptor key list on top-level commas. yarn quotes any\n * descriptor that contains characters needing escaping, so we respect quotes\n * while splitting to avoid breaking on commas inside (rare in practice but\n * cheap to handle).\n */\nexport function splitDescriptors(keyLine: string): string[] {\n  const parts: string[] = [];\n  let current = '';\n  let quote: '\"' | \"'\" | null = null;\n\n  for (let i = 0; i < keyLine.length; i++) {\n    const c = keyLine[i];\n    if (quote !== null) {\n      current += c;\n      if (c === quote) {\n        quote = null;\n      }\n      continue;\n    }\n    if (c === '\"' || c === \"'\") {\n      quote = c;\n      current += c;\n      continue;\n    }\n    if (c === ',') {\n      const piece = current.trim();\n      if (piece.length > 0) {\n        parts.push(piece);\n      }\n      current = '';\n      continue;\n    }\n    current += c;\n  }\n  const tail = current.trim();\n  if (tail.length > 0) {\n    parts.push(tail);\n  }\n  return parts;\n}\n\n/**\n * Extracts the package name from a yarn descriptor like `axios@^1.6.0`,\n * `\"@scope/pkg@^2.1.0\"`, or `\"@scope/pkg@npm:2.1.0\"`. The descriptor's\n * range portion is discarded — we only need the name, since the resolved\n * version comes from the `version` field of the block.\n */\nexport function extractName(rawSpec: string): string | null {\n  let s = rawSpec.trim();\n  if (s.length === 0) {\n    return null;\n  }\n  if (\n    (s.startsWith('\"') && s.endsWith('\"')) ||\n    (s.startsWith(\"'\") && s.endsWith(\"'\"))\n  ) {\n    s = s.slice(1, -1);\n  }\n  // Position-0 `@` belongs to a scope, so we want the last `@` after it.\n  const atIdx = s.lastIndexOf('@');\n  if (atIdx <= 0) {\n    return null;\n  }\n  const name = s.slice(0, atIdx);\n  return name.length > 0 ? name : null;\n}\n\nfunction parseVersionField(content: string): string | null {\n  if (!content.startsWith('version')) {\n    return null;\n  }\n  const after = content.slice('version'.length);\n  // yarn v1: `version \"1.2.3\"` (whitespace then quoted)\n  // yarn berry: `version: 1.2.3` or `version: \"1.2.3\"`\n  const firstChar = after.charAt(0);\n  if (firstChar !== ' ' && firstChar !== '\\t' && firstChar !== ':') {\n    return null;\n  }\n  let rest = firstChar === ':' ? after.slice(1) : after;\n  rest = rest.trim();\n  if (rest.length === 0) {\n    return null;\n  }\n  if (\n    (rest.startsWith('\"') && rest.endsWith('\"')) ||\n    (rest.startsWith(\"'\") && rest.endsWith(\"'\"))\n  ) {\n    rest = rest.slice(1, -1);\n  }\n  return rest.length > 0 ? rest : null;\n}\n\nasync function readDirectDepNames(cwd: string): Promise<Set<string>> {\n  const names = new Set<string>();\n  let raw: string;\n  try {\n    raw = await readFile(path.join(cwd, 'package.json'), 'utf8');\n  } catch {\n    return names;\n  }\n\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(raw);\n  } catch {\n    return names;\n  }\n\n  if (typeof parsed !== 'object' || parsed === null) {\n    return names;\n  }\n  const obj = parsed as Record<string, unknown>;\n\n  for (const field of ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies']) {\n    const section = obj[field];\n    if (typeof section !== 'object' || section === null) {\n      continue;\n    }\n    for (const name of Object.keys(section)) {\n      names.add(name);\n    }\n  }\n\n  return names;\n}\n","import { access } from 'node:fs/promises';\nimport path from 'node:path';\nimport { PatchstackError, type Manifest, type PackageEntry } from '../types.js';\nimport { missingDependencies, readDeclaredDependencyNames } from './consistency.js';\nimport { parseNpmLockfile } from './npm.js';\nimport { walkNodeModules } from './node_modules.js';\nimport { parsePnpmLockfile } from './pnpm.js';\nimport { parseYarnLockfile } from './yarn.js';\n\ntype LockfileFilename =\n  | 'package-lock.json'\n  | 'bun.lock'\n  | 'bun.lockb'\n  | 'yarn.lock'\n  | 'pnpm-lock.yaml';\n\ntype DetectionStrategy =\n  | 'npm-lockfile'\n  | 'node-modules-walk'\n  | 'pnpm-lockfile'\n  | 'yarn-lockfile';\n\ninterface DetectedLockfile {\n  ecosystem: 'npm';\n  filePath: string;\n  filename: LockfileFilename;\n  strategy: DetectionStrategy;\n}\n\ninterface LockfileCandidate {\n  filename: LockfileFilename;\n  strategy: DetectionStrategy;\n}\n\n// Checked in priority order: the first candidate present in `cwd` wins.\nconst LOCKFILE_CANDIDATES: readonly LockfileCandidate[] = [\n  { filename: 'package-lock.json', strategy: 'npm-lockfile' },\n  { filename: 'bun.lock', strategy: 'node-modules-walk' },\n  { filename: 'bun.lockb', strategy: 'node-modules-walk' },\n  { filename: 'pnpm-lock.yaml', strategy: 'pnpm-lockfile' },\n  { filename: 'yarn.lock', strategy: 'yarn-lockfile' },\n];\n\nexport async function detectLockfile(cwd: string): Promise<DetectedLockfile> {\n  // Probe every candidate concurrently, then resolve by declaration order so\n  // the result is identical to a sequential first-match scan — but bounded by a\n  // single I/O round-trip instead of up to one `stat` per candidate.\n  const probed = await Promise.all(\n    LOCKFILE_CANDIDATES.map(async (candidate) => {\n      const filePath = path.join(cwd, candidate.filename);\n      return { ...candidate, filePath, present: await exists(filePath) };\n    }),\n  );\n\n  const match = probed.find((candidate) => candidate.present);\n  if (match) {\n    return {\n      ecosystem: 'npm',\n      filePath: match.filePath,\n      filename: match.filename,\n      strategy: match.strategy,\n    };\n  }\n\n  const expected = LOCKFILE_CANDIDATES.map((candidate) => candidate.filename).join(', ');\n  throw new PatchstackError(\n    `No lockfile found in ${cwd}. Expected one of: ${expected}.`,\n    'LOCKFILE_NOT_FOUND',\n  );\n}\n\nexport async function scanLockfile(cwd: string): Promise<Manifest> {\n  const candidates = await presentLockfiles(cwd);\n  if (candidates.length === 0) {\n    // Preserve the exact historical error for the no-lockfile case.\n    await detectLockfile(cwd);\n  }\n\n  // Validate each source against package.json before trusting it. A lockfile\n  // missing declared dependencies is a fossil — e.g. `npm install` planted a\n  // package-lock.json once on a bun-managed platform (Lovable), and the native\n  // dependency flow never updates it again. Trusting it would freeze the\n  // manifest and the build fingerprint while the real dependency set drifts.\n  const declared = await readDeclaredDependencyNames(cwd);\n  const warnings: string[] = [];\n  let firstParsed: { packages: PackageEntry[]; filename: string } | null = null;\n  let walkTried = false;\n\n  for (const candidate of candidates) {\n    let packages: PackageEntry[];\n    try {\n      packages = await runStrategy(candidate, cwd);\n    } catch {\n      continue;\n    }\n    walkTried ||= candidate.strategy === 'node-modules-walk';\n    firstParsed ??= { packages, filename: candidate.filename };\n\n    const missing = missingDependencies(declared, packages);\n    if (missing.length === 0) {\n      return manifestWith(packages, warnings);\n    }\n    warnings.push(staleWarning(candidate.filename, missing));\n  }\n\n  // Last resort: the installed truth. node_modules reflects what the build\n  // actually compiles against, whichever package manager wrote it.\n  if (!walkTried) {\n    try {\n      const packages = await walkNodeModules(cwd);\n      const missing = missingDependencies(declared, packages);\n      if (missing.length > 0) {\n        warnings.push(staleWarning('node_modules/', missing));\n      }\n      warnings.push('Scanned node_modules/ instead. Delete the stale lockfile to silence this warning.');\n      return manifestWith(packages, warnings);\n    } catch {\n      // fall through to the best lockfile we managed to parse\n    }\n  }\n\n  if (firstParsed === null) {\n    const expected = LOCKFILE_CANDIDATES.map((candidate) => candidate.filename).join(', ');\n    throw new PatchstackError(\n      `No readable lockfile found in ${cwd}. Expected one of: ${expected}.`,\n      'LOCKFILE_NOT_FOUND',\n    );\n  }\n\n  warnings.push(\n    `No fully-consistent source found; reporting ${firstParsed.filename}. The manifest may understate the real dependency set.`,\n  );\n\n  return manifestWith(firstParsed.packages, warnings);\n}\n\nfunction manifestWith(packages: PackageEntry[], warnings: string[]): Manifest {\n  return warnings.length > 0\n    ? { ecosystem: 'npm', packages, warnings }\n    : { ecosystem: 'npm', packages };\n}\n\nfunction staleWarning(source: string, missing: string[]): string {\n  const sample = missing.slice(0, 3).join(', ');\n  const suffix = missing.length > 3 ? `, +${missing.length - 3} more` : '';\n  return `${source} looks stale: package.json declares ${missing.length} dependenc${missing.length === 1 ? 'y' : 'ies'} it does not contain (${sample}${suffix}).`;\n}\n\nasync function presentLockfiles(cwd: string): Promise<DetectedLockfile[]> {\n  const probed = await Promise.all(\n    LOCKFILE_CANDIDATES.map(async (candidate) => {\n      const filePath = path.join(cwd, candidate.filename);\n      return { ...candidate, filePath, present: await exists(filePath) };\n    }),\n  );\n\n  return probed\n    .filter((candidate) => candidate.present)\n    .map(({ filename, strategy, filePath }) => ({ ecosystem: 'npm' as const, filename, strategy, filePath }));\n}\n\nasync function runStrategy(\n  detected: DetectedLockfile,\n  cwd: string,\n): Promise<PackageEntry[]> {\n  switch (detected.strategy) {\n    case 'npm-lockfile':\n      return parseNpmLockfile(detected.filePath);\n    case 'pnpm-lockfile':\n      return parsePnpmLockfile(detected.filePath);\n    case 'yarn-lockfile':\n      return parseYarnLockfile(detected.filePath);\n    case 'node-modules-walk':\n      return walkNodeModules(cwd);\n  }\n}\n\nasync function exists(filePath: string): Promise<boolean> {\n  try {\n    await access(filePath);\n    return true;\n  } catch {\n    return false;\n  }\n}\n","import type { Manifest, PackageEntry } from './types.js';\n\nexport interface WirePackage {\n  name: string;\n  version: string;\n}\n\nexport interface WirePayload {\n  ecosystem: Manifest['ecosystem'];\n  packages: WirePackage[];\n}\n\nexport interface NormalizeStats {\n  uniqueNames: number;\n  duplicateNames: string[];\n  totalEntries: number;\n}\n\nexport interface NormalizeResult {\n  payload: WirePayload;\n  stats: NormalizeStats;\n}\n\nexport function buildWirePayload(manifest: Manifest): NormalizeResult {\n  const seen = new Map<string, Set<string>>();\n  const wirePackages: WirePackage[] = [];\n\n  for (const entry of manifest.packages) {\n    const versions = seen.get(entry.name);\n    if (versions) {\n      if (versions.has(entry.version)) {\n        continue;\n      }\n      versions.add(entry.version);\n    } else {\n      seen.set(entry.name, new Set([entry.version]));\n    }\n    wirePackages.push({ name: entry.name, version: entry.version });\n  }\n\n  wirePackages.sort((a, b) => {\n    if (a.name === b.name) {\n      return compareVersions(a.version, b.version);\n    }\n    return a.name < b.name ? -1 : 1;\n  });\n\n  const duplicateNames: string[] = [];\n  for (const [name, versions] of seen) {\n    if (versions.size > 1) {\n      duplicateNames.push(name);\n    }\n  }\n\n  return {\n    payload: { ecosystem: manifest.ecosystem, packages: wirePackages },\n    stats: {\n      uniqueNames: seen.size,\n      duplicateNames,\n      totalEntries: manifest.packages.length,\n    },\n  };\n}\n\nexport function compareVersions(a: string, b: string): number {\n  if (a === b) {\n    return 0;\n  }\n\n  const [aBase, aPre] = splitPrerelease(a);\n  const [bBase, bPre] = splitPrerelease(b);\n\n  const baseCmp = compareSegments(aBase.split('.'), bBase.split('.'));\n  if (baseCmp !== 0) {\n    return baseCmp;\n  }\n\n  if (aPre === null && bPre === null) {\n    return 0;\n  }\n  if (aPre === null) {\n    return 1;\n  }\n  if (bPre === null) {\n    return -1;\n  }\n  return compareSegments(aPre.split('.'), bPre.split('.'));\n}\n\nfunction splitPrerelease(version: string): [string, string | null] {\n  const cleaned = version.replace(/^[v=]+/, '').split('+')[0]!;\n  const dashIndex = cleaned.indexOf('-');\n  if (dashIndex === -1) {\n    return [cleaned, null];\n  }\n  return [cleaned.slice(0, dashIndex), cleaned.slice(dashIndex + 1)];\n}\n\nfunction compareSegments(a: string[], b: string[]): number {\n  const max = Math.max(a.length, b.length);\n  for (let i = 0; i < max; i++) {\n    const aPart = a[i];\n    const bPart = b[i];\n    if (aPart === undefined) {\n      return -1;\n    }\n    if (bPart === undefined) {\n      return 1;\n    }\n    const aNum = /^\\d+$/.test(aPart);\n    const bNum = /^\\d+$/.test(bPart);\n    if (aNum && bNum) {\n      const diff = Number(aPart) - Number(bPart);\n      if (diff !== 0) {\n        return diff < 0 ? -1 : 1;\n      }\n      continue;\n    }\n    if (aNum) {\n      return -1;\n    }\n    if (bNum) {\n      return 1;\n    }\n    if (aPart < bPart) {\n      return -1;\n    }\n    if (aPart > bPart) {\n      return 1;\n    }\n  }\n  return 0;\n}\n\nexport function findPackageInManifest(\n  manifest: Manifest,\n  name: string,\n): PackageEntry[] {\n  return manifest.packages.filter((p) => p.name === name);\n}\n","// Re-post the project's dependency manifest to Pulse — the runtime counterpart to the CLI's\n// `scan`. The sandbox refresh loop (see runtime.js) calls this each tick so a dependency added\n// after boot is reported without a restart: a targeted `npm install <pkg>` fires no npm lifecycle\n// hook, so nothing else re-scans. Reuses the CLI scan pipeline; best-effort (the caller catches).\nimport { resolveConfig } from '../config.js';\nimport { scanLockfile } from '../parsers/index.js';\nimport { buildWirePayload } from '../normalize.js';\nimport { postManifest } from '../client.js';\n\n/** Scan the lockfile under `cwd` and post the manifest to Pulse. No-op without a provisioned site. */\nexport async function reportManifest(cwd: string): Promise<void> {\n  const config = await resolveConfig({ cwd });\n  if (config.siteUuid === null || config.siteUuid.length === 0) {\n    return;\n  }\n  const manifest = await scanLockfile(cwd);\n  const { payload } = buildWirePayload(manifest);\n  await postManifest(config, payload);\n}\n","// @patchstack/protect — \"Protect = respond\".\n//\n// One entry point that composes the node-waf engine + adapters with:\n//   - a rule source: an explicit bundle, or fetched from the Patchstack API (token),\n//     with a disk cache so the engine keeps working on last-known-good if the API is down\n//   - execution modes: 'dry-run' (detect + log, never block — the safe onramp) and 'block' (enforce).\n//     This API's default is 'dry-run'. NOTE the scaffolded guard (`patchstack-connect protect`)\n//     deliberately passes mode: 'block' and only drops to dry-run when PATCHSTACK_MODE=dry-run — so an\n//     installed guard ENFORCES by default even though this constructor's default doesn't. Precedence:\n//     PATCHSTACK_MODE env > API `enforcement` > options.mode > dry-run.\n//   - fail-open everywhere: a rule/engine error never blocks (or crashes) a request. Where the guard\n//     fails open *without* inspecting (body caps, live streams, binary bodies, resolver failures) it\n//     is counted and reported — see `protection.coverage()` / the `onSkip` option.\n//\n// Runtime guards: .express(), .node(), .fetch(handler) / .fetchGuard() — same policy,\n// every runtime an AI builder deploys to.\n// Vendored node-waf engine (this package is self-contained — no @patchstack/node-waf dep).\nimport { RuleEngine } from './engine/index.js';\nimport { matchValue, walkLeaves, safeRegExp } from './engine/engine.js';\nimport { PulseRuleClient } from './engine/pulse-client.js';\nimport { fromFetchRequest } from './engine/fetch.js';\nimport { fromNodeRequest } from './engine/node.js';\nimport { installEgressGuard } from './egress.js';\nimport { DEFAULT_RESPONSE_RULES, DEFAULT_EGRESS_RULES } from './defaults.js';\nimport { renderBlockPage } from './block-page.js';\n// Rule lifecycle (source / tiered store / refresh) lives in ./rules/ — this file stays focused on\n// composing the engine + guards and running the three screening phases.\nimport { makeStore } from './rules/store.js';\nimport { resolveRules } from './rules/source.js';\nimport { startRefresh, makeRefreshHandler } from './rules/refresh.js';\nimport { createFirewallLogReporter, resolveApiBase, telemetryEnabled } from './firewall-log.js';\n\n// Supabase-tunnel guard for AI-builder apps (Lovable / TanStack Start + Supabase).\nexport { createSupabaseGuard, GUARD_PATH } from './supabase-guard.js';\n\n// Per-site live rule client (Pulse). Re-exported for callers/tests that want to use it directly.\nexport { PulseRuleClient };\n\n// Server-function guard. Modern Lovable apps mutate data through TanStack server functions\n// (browser → server fn → server-side Supabase client), which bypass the browser-side tunnel the\n// Supabase guard relies on. This inspects the decoded server-fn call args against the SAME policy\n// by feeding them through fetchGuard (the args become the request body, so the engine resolves\n// `post.<field>` exactly as it does for a tunneled Supabase insert). Returns a block receipt\n// { rule?, message } to throw on, or null to allow (also null in dry-run — the detection is still\n// recorded by fetchGuard). Fail-open on any error.\nexport function createServerFnGuard({ protection }) {\n  const guard = protection.fetchGuard();\n  return async (data) => {\n    let res;\n    try {\n      const req = new Request('https://patchstack.local/_serverfn', {\n        method: 'POST',\n        headers: { 'content-type': 'application/json' },\n        body: JSON.stringify(data ?? {}),\n      });\n      res = await guard(req);\n    } catch {\n      return null; // fail open\n    }\n    if (!res) return null; // allowed (or dry-run)\n    let body = {};\n    try {\n      body = await res.clone().json();\n    } catch {\n      /* non-JSON block response */\n    }\n    return { rule: body.rule, message: body.message || 'Blocked by Patchstack' };\n  };\n}\n\nexport async function createProtection(options = {}) {\n  const onError = options.onError;\n  const userOnDetect = options.onDetect ?? defaultOnDetect;\n\n  // Report enforced blocks via existing connector POST /api/logs/log (WP path).\n  // Needs api_key from provision / PATCHSTACK_API_KEY / .patchstackrc.json.\n  // Opt out: PATCHSTACK_TELEMETRY=off. Never embed api_key in the public widget.\n  const apiKey = await resolveApiKey(options);\n  const firewallLog =\n    apiKey && telemetryEnabled() && options.reportFirewallLog !== false\n      ? createFirewallLogReporter({\n          apiKey,\n          apiBase: resolveApiBase(options.pulseRulesUrl ?? options.baseUrl),\n          sourceHost: options.sourceHost,\n          fetchImpl: options.fetchImpl,\n        })\n      : null;\n\n  const onDetect = (detection) => {\n    userOnDetect(detection);\n    if (firewallLog && detection?.mode === 'block') {\n      firewallLog.record({\n        rule: detection.rule,\n        method: detection.method,\n        path: detection.path,\n        ip: detection.ip,\n        userAgent: detection.userAgent,\n      });\n    }\n  };\n\n  // One tiered store (memory → filesystem/pluggable) shared by the initial load and every refresh.\n  const store = makeStore(options);\n  // Startup must not hang on the network: hosted platforms (Replit et al.) fail a deploy whose health\n  // check is slow, and the guard can always boot from last-known-good / the bundled fallback. Refreshes\n  // keep the full budget. Override with { bootTimeoutMs }.\n  const bootTimeoutMs = Number(options.bootTimeoutMs) > 0 ? Number(options.bootTimeoutMs) : 5_000;\n  // Resolved once and threaded through ctx: reading it is a filesystem hit on\n  // runtimes that have one, and refreshes should not repeat it.\n  const pulseAuth = await resolvePulseAuth(options);\n  const bundle = await resolveRules(options, store, { timeoutMs: bootTimeoutMs, pulseAuth });\n  // Mode is mutable so a Pulse refresh can flip dry-run ↔ block when SaaS enables production.\n  // Precedence: PATCHSTACK_MODE env (local override) > API enforcement > options.mode > dry-run.\n  let mode = resolveMode(options, bundle);\n  // Rule-derived runtime state. Held in `let` bindings the guard methods below close over, so a\n  // refresh (see the loop near the end) can hot-swap the engines by reassigning them — the\n  // egress interception and the protection object itself stay in place, no re-install.\n  let requestRules;\n  let responseRules;\n  let egressRules;\n  let screenCap; // max body we'll buffer/screen (rules can raise it)\n  let engine;\n  let responseRuleSet;\n  let egressEngine;\n\n  // Split the delivered ruleset by phase (default \"request\"), merging phase defaults +\n  // per-call overrides. Detection is fully rule-driven — nothing hardcoded.\n  const applyBundle = (delivered) => {\n    const incoming = delivered.firewall ?? [];\n    requestRules = byPhase(incoming, 'request');\n    responseRules = [...(options.responseRules ?? DEFAULT_RESPONSE_RULES), ...byPhase(incoming, 'response')];\n    screenCap = responseScreenCap(responseRules);\n    egressRules = [...(options.egressRules ?? DEFAULT_EGRESS_RULES), ...byPhase(incoming, 'egress')];\n    engine = new RuleEngine({\n      firewall: requestRules,\n      whitelists: delivered.whitelists,\n      whitelist_keys: delivered.whitelist_keys,\n      onError,\n    });\n    // One engine per response rule so we can find ALL matches (to redact each). `action:\n    // \"redact\"` masks the offending span(s); anything else withholds the whole response.\n    responseRuleSet = responseRules.map((rule) => ({\n      rule,\n      engine: new RuleEngine({ firewall: [rule], onError }),\n      redactors: rule.action === 'redact' || rule.action === 'encode' ? extractRedactors(rule) : null,\n      // A redact/encode condition that carries body-transforming mutations (base64_decode, urldecode,\n      // json_decode, …) detects on the DECODED body but the span redactors run on the RAW body — so\n      // they mask nothing and the secret is served while the log says \"redacted\". Flag it so screenText\n      // fails such a rule CLOSED (block) instead of serving a no-op redaction.\n      mutatedSpan: (rule.action === 'redact' || rule.action === 'encode') && hasSpanMutations(rule),\n      // Optional cheap pre-filter: literal anchor(s) that MUST appear for the (expensive) regex to\n      // have any chance of matching. Lets screenText skip the full scan on bodies with no candidate —\n      // the common case — cutting CPU/latency and shrinking the regex/ReDoS surface. Case-insensitive.\n      prefilter: Array.isArray(rule.prefilter) && rule.prefilter.length\n        ? rule.prefilter.map((s) => String(s).toLowerCase())\n        : null,\n    }));\n    egressEngine = new RuleEngine({ firewall: egressRules, onError });\n  };\n\n  applyBundle(bundle);\n\n  // Fail-open COVERAGE. The guard deliberately passes traffic through rather than risk breaking the\n  // app: an oversized request body, a response past the screening cap, a live stream, a binary body, a\n  // parse failure, a DNS resolver failure. Each of those is a real hole in enforcement, and until now\n  // it was SILENT — \"always-on\" read as \"always inspected\". Every such bypass is now counted and\n  // reported to `onSkip`, so a host can alert on it and `protection.coverage()` can be surfaced.\n  // `onSkip` is a TRUSTED SERVER callback: `detail` carries operational context (sizes, statuses,\n  // outbound hostnames) for logging/alerting. Do not forward it to a client response.\n  const skipCounts = Object.create(null);\n  const onSkip = typeof options.onSkip === 'function' ? options.onSkip : null;\n  const recordSkip = (phase, reason, detail) => {\n    const key = `${phase}:${reason}`;\n    skipCounts[key] = (skipCounts[key] ?? 0) + 1;\n    if (onSkip) {\n      try {\n        onSkip({ phase, reason, detail, count: skipCounts[key] });\n      } catch {\n        /* a reporting callback must never affect request handling */\n      }\n    }\n  };\n\n  const maskFn =\n    typeof options.maskWith === 'function'\n      ? options.maskWith\n      : () => (typeof options.maskWith === 'string' ? options.maskWith : '[REDACTED]');\n\n  // Given a request/egress result, enforce (block mode) or just record (dry-run).\n  //\n  // A rule may carry its own `enforcement: 'dry-run'`, which wins over block mode for that rule alone.\n  // Auto-generated rules arrive that way: their coordinate comes from best-effort static analysis, so they\n  // are served to detect until a probe or a human has justified them, WITHOUT holding back the\n  // hand-authored rules on the same site. A rule with no `enforcement` follows the bundle exactly as\n  // before, so an older server that never sends the field behaves identically.\n  const ruleMode = (rule) => (rule?.enforcement === 'dry-run' ? 'dry-run' : mode);\n\n  const decide = (phase, result, block, allow, ctx = {}) => {\n    if (!result || !result.blocked) return allow();\n    const effectiveMode = ruleMode(result.rule);\n    onDetect({\n      phase,\n      // The mode this detection was actually handled under, not the site's: a consumer counting blocks\n      // would otherwise over-report, and the whole point of a dry-run rule is that it did not block.\n      mode: effectiveMode,\n      category: result.rule?.category,\n      rule: result.rule,\n      message: result.message,\n      method: ctx.method,\n      path: ctx.path,\n      ip: ctx.ip,\n      userAgent: ctx.userAgent,\n    });\n    return effectiveMode === 'block' ? block() : allow();\n  };\n\n  // Response phase core: screen a text body → { verdict: 'pass'|'block'|'redact', body? }.\n  // redact masks matched spans; block withholds; block wins over redact. Enforcement only in\n  // block mode (dry-run records via onDetect but returns 'pass').\n  const screenText = (text, meta, reqCtx) => {\n    let blockRule = null;\n    const redactions = [];\n    const headerMutations = [];\n    let lowerText = null; // lazily lowercased body, only if a rule uses a prefilter\n    for (const { rule, engine: re, redactors, prefilter, mutatedSpan } of responseRuleSet) {\n      // Cheap pre-filter: if none of the rule's literal anchors is in the body, its regex can't\n      // match — skip the full scan (the common no-secret case) before touching the engine.\n      if (prefilter) {\n        if (lowerText === null) lowerText = text.toLowerCase();\n        if (!prefilter.some((p) => lowerText.includes(p))) continue;\n      }\n      let result;\n      try {\n        // Spread the originating request (method / originalUrl / headers) alongside the response,\n        // so a response rule's `when` route/method scope resolves against the REAL request and so\n        // request Host/Origin are visible to response rules — rather than the phantom empty request\n        // the response phase used to build (which made `when` on a response rule inert).\n        result = re.evaluate({ ...(reqCtx || {}), _response: { ...meta, body: text } });\n      } catch (err) {\n        onError?.(err);\n        continue;\n      }\n      if (!result.blocked) continue;\n      // Per-rule enforcement applies to every phase, not just the request. A generated response rule in\n      // dry-run must not redact or withhold a body either: \"detect until justified\" is meaningless if the\n      // rule still rewrites what the user sees.\n      const responseMode = ruleMode(rule);\n      onDetect({ phase: 'response', mode: responseMode, category: rule.category, rule, message: result.message });\n      if (responseMode !== 'block') continue; // dry-run: observe only\n      if (redactors && redactors.length) {\n        // Span redactors on a mutation-decoded rule can't map back to the raw body → fail closed.\n        const spanRedactors = redactors.filter((r) => !r.jsonPath);\n        if (mutatedSpan && spanRedactors.length) {\n          if (!blockRule) blockRule = rule;\n        } else {\n          redactions.push({ rule, redactors });\n        }\n      } else if (isHeaderMutation(rule.action)) headerMutations.push(rule);\n      else if (!blockRule) blockRule = rule;\n    }\n    if (mode !== 'block' || (!blockRule && !redactions.length && !headerMutations.length)) return { verdict: 'pass' };\n    if (blockRule) return { verdict: 'block' };\n    let body = text;\n    // Redact the offending spans in the body AND in every (string) header value — so a secret\n    // that leaks in a header (Set-Cookie, an echoed X-Api-Key, …) is masked too, and a rule that\n    // targets `response.header.*` actually strips the header rather than just detecting it.\n    const headers = { ...(meta.headers || {}) };\n    for (const { rule, redactors } of redactions) {\n      const mask = maskFn(rule.category);\n      // action `encode` HTML-escapes the matched value in place (neutralize stored XSS at output);\n      // `redact` masks it. jsonPath redactors act on a structural JSON location, span redactors on\n      // text spans in the body AND header values. Apply structural first (on clean JSON), then spans.\n      const transform = rule.action === 'encode' ? htmlEscape : null;\n      const pathRedactors = redactors.filter((r) => r.jsonPath);\n      const spanRedactors = redactors.filter((r) => !r.jsonPath);\n      if (pathRedactors.length) body = applyPathRedactors(body, pathRedactors, mask, screenCap, transform);\n      if (!spanRedactors.length) continue;\n      body = applyRedactors(body, spanRedactors, mask, transform);\n      if (transform) continue; // encoding is a body/output concern — headers aren't HTML\n      for (const name of Object.keys(headers)) {\n        const value = headers[name];\n        if (typeof value === 'string') {\n          headers[name] = applyRedactors(value, spanRedactors, mask);\n        } else if (Array.isArray(value)) {\n          // Multi-valued headers (Set-Cookie) — redact each entry.\n          headers[name] = value.map((item) => (typeof item === 'string' ? applyRedactors(item, spanRedactors, mask) : item));\n        }\n      }\n    }\n    for (const rule of headerMutations) applyHeaderMutation(headers, rule);\n    return { verdict: 'redact', body, headers };\n  };\n\n  // Minimal request context for the response phase: what a response rule's `when` scope and any\n  // request-header reference (Host/Origin) need — method, path, and request headers. No body.\n  const reqContextFromFetch = (request) => {\n    try {\n      const u = new URL(request.url);\n      const headers = headerObject(request.headers);\n      // A fetch Request doesn't expose the Host header (it's set at send time), so derive it from the\n      // URL — response rules that compare origins (open-redirect / CORS) need the request Host.\n      if (!headers.host) headers.host = u.host;\n      return { method: request.method, originalUrl: u.pathname + u.search, headers };\n    } catch {\n      return undefined;\n    }\n  };\n  const reqContextFromNode = (req) => (req ? { method: req.method, originalUrl: req.url, headers: req.headers || {} } : undefined);\n\n  // Screen a fetch Response (used by .fetch() and — via protection.screenResponse — the Supabase guard).\n  const screenResp = async (response, reqCtx) => {\n    const read = await readTextResponse(response, screenCap);\n    if (read.skip) {\n      // Nothing was screened — a leak/PII rule cannot have applied. Record it (a live stream and a\n      // binary body are by design; a body-cap or read failure is a coverage hole worth alerting on).\n      if (read.skip !== 'not-a-response') recordSkip('response', read.skip, { status: response?.status });\n      return response;\n    }\n    const text = read.text;\n    const r = screenText(text, { status: response.status, headers: headerObject(response.headers) }, reqCtx);\n    if (r.verdict === 'block') return leakResponse();\n    if (r.verdict === 'redact') return rebuildResponse(response, r.body, r.headers);\n    return response;\n  };\n\n  // Wrap a Node ServerResponse so its (buffered, text) body is screened before it's sent.\n  // Opt-in (buffering can delay a streamed response); over 512 KiB it stops buffering and\n  // passes through unscanned.\n  const wrapNodeResponse = (res, reqCtx) => {\n    const origWrite = res.write.bind(res);\n    const origEnd = res.end.bind(res);\n    const chunks = [];\n    let size = 0;\n    let overflow = false;\n    const MAX = screenCap;\n    const collect = (chunk, enc) => {\n      if (chunk == null) return;\n      const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, typeof enc === 'string' ? enc : 'utf8');\n      size += buf.length;\n      if (size > MAX) {\n        // Too big to screen — abandon buffering, but FLUSH what we already captured (the head) plus\n        // this chunk before switching to pass-through, so the client gets a complete body (not a\n        // truncated one missing everything before the cap was hit).\n        for (const c of chunks) origWrite(c);\n        chunks.length = 0;\n        origWrite(buf);\n        overflow = true;\n        recordSkip('response', 'body-cap', { bytes: size });\n        return;\n      }\n      chunks.push(buf);\n    };\n    res.write = function (chunk, enc, cb) {\n      if (overflow) return origWrite(chunk, enc, cb);\n      collect(chunk, enc);\n      if (typeof enc === 'function') enc();\n      else if (typeof cb === 'function') cb();\n      return true;\n    };\n    res.end = function (chunk, enc, cb) {\n      if (typeof chunk === 'function') { cb = chunk; chunk = undefined; enc = undefined; }\n      else if (typeof enc === 'function') { cb = enc; enc = undefined; }\n      if (overflow) { if (chunk != null) origWrite(chunk, enc); return origEnd(cb); }\n      collect(chunk, enc);\n      if (overflow) return origEnd(cb); // collect just flushed head + final chunk on overflow\n      const buffer = Buffer.concat(chunks);\n      let ct = res.getHeader ? res.getHeader('content-type') : undefined;\n      if (Array.isArray(ct)) ct = ct[0];\n      const kind = screenableContentType(ct);\n      // Skip live streams / binary bodies (incl. an octet-stream that sniffs as binary) — untouched.\n      if (kind === 'skip' || (kind === 'sniff' && looksBinary(buffer))) {\n        recordSkip('response', kind === 'skip' ? (baseContentType(ct) === 'text/event-stream' ? 'live-stream' : 'non-text-content-type') : 'binary-body');\n        for (const c of chunks) origWrite(c);\n        return origEnd(cb);\n      }\n      const text = buffer.toString('utf8');\n      let r;\n      try {\n        r = screenText(text, { status: res.statusCode, headers: res.getHeaders ? res.getHeaders() : {} }, reqCtx);\n      } catch (err) {\n        onError?.(err);\n        for (const c of chunks) origWrite(c);\n        return origEnd(cb);\n      }\n      if (r.verdict === 'block') {\n        res.statusCode = 500;\n        try { res.setHeader('content-type', 'application/json'); } catch { /* headers sent */ }\n        return origEnd(JSON.stringify({ error: 'Response withheld by Patchstack (sensitive data detected)' }), cb);\n      }\n      if (r.verdict === 'redact') {\n        try { res.removeHeader && res.removeHeader('content-length'); } catch { /* ignore */ }\n        if (r.headers && res.setHeader) {\n          const current = res.getHeaders ? res.getHeaders() : {};\n          for (const [name, value] of Object.entries(r.headers)) {\n            // content-length was just removed (the redacted body has a new length); never re-set a\n            // stale one here or the response truncates/hangs.\n            if (name.toLowerCase() === 'content-length') continue;\n            if (value === null || value === undefined) {\n              try { res.removeHeader && res.removeHeader(name); } catch { /* ignore */ } // header-mutation removal\n            } else if (Array.isArray(value)) {\n              try { res.setHeader(name, value); } catch { /* ignore invalid header */ } // Set-Cookie array\n            } else if (typeof value === 'string' && current[name] !== value) {\n              try { res.setHeader(name, value); } catch { /* ignore invalid header */ }\n            }\n          }\n        }\n        return origEnd(r.body, cb);\n      }\n      for (const c of chunks) origWrite(c);\n      return origEnd(cb);\n    };\n  };\n\n  // Egress phase: is this outbound call blocked? (records detection either way)\n  const allow = new Set((options.allowHosts ?? []).map((h) => String(h).toLowerCase()));\n  const egressShouldBlock = (url, host, method) => {\n    if (host && allow.has(host.toLowerCase())) return false;\n    let result;\n    try {\n      result = egressEngine.evaluate({ _egress: { url, host, method } });\n    } catch (err) {\n      onError?.(err);\n      return false;\n    }\n    if (!result.blocked) return false;\n    // Same for egress: a dry-run rule records the outbound attempt without preventing it. Blocking a\n    // request the app makes is at least as disruptive as blocking one it receives.\n    const egressMode = ruleMode(result.rule);\n    onDetect({ phase: 'egress', mode: egressMode, category: result.rule?.category, rule: result.rule, message: result.message });\n    return egressMode === 'block';\n  };\n\n  const protection = {\n    get mode() {\n      return mode;\n    },\n    get rules() {\n      return { request: requestRules, response: responseRules, egress: egressRules };\n    },\n\n    /**\n     * Enforcement coverage: how often the guard FAILED OPEN rather than inspecting, keyed\n     * `<phase>:<reason>` (e.g. `response:body-cap`, `request:body-cap`, `response:live-stream`,\n     * `egress:resolver-failed`). \"Always-on\" is not \"always inspected\" — surface this (or pass\n     * `onSkip`) so an unscreened path is visible and alertable rather than silent.\n     */\n    coverage() {\n      return { skipped: { ...skipCounts } };\n    },\n\n    // Screen a fetch Response through the response-phase rules (redact/block). Used by\n    // .fetch(), and by the Supabase guard on its forwarded upstream response.\n    screenResponse: (response, request) => screenResp(response, request ? reqContextFromFetch(request) : undefined),\n\n    // (request) => Response | null   (null = allow, caller proceeds). Request phase only.\n    fetchGuard() {\n      return async (request) => {\n        let result;\n        try {\n          result = engine.evaluate(await fromFetchRequest(request));\n        } catch (err) {\n          onError?.(err);\n          return null; // fail open\n        }\n        return decide('request', result, () => blockResponse(result, request), () => null, fetchRequestMeta(request));\n      };\n    },\n\n    // Wrap a fetch handler: screens the request, then the response (redact/block).\n    fetch(handler) {\n      const guard = protection.fetchGuard();\n      return async (request, ...rest) => {\n        const blocked = await guard(request);\n        if (blocked) return blocked;\n        const response = await handler(request, ...rest);\n        return screenResp(response, reqContextFromFetch(request));\n      };\n    },\n\n    // Express middleware (request phase; expects express-parsed req.query/req.body).\n    // Pass { screenResponses: true } to also screen the outgoing response (buffers it).\n    express(exprOptions = {}) {\n      return (req, res, next) => {\n        let result;\n        try {\n          result = engine.evaluate(req);\n        } catch (err) {\n          onError?.(err);\n          if (exprOptions.screenResponses) wrapNodeResponse(res, reqContextFromNode(req));\n          return next();\n        }\n        decide(\n          'request',\n          result,\n          () => {\n            if (isDocumentNavigation((n) => req.headers?.[n])) {\n              res.status(403).type('html').send(renderBlockPage({ url: req.originalUrl || req.url || '/', code: result?.rule?.id }));\n            } else {\n              res.status(403).json(blockBody(result));\n            }\n          },\n          () => {\n            if (exprOptions.screenResponses) wrapNodeResponse(res, reqContextFromNode(req));\n            next();\n          },\n          nodeRequestMeta(req),\n        );\n      };\n    },\n\n    // Node / Connect middleware — buffers the body itself (request phase).\n    // Pass { screenResponses: true } to also screen the outgoing response (buffers it).\n    node(nodeOptions = {}) {\n      const maxBytes = nodeOptions.maxBodyBytes ?? 1024 * 1024;\n      return (req, res, next) => {\n        const chunks = [];\n        let size = 0;\n        let overflow = false;\n        req.on('data', (chunk) => {\n          size += chunk.length;\n          if (size > maxBytes) {\n            overflow = true;\n            return;\n          }\n          chunks.push(chunk);\n        });\n        req.on('error', (err) => {\n          onError?.(err);\n          next();\n        });\n        req.on('end', () => {\n          if (overflow) recordSkip('request', 'body-cap', { bytes: size, limit: maxBytes });\n          const rawBody = overflow ? '' : Buffer.concat(chunks).toString('utf8');\n          let shaped;\n          let result;\n          try {\n            shaped = fromNodeRequest(req, rawBody);\n            result = engine.evaluate(shaped);\n          } catch (err) {\n            onError?.(err);\n            return next();\n          }\n          decide(\n            'request',\n            result,\n            () => {\n              res.statusCode = 403;\n              if (isDocumentNavigation((n) => req.headers?.[n])) {\n                res.setHeader('content-type', 'text/html; charset=utf-8');\n                res.end(renderBlockPage({ url: req.url || '/', code: result?.rule?.id }));\n              } else {\n                res.setHeader('content-type', 'application/json');\n                res.end(JSON.stringify(blockBody(result)));\n              }\n            },\n            () => {\n              // This guard consumed the request stream to screen it; re-expose the parsed\n              // body so a downstream handler (without its own body-parser) can read it.\n              if (req.body === undefined) req.body = shaped.body;\n              if (nodeOptions.screenResponses) wrapNodeResponse(res, reqContextFromNode(req));\n              next();\n            },\n            nodeRequestMeta(req),\n          );\n        });\n      };\n    },\n  };\n\n  // Egress interception is opt-in (it wraps the global fetch, and node:http/https on Node).\n  if (options.egress) {\n    protection.uninstallEgress = await installEgressGuard({\n      shouldBlock: egressShouldBlock,\n      onBlock: options.onEgressBlock,\n      // Route egress coverage gaps (a DNS resolver failure / no resolver on this runtime) into the\n      // same skip accounting as the request/response phases.\n      onSkip: ({ reason, detail }) => recordSkip('egress', reason, detail),\n      dnsScreen: options.screenDns !== false,\n      allowHosts: options.allowHosts,\n    });\n  }\n\n  // Live rule refresh. The guard otherwise reads its rules once, at process start — so a rule that\n  // only becomes relevant after boot (a dependency added mid-session and flagged by Pulse, a\n  // zero-day published) never applies until the process restarts. A refresh re-fetches and\n  // hot-swaps the engines in place; the same tick can be driven by a poll loop (`refreshMs`), a\n  // manual `protection.refresh()`, or an authenticated push (`protection.refreshHandler()`).\n  const cwd = options.cwd ?? (typeof process !== 'undefined' ? process.cwd() : undefined);\n  const live = Boolean(options.siteUuid || options.token);\n  const refreshSecret = options.refreshSecret ?? (typeof process !== 'undefined' ? process.env.PATCHSTACK_REFRESH_SECRET : undefined);\n  const refreshable = live && (options.refreshMs > 0 || Boolean(refreshSecret));\n\n  // On the Pulse (siteUuid) path, re-post the dependency manifest before re-fetching. A targeted\n  // `npm install <pkg>` fires no npm lifecycle hook, so nothing else re-scans; reporting here lets\n  // the server flag a newly-added vulnerable dependency and the SAME tick's rule fetch pick up its\n  // rule. Loaded once, up front, only when a refresh path is enabled — a refresh-off production\n  // guard never pulls in the scan pipeline; a load/report failure never blocks the rule refresh.\n  let reporter = null;\n  if (refreshable && options.siteUuid && options.reportManifest !== false && cwd) {\n    try {\n      ({ reportManifest: reporter } = await import('./refresh-manifest.js'));\n    } catch (err) {\n      onError?.(err); // scan pipeline unavailable (e.g. an edge runtime) — rules still refresh\n    }\n  }\n\n  const runRefreshTick = async () => {\n    if (reporter) {\n      try {\n        await reporter(cwd);\n      } catch (err) {\n        onError?.(err); // a failed report must not stop the rule refresh\n      }\n    }\n    const next = await resolveRules(options, store, { timeoutMs: options.refreshTimeoutMs, pulseAuth });\n    mode = resolveMode(options, next);\n    applyBundle(next);\n  };\n\n  if (live) {\n    // Manual one-shot refresh (also the primitive the loop + push endpoint run).\n    protection.refresh = () => runRefreshTick();\n    // Authenticated push endpoint — the platform/SaaS hits it for an immediate refresh. No secret\n    // configured → the handler 404s (never an open refresh trigger).\n    protection.refreshHandler = () => makeRefreshHandler(runRefreshTick, refreshSecret);\n  }\n\n  if (options.refreshMs > 0 && live) {\n    const loop = startRefresh(runRefreshTick, { refreshMs: options.refreshMs, onError });\n    protection.stopRefresh = () => {\n      loop.stop();\n      firewallLog?.stop();\n    };\n  } else if (firewallLog) {\n    protection.stopRefresh = () => firewallLog.stop();\n  }\n\n  return protection;\n}\n\n/**\n * Resolve runtime enforcement mode.\n * Precedence: PATCHSTACK_MODE env > Pulse `enforcement` on the rules bundle > options.mode > dry-run.\n */\nfunction resolveMode(options, bundle) {\n  const env = typeof process !== 'undefined' ? process.env?.PATCHSTACK_MODE : undefined;\n  if (env === 'block' || env === 'dry-run') return env;\n  if (bundle?.enforcement === 'block' || bundle?.enforcement === 'dry-run') return bundle.enforcement;\n  if (options?.mode === 'block') return 'block';\n  if (options?.mode === 'dry-run') return 'dry-run';\n  return 'dry-run';\n}\n\n/**\n * WP-format api_key for connector /api/logs/log. Never use the public site UUID.\n * The `.patchstackrc.json` fallback reads the filesystem, so fs/path are imported LAZILY — this\n * module must stay loadable on edge runtimes (Next edge middleware, Workers, Deno, Supabase\n * Functions), where a static `node:fs` import fails to resolve and would take the guard down.\n */\nasync function resolveApiKey(options) {\n  if (typeof options?.apiKey === 'string' && options.apiKey.length > 0) return options.apiKey;\n  if (typeof process !== 'undefined') {\n    const fromEnv = process.env?.PATCHSTACK_API_KEY;\n    if (typeof fromEnv === 'string' && fromEnv.length > 0) return fromEnv;\n  }\n  try {\n    if (typeof process === 'undefined' || typeof process.cwd !== 'function') return undefined;\n    const [{ readFileSync }, { join }] = await Promise.all([import('node:fs'), import('node:path')]);\n    const cwd = options?.cwd ?? process.cwd();\n    const raw = readFileSync(join(cwd, '.patchstackrc.json'), 'utf8');\n    const key = JSON.parse(raw)?.apiKey;\n    if (typeof key === 'string' && key.length > 0) return key;\n  } catch {\n    /* missing, or no filesystem on this runtime — reporting stays off */\n  }\n  return undefined;\n}\n\n/**\n * Credential for the authenticated rules lookup (ADR-0018). Same resolution\n * order and the same edge-runtime caution as resolveApiKey, and falls back to\n * it so guards installed before pulseAuth existed keep authenticating.\n *\n * Returning undefined is fine: the rules fetch then goes out unauthenticated,\n * which the server still accepts.\n */\nasync function resolvePulseAuth(options) {\n  if (typeof options?.pulseAuth === 'string' && options.pulseAuth.length > 0) return options.pulseAuth;\n  if (typeof process !== 'undefined') {\n    const fromEnv = process.env?.PATCHSTACK_PULSE_AUTH;\n    if (typeof fromEnv === 'string' && fromEnv.length > 0) return fromEnv;\n  }\n  try {\n    if (typeof process === 'undefined' || typeof process.cwd !== 'function') return resolveApiKey(options);\n    const [{ readFileSync }, { join }] = await Promise.all([import('node:fs'), import('node:path')]);\n    const cwd = options?.cwd ?? process.cwd();\n    const raw = readFileSync(join(cwd, '.patchstackrc.json'), 'utf8');\n    const key = JSON.parse(raw)?.pulseAuth;\n    if (typeof key === 'string' && key.length > 0) return key;\n  } catch {\n    /* missing, or no filesystem here — fall through to the apiKey path */\n  }\n\n  return resolveApiKey(options);\n}\n\n// --- phase / response helpers -------------------------------------------\n\nfunction byPhase(rules, phase) {\n  return (rules ?? []).filter((r) => (r.phase ?? 'request') === phase);\n}\n\n// Classify a content-type for response screening: 'text' = screen; 'sniff' = screen only if the\n// bytes aren't binary (octet-stream is often a misdeclared JSON export/config); 'skip' = pass\n// through unscreened (live streams, known binary families). SSE is matched on the EXACT base type,\n// not a loose substring — `application/json; profile=\"event-stream\"` is not a stream.\nfunction baseContentType(ct) {\n  return String(ct || '').toLowerCase().split(';')[0].trim();\n}\nfunction screenableContentType(ct) {\n  const base = baseContentType(ct);\n  if (base === 'text/event-stream') return 'skip'; // live token/SSE stream — never buffer\n  if (base === '') return 'text';\n  if (/(json|text|xml|html|javascript|csv|yaml|x-www-form-urlencoded)/.test(base)) return 'text';\n  if (base === 'application/octet-stream') return 'sniff'; // maybe a text/JSON export mislabeled\n  return 'skip'; // image/video/audio/font/pdf/zip/wasm/… — don't buffer binary\n}\n// Cheap binary sniff over a byte prefix: a NUL byte, or many control chars, means \"don't treat as text\".\nfunction looksBinary(bytes) {\n  const n = Math.min(bytes.length, 512);\n  let ctrl = 0;\n  for (let i = 0; i < n; i++) {\n    const b = bytes[i];\n    if (b === 0) return true;\n    if (b < 9 || (b > 13 && b < 32)) ctrl++;\n  }\n  return n > 0 && ctrl / n > 0.1;\n}\n\n// Returns { text } when the body was fully buffered for screening, or { skip: <reason> } when it was\n// NOT screened — the reason is surfaced to `onSkip`/coverage so a fail-open bypass is observable\n// instead of silent (an unscreened response is a real hole in enforcement).\nasync function readTextResponse(response, cap = DEFAULT_SCREEN_CAP) {\n  if (!response || typeof response.clone !== 'function') return { skip: 'not-a-response' };\n  const ct = response.headers?.get?.('content-type') || '';\n  const kind = screenableContentType(ct);\n  if (kind === 'skip') return { skip: baseContentType(ct) === 'text/event-stream' ? 'live-stream' : 'non-text-content-type' };\n  const sniff = kind === 'sniff';\n  const len = Number(response.headers?.get?.('content-length') || 0);\n  if (len && len > cap) return { skip: 'body-cap' };\n  let clone;\n  try {\n    clone = response.clone();\n  } catch {\n    return { skip: 'clone-failed' };\n  }\n\n  // Stream the read so a body WITHOUT a Content-Length can't buffer past the cap. Over the cap the\n  // response is left UNSCREENED — but we keep draining the clone so the original stays intact.\n  const body = clone.body;\n  if (body && typeof body.getReader === 'function') {\n    const reader = body.getReader();\n    const chunks = [];\n    let size = 0;\n    let over = false;\n    let sniffed = !sniff;\n    try {\n      for (;;) {\n        const { done, value } = await reader.read();\n        if (done) break;\n        if (!value) continue;\n        if (!sniffed) {\n          sniffed = true;\n          if (looksBinary(value)) return { skip: 'binary-body' };\n        }\n        size += value.byteLength;\n        if (over) continue; // keep draining, stop buffering\n        if (size > cap) { over = true; continue; }\n        chunks.push(value);\n      }\n    } catch {\n      return { skip: 'read-failed' };\n    }\n    if (over) return { skip: 'body-cap' };\n    try {\n      return { text: new TextDecoder().decode(concatBytes(chunks, size)) };\n    } catch {\n      return { skip: 'decode-failed' };\n    }\n  }\n\n  try {\n    const text = await clone.text();\n    if (text.length > cap) return { skip: 'body-cap' };\n    if (sniff && looksBinary(new TextEncoder().encode(text.slice(0, 512)))) return { skip: 'binary-body' };\n    return { text };\n  } catch {\n    return { skip: 'read-failed' };\n  }\n}\n\nfunction concatBytes(chunks, total) {\n  const out = new Uint8Array(total);\n  let offset = 0;\n  for (const c of chunks) {\n    out.set(c, offset);\n    offset += c.byteLength;\n  }\n  return out;\n}\n\nfunction headerObject(headers) {\n  const out = {};\n  headers?.forEach?.((v, k) => { out[k.toLowerCase()] = v; });\n  // Set-Cookie is multi-valued; forEach collapses it. Recover the individual cookies so each can\n  // be screened (and re-emitted) separately.\n  const setCookies = headers?.getSetCookie?.();\n  if (setCookies && setCookies.length) out['set-cookie'] = setCookies;\n  return out;\n}\n\n// True if any of the rule's conditions carries a body-transforming mutation on a SPAN match\n// (regex/contains/stripos) — those decode the body before matching, so a span redactor derived from\n// the literal/regex can't be located in the raw body. (array_key_value structural redaction decodes\n// the JSON itself, so json_decode there is fine and doesn't count.)\nfunction hasSpanMutations(rule) {\n  let found = false;\n  const walk = (conds) => {\n    for (const c of conds ?? []) {\n      if (found) return;\n      if (Array.isArray(c.rules)) walk(c.rules);\n      const isSpan = c.match && (c.match.type === 'regex' || c.match.type === 'contains' || c.match.type === 'stripos');\n      if (isSpan && Array.isArray(c.mutations) && c.mutations.length) found = true;\n    }\n  };\n  walk(rule.rule_v2);\n  return found;\n}\n\n// Derive redaction targets from a rule's own conditions: regex → mask every match;\n// contains/stripos → mask the literal. (Other match types can't identify a span → the\n// rule falls back to block.)\nfunction extractRedactors(rule) {\n  const out = [];\n  const walk = (conds) => {\n    for (const c of conds ?? []) {\n      if (Array.isArray(c.rules)) walk(c.rules);\n      const m = c.match;\n      if (!m) continue;\n      if (m.type === 'regex' && typeof m.value === 'string') {\n        // Route through the SAME ReDoS guard detection uses — a catastrophic redactor pattern must\n        // not hang the response path (safeRegExp returns null for dangerous/invalid patterns → skip).\n        const safe = safeRegExp(m.value);\n        if (safe) {\n          const flags = safe.flags.includes('g') ? safe.flags : safe.flags + 'g';\n          try {\n            out.push({ re: new RegExp(safe.source, flags) });\n          } catch {\n            /* skip invalid */\n          }\n        }\n      } else if ((m.type === 'contains' || m.type === 'stripos') && m.value != null) {\n        out.push({ literal: String(m.value) });\n      } else if (m.type === 'array_key_value' && m.match && isBodyParam(c.parameter)) {\n        // Structural redaction: mask the value at a JSON path (fanning out over arrays) rather than\n        // a text span — e.g. key \"orders.customers.email\" masks that field in every array element.\n        const keys = Array.isArray(m.key) ? m.key : [m.key];\n        for (const key of keys) {\n          out.push({ jsonPath: String(key).split('.'), condition: m.match });\n        }\n      }\n    }\n  };\n  walk(rule.rule_v2);\n  return out;\n}\n\n// HTML-entity escape, for the `encode` action (neutralize markup rather than mask it). NOTE: this is\n// sound only for HTML text / attribute-VALUE contexts. It does NOT neutralize a `javascript:` / `data:`\n// URI or an event-handler name (those carry no HTML metacharacters) — use `block` for a rule that\n// targets a URL/scheme context. See the rule-authoring guidance in the triage-vpatch-npm skill.\nfunction htmlEscape(str) {\n  return String(str).replace(/[&<>\"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' })[c]);\n}\n\n// `transform` (optional): map a matched span to its replacement (the `encode` action passes\n// htmlEscape). Without it, matches are replaced by the `mask` string (the `redact` action).\nfunction applyRedactors(body, redactors, mask, transform) {\n  let out = body;\n  for (const r of redactors) {\n    if (r.re) out = out.replace(r.re, transform ? (m) => transform(m) : mask);\n    else if (r.literal) {\n      // Detection (matchValue for contains/stripos) is case-insensitive, so mask case-insensitively\n      // too — otherwise a `contains: \"SECRET\"` redactor detects `secret` but masks nothing, serving\n      // the leak while reporting a redaction. Escape the literal so it matches literally, not as regex.\n      const re = new RegExp(r.literal.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'gi');\n      out = out.replace(re, (m) => (transform ? transform(m) : mask));\n    }\n  }\n  return out;\n}\n\n// A response-body redaction target (array_key_value masks the JSON body). A bare condition with no\n// parameter also defaults to the body.\nfunction isBodyParam(parameter) {\n  return parameter == null || parameter === 'response.body' || parameter === 'raw' || parameter === 'response.raw';\n}\n\n// Build a predicate from the array_key_value nested match, so a path can be masked conditionally\n// (only leaves that match) or — with `isset` — unconditionally. Fail-closed (don't mask) on error.\nfunction conditionPredicate(condition) {\n  if (!condition || !condition.type) return () => true;\n  return (value) => {\n    try {\n      return matchValue(condition.type, value, condition.value, condition);\n    } catch {\n      return false;\n    }\n  };\n}\n\nconst DEFAULT_SCREEN_CAP = 512 * 1024;\n\n// Effective response-screening size cap for a rule set. Bodies larger than this are passed through\n// UNSCREENED (so a redact rule can't mask them — the leak/PII would slip out). A rule can raise the\n// ceiling for the whole response phase: `bypass_limit: true` removes the cap entirely (accepts the\n// memory cost on a hostile large body), or `max_bytes: <n>` raises it to n. The cap is shared (the\n// body is buffered once), so the effective cap is the MAX across all active response rules.\nfunction responseScreenCap(rules) {\n  let cap = DEFAULT_SCREEN_CAP;\n  for (const r of rules ?? []) {\n    if (r && r.bypass_limit === true) return Infinity;\n    const n = Number(r && r.max_bytes);\n    if (Number.isFinite(n) && n > cap) cap = n;\n  }\n  return cap;\n}\n\n// Apply jsonPath redactors structurally: parse the JSON body, mask each targeted leaf (fanning out\n// over arrays at every path segment), re-serialize. Fail-open — a non-JSON / oversized / unparseable\n// body is returned unchanged, and any per-leaf error is swallowed.\nfunction applyPathRedactors(text, pathRedactors, mask, cap, transform) {\n  if (!pathRedactors.length || typeof text !== 'string' || text.length > cap) return text;\n  const head = text.trimStart()[0];\n  if (head !== '{' && head !== '[') return text; // not a JSON object/array\n  // Preserve out-of-safe-range integers across the parse→stringify round-trip: JSON.parse would\n  // round e.g. a 20-digit id. We quote such number tokens to a sentinel string before parsing and\n  // unquote them after stringifying, so untouched big ints survive losslessly.\n  const preserved = preserveBigInts(text);\n  let obj;\n  try {\n    obj = JSON.parse(preserved);\n  } catch {\n    return text;\n  }\n  let changed = false;\n  for (const r of pathRedactors) {\n    const pred = conditionPredicate(r.condition);\n    walkLeaves(obj, r.jsonPath, (loc) => {\n      try {\n        if (pred(loc.value)) {\n          // `encode`: escape the leaf's own value in place; `redact`: replace it with the mask.\n          loc.parent[loc.key] = transform ? transform(String(loc.value)) : mask;\n          changed = true;\n        }\n      } catch {\n        /* skip this leaf */\n      }\n    });\n  }\n  return changed ? restoreBigInts(JSON.stringify(obj)) : text;\n}\n\nconst BIGINT_OPEN = '__PSBIGINT_9c2f__';\nconst BIGINT_CLOSE = '__DNEGIB__';\n\n// Quote every out-of-safe-range integer *value* (a bare number token outside a string) into a\n// sentinel string, so JSON.parse keeps it verbatim. String-aware scan (respects \\ escapes) so a\n// number inside a string value is never touched. Plain-ASCII sentinel → survives JSON.stringify.\nfunction preserveBigInts(text) {\n  let out = '';\n  let inStr = false;\n  for (let i = 0; i < text.length; ) {\n    const ch = text[i];\n    if (inStr) {\n      out += ch;\n      if (ch === '\\\\') { out += text[i + 1] ?? ''; i += 2; continue; }\n      if (ch === '\"') inStr = false;\n      i++;\n      continue;\n    }\n    if (ch === '\"') { inStr = true; out += ch; i++; continue; }\n    if (ch === '-' || (ch >= '0' && ch <= '9')) {\n      let j = ch === '-' ? i + 1 : i;\n      let digits = 0;\n      while (j < text.length && text[j] >= '0' && text[j] <= '9') { digits++; j++; }\n      const next = text[j];\n      const isIntToken = digits > 0 && next !== '.' && next !== 'e' && next !== 'E';\n      if (isIntToken && digits >= 16) {\n        out += `\"${BIGINT_OPEN}${text.slice(i, j)}${BIGINT_CLOSE}\"`;\n      } else {\n        out += text.slice(i, j || i + 1);\n      }\n      i = j > i ? j : i + 1;\n      continue;\n    }\n    out += ch;\n    i++;\n  }\n  return out;\n}\n\nfunction restoreBigInts(text) {\n  if (!text.includes(BIGINT_OPEN)) return text;\n  return text.replace(new RegExp(`\"${BIGINT_OPEN}(-?\\\\d+)${BIGINT_CLOSE}\"`, 'g'), '$1');\n}\n\n// Response-hardening actions. Mutate the (lowercase-keyed) headers object in place; a `null` value\n// signals removal to rebuildResponse / the node path. `set-header` sets/overwrites (or `ensure`s only\n// when absent); `remove-header` strips; `harden-cookie` adds missing HttpOnly/Secure/SameSite flags.\nfunction isHeaderMutation(action) {\n  return action === 'set-header' || action === 'remove-header' || action === 'harden-cookie';\n}\n\nfunction applyHeaderMutation(headers, rule) {\n  if (rule.action === 'remove-header') {\n    for (const name of rule.remove_headers ?? []) headers[String(name).toLowerCase()] = null;\n    return;\n  }\n  if (rule.action === 'set-header') {\n    const ensure = rule.ensure === true; // set only when the header is absent (don't clobber)\n    for (const [name, value] of Object.entries(rule.set_headers ?? {})) {\n      const key = String(name).toLowerCase();\n      const present = headers[key] != null && headers[key] !== '';\n      if (ensure && present) continue;\n      headers[key] = String(value);\n    }\n    return;\n  }\n  if (rule.action === 'harden-cookie') {\n    const cookie = headers['set-cookie'];\n    const flags = rule.cookie_flags ?? {};\n    if (Array.isArray(cookie)) {\n      headers['set-cookie'] = cookie.map((c) => (typeof c === 'string' ? hardenCookie(c, flags) : c));\n    } else if (typeof cookie === 'string') {\n      headers['set-cookie'] = hardenCookie(cookie, flags);\n    }\n  }\n}\n\nfunction hardenCookie(cookie, { httpOnly = true, secure = true, sameSite = 'Lax' } = {}) {\n  let out = String(cookie);\n  if (httpOnly && !/;\\s*httponly/i.test(out)) out += '; HttpOnly';\n  if (secure && !/;\\s*secure/i.test(out)) out += '; Secure';\n  if (sameSite && !/;\\s*samesite\\s*=/i.test(out)) out += `; SameSite=${sameSite}`;\n  return out;\n}\n\nfunction rebuildResponse(response, body, redactedHeaders) {\n  const headers = new Headers(response.headers);\n  headers.delete('content-length'); // body length changed after redaction\n  if (redactedHeaders) {\n    for (const [name, value] of Object.entries(redactedHeaders)) {\n      if (value === null || value === undefined) {\n        try { headers.delete(name); } catch { /* skip */ } // header-mutation removal\n      } else if (typeof value === 'string') {\n        if (headers.get(name) !== value) {\n          try { headers.set(name, value); } catch { /* invalid header name — skip */ }\n        }\n      } else if (Array.isArray(value)) {\n        // Re-emit each (possibly redacted) Set-Cookie separately (Headers collapses them otherwise).\n        try {\n          headers.delete(name);\n          for (const item of value) headers.append(name, String(item));\n        } catch { /* skip */ }\n      }\n    }\n  }\n  // Null-body statuses (204/205/304/101) must not carry a body, or the Response constructor throws.\n  const nullBody = response.status === 101 || response.status === 204 || response.status === 205 || response.status === 304;\n  return new Response(nullBody ? null : body, { status: response.status, statusText: response.statusText, headers });\n}\n\nfunction leakResponse() {\n  return new Response(JSON.stringify({ error: 'Response withheld by Patchstack (sensitive data detected)' }), {\n    status: 500,\n    headers: { 'content-type': 'application/json' }\n  });\n}\n\n// (rule source / tiered store moved to ./rules/source.js + ./rules/store.js)\n\n// --- responses ----------------------------------------------------------\n\n// Client-facing block text — deliberately generic: no WAF narrative, no rule title. The reason\n// detail stays in the server-side log via onDetect.\nconst BLOCK_MESSAGE = 'This request has been blocked by Patchstack.';\n\nfunction blockBody(result) {\n  // Human text is masked (no WAF narrative, no rule title). The opaque rule id stays for machine\n  // consumers (server-fn receipts, support reference); full rule detail lives in the server log.\n  return { error: BLOCK_MESSAGE, message: BLOCK_MESSAGE, rule: result?.rule?.id };\n}\n\n// A top-level document navigation (vs an XHR/fetch)? Browsers set Sec-Fetch-Dest on navigations;\n// fall back to the Accept header. Governs whether a block returns the HTML page or JSON.\nfunction isDocumentNavigation(getHeader) {\n  const dest = getHeader('sec-fetch-dest');\n  if (dest) return dest === 'document';\n  return (getHeader('accept') || '').includes('text/html');\n}\n\n// Request-phase block. Serves the branded HTML \"Access Denied\" page to a browser navigation, and\n// masked JSON to XHR/fetch/programmatic clients.\nfunction blockResponse(result, request) {\n  if (request && isDocumentNavigation((n) => request.headers.get(n))) {\n    return new Response(renderBlockPage({ url: request.url, code: result?.rule?.id }), {\n      status: 403,\n      headers: { 'content-type': 'text/html; charset=utf-8' },\n    });\n  }\n  return new Response(JSON.stringify(blockBody(result)), {\n    status: 403,\n    headers: { 'content-type': 'application/json' },\n  });\n}\n\nfunction defaultOnDetect({ phase, mode, category, rule, message }) {\n  const tag = mode === 'block' ? 'BLOCK' : 'DETECT (dry-run)';\n  console.warn(`[patchstack] ${tag} phase=${phase ?? 'request'} category=${category ?? '?'} rule=${rule?.id ?? '?'} ${message ?? ''}`.trim());\n}\n\n/** @param {Request} request */\nfunction fetchRequestMeta(request) {\n  if (!request) return {};\n  let path = null;\n  try {\n    path = new URL(request.url).pathname;\n  } catch {\n    path = typeof request.url === 'string' ? request.url : null;\n  }\n  return {\n    method: request.method ?? null,\n    path,\n    ip: request.headers?.get?.('x-forwarded-for') ?? null,\n    userAgent: request.headers?.get?.('user-agent') ?? null,\n  };\n}\n\n/** @param {import('http').IncomingMessage & { ip?: string, originalUrl?: string }} req */\nfunction nodeRequestMeta(req) {\n  if (!req) return {};\n  const headers = req.headers ?? {};\n  const ua = headers['user-agent'] ?? headers['User-Agent'];\n  const fwd = headers['x-forwarded-for'] ?? headers['X-Forwarded-For'];\n  return {\n    method: req.method ?? null,\n    path: req.originalUrl || req.url || null,\n    ip: req.ip ?? (typeof fwd === 'string' ? fwd : null),\n    userAgent: typeof ua === 'string' ? ua : Array.isArray(ua) ? ua[0] : null,\n  };\n}\n","// Which origins this guard is willing to talk to. Both of its remote conversations are security\n// sensitive: the RULE endpoint delivers policy the engine then executes on every request (an\n// attacker-controlled endpoint could remove protection wholesale or serve a CPU-expensive ruleset), and\n// the telemetry endpoint receives the site api_key. Env/CI injection is the realistic threat, so a\n// non-default override must be https — with localhost permitted so local development and tests work.\nexport function isSafeOrigin(value) {\n  try {\n    const u = new URL(value);\n    if (u.protocol === 'https:') return true;\n    return u.protocol === 'http:' && (u.hostname === 'localhost' || u.hostname === '127.0.0.1' || u.hostname === '[::1]' || u.hostname === '::1');\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Accept `candidate` only if it is a safe origin; otherwise warn once and fall back to `fallback`.\n * @param {string|undefined} candidate @param {string} fallback @param {string} label\n */\nexport function safeBaseUrl(candidate, fallback, label) {\n  if (typeof candidate !== 'string' || candidate === '') return fallback;\n  if (isSafeOrigin(candidate)) return candidate;\n  warnOnce(label, `[patchstack] ignoring unsafe ${label} override (${candidate}): must be https (or localhost). Using the default.`);\n  return fallback;\n}\n\nconst warned = new Set();\nfunction warnOnce(key, message) {\n  if (warned.has(key)) return;\n  warned.add(key);\n  // eslint-disable-next-line no-console\n  console.warn(message);\n}\n","import { safeBaseUrl } from '../safe-origin.js';\n\nconst DEFAULT_BASE_URL = 'https://api.patchstack.com';\nconst DEFAULT_CACHE_TTL = 300_000;\n// Randomly shorten the effective TTL by up to this fraction so many long-lived clients don't all\n// revalidate on the same tick (spreads load against the rules API).\nconst JITTER_FRACTION = 0.1;\n\n// Token-authenticated rules client. Conditional fetch (If-None-Match / 304) and the persisted\n// `etag` mirror PulseRuleClient; both are a no-op until the API emits an ETag and honors the\n// conditional request — with no ETag in the response the client behaves as before (full fetch).\nexport class PatchstackRuleClient {\n  #token;\n  #baseUrl;\n  #cacheTtl;\n  #cache = null;\n  #cacheTime = null;\n  #ttlEffective = 0;\n  #etag;\n  #timeoutMs;\n\n  constructor({ token, baseUrl, cacheTtl, etag, timeoutMs } = {}) {\n    // Bounded so app STARTUP can't hang on a slow API (see the boot budget in rules/source.js).\n    this.#timeoutMs = Number(timeoutMs) > 0 ? Number(timeoutMs) : 30_000;\n    this.#token = token ?? process.env.PATCHSTACK_WAF_TOKEN;\n    this.#baseUrl = safeBaseUrl(baseUrl ?? process.env.PATCHSTACK_WAF_API_URL, DEFAULT_BASE_URL, 'rule endpoint');\n    this.#cacheTtl = Number.isFinite(cacheTtl) && cacheTtl > 0 ? cacheTtl : DEFAULT_CACHE_TTL;\n    this.#etag = etag ?? null;\n\n    if (!this.#token) {\n      throw new Error('Patchstack WAF token is required. Pass { token } or set PATCHSTACK_WAF_TOKEN env var.');\n    }\n  }\n\n  async getRules() {\n    const now = Date.now();\n\n    if (this.#cache && this.#cacheTime !== null && (now - this.#cacheTime) < this.#ttlEffective) {\n      return this.#cache;\n    }\n\n    const url = `${this.#baseUrl}/api/get-rules/3`;\n\n    try {\n      const headers = {\n        'Content-Type': 'application/json',\n        'Authorization': `Bearer ${this.#token}`,\n        'LicenseID': '1' // Hard-coded, is never actually used but needed by the API\n      };\n      if (this.#etag) headers['If-None-Match'] = this.#etag;\n\n      const response = await fetch(url, {\n        method: 'POST',\n        headers,\n        body: JSON.stringify({}),\n        signal: AbortSignal.timeout(this.#timeoutMs)\n      });\n\n      if (response.status === 304) {\n        this.#touch(now); // revalidated — reset the clock (fresh jitter)\n        return this.#cache ?? { success: true, notModified: true, etag: this.#etag, firewall: [], whitelists: [], whitelist_keys: {} };\n      }\n\n      if (!response.ok) {\n        return {\n          success: false,\n          error: `API returned ${response.status}: ${response.statusText}`,\n          firewall: [],\n          whitelists: [],\n          whitelist_keys: {}\n        };\n      }\n\n      const data = await response.json();\n\n      // A 200 that isn't a genuine rule envelope must not be treated as \"no rules\". Report failure\n      // so the caller falls back to the cache / bundled rules rather than caching an empty bundle.\n      if (!data || !Array.isArray(data.firewall)) {\n        return { success: false, error: 'unexpected response shape (no firewall array)', firewall: [], whitelists: [], whitelist_keys: {} };\n      }\n\n      const result = {\n        success: true,\n        notModified: false,\n        etag: response.headers?.get?.('etag') ?? null,\n        firewall: data.firewall,\n        whitelists: Array.isArray(data.whitelists) ? data.whitelists : [],\n        whitelist_keys: data.whitelist_keys ?? {}\n      };\n\n      this.#cache = result;\n      this.#etag = result.etag;\n      this.#touch(now);\n\n      return result;\n    } catch (err) {\n      return {\n        success: false,\n        error: err.name === 'TimeoutError'\n          ? 'Request timed out'\n          : err.message,\n        firewall: [],\n        whitelists: [],\n        whitelist_keys: {}\n      };\n    }\n  }\n\n  #touch(now) {\n    this.#cacheTime = now;\n    this.#ttlEffective = this.#cacheTtl - Math.floor(Math.random() * this.#cacheTtl * JITTER_FRACTION);\n  }\n\n  clearCache() {\n    this.#cache = null;\n    this.#cacheTime = null;\n    this.#etag = null;\n  }\n}\n","// Resolvable DATA attributes of an uploaded file part (files.<name>.<attr>). The engine only exposes\n// the raw data — WHAT counts as a malicious upload (signatures, type-vs-content mismatch) is expressed\n// in rules (see the triage-vpatch-npm skill), not hardcoded here.\nconst FILE_ATTRS = new Set(['content', 'filename', 'type']);\n\n// A captured file part is { filename, type, content }; tolerate the legacy bare-filename string.\nconst fileFilename = (f) => (f && typeof f === 'object' ? f.filename : f);\nconst fileAttribute = (f, attr) => (f && typeof f === 'object' ? f[attr] : attr === 'filename' ? f : undefined);\n\n// WinterCG-safe base64 decode: use Buffer on Node, fall back to atob/TextDecoder on\n// edge runtimes (Cloudflare Workers, Deno, Bun) where Buffer may be absent. Keeps the\n// engine hot path free of Node-only APIs (per the ADR engine-language decision).\nfunction base64DecodeUtf8(value) {\n  const str = String(value);\n  if (typeof Buffer !== 'undefined') {\n    return Buffer.from(str, 'base64').toString('utf-8');\n  }\n  const binary = atob(str);\n  const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0));\n  return new TextDecoder().decode(bytes);\n}\n\nexport class RequestResolver {\n  #req;\n  #cookies;\n\n  constructor(req) {\n    this.#req = req;\n    this.#cookies = null;\n  }\n\n  resolve(parameter) {\n    if (!parameter || parameter === 'false') {\n      return [null];\n    }\n\n    if (parameter === 'rules') {\n      return [null];\n    }\n\n    if (parameter === 'raw') {\n      return this.#resolveRaw();\n    }\n\n    if (parameter === 'all') {\n      return this.#resolveAll();\n    }\n\n    const dotIndex = parameter.indexOf('.');\n    if (dotIndex === -1) {\n      return [];\n    }\n\n    const source = parameter.substring(0, dotIndex);\n    const key = parameter.substring(dotIndex + 1);\n\n    switch (source) {\n      case 'get':\n        return this.#resolveGet(key);\n      case 'post':\n        return this.#resolvePost(key);\n      case 'request':\n        return this.#resolveRequest(key);\n      case 'cookie':\n        return this.#resolveCookie(key);\n      case 'server':\n        return this.#resolveServer(key);\n      case 'files':\n        return this.#resolveFiles(key);\n      case 'response':\n        return this.#resolveResponse(key);\n      case 'egress':\n        return this.#resolveEgress(key);\n      default:\n        return [];\n    }\n  }\n\n  // Response-phase sources (req._response = { status, headers, body }). Lets rules inspect\n  // what the app is about to SEND — e.g. a leaked secret in the body — regardless of route.\n  #resolveResponse(key) {\n    const resp = this.#req._response;\n    if (!resp) {\n      return [];\n    }\n    if (key === 'status') {\n      return resp.status !== undefined ? [String(resp.status)] : [];\n    }\n    if (key === 'body') {\n      return resp.body != null && resp.body !== '' ? [resp.body] : [];\n    }\n    if (key === 'headers') {\n      const headers = resp.headers ?? {};\n      return [Object.entries(headers).map(([k, v]) => `${k}: ${v}`).join('\\n')];\n    }\n    if (key.startsWith('header.')) {\n      const name = key.slice('header.'.length).toLowerCase();\n      const value = (resp.headers ?? {})[name];\n      return value !== undefined ? [value] : [];\n    }\n    return [];\n  }\n\n  // Egress-phase sources (req._egress = { url, host, method }). Lets rules inspect an\n  // OUTBOUND request the app is about to make — SSRF at the egress boundary.\n  #resolveEgress(key) {\n    const eg = this.#req._egress;\n    if (!eg) {\n      return [];\n    }\n    if (key === 'url') return eg.url ? [eg.url] : [];\n    if (key === 'host') return eg.host ? [eg.host] : [];\n    if (key === 'method') return eg.method ? [eg.method] : [];\n    return [];\n  }\n\n  applyMutations(mutations, value) {\n    if (!mutations || !Array.isArray(mutations)) {\n      return value;\n    }\n\n    let result = value;\n\n    for (const mutation of mutations) {\n      result = this.#applyMutation(mutation, result);\n    }\n\n    return result;\n  }\n\n  #applyMutation(mutation, value) {\n    if (value === null || value === undefined) {\n      return value;\n    }\n\n    switch (mutation) {\n      case 'base64_decode':\n        try {\n          return base64DecodeUtf8(value);\n        } catch {\n          return value;\n        }\n\n      case 'json_decode':\n        try {\n          return JSON.parse(String(value));\n        } catch {\n          return value;\n        }\n\n      case 'json_encode':\n        try {\n          return JSON.stringify(value);\n        } catch {\n          return value;\n        }\n\n      case 'urldecode':\n        try {\n          return decodeURIComponent(String(value));\n        } catch {\n          return value;\n        }\n\n      case 'intval':\n        return parseInt(String(value), 10) || 0;\n\n      case 'getArrayValues':\n        if (typeof value === 'object' && value !== null) {\n          return Object.values(value);\n        }\n        return value;\n\n      default:\n        return value;\n    }\n  }\n\n  #resolveGet(key) {\n    const query = this.#req.query ?? {};\n\n    if (key.endsWith('*')) {\n      return this.#resolveWildcard(query, key);\n    }\n\n    const value = this.#getNestedValue(query, key);\n    return value !== undefined ? [value] : [];\n  }\n\n  #resolvePost(key) {\n    const body = this.#req.body ?? {};\n\n    if (key.endsWith('*')) {\n      return this.#resolveWildcard(body, key);\n    }\n\n    const value = this.#getNestedValue(body, key);\n    return value !== undefined ? [value] : [];\n  }\n\n  #resolveRequest(key) {\n    const query = this.#req.query ?? {};\n    const body = this.#req.body ?? {};\n    const cookies = this.#parseCookies();\n\n    if (key.endsWith('*')) {\n      return [\n        ...this.#resolveWildcard(query, key),\n        ...this.#resolveWildcard(body, key),\n        ...this.#resolveWildcard(cookies, key)\n      ];\n    }\n\n    const value = this.#getNestedValue(query, key)\n      ?? this.#getNestedValue(body, key)\n      ?? cookies[key];\n\n    return value !== undefined ? [value] : [];\n  }\n\n  #resolveCookie(key) {\n    const cookies = this.#parseCookies();\n\n    if (key.endsWith('*')) {\n      return this.#resolveWildcard(cookies, key);\n    }\n\n    const value = cookies[key];\n    return value !== undefined ? [value] : [];\n  }\n\n  #resolveServer(key) {\n    const req = this.#req;\n\n    switch (key) {\n      case 'REQUEST_URI':\n        return [req.originalUrl ?? req.url ?? '/'];\n      case 'REQUEST_METHOD':\n        return [req.method ?? 'GET'];\n      case 'HTTP_USER_AGENT':\n        return req.headers?.['user-agent'] ? [req.headers['user-agent']] : [];\n      case 'HTTP_REFERER':\n        return req.headers?.referer ? [req.headers.referer] : [];\n      case 'HTTP_HOST':\n        return req.headers?.host ? [req.headers.host] : [];\n      case 'REMOTE_ADDR':\n      case 'ip':\n        return [req.ip ?? req.socket?.remoteAddress ?? ''];\n      case 'CONTENT_TYPE':\n        return req.headers?.['content-type'] ? [req.headers['content-type']] : [];\n      case 'CONTENT_LENGTH':\n        return req.headers?.['content-length'] ? [req.headers['content-length']] : [];\n      default: {\n        if (key.startsWith('HTTP_')) {\n          const headerName = key.substring(5).toLowerCase().replace(/_/g, '-');\n          const headers = req.headers;\n          // Presence, not truthiness. A header sent with an empty value IS present, and an `isset`\n          // rule authored against it must see it — some bypasses are carried by the header existing\n          // at all, so treating `Header:` as absent would make the rule quietly miss the shape it\n          // was written for. (The named cases above keep value semantics: for host/origin/referer an\n          // empty string and an absent header mean the same thing to the matchers that read them.)\n          if (headers === null || typeof headers !== 'object') return [];\n          return Object.prototype.hasOwnProperty.call(headers, headerName) ? [headers[headerName]] : [];\n        }\n        return [];\n      }\n    }\n  }\n\n  #resolveFiles(key) {\n    const files = this.#req.files;\n    if (!files || typeof files !== 'object') {\n      return [];\n    }\n\n    // files.<name>.<attr> — content | filename | type. Fans out over multiple files uploaded under\n    // the same field name.\n    const dot = key.lastIndexOf('.');\n    if (dot !== -1 && FILE_ATTRS.has(key.slice(dot + 1)) && Object.prototype.hasOwnProperty.call(files, key.slice(0, dot))) {\n      const attr = key.slice(dot + 1);\n      const entry = files[key.slice(0, dot)];\n      const list = Array.isArray(entry) ? entry : [entry];\n      const out = [];\n      for (const f of list) {\n        const v = fileAttribute(f, attr);\n        if (v !== undefined && v !== '') out.push(v);\n      }\n      return out;\n    }\n\n    // Bare files.<name> (or wildcard) → the filename(s), preserving the legacy behavior that\n    // filename-scoped rules rely on (the parser now stores a { filename, type, content } object).\n    const filenamesOf = (entry) => (Array.isArray(entry) ? entry.map(fileFilename) : [fileFilename(entry)]);\n    if (key.endsWith('*')) {\n      const prefix = key.slice(0, -1);\n      const out = [];\n      for (const [k, entry] of Object.entries(files)) {\n        if (k.startsWith(prefix)) out.push(...filenamesOf(entry));\n      }\n      return out.filter((v) => v !== undefined);\n    }\n    if (!Object.prototype.hasOwnProperty.call(files, key)) return [];\n    return filenamesOf(files[key]).filter((v) => v !== undefined);\n  }\n\n  #resolveRaw() {\n    // Use pre-captured raw body if available (set by normalizeRequest).\n    // For string bodies, the original text is preserved verbatim.\n    // For pre-parsed objects, serializeForRawDetection uses Object.getOwnPropertyNames()\n    // to include __proto__ own-property keys that JSON.stringify() would silently drop.\n    if (typeof this.#req._rawBody === 'string') {\n      return this.#req._rawBody ? [this.#req._rawBody] : [];\n    }\n\n    const body = this.#req.body;\n\n    if (body === undefined || body === null) {\n      return [];\n    }\n\n    if (typeof body === 'string') {\n      return [body];\n    }\n\n    try {\n      return [JSON.stringify(body)];\n    } catch {\n      return [String(body)];\n    }\n  }\n\n  #resolveAll() {\n    const parts = [];\n\n    const uri = this.#req.originalUrl ?? this.#req.url ?? '/';\n    parts.push(uri);\n\n    const queryString = uri.includes('?') ? uri.split('?')[1] : '';\n    if (queryString) {\n      parts.push(queryString);\n    }\n\n    const body = this.#req.body;\n    if (body) {\n      parts.push(typeof body === 'string' ? body : JSON.stringify(body));\n    }\n    // Also fold in the verbatim body: a body the adapter couldn't structurally parse (an unusual\n    // content-type, a non-JSON payload) leaves `body` empty, but the raw text must still be matchable\n    // by an `all` rule — otherwise it's only visible via `raw`.\n    if (typeof this.#req._rawBody === 'string' && this.#req._rawBody) {\n      parts.push(this.#req._rawBody);\n    }\n\n    const headers = this.#req.headers ?? {};\n    const excludedHeaders = new Set([\n      'host', 'connection', 'cache-control', 'accept', 'accept-encoding',\n      'accept-language', 'priority', 'sec-ch-ua', 'sec-ch-ua-mobile',\n      'sec-ch-ua-platform', 'sec-fetch-dest', 'sec-fetch-mode',\n      'sec-fetch-site', 'sec-fetch-user', 'upgrade-insecure-requests'\n    ]);\n\n    for (const [name, value] of Object.entries(headers)) {\n      if (!excludedHeaders.has(name)) {\n        parts.push(`${name}: ${value}`);\n      }\n    }\n\n    const cookies = this.#parseCookies();\n    const cookieStr = Object.entries(cookies).map(([k, v]) => `${k}=${v}`).join('; ');\n    if (cookieStr) {\n      parts.push(cookieStr);\n    }\n\n    return [parts.join(' ')];\n  }\n\n  #resolveWildcard(obj, pattern) {\n    if (typeof obj !== 'object' || obj === null) {\n      return [];\n    }\n\n    const prefix = pattern.slice(0, -1);\n    const values = [];\n\n    for (const [key, value] of Object.entries(obj)) {\n      if (key.startsWith(prefix)) {\n        values.push(value);\n      }\n    }\n\n    return values;\n  }\n\n  #getNestedValue(obj, key) {\n    if (typeof obj !== 'object' || obj === null) {\n      return undefined;\n    }\n\n    // Own-property only: `key in obj` would resolve `__proto__`/`constructor`/`toString` to the\n    // prototype chain, so a rule like `post.__proto__` (detecting a literal `__proto__` field) would\n    // read Object.prototype instead of request data and never match. Use hasOwnProperty.\n    const own = (o, k) => o !== null && typeof o === 'object' && Object.prototype.hasOwnProperty.call(o, k);\n\n    if (own(obj, key)) {\n      return obj[key];\n    }\n\n    const parts = key.split('.');\n    let current = obj;\n\n    for (const part of parts) {\n      if (!own(current, part)) {\n        return undefined;\n      }\n      current = current[part];\n    }\n\n    return current;\n  }\n\n  #parseCookies() {\n    if (this.#cookies !== null) {\n      return this.#cookies;\n    }\n\n    if (this.#req.cookies) {\n      this.#cookies = this.#req.cookies;\n      return this.#cookies;\n    }\n\n    const header = this.#req.headers?.cookie;\n    if (!header) {\n      this.#cookies = {};\n      return this.#cookies;\n    }\n\n    const cookies = {};\n\n    for (const pair of header.split(';')) {\n      const eqIndex = pair.indexOf('=');\n      if (eqIndex === -1) {\n        continue;\n      }\n      const name = pair.substring(0, eqIndex).trim();\n      const value = pair.substring(eqIndex + 1).trim();\n      cookies[name] = value;\n    }\n\n    this.#cookies = cookies;\n    return this.#cookies;\n  }\n}\n","/**\n * Request Normalization Pipeline\n *\n * Normalizes request data to prevent encoding-based bypass attacks.\n * This module handles URL encoding, HTML entities, SQL comments, and other\n * obfuscation techniques that attackers use to evade pattern matching.\n */\n\nconst HTML_ENTITIES = {\n    '&amp;': '&',\n    '&lt;': '<',\n    '&gt;': '>',\n    '&quot;': '\"',\n    '&#39;': \"'\",\n    '&apos;': \"'\",\n    '&nbsp;': ' ',\n    '&#x27;': \"'\",\n    '&#x22;': '\"',\n    '&#x3C;': '<',\n    '&#x3E;': '>',\n    '&#x26;': '&',\n    '&#34;': '\"',\n    '&#60;': '<',\n    '&#62;': '>',\n    '&#38;': '&'\n};\n\nconst MAX_DECODE_ITERATIONS = 5;\n\nexport function normalize(value, options = {}) {\n    if (typeof value !== 'string') {\n        return value;\n    }\n\n    const opts = {\n        urlDecode: true,\n        htmlDecode: true,\n        sqlComments: true,\n        nullBytes: true,\n        whitespace: true,\n        ...options\n    };\n\n    let result = value;\n\n    if (opts.nullBytes) {\n        result = removeNullBytes(result);\n    }\n\n    if (opts.urlDecode) {\n        result = urlDecode(result);\n    }\n\n    if (opts.htmlDecode) {\n        result = htmlEntityDecode(result);\n    }\n\n    if (opts.sqlComments) {\n        result = removeSqlComments(result);\n    }\n\n    if (opts.whitespace) {\n        result = normalizeWhitespace(result);\n    }\n\n    return result;\n}\n\nexport function urlDecode(value) {\n    if (typeof value !== 'string') {\n        return value;\n    }\n\n    let result = value;\n    let previous = '';\n    let iterations = 0;\n\n    while (result !== previous && iterations < MAX_DECODE_ITERATIONS) {\n        previous = result;\n        iterations++;\n\n        try {\n            result = decodeURIComponent(result);\n        } catch {\n            result = safeUrlDecode(result);\n            break;\n        }\n    }\n\n    return result;\n}\n\nfunction safeUrlDecode(value) {\n    return value.replace(/%([0-9A-Fa-f]{2})/g, (match, hex) => {\n        try {\n            return String.fromCharCode(parseInt(hex, 16));\n        } catch {\n            return match;\n        }\n    });\n}\n\nexport function htmlEntityDecode(value) {\n    if (typeof value !== 'string') {\n        return value;\n    }\n\n    let result = value;\n\n    for (const [entity, char] of Object.entries(HTML_ENTITIES)) {\n        result = result.split(entity).join(char);\n    }\n\n    result = result.replace(/&#(\\d+);/g, (match, code) => {\n        const num = parseInt(code, 10);\n        return num > 0 && num < 65536 ? String.fromCharCode(num) : match;\n    });\n\n    result = result.replace(/&#x([0-9A-Fa-f]+);/g, (match, hex) => {\n        const num = parseInt(hex, 16);\n        return num > 0 && num < 65536 ? String.fromCharCode(num) : match;\n    });\n\n    return result;\n}\n\nexport function removeSqlComments(value) {\n    if (typeof value !== 'string') {\n        return value;\n    }\n\n    // Collapse inline block comments to a space (the anti-obfuscation goal). We must NOT strip the\n    // line-comment forms (`--…`, `#…`) to end-of-line: on the WAF inspection path that DELETES\n    // attacker-controlled spans from the value the engine sees while the app still processes the\n    // original — e.g. `#<script>…` becomes empty and evades an XSS rule, though the browser still\n    // runs it. Keeping the content only ever ADDS matches (more of the value is inspected), never\n    // hides one. SQLi keyword detection is unaffected — the keywords remain visible.\n    let result = value;\n\n    result = result.replace(/\\/\\*[\\s\\S]*?\\*\\//g, ' ');\n    result = result.replace(/\\/\\*![\\s\\S]*?\\*\\//g, ' ');\n\n    return result;\n}\n\nexport function removeNullBytes(value) {\n    if (typeof value !== 'string') {\n        return value;\n    }\n\n    let result = value.replace(/\\x00/g, '');\n\n    result = result.replace(/[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F]/g, '');\n\n    return result;\n}\n\nexport function normalizeWhitespace(value) {\n    if (typeof value !== 'string') {\n        return value;\n    }\n\n    let result = value.replace(/[\\t\\r\\n\\f\\v]+/g, ' ');\n\n    result = result.replace(/ {2,}/g, ' ');\n\n    return result;\n}\n\nfunction serializeForRawDetection(body, visited = new Set(), isRoot = true) {\n    if (body === null || body === undefined) {\n        return isRoot ? '' : 'null';\n    }\n\n    if (typeof body === 'string') {\n        return isRoot ? body : JSON.stringify(body);\n    }\n\n    if (typeof body !== 'object') {\n        return String(body);\n    }\n\n    if (visited.has(body)) {\n        return '[Circular]';\n    }\n    visited.add(body);\n\n    if (Array.isArray(body)) {\n        const items = body.map(item => serializeForRawDetection(item, visited, false));\n        return '[' + items.join(',') + ']';\n    }\n\n    // Object.getOwnPropertyNames includes non-enumerable own properties, so a __proto__ key\n    // set via Object.defineProperty (as modern JSON.parse may do) is included in the output.\n    const keys = Object.getOwnPropertyNames(body);\n    const parts = keys.map(key => {\n        const val = serializeForRawDetection(body[key], visited, false);\n        return JSON.stringify(key) + ':' + val;\n    });\n\n    return '{' + parts.join(',') + '}';\n}\n\nexport function normalizeRequest(req, options = {}) {\n    // Prefer a caller-provided verbatim body string (set by the fetch/node adapters):\n    // it preserves literal keys like `__proto__` that JSON.stringify drops, which is\n    // what makes prototype-pollution rules on `raw` robust. Fall back to a\n    // reconstruction from the parsed body (the Express path, which has no raw text).\n    const rawBody = typeof req._rawBody === 'string'\n        ? req._rawBody\n        : serializeForRawDetection(req.body ?? null);\n\n    return {\n        query: normalizeObject(req.query || {}, options),\n        body: normalizeObject(req.body || {}, options),\n        headers: normalizeObject(req.headers || {}, options),\n        url: normalize(req.url || '', options),\n        originalUrl: normalize(req.originalUrl || req.url || '', options),\n        _rawBody: rawBody\n    };\n}\n\n// Depth bound for the recursive walk: a pathologically deep object would otherwise overflow the\n// stack, and the engine's per-rule catch would swallow that into a fail-open. Beyond the bound the\n// sub-value is left un-normalized (still matched, just in its raw form) rather than crashing.\nconst MAX_NORMALIZE_DEPTH = 200;\n\nexport function normalizeObject(value, options = {}, depth = 0) {\n    if (typeof value === 'string') {\n        return normalize(value, options);\n    }\n\n    if (depth >= MAX_NORMALIZE_DEPTH) {\n        return value;\n    }\n\n    if (Array.isArray(value)) {\n        return value.map(item => normalizeObject(item, options, depth + 1));\n    }\n\n    if (typeof value === 'object' && value !== null) {\n        const result = {};\n\n        for (const [key, val] of Object.entries(value)) {\n            result[key] = normalizeObject(val, options, depth + 1);\n        }\n\n        return result;\n    }\n\n    return value;\n}\n\nexport function createMatchVariants(value) {\n    if (typeof value !== 'string') {\n        return [value];\n    }\n\n    const variants = new Set();\n\n    variants.add(value);\n\n    const urlDecoded = urlDecode(value);\n    variants.add(urlDecoded);\n\n    const htmlDecoded = htmlEntityDecode(value);\n    variants.add(htmlDecoded);\n\n    const bothDecoded = htmlEntityDecode(urlDecoded);\n    variants.add(bothDecoded);\n\n    const normalized = normalize(value);\n    variants.add(normalized);\n\n    variants.add(value.toLowerCase());\n    variants.add(normalized.toLowerCase());\n\n    return Array.from(variants);\n}\n\nexport const _testExports = {\n    safeUrlDecode,\n    serializeForRawDetection,\n    HTML_ENTITIES,\n    MAX_DECODE_ITERATIONS\n};\n","import { RequestResolver } from './request.js';\nimport { normalizeRequest } from './normalizer.js';\n\n// Catastrophic-backtracking shapes. Broad on purpose: a group whose inner content is quantified\n// (+, *, or {n,}) and is itself quantified — (a+)+, (\\w+)+, (.*)*, ([a-z]+)*, (ab+)+ — or an\n// alternation under an outer quantifier — (a|a)*, (x|y)+. A rule matching one of these is skipped\n// (safer than hanging the event loop). The `NEST` variants allow ONE level of nested parentheses in\n// the outer group so a quantified SUBGROUP is caught too (`((ab)+)+`, `((a|b)+)*`) — the earlier\n// `[^)]*` forms stopped at the first inner `)` and missed those. `.test()` scans every start offset,\n// so deeper nestings match at an inner window too.\nconst GRP = '(?:[^()]|\\\\([^()]*\\\\))*'; // group body allowing one level of nested parens\nconst REDOS_PATTERNS = [\n  /\\([^)]*[+*}][^)]*\\)\\s*[+*]/,\n  /\\([^)]*\\|[^)]*\\)\\s*[+*]/,\n  new RegExp('\\\\(' + GRP + '[+*}]' + GRP + '\\\\)\\\\s*[+*]'), // nested quantified subgroup\n  new RegExp('\\\\(' + GRP + '\\\\|' + GRP + '\\\\)\\\\s*[+*]')    // nested alternation under a quantifier\n];\n\n// Report once when a rule's regex is rejected (ReDoS-shaped or unparseable). Unlike an unknown match\n// type, a rejected regex used to fail silently — so a delivered rule protected nothing and nobody knew.\nconst warnedRejectedPatterns = new Set();\nfunction warnRejectedPatternOnce(pattern) {\n  const key = String(pattern);\n  if (warnedRejectedPatterns.has(key)) return;\n  warnedRejectedPatterns.add(key);\n  console.warn(\n    `[patchstack] rule_v2 regex pattern rejected (unsafe or invalid) — condition treated as no-match. ` +\n      `The rule relying on it is NOT enforced: ${key}`\n  );\n}\n\n// An absurdly long pattern is either a mistake or an attack on our own matcher; compiling and running\n// it on every request is unbounded work. The rule-bundle validator rejects these upstream — this is the\n// backstop for a caller-supplied bundle that never went through it.\nconst MAX_PATTERN_LENGTH = 1000;\n\nexport function safeRegExp(pattern) {\n  if (!pattern) {\n    return null;\n  }\n  if (typeof pattern !== 'string' || pattern.length > MAX_PATTERN_LENGTH) {\n    return null;\n  }\n\n  for (const dangerous of REDOS_PATTERNS) {\n    if (dangerous.test(pattern)) {\n      return null;\n    }\n  }\n\n  const match = pattern.match(/^\\/(.+?)\\/([gimsuy]*)$/s);\n  if (!match) {\n    return null;\n  }\n\n  try {\n    return new RegExp(match[1], match[2]);\n  } catch {\n    return null;\n  }\n}\n\n// ctype_*/is_numeric compare their character-class result to the rule's expected\n// `value`. Rules are almost always written `{ \"type\": \"ctype_digit\", \"value\": false }`\n// meaning \"flag when NOT of this class\" — so the result must be compared to matchVal,\n// not returned raw. Empty/absent values never match (mirrors engine-php's `$value != ''`\n// guard), otherwise every missing parameter false-positives a `value:false` rule.\n// When `value` is not a boolean (null/omitted) the legacy default of `true` is used, so\n// existing rules that relied on the raw class check are unaffected.\nfunction ctypeResult(strValue, isClass, matchVal) {\n  if (strValue === '') {\n    return false;\n  }\n  const expected = typeof matchVal === 'boolean' ? matchVal : true;\n  return isClass === expected;\n}\n\n// Walk a dot-path into a decoded object and invoke `cb({ parent, key, value })` for every leaf it\n// reaches, fanning out over arrays at EVERY segment (not just the last) — so `orders.customers.email`\n// visits the email of each customer of each order, for arbitrary-length / arbitrarily-nested arrays.\n// `cb` gets the container + key so callers can either read (match) or set (redact) the leaf.\nexport function walkLeaves(node, segments, cb) {\n  if (node === null || typeof node !== 'object') return;\n  if (Array.isArray(node)) {\n    for (const el of node) walkLeaves(el, segments, cb);\n    return;\n  }\n  const [head, ...rest] = segments;\n  if (head === undefined || !Object.prototype.hasOwnProperty.call(node, head)) return;\n  if (rest.length === 0) {\n    const leaf = node[head];\n    if (Array.isArray(leaf)) {\n      for (let i = 0; i < leaf.length; i++) cb({ parent: leaf, key: i, value: leaf[i] });\n    } else {\n      cb({ parent: node, key: head, value: leaf });\n    }\n  } else {\n    walkLeaves(node[head], rest, cb);\n  }\n}\n\n// array_key_value: navigate `match.key` (a dot-path, or an array of paths) inside the decoded value\n// and run the nested `match.match` against every leaf it finds (fanning out over arrays at every\n// segment). Mirrors engine-php's recursive array_key_value handling.\nfunction arrayKeyValue(value, matchObj) {\n  if (!matchObj || !matchObj.match || value === null || typeof value !== 'object') {\n    return false;\n  }\n  const keys = Array.isArray(matchObj.key) ? matchObj.key : [matchObj.key];\n  const sub = matchObj.match;\n\n  for (const key of keys) {\n    let matched = false;\n    walkLeaves(value, String(key).split('.'), ({ value: leaf }) => {\n      if (!matched && matchValue(sub.type, leaf, sub.value, sub)) matched = true;\n    });\n    if (matched) return true;\n  }\n  return false;\n}\n\n// Match types that operate on the whole container (not per-leaf): `isset` (presence) and\n// `array_in_array` / `array_key_value` (structural). Everything else is a scalar matcher that must\n// fan out over the leaves of an object/array value.\nconst WHOLE_VALUE_MATCH_TYPES = new Set(['isset', 'array_in_array', 'array_key_value']);\n\n// Iteratively collect every scalar (non-object) leaf of a structured value. Iterative + bounded\n// (depth and node caps) so a pathologically deep/large attacker payload STOPS at the bound rather\n// than throwing a RangeError that the per-rule catch would swallow into a fail-open bypass.\nfunction collectLeafValues(root, nodeCap = 20000, maxDepth = 1000) {\n  const out = [];\n  const stack = [[root, 0]];\n  let visited = 0;\n  while (stack.length) {\n    const [node, depth] = stack.pop();\n    if (node === null || node === undefined) continue;\n    if (typeof node !== 'object') {\n      out.push(node);\n      continue;\n    }\n    if (depth >= maxDepth || visited >= nodeCap) continue;\n    visited++;\n    if (Array.isArray(node)) {\n      for (let i = node.length - 1; i >= 0; i--) stack.push([node[i], depth + 1]);\n    } else {\n      for (const k of Object.keys(node)) stack.push([node[k], depth + 1]);\n    }\n  }\n  return out;\n}\n\n// Emit a warning at most once per distinct key (keeps a persistent misconfiguration from spamming).\nconst warnedKeys = new Set();\nfunction warnOnce(key, message) {\n  if (warnedKeys.has(key)) return;\n  warnedKeys.add(key);\n  console.warn(message);\n}\n\n// Report an unknown/removed match type once, so a rule referencing it is not silently\n// unenforced (ADR: \"unknown match type → skipped and logged, never silently passed\").\nconst warnedMatchTypes = new Set();\nfunction warnUnsupportedMatchType(type) {\n  if (type == null || warnedMatchTypes.has(type)) {\n    return;\n  }\n  warnedMatchTypes.add(type);\n  console.warn(\n    `[patchstack] Unsupported rule_v2 match type \"${type}\" — condition treated as no-match. ` +\n      `Rules relying on it are not enforced by this engine.`\n  );\n}\n\n// Internal / private / loopback / link-local / cloud-metadata host check, used by the\n// `internal_host` match type for SSRF egress rules. It CANONICALIZES the host before classifying —\n// a textual/prefix check is bypassable by alternate encodings (decimal/hex/octal IPv4, expanded or\n// IPv4-mapped IPv6), which is a classic SSRF evasion. Handles localhost / *.local / GCP metadata\n// names, every IPv4 spelling inet_aton accepts, and IPv6 loopback/link-local/unique-local/mapped.\nfunction isInternalHost(hostname) {\n  if (!hostname) return false;\n  let host = String(hostname).toLowerCase().replace(/^\\[|\\]$/g, '');\n  host = host.replace(/%[^\\]]*$/, ''); // strip an IPv6 zone id (fe80::1%eth0)\n  host = host.replace(/\\.$/, ''); // strip a single trailing dot (127.0.0.1.)\n\n  if (host === 'localhost' || host.endsWith('.localhost') || host.endsWith('.local')) return true;\n  if (host === 'metadata.google.internal') return true;\n\n  // IPv6 (contains a colon): expand to 8 groups, then classify on the canonical form.\n  if (host.includes(':')) {\n    const g = expandIPv6(host);\n    if (!g) return false;\n    const allZeroHi = g[0] === 0 && g[1] === 0 && g[2] === 0 && g[3] === 0 && g[4] === 0;\n    if (allZeroHi && g[5] === 0 && g[6] === 0 && (g[7] === 0 || g[7] === 1)) return true; // ::, ::1 loopback\n    if ((g[0] & 0xffc0) === 0xfe80) return true; // link-local fe80::/10\n    if ((g[0] & 0xfe00) === 0xfc00) return true; // unique-local fc00::/7\n    if (allZeroHi && (g[5] === 0xffff || g[5] === 0)) {\n      // IPv4-mapped (::ffff:a.b.c.d) / IPv4-compatible (::a.b.c.d) — classify the embedded v4.\n      return isPrivateV4Int((((g[6] << 16) >>> 0) | g[7]) >>> 0);\n    }\n    return false;\n  }\n\n  // IPv4 in any inet_aton spelling (dotted quad, shorthand, decimal, hex, octal).\n  const v4 = parseIPv4ToInt(host);\n  if (v4 !== null) return isPrivateV4Int(v4);\n  return false;\n}\n\n// Private / loopback / link-local / this-host / CGNAT test on a 32-bit IPv4 integer.\nfunction isPrivateV4Int(n) {\n  const a = (n >>> 24) & 0xff;\n  const b = (n >>> 16) & 0xff;\n  if (a === 127 || a === 10 || a === 0) return true; // loopback / private / this-host\n  if (a === 169 && b === 254) return true; // link-local incl. 169.254.169.254 metadata\n  if (a === 172 && b >= 16 && b <= 31) return true; // 172.16.0.0/12\n  if (a === 192 && b === 168) return true; // 192.168.0.0/16\n  if (a === 100 && b >= 64 && b <= 127) return true; // 100.64.0.0/10 CGNAT (Alibaba metadata 100.100.100.200)\n  return false;\n}\n\n// inet_aton-style parse: 1–4 dot-separated parts, each decimal / 0x-hex / 0-octal; the final part\n// fills the remaining low bytes. Returns a uint32, or null if the host isn't a numeric IPv4 form\n// (so ordinary hostnames — which contain letters outside [0-9a-fx] or other chars — return null).\nfunction parseIPv4ToInt(host) {\n  if (!/^[0-9a-fx]+(\\.[0-9a-fx]+)*$/i.test(host)) return null;\n  const parts = host.split('.');\n  if (parts.length > 4) return null;\n  const nums = [];\n  for (const p of parts) {\n    let n;\n    if (/^0x[0-9a-f]+$/i.test(p)) n = parseInt(p, 16);\n    else if (/^0[0-7]+$/.test(p)) n = parseInt(p, 8);\n    else if (/^[0-9]+$/.test(p)) n = parseInt(p, 10);\n    else return null; // e.g. a bare hex like \"7f\" (not inet_aton-valid without 0x)\n    if (!Number.isInteger(n) || n < 0) return null;\n    nums.push(n);\n  }\n  const last = nums.length - 1;\n  let value = 0;\n  for (let i = 0; i < last; i++) {\n    if (nums[i] > 0xff) return null;\n    value += nums[i] * 2 ** (8 * (3 - i));\n  }\n  const maxLast = 2 ** (8 * (5 - nums.length)) - 1; // the final part fills the remaining low bytes\n  if (nums[last] > maxLast) return null;\n  value += nums[last];\n  if (value < 0 || value > 0xffffffff) return null;\n  return value >>> 0;\n}\n\n// Expand an IPv6 string (any `::` compression, optional embedded IPv4 tail) to 8 numeric groups,\n// or null if it isn't valid IPv6. Lets the classifier compare the canonical form, not a string prefix.\nfunction expandIPv6(host) {\n  if (!host.includes(':')) return null;\n  let s = host;\n  // Embedded IPv4 tail (::ffff:127.0.0.1) → convert the dotted part to two hex groups.\n  const lastColon = s.lastIndexOf(':');\n  const tail = s.slice(lastColon + 1);\n  if (tail.includes('.')) {\n    const v4 = parseIPv4ToInt(tail);\n    if (v4 === null) return null;\n    s = s.slice(0, lastColon + 1) + ((v4 >>> 16) & 0xffff).toString(16) + ':' + (v4 & 0xffff).toString(16);\n  }\n  const halves = s.split('::');\n  if (halves.length > 2) return null;\n  const head = halves[0] ? halves[0].split(':') : [];\n  const back = halves.length === 2 ? (halves[1] ? halves[1].split(':') : []) : null;\n  let groups;\n  if (back === null) {\n    groups = head;\n  } else {\n    const fill = 8 - head.length - back.length;\n    if (fill < 0) return null;\n    groups = [...head, ...Array(fill).fill('0'), ...back];\n  }\n  if (groups.length !== 8) return null;\n  const out = [];\n  for (const g of groups) {\n    if (!/^[0-9a-f]{1,4}$/i.test(g)) return null;\n    out.push(parseInt(g, 16));\n  }\n  return out;\n}\n\n// Route/method scope for a rule's optional `when: { method, path }`. Fail-open: if the scope can't\n// be evaluated, the rule still applies (never silently suppress a rule).\nfunction ruleAppliesTo(when, resolver) {\n  try {\n    if (when.method) {\n      const methods = (Array.isArray(when.method) ? when.method : [when.method]).map((m) => String(m).toUpperCase());\n      const actual = String(resolver.resolve('server.REQUEST_METHOD')[0] ?? 'GET').toUpperCase();\n      if (!methods.includes(actual)) return false;\n    }\n    if (when.path) {\n      const uri = String(resolver.resolve('server.REQUEST_URI')[0] ?? '/');\n      if (!pathMatches(String(when.path), uri.split('?')[0])) return false;\n    }\n    return true;\n  } catch {\n    return true;\n  }\n}\n\n// `when.path`: an exact path, a glob with `*`, or an explicit `/regex/` (starts & ends with `/`).\nfunction pathMatches(pattern, path) {\n  if (pattern.length > 2 && pattern.startsWith('/') && pattern.endsWith('/')) {\n    const re = safeRegExp(pattern);\n    return re ? re.test(path) : false;\n  }\n  if (pattern.includes('*')) {\n    const re = safeRegExp('/^' + pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '[^?]*') + '$/');\n    return re ? re.test(path) : false;\n  }\n  return path === pattern;\n}\n\n// Drop a default port so `app.com:443` and `app.com` compare equal (a real proxy shape), without\n// dropping a non-default port (so genuine cross-port stays distinguishable).\nfunction normalizeDefaultPort(host) {\n  return String(host).toLowerCase().replace(/:(?:80|443)$/, '');\n}\n\n// CSRF primitive: does the request come from a different origin than its own Host? Lenient only when\n// the Origin AND Referer are TRULY ABSENT (a non-browser client). A present-but-opaque `Origin: null`\n// / empty / unparseable value is NOT same-origin — it's the sandboxed-iframe / opaque-origin signal a\n// CSRF attacker supplies, so it is treated as cross-origin.\nfunction isCrossOrigin(resolver) {\n  try {\n    const host = normalizeDefaultPort(String(resolver.resolve('server.HTTP_HOST')[0] ?? ''));\n    if (!host) return false;\n    const originRaw = resolver.resolve('server.HTTP_ORIGIN')[0];\n    const hasOrigin = originRaw !== undefined && originRaw !== null;\n    const src = hasOrigin ? originRaw : resolver.resolve('server.HTTP_REFERER')[0];\n    if (src === undefined || src === null) return false; // both absent → lenient\n    const s = String(src).trim();\n    if (hasOrigin && (s === '' || s.toLowerCase() === 'null')) return true; // present but opaque → cross-origin\n    const srcHost = hostFromUrl(s);\n    if (srcHost === null) return hasOrigin; // present-but-unparseable Origin → treat as cross-origin\n    return normalizeDefaultPort(srcHost) !== host;\n  } catch {\n    return false;\n  }\n}\n\nfunction hostFromUrl(value) {\n  try {\n    return new URL(value).host.toLowerCase();\n  } catch {\n    return null;\n  }\n}\n\n// Open-redirect primitive (response phase): a 3xx whose Location header points to a DIFFERENT origin\n// than the request's own Host. A relative Location (same-origin) never matches. Needs the request\n// Host, which the response phase threads in via reqCtx. Lenient: no Location, no request Host, or a\n// same-origin / relative target → not flagged (so it can't false-positive without the signal).\nfunction isOffOriginRedirect(resolver) {\n  try {\n    const status = Number(resolver.resolve('response.status')[0] ?? 0);\n    if (status < 300 || status >= 400) return false;\n    const location = resolver.resolve('response.header.location')[0];\n    if (!location) return false;\n    const host = String(resolver.resolve('server.HTTP_HOST')[0] ?? '').toLowerCase();\n    if (!host) return false;\n    // Resolve the Location the way a browser would before comparing hosts: strip TAB/CR/LF and\n    // normalize backslashes to forward slashes (browsers do), then resolve against the request origin\n    // as a base. A relative `/path` resolves to our own host (not flagged); a protocol-relative\n    // `//evil.com` or backslash `/\\evil.com` resolves off-origin (flagged) — the canonical\n    // open-redirect payloads that a base-less `new URL()` used to treat as \"relative & safe\".\n    const loc = String(location).replace(/[\\t\\r\\n]/g, '').replace(/\\\\/g, '/');\n    let target;\n    try {\n      target = new URL(loc, 'http://' + host).host.toLowerCase();\n    } catch {\n      return false; // unresolvable even with a base → not a redirect we can judge\n    }\n    return normalizeDefaultPort(target) !== normalizeDefaultPort(host);\n  } catch {\n    return false;\n  }\n}\n\n// CORS-reflection primitive (response phase): the response allows credentials AND lets any origin\n// read it — either `Access-Control-Allow-Origin: *`, or it reflects the caller's own Origin (so\n// every origin is allowed) — rather than a fixed allowlisted origin. That combination lets any\n// malicious site read the authenticated response. Needs the request Origin (threaded via reqCtx).\n// Lenient: credentials not allowed, no ACAO, or a fixed (non-reflected, non-*) ACAO → not flagged.\nfunction isReflectedCorsWithCredentials(resolver) {\n  try {\n    const acac = String(resolver.resolve('response.header.access-control-allow-credentials')[0] ?? '').toLowerCase();\n    if (acac !== 'true') return false; // only dangerous when credentials are allowed\n    const acao = String(resolver.resolve('response.header.access-control-allow-origin')[0] ?? '');\n    if (!acao) return false;\n    if (acao === '*') return true; // wildcard + credentials\n    if (acao.toLowerCase() === 'null') return true; // `null` + credentials is readable from a sandboxed iframe (Origin: null)\n    const origin = String(resolver.resolve('server.HTTP_ORIGIN')[0] ?? '');\n    if (!origin) return false;\n    return acao === origin; // ACAO echoes the caller's Origin → any origin is allowed\n  } catch {\n    return false;\n  }\n}\n\n// `matchObj` is the full match object; needed by types that read sibling fields\n// (array_key_value reads `key`/`match`). Optional so direct callers/tests can keep\n// using the (type, value, matchVal) signature.\nexport function matchValue(type, value, matchVal, matchObj) {\n  if (value === null || value === undefined) {\n    if (type === 'isset') {\n      return false;\n    }\n    return false;\n  }\n\n  // Guard the coercion: String() on a pathologically deep array/object can throw RangeError\n  // (stack overflow). Catching it here keeps a hostile nested value from failing the rule open.\n  let strValue;\n  if (typeof value === 'string') {\n    strValue = value;\n  } else {\n    try {\n      strValue = String(value);\n    } catch {\n      strValue = '';\n    }\n  }\n\n  switch (type) {\n    case 'equals':\n      return strValue == matchVal;\n\n    case 'equals_strict':\n      // Type-strict by design (`'1' !== 1`). A rule that wants loose matching should use `equals`.\n      return strValue === matchVal;\n\n    case 'contains':\n    // engine-php exposes `stripos` as an alias of `contains`.\n    case 'stripos': {\n      const lower = strValue.toLowerCase();\n      const target = String(matchVal).toLowerCase();\n      return lower.includes(target);\n    }\n\n    case 'not_contains': {\n      const lower = strValue.toLowerCase();\n      const target = String(matchVal).toLowerCase();\n      return !lower.includes(target);\n    }\n\n    case 'regex': {\n      const regex = safeRegExp(matchVal);\n      if (!regex) {\n        warnRejectedPatternOnce(matchVal);\n        return false;\n      }\n      return regex.test(strValue);\n    }\n\n    case 'more_than':\n      return Number(strValue) > Number(matchVal);\n\n    case 'less_than':\n      return Number(strValue) < Number(matchVal);\n\n    case 'ctype_digit':\n      return ctypeResult(strValue, /^\\d+$/.test(strValue), matchVal);\n\n    case 'ctype_alnum':\n      return ctypeResult(strValue, /^[\\w$\\u0080-\\uFFFF]+$/.test(strValue), matchVal);\n\n    case 'is_numeric':\n      return ctypeResult(strValue, !isNaN(strValue) && strValue.trim() !== '', matchVal);\n\n    case 'isset':\n      return true;\n\n    case 'in_array': {\n      const arr = (Array.isArray(matchVal) ? matchVal : [matchVal]).map((x) => String(x));\n      return arr.includes(strValue);\n    }\n\n    case 'not_in_array': {\n      const arr = (Array.isArray(matchVal) ? matchVal : [matchVal]).map((x) => String(x));\n      return !arr.includes(strValue);\n    }\n\n    case 'array_in_array': {\n      if (!Array.isArray(value) || !Array.isArray(matchVal)) {\n        return false;\n      }\n      const target = matchVal.map((x) => String(x));\n      return value.some((v) => target.includes(String(v)));\n    }\n\n    case 'hostname': {\n      try {\n        const url = new URL(strValue);\n        return url.hostname === matchVal;\n      } catch {\n        return false;\n      }\n    }\n\n    case 'internal_host':\n      // SSRF egress: private / loopback / link-local / cloud-metadata destinations.\n      return isInternalHost(strValue);\n\n    case 'quotes':\n    // engine-php exposes `inline_js_xss` as an alias of `quotes`.\n    case 'inline_js_xss':\n      return /['\"]/.test(strValue);\n\n    case 'inline_xss':\n      // Attribute-breakout heuristic: a quote AND a `>` or `=` (matches engine-php).\n      return /['\"]/.test(strValue) && /[>=]/.test(strValue);\n\n    case 'ctype_special': {\n      // engine-php strips space, `_`, `-`, `,` then applies the alnum/unicode check,\n      // and compares the result to `value` (usually false = \"flag when NOT clean\").\n      const stripped = strValue.replace(/[ _\\-,]/g, '');\n      return ctypeResult(strValue, /^[\\w$-￿]*$/.test(stripped), matchVal);\n    }\n\n    case 'array_key_value':\n      // Navigate `match.key` (dot-path, or array of paths) inside the decoded value and\n      // run the nested `match.match` against it — e.g. a json_decode'd body where a\n      // specific key must hold a specific value.\n      return arrayKeyValue(value, matchObj);\n\n    // file_contains (uploaded-file content scanning) is NOT WordPress-specific, but is\n    // not yet implemented in the JS engine (needs multipart body access). Kept as an\n    // explicit, documented no-match rather than silently hitting `default`.\n    case 'file_contains':\n      return false;\n\n    // WordPress-only match types (current_user_cannot, general_xss, getShortcodeAtts,\n    // getBlockAtts) have been removed: they depend on WP capabilities, wp_kses_post, and\n    // the shortcode/block parsers, and have no meaning in a JS app. They now fall through\n    // here and are reported once instead of pretending to be a no-match.\n    default:\n      warnUnsupportedMatchType(type);\n      return false;\n  }\n}\n\nexport class RuleEngine {\n  #rules;\n  #whitelists;\n  #whitelistKeys;\n  #onError;\n  #reportedErrors = new Set();\n\n  constructor({ firewall = [], whitelists = [], whitelist_keys = {}, onError } = {}) {\n    this.#rules = firewall;\n    this.#whitelists = whitelists;\n    this.#whitelistKeys = whitelist_keys;\n    this.#onError = onError;\n    // A whitelist with no `rule_id` suppresses EVERY rule when its (attacker-reachable) condition\n    // trips — almost never intended. And `whitelist_keys` is accepted but not implemented. Warn once\n    // for each so a misconfiguration that silently weakens the firewall is visible to the operator.\n    if (Array.isArray(whitelists) && whitelists.some((w) => w && Array.isArray(w.rule_v2) && !w.rule_id)) {\n      warnOnce(\n        'whitelist-no-rule-id',\n        '[patchstack] a whitelist has no `rule_id` — it suppresses ALL rules when it matches. ' +\n          'Scope each whitelist to a specific rule_id, and key it only on values an attacker cannot set.'\n      );\n    }\n    if (whitelist_keys && typeof whitelist_keys === 'object' && Object.keys(whitelist_keys).length > 0) {\n      warnOnce('whitelist-keys-unimplemented', '[patchstack] `whitelist_keys` is not implemented and has no effect.');\n    }\n  }\n\n  // A mitigation engine must never take down the app it protects: any error while\n  // evaluating a rule is reported and the request is allowed through (fail open). A\n  // malformed rule is skipped without aborting the rest of the ruleset.\n  #reportError(err) {\n    if (this.#onError) {\n      this.#onError(err);\n      return;\n    }\n    // Default: log once per distinct message so a persistently-broken rule doesn't\n    // spam per request (never silently swallow — hosts can pass `onError` for structured logging).\n    const key = err && err.message ? err.message : String(err);\n    if (this.#reportedErrors.has(key)) {\n      return;\n    }\n    this.#reportedErrors.add(key);\n    console.error('[patchstack] rule evaluation error (rule skipped, request allowed):', err);\n  }\n\n  evaluate(req) {\n    let normalizedReq;\n    let resolver;\n    try {\n      normalizedReq = { ...req, ...normalizeRequest(req) };\n      resolver = new RequestResolver(normalizedReq);\n    } catch (err) {\n      this.#reportError(err);\n      return { blocked: false, rule: null, message: null }; // fail open\n    }\n\n    for (const rule of this.#rules) {\n      try {\n        // Route/method scope: a rule may declare `when: { method, path }` to apply only on matching\n        // requests (so an auto-generated per-endpoint rule doesn't fire elsewhere).\n        if (rule.when && !ruleAppliesTo(rule.when, resolver)) {\n          continue;\n        }\n\n        const conditions = rule.rule_v2;\n\n        if (!Array.isArray(conditions) || conditions.length === 0) {\n          continue;\n        }\n\n        if (this.#evaluateRule(conditions, resolver)) {\n          if (this.#isWhitelisted(normalizedReq, rule)) {\n            continue;\n          }\n\n          return {\n            blocked: true,\n            rule,\n            message: rule.message ?? `Blocked by Patchstack WAF rule: ${rule.title ?? rule.id}`\n          };\n        }\n      } catch (err) {\n        // Skip this rule and keep evaluating the rest — one bad rule never blocks a\n        // request nor shadows the rules after it.\n        this.#reportError(err);\n      }\n    }\n\n    return { blocked: false, rule: null, message: null };\n  }\n\n  #evaluateRule(conditions, resolver) {\n    const inclusiveConditions = conditions.filter(c => c.inclusive);\n    const nonInclusiveConditions = conditions.filter(c => !c.inclusive);\n\n    if (inclusiveConditions.length > 0) {\n      let inclusiveHits = 0;\n\n      for (const condition of inclusiveConditions) {\n        if (this.#evaluateCondition(condition, resolver)) {\n          inclusiveHits++;\n        }\n      }\n\n      if (inclusiveHits === inclusiveConditions.length) {\n        return true;\n      }\n    }\n\n    for (const condition of nonInclusiveConditions) {\n      if (this.#evaluateCondition(condition, resolver)) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  #evaluateCondition(condition, resolver) {\n    const { parameter, match, mutations } = condition;\n\n    if (parameter === 'rules' && Array.isArray(condition.rules)) {\n      return this.#evaluateRule(condition.rules, resolver);\n    }\n\n    // `cross_origin` needs the request as a whole (Origin/Referer vs Host), not a single resolved\n    // parameter — it's the CSRF primitive: true (→ block) when the request comes from another origin.\n    if (match && match.type === 'cross_origin') {\n      return isCrossOrigin(resolver);\n    }\n\n    // `off_origin` (response phase): true (→ block) when a 3xx redirects to a different origin than\n    // the request Host — the open-redirect primitive. Like cross_origin, it needs the whole resolver.\n    if (match && match.type === 'off_origin') {\n      return isOffOriginRedirect(resolver);\n    }\n\n    // `cors_reflected` (response phase): true (→ block) when the response allows credentials and\n    // reflects the caller's Origin (or uses `*`) — the CORS-misconfiguration primitive. Needs the\n    // whole resolver (request Origin vs response ACAO/ACAC).\n    if (match && match.type === 'cors_reflected') {\n      return isReflectedCorsWithCredentials(resolver);\n    }\n\n    // `parameter` may be an array (e.g. [\"get.action\",\"post.action\"]) — the rule_v2 format\n    // uses these pervasively to mean \"any of these sources\". Resolve each and OR the\n    // candidate values together. (A bare string resolves as a single source.)\n    const params = Array.isArray(parameter) ? parameter : [parameter];\n    const values = params.flatMap((p) => resolver.resolve(p));\n\n    if (values.length === 0) {\n      return false;\n    }\n\n    for (let value of values) {\n      if (mutations) {\n        value = resolver.applyMutations(mutations, value);\n      }\n\n      // array_key_value inspects the object as a whole (it navigates a key path),\n      // so it must not go through the per-value object iteration below.\n      if (match.type === 'array_key_value') {\n        if (matchValue(match.type, value, match.value, match)) {\n          return true;\n        }\n        continue;\n      }\n\n      // A structured (object / array-of-object) value must be inspected at every leaf: a payload\n      // nested deeper than a scalar rule expects would otherwise stringify to \"[object Object]\" and\n      // evade the match, while the app still reads the live value. Whole-value match types\n      // (isset / array_in_array) see the container; scalar matchers fan out over all leaves.\n      if (typeof value === 'object' && value !== null) {\n        if (WHOLE_VALUE_MATCH_TYPES.has(match.type)) {\n          if (matchValue(match.type, value, match.value, match)) return true;\n        } else {\n          for (const leaf of collectLeafValues(value)) {\n            if (matchValue(match.type, leaf, match.value, match)) return true;\n          }\n        }\n        continue;\n      }\n\n      if (matchValue(match.type, value, match.value, match)) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  #isWhitelisted(req, rule) {\n    if (!this.#whitelists || this.#whitelists.length === 0) {\n      return false;\n    }\n\n    for (const whitelist of this.#whitelists) {\n      if (!Array.isArray(whitelist.rule_v2)) {\n        continue;\n      }\n\n      if (whitelist.rule_id && whitelist.rule_id !== rule.id) {\n        continue;\n      }\n\n      const resolver = new RequestResolver(req);\n      if (this.#evaluateRule(whitelist.rule_v2, resolver)) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n}\n\nexport const _testExports = { matchValue, safeRegExp, isInternalHost };\n","import { safeBaseUrl } from '../safe-origin.js';\nimport { pulseAuthHeader } from '../../pulse-token.js';\n\nconst DEFAULT_BASE_URL = 'https://api.patchstack.com/monitor/pulse';\nconst DEFAULT_CACHE_TTL = 300_000;\n// Randomly shorten the effective TTL by up to this fraction so many long-lived clients don't all\n// revalidate on the same tick (spreads load / avoids a thundering herd against the rules API).\nconst JITTER_FRACTION = 0.1;\n\n// Per-site rules client for Pulse (npm/JS) apps. Public endpoint — the site UUID is the only\n// credential, passed in the path. Fail-open: any error returns success:false + empty rules so\n// createProtection falls back to the disk cache or the bundled rules.\n//\n// Conditional fetch: pass a prior `etag` (persisted with the last cached bundle) and the client\n// sends `If-None-Match`; a 304 returns `{ notModified: true }` so the caller reuses its cache\n// without re-downloading, and a 200 returns the new bundle plus its `etag` to persist. This is a\n// no-op until the rules API emits an ETag and honors If-None-Match — with no ETag in the response\n// the client simply behaves as before (a full fetch every refresh).\nexport class PulseRuleClient {\n  #siteUuid;\n  #timeoutMs;\n  #baseUrl;\n  #cacheTtl;\n  #cache = null;\n  #cacheTime = null;\n  #ttlEffective = 0;\n  #etag;\n  #pulseAuth;\n\n  constructor({ siteUuid, baseUrl, cacheTtl, etag, timeoutMs, pulseAuth } = {}) {\n    // Bounded so app STARTUP can't hang on a slow API: hosted platforms fail a deploy whose health\n    // check is slow, and we always have a cache/bundled fallback to boot from.\n    this.#timeoutMs = Number(timeoutMs) > 0 ? Number(timeoutMs) : 30_000;\n    this.#siteUuid = siteUuid ?? process.env.PATCHSTACK_SITE_UUID;\n    // Rules are executed policy — refuse a plaintext remote override (see safe-origin.js).\n    this.#baseUrl = safeBaseUrl(baseUrl ?? process.env.PATCHSTACK_PULSE_RULES_URL, DEFAULT_BASE_URL, 'rule endpoint');\n    this.#cacheTtl = Number.isFinite(cacheTtl) && cacheTtl > 0 ? cacheTtl : DEFAULT_CACHE_TTL;\n    this.#etag = etag ?? null;\n    this.#pulseAuth = pulseAuth ?? null;\n    if (!this.#siteUuid) {\n      throw new Error('Patchstack site UUID is required. Pass { siteUuid } or set PATCHSTACK_SITE_UUID.');\n    }\n  }\n\n  async getRules() {\n    const now = Date.now();\n    if (this.#cache && this.#cacheTime !== null && now - this.#cacheTime < this.#ttlEffective) {\n      return this.#cache;\n    }\n    const url = `${this.#baseUrl}/rules/${encodeURIComponent(this.#siteUuid)}`;\n    try {\n      // Unauthenticated when no credential resolved, or when the exchange\n      // fails — the server still accepts the UUID, and protection must never\n      // hinge on getting a token.\n      const headers = {\n        Accept: 'application/json',\n        ...(await pulseAuthHeader(\n          { pulseAuth: this.#pulseAuth, endpoint: this.#baseUrl, timeoutMs: this.#timeoutMs },\n          fetch,\n        )),\n      };\n      if (this.#etag) headers['If-None-Match'] = this.#etag;\n      const response = await fetch(url, { method: 'GET', headers, signal: AbortSignal.timeout(this.#timeoutMs) });\n\n      if (response.status === 304) {\n        this.#touch(now); // revalidated — reset the clock (fresh jitter)\n        return this.#cache ?? { success: true, notModified: true, etag: this.#etag, firewall: [], whitelists: [], whitelist_keys: {} };\n      }\n      if (!response.ok) {\n        return { success: false, error: `API returned ${response.status}`, firewall: [], whitelists: [], whitelist_keys: {} };\n      }\n      const data = await response.json();\n      // A 200 that isn't a genuine rule envelope (schema drift, a proxy/interstitial page, an\n      // {error} body) must not be treated as \"no rules\". Report failure so the caller falls back to\n      // the cache / bundled rules rather than caching an empty bundle.\n      if (!data || !Array.isArray(data.firewall)) {\n        return { success: false, error: 'unexpected response shape (no firewall array)', firewall: [], whitelists: [], whitelist_keys: {} };\n      }\n      const result = {\n        success: true,\n        notModified: false,\n        etag: response.headers?.get?.('etag') ?? null,\n        firewall: data.firewall,\n        whitelists: Array.isArray(data.whitelists) ? data.whitelists : [],\n        whitelist_keys: data.whitelist_keys ?? {},\n        ...enforcementField(data),\n      };\n      this.#cache = result;\n      this.#etag = result.etag;\n      this.#touch(now);\n      return result;\n    } catch (err) {\n      return {\n        success: false,\n        error: err.name === 'TimeoutError' ? 'Request timed out' : err.message,\n        firewall: [], whitelists: [], whitelist_keys: {},\n      };\n    }\n  }\n\n  #touch(now) {\n    this.#cacheTime = now;\n    this.#ttlEffective = this.#cacheTtl - Math.floor(Math.random() * this.#cacheTtl * JITTER_FRACTION);\n  }\n\n  clearCache() {\n    this.#cache = null;\n    this.#cacheTime = null;\n    this.#etag = null;\n  }\n}\n\n/** @param {unknown} data @returns {{ enforcement?: 'block'|'dry-run' }} */\nfunction enforcementField(data) {\n  if (!data || typeof data !== 'object') return {};\n  const v = data.enforcement ?? data.mode;\n  return v === 'block' || v === 'dry-run' ? { enforcement: v } : {};\n}\n","// Web Fetch adapter — runs the node-waf engine on any runtime where a request is a\n// WHATWG `Request` and a handler returns a `Response`: Cloudflare Workers, Bun, Deno,\n// Hono, Next.js edge, and TanStack Start's `server.ts`. This is the surface AI-builder\n// apps actually deploy to, and where require-based instrumentation can't reach.\n//\n// The engine already consumes a runtime-neutral request shape; this adapter builds that\n// shape from a `Request`, so no engine changes are needed beyond keeping the hot path\n// free of Node-only APIs.\nimport { RuleEngine } from './engine.js';\n\n// Cap how much request body we buffer for inspection. A larger body is left UNSCANNED\n// (fail-open) rather than buffered into memory — matches the node adapter's maxBodyBytes.\nconst MAX_BODY_BYTES = 1024 * 1024;\n\n// Build the engine's request shape from a WHATWG Request. The body is read from a\n// CLONE so the downstream handler still receives an intact request.\nexport async function fromFetchRequest(request, options = {}) {\n  const maxBodyBytes = options.maxBodyBytes ?? MAX_BODY_BYTES;\n  const url = new URL(request.url);\n  const method = (request.method || 'GET').toUpperCase();\n\n  const headers = {};\n  request.headers.forEach((value, key) => {\n    headers[key.toLowerCase()] = value;\n  });\n\n  const query = {};\n  for (const [key, value] of url.searchParams) {\n    if (key in query) {\n      query[key] = Array.isArray(query[key]) ? [...query[key], value] : [query[key], value];\n    } else {\n      query[key] = value;\n    }\n  }\n\n  let rawBody = '';\n  if (method !== 'GET' && method !== 'HEAD') {\n    rawBody = await readCappedText(request, maxBodyBytes);\n  }\n\n  const contentType = headers['content-type'] || '';\n  let body = {};\n  let files;\n  if (rawBody) {\n    const parsed = parseBody(rawBody, contentType);\n    body = parsed.body;\n    files = parsed.files;\n  }\n\n  const uri = url.pathname + url.search;\n  const forwarded =\n    headers['cf-connecting-ip'] || headers['x-forwarded-for'] || headers['x-real-ip'] || '';\n\n  return {\n    method,\n    url: uri,\n    originalUrl: uri,\n    query,\n    body,\n    files,\n    headers,\n    ip: forwarded.split(',')[0].trim(),\n    cookies: parseCookies(headers.cookie),\n    // Verbatim body text: preserves literal keys (e.g. `__proto__`) that JSON.stringify\n    // drops, so prototype-pollution rules on `raw` are robust.\n    _rawBody: rawBody\n  };\n}\n\n// Read a request body as text for inspection. Memory is bounded by a hard ceiling (4× the scan\n// cap): a body whose declared Content-Length exceeds it is left UNSCANNED (fail-open). Within the\n// ceiling, an oversize body is TRUNCATED to `max` and its prefix is still scanned — so a\n// front-loaded payload is caught — rather than being discarded outright. Reads a clone so the\n// downstream handler keeps an intact body. (`max` is compared in bytes against Content-Length; the\n// prefix slice is by character, which can only over-scan a multibyte body — the safe direction.)\nasync function readCappedText(request, max) {\n  // Do NOT skip scanning based on a declared Content-Length: an attacker can declare a huge length\n  // (or none) to dodge inspection while sending a small exploit body. Always stream-scan the prefix\n  // up to `max` (buffering is bounded to `max`; the rest is drained but not retained). Anything past\n  // the cap is unscanned — the documented prefix-scan tradeoff — but the body is never skipped whole.\n  let clone;\n  try {\n    clone = request.clone();\n  } catch {\n    return '';\n  }\n\n  // Stream the read so a body WITHOUT a Content-Length can't buffer unbounded: retain only up to the\n  // scan cap (`max`) for inspection, but keep draining to completion so the original request stays\n  // intact. A front-loaded payload is still caught; anything past the cap is not scanned (same\n  // partial-scan tradeoff as before, now with a hard memory bound regardless of Content-Length).\n  const body = clone.body;\n  if (body && typeof body.getReader === 'function') {\n    const reader = body.getReader();\n    const chunks = [];\n    let buffered = 0;\n    try {\n      for (;;) {\n        const { done, value } = await reader.read();\n        if (done) break;\n        if (!value || buffered >= max) continue; // keep draining, stop buffering past the cap\n        const take = Math.min(value.byteLength, max - buffered);\n        chunks.push(take === value.byteLength ? value : value.subarray(0, take));\n        buffered += take;\n      }\n    } catch {\n      return '';\n    }\n    try {\n      return new TextDecoder().decode(concatChunks(chunks, buffered));\n    } catch {\n      return '';\n    }\n  }\n\n  // No readable stream — fall back to text() with the post-read guard.\n  try {\n    const text = await clone.text();\n    return text.length > max ? text.slice(0, max) : text;\n  } catch {\n    return '';\n  }\n}\n\nfunction concatChunks(chunks, total) {\n  const out = new Uint8Array(total);\n  let offset = 0;\n  for (const c of chunks) {\n    out.set(c, offset);\n    offset += c.byteLength;\n  }\n  return out;\n}\n\n// Minimal multipart/form-data parser: enough to expose field names + values (so `post.<field>`\n// and `raw` rules match uploads, e.g. a `__proto__` field name) and file metadata (filename via\n// `files.<field>`). We only need the textual structure, not the binary file contents.\n// Parse a request body into { body, files } for parameter-scoped rules. Content-type detection is\n// deliberately permissive: many AI-built apps `JSON.parse(await req.text())` regardless of the\n// declared type, so a JSON body arriving as `application/vnd.api+json`, `application/ld+json`,\n// `text/plain`, `application/csp-report`, or with NO content-type must still populate post.<field>\n// (otherwise a field-scoped rule silently resolves to nothing). Unrecognized/binary bodies stay `{}`\n// and are still matchable via `raw`.\nexport function parseBody(rawBody, contentType) {\n  const ct = String(contentType || '').toLowerCase();\n  const isJson = ct.includes('application/json') || /\\+json\\b/.test(ct);\n  const isForm = ct.includes('application/x-www-form-urlencoded');\n  const isMultipart = ct.includes('multipart/form-data');\n  // \"ambiguous\" = a type an app commonly parses as JSON/form even though it isn't declared as such.\n  const isAmbiguous = ct === '' || ct.startsWith('text/plain') || ct.includes('csp-report') || ct.includes('/json');\n\n  if (isMultipart) {\n    const boundary = /boundary=(\"?)([^\";]+)\\1/i.exec(contentType)?.[2];\n    if (boundary) return parseMultipart(rawBody, boundary);\n    return { body: {}, files: undefined };\n  }\n  if (isForm) {\n    const body = {};\n    for (const [k, v] of new URLSearchParams(rawBody)) body[k] = k in body ? [].concat(body[k], v) : v;\n    return { body, files: undefined };\n  }\n  if (isJson || isAmbiguous) {\n    try {\n      const parsed = JSON.parse(rawBody);\n      if (parsed && typeof parsed === 'object') return { body: parsed, files: undefined };\n    } catch {\n      /* not JSON — leave body empty; `raw`/`all` still see the verbatim text */\n    }\n  }\n  return { body: {}, files: undefined };\n}\n\nexport function parseMultipart(rawBody, boundary) {\n  const body = {};\n  const files = {};\n  for (const part of rawBody.split('--' + boundary)) {\n    // Tolerate both CRLF and LF-only line endings (some clients/proxies send bare \\n).\n    const sep = /\\r?\\n\\r?\\n/.exec(part);\n    if (!sep) continue;\n    const rawHeaders = part.slice(0, sep.index);\n    const disposition = /content-disposition:[^\\r\\n]*/i.exec(rawHeaders)?.[0];\n    if (!disposition) continue;\n    const name = /name=\"([^\"]*)\"/i.exec(disposition)?.[1];\n    if (name == null) continue;\n    const content = part.slice(sep.index + sep[0].length).replace(/\\r?\\n$/, '');\n    const filename = /filename=\"([^\"]*)\"/i.exec(disposition)?.[1];\n    if (filename !== undefined) {\n      // Capture the part's declared content-type and CONTENT (not just the filename), so rules can\n      // inspect an upload's bytes (files.<name>.content) and detect a declared-vs-actual type\n      // mismatch (files.<name>.mismatch). The content rides inside the already-capped rawBody.\n      const partType = /content-type:\\s*([^\\r\\n;]+)/i.exec(rawHeaders)?.[1]?.trim() || '';\n      const file = { filename, type: partType, content };\n      files[name] = name in files ? [].concat(files[name], file) : file;\n    } else {\n      body[name] = name in body ? [].concat(body[name], content) : content;\n    }\n  }\n  return { body, files };\n}\n\nfunction parseCookies(header) {\n  const cookies = {};\n  if (!header) {\n    return cookies;\n  }\n  for (const pair of header.split(';')) {\n    const idx = pair.indexOf('=');\n    if (idx === -1) {\n      continue;\n    }\n    cookies[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();\n  }\n  return cookies;\n}\n\nfunction defaultBlockResponse(result) {\n  return new Response(\n    JSON.stringify({\n      error: 'Blocked by Patchstack WAF',\n      message: result.message,\n      timestamp: new Date().toISOString()\n    }),\n    { status: 403, headers: { 'content-type': 'application/json' } }\n  );\n}\n\n/**\n * Returns a guard `(request) => Promise<Response|null>`. A `Response` means blocked;\n * `null` means allowed — the caller should proceed to its handler. Accepts either a\n * rules bundle (`{ firewall, whitelists, whitelist_keys }`) or a `RuleEngine` instance.\n * Fails open: a rule that throws never blocks the request.\n */\nexport function createFetchMiddleware(rulesData, options = {}) {\n  const engine =\n    rulesData && typeof rulesData.evaluate === 'function'\n      ? rulesData\n      : new RuleEngine(rulesData);\n\n  const guard = async (request) => {\n    let req;\n    let result;\n    try {\n      req = await fromFetchRequest(request); // shaping inside the try — a bad/relative request.url must fail open\n      result = engine.evaluate(req);\n    } catch (err) {\n      if (options.onError) {\n        options.onError(err);\n      }\n      return null; // fail open\n    }\n\n    if (result.blocked) {\n      if (options.onBlock) {\n        options.onBlock({\n          rule: result.rule,\n          message: result.message,\n          request: { method: req.method, url: req.url, ip: req.ip }\n        });\n      }\n      return (options.response || defaultBlockResponse)(result);\n    }\n\n    return null;\n  };\n\n  guard.engine = engine;\n  return guard;\n}\n\n/**\n * Wrap a fetch handler so every request is screened first. One-line hook:\n *   export default { fetch: wrapFetchHandler(app.fetch, rulesData) }\n */\nexport function wrapFetchHandler(handler, rulesData, options = {}) {\n  const guard = createFetchMiddleware(rulesData, options);\n  const wrapped = async (request, ...rest) => {\n    const blocked = await guard(request);\n    return blocked ?? handler(request, ...rest);\n  };\n  wrapped.engine = guard.engine;\n  return wrapped;\n}\n","// Raw Node.js / Connect adapter — for traditional Node servers where the request is a\n// `http.IncomingMessage` and the body is NOT already parsed (plain `http`, Connect,\n// Express without a body-parser, Fastify via its Node req). It buffers the body once,\n// builds the engine's request shape, and blocks or calls `next()`.\n//\n// This complements the Express `createMiddleware` (which assumes `req.body`/`req.query`\n// are already populated) and the Web-Fetch adapter (Workers/edge). Mount it FIRST, before\n// any body-parser — it consumes the stream and exposes the parsed body as `req.body`.\nimport { RuleEngine } from './engine.js';\nimport { parseBody } from './fetch.js';\n\n// Build the engine's request shape from a Node IncomingMessage + its raw body text.\nexport function fromNodeRequest(req, rawBody = '') {\n  const method = (req.method || 'GET').toUpperCase();\n\n  const headers = {};\n  for (const [key, value] of Object.entries(req.headers || {})) {\n    headers[key.toLowerCase()] = Array.isArray(value) ? value.join(', ') : value;\n  }\n\n  // An unusual Host header or req.url can make `new URL` throw; shaping must never crash the\n  // request (fail-open), so fall back to a safe base.\n  const host = headers.host || 'localhost';\n  let url;\n  try {\n    url = new URL(req.url || '/', `http://${host}`);\n  } catch {\n    try {\n      url = new URL(req.url || '/', 'http://localhost');\n    } catch {\n      url = new URL('http://localhost/');\n    }\n  }\n\n  const query = {};\n  for (const [key, value] of url.searchParams) {\n    if (key in query) {\n      query[key] = Array.isArray(query[key]) ? [...query[key], value] : [query[key], value];\n    } else {\n      query[key] = value;\n    }\n  }\n\n  const contentType = headers['content-type'] || '';\n  let body = {};\n  let files;\n  if (rawBody) {\n    // Same permissive content-type handling as the fetch adapter (+json / text/plain / no-CT bodies\n    // still populate post.<field>; multipart exposes field + file metadata) on a raw-Node server too.\n    const parsed = parseBody(rawBody, contentType);\n    body = parsed.body;\n    files = parsed.files;\n  }\n\n  const uri = url.pathname + url.search;\n  const forwarded =\n    headers['cf-connecting-ip'] || headers['x-forwarded-for'] || headers['x-real-ip'] || '';\n\n  return {\n    method,\n    url: uri,\n    originalUrl: uri,\n    query,\n    body,\n    files,\n    headers,\n    ip: forwarded.split(',')[0].trim() || (req.socket && req.socket.remoteAddress) || '',\n    cookies: parseCookies(headers.cookie),\n    // Verbatim body text: preserves literal keys (e.g. `__proto__`) that JSON.stringify drops.\n    _rawBody: rawBody\n  };\n}\n\nfunction parseCookies(header) {\n  const cookies = {};\n  if (!header) {\n    return cookies;\n  }\n  for (const pair of header.split(';')) {\n    const idx = pair.indexOf('=');\n    if (idx === -1) {\n      continue;\n    }\n    cookies[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();\n  }\n  return cookies;\n}\n\nfunction defaultBlock(res, result) {\n  res.statusCode = 403;\n  res.setHeader('content-type', 'application/json');\n  res.end(\n    JSON.stringify({\n      error: 'Blocked by Patchstack WAF',\n      message: result.message,\n      timestamp: new Date().toISOString()\n    })\n  );\n}\n\n/**\n * Connect/Express-style middleware `(req, res, next)` that buffers the body itself.\n * Accepts a `RuleEngine` instance or a `{ firewall, whitelists, whitelist_keys }` bundle.\n * Fails open: an engine error (or oversized body) never blocks the request.\n * Options: `{ maxBodyBytes = 1MiB, onBlock, onError, response }`.\n */\nexport function createNodeMiddleware(rulesData, options = {}) {\n  const engine =\n    rulesData && typeof rulesData.evaluate === 'function' ? rulesData : new RuleEngine(rulesData);\n  const maxBytes = options.maxBodyBytes ?? 1024 * 1024;\n\n  return function guard(req, res, next) {\n    const chunks = [];\n    let size = 0;\n    let overflow = false;\n\n    req.on('data', (chunk) => {\n      size += chunk.length;\n      if (size > maxBytes) {\n        overflow = true;\n        return;\n      }\n      chunks.push(chunk);\n    });\n\n    req.on('error', (err) => next(err));\n\n    req.on('end', () => {\n      let result;\n      let shaped;\n      try {\n        const rawBody = overflow ? '' : Buffer.concat(chunks).toString('utf8');\n        shaped = fromNodeRequest(req, rawBody); // shaping is inside the try too — never crash\n        result = engine.evaluate(shaped);\n      } catch (err) {\n        if (options.onError) {\n          options.onError(err);\n        }\n        return next(); // fail open\n      }\n\n      if (result.blocked) {\n        if (options.onBlock) {\n          options.onBlock({\n            rule: result.rule,\n            message: result.message,\n            request: { method: shaped.method, url: shaped.url, ip: shaped.ip }\n          });\n        }\n        return (options.response || defaultBlock)(res, result);\n      }\n\n      // Expose the parsed body downstream so a body-parser isn't also required.\n      req.body = shaped.body;\n      next();\n    });\n  };\n}\n","// Egress guard MECHANISM only. Wraps the app's outbound calls so they can be screened; the\n// block DECISION is delegated to a caller-supplied `shouldBlock` predicate (which the runtime\n// builds from egress-phase rules — see defaults.js). No policy is hardcoded here.\n// WinterCG-first: always wraps the global `fetch` (Node 18+, Workers, Bun, Deno). On Node it\n// ALSO patches `node:http`/`node:https` so outbound calls made via those modules (axios, got,\n// the raw http client, …) — which never touch `fetch` — are screened too.\n\n/**\n * @param {{ shouldBlock: (url:string, host:string|null, method:string)=>boolean,\n *           onBlock?: (info:{url:string,host:string|null,method:string})=>void,\n *           dnsScreen?: boolean,\n *           lookup?: Function }} opts\n * @returns {Promise<() => void>} uninstall (restores every patched surface)\n */\nexport async function installEgressGuard({ shouldBlock, onBlock, onSkip, dnsScreen = true, lookup, allowHosts } = {}) {\n  const restores = [];\n  if (typeof shouldBlock !== 'function') return () => {};\n  const exempt = new Set((allowHosts ?? []).map((h) => String(h).toLowerCase()));\n\n  const block = (url, host, method) => {\n    if (!shouldBlock(url, host, method)) return false;\n    onBlock?.({ url, host, method });\n    return true;\n  };\n\n  // DNS resolution, shared by the fetch wrapper and the node http path. Instead of trusting the\n  // hostname, resolve it and check the resolved address(es). On the node path we also PIN the socket\n  // to the vetted IP (no time-of-check/use gap); on fetch we can't pin without a custom undici\n  // dispatcher, so we screen the resolution but a re-resolve at connect is a residual window.\n  // Needs node:dns + node:net; absent on edge runtimes, where the hostname rules still apply.\n  let screen = null;\n  if (dnsScreen) {\n    try {\n      const resolveLookup = lookup ?? (await import('node:dns')).lookup;\n      const { isIP } = await import('node:net');\n      if (typeof resolveLookup === 'function' && typeof isIP === 'function') {\n        screen = { lookup: resolveLookup, isIP, isExempt: (h) => exempt.has(String(h).toLowerCase()) };\n      }\n    } catch {\n      screen = null; // no node:dns/net here — skip, hostname rules still apply\n    }\n  }\n\n  // A resolver failure means the destination was NOT screened by IP — the hostname check alone let it\n  // through. That's a real (if rare) coverage hole, so report it via onSkip instead of failing open\n  // silently. Still fail-open: a broken resolver must not take the app's outbound traffic down.\n  const skip = (reason, detail) => { try { onSkip?.({ phase: 'egress', reason, detail }); } catch { /* never affect traffic */ } };\n\n  // True when a hostname resolves to a disallowed address. Fail-open: any resolver error → false.\n  const resolvesToDisallowed = (url, host, method) =>\n    new Promise((resolve) => {\n      if (!screen) {\n        // No node:dns/net here (edge runtime) or screening disabled — hostname rules only.\n        if (host && dnsScreen) skip('resolver-unavailable', { host });\n        return resolve(false);\n      }\n      if (!host || screen.isIP(host) !== 0 || screen.isExempt(host)) return resolve(false);\n      try {\n        screen.lookup(host, { all: true }, (err, addresses) => {\n          if (err || !Array.isArray(addresses)) { skip('resolver-failed', { host }); return resolve(false); }\n          for (const a of addresses) {\n            const ip = a && typeof a === 'object' ? a.address : a;\n            if (ip && block(url, ip, method)) return resolve(true);\n          }\n          resolve(false);\n        });\n      } catch {\n        skip('resolver-failed', { host });\n        resolve(false);\n      }\n    });\n\n  // 1. global fetch — synchronous install, so it's active the instant this returns (no startup race).\n  const originalFetch = globalThis.fetch;\n  if (typeof originalFetch === 'function' && !originalFetch.__patchstackGuarded) {\n    const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\n    const MAX_REDIRECTS = 20;\n\n    // Screen one outbound URL: hostname/allowlist/literal-IP check, then a DNS-resolution check for\n    // real hostnames. Throws if the destination is disallowed.\n    const screenUrl = async (u, method) => {\n      let host = null;\n      try {\n        host = new URL(u).hostname;\n      } catch {\n        host = null;\n      }\n      if (block(u, host, method) || (await resolvesToDisallowed(u, host, method))) {\n        throw new Error(`Patchstack blocked an outbound request to a disallowed address: ${host ?? u}`);\n      }\n    };\n\n    const guarded = async (input, init) => {\n      let cur;\n      try {\n        cur = new Request(input, { ...(init || {}), redirect: 'manual' });\n      } catch {\n        return originalFetch(input, init); // odd input we can't normalize — fail open, don't break the caller\n      }\n      const callerRedirect = (init && init.redirect) || (input && input.redirect) || 'follow';\n\n      let url = cur.url;\n      let method = cur.method;\n      await screenUrl(url, method);\n\n      // Caller manages redirects itself (manual/error) → screen once, hand back the raw response.\n      if (callerRedirect !== 'follow') return originalFetch(input, init);\n\n      // Otherwise follow redirects ourselves so EVERY hop is screened. Native `follow` re-resolves\n      // internally and would let a 3xx to an internal address slip past the initial check — SSRF via\n      // an open redirect. Buffer the body once (a stream can't be re-read) so 307/308 can replay it.\n      const headers = new Headers(cur.headers);\n      const signal = cur.signal;\n      let body = method === 'GET' || method === 'HEAD' ? undefined : await cur.clone().arrayBuffer();\n\n      for (let hop = 0; ; hop++) {\n        const resp = await originalFetch(\n          hop === 0 ? cur : new Request(url, { method, headers, body, redirect: 'manual', signal }),\n        );\n        const location = REDIRECT_STATUSES.has(resp.status) ? resp.headers.get('location') : null;\n        if (!location) return resp;\n        if (hop >= MAX_REDIRECTS) throw new Error('Patchstack blocked an outbound request: too many redirects');\n\n        const next = new URL(location, url).href;\n        // Fetch redirect semantics: 303, and 301/302 on a POST, become a bodyless GET.\n        if (resp.status === 303 || ((resp.status === 301 || resp.status === 302) && method === 'POST')) {\n          method = 'GET';\n          body = undefined;\n          headers.delete('content-type');\n          headers.delete('content-length');\n        }\n        // Drop credentials on a cross-origin hop, mirroring the browser.\n        if (new URL(next).origin !== new URL(url).origin) {\n          headers.delete('authorization');\n          headers.delete('cookie');\n        }\n        await screenUrl(next, method);\n        url = next;\n      }\n    };\n    guarded.__patchstackGuarded = true;\n    globalThis.fetch = guarded;\n    restores.push(() => {\n      if (globalThis.fetch === guarded) globalThis.fetch = originalFetch;\n    });\n  }\n\n  // node:http / node:https — best-effort; absent on Workers/Deno-without-node (import throws).\n  for (const moduleName of ['node:http', 'node:https']) {\n    try {\n      const mod = await import(moduleName);\n      const restore = patchHttpModule(mod.default ?? mod, block, screen);\n      if (restore) restores.push(restore);\n    } catch {\n      /* module not available on this runtime — skip */\n    }\n  }\n\n  // WebSocket egress is intentionally NOT screened. The WebSocket constructor is synchronous, so\n  // the only check possible inline is a textual hostname match — which can't offer the\n  // DNS-resolution guarantee the fetch and node:http/https paths give (a name that resolves to an\n  // internal address would pass). A connection-pinning dispatcher could close that, but the\n  // server-side, attacker-controlled-WebSocket sink is rare, and a partial hostname-only check\n  // over-promises the control. Outbound SSRF screening covers fetch + node:http/https.\n\n  return () => {\n    for (const restore of restores) {\n      try {\n        restore();\n      } catch {\n        /* ignore */\n      }\n    }\n  };\n}\n\n// Wrap http(s).request/get so a blocked destination throws before the socket opens.\nfunction patchHttpModule(http, block, screen) {\n  if (!http || typeof http.request !== 'function' || http.__patchstackGuarded) return null;\n  const originalRequest = http.request;\n  const originalGet = http.get;\n\n  const wrap = (original) =>\n    function (...args) {\n      const target = extractHttpTarget(args);\n      if (target && block(target.url, target.host, target.method)) {\n        throw new Error(`Patchstack blocked an outbound request to a disallowed address: ${target.host ?? target.url}`);\n      }\n      // DNS screen: only for real hostnames (a literal IP was already covered by the check above),\n      // and skip an explicitly allowlisted host (the operator trusts it — don't second-guess its DNS).\n      if (target && screen && target.host && screen.isIP(target.host) === 0 && !screen.isExempt(target.host)) {\n        try {\n          args = withScreeningLookup(args, target, block, screen.lookup);\n        } catch {\n          /* injection failed — proceed unscreened (fail-open) */\n        }\n      }\n      return original.apply(this, args);\n    };\n\n  const guardedRequest = wrap(originalRequest);\n  http.request = guardedRequest;\n  let guardedGet;\n  if (typeof originalGet === 'function') {\n    guardedGet = wrap(originalGet);\n    http.get = guardedGet;\n  }\n  http.__patchstackGuarded = true;\n\n  return () => {\n    // Only restore if our wrapper is still installed — don't clobber a wrapper another library\n    // (an APM agent, etc.) layered on top of us after install.\n    if (http.request === guardedRequest) http.request = originalRequest;\n    if (guardedGet && http.get === guardedGet) http.get = originalGet;\n    delete http.__patchstackGuarded;\n  };\n}\n\n// http.request accepts (url), (url, options), or (options) — with an optional trailing callback.\nfunction extractHttpTarget(args) {\n  const first = args[0];\n  try {\n    if (typeof first === 'string' || first instanceof URL) {\n      const url = new URL(String(first));\n      const opts = args.find((a) => a && typeof a === 'object' && !(a instanceof URL));\n      return { url: url.href, host: url.hostname, method: (opts && opts.method) || 'GET' };\n    }\n    if (first && typeof first === 'object') {\n      // Node defaults an absent host to localhost — reflect that so the block/screen see a real target.\n      const host = normalizeHost(first.hostname || first.host) || 'localhost';\n      const protocol = first.protocol || 'http:';\n      const port = first.port ? `:${first.port}` : '';\n      const path = first.path || '/';\n      return { url: `${protocol}//${host}${port}${path}`, host, method: first.method || 'GET' };\n    }\n  } catch {\n    /* fall through */\n  }\n  return null;\n}\n\n// Extract the bare host from a node http(s) options `host`/`hostname`, WITHOUT mangling IPv6.\n// `[::1]:8080` → `::1`, bare `::1`/`fe80::1` → unchanged, `example.com:443` → `example.com`.\n// (isInternalHost strips brackets and matches ::1 / fe80: / fc / fd, so this must not corrupt them.)\nfunction normalizeHost(raw) {\n  const host = String(raw || '').trim();\n  const bracketed = /^\\[([^\\]]+)\\]/.exec(host);\n  if (bracketed) return bracketed[1];\n  if ((host.match(/:/g) || []).length > 1) return host; // bare IPv6 — no host:port to split\n  return host.split(':')[0];\n}\n\n// Given the addresses a hostname resolved to, return the first one the policy blocks (else null).\n// Reuses the same `block` predicate as the hostname check, so egress rules + allowlist apply to\n// the resolved IP too. Exported for tests.\nexport function screenResolved(addresses, target, block) {\n  for (const a of addresses || []) {\n    const ip = a && typeof a === 'object' ? a.address : a;\n    if (ip && block(target.url, ip, target.method)) return ip;\n  }\n  return null;\n}\n\n// Build a DNS `lookup` that screens every resolved address before the socket connects, then hands\n// back the vetted addresses (pinning the connection to what we checked). A blocked address errors\n// the connection; a resolver error or our own failure falls through to normal resolution (fail-open).\nfunction withScreeningLookup(args, target, block, lookup) {\n  const screeningLookup = (hostname, options, callback) => {\n    let opts = options;\n    let cb = callback;\n    if (typeof opts === 'function') {\n      cb = opts;\n      opts = {};\n    }\n    if (!opts || typeof opts !== 'object') opts = {};\n    try {\n      lookup(hostname, { ...opts, all: true }, (err, addresses) => {\n        if (err) return cb(err);\n        const list = Array.isArray(addresses) ? addresses : [];\n        const blocked = screenResolved(list, target, block);\n        if (blocked) {\n          return cb(new Error(`Patchstack blocked an outbound request to a disallowed address: ${target.host} resolved to ${blocked}`));\n        }\n        if (opts.all) return cb(null, list);\n        const first = list[0];\n        if (!first) return cb(new Error(`Patchstack: could not resolve ${hostname}`));\n        return cb(null, first.address, first.family);\n      });\n    } catch {\n      // Our screening threw — fall back to a plain resolution so we never break a request ourselves.\n      try {\n        lookup(hostname, opts, cb);\n      } catch {\n        cb(new Error(`Patchstack: lookup failed for ${hostname}`));\n      }\n    }\n  };\n  return injectLookupOption(args, screeningLookup);\n}\n\n// Return a new args array for http(s).request with our `lookup` set on the options object (cloned,\n// never mutating the caller's object), inserting an options object when the call didn't pass one.\nfunction injectLookupOption(args, lookup) {\n  const first = args[0];\n  if (first && typeof first === 'object' && !(first instanceof URL)) {\n    return [{ ...first, lookup }, ...args.slice(1)];\n  }\n  const rest = args.slice(1);\n  const optIdx = rest.findIndex((a) => a && typeof a === 'object' && !(a instanceof URL));\n  if (optIdx !== -1) {\n    const next = [...rest];\n    next[optIdx] = { ...rest[optIdx], lookup };\n    return [first, ...next];\n  }\n  const cbIdx = rest.findIndex((a) => typeof a === 'function');\n  if (cbIdx === -1) return [first, { lookup }, ...rest];\n  return [first, ...rest.slice(0, cbIdx), { lookup }, ...rest.slice(cbIdx)];\n}\n","// Default response- and egress-phase rule bundles, as JS constants (not JSON files) so\n// tsup bundles them into dist/protect.js without a copy step. These are just rules —\n// override per app via createProtection({ responseRules, egressRules }) or extend by\n// adding phase-tagged rules to the delivered bundle. Patterns are high-precision\n// (low false positive): structural markers a real secret has and normal content doesn't.\n//\n// Each rule carries a `prefilter`: cheap literal anchor(s) that MUST appear in the body for the\n// regex to have any chance of matching. The response screener runs the (expensive) regex only when\n// an anchor is present (case-insensitive), so a body with no candidate — the common case — skips\n// the scan entirely. This cuts CPU/latency and shrinks the regex/ReDoS surface. (Honored by the\n// response phase once the prefilter mechanism lands; a no-op before that.)\n\n// Response phase — secret / info exposure. Default action `redact` masks only the\n// offending span and still serves the page (a legit response that leaks one key gets\n// that key masked, not withheld). Use `action: \"block\"` to withhold the whole response.\nexport const DEFAULT_RESPONSE_RULES = [\n  {\n    id: 'resp-private-key',\n    title: 'Private key in response body',\n    phase: 'response',\n    category: 'secret-exposure',\n    action: 'redact',\n    prefilter: ['PRIVATE KEY'],\n    rule_v2: [{ parameter: 'response.body', match: { type: 'regex', value: '/-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/' } }]\n  },\n  {\n    id: 'resp-aws-access-key',\n    title: 'AWS access key id in response body',\n    phase: 'response',\n    category: 'secret-exposure',\n    action: 'redact',\n    prefilter: ['AKIA', 'ASIA'],\n    rule_v2: [{ parameter: 'response.body', match: { type: 'regex', value: '/\\\\b(?:AKIA|ASIA)[0-9A-Z]{16}\\\\b/' } }]\n  },\n  {\n    id: 'resp-gcp-api-key',\n    title: 'Google API key in response body',\n    phase: 'response',\n    category: 'secret-exposure',\n    action: 'redact',\n    prefilter: ['AIza'],\n    rule_v2: [{ parameter: 'response.body', match: { type: 'regex', value: '/\\\\bAIza[0-9A-Za-z_-]{35}\\\\b/' } }]\n  },\n  {\n    id: 'resp-vendor-api-key',\n    title: 'Vendor API key / token in response body',\n    phase: 'response',\n    category: 'secret-exposure',\n    action: 'redact',\n    // High-signal, prefix-anchored provider tokens that never legitimately appear in a response\n    // body: Stripe (sk_live_/rk_live_), GitHub (gh[opsu]_ / github_pat_), GitLab (glpat-),\n    // Slack (xox[baprs]-), Anthropic (sk-ant-), Google OAuth (ya29.), npm (npm_). Trailing\n    // (?![0-9A-Za-z]) instead of \\\\b since some tokens end in - / _ .\n    prefilter: ['sk_live_', 'rk_live_', 'ghp_', 'gho_', 'ghs_', 'ghu_', 'github_pat_', 'glpat-', 'xox', 'sk-ant-', 'ya29.', 'npm_'],\n    rule_v2: [{ parameter: 'response.body', match: { type: 'regex', value: '/\\\\b(?:sk_live_[0-9A-Za-z]{16,}|rk_live_[0-9A-Za-z]{16,}|gh[opsu]_[0-9A-Za-z]{36}|github_pat_[0-9A-Za-z_]{60,}|glpat-[0-9A-Za-z_-]{20,}|xox[baprs]-[0-9A-Za-z-]{10,}|sk-ant-[0-9A-Za-z_-]{20,}|ya29\\\\.[0-9A-Za-z_-]{20,}|npm_[0-9A-Za-z]{36})(?![0-9A-Za-z])/' } }]\n  },\n  {\n    id: 'resp-jwt',\n    title: 'JWT in response body',\n    phase: 'response',\n    category: 'secret-exposure',\n    action: 'redact',\n    prefilter: ['eyJ'],\n    rule_v2: [{ parameter: 'response.body', match: { type: 'regex', value: '/\\\\beyJ[A-Za-z0-9_-]{8,}\\\\.eyJ[A-Za-z0-9_-]{8,}\\\\.[A-Za-z0-9_-]{8,}\\\\b/' } }]\n  },\n  {\n    id: 'resp-db-connection-string',\n    title: 'Database connection string with credentials in response body',\n    phase: 'response',\n    category: 'secret-exposure',\n    action: 'redact',\n    prefilter: ['mongodb', 'postgres', 'mysql', 'redis', 'amqp'],\n    rule_v2: [{ parameter: 'response.body', match: { type: 'regex', value: '/\\\\b(?:mongodb(?:\\\\+srv)?|postgres(?:ql)?|mysql|redis|amqps?):\\\\/\\\\/[^\\\\s:@\\\\/]+:[^\\\\s:@\\\\/]+@/i' } }]\n  },\n  {\n    id: 'resp-stack-trace',\n    title: 'Node stack trace leaking in response body',\n    phase: 'response',\n    category: 'info-exposure',\n    action: 'redact',\n    // No prefilter: a Node stack frame has no single distinctive literal (` at ` is too common to\n    // gate on). The pattern is linearly bounded per line, so it runs on every screened body.\n    rule_v2: [{ parameter: 'response.body', match: { type: 'regex', value: '/\\\\n\\\\s+at\\\\s+.+\\\\(.+:\\\\d+:\\\\d+\\\\)/' } }]\n  },\n  {\n    id: 'resp-sql-error',\n    title: 'SQL / ORM error disclosure in response body',\n    phase: 'response',\n    category: 'info-exposure',\n    action: 'redact',\n    prefilter: ['SQLSTATE', 'Sequelize', 'ER_', 'ORA-', 'PG::', 'SQLITE_ERROR', 'SQL syntax'],\n    rule_v2: [{ parameter: 'response.body', match: { type: 'regex', value: '/(SQLSTATE\\\\[[0-9A-Z]+\\\\]|SequelizeDatabaseError|ER_[A-Z_]+|ORA-\\\\d{5}|PG::[A-Za-z]+Error|SQLITE_ERROR|You have an error in your SQL syntax)/i' } }]\n  },\n  {\n    id: 'resp-exception-trace',\n    title: 'Backend exception / stack trace disclosure in response body',\n    phase: 'response',\n    category: 'info-exposure',\n    action: 'redact',\n    // Multi-language exception/traceback signatures a normal API response never carries:\n    // Python traceback, Java \"Exception in thread\", .NET System.*Exception, JVM stack frames,\n    // Go goroutine dumps. (Node `at fn (file:line:col)` frames are handled by resp-stack-trace.)\n    prefilter: ['Traceback', 'Exception in thread', 'System.', 'goroutine ', '.java:', '.kt:', '.scala:', '.rb:', '.py:', '.cs:'],\n    rule_v2: [{ parameter: 'response.body', match: { type: 'regex', value: '/(Traceback \\\\(most recent call last\\\\)|Exception in thread \"|System\\\\.[A-Za-z.]+Exception|\\\\bat [\\\\w.$]+\\\\([\\\\w]+\\\\.(?:java|kt|scala|rb|py|cs):\\\\d+\\\\)|goroutine \\\\d+ \\\\[)/' } }]\n  }\n];\n\n// Egress phase — SSRF: block the app's outbound calls to internal / metadata addresses.\nexport const DEFAULT_EGRESS_RULES = [\n  {\n    id: 'egress-internal-address',\n    title: 'Outbound request to an internal / metadata address (SSRF)',\n    phase: 'egress',\n    category: 'ssrf',\n    rule_v2: [{ parameter: 'egress.host', match: { type: 'internal_host' } }]\n  }\n];\n","// Full-page \"Access Denied\" block view, ported from the Patchstack WordPress plugin's\n// sample.php. Served (instead of JSON) when a BLOCKED request is a top-level document navigation\n// rather than an XHR/fetch — so a user who browses into a blocked URL sees a branded page, while\n// programmatic clients still get JSON. Self-contained (inline CSS + base64 SVGs); exposes no WAF\n// narrative and no rule details.\n\nfunction escapeHtml(s) {\n  return String(s).replace(/[&<>\"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' }[c]));\n}\n\n/** @param {{ url?: string, code?: string }} opts @returns {string} a complete HTML document */\nexport function renderBlockPage({ url = '', code = 'patchstack' } = {}) {\n  const safeUrl = escapeHtml(url);\n  const safeCode = escapeHtml(code || 'patchstack');\n  return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <style type=\"text/css\">\n\t\t.access-denied,.site-url-text{letter-spacing:.01em;color:#fff}body{background:#111216}.main-container{display:flex;justify-content:center;flex-direction:column;align-items:center}.container{width:688px;height:456px;background:#1c1e22;border-radius:16px;margin-top:120px}.content{height:330px;margin:64px}.access-denied{font-family:Verdana;font-style:normal;font-weight:600;font-size:24px;line-height:32px;display:flex;align-items:center}.descp-text,.site-url{display:flex;align-items:center}.site-url{margin-top:32px;width:560px;height:64px;background:#26282c;border-radius:4px}.reason-code-text,.site-url-text{font-family:Verdana;font-style:normal;border:none;background:#26282c}.site-url-text{text-overflow: ellipsis;font-weight:400;font-size:16px;line-height:24px;margin-left:16px;width:85%}.copy-icon{width:19px;height:22px;margin-left:20px}.copy-icon:hover{cursor:pointer}.reason-code-text{font-weight:600;font-size:24px;line-height:32px;letter-spacing:.01em;color:#AFE614;margin-left:16px;width:85%}.descp-text,.return-text{font-size:16px;line-height:24px;letter-spacing:.01em;font-weight:400}.return-text:hover{color: #AFE614}.descp-text,.logoText,.return-text,.secured-text{font-family:Verdana;font-style:normal;color:#fff}.descp{margin-top:32px;width:560px}.bottom-second-containers,.bottom-text-containers{align-items:center;display:flex}.bottom-container{margin-top:40px;display:flex;width:688px}.bottom-second-containers{margin-left:auto}.arrow-vector{margin-left:20px}.return-text{text-align:center;margin-left:12.59px;text-decoration:none}.secured-text{font-weight:400;font-size:11.2px;line-height:16px;display:flex;align-items:center;letter-spacing:.02em;margin-right:8px}.logoText{font-weight:600;font-size:16px;line-height:24px;letter-spacing:.01em;flex:none;order:1;flex-grow:0}.patch-logo{width:120px}.mobile-bottom-container{margin-top:40px;width:372px;display:none}.mobile-bottom-second-containers{margin-top:64px;display:flex;margin-left:16.5px}@media only screen and (max-width:900px){.container{background:#111216;width:370px;height:auto;margin-top:0}.content{margin-left:16.5px}.descp,.site-url{width:340px}.site-url-text{font-weight:400;font-size:14.4px;line-height:20px;letter-spacing:.02em;width:80%}.copy-icon{margin-left:20px}.reason-code-text{font-size:16px;line-height:32px;letter-spacing:.02em;margin-left:16px;width:80%}.descp-text,.return-text{font-size:14.4px;line-height:20px}.descp-text{display:flex;align-items:center;letter-spacing:.02em}.bottom-container{display:none}.mobile-bottom-container{display:block}.return-text{text-align:center;letter-spacing:.01em;color:#fff;margin-left:9.73px}}\n    </style>\n    <title>Access Denied</title>\n</head>\n<body>\n    <div class=\"main-container\">\n        <div class=\"container\">\n            <div class=\"content\">\n                <span class=\"access-denied\">Access Denied</span>\n                <div class=\"site-url\">\n                    <input id=\"url\" class=\"site-url-text\" type=\"text\"\n                        value=\"${safeUrl}\" readonly>\n                    <img class=\"copy-icon\" src=\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkiIGhlaWdodD0iMjMiIHZpZXdCb3g9IjAgMCAxOSAyMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE0IDAuMDIzNDM3NUgwVjE2LjAyMzRIMlYyLjAyMzQ0SDE0VjAuMDIzNDM3NVpNMTkgNC4wMjM0NEg0VjIyLjAyMzRIMTlWNC4wMjM0NFpNMTcgMjAuMDIzNEg2VjYuMDIzNDRIMTdWMjAuMDIzNFoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=\" alt=\"Copy Text\" onmouseover=\"hover(this);\" onmouseout=\"unhover(this);\" onclick=\"copyText(id='url')\">\n                </div>\n                <div class=\"site-url\">\n                    <input id=\"response\" class=\"reason-code-text\" type=\"text\" value=\"${safeCode}\" readonly>\n                    <img class=\"copy-icon\" src=\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkiIGhlaWdodD0iMjMiIHZpZXdCb3g9IjAgMCAxOSAyMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE0IDAuMDIzNDM3NUgwVjE2LjAyMzRIMlYyLjAyMzQ0SDE0VjAuMDIzNDM3NVpNMTkgNC4wMjM0NEg0VjIyLjAyMzRIMTlWNC4wMjM0NFpNMTcgMjAuMDIzNEg2VjYuMDIzNDRIMTdWMjAuMDIzNFoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=\" alt=\"Copy Text\" onmouseover=\"hover(this);\" onmouseout=\"unhover(this);\" onclick=\"copyText(id='response')\">\n                </div>\n                <div class=\"descp\">\n                    <span class=\"descp-text\">This request has been blocked by Patchstack. If this message persists and you are a legitimate user, contact the site administrator with the reference above.</span>\n                </div>\n            </div>\n        </div>\n        <div class=\"bottom-container\">\n            <div class=\"bottom-text-containers\">\n                <img class=\"arrow-vector\" src=\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iOCIgaGVpZ2h0PSIxMyIgdmlld0JveD0iMCAwIDggMTMiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik03LjQxIDEuNDMzNDRMNiAwLjAyMzQzNzVMMCA2LjAyMzQ0TDYgMTIuMDIzNEw3LjQxIDEwLjYxMzRMMi44MyA2LjAyMzQ0TDcuNDEgMS40MzM0NFoiIGZpbGw9IiNBRkU2MTQiLz4KPC9zdmc+Cg==\" alt=\"Arrow Left\">\n                <a href=\"/\" class=\"return-text\">Return to homepage</a>\n            </div>\n            <div class=\"bottom-second-containers\">\n                <span class=\"secured-text\">This website is secured by</span>\n                <a href=\"https://patchstack.com\" class=\"logoText\">\n                    <img class=\"patch-logo\" src=\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTg0IiBoZWlnaHQ9IjIyIiB2aWV3Qm94PSIwIDAgMTg0IDIyIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTUwLjQwMDEgMTEuNTAwOEM1MC40MDAxIDkuMTAwNzggNDkuMzAwMSA4LjEwMDc4IDQ2LjYwMDEgOC4xMDA3OEM0NC4wMDAxIDguMTAwNzggNDIuNzAwMSA5LjIwMDc4IDQyLjcwMDEgMTEuNTAwOEM0Mi43MDAxIDEzLjgwMDggNDQuMDAwMSAxNC45MDA4IDQ2LjYwMDEgMTQuOTAwOEM0OS4zMDAxIDE0LjkwMDggNTAuNDAwMSAxMy44MDA4IDUwLjQwMDEgMTEuNTAwOFpNNTMuNDAwMSAxMS41MDA4QzUzLjQwMDEgMTUuMzAwOCA1MS4zMDAxIDE3LjYwMDggNDcuNDAwMSAxNy42MDA4QzQ1LjQwMDEgMTcuNjAwOCA0My42MDAxIDE2LjUwMDggNDIuNzAwMSAxNC41MDA4VjIxLjUwMDhIMzkuNjAwMVY1LjYwMDc4SDQyLjcwMDFWOC41MDA3OEM0My42MDAxIDYuNTAwNzggNDUuNDAwMSA1LjMwMDc4IDQ3LjUwMDEgNS4zMDA3OEM1MS40MDAxIDUuMzAwNzggNTMuNDAwMSA3LjcwMDc4IDUzLjQwMDEgMTEuNTAwOFoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNjYuNDAwMSAxMS40OTg0QzY2LjQwMDEgOS4xOTg0NCA2NS4xMDAxIDguMDk4NDQgNjIuNTAwMSA4LjA5ODQ0QzU5LjgwMDEgOC4wOTg0NCA1OC43MDAxIDkuMDk4NDQgNTguNzAwMSAxMS40OTg0QzU4LjcwMDEgMTMuNzk4NCA1OS44MDAxIDE0Ljg5ODQgNjIuNTAwMSAxNC44OTg0QzY1LjEwMDEgMTQuODk4NCA2Ni40MDAxIDEzLjc5ODQgNjYuNDAwMSAxMS40OTg0Wk02Ni4zMDAxIDUuNTk4NDRINjkuNDAwMVYxNy4zOTg0SDY2LjMwMDFWMTQuNDk4NEM2NS40MDAxIDE2LjQ5ODQgNjMuNzAwMSAxNy42OTg0IDYxLjYwMDEgMTcuNjk4NEM1Ny43MDAxIDE3LjY5ODQgNTUuNjAwMSAxNS4yOTg0IDU1LjYwMDEgMTEuNTk4NEM1NS42MDAxIDcuNzk4NDQgNTcuNjAwMSA1LjM5ODQ0IDYxLjQwMDEgNS4zOTg0NEM2My41MDAxIDUuMzk4NDQgNjUuNDAwMSA2LjU5ODQ0IDY2LjIwMDEgOC41OTg0NFY1LjU5ODQ0SDY2LjMwMDFaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTgxLjM5OTkgOC4zSDc3LjM5OTlWMTQuN0g4MS4wOTk5VjE3LjRINzcuOTk5OUM3NS43OTk5IDE3LjQgNzQuMjk5OSAxNS45IDc0LjI5OTkgMTMuN1Y4LjNINzEuMzk5OVY1LjZINzQuMjk5OVYySDc3LjM5OTlWNS41SDgxLjM5OTlWOC4zWiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik05My42OTk5IDEyLjIwMDhMOTYuNjk5OSAxMi45MDA4Qzk1Ljk5OTkgMTYuMDAwOCA5My42OTk5IDE3LjYwMDggODkuOTk5OSAxNy42MDA4Qzg3Ljc5OTkgMTcuNjAwOCA4Ni4wOTk5IDE3LjAwMDggODQuNzk5OSAxNS45MDA4QzgzLjQ5OTkgMTQuODAwOCA4Mi44OTk5IDEzLjMwMDggODIuODk5OSAxMS41MDA4QzgyLjg5OTkgOS42MDA3OCA4My40OTk5IDguMTAwNzggODQuNzk5OSA3LjAwMDc4Qzg2LjA5OTkgNS45MDA3OCA4Ny43OTk5IDUuMzAwNzggODkuOTk5OSA1LjMwMDc4QzkzLjY5OTkgNS4zMDA3OCA5NS45OTk5IDYuOTAwNzggOTYuNjk5OSAxMC4wMDA4TDkzLjY5OTkgMTAuNzAwOEM5My4yOTk5IDguODAwNzggOTIuMjk5OSA4LjEwMDc4IDg5Ljg5OTkgOC4xMDA3OEM4Ni45OTk5IDguMTAwNzggODUuODk5OSA5LjIwMDc4IDg1Ljg5OTkgMTEuNTAwOEM4NS44OTk5IDEzLjgwMDggODYuOTk5OSAxNC45MDA4IDg5Ljg5OTkgMTQuOTAwOEM5Mi4yOTk5IDE0LjkwMDggOTMuMjk5OSAxNC4yMDA4IDkzLjY5OTkgMTIuMjAwOFoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTExLjggMTAuNlYxNy40SDEwOC43VjExLjJDMTA4LjcgOSAxMDcuOCA4LjEgMTA1LjkgOC4xQzEwMy42IDguMSAxMDIuNCA5LjMgMTAyLjQgMTEuN1YxNy4zSDk5LjI5OThWMC41SDEwMi40VjguM0MxMDMuMSA2LjMgMTA0LjYgNS4zIDEwNyA1LjNDMTEwLjIgNS4zIDExMS44IDcuMSAxMTEuOCAxMC42WiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMTQuMSAxNC4wOTg0TDExNy4xIDEzLjI5ODRDMTE3LjQgMTQuNzk4NCAxMTguMyAxNS4yOTg0IDEyMC4yIDE1LjI5ODRDMTIxLjggMTUuMjk4NCAxMjIuNyAxNC44OTg0IDEyMi43IDE0LjA5ODRDMTIyLjcgMTMuMjk4NCAxMjIuMiAxMi45OTg0IDEyMC42IDEyLjc5ODRMMTE4LjIgMTIuNDk4NEMxMTUuOSAxMi4xOTg0IDExNC41IDEwLjg5ODQgMTE0LjUgOC45OTg0NEMxMTQuNSA2Ljc5ODQ0IDExNi41IDUuMzk4NDQgMTE5LjggNS4zOTg0NEMxMjMuMSA1LjM5ODQ0IDEyNSA2LjY5ODQ0IDEyNS41IDguODk4NDRMMTIyLjUgOS41OTg0NEMxMjIuMyA4LjA5ODQ0IDEyMS41IDcuNjk4NDQgMTE5LjkgNy42OTg0NEMxMTguNCA3LjY5ODQ0IDExNy42IDguMDk4NDQgMTE3LjYgOC44OTg0NEMxMTcuNiA5LjU5ODQ0IDExOC4xIDkuOTk4NDQgMTE5LjMgMTAuMDk4NEwxMjIuMiAxMC40OTg0QzEyNC40IDEwLjc5ODQgMTI1LjggMTEuOTk4NCAxMjUuOCAxMy44OTg0QzEyNS44IDE2LjI5ODQgMTIzLjcgMTcuNzk4NCAxMjAuMSAxNy43OTg0QzExNi43IDE3LjU5ODQgMTE0LjUgMTYuMTk4NCAxMTQuMSAxNC4wOTg0WiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMzYuNyA4LjNIMTMyLjdWMTQuN0gxMzYuNFYxNy40SDEzMy4zQzEzMS4xIDE3LjQgMTI5LjYgMTUuOSAxMjkuNiAxMy43VjguM0gxMjYuN1Y1LjZIMTI5LjZWMkgxMzIuN1Y1LjVIMTM2LjdWOC4zWiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNDkuMiAxMS40OTg0QzE0OS4yIDkuMTk4NDQgMTQ3LjkgOC4wOTg0NCAxNDUuMyA4LjA5ODQ0QzE0Mi42IDguMDk4NDQgMTQxLjUgOS4wOTg0NCAxNDEuNSAxMS40OTg0QzE0MS41IDEzLjc5ODQgMTQyLjYgMTQuODk4NCAxNDUuMyAxNC44OTg0QzE0Ny45IDE0Ljg5ODQgMTQ5LjIgMTMuNzk4NCAxNDkuMiAxMS40OTg0Wk0xNDkuMSA1LjU5ODQ0SDE1Mi4yVjE3LjM5ODRIMTQ5LjFWMTQuNDk4NEMxNDguMiAxNi40OTg0IDE0Ni41IDE3LjY5ODQgMTQ0LjQgMTcuNjk4NEMxNDAuNSAxNy42OTg0IDEzOC40IDE1LjI5ODQgMTM4LjQgMTEuNTk4NEMxMzguNCA3Ljc5ODQ0IDE0MC40IDUuMzk4NDQgMTQ0LjIgNS4zOTg0NEMxNDYuMyA1LjM5ODQ0IDE0OC4yIDYuNTk4NDQgMTQ5IDguNTk4NDRWNS41OTg0NEgxNDkuMVoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTY1LjYgMTIuMjAwOEwxNjguNiAxMi45MDA4QzE2Ny45IDE2LjAwMDggMTY1LjYgMTcuNjAwOCAxNjEuOSAxNy42MDA4QzE1OS43IDE3LjYwMDggMTU4IDE3LjAwMDggMTU2LjcgMTUuOTAwOEMxNTUuNCAxNC44MDA4IDE1NC44IDEzLjMwMDggMTU0LjggMTEuNTAwOEMxNTQuOCA5LjYwMDc4IDE1NS40IDguMTAwNzggMTU2LjcgNy4wMDA3OEMxNTggNS45MDA3OCAxNTkuNyA1LjMwMDc4IDE2MS45IDUuMzAwNzhDMTY1LjYgNS4zMDA3OCAxNjcuOSA2LjkwMDc4IDE2OC42IDEwLjAwMDhMMTY1LjYgMTAuNzAwOEMxNjUuMiA4LjgwMDc4IDE2NC4yIDguMTAwNzggMTYxLjggOC4xMDA3OEMxNTguOSA4LjEwMDc4IDE1Ny44IDkuMjAwNzggMTU3LjggMTEuNTAwOEMxNTcuOCAxMy44MDA4IDE1OC45IDE0LjkwMDggMTYxLjggMTQuOTAwOEMxNjQuMSAxNC45MDA4IDE2NS4xIDE0LjIwMDggMTY1LjYgMTIuMjAwOFoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTgwLjI1NyAxNy40TDE3Ni42NTcgMTIuM0wxNzQuMTU3IDE0LjZWMTcuNEgxNzEuMTU3VjAuNUgxNzQuMTU3VjExLjFMMTc5Ljg1NyA1LjZIMTgzLjc1N0wxNzguNTU3IDEwLjVMMTgzLjk1NyAxNy40SDE4MC4yNTdaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTAgMjEuNTAwOEg3LjNWMTYuMzAwOEgwVjIxLjUwMDhaIiBmaWxsPSIjQUZFNjE0Ii8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNy4yOTk4IDIxLjUwMDhIMTQuNTk5OFYxNi4zMDA4SDcuMjk5OFYyMS41MDA4WiIgZmlsbD0iIzZFQkUwMCIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTE0LjYwMDEgMTYuM0gyOS4yMDAxVjAuNUgxNC42MDAxVjE2LjNaIiBmaWxsPSIjQUZFNjE0Ii8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMCAxMUgxNC42VjAuNUgwVjExWiIgZmlsbD0iIzZFQkUwMCIvPgo8L3N2Zz4K\" alt=\"Patchstack Logo\">\n\t\t\t\t</a>\n            </div>\n        </div>\n    \n        <div class=\"mobile-bottom-container\">\n            <div class=\"mobile-bottom-text-containers\">\n                <img class=\"arrow-vector\" src=\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iOCIgaGVpZ2h0PSIxMyIgdmlld0JveD0iMCAwIDggMTMiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik03LjQxIDEuNDMzNDRMNiAwLjAyMzQzNzVMMCA2LjAyMzQ0TDYgMTIuMDIzNEw3LjQxIDEwLjYxMzRMMi44MyA2LjAyMzQ0TDcuNDEgMS40MzM0NFoiIGZpbGw9IiNBRkU2MTQiLz4KPC9zdmc+Cg==\" alt=\"Arrow Left\">\n                <a href=\"/\" class=\"return-text\">Return to homepage</a>\n            </div>\n            <div class=\"mobile-bottom-second-containers\">\n                <span class=\"secured-text\">This website is secured by</span>\n                <a href=\"https://patchstack.com\" class=\"logoText\">\n                    <img class=\"patch-logo\" src=\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTg0IiBoZWlnaHQ9IjIyIiB2aWV3Qm94PSIwIDAgMTg0IDIyIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTUwLjQwMDEgMTEuNTAwOEM1MC40MDAxIDkuMTAwNzggNDkuMzAwMSA4LjEwMDc4IDQ2LjYwMDEgOC4xMDA3OEM0NC4wMDAxIDguMTAwNzggNDIuNzAwMSA5LjIwMDc4IDQyLjcwMDEgMTEuNTAwOEM0Mi43MDAxIDEzLjgwMDggNDQuMDAwMSAxNC45MDA4IDQ2LjYwMDEgMTQuOTAwOEM0OS4zMDAxIDE0LjkwMDggNTAuNDAwMSAxMy44MDA4IDUwLjQwMDEgMTEuNTAwOFpNNTMuNDAwMSAxMS41MDA4QzUzLjQwMDEgMTUuMzAwOCA1MS4zMDAxIDE3LjYwMDggNDcuNDAwMSAxNy42MDA4QzQ1LjQwMDEgMTcuNjAwOCA0My42MDAxIDE2LjUwMDggNDIuNzAwMSAxNC41MDA4VjIxLjUwMDhIMzkuNjAwMVY1LjYwMDc4SDQyLjcwMDFWOC41MDA3OEM0My42MDAxIDYuNTAwNzggNDUuNDAwMSA1LjMwMDc4IDQ3LjUwMDEgNS4zMDA3OEM1MS40MDAxIDUuMzAwNzggNTMuNDAwMSA3LjcwMDc4IDUzLjQwMDEgMTEuNTAwOFoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNjYuNDAwMSAxMS40OTg0QzY2LjQwMDEgOS4xOTg0NCA2NS4xMDAxIDguMDk4NDQgNjIuNTAwMSA4LjA5ODQ0QzU5LjgwMDEgOC4wOTg0NCA1OC43MDAxIDkuMDk4NDQgNTguNzAwMSAxMS40OTg0QzU4LjcwMDEgMTMuNzk4NCA1OS44MDAxIDE0Ljg5ODQgNjIuNTAwMSAxNC44OTg0QzY1LjEwMDEgMTQuODk4NCA2Ni40MDAxIDEzLjc5ODQgNjYuNDAwMSAxMS40OTg0Wk02Ni4zMDAxIDUuNTk4NDRINjkuNDAwMVYxNy4zOTg0SDY2LjMwMDFWMTQuNDk4NEM2NS40MDAxIDE2LjQ5ODQgNjMuNzAwMSAxNy42OTg0IDYxLjYwMDEgMTcuNjk4NEM1Ny43MDAxIDE3LjY5ODQgNTUuNjAwMSAxNS4yOTg0IDU1LjYwMDEgMTEuNTk4NEM1NS42MDAxIDcuNzk4NDQgNTcuNjAwMSA1LjM5ODQ0IDYxLjQwMDEgNS4zOTg0NEM2My41MDAxIDUuMzk4NDQgNjUuNDAwMSA2LjU5ODQ0IDY2LjIwMDEgOC41OTg0NFY1LjU5ODQ0SDY2LjMwMDFaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTgxLjM5OTkgOC4zSDc3LjM5OTlWMTQuN0g4MS4wOTk5VjE3LjRINzcuOTk5OUM3NS43OTk5IDE3LjQgNzQuMjk5OSAxNS45IDc0LjI5OTkgMTMuN1Y4LjNINzEuMzk5OVY1LjZINzQuMjk5OVYySDc3LjM5OTlWNS41SDgxLjM5OTlWOC4zWiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik05My42OTk5IDEyLjIwMDhMOTYuNjk5OSAxMi45MDA4Qzk1Ljk5OTkgMTYuMDAwOCA5My42OTk5IDE3LjYwMDggODkuOTk5OSAxNy42MDA4Qzg3Ljc5OTkgMTcuNjAwOCA4Ni4wOTk5IDE3LjAwMDggODQuNzk5OSAxNS45MDA4QzgzLjQ5OTkgMTQuODAwOCA4Mi44OTk5IDEzLjMwMDggODIuODk5OSAxMS41MDA4QzgyLjg5OTkgOS42MDA3OCA4My40OTk5IDguMTAwNzggODQuNzk5OSA3LjAwMDc4Qzg2LjA5OTkgNS45MDA3OCA4Ny43OTk5IDUuMzAwNzggODkuOTk5OSA1LjMwMDc4QzkzLjY5OTkgNS4zMDA3OCA5NS45OTk5IDYuOTAwNzggOTYuNjk5OSAxMC4wMDA4TDkzLjY5OTkgMTAuNzAwOEM5My4yOTk5IDguODAwNzggOTIuMjk5OSA4LjEwMDc4IDg5Ljg5OTkgOC4xMDA3OEM4Ni45OTk5IDguMTAwNzggODUuODk5OSA5LjIwMDc4IDg1Ljg5OTkgMTEuNTAwOEM4NS44OTk5IDEzLjgwMDggODYuOTk5OSAxNC45MDA4IDg5Ljg5OTkgMTQuOTAwOEM5Mi4yOTk5IDE0LjkwMDggOTMuMjk5OSAxNC4yMDA4IDkzLjY5OTkgMTIuMjAwOFoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTExLjggMTAuNlYxNy40SDEwOC43VjExLjJDMTA4LjcgOSAxMDcuOCA4LjEgMTA1LjkgOC4xQzEwMy42IDguMSAxMDIuNCA5LjMgMTAyLjQgMTEuN1YxNy4zSDk5LjI5OThWMC41SDEwMi40VjguM0MxMDMuMSA2LjMgMTA0LjYgNS4zIDEwNyA1LjNDMTEwLjIgNS4zIDExMS44IDcuMSAxMTEuOCAxMC42WiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMTQuMSAxNC4wOTg0TDExNy4xIDEzLjI5ODRDMTE3LjQgMTQuNzk4NCAxMTguMyAxNS4yOTg0IDEyMC4yIDE1LjI5ODRDMTIxLjggMTUuMjk4NCAxMjIuNyAxNC44OTg0IDEyMi43IDE0LjA5ODRDMTIyLjcgMTMuMjk4NCAxMjIuMiAxMi45OTg0IDEyMC42IDEyLjc5ODRMMTE4LjIgMTIuNDk4NEMxMTUuOSAxMi4xOTg0IDExNC41IDEwLjg5ODQgMTE0LjUgOC45OTg0NEMxMTQuNSA2Ljc5ODQ0IDExNi41IDUuMzk4NDQgMTE5LjggNS4zOTg0NEMxMjMuMSA1LjM5ODQ0IDEyNSA2LjY5ODQ0IDEyNS41IDguODk4NDRMMTIyLjUgOS41OTg0NEMxMjIuMyA4LjA5ODQ0IDEyMS41IDcuNjk4NDQgMTE5LjkgNy42OTg0NEMxMTguNCA3LjY5ODQ0IDExNy42IDguMDk4NDQgMTE3LjYgOC44OTg0NEMxMTcuNiA5LjU5ODQ0IDExOC4xIDkuOTk4NDQgMTE5LjMgMTAuMDk4NEwxMjIuMiAxMC40OTg0QzEyNC40IDEwLjc5ODQgMTI1LjggMTEuOTk4NCAxMjUuOCAxMy44OTg0QzEyNS44IDE2LjI5ODQgMTIzLjcgMTcuNzk4NCAxMjAuMSAxNy43OTg0QzExNi43IDE3LjU5ODQgMTE0LjUgMTYuMTk4NCAxMTQuMSAxNC4wOTg0WiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMzYuNyA4LjNIMTMyLjdWMTQuN0gxMzYuNFYxNy40SDEzMy4zQzEzMS4xIDE3LjQgMTI5LjYgMTUuOSAxMjkuNiAxMy43VjguM0gxMjYuN1Y1LjZIMTI5LjZWMkgxMzIuN1Y1LjVIMTM2LjdWOC4zWiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNDkuMiAxMS40OTg0QzE0OS4yIDkuMTk4NDQgMTQ3LjkgOC4wOTg0NCAxNDUuMyA4LjA5ODQ0QzE0Mi42IDguMDk4NDQgMTQxLjUgOS4wOTg0NCAxNDEuNSAxMS40OTg0QzE0MS41IDEzLjc5ODQgMTQyLjYgMTQuODk4NCAxNDUuMyAxNC44OTg0QzE0Ny45IDE0Ljg5ODQgMTQ5LjIgMTMuNzk4NCAxNDkuMiAxMS40OTg0Wk0xNDkuMSA1LjU5ODQ0SDE1Mi4yVjE3LjM5ODRIMTQ5LjFWMTQuNDk4NEMxNDguMiAxNi40OTg0IDE0Ni41IDE3LjY5ODQgMTQ0LjQgMTcuNjk4NEMxNDAuNSAxNy42OTg0IDEzOC40IDE1LjI5ODQgMTM4LjQgMTEuNTk4NEMxMzguNCA3Ljc5ODQ0IDE0MC40IDUuMzk4NDQgMTQ0LjIgNS4zOTg0NEMxNDYuMyA1LjM5ODQ0IDE0OC4yIDYuNTk4NDQgMTQ5IDguNTk4NDRWNS41OTg0NEgxNDkuMVoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTY1LjYgMTIuMjAwOEwxNjguNiAxMi45MDA4QzE2Ny45IDE2LjAwMDggMTY1LjYgMTcuNjAwOCAxNjEuOSAxNy42MDA4QzE1OS43IDE3LjYwMDggMTU4IDE3LjAwMDggMTU2LjcgMTUuOTAwOEMxNTUuNCAxNC44MDA4IDE1NC44IDEzLjMwMDggMTU0LjggMTEuNTAwOEMxNTQuOCA5LjYwMDc4IDE1NS40IDguMTAwNzggMTU2LjcgNy4wMDA3OEMxNTggNS45MDA3OCAxNTkuNyA1LjMwMDc4IDE2MS45IDUuMzAwNzhDMTY1LjYgNS4zMDA3OCAxNjcuOSA2LjkwMDc4IDE2OC42IDEwLjAwMDhMMTY1LjYgMTAuNzAwOEMxNjUuMiA4LjgwMDc4IDE2NC4yIDguMTAwNzggMTYxLjggOC4xMDA3OEMxNTguOSA4LjEwMDc4IDE1Ny44IDkuMjAwNzggMTU3LjggMTEuNTAwOEMxNTcuOCAxMy44MDA4IDE1OC45IDE0LjkwMDggMTYxLjggMTQuOTAwOEMxNjQuMSAxNC45MDA4IDE2NS4xIDE0LjIwMDggMTY1LjYgMTIuMjAwOFoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTgwLjI1NyAxNy40TDE3Ni42NTcgMTIuM0wxNzQuMTU3IDE0LjZWMTcuNEgxNzEuMTU3VjAuNUgxNzQuMTU3VjExLjFMMTc5Ljg1NyA1LjZIMTgzLjc1N0wxNzguNTU3IDEwLjVMMTgzLjk1NyAxNy40SDE4MC4yNTdaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTAgMjEuNTAwOEg3LjNWMTYuMzAwOEgwVjIxLjUwMDhaIiBmaWxsPSIjQUZFNjE0Ii8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNy4yOTk4IDIxLjUwMDhIMTQuNTk5OFYxNi4zMDA4SDcuMjk5OFYyMS41MDA4WiIgZmlsbD0iIzZFQkUwMCIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTE0LjYwMDEgMTYuM0gyOS4yMDAxVjAuNUgxNC42MDAxVjE2LjNaIiBmaWxsPSIjQUZFNjE0Ii8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMCAxMUgxNC42VjAuNUgwVjExWiIgZmlsbD0iIzZFQkUwMCIvPgo8L3N2Zz4K\" alt=\"Patchstack Logo\">\n\t\t\t\t</a>\n            </div>\n        </div>\n    </div>\n</body>\n<script>\n    function copyText(id) {\n        var copyText = document.getElementById(id)\n        copyText.select();\n        copyText.setSelectionRange(0, 99999);\n        navigator.clipboard.writeText(copyText.value);\n    }\n\n    function hover(element) {\n        element.setAttribute('src', 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkiIGhlaWdodD0iMjMiIHZpZXdCb3g9IjAgMCAxOSAyMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE0IDAuMDIzNDM3NUgwVjE2LjAyMzRIMlYyLjAyMzQ0SDE0VjAuMDIzNDM3NVpNMTkgNC4wMjM0NEg0VjIyLjAyMzRIMTlWNC4wMjM0NFpNMTcgMjAuMDIzNEg2VjYuMDIzNDRIMTdWMjAuMDIzNFoiIGZpbGw9IiNBRkU2MTQiLz4KPC9zdmc+Cg==');\n    }\n\n    function unhover(element) {\n        element.setAttribute('src', 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkiIGhlaWdodD0iMjMiIHZpZXdCb3g9IjAgMCAxOSAyMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE0IDAuMDIzNDM3NUgwVjE2LjAyMzRIMlYyLjAyMzQ0SDE0VjAuMDIzNDM3NVpNMTkgNC4wMjM0NEg0VjIyLjAyMzRIMTlWNC4wMjM0NFpNMTcgMjAuMDIzNEg2VjYuMDIzNDRIMTdWMjAuMDIzNFoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=');\n    }\n</script>\n</html>`;\n}\n","// Rule cache as a TIERED store of a `{ bundle, etag }` envelope:\n//   1. memory     — always present; last-known-good within the process. Survives refreshes and is\n//                   the fallback when the disk isn't writable (read-only FS, sandbox).\n//   2. durable    — filesystem (default, via `cacheDir`) OR a pluggable adapter (`ruleCache`, e.g.\n//                   a KV store for filesystem-less runtimes). Survives process restarts.\n// read: memory → durable → null.  write: memory + best-effort durable.  Everything is fail-open —\n// a read/write error yields \"no cache\" rather than throwing.\n//\n// Node's fs/path are loaded LAZILY (dynamic import), never as a static top-level import: this module\n// is part of the WinterCG/edge-safe graph (Next edge middleware, Workers, Deno, Supabase Functions),\n// where a static `node:fs` import fails to resolve at build/load time and would take the whole guard\n// down. On those runtimes the disk tier simply reports \"no cache\" and the memory tier (or a pluggable\n// `ruleCache` adapter) carries last-known-good.\n\nlet fsMod; // memoized { readFileSync, writeFileSync, mkdirSync, join } | null (unavailable)\nasync function loadFs() {\n  if (fsMod !== undefined) return fsMod;\n  try {\n    const [fs, path] = await Promise.all([import('node:fs'), import('node:path')]);\n    fsMod = {\n      readFileSync: fs.readFileSync,\n      writeFileSync: fs.writeFileSync,\n      mkdirSync: fs.mkdirSync,\n      join: path.join,\n    };\n  } catch {\n    fsMod = null; // no filesystem here (edge runtime) — memory/adapter tiers still work\n  }\n  return fsMod;\n}\n\nexport function makeStore(options = {}) {\n  let mem = null;\n  const durable = durableTier(options);\n  return {\n    async read() {\n      if (mem) return mem;\n      const env = await durable.read();\n      if (env) mem = env;\n      return env;\n    },\n    async write(env) {\n      if (env) mem = env;\n      await durable.write(env);\n    },\n  };\n}\n\n// The durable tier: a caller-supplied adapter wins; otherwise a disk cache under `cacheDir`; if\n// neither is configured, a no-op (memory-only — fine for a long-lived process).\nfunction durableTier(options) {\n  const adapter = options.ruleCache;\n  if (adapter && typeof adapter.read === 'function' && typeof adapter.write === 'function') {\n    return {\n      read: async () => {\n        try {\n          return toEnvelope(await adapter.read());\n        } catch {\n          return null;\n        }\n      },\n      write: async (env) => {\n        try {\n          await adapter.write(env);\n        } catch {\n          /* best-effort */\n        }\n      },\n    };\n  }\n  const dir = options.cacheDir;\n  return {\n    read: async () => cacheRead(dir),\n    write: async (env) => cacheWrite(dir, env),\n  };\n}\n\nasync function cacheWrite(dir, env) {\n  if (!dir) return;\n  const fs = await loadFs();\n  if (!fs) return; // filesystem-less runtime — memory tier only\n  try {\n    fs.mkdirSync(dir, { recursive: true });\n    fs.writeFileSync(fs.join(dir, 'patchstack-rules.json'), JSON.stringify(env));\n  } catch {\n    /* cache is best-effort — the memory tier still holds last-known-good */\n  }\n}\n\nasync function cacheRead(dir) {\n  if (!dir) return null;\n  const fs = await loadFs();\n  if (!fs) return null;\n  try {\n    return toEnvelope(JSON.parse(fs.readFileSync(fs.join(dir, 'patchstack-rules.json'), 'utf8')));\n  } catch {\n    return null;\n  }\n}\n\n// Accept the current { bundle, etag } envelope and a legacy bare bundle (pre-envelope cache files).\nexport function toEnvelope(value) {\n  if (!value || typeof value !== 'object') return null;\n  if (value.bundle && typeof value.bundle === 'object') {\n    return { bundle: value.bundle, etag: value.etag ?? null };\n  }\n  if (Array.isArray(value.firewall) || Array.isArray(value.whitelists)) {\n    return { bundle: value, etag: null }; // legacy bare-bundle cache file\n  }\n  return null;\n}\n","// Rule-bundle validation. Delivered rules are POLICY fetched over the network, and the engine executes\n// them on every request — so an upstream compromise, a schema drift, or a mistake in the corpus could\n// otherwise hand the app unbounded work (a 50k-rule bundle, a 500-deep condition tree, a pathological\n// regex) or silently unenforceable junk.\n//\n// Two principles:\n//   1. REJECT, don't silently skip. A rule that fails validation is dropped WITH a reported reason, so\n//      an unenforceable rule is visible instead of quietly protecting nothing.\n//   2. Bound everything the engine will walk: rule count, conditions per rule, nesting depth, and\n//      pattern length. Caps are deliberately far above any real corpus rule.\n//\n// Fail-open in spirit: validation never throws, and a bundle whose rules are all rejected simply means\n// \"no rules\" (the app keeps serving) — never a crash.\n\nexport const LIMITS = {\n  maxRules: 5000,\n  maxWhitelists: 2000,\n  maxConditionsPerRule: 250,\n  maxNestingDepth: 12,\n  maxRegexLength: 1000,\n  maxValueLength: 8192,\n};\n\nconst PHASES = new Set(['request', 'response', 'egress']);\nconst ACTIONS = new Set(['block', 'redact', 'encode', 'set-header', 'remove-header', 'harden-cookie']);\n\n/**\n * Validate a delivered bundle. Returns `{ bundle, rejected }` where `bundle` contains only rules that\n * passed and `rejected` is `[{ id, reason }]` for everything dropped.\n * @param {object} bundle\n * @returns {{ bundle: object, rejected: Array<{id: string, reason: string}> }}\n */\nexport function validateBundle(bundle, opts = {}) {\n  const rejected = [];\n  const inFirewall = Array.isArray(bundle?.firewall) ? bundle.firewall : [];\n  const inWhitelists = Array.isArray(bundle?.whitelists) ? bundle.whitelists : [];\n\n  const firewall = [];\n  for (const rule of inFirewall) {\n    if (firewall.length >= LIMITS.maxRules) {\n      rejected.push({ id: idOf(rule), reason: `bundle exceeds maxRules (${LIMITS.maxRules})` });\n      continue;\n    }\n    const reason = ruleProblem(rule);\n    if (reason) rejected.push({ id: idOf(rule), reason });\n    else firewall.push(rule);\n  }\n\n  const whitelists = [];\n  for (const wl of inWhitelists) {\n    if (whitelists.length >= LIMITS.maxWhitelists) {\n      rejected.push({ id: idOf(wl), reason: `bundle exceeds maxWhitelists (${LIMITS.maxWhitelists})` });\n      continue;\n    }\n    // A whitelist SUPPRESSES rules, so a malformed one is a protection risk, not a detection risk.\n    // One with no `rule_id` applies to EVERY rule — a single tripped condition disables the whole\n    // firewall for that request — so it must be opted into explicitly.\n    if (!opts.allowGlobalWhitelists && wl && Array.isArray(wl.rule_v2) && !wl.rule_id) {\n      rejected.push({ id: idOf(wl), reason: 'whitelist has no rule_id (would suppress every rule); set allowGlobalWhitelists to permit' });\n      continue;\n    }\n    const reason = conditionsProblem(wl?.rule_v2);\n    if (reason) rejected.push({ id: idOf(wl), reason: `whitelist: ${reason}` });\n    else whitelists.push(wl);\n  }\n\n  return {\n    bundle: { ...bundle, firewall, whitelists },\n    rejected,\n  };\n}\n\nfunction idOf(rule) {\n  const id = rule?.id ?? rule?.rule_id;\n  return id === undefined || id === null ? '(unidentified)' : String(id);\n}\n\n/** @returns {string|null} a reason the rule must be dropped, or null when it's acceptable. */\nfunction ruleProblem(rule) {\n  if (!rule || typeof rule !== 'object') return 'not an object';\n  if (rule.phase !== undefined && !PHASES.has(rule.phase)) return `unknown phase \"${rule.phase}\"`;\n  if (rule.action !== undefined && !ACTIONS.has(rule.action)) return `unknown action \"${rule.action}\"`;\n  const capOverride = rule.max_bytes;\n  if (capOverride !== undefined && !(Number(capOverride) > 0)) return 'max_bytes must be a positive number';\n  return conditionsProblem(rule.rule_v2);\n}\n\nfunction conditionsProblem(conditions, depth = 0) {\n  if (!Array.isArray(conditions)) return 'rule_v2 must be an array of conditions';\n  if (conditions.length === 0) return 'rule_v2 is empty (would never match)';\n  if (depth > LIMITS.maxNestingDepth) return `nesting deeper than ${LIMITS.maxNestingDepth}`;\n  if (conditions.length > LIMITS.maxConditionsPerRule) {\n    return `more than ${LIMITS.maxConditionsPerRule} conditions`;\n  }\n  for (const c of conditions) {\n    if (!c || typeof c !== 'object') return 'condition is not an object';\n    if (Array.isArray(c.rules)) {\n      const nested = conditionsProblem(c.rules, depth + 1);\n      if (nested) return nested;\n      continue; // a group carries no match of its own\n    }\n    const m = c.match;\n    if (!m || typeof m !== 'object') return 'condition has no match object';\n    if (typeof m.type !== 'string' || m.type === '') return 'match.type must be a non-empty string';\n    if (m.type === 'regex') {\n      if (typeof m.value !== 'string') return 'regex match.value must be a string';\n      if (m.value.length > LIMITS.maxRegexLength) return `regex longer than ${LIMITS.maxRegexLength} chars`;\n    } else if (typeof m.value === 'string' && m.value.length > LIMITS.maxValueLength) {\n      return `match.value longer than ${LIMITS.maxValueLength} chars`;\n    }\n    if (m.match) {\n      // array_key_value nests a sub-match; count it toward depth so a chain can't be unbounded.\n      const nested = conditionsProblem([{ match: m.match }], depth + 1);\n      if (nested) return nested;\n    }\n  }\n  return null;\n}\n","// Rule source: pick where the ruleset comes from — an explicit bundle, or the live API by site\n// UUID (Pulse) or token — fetch it (conditional/If-None-Match via the persisted etag), and fall\n// back through last-known-good → bundled → empty. Fail-open: a fetch/parse error never throws.\n// The `store` (see ./store.js) is passed in so a refresh reuses the same tiered cache.\nimport { PatchstackRuleClient } from '../engine/index.js';\nimport { PulseRuleClient } from '../engine/pulse-client.js';\nimport { validateBundle } from './validate.js';\n\n// A LIVE update is accepted ATOMICALLY. Dropping individual invalid rules is fine for a bundle we\n// already trust (a cache entry, a bundled fallback), but for a fresh remote response it would let a\n// broken update REPLACE known-good policy with partial or empty policy — turning \"we validated it\" into\n// a loss of protection, and caching that loss. So: if any rule/whitelist fails validation, reject the\n// whole update, keep last-known-good, report it, and do NOT write the cache. Opt in to the old\n// behaviour with `acceptPartialBundle: true` (metrics still report every drop).\nfunction liveUpdateRejections(res, options) {\n  if (options.acceptPartialBundle) return [];\n  const { rejected } = validateBundle(\n    { firewall: Array.isArray(res.firewall) ? res.firewall : [], whitelists: Array.isArray(res.whitelists) ? res.whitelists : [] },\n    { allowGlobalWhitelists: options.allowGlobalWhitelists },\n  );\n  return rejected;\n}\n\nfunction reportRejections(rejected, options, label) {\n  const report = options.onRuleRejected;\n  for (const r of rejected) {\n    if (typeof report === 'function') {\n      try { report({ ...r, accepted: false }); } catch { /* reporting must never break rule loading */ }\n    }\n  }\n  const sample = rejected.slice(0, 3).map((r) => `${r.id} (${r.reason})`).join('; ');\n  options.onError?.(new Error(\n    `${label}: rejected the entire update because ${rejected.length} rule(s) failed validation — ` +\n    `keeping the previous ruleset and NOT caching this response: ${sample}${rejected.length > 3 ? ', …' : ''}`,\n  ));\n}\n\nexport async function resolveRules(options, store, ctx = {}) {\n  // The INITIAL load is on the app's startup path, so the runtime gives it a short budget (see\n  // bootTimeoutMs) and falls back to cache/bundled rather than delaying boot; refreshes get the full\n  // budget. A timeout here is not a protection gap by itself — last-known-good still applies.\n  const timeoutMs = ctx.timeoutMs;\n  if (options.siteUuid) {\n    const prior = await store.read(); // { bundle, etag } | null\n    const client = new PulseRuleClient({ siteUuid: options.siteUuid, baseUrl: options.pulseRulesUrl, etag: prior?.etag, timeoutMs, pulseAuth: ctx.pulseAuth });\n    const res = await client.getRules();\n    if (res.success && res.notModified && prior?.bundle) return normalizeBundle(prior.bundle, options);\n    if (res.success && !res.notModified) {\n      const rejected = liveUpdateRejections(res, options);\n      if (rejected.length > 0) {\n        reportRejections(rejected, options, 'rule update rejected');\n        if (prior?.bundle) return normalizeBundle(prior.bundle, options);\n        if (options.rules) return normalizeBundle(options.rules, options);\n        return emptyBundle();\n      }\n      const bundle = normalizeBundle(res, options);\n      await store.write({ bundle, etag: res.etag ?? null });\n      return bundle;\n    }\n    if (prior?.bundle) {\n      options.onError?.(new Error(`pulse rule fetch failed (${res.error ?? 'no usable response'}); using cached bundle`));\n      return normalizeBundle(prior.bundle, options);\n    }\n    if (options.rules) {\n      options.onError?.(new Error(`pulse rule fetch failed (${res.error ?? 'no usable response'}); using bundled fallback`));\n      return normalizeBundle(options.rules, options);\n    }\n    options.onError?.(new Error(`pulse rule fetch failed (${res.error ?? 'no usable response'}); no cache — running with no rules`));\n    return emptyBundle();\n  }\n\n  if (options.token) {\n    const prior = await store.read();\n    const client = new PatchstackRuleClient({ token: options.token, baseUrl: options.baseUrl, etag: prior?.etag, timeoutMs });\n    const res = await client.getRules();\n    if (res.success && res.notModified && prior?.bundle) return normalizeBundle(prior.bundle, options);\n    if (res.success && !res.notModified) {\n      const rejected = liveUpdateRejections(res, options);\n      if (rejected.length > 0) {\n        reportRejections(rejected, options, 'rule update rejected');\n        if (prior?.bundle) return normalizeBundle(prior.bundle, options);\n        if (options.rules) return normalizeBundle(options.rules, options);\n        return emptyBundle();\n      }\n      const bundle = normalizeBundle(res, options);\n      await store.write({ bundle, etag: res.etag ?? null });\n      return bundle;\n    }\n    if (prior?.bundle) {\n      options.onError?.(new Error(`rule fetch failed (${res.error ?? 'no usable response'}); using cached bundle`));\n      return normalizeBundle(prior.bundle, options);\n    }\n    options.onError?.(new Error(`rule fetch failed (${res.error ?? 'no usable response'}); no cache — running with no rules`));\n    return emptyBundle();\n  }\n\n  if (options.rules) {\n    return normalizeBundle(options.rules, options);\n  }\n\n  return emptyBundle();\n}\n\n// Every rule path (live fetch, cache, bundled fallback) funnels through here, so this is where the\n// delivered policy is VALIDATED before the engine ever executes it: bounded rule count / conditions /\n// nesting / pattern length, known phases + actions. A rule that fails is dropped with a reported reason\n// (`onRuleRejected`) rather than silently kept — an unenforceable rule must never look enforced.\nexport function normalizeBundle(b, options = {}) {\n  const enforcement = b?.enforcement ?? b?.mode;\n  const { bundle: checked, rejected } = validateBundle(\n    {\n      firewall: Array.isArray(b.firewall) ? b.firewall : [],\n      whitelists: Array.isArray(b.whitelists) ? b.whitelists : [],\n    },\n    { allowGlobalWhitelists: options.allowGlobalWhitelists },\n  );\n  if (rejected.length > 0) {\n    const report = options.onRuleRejected;\n    if (typeof report === 'function') {\n      for (const r of rejected) {\n        try { report(r); } catch { /* reporting must never break rule loading */ }\n      }\n    } else {\n      const sample = rejected.slice(0, 3).map((r) => `${r.id} (${r.reason})`).join('; ');\n      // eslint-disable-next-line no-console\n      console.warn(\n        `[patchstack] ${rejected.length} delivered rule(s) rejected as invalid/oversized and are NOT enforced: ${sample}` +\n          (rejected.length > 3 ? ', …' : ''),\n      );\n    }\n  }\n  return {\n    firewall: checked.firewall,\n    whitelists: checked.whitelists,\n    whitelist_keys: b.whitelist_keys ?? {},\n    ...(enforcement === 'block' || enforcement === 'dry-run' ? { enforcement } : {}),\n  };\n}\n\nexport function emptyBundle() {\n  return { firewall: [], whitelists: [], whitelist_keys: {} };\n}\n","// Rule refresh scheduling — how a long-lived guard picks up rules that become relevant after boot\n// (a dependency added mid-session, a zero-day published). Two triggers, both driving the same\n// caller-supplied `tick` (which re-fetches + hot-swaps the engines):\n//   - startRefresh: a self-scheduling poll LOOP (reschedules after each tick settles, so runs never\n//     overlap), with ±jitter (avoid a thundering herd) and exponential backoff on consecutive\n//     failures. `unref`'d — it never keeps the process alive.\n//   - makeRefreshHandler: a PUSH endpoint — an authenticated fetch handler the platform/SaaS hits\n//     for an immediate refresh (zero-day fast lane) instead of waiting for the next poll.\n\nconst JITTER_FRACTION = 0.1;\nconst MAX_BACKOFF_MULTIPLIER = 8; // cap consecutive-failure backoff at 8× the base interval\n\nexport function startRefresh(tick, { refreshMs, onError } = {}) {\n  let stopped = false;\n  let failures = 0;\n  let timer = null;\n\n  const schedule = () => {\n    if (stopped) return;\n    const backoff = Math.min(2 ** failures, MAX_BACKOFF_MULTIPLIER);\n    const jitter = 1 - Math.random() * JITTER_FRACTION; // shorten by up to 10% so clients don't align\n    const delay = refreshMs * backoff * jitter;\n    timer = setTimeout(run, delay);\n    timer?.unref?.();\n  };\n\n  const run = async () => {\n    if (stopped) return;\n    try {\n      await tick();\n      failures = 0;\n    } catch (err) {\n      failures++;\n      onError?.(err);\n    }\n    schedule();\n  };\n\n  schedule();\n  return {\n    stop() {\n      stopped = true;\n      if (timer) clearTimeout(timer);\n    },\n  };\n}\n\nexport function makeRefreshHandler(tick, secret) {\n  return async (request) => {\n    // No secret configured → the endpoint doesn't exist (never an open refresh-DoS surface).\n    if (!secret) return new Response('not found', { status: 404 });\n    let provided = null;\n    try {\n      provided = request?.headers?.get?.('x-patchstack-refresh') ?? new URL(request.url).searchParams.get('token');\n    } catch {\n      provided = null;\n    }\n    if (provided !== secret) return new Response('forbidden', { status: 403 });\n    let refreshed = true;\n    try {\n      await tick();\n    } catch {\n      refreshed = false; // fail-open: report the outcome, never throw\n    }\n    return new Response(JSON.stringify({ refreshed }), { status: 200, headers: { 'content-type': 'application/json' } });\n  };\n}\n","import { isSafeOrigin } from './safe-origin.js';\n// Fire-and-forget reporter: Connect runtime → existing connector POST /api/logs/log\n// (same path WordPress uses). Auth: WP-style api_key (`{secret}-{oauth.id}`) →\n// POST /oauth/token (client_credentials) → Bearer JWT on /api/logs/log.\n// Opt out: PATCHSTACK_TELEMETRY=off. Never put api_key in the public widget.\n\nconst DEFAULT_API_BASE = 'https://api.patchstack.com';\nconst DEFAULT_FLUSH_MS = 1000;\nconst MAX_BATCH = 50;\nconst TOKEN_SKEW_MS = 60_000;\n\n/**\n * Parse WP plugin api_key (`{secret}-{oauth.id}`) into client credentials.\n * @param {string} apiKey\n * @returns {{ clientId: string, clientSecret: string } | null}\n */\nexport function parseApiKey(apiKey) {\n  if (typeof apiKey !== 'string' || apiKey.length === 0) return null;\n  const idx = apiKey.lastIndexOf('-');\n  if (idx <= 0 || idx === apiKey.length - 1) return null;\n  const clientSecret = apiKey.slice(0, idx);\n  const clientId = apiKey.slice(idx + 1);\n  if (!/^\\d+$/.test(clientId) || clientSecret.length === 0) return null;\n  return { clientId, clientSecret };\n}\n\n/**\n * Derive api.patchstack.com origin from a Pulse manifest/rules URL override.\n * @param {string | undefined} pulseOrManifestUrl\n */\nexport function resolveApiBase(pulseOrManifestUrl) {\n  const fromEnv = typeof process !== 'undefined' ? process.env?.PATCHSTACK_API_BASE : undefined;\n  if (typeof fromEnv === 'string' && fromEnv.length > 0) {\n    // The site api_key is exchanged for a token against this origin, so a hostile/injected env value\n    // would be a credential-exfiltration path. Require HTTPS (localhost excepted for local testing);\n    // anything else falls back to the default origin rather than shipping the key off-platform.\n    const candidate = fromEnv.replace(/\\/$/, '');\n    if (isSafeOrigin(candidate)) return candidate;\n    // eslint-disable-next-line no-console\n    console.warn(\n      '[patchstack] ignoring PATCHSTACK_API_BASE: block-log reporting requires an https origin ' +\n        '(or localhost). Falling back to the default API origin.',\n    );\n  }\n  if (typeof pulseOrManifestUrl === 'string' && pulseOrManifestUrl.length > 0) {\n    try {\n      return new URL(pulseOrManifestUrl).origin;\n    } catch {\n      /* fall through */\n    }\n  }\n  const endpoint = typeof process !== 'undefined' ? process.env?.PATCHSTACK_ENDPOINT : undefined;\n  if (typeof endpoint === 'string' && endpoint.length > 0) {\n    try {\n      return new URL(endpoint).origin;\n    } catch {\n      /* fall through */\n    }\n  }\n  return DEFAULT_API_BASE;\n}\n\n/**\n * @param {{\n *   apiKey: string,\n *   apiBase?: string,\n *   sourceHost?: string,\n *   fetchImpl?: typeof fetch,\n *   flushMs?: number,\n * }} opts\n */\nexport function createFirewallLogReporter(opts) {\n  const creds = parseApiKey(opts.apiKey);\n  if (!creds) {\n    return { record() {}, flush() {}, stop() {} };\n  }\n\n  const apiBase = (opts.apiBase ?? DEFAULT_API_BASE).replace(/\\/$/, '');\n  const fetchImpl = opts.fetchImpl ?? globalThis.fetch;\n  const flushMs = Number.isFinite(opts.flushMs) ? opts.flushMs : DEFAULT_FLUSH_MS;\n  const sourceHost = typeof opts.sourceHost === 'string' ? opts.sourceHost : '';\n\n  /** @type {Array<Record<string, unknown>>} */\n  let queue = [];\n  /** @type {ReturnType<typeof setTimeout> | null} */\n  let timer = null;\n  let stopped = false;\n\n  /** @type {{ token: string, expiresAt: number } | null} */\n  let cachedToken = null;\n  /** @type {Promise<string | null> | null} */\n  let tokenInflight = null;\n\n  const fetchAccessToken = async () => {\n    if (cachedToken && Date.now() < cachedToken.expiresAt - TOKEN_SKEW_MS) {\n      return cachedToken.token;\n    }\n    if (tokenInflight) return tokenInflight;\n\n    tokenInflight = (async () => {\n      try {\n        const res = await fetchImpl(`${apiBase}/oauth/token`, {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n            Accept: 'application/json',\n            'User-Agent': '@patchstack/connect',\n          },\n          body: JSON.stringify({\n            grant_type: 'client_credentials',\n            client_id: creds.clientId,\n            client_secret: creds.clientSecret,\n          }),\n        });\n        if (!res || !res.ok) return null;\n        const body = await res.json();\n        const token = body?.access_token;\n        if (typeof token !== 'string' || token.length === 0) return null;\n        const expiresIn = Number(body?.expires_in);\n        const ttlMs = Number.isFinite(expiresIn) && expiresIn > 0 ? expiresIn * 1000 : 3600_000;\n        cachedToken = { token, expiresAt: Date.now() + ttlMs };\n        return token;\n      } catch {\n        return null;\n      } finally {\n        tokenInflight = null;\n      }\n    })();\n\n    return tokenInflight;\n  };\n\n  const flush = () => {\n    if (timer) {\n      clearTimeout(timer);\n      timer = null;\n    }\n    if (queue.length === 0 || typeof fetchImpl !== 'function') return;\n\n    const batch = queue.splice(0, MAX_BATCH);\n    void (async () => {\n      const token = await fetchAccessToken();\n      if (!token) return;\n\n      const body = new URLSearchParams();\n      body.set('type', 'firewall');\n      body.set('logs', JSON.stringify(batch));\n\n      try {\n        const p = fetchImpl(`${apiBase}/api/logs/log`, {\n          method: 'POST',\n          headers: {\n            Authorization: `Bearer ${token}`,\n            Accept: 'application/json',\n            'Content-Type': 'application/x-www-form-urlencoded',\n            'User-Agent': '@patchstack/connect',\n            ...(sourceHost ? { 'Source-Host': sourceHost } : {}),\n          },\n          body,\n        });\n        if (p && typeof p.then === 'function') p.catch(() => {});\n      } catch {\n        /* ignore */\n      }\n    })();\n  };\n\n  return {\n    /**\n     * @param {{\n     *   rule?: { id?: string | number },\n     *   method?: string | null,\n     *   path?: string | null,\n     *   ip?: string | null,\n     *   userAgent?: string | null,\n     * }} event\n     */\n    record(event) {\n      if (stopped) return;\n      const fid = event?.rule?.id;\n      if (fid === undefined || fid === null || fid === '') return;\n\n      queue.push({\n        fid,\n        method: event.method ?? null,\n        request_uri: event.path ?? null,\n        ip: event.ip ?? null,\n        user_agent: event.userAgent ?? null,\n        log_date: new Date().toISOString(),\n      });\n\n      if (queue.length >= MAX_BATCH) {\n        flush();\n        return;\n      }\n      if (!timer) timer = setTimeout(flush, flushMs);\n    },\n    flush,\n    stop() {\n      stopped = true;\n      flush();\n    },\n  };\n}\n\n/** @returns {boolean} */\nexport function telemetryEnabled() {\n  const v = typeof process !== 'undefined' ? process.env?.PATCHSTACK_TELEMETRY : undefined;\n  if (v === undefined || v === '') return true;\n  return !/^(0|false|off|no)$/i.test(String(v));\n}\n","// Supabase-tunnel guard for AI-builder apps (Lovable / TanStack Start + Supabase).\n//\n// The vibe-coded app's browser talks straight to Supabase, bypassing the app's own server —\n// so a normal in-app WAF never sees the data traffic. The installer patches the generated\n// Supabase client to tunnel every call through this guard (running in the app's own server /\n// Worker). The guard runs the Patchstack protection policy on the tunneled request, then\n// forwards it to Supabase — pinned to the app's own project so it can't be turned into an\n// open proxy (SSRF).\n//\n// The heavy lifting (rule evaluation, dry-run/block, fail-open) is `protection.fetchGuard()`\n// from `createProtection` — this module is just the Supabase-specific tunnel around it.\n\nexport const GUARD_PATH = '/_patchstack/guard';\n\n// Headers we must not copy verbatim when re-emitting the upstream response.\nconst HOP_BY_HOP = new Set(['content-encoding', 'content-length', 'transfer-encoding', 'connection']);\n\n/**\n * @param {object} opts\n * @param {{ fetchGuard: () => (req: Request) => Promise<Response|null> }} opts.protection  a createProtection() result\n * @param {string|undefined} opts.supabaseUrl  the app's Supabase project URL (server-side env) — the only allowed forward target\n * @param {typeof fetch} [opts.fetchImpl]  injectable fetch (tests)\n * @returns {(request: Request) => Promise<Response>}\n */\nexport function createSupabaseGuard({ protection, supabaseUrl, fetchImpl = fetch }) {\n  const guard = protection.fetchGuard();\n  const allowedOrigin = supabaseUrl ? new URL(supabaseUrl).origin : null;\n\n  return async function handleGuardRequest(request) {\n    const target = request.headers.get('x-ps-target');\n    if (!target) return new Response('patchstack: missing x-ps-target', { status: 400 });\n\n    let targetUrl;\n    try {\n      targetUrl = new URL(target);\n    } catch {\n      return new Response('patchstack: invalid target', { status: 400 });\n    }\n\n    // SSRF pin: only ever forward to the app's own Supabase project (origin from server-side\n    // env, never the client-supplied header). Anything else — internal hosts, cloud metadata,\n    // a different scheme — is rejected before any outbound request.\n    if (!allowedOrigin || targetUrl.protocol !== 'https:' || targetUrl.origin !== allowedOrigin) {\n      return new Response('patchstack: target not allowed', { status: 403 });\n    }\n\n    const hasBody = request.method !== 'GET' && request.method !== 'HEAD';\n    const bodyText = hasBody ? await request.text() : '';\n\n    // Evaluate the tunneled call against the policy. fetchGuard returns a 403 Response when it\n    // blocks (block mode + match), or null to allow (allow, or dry-run — it records via onDetect).\n    const evalReq = new Request(targetUrl.toString(), {\n      method: request.method,\n      headers: request.headers,\n      body: hasBody ? bodyText : undefined,\n    });\n    const blocked = await guard(evalReq);\n    if (blocked) return blocked;\n\n    // Allowed → forward to Supabase, server-side.\n    const forwardHeaders = new Headers(request.headers);\n    forwardHeaders.delete('x-ps-target');\n    forwardHeaders.delete('host');\n    const upstream = await fetchImpl(targetUrl.toString(), {\n      method: request.method,\n      headers: forwardHeaders,\n      body: hasBody ? bodyText : undefined,\n      redirect: 'manual',\n    });\n\n    const outHeaders = new Headers();\n    upstream.headers.forEach((value, key) => {\n      if (!HOP_BY_HOP.has(key.toLowerCase())) outHeaders.set(key, value);\n    });\n    const buf = await upstream.arrayBuffer();\n    const forwarded = new Response(buf, { status: upstream.status, statusText: upstream.statusText, headers: outHeaders });\n\n    // Response phase: screen what Supabase returned (query results can leak secrets/PII) —\n    // redact the offending spans / withhold, per the response rules. Fail-open if unavailable.\n    return protection.screenResponse ? protection.screenResponse(forwarded) : forwarded;\n  };\n}\n"],"mappings":"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","names":["path","path","path","import_promises","import_node_path","path","import_promises","import_node_path","path","import_promises","import_node_path","import_promises","path","import_promises","import_node_path","path","import_promises","import_node_path","warnOnce","path","DEFAULT_BASE_URL","DEFAULT_CACHE_TTL","JITTER_FRACTION","parseCookies","path","path","JITTER_FRACTION","TOKEN_SKEW_MS","allow","walk","path"]}