@patchstack/connect 0.3.19 → 0.3.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/protect/runtime.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/supabase-guard.js"],"sourcesContent":["// @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\n// 'block' (enforce). Default is 'dry-run'.\n// - fail-open everywhere: a rule/engine error never blocks (or crashes) a request.\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, PatchstackRuleClient } from './engine/index.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';\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\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 mode = options.mode === 'block' ? 'block' : 'dry-run';\n const onError = options.onError;\n const onDetect = options.onDetect ?? defaultOnDetect;\n\n const bundle = await resolveRules(options);\n const incoming = bundle.firewall ?? [];\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 requestRules = byPhase(incoming, 'request');\n const responseRules = [...(options.responseRules ?? DEFAULT_RESPONSE_RULES), ...byPhase(incoming, 'response')];\n const egressRules = [...(options.egressRules ?? DEFAULT_EGRESS_RULES), ...byPhase(incoming, 'egress')];\n\n const engine = new RuleEngine({\n firewall: requestRules,\n whitelists: bundle.whitelists,\n whitelist_keys: bundle.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 const responseRuleSet = responseRules.map((rule) => ({\n rule,\n engine: new RuleEngine({ firewall: [rule], onError }),\n redactors: rule.action === 'redact' ? extractRedactors(rule) : null\n }));\n const egressEngine = new RuleEngine({ firewall: egressRules, onError });\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 const decide = (phase, result, block, allow) => {\n if (!result || !result.blocked) return allow();\n onDetect({ phase, mode, category: result.rule?.category, rule: result.rule, message: result.message });\n return mode === '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 isTextCT = (ct) => {\n ct = (ct || '').toLowerCase();\n return ct === '' || /(json|text|xml|html|javascript|csv|yaml|x-www-form-urlencoded)/.test(ct);\n };\n const screenText = (text, meta) => {\n let blockRule = null;\n const redactions = [];\n for (const { rule, engine: re, redactors } of responseRuleSet) {\n let result;\n try {\n result = re.evaluate({ _response: { ...meta, body: text } });\n } catch (err) {\n onError?.(err);\n continue;\n }\n if (!result.blocked) continue;\n onDetect({ phase: 'response', mode, category: rule.category, rule, message: result.message });\n if (mode !== 'block') continue; // dry-run: observe only\n if (redactors && redactors.length) redactions.push({ rule, redactors });\n else if (!blockRule) blockRule = rule;\n }\n if (mode !== 'block' || (!blockRule && !redactions.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 body = applyRedactors(body, redactors, mask);\n for (const name of Object.keys(headers)) {\n const value = headers[name];\n if (typeof value === 'string') {\n headers[name] = applyRedactors(value, redactors, 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, redactors, mask) : item));\n }\n }\n }\n return { verdict: 'redact', body, headers };\n };\n\n // Screen a fetch Response (used by .fetch() and — via protection.screenResponse — the Supabase guard).\n const screenResp = async (response) => {\n const text = await readTextResponse(response);\n if (text == null) return response;\n const r = screenText(text, { status: response.status, headers: headerObject(response.headers) });\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) => {\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 = 512 * 1024;\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) { overflow = true; return; }\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 const text = Buffer.concat(chunks).toString('utf8');\n let ct = res.getHeader ? res.getHeader('content-type') : undefined;\n if (Array.isArray(ct)) ct = ct[0];\n if (!isTextCT(ct)) { for (const c of chunks) origWrite(c); return origEnd(cb); }\n let r;\n try {\n r = screenText(text, { status: res.statusCode, headers: res.getHeaders ? res.getHeaders() : {} });\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 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 onDetect({ phase: 'egress', mode, category: result.rule?.category, rule: result.rule, message: result.message });\n return mode === 'block';\n };\n\n const protection = {\n mode,\n rules: { request: requestRules, response: responseRules, egress: egressRules },\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) => screenResp(response),\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);\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);\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);\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);\n next();\n },\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 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);\n next();\n },\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({ shouldBlock: egressShouldBlock, onBlock: options.onEgressBlock });\n }\n\n return protection;\n}\n\n// --- phase / response helpers -------------------------------------------\n\nfunction byPhase(rules, phase) {\n return (rules ?? []).filter((r) => (r.phase ?? 'request') === phase);\n}\n\nasync function readTextResponse(response) {\n if (!response || typeof response.clone !== 'function') return null;\n const ct = (response.headers?.get?.('content-type') || '').toLowerCase();\n const isText = ct === '' || /(json|text|xml|html|javascript|csv|yaml|x-www-form-urlencoded)/.test(ct);\n if (!isText) return null;\n const len = Number(response.headers?.get?.('content-length') || 0);\n if (len && len > 512 * 1024) return null;\n try {\n const text = await response.clone().text();\n return text.length > 512 * 1024 ? null : text;\n } catch {\n return null;\n }\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// 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 const parsed = m.value.match(/^\\/(.+)\\/([a-z]*)$/is);\n if (parsed) {\n const flags = parsed[2].includes('g') ? parsed[2] : parsed[2] + 'g';\n try {\n out.push({ re: new RegExp(parsed[1], 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 }\n }\n };\n walk(rule.rule_v2);\n return out;\n}\n\nfunction applyRedactors(body, redactors, mask) {\n let out = body;\n for (const r of redactors) {\n if (r.re) out = out.replace(r.re, mask);\n else if (r.literal) out = out.split(r.literal).join(mask);\n }\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 (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 return new Response(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 --------------------------------------------------------\n\nasync function resolveRules(options) {\n const cache = makeCache(options);\n\n if (options.siteUuid) {\n const prior = await cache.read(); // { bundle, etag } | null\n const client = new PulseRuleClient({ siteUuid: options.siteUuid, baseUrl: options.pulseRulesUrl, etag: prior?.etag });\n const res = await client.getRules();\n if (res.success && res.notModified && prior?.bundle) return normalizeBundle(prior.bundle);\n if (res.success && !res.notModified) {\n const bundle = normalizeBundle(res);\n await cache.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);\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);\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 cache.read();\n const client = new PatchstackRuleClient({ token: options.token, baseUrl: options.baseUrl, etag: prior?.etag });\n const res = await client.getRules();\n if (res.success && res.notModified && prior?.bundle) return normalizeBundle(prior.bundle);\n if (res.success && !res.notModified) {\n const bundle = normalizeBundle(res);\n await cache.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);\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);\n }\n\n return emptyBundle();\n}\n\nfunction normalizeBundle(b) {\n return {\n firewall: Array.isArray(b.firewall) ? b.firewall : [],\n whitelists: Array.isArray(b.whitelists) ? b.whitelists : [],\n whitelist_keys: b.whitelist_keys ?? {},\n };\n}\n\nfunction emptyBundle() {\n return { firewall: [], whitelists: [], whitelist_keys: {} };\n}\n\n// The cache stores an envelope { bundle, etag } so a restart can revalidate with If-None-Match. A\n// pluggable adapter (options.ruleCache) lets runtimes without a filesystem (Workers/Deno) persist\n// last-known-good in their own store; the default is a disk cache under options.cacheDir. Both\n// paths are best-effort — a read/write error yields no cache rather than throwing.\nfunction makeCache(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\nfunction cachePath(dir) {\n return join(dir, 'patchstack-rules.json');\n}\n\nfunction cacheWrite(dir, env) {\n if (!dir) return;\n try {\n mkdirSync(dir, { recursive: true });\n writeFileSync(cachePath(dir), JSON.stringify(env));\n } catch {\n /* cache is best-effort */\n }\n}\n\nfunction cacheRead(dir) {\n if (!dir) return null;\n try {\n return toEnvelope(JSON.parse(readFileSync(cachePath(dir), '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).\nfunction 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\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","const 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\n constructor({ token, baseUrl, cacheTtl, etag } = {}) {\n this.#token = token ?? process.env.PATCHSTACK_WAF_TOKEN;\n this.#baseUrl = baseUrl ?? process.env.PATCHSTACK_WAF_API_URL ?? DEFAULT_BASE_URL;\n this.#cacheTtl = 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(30_000)\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 const result = {\n success: true,\n notModified: false,\n etag: response.headers?.get?.('etag') ?? null,\n firewall: Array.isArray(data.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","// 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 return req.headers?.[headerName] ? [req.headers[headerName]] : [];\n }\n return [];\n }\n }\n }\n\n #resolveFiles(key) {\n const files = this.#req.files;\n if (!files) {\n return [];\n }\n\n if (key.endsWith('*')) {\n return this.#resolveWildcard(files, key);\n }\n\n const value = files[key];\n return value !== undefined ? [value] : [];\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\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 if (key in obj) {\n return obj[key];\n }\n\n const parts = key.split('.');\n let current = obj;\n\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') {\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 let result = value;\n\n result = result.replace(/\\/\\*[\\s\\S]*?\\*\\//g, ' ');\n result = result.replace(/\\/\\*![\\s\\S]*?\\*\\//g, ' ');\n result = result.replace(/--[^\\r\\n]*/g, '');\n result = result.replace(/#[^\\r\\n]*/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\nexport function normalizeObject(value, options = {}) {\n if (typeof value === 'string') {\n return normalize(value, options);\n }\n\n if (Array.isArray(value)) {\n return value.map(item => normalizeObject(item, options));\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);\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\nconst REDOS_PATTERNS = [\n /\\(\\w\\+\\)\\+/,\n /\\(\\w\\*\\)\\+/,\n /\\(\\w\\+\\)\\*/,\n /\\(\\w\\*\\)\\*/,\n /\\(\\w\\|\\w\\)\\+/\n];\n\nfunction safeRegExp(pattern) {\n if (!pattern) {\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// array_key_value: navigate `match.key` (a dot-path, or an array of paths) inside the\n// decoded value and run the nested `match.match` against whatever it finds. Mirrors\n// 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 node = value;\n for (const part of String(key).split('.')) {\n if (node === null || typeof node !== 'object') {\n node = undefined;\n break;\n }\n node = node[part];\n }\n if (node === undefined) {\n continue;\n }\n const candidates = Array.isArray(node) ? node : [node];\n for (const candidate of candidates) {\n if (matchValue(sub.type, candidate, sub.value, sub)) {\n return true;\n }\n }\n }\n return false;\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. Handles IPv4 (incl. IPv4-mapped IPv6),\n// IPv6 loopback/link-local/unique-local, and localhost / *.local / GCP metadata names.\nfunction isInternalHost(hostname) {\n if (!hostname) return false;\n const host = String(hostname).toLowerCase().replace(/^\\[|\\]$/g, '');\n\n if (host === 'localhost' || host.endsWith('.localhost') || host.endsWith('.local')) return true;\n if (host === 'metadata.google.internal') return true;\n if (host === '::1' || host === '::') return true;\n if (host.startsWith('fe80:') || host.startsWith('fc') || host.startsWith('fd')) return true;\n\n const v4 = host.match(/(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/);\n if (v4) {\n const a = Number(v4[1]);\n const b = Number(v4[2]);\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 }\n return false;\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.\nfunction 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 const strValue = typeof value === 'string' ? value : String(value);\n\n switch (type) {\n case 'equals':\n return strValue == matchVal;\n\n case 'equals_strict':\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 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];\n return arr.includes(strValue);\n }\n\n case 'not_in_array': {\n const arr = Array.isArray(matchVal) ? matchVal : [matchVal];\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 return value.some(v => matchVal.includes(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 }\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 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 // `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 if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n for (const v of Object.values(value)) {\n if (matchValue(match.type, v, match.value, match)) {\n 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","const 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 #baseUrl;\n #cacheTtl;\n #cache = null;\n #cacheTime = null;\n #ttlEffective = 0;\n #etag;\n\n constructor({ siteUuid, baseUrl, cacheTtl, etag } = {}) {\n this.#siteUuid = siteUuid ?? process.env.PATCHSTACK_SITE_UUID;\n this.#baseUrl = baseUrl ?? process.env.PATCHSTACK_PULSE_RULES_URL ?? DEFAULT_BASE_URL;\n this.#cacheTtl = cacheTtl ?? DEFAULT_CACHE_TTL;\n this.#etag = etag ?? 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 const headers = { Accept: 'application/json' };\n if (this.#etag) headers['If-None-Match'] = this.#etag;\n const response = await fetch(url, { method: 'GET', headers, signal: AbortSignal.timeout(30_000) });\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 const result = {\n success: true,\n notModified: false,\n etag: response.headers?.get?.('etag') ?? null,\n firewall: Array.isArray(data.firewall) ? data.firewall : [],\n whitelists: Array.isArray(data.whitelists) ? data.whitelists : [],\n whitelist_keys: data.whitelist_keys ?? {},\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","// 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 if (contentType.includes('application/json')) {\n try {\n body = JSON.parse(rawBody);\n } catch {\n body = {};\n }\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n body = {};\n for (const [k, v] of new URLSearchParams(rawBody)) {\n body[k] = k in body ? [].concat(body[k], v) : v;\n }\n } else if (contentType.includes('multipart/form-data')) {\n const boundary = /boundary=(\"?)([^\";]+)\\1/i.exec(contentType)?.[2];\n if (boundary) {\n const parsed = parseMultipart(rawBody, boundary);\n body = parsed.body;\n files = parsed.files;\n }\n }\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 const ceiling = Math.max(max, max * 4);\n const declared = Number(request.headers?.get?.('content-length') || 0);\n if (declared && declared > ceiling) return '';\n let clone;\n try {\n clone = request.clone();\n } catch {\n return '';\n }\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\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.\nfunction 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 files[name] = name in files ? [].concat(files[name], filename) : filename;\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 const req = await fromFetchRequest(request);\n\n let result;\n try {\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';\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 const host = headers.host || 'localhost';\n const url = new URL(req.url || '/', `http://${host}`);\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 if (rawBody) {\n if (contentType.includes('application/json')) {\n try {\n body = JSON.parse(rawBody);\n } catch {\n body = {};\n }\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n body = {};\n for (const [k, v] of new URLSearchParams(rawBody)) {\n body[k] = k in body ? [].concat(body[k], v) : v;\n }\n }\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 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 const rawBody = overflow ? '' : Buffer.concat(chunks).toString('utf8');\n const shaped = fromNodeRequest(req, rawBody);\n\n let result;\n try {\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 }} opts\n * @returns {Promise<() => void>} uninstall (restores every patched surface)\n */\nexport async function installEgressGuard({ shouldBlock, onBlock } = {}) {\n const restores = [];\n if (typeof shouldBlock !== 'function') return () => {};\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 // 1. global fetch — synchronous, 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 guarded = async (input, init) => {\n const url = typeof input === 'string' ? input : (input && input.url) || String(input);\n let host = null;\n try {\n host = new URL(url).hostname;\n } catch {\n host = null;\n }\n const method = (init && init.method) || (input && input.method) || 'GET';\n if (block(url, host, method)) {\n throw new Error(`Patchstack blocked an outbound request to a disallowed address: ${host ?? url}`);\n }\n return originalFetch(input, init);\n };\n guarded.__patchstackGuarded = true;\n globalThis.fetch = guarded;\n restores.push(() => {\n if (globalThis.fetch === guarded) globalThis.fetch = originalFetch;\n });\n }\n\n // 2. 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);\n if (restore) restores.push(restore);\n } catch {\n /* module not available on this runtime — skip */\n }\n }\n\n // 3. global WebSocket — ws:// / wss:// egress that never touches fetch or node:http.\n const OriginalWS = globalThis.WebSocket;\n if (typeof OriginalWS === 'function' && !OriginalWS.__patchstackGuarded) {\n const GuardedWS = new Proxy(OriginalWS, {\n construct(target, args, newTarget) {\n const url = String(args?.[0] ?? '');\n let host = null;\n try {\n host = new URL(url).hostname;\n } catch {\n host = null;\n }\n if (block(url, host, 'WEBSOCKET')) {\n throw new Error(`Patchstack blocked an outbound WebSocket to a disallowed address: ${host ?? url}`);\n }\n return Reflect.construct(target, args, newTarget);\n },\n });\n OriginalWS.__patchstackGuarded = true; // marker on the original guards against double-wrap\n globalThis.WebSocket = GuardedWS;\n restores.push(() => {\n if (globalThis.WebSocket === GuardedWS) globalThis.WebSocket = OriginalWS;\n delete OriginalWS.__patchstackGuarded;\n });\n }\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) {\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 return original.apply(this, args);\n };\n\n http.request = wrap(originalRequest);\n if (typeof originalGet === 'function') http.get = wrap(originalGet);\n http.__patchstackGuarded = true;\n\n return () => {\n http.request = originalRequest;\n if (typeof originalGet === 'function') 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 const host = normalizeHost(first.hostname || first.host);\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","// 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// 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 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 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 rule_v2: [{ parameter: 'response.body', match: { type: 'regex', value: '/\\\\bAIza[0-9A-Za-z_-]{35}\\\\b/' } }]\n },\n {\n id: 'resp-jwt',\n title: 'JWT in response body',\n phase: 'response',\n category: 'secret-exposure',\n action: 'redact',\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 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 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 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 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","// 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":["DEFAULT_BASE_URL","DEFAULT_CACHE_TTL","JITTER_FRACTION","parseCookies","allow"]}
1
+ {"version":3,"sources":["../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/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/supabase-guard.js"],"sourcesContent":["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 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 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';\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\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 response = await fetch(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 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 return {\n siteUuid: siteUuid === null || siteUuid.length === 0 ? null : siteUuid,\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` 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\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 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\n// 'block' (enforce). Default is 'dry-run'.\n// - fail-open everywhere: a rule/engine error never blocks (or crashes) a request.\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, PatchstackRuleClient } 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';\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\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 mode = options.mode === 'block' ? 'block' : 'dry-run';\n const onError = options.onError;\n const onDetect = options.onDetect ?? defaultOnDetect;\n\n const bundle = await resolveRules(options);\n // Rule-derived runtime state. Held in `let` bindings the guard methods below close over, so a\n // refresh (see the interval 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 }));\n egressEngine = new RuleEngine({ firewall: egressRules, onError });\n };\n\n applyBundle(bundle);\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 const decide = (phase, result, block, allow) => {\n if (!result || !result.blocked) return allow();\n onDetect({ phase, mode, category: result.rule?.category, rule: result.rule, message: result.message });\n return mode === '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 isTextCT = (ct) => {\n ct = (ct || '').toLowerCase();\n return ct === '' || /(json|text|xml|html|javascript|csv|yaml|x-www-form-urlencoded)/.test(ct);\n };\n const screenText = (text, meta) => {\n let blockRule = null;\n const redactions = [];\n for (const { rule, engine: re, redactors } of responseRuleSet) {\n let result;\n try {\n result = re.evaluate({ _response: { ...meta, body: text } });\n } catch (err) {\n onError?.(err);\n continue;\n }\n if (!result.blocked) continue;\n onDetect({ phase: 'response', mode, category: rule.category, rule, message: result.message });\n if (mode !== 'block') continue; // dry-run: observe only\n if (redactors && redactors.length) redactions.push({ rule, redactors });\n else if (!blockRule) blockRule = rule;\n }\n if (mode !== 'block' || (!blockRule && !redactions.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 return { verdict: 'redact', body, headers };\n };\n\n // Screen a fetch Response (used by .fetch() and — via protection.screenResponse — the Supabase guard).\n const screenResp = async (response) => {\n const text = await readTextResponse(response, screenCap);\n if (text == null) return response;\n const r = screenText(text, { status: response.status, headers: headerObject(response.headers) });\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) => {\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 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 text = Buffer.concat(chunks).toString('utf8');\n let ct = res.getHeader ? res.getHeader('content-type') : undefined;\n if (Array.isArray(ct)) ct = ct[0];\n if (!isTextCT(ct)) { for (const c of chunks) origWrite(c); return origEnd(cb); }\n let r;\n try {\n r = screenText(text, { status: res.statusCode, headers: res.getHeaders ? res.getHeaders() : {} });\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 (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 onDetect({ phase: 'egress', mode, category: result.rule?.category, rule: result.rule, message: result.message });\n return mode === 'block';\n };\n\n const protection = {\n mode,\n get rules() {\n return { request: requestRules, response: responseRules, egress: egressRules };\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) => screenResp(response),\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);\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);\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);\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);\n next();\n },\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 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);\n next();\n },\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 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 (e.g. a dependency added mid-session, then flagged by Pulse)\n // never applies until the process restarts. Where the runtime is long-lived and isn't restarted\n // on change — the sandbox/preview of an AI builder — the host sets `refreshMs` so the engines are\n // periodically re-fetched and hot-swapped in place. Left off (0) by default: a real deploy\n // restarts the process, which re-fetches anyway. Only meaningful with a live rule source.\n if (options.refreshMs > 0 && (options.siteUuid || options.token)) {\n // On the Pulse (siteUuid) path, re-post the dependency manifest before re-fetching rules. A\n // targeted `npm install <pkg>` fires no npm lifecycle hook, so nothing else re-scans; reporting\n // here lets the server detect a newly-added vulnerable dependency and the SAME tick's rule fetch\n // pick up its rule — a restart-free catch. Loaded lazily so production guards (refresh off)\n // never pull in the scan pipeline; a load/report failure never blocks the rule refresh.\n const cwd = options.cwd ?? (typeof process !== 'undefined' ? process.cwd() : undefined);\n let reportManifest = null;\n if (options.siteUuid && options.reportManifest !== false && cwd) {\n try {\n ({ reportManifest } = 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 const timer = setInterval(() => {\n (async () => {\n if (reportManifest) {\n try {\n await reportManifest(cwd);\n } catch (err) {\n onError?.(err); // a failed report must not stop the rule refresh\n }\n }\n applyBundle(await resolveRules(options));\n })().catch((err) => onError?.(err));\n }, options.refreshMs);\n timer.unref?.(); // never keep the process alive for the refresh\n protection.stopRefresh = () => clearInterval(timer);\n }\n\n return protection;\n}\n\n// --- phase / response helpers -------------------------------------------\n\nfunction byPhase(rules, phase) {\n return (rules ?? []).filter((r) => (r.phase ?? 'request') === phase);\n}\n\nasync function readTextResponse(response, cap = DEFAULT_SCREEN_CAP) {\n if (!response || typeof response.clone !== 'function') return null;\n const ct = (response.headers?.get?.('content-type') || '').toLowerCase();\n const isText = ct === '' || /(json|text|xml|html|javascript|csv|yaml|x-www-form-urlencoded)/.test(ct);\n if (!isText) return null;\n const len = Number(response.headers?.get?.('content-length') || 0);\n if (len && len > cap) return null;\n let clone;\n try {\n clone = response.clone();\n } catch {\n return null;\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 (null) — 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 try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n if (!value) continue;\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 null;\n }\n if (over) return null;\n try {\n return new TextDecoder().decode(concatBytes(chunks, size));\n } catch {\n return null;\n }\n }\n\n try {\n const text = await clone.text();\n return text.length > cap ? null : text;\n } catch {\n return null;\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// 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).\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) out = out.split(r.literal).join(transform ? transform(r.literal) : mask);\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\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 (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 return new Response(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 --------------------------------------------------------\n\nasync function resolveRules(options) {\n const cache = makeCache(options);\n\n if (options.siteUuid) {\n const prior = await cache.read(); // { bundle, etag } | null\n const client = new PulseRuleClient({ siteUuid: options.siteUuid, baseUrl: options.pulseRulesUrl, etag: prior?.etag });\n const res = await client.getRules();\n if (res.success && res.notModified && prior?.bundle) return normalizeBundle(prior.bundle);\n if (res.success && !res.notModified) {\n const bundle = normalizeBundle(res);\n await cache.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);\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);\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 cache.read();\n const client = new PatchstackRuleClient({ token: options.token, baseUrl: options.baseUrl, etag: prior?.etag });\n const res = await client.getRules();\n if (res.success && res.notModified && prior?.bundle) return normalizeBundle(prior.bundle);\n if (res.success && !res.notModified) {\n const bundle = normalizeBundle(res);\n await cache.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);\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);\n }\n\n return emptyBundle();\n}\n\nfunction normalizeBundle(b) {\n return {\n firewall: Array.isArray(b.firewall) ? b.firewall : [],\n whitelists: Array.isArray(b.whitelists) ? b.whitelists : [],\n whitelist_keys: b.whitelist_keys ?? {},\n };\n}\n\nfunction emptyBundle() {\n return { firewall: [], whitelists: [], whitelist_keys: {} };\n}\n\n// The cache stores an envelope { bundle, etag } so a restart can revalidate with If-None-Match. A\n// pluggable adapter (options.ruleCache) lets runtimes without a filesystem (Workers/Deno) persist\n// last-known-good in their own store; the default is a disk cache under options.cacheDir. Both\n// paths are best-effort — a read/write error yields no cache rather than throwing.\nfunction makeCache(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\nfunction cachePath(dir) {\n return join(dir, 'patchstack-rules.json');\n}\n\nfunction cacheWrite(dir, env) {\n if (!dir) return;\n try {\n mkdirSync(dir, { recursive: true });\n writeFileSync(cachePath(dir), JSON.stringify(env));\n } catch {\n /* cache is best-effort */\n }\n}\n\nfunction cacheRead(dir) {\n if (!dir) return null;\n try {\n return toEnvelope(JSON.parse(readFileSync(cachePath(dir), '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).\nfunction 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\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","const 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\n constructor({ token, baseUrl, cacheTtl, etag } = {}) {\n this.#token = token ?? process.env.PATCHSTACK_WAF_TOKEN;\n this.#baseUrl = baseUrl ?? process.env.PATCHSTACK_WAF_API_URL ?? DEFAULT_BASE_URL;\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(30_000)\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","// 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 return req.headers?.[headerName] ? [req.headers[headerName]] : [];\n }\n return [];\n }\n }\n }\n\n #resolveFiles(key) {\n const files = this.#req.files;\n if (!files) {\n return [];\n }\n\n if (key.endsWith('*')) {\n return this.#resolveWildcard(files, key);\n }\n\n const value = files[key];\n return value !== undefined ? [value] : [];\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\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 let result = value;\n\n result = result.replace(/\\/\\*[\\s\\S]*?\\*\\//g, ' ');\n result = result.replace(/\\/\\*![\\s\\S]*?\\*\\//g, ' ');\n result = result.replace(/--[^\\r\\n]*/g, '');\n result = result.replace(/#[^\\r\\n]*/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\nexport function normalizeObject(value, options = {}) {\n if (typeof value === 'string') {\n return normalize(value, options);\n }\n\n if (Array.isArray(value)) {\n return value.map(item => normalizeObject(item, options));\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);\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). Earlier patterns only caught literal-letter groups and\n// missed the far more common `\\w`/`.`/char-class forms.\nconst REDOS_PATTERNS = [\n /\\([^)]*[+*}][^)]*\\)\\s*[+*]/,\n /\\([^)]*\\|[^)]*\\)\\s*[+*]/\n];\n\nexport function safeRegExp(pattern) {\n if (!pattern) {\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// 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. Handles IPv4 (incl. IPv4-mapped IPv6),\n// IPv6 loopback/link-local/unique-local, and localhost / *.local / GCP metadata names.\nfunction isInternalHost(hostname) {\n if (!hostname) return false;\n const host = String(hostname).toLowerCase().replace(/^\\[|\\]$/g, '');\n\n if (host === 'localhost' || host.endsWith('.localhost') || host.endsWith('.local')) return true;\n if (host === 'metadata.google.internal') return true;\n if (host === '::1' || host === '::') return true;\n if (host.startsWith('fe80:') || host.startsWith('fc') || host.startsWith('fd')) return true;\n\n // Dotted IPv4 (incl. dotted IPv4-mapped `::ffff:127.0.0.1`, which ends in dotted form).\n const v4 = host.match(/(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/);\n if (v4 && isPrivateV4(Number(v4[1]), Number(v4[2]))) return true;\n\n // Hex IPv4-mapped IPv6 (`::ffff:7f00:1` = 127.0.0.1) — Node's URL doesn't dotted-normalize this\n // form, so classify it here too.\n const mapped = host.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);\n if (mapped) {\n const g1 = parseInt(mapped[1], 16);\n const g2 = parseInt(mapped[2], 16);\n if (isPrivateV4((g1 >> 8) & 0xff, g1 & 0xff)) return true;\n }\n return false;\n}\n\n// Private / loopback / link-local / this-host IPv4 test (first two octets are enough for our ranges).\nfunction isPrivateV4(a, b) {\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 return false;\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// CSRF primitive: does the request come from a different origin than its own Host? Lenient — a\n// missing Origin/Referer (a non-browser client) is NOT treated as cross-origin.\nfunction isCrossOrigin(resolver) {\n try {\n const host = String(resolver.resolve('server.HTTP_HOST')[0] ?? '').toLowerCase();\n if (!host) return false;\n const src = resolver.resolve('server.HTTP_ORIGIN')[0] ?? resolver.resolve('server.HTTP_REFERER')[0];\n if (!src) return false;\n const srcHost = hostFromUrl(String(src));\n return srcHost !== null && 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// `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 const strValue = typeof value === 'string' ? value : String(value);\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 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 }\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 // `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 if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n for (const v of Object.values(value)) {\n if (matchValue(match.type, v, match.value, match)) {\n 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","const 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 #baseUrl;\n #cacheTtl;\n #cache = null;\n #cacheTime = null;\n #ttlEffective = 0;\n #etag;\n\n constructor({ siteUuid, baseUrl, cacheTtl, etag } = {}) {\n this.#siteUuid = siteUuid ?? process.env.PATCHSTACK_SITE_UUID;\n this.#baseUrl = baseUrl ?? process.env.PATCHSTACK_PULSE_RULES_URL ?? DEFAULT_BASE_URL;\n this.#cacheTtl = Number.isFinite(cacheTtl) && cacheTtl > 0 ? cacheTtl : DEFAULT_CACHE_TTL;\n this.#etag = etag ?? 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 const headers = { Accept: 'application/json' };\n if (this.#etag) headers['If-None-Match'] = this.#etag;\n const response = await fetch(url, { method: 'GET', headers, signal: AbortSignal.timeout(30_000) });\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 };\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","// 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 if (contentType.includes('application/json')) {\n try {\n body = JSON.parse(rawBody);\n } catch {\n body = {};\n }\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n body = {};\n for (const [k, v] of new URLSearchParams(rawBody)) {\n body[k] = k in body ? [].concat(body[k], v) : v;\n }\n } else if (contentType.includes('multipart/form-data')) {\n const boundary = /boundary=(\"?)([^\";]+)\\1/i.exec(contentType)?.[2];\n if (boundary) {\n const parsed = parseMultipart(rawBody, boundary);\n body = parsed.body;\n files = parsed.files;\n }\n }\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 const ceiling = Math.max(max, max * 4);\n const declared = Number(request.headers?.get?.('content-length') || 0);\n if (declared && declared > ceiling) return '';\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.\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 files[name] = name in files ? [].concat(files[name], filename) : filename;\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 { parseMultipart } 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 if (contentType.includes('application/json')) {\n try {\n body = JSON.parse(rawBody);\n } catch {\n body = {};\n }\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n body = {};\n for (const [k, v] of new URLSearchParams(rawBody)) {\n body[k] = k in body ? [].concat(body[k], v) : v;\n }\n } else if (contentType.includes('multipart/form-data')) {\n // Same parsing as the fetch adapter — expose field names/values via post.<field> and file\n // metadata via files.<field>, so field-scoped rules match uploads on a raw-Node server too.\n const boundary = /boundary=(\"?)([^\";]+)\\1/i.exec(contentType)?.[2];\n if (boundary) {\n const parsed = parseMultipart(rawBody, boundary);\n body = parsed.body;\n files = parsed.files;\n }\n }\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, 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 // 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 || !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)) 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 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 guarded = async (input, init) => {\n const url = typeof input === 'string' ? input : (input && input.url) || String(input);\n let host = null;\n try {\n host = new URL(url).hostname;\n } catch {\n host = null;\n }\n const method = (init && init.method) || (input && input.method) || 'GET';\n // hostname / allowlist / literal-IP check, then a DNS-resolution check for real hostnames.\n if (block(url, host, method) || (await resolvesToDisallowed(url, host, method))) {\n throw new Error(`Patchstack blocked an outbound request to a disallowed address: ${host ?? url}`);\n }\n return originalFetch(input, init);\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 // 3. global WebSocket — ws:// / wss:// egress that never touches fetch or node:http.\n const OriginalWS = globalThis.WebSocket;\n if (typeof OriginalWS === 'function' && !OriginalWS.__patchstackGuarded) {\n const GuardedWS = new Proxy(OriginalWS, {\n construct(target, args, newTarget) {\n const url = String(args?.[0] ?? '');\n let host = null;\n try {\n host = new URL(url).hostname;\n } catch {\n host = null;\n }\n if (block(url, host, 'WEBSOCKET')) {\n throw new Error(`Patchstack blocked an outbound WebSocket to a disallowed address: ${host ?? url}`);\n }\n return Reflect.construct(target, args, newTarget);\n },\n });\n OriginalWS.__patchstackGuarded = true; // marker on the original guards against double-wrap\n globalThis.WebSocket = GuardedWS;\n restores.push(() => {\n if (globalThis.WebSocket === GuardedWS) globalThis.WebSocket = OriginalWS;\n delete OriginalWS.__patchstackGuarded;\n });\n }\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// 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 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 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 rule_v2: [{ parameter: 'response.body', match: { type: 'regex', value: '/\\\\bAIza[0-9A-Za-z_-]{35}\\\\b/' } }]\n },\n {\n id: 'resp-jwt',\n title: 'JWT in response body',\n phase: 'response',\n category: 'secret-exposure',\n action: 'redact',\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 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 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 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 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","// 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","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","path","DEFAULT_BASE_URL","DEFAULT_CACHE_TTL","JITTER_FRACTION","parseCookies","path","import_node_path","allow","reportManifest","walk"]}