@secondlayer/subgraphs 8.0.2 → 8.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@
2
2
  "version": 3,
3
3
  "sources": ["src/runtime/emitter.ts", "src/runtime/formats/index.ts", "src/runtime/formats/cloudevents.ts", "src/runtime/formats/cloudflare.ts", "src/runtime/formats/inngest.ts", "src/runtime/formats/raw.ts", "src/runtime/formats/standard-webhooks.ts", "src/runtime/formats/trigger.ts", "src/runtime/meter-socket.ts", "src/runtime/receiver-cert.ts"],
4
4
  "sourcesContent": [
5
- "import { randomUUID } from \"node:crypto\";\nimport { lookup as dnsLookup } from \"node:dns/promises\";\nimport {\n\ttype Database,\n\ttype Webhook,\n\ttype WebhookOutbox,\n\tdescribeDbUrl,\n\tgetTargetDb,\n} from \"@secondlayer/shared/db\";\nimport { finalizeReplays } from \"@secondlayer/shared/db/queries/webhook-replays\";\nimport { getWebhookSigningSecret } from \"@secondlayer/shared/db/queries/webhooks\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport { listen, targetListenerUrl } from \"@secondlayer/shared/queue/listener\";\nimport {\n\ttype WebhookTestResult,\n\twebhookTimeoutMsCeiling,\n} from \"@secondlayer/shared/schemas/webhooks\";\nimport { type Kysely, sql } from \"kysely\";\nimport { buildForFormat } from \"./formats/index.ts\";\nimport { recordDelivery } from \"./meter-socket.ts\";\nimport { refreshReceiverCerts } from \"./receiver-cert.ts\";\n\n/**\n * Webhook emitter — drains `webhook_outbox` and POSTs deliveries.\n *\n * Hot path: LISTEN on `webhooks:new_outbox` and `webhooks:changed`.\n * On notify, claim a batch with `FOR UPDATE SKIP LOCKED LIMIT 50`, dispatch\n * each row via HTTP, write a `webhook_deliveries` attempt row, then\n * either mark `status='delivered'` or schedule the next attempt.\n *\n * Backoff schedule (attempt → wait):\n * 0 → 30s, 1 → 2m, 2 → 10m, 3 → 1h, 4 → 6h, 5 → 24h, 6 → 72h.\n * After `max_retries` (default 7) attempts → `status='dead'`.\n *\n * Per-sub circuit breaker: 20 consecutive failures → sub flipped to\n * `paused` with `circuit_opened_at=NOW()`. Manual /resume drains backlog.\n *\n * Per-sub concurrency cap: in-memory semaphore, default 4 in-flight HTTP\n * requests per webhook. Sprint-4 adds SSRF allowlist.\n */\n\nconst BATCH_SIZE = 50;\nconst LIVE_SHARE = 0.9; // 90% of batch to non-replay, 10% to replay\nconst BACKOFF_SECONDS = [30, 120, 600, 3600, 21600, 86400, 259200];\nconst CIRCUIT_THRESHOLD = 20;\n/**\n * When a batch is claimed the outbox row's `next_attempt_at` is pushed\n * `LOCK_WINDOW_MS` into the future. Any crash between claim + settle\n * leaves the row re-claimable after this window expires — the SSOT for\n * double-dispatch prevention.\n *\n * Must exceed the maximum possible in-flight delivery time so a slow-but-alive\n * receiver's row is never re-claimed mid-delivery (duplicate dispatch). Derived\n * from the configurable timeout ceiling (`WEBHOOK_TIMEOUT_MS_CEILING`, default\n * 300_000ms — see `webhookTimeoutMsCeiling` in shared/schemas/webhooks.ts) so a\n * raised ceiling can never create a delivery window shorter than a webhook's\n * own timeout.\n */\nexport const MAX_WEBHOOK_TIMEOUT_MS: number = webhookTimeoutMsCeiling();\nexport const LOCK_WINDOW_MS: number = MAX_WEBHOOK_TIMEOUT_MS + 60_000; // ceiling + settle margin\n\n/** A sub's persistent delivery queue + in-flight counter. Lives for as long\n * as the sub has (or recently had) work — see `enqueueForSub`/`pumpSub`.\n * `sub` is refreshed on every enqueue so a status/concurrency change (a\n * pause, a resume, a config edit) is picked up by the next batch of rows\n * without waiting for anything to expire. */\ninterface SubQueue {\n\tsub: Webhook;\n\tqueue: WebhookOutbox[];\n\tinFlight: number;\n}\n\ninterface RunningState {\n\trunning: boolean;\n\t/** Per-webhook queue + concurrency counter — see `SubQueue`. Replaces a\n\t * bare in-flight counter so dispatch can be decoupled from the claim\n\t * transaction (see `claimAndDispatchOnce`): claiming a batch no longer\n\t * waits for a sub's HTTP calls to finish before the NEXT claim can run,\n\t * it just hands rows to that sub's queue and returns. */\n\tsubQueues: Map<string, SubQueue>;\n\tclaimInFlight: boolean;\n\t/** Set when a wake (NOTIFY) arrives while a claim cycle is already\n\t * running. The in-flight cycle checks this before releasing the lock —\n\t * see `claimAndDrain`'s \"drain-loop\" pass — so rows that land mid-drain\n\t * aren't stranded until an unrelated future wake or the safety poll. */\n\tclaimPending: boolean;\n\t/** The promise of whichever `claimAndDrain` call currently owns\n\t * `claimInFlight` (assigned by that call itself, before its first\n\t * `await`, so there is no race with a concurrent caller that just sets\n\t * `claimPending` and returns). `stopEmitter`'s clean-stop path awaits\n\t * this so shutdown doesn't race a claim pass that's mid-dispatch. */\n\tcurrentClaim: Promise<number> | null;\n\t/** Every `runOne` promise currently dispatching, added by `pumpSub` at\n\t * start and removed on settle. `stopEmitter` awaits this set (bounded)\n\t * so it never reports \"stopped\" while a delivery is still mid-flight. */\n\tinFlightRuns: Set<Promise<void>>;\n}\n\nfunction nextDelaySeconds(attempt: number): number {\n\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\treturn BACKOFF_SECONDS[Math.min(attempt, BACKOFF_SECONDS.length - 1)]!;\n}\n\n// ── SSRF guard ────────────────────────────────────────────────────────\n// Block deliveries to private/loopback/link-local ranges unless\n// SECONDLAYER_ALLOW_PRIVATE_EGRESS=true (self-host + local-dev opt-in).\n\nconst PRIVATE_V4_PATTERNS = [\n\t/^127\\./, // loopback\n\t/^10\\./, // private class A\n\t/^172\\.(1[6-9]|2\\d|3[01])\\./, // private class B\n\t/^192\\.168\\./, // private class C\n\t/^169\\.254\\./, // link-local\n\t/^0\\./, // \"this\" network\n\t/^100\\.(6[4-9]|[7-9]\\d|1[01]\\d|12[0-7])\\./, // CGNAT 100.64/10\n\t/^198\\.(1[89])\\./, // benchmarking 198.18.0.0/15\n\t/^(22[4-9]|23[0-9])\\./, // multicast 224.0.0.0/4\n\t/^(24[0-9]|25[0-5])\\./, // reserved 240.0.0.0/4 (incl. 255.255.255.255 broadcast)\n];\n\n/**\n * Classify a raw IP address literal (v4 or v6, no brackets, already lowercased\n * or not) as private/loopback/link-local/reserved. Covers v4 private ranges +\n * link-local (incl. `169.254.169.254`), `0.0.0.0`, benchmarking\n * (`198.18.0.0/15`), multicast (`224.0.0.0/4`), reserved/broadcast\n * (`240.0.0.0/4`, incl. `255.255.255.255`), IPv6 loopback (`::1`), unspecified\n * (`::`), unique-local (`fc00::/7`), link-local (`fe80::/10`), IPv6 multicast\n * (`ff00::/8`), IPv4-mapped IPv6 (`::ffff:127.0.0.1`, `::ffff:7f00:0001`), and\n * NAT64 (`64:ff9b::/96`, embedded v4 classified the same as IPv4-mapped).\n *\n * Shared by `isPrivateEgress` (literal-hostname fast-fail) and the resolved-\n * DNS-address check in `checkEgressAllowed` (rebinding mitigation).\n */\nfunction isPrivateIp(address: string): boolean {\n\tconst host = address.toLowerCase();\n\n\tif (host === \"0.0.0.0\") return true;\n\tif (host === \"::\" || host === \"::1\") return true;\n\t// Unique-local (fc00::/7) + link-local (fe80::/10) + multicast (ff00::/8)\n\tif (/^f[cd][0-9a-f]{2}:/.test(host)) return true;\n\tif (/^fe[89ab][0-9a-f]:/.test(host)) return true;\n\tif (/^ff[0-9a-f]{2}:/.test(host)) return true;\n\n\t// IPv4-mapped IPv6 — `::ffff:127.0.0.1` or `::ffff:7f00:0001`\n\tconst mapped = host.match(/^::ffff:(.+)$/);\n\tif (mapped) {\n\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\tconst inner = mapped[1]!;\n\t\t// Dotted form: rerun v4 checks.\n\t\tif (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(inner)) {\n\t\t\tfor (const p of PRIVATE_V4_PATTERNS) if (p.test(inner)) return true;\n\t\t}\n\t\t// Hex form: 7f00:0001 → 127.0.0.1\n\t\tconst hex = inner.match(/^([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);\n\t\tif (hex) {\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\t\tconst a = Number.parseInt(hex[1]!, 16);\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\t\tconst b = Number.parseInt(hex[2]!, 16);\n\t\t\tconst dotted = `${(a >> 8) & 0xff}.${a & 0xff}.${(b >> 8) & 0xff}.${b & 0xff}`;\n\t\t\tfor (const p of PRIVATE_V4_PATTERNS) if (p.test(dotted)) return true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t// NAT64 (`64:ff9b::/96`) embeds an IPv4 address in the low 32 bits —\n\t// classify it exactly like the IPv4-mapped case above (dotted or hex).\n\tconst nat64 = host.match(/^64:ff9b::(.+)$/);\n\tif (nat64) {\n\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\tconst inner = nat64[1]!;\n\t\tif (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(inner)) {\n\t\t\tfor (const p of PRIVATE_V4_PATTERNS) if (p.test(inner)) return true;\n\t\t}\n\t\tconst hex = inner.match(/^([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);\n\t\tif (hex) {\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\t\tconst a = Number.parseInt(hex[1]!, 16);\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\t\tconst b = Number.parseInt(hex[2]!, 16);\n\t\t\tconst dotted = `${(a >> 8) & 0xff}.${a & 0xff}.${(b >> 8) & 0xff}.${b & 0xff}`;\n\t\t\tfor (const p of PRIVATE_V4_PATTERNS) if (p.test(dotted)) return true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tfor (const p of PRIVATE_V4_PATTERNS) {\n\t\tif (p.test(host)) return true;\n\t}\n\treturn false;\n}\n\n/**\n * Reject hostnames spelled as private IPs (cheap, synchronous, no I/O — a\n * fast-fail pre-filter). DNS-level rebinding (hostname that *resolves* to a\n * private IP at egress time) is NOT caught here — see `checkEgressAllowed`,\n * which resolves DNS and validates every returned address.\n */\nfunction isPrivateEgress(url: string): boolean {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(url);\n\t} catch {\n\t\treturn true; // malformed URL: reject\n\t}\n\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n\t\treturn true;\n\t}\n\n\t// Strip brackets from IPv6 literals.\n\tconst raw = parsed.hostname.toLowerCase();\n\tconst host =\n\t\traw.startsWith(\"[\") && raw.endsWith(\"]\") ? raw.slice(1, -1) : raw;\n\n\tif (host === \"localhost\") return true;\n\treturn isPrivateIp(host);\n}\n\n/** How often the emitter re-probes receivers' TLS certificates. */\nconst RECEIVER_CERT_INTERVAL_MS = 30 * 60_000;\n\nexport function allowPrivateEgress(): boolean {\n\treturn process.env.SECONDLAYER_ALLOW_PRIVATE_EGRESS === \"true\";\n}\n\ninterface ResolvedAddress {\n\taddress: string;\n\tfamily: number;\n}\n\ntype DnsLookupFn = (hostname: string) => Promise<ResolvedAddress[]>;\n\nasync function defaultDnsLookup(hostname: string): Promise<ResolvedAddress[]> {\n\treturn dnsLookup(hostname, { all: true });\n}\n\nlet dnsLookupImpl: DnsLookupFn = defaultDnsLookup;\n\n/**\n * Test-only seam: inject a fake DNS resolver so tests can simulate a hostname\n * resolving to a private/metadata IP without depending on real DNS or\n * network access. Pass `null` to restore the real `dns.lookup`-backed\n * resolver. Production code never calls this — only `ssrf.test.ts` does.\n */\nexport function __setDnsLookupForTest(fn: DnsLookupFn | null): void {\n\tdnsLookupImpl = fn ?? defaultDnsLookup;\n}\n\nconst ALLOW_HINT = \"(set SECONDLAYER_ALLOW_PRIVATE_EGRESS=true to allow)\";\n\n/**\n * Full egress check: literal fast-fail, then resolve DNS and reject if *any*\n * returned address (not just the first) is private/loopback/link-local —\n * a single private answer among several is enough for an attacker to abuse.\n *\n * Residual TOCTOU: this resolves-and-validates *immediately before* `fetch()`\n * but does not pin the actual connection to the validated address. True\n * pinning (resolve once, connect to that literal IP, keep the original `Host`\n * header/SNI) was attempted per plan f053 via a custom undici `Agent` with\n * `connect.lookup` passed as `fetch()`'s `dispatcher` — the standard Node\n * ecosystem pattern for this. Empirically, under Bun 1.3.10, that hook was\n * silently never invoked (confirmed with a throwaway smoke test hitting a\n * real local HTTP server: `lookupCalled` stayed `false` and the connection\n * failed even though the dispatcher was passed) — Bun's `fetch()` does not\n * implement undici's `connect.lookup` dispatcher hook, whether reached via\n * the global `fetch` or `import { fetch } from \"undici\"` (Bun overrides\n * \"undici\"'s `fetch` export with its own native implementation regardless of\n * an installed real `undici` package). Re-tested under Bun 1.4.2 (plan 043):\n * identical result — `lookupCalled` still stays `false` via both the global\n * `fetch` and `import { fetch } from \"undici\"`, so the gap remains unfixed at\n * this version too. So a second DNS answer between this check and `fetch()`'s\n * own resolution (true rebinding, not just a one-time private answer) could\n * in theory still slip through. This closes the practical rebinding gap\n * (attacker's hostname resolves private at delivery time) without adding a\n * dependency; a network-level egress allowlist/proxy is the recommended\n * defense-in-depth for the remaining TOCTOU sliver.\n */\nexport async function checkEgressAllowed(url: string): Promise<string | null> {\n\tif (isPrivateEgress(url)) {\n\t\treturn `refused private egress: literal address ${ALLOW_HINT}`;\n\t}\n\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(url);\n\t} catch {\n\t\treturn `refused private egress: malformed URL ${ALLOW_HINT}`;\n\t}\n\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n\t\treturn `refused private egress: unsupported protocol ${ALLOW_HINT}`;\n\t}\n\n\tconst raw = parsed.hostname.toLowerCase();\n\tconst hostname =\n\t\traw.startsWith(\"[\") && raw.endsWith(\"]\") ? raw.slice(1, -1) : raw;\n\n\tlet resolved: ResolvedAddress[];\n\ttry {\n\t\tresolved = await dnsLookupImpl(hostname);\n\t} catch (err) {\n\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\treturn `refused private egress: DNS resolution failed (${msg}) ${ALLOW_HINT}`;\n\t}\n\tif (resolved.length === 0) {\n\t\treturn `refused private egress: DNS resolution returned no addresses ${ALLOW_HINT}`;\n\t}\n\tfor (const { address } of resolved) {\n\t\tif (isPrivateIp(address)) {\n\t\t\treturn `refused private egress: hostname resolves to private address ${address} ${ALLOW_HINT}`;\n\t\t}\n\t}\n\treturn null;\n}\n\n/** The wire result of one POST attempt (no DB side effect) — shared by the\n * emitter hot path and the `deliverTestEvent` test path. */\ninterface PostResult {\n\tok: boolean;\n\tstatusCode: number | null;\n\terror: string | null;\n\tdurationMs: number;\n\tresponseBody: string | null;\n\tresponseHeaders: Record<string, string> | null;\n}\n\n/**\n * Bound on redirect hops honored while delivering a webhook. `fetch` is\n * called with `redirect: \"manual\"` so a 3xx never auto-follows — each hop's\n * target is re-validated through `checkEgressAllowed` before it is fetched\n * (see `postToWebhook`), otherwise a `Location` header pointing at a\n * private/metadata address would bypass the egress guard entirely. Counts\n * every fetch issued (the initial request plus each redirect), so this is\n * also the max number of `fetch` calls one delivery attempt can make.\n */\nexport const MAX_REDIRECT_HOPS: number = 3;\n\n/** POST a pre-built body to a webhook URL with the SSRF guard + timeout.\n * Pure transport: returns the attempt result; the caller logs the delivery row.\n * Follows redirects manually (up to `MAX_REDIRECT_HOPS`), re-running the\n * egress guard against every hop's target — the guard only protects the\n * first request otherwise, and a webhook target can redirect to a private/\n * metadata address to read back the response after f053 pinned the guard to\n * just the original URL. */\nasync function postToWebhook(\n\turl: string,\n\tbody: string,\n\theaders: Record<string, string>,\n\ttimeoutMs: number,\n): Promise<PostResult> {\n\tconst start = performance.now();\n\tlet target = url;\n\tlet statusCode: number | null = null;\n\tlet error: string | null = null;\n\tlet ok = false;\n\tlet responseBody = \"\";\n\tlet responseHeaders: Record<string, string> | null = null;\n\ttry {\n\t\tfor (let hop = 0; ; hop++) {\n\t\t\tif (!allowPrivateEgress()) {\n\t\t\t\tconst refusal = await checkEgressAllowed(target);\n\t\t\t\tif (refusal) {\n\t\t\t\t\tlogger.warn(\"[emitter] refused private egress\", {\n\t\t\t\t\t\turl: target,\n\t\t\t\t\t\treason: refusal,\n\t\t\t\t\t});\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tstatusCode: null,\n\t\t\t\t\t\terror: refusal,\n\t\t\t\t\t\tdurationMs: Math.round(performance.now() - start),\n\t\t\t\t\t\tresponseBody: null,\n\t\t\t\t\t\tresponseHeaders: null,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (hop >= MAX_REDIRECT_HOPS) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tstatusCode,\n\t\t\t\t\terror: `too many redirects (exceeded ${MAX_REDIRECT_HOPS} hops)`,\n\t\t\t\t\tdurationMs: Math.round(performance.now() - start),\n\t\t\t\t\tresponseBody: null,\n\t\t\t\t\tresponseHeaders: null,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst res = await fetch(target, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders,\n\t\t\t\tbody,\n\t\t\t\tredirect: \"manual\",\n\t\t\t\tsignal: AbortSignal.timeout(timeoutMs),\n\t\t\t});\n\t\t\tstatusCode = res.status;\n\n\t\t\tconst location = res.headers.get(\"location\");\n\t\t\tif (res.status >= 300 && res.status < 400 && location) {\n\t\t\t\ttarget = new URL(location, target).toString();\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tok = res.ok;\n\t\t\t// Collect small response preview for the delivery log (≤8KB).\n\t\t\tconst buf = await res.arrayBuffer();\n\t\t\tconst truncated = buf.byteLength > 8192 ? buf.slice(0, 8192) : buf;\n\t\t\tresponseBody = Buffer.from(truncated).toString(\"utf8\");\n\t\t\tresponseHeaders = Object.fromEntries(res.headers.entries());\n\t\t\tbreak;\n\t\t}\n\t} catch (err) {\n\t\terror = err instanceof Error ? err.message : String(err);\n\t}\n\treturn {\n\t\tok,\n\t\tstatusCode,\n\t\terror,\n\t\tdurationMs: Math.round(performance.now() - start),\n\t\tresponseBody: responseBody || null,\n\t\tresponseHeaders,\n\t};\n}\n\n/**\n * Test-only seam: exposes `postToWebhook` (otherwise module-private) so\n * redirect/egress behavior can be exercised directly against a stubbed\n * `fetch` + injected DNS lookup, without standing up the DB-backed emitter\n * loop. Production code never calls this — only tests do.\n */\nexport const __postToWebhookForTest: (\n\turl: string,\n\tbody: string,\n\theaders: Record<string, string>,\n\ttimeoutMs: number,\n) => Promise<PostResult> = postToWebhook;\n\nasync function dispatchOne(\n\tdb: Kysely<Database>,\n\toutboxRow: WebhookOutbox,\n\tsub: Webhook,\n): Promise<{\n\tok: boolean;\n\tstatusCode: number | null;\n\terror: string | null;\n\tdurationMs: number;\n}> {\n\tconst { body, headers } = buildForFormat(\n\t\toutboxRow,\n\t\tsub,\n\t\tgetWebhookSigningSecret(sub),\n\t);\n\tconst r = await postToWebhook(sub.url, body, headers, sub.timeout_ms);\n\n\tconst attempt = outboxRow.attempt + 1;\n\tawait db\n\t\t.insertInto(\"webhook_deliveries\")\n\t\t.values({\n\t\t\toutbox_id: outboxRow.id,\n\t\t\twebhook_id: outboxRow.webhook_id,\n\t\t\tattempt,\n\t\t\tstatus_code: r.statusCode,\n\t\t\tresponse_headers: r.responseHeaders,\n\t\t\tresponse_body: r.responseBody,\n\t\t\terror_message: r.error,\n\t\t\tduration_ms: r.durationMs,\n\t\t})\n\t\t.execute();\n\n\treturn {\n\t\tok: r.ok,\n\t\tstatusCode: r.statusCode,\n\t\terror: r.error,\n\t\tdurationMs: r.durationMs,\n\t};\n}\n\n/** A representative (non-persisted) outbox row for a test delivery, so\n * `buildForFormat` produces a realistic body. */\nfunction buildTestOutboxRow(sub: Webhook): WebhookOutbox {\n\tconst now = new Date();\n\treturn {\n\t\tid: randomUUID(),\n\t\twebhook_id: sub.id,\n\t\tkind: sub.kind,\n\t\tblock_height: 0,\n\t\ttx_id: null,\n\t\trow_pk: null,\n\t\tevent_type: \"chain.test.apply\",\n\t\tpayload: {\n\t\t\ttest: true,\n\t\t\tmessage: \"Secondlayer test delivery\",\n\t\t\twebhook_id: sub.id,\n\t\t\tsent_at: now.toISOString(),\n\t\t},\n\t\tdedup_key: `test:${sub.id}:${now.getTime()}`,\n\t\tattempt: 0,\n\t\tnext_attempt_at: now,\n\t\tstatus: \"pending\",\n\t\tis_replay: false,\n\t\tblock_time: null,\n\t\tdelivered_at: null,\n\t\tfailed_at: null,\n\t\tlocked_by: null,\n\t\tlocked_until: null,\n\t\tlast_error: null,\n\t\tcreated_at: now,\n\t};\n}\n\n/**\n * Build a representative webhook for `sub`'s configured format, POST it (same\n * SSRF guard + timeout + signing as a real delivery), and log a delivery row\n * with a null `outbox_id` so it appears under the webhook's deliveries\n * without being tied to a queued event. Powers `POST /:id/test`.\n */\nexport async function deliverTestEvent(\n\tdb: Kysely<Database>,\n\tsub: Webhook,\n): Promise<WebhookTestResult> {\n\tconst testRow = buildTestOutboxRow(sub);\n\tconst { body, headers } = buildForFormat(\n\t\ttestRow,\n\t\tsub,\n\t\tgetWebhookSigningSecret(sub),\n\t);\n\tconst r = await postToWebhook(sub.url, body, headers, sub.timeout_ms);\n\tconst inserted = await db\n\t\t.insertInto(\"webhook_deliveries\")\n\t\t.values({\n\t\t\toutbox_id: null,\n\t\t\twebhook_id: sub.id,\n\t\t\tattempt: 1,\n\t\t\tstatus_code: r.statusCode,\n\t\t\tresponse_headers: r.responseHeaders,\n\t\t\tresponse_body: r.responseBody,\n\t\t\terror_message: r.error,\n\t\t\tduration_ms: r.durationMs,\n\t\t})\n\t\t.returning(\"id\")\n\t\t.executeTakeFirstOrThrow();\n\treturn {\n\t\tok: r.ok,\n\t\tstatusCode: r.statusCode,\n\t\terror: r.error,\n\t\tdurationMs: r.durationMs,\n\t\tdeliveryId: inserted.id,\n\t};\n}\n\nasync function settleDelivered(\n\tdb: Kysely<Database>,\n\toutboxRow: WebhookOutbox,\n): Promise<void> {\n\tawait db.transaction().execute(async (tx) => {\n\t\tconst result = await tx\n\t\t\t.updateTable(\"webhook_outbox\")\n\t\t\t.set({\n\t\t\t\tstatus: \"delivered\",\n\t\t\t\tdelivered_at: new Date(),\n\t\t\t\tattempt: outboxRow.attempt + 1,\n\t\t\t\tlocked_by: null,\n\t\t\t\tlocked_until: null,\n\t\t\t})\n\t\t\t// Guard against a reorg that marked this row `dead` (orphaned) while\n\t\t\t// the POST was in flight — settling a delivery outcome must never\n\t\t\t// resurrect a row the reorg already decided is gone. `status='pending'`\n\t\t\t// is the only state a claimed row can settle from.\n\t\t\t.where(\"id\", \"=\", outboxRow.id)\n\t\t\t.where(\"status\", \"=\", \"pending\")\n\t\t\t.executeTakeFirst();\n\t\tif (Number(result.numUpdatedRows ?? 0) === 0) {\n\t\t\tlogger.info(\"webhook.settle.orphaned\", {\n\t\t\t\toutboxId: outboxRow.id,\n\t\t\t\twebhookId: outboxRow.webhook_id,\n\t\t\t\toutcome: \"delivered\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tawait tx\n\t\t\t.updateTable(\"webhooks\")\n\t\t\t.set({\n\t\t\t\tlast_delivery_at: new Date(),\n\t\t\t\tlast_success_at: new Date(),\n\t\t\t\tcircuit_failures: 0,\n\t\t\t\tlast_error: null,\n\t\t\t\tupdated_at: new Date(),\n\t\t\t})\n\t\t\t.where(\"id\", \"=\", outboxRow.webhook_id)\n\t\t\t.execute();\n\n\t\t// Hosted-stack event meter (plan 044, step 5): counts a real delivery,\n\t\t// never a retry (this function only runs on the successful outcome) and\n\t\t// never a test delivery (`deliverTestEvent` never calls this). A no-op\n\t\t// on self-host (WEBHOOK_METER_SOCKET unset).\n\t\trecordDelivery();\n\t});\n}\n\nasync function settleFailed(\n\tdb: Kysely<Database>,\n\toutboxRow: WebhookOutbox,\n\tsub: Webhook,\n\terrText: string,\n): Promise<void> {\n\tconst attempt = outboxRow.attempt + 1;\n\tconst isDead = attempt >= sub.max_retries;\n\tconst nextAt = isDead\n\t\t? null\n\t\t: new Date(Date.now() + nextDelaySeconds(outboxRow.attempt) * 1000);\n\n\tawait db.transaction().execute(async (tx) => {\n\t\tconst result = await tx\n\t\t\t.updateTable(\"webhook_outbox\")\n\t\t\t.set({\n\t\t\t\tattempt,\n\t\t\t\tnext_attempt_at: nextAt ?? new Date(),\n\t\t\t\tstatus: isDead ? \"dead\" : \"pending\",\n\t\t\t\tfailed_at: isDead ? new Date() : null,\n\t\t\t\tlocked_by: null,\n\t\t\t\tlocked_until: null,\n\t\t\t})\n\t\t\t// Guard against a reorg that marked this row `dead` (orphaned) while\n\t\t\t// the POST was in flight — see the matching guard in `settleDelivered`.\n\t\t\t.where(\"id\", \"=\", outboxRow.id)\n\t\t\t.where(\"status\", \"=\", \"pending\")\n\t\t\t.executeTakeFirst();\n\t\tif (Number(result.numUpdatedRows ?? 0) === 0) {\n\t\t\tlogger.info(\"webhook.settle.orphaned\", {\n\t\t\t\toutboxId: outboxRow.id,\n\t\t\t\twebhookId: outboxRow.webhook_id,\n\t\t\t\toutcome: \"failed\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Atomic increment — concurrent failures must not clobber each other.\n\t\t// `RETURNING circuit_failures` gives us the post-increment value to\n\t\t// decide whether this failure tripped the circuit.\n\t\tconst incResult = await sql<{ circuit_failures: number }>`\n\t\t\tUPDATE webhooks\n\t\t\tSET circuit_failures = circuit_failures + 1,\n\t\t\t\tlast_delivery_at = NOW(),\n\t\t\t\tlast_error = ${errText.slice(0, 500)},\n\t\t\t\tupdated_at = NOW()\n\t\t\tWHERE id = ${sub.id}\n\t\t\tRETURNING circuit_failures\n\t\t`.execute(tx);\n\t\tconst newFailures =\n\t\t\tincResult.rows[0]?.circuit_failures ?? sub.circuit_failures + 1;\n\t\tconst shouldTripCircuit = newFailures >= CIRCUIT_THRESHOLD;\n\n\t\tif (shouldTripCircuit) {\n\t\t\t// Transition to paused only on the first failure that crossed\n\t\t\t// the threshold — additional failures in-flight harmlessly\n\t\t\t// re-set the same fields.\n\t\t\tawait tx\n\t\t\t\t.updateTable(\"webhooks\")\n\t\t\t\t.set({\n\t\t\t\t\tstatus: \"paused\",\n\t\t\t\t\tcircuit_opened_at: new Date(),\n\t\t\t\t\tupdated_at: new Date(),\n\t\t\t\t})\n\t\t\t\t.where(\"id\", \"=\", sub.id)\n\t\t\t\t.execute();\n\t\t\tlogger.warn(\n\t\t\t\t\"Webhook circuit tripped — paused after consecutive failures\",\n\t\t\t\t{\n\t\t\t\t\twebhook: sub.name,\n\t\t\t\t\tfailures: newFailures,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t});\n}\n\n/** What woke this claim cycle — purely for the diagnostic log below; the\n * claim/dispatch logic itself doesn't branch on it. `\"drain-loop\"` marks a\n * pass this function re-ran on itself (see `claimAndDrain`) because a wake\n * arrived (or a per-lane batch cap was hit) while the previous pass was\n * still claiming. `\"changed\"` is a resume (or any webhook edit) — see the\n * `webhooks:changed` listener. */\ntype ClaimTrigger = \"notify\" | \"poll\" | \"startup\" | \"changed\" | \"drain-loop\";\n\n/**\n * The regression this closes: a NOTIFY that arrives while a claim cycle is\n * ALREADY running used to be dropped on the floor (the `claimInFlight` guard\n * below just returned 0), and nothing re-checked once that cycle finished.\n * Rows inserted mid-cycle — a normal burst of ~6 chain-webhook matches per\n * block — sat `pending` until an UNRELATED future wake happened to fire, or\n * the 2-minute safety poll.\n *\n * The holder of `claimInFlight` now keeps looping (`claimPending`, set by any\n * caller that finds the lock held) until a pass claims nothing NEW and no one\n * asked for a recheck while it ran — so a burst drains fully off one wake\n * instead of needing one wake per claim-sized chunk. Critically, this lock\n * wraps ONLY `claimAndDispatchOnce`'s DB claim query, never dispatch (see its\n * doc) — a slow or hanging receiver must never hold up the next claim.\n */\nasync function claimAndDrain(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\temitterId: string,\n\ttrigger: ClaimTrigger,\n): Promise<number> {\n\tif (state.claimInFlight) {\n\t\tstate.claimPending = true;\n\t\treturn 0;\n\t}\n\tstate.claimInFlight = true;\n\t// Assigned synchronously (before any `await` in `runClaimLoop` yields back\n\t// to the event loop) so `stopEmitter` can always await the pass that\n\t// actually owns the lock, never a concurrent caller's already-resolved\n\t// `claimPending` short-circuit above.\n\tconst drainPromise = runClaimLoop(db, state, emitterId, trigger);\n\tstate.currentClaim = drainPromise;\n\ttry {\n\t\treturn await drainPromise;\n\t} finally {\n\t\tif (state.currentClaim === drainPromise) state.currentClaim = null;\n\t}\n}\n\nasync function runClaimLoop(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\temitterId: string,\n\ttrigger: ClaimTrigger,\n): Promise<number> {\n\tlet totalClaimed = 0;\n\ttry {\n\t\tlet currentTrigger = trigger;\n\t\tfor (;;) {\n\t\t\t// Stop requested: claim no new rows. Anything already claimed by an\n\t\t\t// in-flight `claimAndDispatchOnce` call still gets handed to its\n\t\t\t// sub's queue, but `pumpSub`'s own `state.running` check means it\n\t\t\t// won't dispatch — those rows just keep their lock until the next\n\t\t\t// emitter re-claims them after LOCK_WINDOW_MS.\n\t\t\tif (!state.running) break;\n\t\t\tstate.claimPending = false;\n\t\t\tconst result = await claimAndDispatchOnce(\n\t\t\t\tdb,\n\t\t\t\tstate,\n\t\t\t\temitterId,\n\t\t\t\tcurrentTrigger,\n\t\t\t);\n\t\t\ttotalClaimed += result.claimed;\n\t\t\t// Keep going while either: a wake landed mid-pass (claimPending —\n\t\t\t// set by the guard above, from another caller), or either lane\n\t\t\t// (live/replay) came back full, meaning more may be waiting behind\n\t\t\t// it. Comparing against the LANE limits, not the combined batch\n\t\t\t// size, matters: live traffic alone is capped at `liveLimit` (90%\n\t\t\t// of BATCH_SIZE) and would never reach the full BATCH_SIZE on its\n\t\t\t// own, so that comparison never re-looped on a live-only backlog.\n\t\t\tif (!state.claimPending && !result.mayHaveMore) break;\n\t\t\tcurrentTrigger = \"drain-loop\";\n\t\t}\n\t} finally {\n\t\tstate.claimInFlight = false;\n\t}\n\treturn totalClaimed;\n}\n\ninterface ClaimResult {\n\tclaimed: number;\n\tdispatched: number;\n\treleased: number;\n\tmayHaveMore: boolean;\n}\n\n/**\n * One claim pass: SELECT a batch, mark it locked, then hand each sub's slice\n * to its persistent queue and return — WITHOUT waiting for any of it to\n * dispatch. Caller (`claimAndDrain`) owns the re-loop and the `claimInFlight`\n * lock, which now covers only this function's DB work.\n *\n * This decoupling is the fix for the emitter-wide latency regression: the\n * previous version awaited `Promise.all(subIds.map(drainForSub))` — every\n * sub's FULL dispatch — before returning, so the slowest receiver in a batch\n * (a hung connection, a multi-second response) held the process-wide claim\n * lock for as long as IT took, starving every other sub's claims (including\n * a fast sub's own fresh rows) for that whole time. Claiming is now a single\n * short transaction; delivery happens on each sub's own independent\n * queue/semaphore (`enqueueForSub`/`pumpSub`), so one sub's pace never\n * gates another's.\n *\n * Also fixes the \"stuck rows\" bug: a row claimed for a sub that turns out to\n * be `paused` (status read fresh here, after the claim) is released\n * IMMEDIATELY — `next_attempt_at` reset to now, lock cleared — instead of\n * being silently abandoned with its lock held for the full `LOCK_WINDOW_MS`.\n * The old code's `if (sub.status !== \"active\") return;` left the row\n * claimed-but-untouched: locked, `next_attempt_at` pushed far into the\n * future, never dispatched, never settled — a resumed webhook's backlog\n * then only drained once each row's stale lock happened to expire.\n */\nasync function claimAndDispatchOnce(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\temitterId: string,\n\ttrigger: ClaimTrigger,\n): Promise<ClaimResult> {\n\t// FOR UPDATE SKIP LOCKED — multiple emitters split the batch.\n\t// 90/10 live vs replay so a big replay doesn't starve live emits.\n\tconst liveLimit = Math.max(1, Math.round(BATCH_SIZE * LIVE_SHARE));\n\tconst replayLimit = BATCH_SIZE - liveLimit;\n\tconst { combined, liveCount, replayCount } = await db\n\t\t.transaction()\n\t\t.execute(async (tx) => {\n\t\t\tconst live = await sql<WebhookOutbox>`\n\t\t\t\t\tSELECT * FROM webhook_outbox\n\t\t\t\t\tWHERE status = 'pending'\n\t\t\t\t\t\tAND next_attempt_at <= NOW()\n\t\t\t\t\t\tAND is_replay = FALSE\n\t\t\t\t\tORDER BY next_attempt_at ASC\n\t\t\t\t\tFOR UPDATE SKIP LOCKED\n\t\t\t\t\tLIMIT ${sql.lit(liveLimit)}\n\t\t\t\t`.execute(tx);\n\t\t\tconst replay = await sql<WebhookOutbox>`\n\t\t\t\t\tSELECT * FROM webhook_outbox\n\t\t\t\t\tWHERE status = 'pending'\n\t\t\t\t\t\tAND next_attempt_at <= NOW()\n\t\t\t\t\t\tAND is_replay = TRUE\n\t\t\t\t\tORDER BY next_attempt_at ASC\n\t\t\t\t\tFOR UPDATE SKIP LOCKED\n\t\t\t\t\tLIMIT ${sql.lit(replayLimit)}\n\t\t\t\t`.execute(tx);\n\n\t\t\tconst rows = [...live.rows, ...replay.rows];\n\t\t\tif (rows.length === 0) {\n\t\t\t\treturn { combined: rows, liveCount: 0, replayCount: 0 };\n\t\t\t}\n\n\t\t\t// Push `next_attempt_at` forward by the lock window. This is\n\t\t\t// the only defense against double-dispatch if the emitter\n\t\t\t// process crashes mid-HTTP-call: the row won't be re-claimable\n\t\t\t// until `LOCK_WINDOW_MS` elapses, giving us a stale-lock\n\t\t\t// recovery window. `settleDelivered`/`settleFailed` overrides\n\t\t\t// this on the success/failure path (and the paused-sub release\n\t\t\t// below overrides it on the \"never got dispatched\" path).\n\t\t\tconst now = new Date();\n\t\t\tconst lockUntil = new Date(now.getTime() + LOCK_WINDOW_MS);\n\t\t\tawait tx\n\t\t\t\t.updateTable(\"webhook_outbox\")\n\t\t\t\t.set({\n\t\t\t\t\tlocked_by: emitterId,\n\t\t\t\t\tlocked_until: lockUntil,\n\t\t\t\t\tnext_attempt_at: lockUntil,\n\t\t\t\t})\n\t\t\t\t.where(\n\t\t\t\t\t\"id\",\n\t\t\t\t\t\"in\",\n\t\t\t\t\trows.map((r) => r.id),\n\t\t\t\t)\n\t\t\t\t.execute();\n\t\t\treturn {\n\t\t\t\tcombined: rows,\n\t\t\t\tliveCount: live.rows.length,\n\t\t\t\treplayCount: replay.rows.length,\n\t\t\t};\n\t\t});\n\n\tif (combined.length === 0) {\n\t\treturn { claimed: 0, dispatched: 0, released: 0, mayHaveMore: false };\n\t}\n\n\tconst bySubId = new Map<string, WebhookOutbox[]>();\n\tfor (const row of combined) {\n\t\tconst arr = bySubId.get(row.webhook_id);\n\t\tif (arr) arr.push(row);\n\t\telse bySubId.set(row.webhook_id, [row]);\n\t}\n\n\tconst subIds = Array.from(bySubId.keys());\n\tconst subs = await db\n\t\t.selectFrom(\"webhooks\")\n\t\t.selectAll()\n\t\t.where(\"id\", \"in\", subIds)\n\t\t.execute();\n\tconst subById = new Map(subs.map((s) => [s.id, s]));\n\n\tlet dispatched = 0;\n\tlet released = 0;\n\tconst releasedIds: string[] = [];\n\tfor (const subId of subIds) {\n\t\tconst sub = subById.get(subId);\n\t\t// biome-ignore lint/style/noNonNullAssertion: key came from bySubId itself\n\t\tconst rows = bySubId.get(subId)!;\n\t\tif (!sub || sub.status !== \"active\") {\n\t\t\treleased += rows.length;\n\t\t\treleasedIds.push(...rows.map((r) => r.id));\n\t\t\tcontinue;\n\t\t}\n\t\tdispatched += rows.length;\n\t\tenqueueForSub(db, state, sub, rows);\n\t}\n\n\tif (releasedIds.length > 0) {\n\t\t// Claimable again immediately: a webhook that's already resumed by the\n\t\t// time we notice the release loses nothing waiting for LOCK_WINDOW_MS\n\t\t// (up to several minutes) to expire on its own.\n\t\tawait db\n\t\t\t.updateTable(\"webhook_outbox\")\n\t\t\t.set({ next_attempt_at: new Date(), locked_by: null, locked_until: null })\n\t\t\t.where(\"id\", \"in\", releasedIds)\n\t\t\t.execute();\n\t}\n\n\t// One line per claim pass: what woke it, how much it found, how it split\n\t// between dispatched-now and released-back (paused), how stale the oldest\n\t// row was, and how loaded the in-flight pool already was — everything\n\t// needed to tell \"briefly busy\" apart from \"actually stuck\" without\n\t// reproducing it live. `in_flight`/`concurrency` sum across only the subs\n\t// THIS pass touched (a quiet sub's unrelated cap doesn't dilute the\n\t// reading).\n\tconst oldestCreatedAtMs = Math.min(\n\t\t...combined.map((r) => new Date(r.created_at).getTime()),\n\t);\n\tconst inFlight = subIds.reduce(\n\t\t(sum, id) => sum + (state.subQueues.get(id)?.inFlight ?? 0),\n\t\t0,\n\t);\n\tconst concurrency = subIds.reduce(\n\t\t(sum, id) => sum + (subById.get(id)?.concurrency || 4),\n\t\t0,\n\t);\n\tlogger.info(\"emitter claim cycle\", {\n\t\tevent: \"emitter_claim\",\n\t\ttrigger,\n\t\tclaimed: combined.length,\n\t\tdispatched,\n\t\treleased,\n\t\toldest_created_at_age_ms: Date.now() - oldestCreatedAtMs,\n\t\tin_flight: inFlight,\n\t\tconcurrency,\n\t});\n\n\treturn {\n\t\tclaimed: combined.length,\n\t\tdispatched,\n\t\treleased,\n\t\tmayHaveMore: liveCount >= liveLimit || replayCount >= replayLimit,\n\t};\n}\n\n/**\n * Hand `rows` to `sub`'s persistent queue and try to start dispatching\n * immediately. Decoupled from the claim transaction on purpose (see\n * `claimAndDispatchOnce`'s doc) — a slow or hanging sub's in-flight HTTP\n * calls must never hold up the next claim, for this sub or any other.\n *\n * `sub` is refreshed here on every call (not just on first creation) so a\n * status/concurrency change since the last batch — most importantly a\n * pause — is picked up by `pumpSub` without waiting for anything to expire.\n */\nfunction enqueueForSub(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\tsub: Webhook,\n\trows: WebhookOutbox[],\n): void {\n\tlet sq = state.subQueues.get(sub.id);\n\tif (!sq) {\n\t\tsq = { sub, queue: [], inFlight: 0 };\n\t\tstate.subQueues.set(sub.id, sq);\n\t} else {\n\t\tsq.sub = sub;\n\t}\n\tsq.queue.push(...rows);\n\tpumpSub(db, state, sub.id);\n}\n\n/**\n * Start as many workers as the sub's remaining concurrency allows, pulling\n * from its queue. Reentrant-safe without an explicit lock: every branch here\n * is synchronous (the only `await` lives in `runOne`, called but not\n * awaited), so JS's single-threaded execution means two calls — one from\n * `enqueueForSub`, one from a just-finished worker's `finally` — can never\n * interleave mid-loop; each runs to completion before the other starts.\n */\nfunction pumpSub(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\tsubId: string,\n): void {\n\tconst sq = state.subQueues.get(subId);\n\tif (!sq) return;\n\tconst cap = sq.sub.concurrency || 4;\n\twhile (\n\t\tstate.running &&\n\t\tsq.sub.status === \"active\" &&\n\t\tsq.inFlight < cap &&\n\t\tsq.queue.length > 0\n\t) {\n\t\tconst row = sq.queue.shift();\n\t\tif (!row) break;\n\t\tsq.inFlight++;\n\t\tconst runPromise = runOne(db, state, sq, row);\n\t\tstate.inFlightRuns.add(runPromise);\n\t\tvoid runPromise.finally(() => {\n\t\t\tstate.inFlightRuns.delete(runPromise);\n\t\t});\n\t}\n}\n\n/** Dispatch one claimed row end to end (POST, settle), then release its\n * in-flight slot and try to pull more work for the same sub. */\nasync function runOne(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\tsq: SubQueue,\n\trow: WebhookOutbox,\n): Promise<void> {\n\ttry {\n\t\tconst result = await dispatchOne(db, row, sq.sub);\n\t\tif (result.ok) {\n\t\t\tawait settleDelivered(db, row);\n\t\t} else {\n\t\t\tconst err = result.error ?? `HTTP ${result.statusCode ?? \"?\"}`;\n\t\t\tawait settleFailed(db, row, sq.sub, err);\n\t\t}\n\t} catch (err) {\n\t\tlogger.error(\"Emitter dispatch crashed\", {\n\t\t\toutboxId: row.id,\n\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t});\n\t\tawait settleFailed(\n\t\t\tdb,\n\t\t\trow,\n\t\t\tsq.sub,\n\t\t\terr instanceof Error ? err.message : String(err),\n\t\t);\n\t} finally {\n\t\tsq.inFlight--;\n\t\tpumpSub(db, state, sq.sub.id);\n\t}\n}\n\nexport interface StartEmitterOptions {\n\t/** Interval for the background poll (ms). Defaults to 2 minutes. */\n\tpollIntervalMs?: number;\n\t/** Retention sweep interval (ms). Defaults to 1 hour. */\n\tretentionIntervalMs?: number;\n\t/** Bound for the returned stop function's clean-shutdown drain — how long\n\t * it waits for the current claim pass + in-flight dispatches before\n\t * giving up and reporting them abandoned. Defaults to\n\t * `MAX_WEBHOOK_TIMEOUT_MS + 5_000` (a dispatch can't legitimately run\n\t * longer than the webhook timeout ceiling). `MAX_WEBHOOK_TIMEOUT_MS` is\n\t * fixed at module load from `WEBHOOK_TIMEOUT_MS_CEILING`, so this exists\n\t * mainly for tests that need a short bound without a 5-minute wait. */\n\tstopDrainDeadlineMs?: number;\n}\n\nasync function runRetention(db: Kysely<Database>): Promise<void> {\n\t// Replays first: their final counts come from outbox rows the deletes below\n\t// remove. Then delivered outbox >7d, deliveries >30d, dead outbox >90d,\n\t// finished replay records >90d.\n\tawait finalizeReplays(db);\n\tawait sql`\n\t\tDELETE FROM webhook_outbox\n\t\tWHERE status = 'delivered' AND delivered_at < NOW() - interval '7 days'\n\t`.execute(db);\n\tawait sql`\n\t\tDELETE FROM webhook_deliveries\n\t\tWHERE dispatched_at < NOW() - interval '30 days'\n\t`.execute(db);\n\tawait sql`\n\t\tDELETE FROM webhook_outbox\n\t\tWHERE status = 'dead' AND failed_at < NOW() - interval '90 days'\n\t`.execute(db);\n\tawait sql`\n\t\tDELETE FROM webhook_replays\n\t\tWHERE finished_at < NOW() - interval '90 days'\n\t`.execute(db);\n}\n\nexport async function startEmitter(\n\topts?: StartEmitterOptions,\n): Promise<() => Promise<void>> {\n\tconst emitterId = `emitter-${Math.random().toString(36).slice(2, 10)}`;\n\tconst db = getTargetDb();\n\tconst state: RunningState = {\n\t\trunning: true,\n\t\tsubQueues: new Map(),\n\t\tclaimInFlight: false,\n\t\tclaimPending: false,\n\t\tcurrentClaim: null,\n\t\tinFlightRuns: new Set(),\n\t};\n\tconst pollIntervalMs = opts?.pollIntervalMs ?? 120_000;\n\tconst retentionIntervalMs = opts?.retentionIntervalMs ?? 60 * 60_000;\n\n\tlogger.info(\"[emitter] started\", { id: emitterId });\n\n\t// LISTEN on new outbox + sub changes. Both channels fire on the TARGET DB\n\t// (webhook_outbox + webhooks are control-plane tables), so bind the\n\t// listener there — under the split it is NOT `DATABASE_URL`.\n\tconst listenUrl = targetListenerUrl();\n\tconst stopNew = await listen(\n\t\t\"webhooks:new_outbox\",\n\t\t() => {\n\t\t\tif (!state.running) return;\n\t\t\tvoid claimAndDrain(db, state, emitterId, \"notify\").catch((err) =>\n\t\t\t\tlogger.error(\"[emitter] claim failed\", {\n\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\t{ connectionString: listenUrl },\n\t);\n\tconst stopChanged = await listen(\n\t\t\"webhooks:changed\",\n\t\t() => {\n\t\t\tif (!state.running) return;\n\t\t\t// A resume is exactly `webhooks:changed` — its rows were already\n\t\t\t// released back to claimable (see claimAndDispatchOnce's paused-sub\n\t\t\t// branch) as soon as we noticed the pause, so a resumed webhook's\n\t\t\t// backlog drains on the SAME event that flips it active again,\n\t\t\t// instead of waiting for an unrelated future notify or the poll.\n\t\t\tvoid claimAndDrain(db, state, emitterId, \"changed\").catch((err) =>\n\t\t\t\tlogger.error(\"[emitter] claim failed\", {\n\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\t{ connectionString: listenUrl },\n\t);\n\t// Names both channels + the exact host/db LISTENed on (no credentials) so\n\t// a split-DB misconfiguration — the wake never reaching this process — is\n\t// visible in `docker logs` at boot, not only inferred from a delivery\n\t// latency graph later.\n\tlogger.info(\"[emitter] wake listeners connected\", {\n\t\tchannels: [\"webhooks:new_outbox\", \"webhooks:changed\"],\n\t\tdb: describeDbUrl(listenUrl),\n\t});\n\n\t// Poll every pollIntervalMs as a safety net for missed notifications +\n\t// backoff wakeups (rows whose next_attempt_at has passed).\n\tconst poll = setInterval(() => {\n\t\tif (!state.running) return;\n\t\tvoid claimAndDrain(db, state, emitterId, \"poll\").catch((err) =>\n\t\t\tlogger.error(\"[emitter] poll claim failed\", {\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t}),\n\t\t);\n\t}, pollIntervalMs);\n\n\t// Kick once on startup so any rows that arrived before we started drain.\n\tvoid claimAndDrain(db, state, emitterId, \"startup\");\n\n\t// Retention sweep — hourly by default.\n\tconst retention = setInterval(() => {\n\t\tif (!state.running) return;\n\t\tvoid runRetention(db).catch((err) =>\n\t\t\tlogger.error(\"[emitter] retention failed\", {\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t}),\n\t\t);\n\t}, retentionIntervalMs);\n\n\t// Receiver TLS expiry probe: Bun's fetch can't read peer certificates.\n\tconst receiverCerts = setInterval(() => {\n\t\tif (!state.running) return;\n\t\tvoid refreshReceiverCerts(db).catch((err) =>\n\t\t\tlogger.error(\"[emitter] receiver cert refresh failed\", {\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t}),\n\t\t);\n\t}, RECEIVER_CERT_INTERVAL_MS);\n\n\treturn async () => {\n\t\t// No new claims start (`runClaimLoop`'s own check) and no new\n\t\t// dispatches start (`pumpSub`'s own check) from this point on — the\n\t\t// two sets we're about to await can only shrink from here.\n\t\tstate.running = false;\n\t\tclearInterval(poll);\n\t\tclearInterval(retention);\n\t\tclearInterval(receiverCerts);\n\t\tawait stopNew();\n\t\tawait stopChanged();\n\n\t\tconst pendingRuns = new Set(state.inFlightRuns);\n\t\tconst drainTarget = pendingRuns.size;\n\t\t// `runOne` never rejects (it catches into `settleFailed`), but a claim\n\t\t// pass could — swallow that here rather than let it crash shutdown; the\n\t\t// call site that kicked off the claim already logs its own errors.\n\t\tconst claimSettled = (state.currentClaim ?? Promise.resolve()).catch(\n\t\t\t() => {},\n\t\t);\n\t\tconst waitAll = Promise.all([claimSettled, ...pendingRuns]);\n\t\t// A dispatch can't legitimately run longer than the webhook timeout\n\t\t// ceiling — bound the wait so a hung receiver can't hold up shutdown\n\t\t// forever. Rows still claimed/locked at the deadline keep their lock\n\t\t// and are re-claimed by the next emitter after LOCK_WINDOW_MS.\n\t\tconst deadlineMs =\n\t\t\topts?.stopDrainDeadlineMs ?? MAX_WEBHOOK_TIMEOUT_MS + 5_000;\n\t\tlet timedOut = false;\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\tconst timeout = new Promise<void>((resolve) => {\n\t\t\ttimer = setTimeout(() => {\n\t\t\t\ttimedOut = true;\n\t\t\t\tresolve();\n\t\t\t}, deadlineMs);\n\t\t});\n\t\tawait Promise.race([waitAll, timeout]);\n\t\tclearTimeout(timer);\n\n\t\tconst abandoned = timedOut ? state.inFlightRuns.size : 0;\n\t\tconst drained = drainTarget - abandoned;\n\t\tlogger.info(\"[emitter] stopped\", {\n\t\t\tid: emitterId,\n\t\t\tevent: \"emitter_stopped\",\n\t\t\tdrained,\n\t\t\tabandoned,\n\t\t});\n\t};\n}\n",
5
+ "import { randomUUID } from \"node:crypto\";\nimport { lookup as dnsLookup } from \"node:dns/promises\";\nimport {\n\ttype Database,\n\ttype Webhook,\n\ttype WebhookOutbox,\n\tdescribeDbUrl,\n\tgetTargetDb,\n} from \"@secondlayer/shared/db\";\nimport { finalizeReplays } from \"@secondlayer/shared/db/queries/webhook-replays\";\nimport { getWebhookSigningSecret } from \"@secondlayer/shared/db/queries/webhooks\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport { listen, targetListenerUrl } from \"@secondlayer/shared/queue/listener\";\nimport {\n\ttype WebhookTestResult,\n\twebhookTimeoutMsCeiling,\n} from \"@secondlayer/shared/schemas/webhooks\";\nimport { type Kysely, sql } from \"kysely\";\nimport { buildForFormat } from \"./formats/index.ts\";\nimport { recordDelivery } from \"./meter-socket.ts\";\nimport { refreshReceiverCerts } from \"./receiver-cert.ts\";\n\n/**\n * Webhook emitter — drains `webhook_outbox` and POSTs deliveries.\n *\n * Hot path: LISTEN on `webhooks:new_outbox` and `webhooks:changed`.\n * On notify, claim a batch with `FOR UPDATE SKIP LOCKED LIMIT 50`, dispatch\n * each row via HTTP, write a `webhook_deliveries` attempt row, then\n * either mark `status='delivered'` or schedule the next attempt.\n *\n * Backoff schedule (attempt → wait):\n * 0 → 30s, 1 → 2m, 2 → 10m, 3 → 1h, 4 → 6h, 5 → 24h, 6 → 72h.\n * After `max_retries` (default 7) attempts → `status='dead'`.\n *\n * Per-sub circuit breaker: 20 consecutive failures → sub flipped to\n * `paused` with `circuit_opened_at=NOW()`. Manual /resume drains backlog.\n *\n * Per-sub concurrency cap: in-memory semaphore, default 4 in-flight HTTP\n * requests per webhook. Sprint-4 adds SSRF allowlist.\n */\n\nconst BATCH_SIZE = 50;\nconst LIVE_SHARE = 0.9; // 90% of batch to non-replay, 10% to replay\nconst BACKOFF_SECONDS = [30, 120, 600, 3600, 21600, 86400, 259200];\nconst CIRCUIT_THRESHOLD = 20;\n/**\n * When a batch is claimed the outbox row's `next_attempt_at` is pushed\n * `LOCK_WINDOW_MS` into the future. Any crash between claim + settle\n * leaves the row re-claimable after this window expires — the SSOT for\n * double-dispatch prevention.\n *\n * Must exceed the maximum possible in-flight delivery time so a slow-but-alive\n * receiver's row is never re-claimed mid-delivery (duplicate dispatch). Derived\n * from the configurable timeout ceiling (`WEBHOOK_TIMEOUT_MS_CEILING`, default\n * 300_000ms — see `webhookTimeoutMsCeiling` in shared/schemas/webhooks.ts) so a\n * raised ceiling can never create a delivery window shorter than a webhook's\n * own timeout.\n */\nexport const MAX_WEBHOOK_TIMEOUT_MS: number = webhookTimeoutMsCeiling();\nexport const LOCK_WINDOW_MS: number = MAX_WEBHOOK_TIMEOUT_MS + 60_000; // ceiling + settle margin\n\n/** A sub's persistent delivery queue + in-flight counter. Lives for as long\n * as the sub has (or recently had) work — see `enqueueForSub`/`pumpSub`.\n * `sub` is refreshed on every enqueue so a status/concurrency change (a\n * pause, a resume, a config edit) is picked up by the next batch of rows\n * without waiting for anything to expire. */\ninterface SubQueue {\n\tsub: Webhook;\n\tqueue: WebhookOutbox[];\n\tinFlight: number;\n}\n\ninterface RunningState {\n\trunning: boolean;\n\t/** Per-webhook queue + concurrency counter — see `SubQueue`. Replaces a\n\t * bare in-flight counter so dispatch can be decoupled from the claim\n\t * transaction (see `claimAndDispatchOnce`): claiming a batch no longer\n\t * waits for a sub's HTTP calls to finish before the NEXT claim can run,\n\t * it just hands rows to that sub's queue and returns. */\n\tsubQueues: Map<string, SubQueue>;\n\tclaimInFlight: boolean;\n\t/** Set when a wake (NOTIFY) arrives while a claim cycle is already\n\t * running. The in-flight cycle checks this before releasing the lock —\n\t * see `claimAndDrain`'s \"drain-loop\" pass — so rows that land mid-drain\n\t * aren't stranded until an unrelated future wake or the safety poll. */\n\tclaimPending: boolean;\n\t/** The promise of whichever `claimAndDrain` call currently owns\n\t * `claimInFlight` (assigned by that call itself, before its first\n\t * `await`, so there is no race with a concurrent caller that just sets\n\t * `claimPending` and returns). `stopEmitter`'s clean-stop path awaits\n\t * this so shutdown doesn't race a claim pass that's mid-dispatch. */\n\tcurrentClaim: Promise<number> | null;\n\t/** Every `runOne` promise currently dispatching, added by `pumpSub` at\n\t * start and removed on settle. `stopEmitter` awaits this set (bounded)\n\t * so it never reports \"stopped\" while a delivery is still mid-flight. */\n\tinFlightRuns: Set<Promise<void>>;\n}\n\nfunction nextDelaySeconds(attempt: number): number {\n\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\treturn BACKOFF_SECONDS[Math.min(attempt, BACKOFF_SECONDS.length - 1)]!;\n}\n\n// ── SSRF guard ────────────────────────────────────────────────────────\n// Block deliveries to private/loopback/link-local ranges unless\n// SECONDLAYER_ALLOW_PRIVATE_EGRESS=true (self-host + local-dev opt-in).\n\nconst PRIVATE_V4_PATTERNS = [\n\t/^127\\./, // loopback\n\t/^10\\./, // private class A\n\t/^172\\.(1[6-9]|2\\d|3[01])\\./, // private class B\n\t/^192\\.168\\./, // private class C\n\t/^169\\.254\\./, // link-local\n\t/^0\\./, // \"this\" network\n\t/^100\\.(6[4-9]|[7-9]\\d|1[01]\\d|12[0-7])\\./, // CGNAT 100.64/10\n\t/^198\\.(1[89])\\./, // benchmarking 198.18.0.0/15\n\t/^(22[4-9]|23[0-9])\\./, // multicast 224.0.0.0/4\n\t/^(24[0-9]|25[0-5])\\./, // reserved 240.0.0.0/4 (incl. 255.255.255.255 broadcast)\n];\n\n/**\n * Classify a raw IP address literal (v4 or v6, no brackets, already lowercased\n * or not) as private/loopback/link-local/reserved. Covers v4 private ranges +\n * link-local (incl. `169.254.169.254`), `0.0.0.0`, benchmarking\n * (`198.18.0.0/15`), multicast (`224.0.0.0/4`), reserved/broadcast\n * (`240.0.0.0/4`, incl. `255.255.255.255`), IPv6 loopback (`::1`), unspecified\n * (`::`), unique-local (`fc00::/7`), link-local (`fe80::/10`), IPv6 multicast\n * (`ff00::/8`), IPv4-mapped IPv6 (`::ffff:127.0.0.1`, `::ffff:7f00:0001`), and\n * NAT64 (`64:ff9b::/96`, embedded v4 classified the same as IPv4-mapped).\n *\n * Shared by `isPrivateEgress` (literal-hostname fast-fail) and the resolved-\n * DNS-address check in `checkEgressAllowed` (rebinding mitigation).\n */\nfunction isPrivateIp(address: string): boolean {\n\tconst host = address.toLowerCase();\n\n\tif (host === \"0.0.0.0\") return true;\n\tif (host === \"::\" || host === \"::1\") return true;\n\t// Unique-local (fc00::/7) + link-local (fe80::/10) + multicast (ff00::/8)\n\tif (/^f[cd][0-9a-f]{2}:/.test(host)) return true;\n\tif (/^fe[89ab][0-9a-f]:/.test(host)) return true;\n\tif (/^ff[0-9a-f]{2}:/.test(host)) return true;\n\n\t// IPv4-mapped IPv6 — `::ffff:127.0.0.1` or `::ffff:7f00:0001`\n\tconst mapped = host.match(/^::ffff:(.+)$/);\n\tif (mapped) {\n\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\tconst inner = mapped[1]!;\n\t\t// Dotted form: rerun v4 checks.\n\t\tif (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(inner)) {\n\t\t\tfor (const p of PRIVATE_V4_PATTERNS) if (p.test(inner)) return true;\n\t\t}\n\t\t// Hex form: 7f00:0001 → 127.0.0.1\n\t\tconst hex = inner.match(/^([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);\n\t\tif (hex) {\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\t\tconst a = Number.parseInt(hex[1]!, 16);\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\t\tconst b = Number.parseInt(hex[2]!, 16);\n\t\t\tconst dotted = `${(a >> 8) & 0xff}.${a & 0xff}.${(b >> 8) & 0xff}.${b & 0xff}`;\n\t\t\tfor (const p of PRIVATE_V4_PATTERNS) if (p.test(dotted)) return true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t// NAT64 (`64:ff9b::/96`) embeds an IPv4 address in the low 32 bits —\n\t// classify it exactly like the IPv4-mapped case above (dotted or hex).\n\tconst nat64 = host.match(/^64:ff9b::(.+)$/);\n\tif (nat64) {\n\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\tconst inner = nat64[1]!;\n\t\tif (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(inner)) {\n\t\t\tfor (const p of PRIVATE_V4_PATTERNS) if (p.test(inner)) return true;\n\t\t}\n\t\tconst hex = inner.match(/^([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);\n\t\tif (hex) {\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\t\tconst a = Number.parseInt(hex[1]!, 16);\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\t\tconst b = Number.parseInt(hex[2]!, 16);\n\t\t\tconst dotted = `${(a >> 8) & 0xff}.${a & 0xff}.${(b >> 8) & 0xff}.${b & 0xff}`;\n\t\t\tfor (const p of PRIVATE_V4_PATTERNS) if (p.test(dotted)) return true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tfor (const p of PRIVATE_V4_PATTERNS) {\n\t\tif (p.test(host)) return true;\n\t}\n\treturn false;\n}\n\n/**\n * Reject hostnames spelled as private IPs (cheap, synchronous, no I/O — a\n * fast-fail pre-filter). DNS-level rebinding (hostname that *resolves* to a\n * private IP at egress time) is NOT caught here — see `checkEgressAllowed`,\n * which resolves DNS and validates every returned address.\n */\nfunction isPrivateEgress(url: string): boolean {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(url);\n\t} catch {\n\t\treturn true; // malformed URL: reject\n\t}\n\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n\t\treturn true;\n\t}\n\n\t// Strip brackets from IPv6 literals.\n\tconst raw = parsed.hostname.toLowerCase();\n\tconst host =\n\t\traw.startsWith(\"[\") && raw.endsWith(\"]\") ? raw.slice(1, -1) : raw;\n\n\tif (host === \"localhost\") return true;\n\treturn isPrivateIp(host);\n}\n\n/** How often the emitter re-probes receivers' TLS certificates. */\nconst RECEIVER_CERT_INTERVAL_MS = 30 * 60_000;\n\nexport function allowPrivateEgress(): boolean {\n\treturn process.env.SECONDLAYER_ALLOW_PRIVATE_EGRESS === \"true\";\n}\n\ninterface ResolvedAddress {\n\taddress: string;\n\tfamily: number;\n}\n\ntype DnsLookupFn = (hostname: string) => Promise<ResolvedAddress[]>;\n\nasync function defaultDnsLookup(hostname: string): Promise<ResolvedAddress[]> {\n\treturn dnsLookup(hostname, { all: true });\n}\n\nlet dnsLookupImpl: DnsLookupFn = defaultDnsLookup;\n\n/**\n * Test-only seam: inject a fake DNS resolver so tests can simulate a hostname\n * resolving to a private/metadata IP without depending on real DNS or\n * network access. Pass `null` to restore the real `dns.lookup`-backed\n * resolver. Production code never calls this — only `ssrf.test.ts` does.\n */\nexport function __setDnsLookupForTest(fn: DnsLookupFn | null): void {\n\tdnsLookupImpl = fn ?? defaultDnsLookup;\n}\n\nconst ALLOW_HINT = \"(set SECONDLAYER_ALLOW_PRIVATE_EGRESS=true to allow)\";\n\n/**\n * Full egress check: literal fast-fail, then resolve DNS and reject if *any*\n * returned address (not just the first) is private/loopback/link-local —\n * a single private answer among several is enough for an attacker to abuse.\n *\n * Residual TOCTOU: this resolves-and-validates *immediately before* `fetch()`\n * but does not pin the actual connection to the validated address. True\n * pinning (resolve once, connect to that literal IP, keep the original `Host`\n * header/SNI) was attempted per plan f053 via a custom undici `Agent` with\n * `connect.lookup` passed as `fetch()`'s `dispatcher` — the standard Node\n * ecosystem pattern for this. Empirically, under Bun 1.3.10, that hook was\n * silently never invoked (confirmed with a throwaway smoke test hitting a\n * real local HTTP server: `lookupCalled` stayed `false` and the connection\n * failed even though the dispatcher was passed) — Bun's `fetch()` does not\n * implement undici's `connect.lookup` dispatcher hook, whether reached via\n * the global `fetch` or `import { fetch } from \"undici\"` (Bun overrides\n * \"undici\"'s `fetch` export with its own native implementation regardless of\n * an installed real `undici` package). Re-tested under Bun 1.4.2 (plan 043):\n * identical result — `lookupCalled` still stays `false` via both the global\n * `fetch` and `import { fetch } from \"undici\"`, so the gap remains unfixed at\n * this version too. So a second DNS answer between this check and `fetch()`'s\n * own resolution (true rebinding, not just a one-time private answer) could\n * in theory still slip through. This closes the practical rebinding gap\n * (attacker's hostname resolves private at delivery time) without adding a\n * dependency; a network-level egress allowlist/proxy is the recommended\n * defense-in-depth for the remaining TOCTOU sliver.\n */\nexport async function checkEgressAllowed(url: string): Promise<string | null> {\n\tif (isPrivateEgress(url)) {\n\t\treturn `refused private egress: literal address ${ALLOW_HINT}`;\n\t}\n\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(url);\n\t} catch {\n\t\treturn `refused private egress: malformed URL ${ALLOW_HINT}`;\n\t}\n\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n\t\treturn `refused private egress: unsupported protocol ${ALLOW_HINT}`;\n\t}\n\n\tconst raw = parsed.hostname.toLowerCase();\n\tconst hostname =\n\t\traw.startsWith(\"[\") && raw.endsWith(\"]\") ? raw.slice(1, -1) : raw;\n\n\tlet resolved: ResolvedAddress[];\n\ttry {\n\t\tresolved = await dnsLookupImpl(hostname);\n\t} catch (err) {\n\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\treturn `refused private egress: DNS resolution failed (${msg}) ${ALLOW_HINT}`;\n\t}\n\tif (resolved.length === 0) {\n\t\treturn `refused private egress: DNS resolution returned no addresses ${ALLOW_HINT}`;\n\t}\n\tfor (const { address } of resolved) {\n\t\tif (isPrivateIp(address)) {\n\t\t\treturn `refused private egress: hostname resolves to private address ${address} ${ALLOW_HINT}`;\n\t\t}\n\t}\n\treturn null;\n}\n\n/** The wire result of one POST attempt (no DB side effect) — shared by the\n * emitter hot path and the `deliverTestEvent` test path. */\ninterface PostResult {\n\tok: boolean;\n\tstatusCode: number | null;\n\terror: string | null;\n\tdurationMs: number;\n\tresponseBody: string | null;\n\tresponseHeaders: Record<string, string> | null;\n}\n\n/**\n * Bound on redirect hops honored while delivering a webhook. `fetch` is\n * called with `redirect: \"manual\"` so a 3xx never auto-follows — each hop's\n * target is re-validated through `checkEgressAllowed` before it is fetched\n * (see `postToWebhook`), otherwise a `Location` header pointing at a\n * private/metadata address would bypass the egress guard entirely. Counts\n * every fetch issued (the initial request plus each redirect), so this is\n * also the max number of `fetch` calls one delivery attempt can make.\n */\nexport const MAX_REDIRECT_HOPS: number = 3;\n\n/** POST a pre-built body to a webhook URL with the SSRF guard + timeout.\n * Pure transport: returns the attempt result; the caller logs the delivery row.\n * Follows redirects manually (up to `MAX_REDIRECT_HOPS`), re-running the\n * egress guard against every hop's target — the guard only protects the\n * first request otherwise, and a webhook target can redirect to a private/\n * metadata address to read back the response after f053 pinned the guard to\n * just the original URL. */\nasync function postToWebhook(\n\turl: string,\n\tbody: string,\n\theaders: Record<string, string>,\n\ttimeoutMs: number,\n): Promise<PostResult> {\n\tconst start = performance.now();\n\tlet target = url;\n\tlet statusCode: number | null = null;\n\tlet error: string | null = null;\n\tlet ok = false;\n\tlet responseBody = \"\";\n\tlet responseHeaders: Record<string, string> | null = null;\n\ttry {\n\t\tfor (let hop = 0; ; hop++) {\n\t\t\tif (!allowPrivateEgress()) {\n\t\t\t\tconst refusal = await checkEgressAllowed(target);\n\t\t\t\tif (refusal) {\n\t\t\t\t\tlogger.warn(\"[emitter] refused private egress\", {\n\t\t\t\t\t\turl: target,\n\t\t\t\t\t\treason: refusal,\n\t\t\t\t\t});\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tstatusCode: null,\n\t\t\t\t\t\terror: refusal,\n\t\t\t\t\t\tdurationMs: Math.round(performance.now() - start),\n\t\t\t\t\t\tresponseBody: null,\n\t\t\t\t\t\tresponseHeaders: null,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (hop >= MAX_REDIRECT_HOPS) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tstatusCode,\n\t\t\t\t\terror: `too many redirects (exceeded ${MAX_REDIRECT_HOPS} hops)`,\n\t\t\t\t\tdurationMs: Math.round(performance.now() - start),\n\t\t\t\t\tresponseBody: null,\n\t\t\t\t\tresponseHeaders: null,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst res = await fetch(target, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders,\n\t\t\t\tbody,\n\t\t\t\tredirect: \"manual\",\n\t\t\t\tsignal: AbortSignal.timeout(timeoutMs),\n\t\t\t});\n\t\t\tstatusCode = res.status;\n\n\t\t\tconst location = res.headers.get(\"location\");\n\t\t\tif (res.status >= 300 && res.status < 400 && location) {\n\t\t\t\ttarget = new URL(location, target).toString();\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tok = res.ok;\n\t\t\t// Collect small response preview for the delivery log (≤8KB).\n\t\t\tconst buf = await res.arrayBuffer();\n\t\t\tconst truncated = buf.byteLength > 8192 ? buf.slice(0, 8192) : buf;\n\t\t\tresponseBody = Buffer.from(truncated).toString(\"utf8\");\n\t\t\tresponseHeaders = Object.fromEntries(res.headers.entries());\n\t\t\tbreak;\n\t\t}\n\t} catch (err) {\n\t\terror = err instanceof Error ? err.message : String(err);\n\t}\n\treturn {\n\t\tok,\n\t\tstatusCode,\n\t\terror,\n\t\tdurationMs: Math.round(performance.now() - start),\n\t\tresponseBody: responseBody || null,\n\t\tresponseHeaders,\n\t};\n}\n\n/**\n * Test-only seam: exposes `postToWebhook` (otherwise module-private) so\n * redirect/egress behavior can be exercised directly against a stubbed\n * `fetch` + injected DNS lookup, without standing up the DB-backed emitter\n * loop. Production code never calls this — only tests do.\n */\nexport const __postToWebhookForTest: (\n\turl: string,\n\tbody: string,\n\theaders: Record<string, string>,\n\ttimeoutMs: number,\n) => Promise<PostResult> = postToWebhook;\n\nasync function dispatchOne(\n\tdb: Kysely<Database>,\n\toutboxRow: WebhookOutbox,\n\tsub: Webhook,\n): Promise<{\n\tok: boolean;\n\tstatusCode: number | null;\n\terror: string | null;\n\tdurationMs: number;\n}> {\n\tconst { body, headers } = buildForFormat(\n\t\toutboxRow,\n\t\tsub,\n\t\tgetWebhookSigningSecret(sub),\n\t);\n\tconst r = await postToWebhook(sub.url, body, headers, sub.timeout_ms);\n\n\tconst attempt = outboxRow.attempt + 1;\n\tawait db\n\t\t.insertInto(\"webhook_deliveries\")\n\t\t.values({\n\t\t\toutbox_id: outboxRow.id,\n\t\t\twebhook_id: outboxRow.webhook_id,\n\t\t\tattempt,\n\t\t\tstatus_code: r.statusCode,\n\t\t\tresponse_headers: r.responseHeaders,\n\t\t\tresponse_body: r.responseBody,\n\t\t\terror_message: r.error,\n\t\t\tduration_ms: r.durationMs,\n\t\t})\n\t\t.execute();\n\n\treturn {\n\t\tok: r.ok,\n\t\tstatusCode: r.statusCode,\n\t\terror: r.error,\n\t\tdurationMs: r.durationMs,\n\t};\n}\n\n/** A representative (non-persisted) outbox row for a test delivery, so\n * `buildForFormat` produces a realistic body. */\nfunction buildTestOutboxRow(sub: Webhook): WebhookOutbox {\n\tconst now = new Date();\n\treturn {\n\t\tid: randomUUID(),\n\t\twebhook_id: sub.id,\n\t\tkind: sub.kind,\n\t\tblock_height: 0,\n\t\ttx_id: null,\n\t\trow_pk: null,\n\t\tevent_type: \"chain.test.apply\",\n\t\tpayload: {\n\t\t\ttest: true,\n\t\t\tmessage: \"Secondlayer test delivery\",\n\t\t\twebhook_id: sub.id,\n\t\t\tsent_at: now.toISOString(),\n\t\t},\n\t\tdedup_key: `test:${sub.id}:${now.getTime()}`,\n\t\tattempt: 0,\n\t\tnext_attempt_at: now,\n\t\tstatus: \"pending\",\n\t\tis_replay: false,\n\t\tblock_time: null,\n\t\tdelivered_at: null,\n\t\tfailed_at: null,\n\t\tlocked_by: null,\n\t\tlocked_until: null,\n\t\tlast_error: null,\n\t\tcreated_at: now,\n\t};\n}\n\n/**\n * Build a representative webhook for `sub`'s configured format, POST it (same\n * SSRF guard + timeout + signing as a real delivery), and log a delivery row\n * with a null `outbox_id` so it appears under the webhook's deliveries\n * without being tied to a queued event. Powers `POST /:id/test`.\n */\nexport async function deliverTestEvent(\n\tdb: Kysely<Database>,\n\tsub: Webhook,\n): Promise<WebhookTestResult> {\n\tconst testRow = buildTestOutboxRow(sub);\n\tconst { body, headers } = buildForFormat(\n\t\ttestRow,\n\t\tsub,\n\t\tgetWebhookSigningSecret(sub),\n\t);\n\tconst r = await postToWebhook(sub.url, body, headers, sub.timeout_ms);\n\tconst inserted = await db\n\t\t.insertInto(\"webhook_deliveries\")\n\t\t.values({\n\t\t\toutbox_id: null,\n\t\t\twebhook_id: sub.id,\n\t\t\tattempt: 1,\n\t\t\tstatus_code: r.statusCode,\n\t\t\tresponse_headers: r.responseHeaders,\n\t\t\tresponse_body: r.responseBody,\n\t\t\terror_message: r.error,\n\t\t\tduration_ms: r.durationMs,\n\t\t})\n\t\t.returning(\"id\")\n\t\t.executeTakeFirstOrThrow();\n\treturn {\n\t\tok: r.ok,\n\t\tstatusCode: r.statusCode,\n\t\terror: r.error,\n\t\tdurationMs: r.durationMs,\n\t\tdeliveryId: inserted.id,\n\t};\n}\n\nasync function settleDelivered(\n\tdb: Kysely<Database>,\n\toutboxRow: WebhookOutbox,\n): Promise<void> {\n\tawait db.transaction().execute(async (tx) => {\n\t\tconst result = await tx\n\t\t\t.updateTable(\"webhook_outbox\")\n\t\t\t.set({\n\t\t\t\tstatus: \"delivered\",\n\t\t\t\tdelivered_at: new Date(),\n\t\t\t\tattempt: outboxRow.attempt + 1,\n\t\t\t\tlocked_by: null,\n\t\t\t\tlocked_until: null,\n\t\t\t})\n\t\t\t// Guard against a reorg that marked this row `dead` (orphaned) while\n\t\t\t// the POST was in flight — settling a delivery outcome must never\n\t\t\t// resurrect a row the reorg already decided is gone. `status='pending'`\n\t\t\t// is the only state a claimed row can settle from.\n\t\t\t.where(\"id\", \"=\", outboxRow.id)\n\t\t\t.where(\"status\", \"=\", \"pending\")\n\t\t\t.executeTakeFirst();\n\t\tif (Number(result.numUpdatedRows ?? 0) === 0) {\n\t\t\tlogger.info(\"webhook.settle.orphaned\", {\n\t\t\t\toutboxId: outboxRow.id,\n\t\t\t\twebhookId: outboxRow.webhook_id,\n\t\t\t\toutcome: \"delivered\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tawait tx\n\t\t\t.updateTable(\"webhooks\")\n\t\t\t.set({\n\t\t\t\tlast_delivery_at: new Date(),\n\t\t\t\tlast_success_at: new Date(),\n\t\t\t\tcircuit_failures: 0,\n\t\t\t\tlast_error: null,\n\t\t\t\tupdated_at: new Date(),\n\t\t\t})\n\t\t\t.where(\"id\", \"=\", outboxRow.webhook_id)\n\t\t\t.execute();\n\n\t\t// Hosted-stack event meter (plan 044, step 5): counts a real delivery,\n\t\t// never a retry (this function only runs on the successful outcome) and\n\t\t// never a test delivery (`deliverTestEvent` never calls this). A no-op\n\t\t// on self-host (WEBHOOK_METER_SOCKET unset).\n\t\trecordDelivery();\n\t});\n}\n\nasync function settleFailed(\n\tdb: Kysely<Database>,\n\toutboxRow: WebhookOutbox,\n\tsub: Webhook,\n\terrText: string,\n): Promise<void> {\n\tconst attempt = outboxRow.attempt + 1;\n\tconst isDead = attempt >= sub.max_retries;\n\tconst nextAt = isDead\n\t\t? null\n\t\t: new Date(Date.now() + nextDelaySeconds(outboxRow.attempt) * 1000);\n\n\tawait db.transaction().execute(async (tx) => {\n\t\tconst result = await tx\n\t\t\t.updateTable(\"webhook_outbox\")\n\t\t\t.set({\n\t\t\t\tattempt,\n\t\t\t\tnext_attempt_at: nextAt ?? new Date(),\n\t\t\t\tstatus: isDead ? \"dead\" : \"pending\",\n\t\t\t\tfailed_at: isDead ? new Date() : null,\n\t\t\t\tlocked_by: null,\n\t\t\t\tlocked_until: null,\n\t\t\t})\n\t\t\t// Guard against a reorg that marked this row `dead` (orphaned) while\n\t\t\t// the POST was in flight — see the matching guard in `settleDelivered`.\n\t\t\t.where(\"id\", \"=\", outboxRow.id)\n\t\t\t.where(\"status\", \"=\", \"pending\")\n\t\t\t.executeTakeFirst();\n\t\tif (Number(result.numUpdatedRows ?? 0) === 0) {\n\t\t\tlogger.info(\"webhook.settle.orphaned\", {\n\t\t\t\toutboxId: outboxRow.id,\n\t\t\t\twebhookId: outboxRow.webhook_id,\n\t\t\t\toutcome: \"failed\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Atomic increment — concurrent failures must not clobber each other.\n\t\t// `RETURNING circuit_failures` gives us the post-increment value to\n\t\t// decide whether this failure tripped the circuit.\n\t\tconst incResult = await sql<{ circuit_failures: number }>`\n\t\t\tUPDATE webhooks\n\t\t\tSET circuit_failures = circuit_failures + 1,\n\t\t\t\tlast_delivery_at = NOW(),\n\t\t\t\tlast_error = ${errText.slice(0, 500)},\n\t\t\t\tupdated_at = NOW()\n\t\t\tWHERE id = ${sub.id}\n\t\t\tRETURNING circuit_failures\n\t\t`.execute(tx);\n\t\tconst newFailures =\n\t\t\tincResult.rows[0]?.circuit_failures ?? sub.circuit_failures + 1;\n\t\tconst shouldTripCircuit = newFailures >= CIRCUIT_THRESHOLD;\n\n\t\tif (shouldTripCircuit) {\n\t\t\t// Transition to paused only on the first failure that crossed\n\t\t\t// the threshold — additional failures in-flight harmlessly\n\t\t\t// re-set the same fields.\n\t\t\tawait tx\n\t\t\t\t.updateTable(\"webhooks\")\n\t\t\t\t.set({\n\t\t\t\t\tstatus: \"paused\",\n\t\t\t\t\tcircuit_opened_at: new Date(),\n\t\t\t\t\tupdated_at: new Date(),\n\t\t\t\t})\n\t\t\t\t.where(\"id\", \"=\", sub.id)\n\t\t\t\t.execute();\n\t\t\tlogger.warn(\n\t\t\t\t\"Webhook circuit tripped — paused after consecutive failures\",\n\t\t\t\t{\n\t\t\t\t\twebhook: sub.name,\n\t\t\t\t\tfailures: newFailures,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t});\n}\n\n/** What woke this claim cycle — purely for the diagnostic log below; the\n * claim/dispatch logic itself doesn't branch on it. `\"drain-loop\"` marks a\n * pass this function re-ran on itself (see `claimAndDrain`) because a wake\n * arrived (or a per-lane batch cap was hit) while the previous pass was\n * still claiming. `\"changed\"` is a resume (or any webhook edit) — see the\n * `webhooks:changed` listener. */\ntype ClaimTrigger = \"notify\" | \"poll\" | \"startup\" | \"changed\" | \"drain-loop\";\n\n/**\n * The regression this closes: a NOTIFY that arrives while a claim cycle is\n * ALREADY running used to be dropped on the floor (the `claimInFlight` guard\n * below just returned 0), and nothing re-checked once that cycle finished.\n * Rows inserted mid-cycle — a normal burst of ~6 chain-webhook matches per\n * block — sat `pending` until an UNRELATED future wake happened to fire, or\n * the 2-minute safety poll.\n *\n * The holder of `claimInFlight` now keeps looping (`claimPending`, set by any\n * caller that finds the lock held) until a pass claims nothing NEW and no one\n * asked for a recheck while it ran — so a burst drains fully off one wake\n * instead of needing one wake per claim-sized chunk. Critically, this lock\n * wraps ONLY `claimAndDispatchOnce`'s DB claim query, never dispatch (see its\n * doc) — a slow or hanging receiver must never hold up the next claim.\n */\nasync function claimAndDrain(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\temitterId: string,\n\ttrigger: ClaimTrigger,\n): Promise<number> {\n\tif (state.claimInFlight) {\n\t\tstate.claimPending = true;\n\t\treturn 0;\n\t}\n\tstate.claimInFlight = true;\n\t// Assigned synchronously (before any `await` in `runClaimLoop` yields back\n\t// to the event loop) so `stopEmitter` can always await the pass that\n\t// actually owns the lock, never a concurrent caller's already-resolved\n\t// `claimPending` short-circuit above.\n\tconst drainPromise = runClaimLoop(db, state, emitterId, trigger);\n\tstate.currentClaim = drainPromise;\n\ttry {\n\t\treturn await drainPromise;\n\t} finally {\n\t\tif (state.currentClaim === drainPromise) state.currentClaim = null;\n\t}\n}\n\nasync function runClaimLoop(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\temitterId: string,\n\ttrigger: ClaimTrigger,\n): Promise<number> {\n\tlet totalClaimed = 0;\n\ttry {\n\t\tlet currentTrigger = trigger;\n\t\tfor (;;) {\n\t\t\t// Stop requested: claim no new rows. Anything already claimed by an\n\t\t\t// in-flight `claimAndDispatchOnce` call still gets handed to its\n\t\t\t// sub's queue, but `pumpSub`'s own `state.running` check means it\n\t\t\t// won't dispatch — those rows just keep their lock until the next\n\t\t\t// emitter re-claims them after LOCK_WINDOW_MS.\n\t\t\tif (!state.running) break;\n\t\t\tstate.claimPending = false;\n\t\t\tconst result = await claimAndDispatchOnce(\n\t\t\t\tdb,\n\t\t\t\tstate,\n\t\t\t\temitterId,\n\t\t\t\tcurrentTrigger,\n\t\t\t);\n\t\t\ttotalClaimed += result.claimed;\n\t\t\t// Keep going while either: a wake landed mid-pass (claimPending —\n\t\t\t// set by the guard above, from another caller), or either lane\n\t\t\t// (live/replay) came back full, meaning more may be waiting behind\n\t\t\t// it. Comparing against the LANE limits, not the combined batch\n\t\t\t// size, matters: live traffic alone is capped at `liveLimit` (90%\n\t\t\t// of BATCH_SIZE) and would never reach the full BATCH_SIZE on its\n\t\t\t// own, so that comparison never re-looped on a live-only backlog.\n\t\t\tif (!state.claimPending && !result.mayHaveMore) break;\n\t\t\tcurrentTrigger = \"drain-loop\";\n\t\t}\n\t} finally {\n\t\tstate.claimInFlight = false;\n\t}\n\treturn totalClaimed;\n}\n\ninterface ClaimResult {\n\tclaimed: number;\n\tdispatched: number;\n\treleased: number;\n\tmayHaveMore: boolean;\n}\n\n/**\n * One claim pass: SELECT a batch, mark it locked, then hand each sub's slice\n * to its persistent queue and return — WITHOUT waiting for any of it to\n * dispatch. Caller (`claimAndDrain`) owns the re-loop and the `claimInFlight`\n * lock, which now covers only this function's DB work.\n *\n * This decoupling is the fix for the emitter-wide latency regression: the\n * previous version awaited `Promise.all(subIds.map(drainForSub))` — every\n * sub's FULL dispatch — before returning, so the slowest receiver in a batch\n * (a hung connection, a multi-second response) held the process-wide claim\n * lock for as long as IT took, starving every other sub's claims (including\n * a fast sub's own fresh rows) for that whole time. Claiming is now a single\n * short transaction; delivery happens on each sub's own independent\n * queue/semaphore (`enqueueForSub`/`pumpSub`), so one sub's pace never\n * gates another's.\n *\n * Also fixes the \"stuck rows\" bug: a row claimed for a sub that turns out to\n * be `paused` (status read fresh here, after the claim) is released\n * IMMEDIATELY — `next_attempt_at` reset to now, lock cleared — instead of\n * being silently abandoned with its lock held for the full `LOCK_WINDOW_MS`.\n * The old code's `if (sub.status !== \"active\") return;` left the row\n * claimed-but-untouched: locked, `next_attempt_at` pushed far into the\n * future, never dispatched, never settled — a resumed webhook's backlog\n * then only drained once each row's stale lock happened to expire.\n */\nasync function claimAndDispatchOnce(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\temitterId: string,\n\ttrigger: ClaimTrigger,\n): Promise<ClaimResult> {\n\t// FOR UPDATE SKIP LOCKED — multiple emitters split the batch.\n\t// 90/10 live vs replay so a big replay doesn't starve live emits.\n\tconst liveLimit = Math.max(1, Math.round(BATCH_SIZE * LIVE_SHARE));\n\tconst replayLimit = BATCH_SIZE - liveLimit;\n\tconst { combined, liveCount, replayCount } = await db\n\t\t.transaction()\n\t\t.execute(async (tx) => {\n\t\t\tconst live = await sql<WebhookOutbox>`\n\t\t\t\t\tSELECT * FROM webhook_outbox\n\t\t\t\t\tWHERE status = 'pending'\n\t\t\t\t\t\tAND next_attempt_at <= NOW()\n\t\t\t\t\t\tAND is_replay = FALSE\n\t\t\t\t\tORDER BY next_attempt_at ASC\n\t\t\t\t\tFOR UPDATE SKIP LOCKED\n\t\t\t\t\tLIMIT ${sql.lit(liveLimit)}\n\t\t\t\t`.execute(tx);\n\t\t\tconst replay = await sql<WebhookOutbox>`\n\t\t\t\t\tSELECT * FROM webhook_outbox\n\t\t\t\t\tWHERE status = 'pending'\n\t\t\t\t\t\tAND next_attempt_at <= NOW()\n\t\t\t\t\t\tAND is_replay = TRUE\n\t\t\t\t\tORDER BY next_attempt_at ASC\n\t\t\t\t\tFOR UPDATE SKIP LOCKED\n\t\t\t\t\tLIMIT ${sql.lit(replayLimit)}\n\t\t\t\t`.execute(tx);\n\n\t\t\tconst rows = [...live.rows, ...replay.rows];\n\t\t\tif (rows.length === 0) {\n\t\t\t\treturn { combined: rows, liveCount: 0, replayCount: 0 };\n\t\t\t}\n\n\t\t\t// Push `next_attempt_at` forward by the lock window. This is\n\t\t\t// the only defense against double-dispatch if the emitter\n\t\t\t// process crashes mid-HTTP-call: the row won't be re-claimable\n\t\t\t// until `LOCK_WINDOW_MS` elapses, giving us a stale-lock\n\t\t\t// recovery window. `settleDelivered`/`settleFailed` overrides\n\t\t\t// this on the success/failure path (and the paused-sub release\n\t\t\t// below overrides it on the \"never got dispatched\" path).\n\t\t\tconst now = new Date();\n\t\t\tconst lockUntil = new Date(now.getTime() + LOCK_WINDOW_MS);\n\t\t\tawait tx\n\t\t\t\t.updateTable(\"webhook_outbox\")\n\t\t\t\t.set({\n\t\t\t\t\tlocked_by: emitterId,\n\t\t\t\t\tlocked_until: lockUntil,\n\t\t\t\t\tnext_attempt_at: lockUntil,\n\t\t\t\t})\n\t\t\t\t.where(\n\t\t\t\t\t\"id\",\n\t\t\t\t\t\"in\",\n\t\t\t\t\trows.map((r) => r.id),\n\t\t\t\t)\n\t\t\t\t.execute();\n\t\t\treturn {\n\t\t\t\tcombined: rows,\n\t\t\t\tliveCount: live.rows.length,\n\t\t\t\treplayCount: replay.rows.length,\n\t\t\t};\n\t\t});\n\n\tif (combined.length === 0) {\n\t\treturn { claimed: 0, dispatched: 0, released: 0, mayHaveMore: false };\n\t}\n\n\tconst bySubId = new Map<string, WebhookOutbox[]>();\n\tfor (const row of combined) {\n\t\tconst arr = bySubId.get(row.webhook_id);\n\t\tif (arr) arr.push(row);\n\t\telse bySubId.set(row.webhook_id, [row]);\n\t}\n\n\tconst subIds = Array.from(bySubId.keys());\n\tconst subs = await db\n\t\t.selectFrom(\"webhooks\")\n\t\t.selectAll()\n\t\t.where(\"id\", \"in\", subIds)\n\t\t.execute();\n\tconst subById = new Map(subs.map((s) => [s.id, s]));\n\n\tlet dispatched = 0;\n\tlet released = 0;\n\tconst releasedIds: string[] = [];\n\tfor (const subId of subIds) {\n\t\tconst sub = subById.get(subId);\n\t\t// biome-ignore lint/style/noNonNullAssertion: key came from bySubId itself\n\t\tconst rows = bySubId.get(subId)!;\n\t\tif (!sub || sub.status !== \"active\") {\n\t\t\treleased += rows.length;\n\t\t\treleasedIds.push(...rows.map((r) => r.id));\n\t\t\tcontinue;\n\t\t}\n\t\tdispatched += rows.length;\n\t\tenqueueForSub(db, state, sub, rows);\n\t}\n\n\tif (releasedIds.length > 0) {\n\t\t// Claimable again immediately: a webhook that's already resumed by the\n\t\t// time we notice the release loses nothing waiting for LOCK_WINDOW_MS\n\t\t// (up to several minutes) to expire on its own.\n\t\tawait db\n\t\t\t.updateTable(\"webhook_outbox\")\n\t\t\t.set({ next_attempt_at: new Date(), locked_by: null, locked_until: null })\n\t\t\t.where(\"id\", \"in\", releasedIds)\n\t\t\t.execute();\n\t}\n\n\t// One line per claim pass: what woke it, how much it found, how it split\n\t// between dispatched-now and released-back (paused), how stale the oldest\n\t// row was, and how loaded the in-flight pool already was — everything\n\t// needed to tell \"briefly busy\" apart from \"actually stuck\" without\n\t// reproducing it live. `in_flight`/`concurrency` sum across only the subs\n\t// THIS pass touched (a quiet sub's unrelated cap doesn't dilute the\n\t// reading).\n\tconst oldestCreatedAtMs = Math.min(\n\t\t...combined.map((r) => new Date(r.created_at).getTime()),\n\t);\n\tconst inFlight = subIds.reduce(\n\t\t(sum, id) => sum + (state.subQueues.get(id)?.inFlight ?? 0),\n\t\t0,\n\t);\n\tconst concurrency = subIds.reduce(\n\t\t(sum, id) => sum + (subById.get(id)?.concurrency || 4),\n\t\t0,\n\t);\n\tlogger.info(\"emitter claim cycle\", {\n\t\tevent: \"emitter_claim\",\n\t\ttrigger,\n\t\tclaimed: combined.length,\n\t\tdispatched,\n\t\treleased,\n\t\toldest_created_at_age_ms: Date.now() - oldestCreatedAtMs,\n\t\tin_flight: inFlight,\n\t\tconcurrency,\n\t});\n\n\treturn {\n\t\tclaimed: combined.length,\n\t\tdispatched,\n\t\treleased,\n\t\tmayHaveMore: liveCount >= liveLimit || replayCount >= replayLimit,\n\t};\n}\n\n/**\n * Hand `rows` to `sub`'s persistent queue and try to start dispatching\n * immediately. Decoupled from the claim transaction on purpose (see\n * `claimAndDispatchOnce`'s doc) — a slow or hanging sub's in-flight HTTP\n * calls must never hold up the next claim, for this sub or any other.\n *\n * `sub` is refreshed here on every call (not just on first creation) so a\n * status/concurrency change since the last batch — most importantly a\n * pause — is picked up by `pumpSub` without waiting for anything to expire.\n */\nfunction enqueueForSub(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\tsub: Webhook,\n\trows: WebhookOutbox[],\n): void {\n\tlet sq = state.subQueues.get(sub.id);\n\tif (!sq) {\n\t\tsq = { sub, queue: [], inFlight: 0 };\n\t\tstate.subQueues.set(sub.id, sq);\n\t} else {\n\t\tsq.sub = sub;\n\t}\n\tsq.queue.push(...rows);\n\tpumpSub(db, state, sub.id);\n}\n\n/**\n * Start as many workers as the sub's remaining concurrency allows, pulling\n * from its queue. Reentrant-safe without an explicit lock: every branch here\n * is synchronous (the only `await` lives in `runOne`, called but not\n * awaited), so JS's single-threaded execution means two calls — one from\n * `enqueueForSub`, one from a just-finished worker's `finally` — can never\n * interleave mid-loop; each runs to completion before the other starts.\n */\nfunction pumpSub(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\tsubId: string,\n): void {\n\tconst sq = state.subQueues.get(subId);\n\tif (!sq) return;\n\tconst cap = sq.sub.concurrency || 4;\n\twhile (\n\t\tstate.running &&\n\t\tsq.sub.status === \"active\" &&\n\t\tsq.inFlight < cap &&\n\t\tsq.queue.length > 0\n\t) {\n\t\tconst row = sq.queue.shift();\n\t\tif (!row) break;\n\t\tsq.inFlight++;\n\t\tconst runPromise = runOne(db, state, sq, row);\n\t\tstate.inFlightRuns.add(runPromise);\n\t\tvoid runPromise.finally(() => {\n\t\t\tstate.inFlightRuns.delete(runPromise);\n\t\t});\n\t}\n}\n\n/** Dispatch one claimed row end to end (POST, settle), then release its\n * in-flight slot and try to pull more work for the same sub. */\nasync function runOne(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\tsq: SubQueue,\n\trow: WebhookOutbox,\n): Promise<void> {\n\ttry {\n\t\tconst result = await dispatchOne(db, row, sq.sub);\n\t\tif (result.ok) {\n\t\t\tawait settleDelivered(db, row);\n\t\t} else {\n\t\t\tconst err = result.error ?? `HTTP ${result.statusCode ?? \"?\"}`;\n\t\t\tawait settleFailed(db, row, sq.sub, err);\n\t\t}\n\t} catch (err) {\n\t\tlogger.error(\"Emitter dispatch crashed\", {\n\t\t\toutboxId: row.id,\n\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t});\n\t\tawait settleFailed(\n\t\t\tdb,\n\t\t\trow,\n\t\t\tsq.sub,\n\t\t\terr instanceof Error ? err.message : String(err),\n\t\t);\n\t} finally {\n\t\tsq.inFlight--;\n\t\tpumpSub(db, state, sq.sub.id);\n\t}\n}\n\nexport interface StartEmitterOptions {\n\t/** Interval for the background poll (ms). Defaults to 2 minutes. */\n\tpollIntervalMs?: number;\n\t/** Retention sweep interval (ms). Defaults to 1 hour. */\n\tretentionIntervalMs?: number;\n\t/** Bound for the returned stop function's clean-shutdown drain — how long\n\t * it waits for the current claim pass + in-flight dispatches before\n\t * giving up and reporting them abandoned. Defaults to\n\t * `MAX_WEBHOOK_TIMEOUT_MS + 5_000` (a dispatch can't legitimately run\n\t * longer than the webhook timeout ceiling). `MAX_WEBHOOK_TIMEOUT_MS` is\n\t * fixed at module load from `WEBHOOK_TIMEOUT_MS_CEILING`, so this exists\n\t * mainly for tests that need a short bound without a 5-minute wait. */\n\tstopDrainDeadlineMs?: number;\n}\n\nasync function runRetention(db: Kysely<Database>): Promise<void> {\n\t// Replays first: their final counts come from outbox rows the deletes below\n\t// remove. Then delivered outbox >7d, deliveries >30d, dead outbox >90d,\n\t// finished replay records >90d.\n\tawait finalizeReplays(db);\n\tawait sql`\n\t\tDELETE FROM webhook_outbox\n\t\tWHERE status = 'delivered' AND delivered_at < NOW() - interval '7 days'\n\t`.execute(db);\n\tawait sql`\n\t\tDELETE FROM webhook_deliveries\n\t\tWHERE dispatched_at < NOW() - interval '30 days'\n\t`.execute(db);\n\t// The hourly counts outlive the attempts they summarise (30 d) by five\n\t// days; deleting deliveries above never decrements them.\n\tawait sql`\n\t\tDELETE FROM webhook_delivery_hours\n\t\tWHERE hour < NOW() - interval '35 days'\n\t`.execute(db);\n\tawait sql`\n\t\tDELETE FROM webhook_outbox\n\t\tWHERE status = 'dead' AND failed_at < NOW() - interval '90 days'\n\t`.execute(db);\n\tawait sql`\n\t\tDELETE FROM webhook_replays\n\t\tWHERE finished_at < NOW() - interval '90 days'\n\t`.execute(db);\n}\n\nexport async function startEmitter(\n\topts?: StartEmitterOptions,\n): Promise<() => Promise<void>> {\n\tconst emitterId = `emitter-${Math.random().toString(36).slice(2, 10)}`;\n\tconst db = getTargetDb();\n\tconst state: RunningState = {\n\t\trunning: true,\n\t\tsubQueues: new Map(),\n\t\tclaimInFlight: false,\n\t\tclaimPending: false,\n\t\tcurrentClaim: null,\n\t\tinFlightRuns: new Set(),\n\t};\n\tconst pollIntervalMs = opts?.pollIntervalMs ?? 120_000;\n\tconst retentionIntervalMs = opts?.retentionIntervalMs ?? 60 * 60_000;\n\n\tlogger.info(\"[emitter] started\", { id: emitterId });\n\n\t// LISTEN on new outbox + sub changes. Both channels fire on the TARGET DB\n\t// (webhook_outbox + webhooks are control-plane tables), so bind the\n\t// listener there — under the split it is NOT `DATABASE_URL`.\n\tconst listenUrl = targetListenerUrl();\n\tconst stopNew = await listen(\n\t\t\"webhooks:new_outbox\",\n\t\t() => {\n\t\t\tif (!state.running) return;\n\t\t\tvoid claimAndDrain(db, state, emitterId, \"notify\").catch((err) =>\n\t\t\t\tlogger.error(\"[emitter] claim failed\", {\n\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\t{ connectionString: listenUrl },\n\t);\n\tconst stopChanged = await listen(\n\t\t\"webhooks:changed\",\n\t\t() => {\n\t\t\tif (!state.running) return;\n\t\t\t// A resume is exactly `webhooks:changed` — its rows were already\n\t\t\t// released back to claimable (see claimAndDispatchOnce's paused-sub\n\t\t\t// branch) as soon as we noticed the pause, so a resumed webhook's\n\t\t\t// backlog drains on the SAME event that flips it active again,\n\t\t\t// instead of waiting for an unrelated future notify or the poll.\n\t\t\tvoid claimAndDrain(db, state, emitterId, \"changed\").catch((err) =>\n\t\t\t\tlogger.error(\"[emitter] claim failed\", {\n\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\t{ connectionString: listenUrl },\n\t);\n\t// Names both channels + the exact host/db LISTENed on (no credentials) so\n\t// a split-DB misconfiguration — the wake never reaching this process — is\n\t// visible in `docker logs` at boot, not only inferred from a delivery\n\t// latency graph later.\n\tlogger.info(\"[emitter] wake listeners connected\", {\n\t\tchannels: [\"webhooks:new_outbox\", \"webhooks:changed\"],\n\t\tdb: describeDbUrl(listenUrl),\n\t});\n\n\t// Poll every pollIntervalMs as a safety net for missed notifications +\n\t// backoff wakeups (rows whose next_attempt_at has passed).\n\tconst poll = setInterval(() => {\n\t\tif (!state.running) return;\n\t\tvoid claimAndDrain(db, state, emitterId, \"poll\").catch((err) =>\n\t\t\tlogger.error(\"[emitter] poll claim failed\", {\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t}),\n\t\t);\n\t}, pollIntervalMs);\n\n\t// Kick once on startup so any rows that arrived before we started drain.\n\tvoid claimAndDrain(db, state, emitterId, \"startup\");\n\n\t// Retention sweep — hourly by default.\n\tconst retention = setInterval(() => {\n\t\tif (!state.running) return;\n\t\tvoid runRetention(db).catch((err) =>\n\t\t\tlogger.error(\"[emitter] retention failed\", {\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t}),\n\t\t);\n\t}, retentionIntervalMs);\n\n\t// Receiver TLS expiry probe: Bun's fetch can't read peer certificates.\n\tconst receiverCerts = setInterval(() => {\n\t\tif (!state.running) return;\n\t\tvoid refreshReceiverCerts(db).catch((err) =>\n\t\t\tlogger.error(\"[emitter] receiver cert refresh failed\", {\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t}),\n\t\t);\n\t}, RECEIVER_CERT_INTERVAL_MS);\n\n\treturn async () => {\n\t\t// No new claims start (`runClaimLoop`'s own check) and no new\n\t\t// dispatches start (`pumpSub`'s own check) from this point on — the\n\t\t// two sets we're about to await can only shrink from here.\n\t\tstate.running = false;\n\t\tclearInterval(poll);\n\t\tclearInterval(retention);\n\t\tclearInterval(receiverCerts);\n\t\tawait stopNew();\n\t\tawait stopChanged();\n\n\t\tconst pendingRuns = new Set(state.inFlightRuns);\n\t\tconst drainTarget = pendingRuns.size;\n\t\t// `runOne` never rejects (it catches into `settleFailed`), but a claim\n\t\t// pass could — swallow that here rather than let it crash shutdown; the\n\t\t// call site that kicked off the claim already logs its own errors.\n\t\tconst claimSettled = (state.currentClaim ?? Promise.resolve()).catch(\n\t\t\t() => {},\n\t\t);\n\t\tconst waitAll = Promise.all([claimSettled, ...pendingRuns]);\n\t\t// A dispatch can't legitimately run longer than the webhook timeout\n\t\t// ceiling — bound the wait so a hung receiver can't hold up shutdown\n\t\t// forever. Rows still claimed/locked at the deadline keep their lock\n\t\t// and are re-claimed by the next emitter after LOCK_WINDOW_MS.\n\t\tconst deadlineMs =\n\t\t\topts?.stopDrainDeadlineMs ?? MAX_WEBHOOK_TIMEOUT_MS + 5_000;\n\t\tlet timedOut = false;\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\tconst timeout = new Promise<void>((resolve) => {\n\t\t\ttimer = setTimeout(() => {\n\t\t\t\ttimedOut = true;\n\t\t\t\tresolve();\n\t\t\t}, deadlineMs);\n\t\t});\n\t\tawait Promise.race([waitAll, timeout]);\n\t\tclearTimeout(timer);\n\n\t\tconst abandoned = timedOut ? state.inFlightRuns.size : 0;\n\t\tconst drained = drainTarget - abandoned;\n\t\tlogger.info(\"[emitter] stopped\", {\n\t\t\tid: emitterId,\n\t\t\tevent: \"emitter_stopped\",\n\t\t\tdrained,\n\t\t\tabandoned,\n\t\t});\n\t};\n}\n",
6
6
  "import { signSecondlayerWebhook } from \"@secondlayer/shared/crypto/secondlayer-webhook\";\nimport type { Webhook, WebhookOutbox } from \"@secondlayer/shared/db\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport { buildCloudEvents } from \"./cloudevents.ts\";\nimport { buildCloudflare } from \"./cloudflare.ts\";\nimport { buildInngest } from \"./inngest.ts\";\nimport { buildRaw } from \"./raw.ts\";\nimport { buildStandardWebhooks } from \"./standard-webhooks.ts\";\nimport { buildTrigger } from \"./trigger.ts\";\n\nexport interface FormatBuildResult {\n\tbody: string;\n\theaders: Record<string, string>;\n}\n\nfunction buildBody(\n\toutboxRow: WebhookOutbox,\n\tsub: Webhook,\n\tsigningSecret: string,\n): FormatBuildResult {\n\tswitch (sub.format) {\n\t\tcase \"inngest\":\n\t\t\treturn buildInngest(outboxRow);\n\t\tcase \"trigger\":\n\t\t\treturn buildTrigger(outboxRow, sub);\n\t\tcase \"cloudflare\":\n\t\t\treturn buildCloudflare(outboxRow, sub);\n\t\tcase \"cloudevents\":\n\t\t\treturn buildCloudEvents(outboxRow, sub);\n\t\tcase \"raw\":\n\t\t\treturn buildRaw(outboxRow, sub);\n\t\tcase \"standard-webhooks\":\n\t\t\treturn buildStandardWebhooks(outboxRow, signingSecret);\n\t\tdefault:\n\t\t\tlogger.warn(\"Unknown webhook format, falling back to standard-webhooks\", {\n\t\t\t\tformat: sub.format,\n\t\t\t\twebhookId: sub.id,\n\t\t\t});\n\t\t\treturn buildStandardWebhooks(outboxRow, signingSecret);\n\t}\n}\n\n/**\n * Dispatch an outbox row through the format matching the webhook's\n * `format` column. Unknown formats fall back to `standard-webhooks` with\n * a warning log — receivers always get something deliverable.\n *\n * Every delivery, whatever its body shape, also gets the universal Secondlayer\n * authenticity headers (`webhook-id` + `X-Secondlayer-Signature`) so a receiver\n * can prove the payload came from us with one published public key — not just\n * the `standard-webhooks` format. The signature covers the exact body bytes\n * built here, so it must be attached after the body is final.\n */\nexport function buildForFormat(\n\toutboxRow: WebhookOutbox,\n\tsub: Webhook,\n\tsigningSecret: string,\n): FormatBuildResult {\n\tconst result = buildBody(outboxRow, sub, signingSecret);\n\tconst sigHeaders = signSecondlayerWebhook(outboxRow.id, result.body);\n\tif (sigHeaders) {\n\t\tresult.headers = { ...result.headers, ...sigHeaders };\n\t}\n\treturn result;\n}\n",
7
7
  "import type { Webhook, WebhookOutbox } from \"@secondlayer/shared/db\";\n\n/**\n * CloudEvents 1.0 structured JSON — https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md\n *\n * Body shape:\n * {\n * \"specversion\": \"1.0\",\n * \"type\": \"chain.<trigger>.apply\",\n * \"source\": \"secondlayer:<chain>\", // stacks | bitcoin\n * \"id\": <outbox.id>, // UUID, used for dedup\n * \"time\": <ISO 8601>,\n * \"datacontenttype\": \"application/json\",\n * \"data\": { ...event }\n * }\n *\n * Content-Type is `application/cloudevents+json; charset=utf-8`. Binary\n * mode (headers as ce-*) isn't needed — structured mode is what every CE\n * SDK accepts out of the box.\n */\n\n/** The chain that produced the event. Runes (Bitcoin) payloads carry\n * `chain: \"bitcoin\"`; every other trigger matches Stacks events. */\nfunction chainOf(payload: unknown): \"stacks\" | \"bitcoin\" {\n\treturn (payload as { chain?: unknown } | null)?.chain === \"bitcoin\"\n\t\t? \"bitcoin\"\n\t\t: \"stacks\";\n}\n\nexport function buildCloudEvents(\n\toutboxRow: WebhookOutbox,\n\t_sub: Webhook,\n): { body: string; headers: Record<string, string> } {\n\tconst event = {\n\t\tspecversion: \"1.0\",\n\t\ttype: outboxRow.event_type,\n\t\tsource: `secondlayer:${chainOf(outboxRow.payload)}`,\n\t\tid: outboxRow.id,\n\t\ttime: new Date(outboxRow.created_at).toISOString(),\n\t\tdatacontenttype: \"application/json\",\n\t\tdata: outboxRow.payload,\n\t};\n\treturn {\n\t\tbody: JSON.stringify(event),\n\t\theaders: {\n\t\t\t\"content-type\": \"application/cloudevents+json; charset=utf-8\",\n\t\t},\n\t};\n}\n",
8
8
  "import { decryptSecret } from \"@secondlayer/shared/crypto/secrets\";\nimport type { Webhook, WebhookOutbox } from \"@secondlayer/shared/db\";\n\n/**\n * Cloudflare Workflows — https://developers.cloudflare.com/workflows/build/events-and-parameters/\n *\n * POST https://api.cloudflare.com/client/v4/accounts/{account}/workflows/{name}/instances\n * Authorization: Bearer <CF_API_TOKEN>\n *\n * Body: `{ params }` — the workflow entrypoint receives this as the\n * `event.payload` object. We slip the outbox id into `params._outboxId`\n * so Workflows can dedupe on replays.\n */\n\nfunction resolveBearer(sub: Webhook): string | null {\n\tconst cfg = sub.auth_config as { token?: string; tokenEnc?: string };\n\tif (cfg.tokenEnc) {\n\t\t// Let decrypt errors propagate — see trigger.ts comment.\n\t\treturn decryptSecret(Buffer.from(cfg.tokenEnc, \"base64\"));\n\t}\n\treturn cfg.token ?? null;\n}\n\nexport function buildCloudflare(\n\toutboxRow: WebhookOutbox,\n\tsub: Webhook,\n): { body: string; headers: Record<string, string> } {\n\tconst body = JSON.stringify({\n\t\tparams: {\n\t\t\t...(outboxRow.payload as Record<string, unknown>),\n\t\t\t_type: outboxRow.event_type,\n\t\t\t_outboxId: outboxRow.id,\n\t\t},\n\t});\n\tconst headers: Record<string, string> = {\n\t\t\"content-type\": \"application/json\",\n\t};\n\tconst token = resolveBearer(sub);\n\tif (token) headers.authorization = `Bearer ${token}`;\n\treturn { body, headers };\n}\n",
@@ -13,7 +13,7 @@
13
13
  "/**\n * Hosted-stack event meter counter (plan 044, step 5). Counts webhook\n * deliveries (never retries) and pushes the count to the provisioner over a\n * unix socket every 60s. Inert unless `WEBHOOK_METER_SOCKET` is set — a\n * self-host instance never has this env var, so this module is a total\n * no-op there (no socket, no interval, no behavior change).\n *\n * Runs only inside `webhook-processor` (`webhook-service.ts` /\n * `webhook-plane.ts`) — never the subgraph indexer, never `api`. Counts\n * never touch this instance's own Postgres, so once 046 runs customer\n * handler code in `api`, that code has no path to lower them (Design,\n * \"Open\" section).\n */\n\nimport { logger } from \"@secondlayer/shared\";\n\nconst FLUSH_INTERVAL_MS = 60_000;\n\nlet pending = 0;\nlet flushTimer: ReturnType<typeof setInterval> | undefined;\n\n/** Socket path this process pushes to, or `undefined` when the meter is\n * off (self-host, or hosted before this env is wired). Read once at\n * `startMeterSocketReporter()` time, not per-call, so a mid-process env\n * mutation (tests) can't half-apply. */\nfunction socketPath(env: NodeJS.ProcessEnv = process.env): string | undefined {\n\tconst path = env.WEBHOOK_METER_SOCKET?.trim();\n\treturn path && path.length > 0 ? path : undefined;\n}\n\n/** Count one delivered event (never a retry — call this only from the path\n * that already excludes retries, `emitter.ts`'s `settleDelivered`). A\n * no-op with zero overhead when the meter is off. */\nexport function recordDelivery(): void {\n\tif (!socketPath()) return;\n\tpending += 1;\n}\n\nasync function flush(path: string): Promise<void> {\n\tconst count = pending;\n\tif (count === 0) return;\n\t// Optimistic reset before the push: if the push fails we've undercounted\n\t// by at most one interval's worth once (logged below), never double-count\n\t// on a retry — the alternative (reset after success) risks double-adding\n\t// events recorded during a slow/failed push into the NEXT flush.\n\tpending = 0;\n\ttry {\n\t\tconst res = await fetch(\"http://localhost/\", {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify({ delivered_events: count }),\n\t\t\tunix: path,\n\t\t});\n\t\tif (!res.ok) {\n\t\t\tlogger.warn(\"webhook.meter_socket.push_rejected\", {\n\t\t\t\tstatus: res.status,\n\t\t\t\tcount,\n\t\t\t});\n\t\t}\n\t} catch (err) {\n\t\t// The provisioner's socket may not be listening yet (mid-provision) or\n\t\t// briefly restarting — never fatal to webhook delivery, which is this\n\t\t// process's actual job.\n\t\tlogger.warn(\"webhook.meter_socket.push_failed\", {\n\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\tcount,\n\t\t});\n\t}\n}\n\n/** Starts the 60s flush loop when `WEBHOOK_METER_SOCKET` is set; a no-op\n * (returns a no-op stop function) otherwise. Idempotent — a second call\n * while already running clears the previous interval first. */\nexport function startMeterSocketReporter(): () => void {\n\tconst path = socketPath();\n\tif (!path) return () => {};\n\n\tif (flushTimer) clearInterval(flushTimer);\n\tflushTimer = setInterval(() => {\n\t\tflush(path).catch(() => {}); // flush() already logs; never throw into the timer\n\t}, FLUSH_INTERVAL_MS);\n\n\treturn () => {\n\t\tif (flushTimer) {\n\t\t\tclearInterval(flushTimer);\n\t\t\tflushTimer = undefined;\n\t\t}\n\t};\n}\n\n/** Test-only: reset the module-level counter between test files. */\nexport function resetMeterSocketCounterForTests(): void {\n\tpending = 0;\n}\n\n/** Test-only: read the current unflushed count. */\nexport function pendingCountForTests(): number {\n\treturn pending;\n}\n",
14
14
  "import { isIP } from \"node:net\";\nimport tls from \"node:tls\";\nimport type { Database } from \"@secondlayer/shared/db\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport { type Kysely, sql } from \"kysely\";\nimport { allowPrivateEgress, checkEgressAllowed } from \"./emitter.ts\";\n\n/**\n * Receiver TLS certificate expiry. Bun's `fetch` does not expose the peer\n * certificate, so the emitter probes each https origin out of band with\n * `node:tls` (works under Bun) and stores the result on `webhooks`.\n */\n\nconst PROBE_TIMEOUT_MS = 5_000;\nconst RECHECK_AFTER_HOURS = 6;\nconst BATCH_LIMIT = 50;\n\n/**\n * Leaf certificate expiry of an https receiver, or null for non-https URLs,\n * refused egress, connection errors and timeouts. Never throws. Passes the\n * same egress guard as deliveries.\n */\nexport async function probeCertExpiry(\n\turl: string,\n\topts?: { connect?: typeof tls.connect; timeoutMs?: number },\n): Promise<Date | null> {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(url);\n\t} catch {\n\t\treturn null;\n\t}\n\tif (parsed.protocol !== \"https:\") return null;\n\n\tif (!allowPrivateEgress()) {\n\t\tlet refusal: string | null;\n\t\ttry {\n\t\t\trefusal = await checkEgressAllowed(url);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t\tif (refusal) return null;\n\t}\n\n\tconst raw = parsed.hostname;\n\tconst host =\n\t\traw.startsWith(\"[\") && raw.endsWith(\"]\") ? raw.slice(1, -1) : raw;\n\tconst connect = opts?.connect ?? tls.connect;\n\tconst timeoutMs = opts?.timeoutMs ?? PROBE_TIMEOUT_MS;\n\n\treturn new Promise<Date | null>((resolve) => {\n\t\tconst open: { socket?: tls.TLSSocket } = {};\n\t\tlet settled = false;\n\t\tconst finish = (expires: Date | null) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timer);\n\t\t\ttry {\n\t\t\t\topen.socket?.destroy();\n\t\t\t} catch {\n\t\t\t\t// already closed\n\t\t\t}\n\t\t\tresolve(expires);\n\t\t};\n\t\tconst timer = setTimeout(() => finish(null), timeoutMs);\n\t\tlet probe: tls.TLSSocket;\n\t\ttry {\n\t\t\tprobe = connect({\n\t\t\t\thost,\n\t\t\t\tport: Number(parsed.port) || 443,\n\t\t\t\t...(isIP(host) ? {} : { servername: host }),\n\t\t\t\t// Only the leaf cert is read and no data is sent, so an expired or\n\t\t\t\t// self-signed cert must still report its expiry.\n\t\t\t\trejectUnauthorized: false,\n\t\t\t});\n\t\t} catch {\n\t\t\tfinish(null);\n\t\t\treturn;\n\t\t}\n\t\topen.socket = probe;\n\t\tprobe.once(\"secureConnect\", () => {\n\t\t\ttry {\n\t\t\t\tconst expires = new Date(probe.getPeerCertificate().valid_to);\n\t\t\t\tfinish(Number.isNaN(expires.getTime()) ? null : expires);\n\t\t\t} catch {\n\t\t\t\tfinish(null);\n\t\t\t}\n\t\t});\n\t\tprobe.once(\"error\", () => finish(null));\n\t});\n}\n\n/**\n * Probe the https receivers whose expiry is unknown or older than six hours.\n * One probe per distinct origin; every selected webhook on that origin gets\n * the result (which may be null) and a fresh `receiver_cert_checked_at`.\n */\nexport async function refreshReceiverCerts(\n\tdb: Kysely<Database>,\n\topts?: { probe?: (url: string) => Promise<Date | null> },\n): Promise<void> {\n\tconst probe = opts?.probe ?? probeCertExpiry;\n\tconst due = await db\n\t\t.selectFrom(\"webhooks\")\n\t\t.select([\"id\", \"url\"])\n\t\t.where(\"status\", \"=\", \"active\")\n\t\t.where(\"url\", \"like\", \"https:%\")\n\t\t.where((eb) =>\n\t\t\teb.or([\n\t\t\t\teb(\"receiver_cert_checked_at\", \"is\", null),\n\t\t\t\teb(\n\t\t\t\t\t\"receiver_cert_checked_at\",\n\t\t\t\t\t\"<\",\n\t\t\t\t\tsql<Date>`now() - make_interval(hours => ${RECHECK_AFTER_HOURS})`,\n\t\t\t\t),\n\t\t\t]),\n\t\t)\n\t\t.orderBy(sql`receiver_cert_checked_at asc nulls first`)\n\t\t.limit(BATCH_LIMIT)\n\t\t.execute();\n\n\tconst idsByOrigin = new Map<string, { url: string; ids: string[] }>();\n\tfor (const { id, url } of due) {\n\t\tlet origin: string;\n\t\ttry {\n\t\t\torigin = new URL(url).origin;\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\t\tconst entry = idsByOrigin.get(origin) ?? { url, ids: [] };\n\t\tentry.ids.push(id);\n\t\tidsByOrigin.set(origin, entry);\n\t}\n\n\tfor (const [origin, { url, ids }] of idsByOrigin) {\n\t\tconst expires = await probe(url);\n\t\tawait db\n\t\t\t.updateTable(\"webhooks\")\n\t\t\t.set({\n\t\t\t\treceiver_cert_expires_at: expires,\n\t\t\t\treceiver_cert_checked_at: new Date(),\n\t\t\t})\n\t\t\t.where(\"id\", \"in\", ids)\n\t\t\t.execute();\n\t\tlogger.debug(\"[emitter] receiver cert probed\", {\n\t\t\torigin,\n\t\t\texpiresAt: expires?.toISOString() ?? null,\n\t\t});\n\t}\n}\n"
15
15
  ],
16
- "mappings": ";AAAA;AACA,mBAAS;AACT;AAAA;AAAA;AAAA;AAOA;AACA;AACA,mBAAS;AACT;AACA;AAAA;AAAA;AAIA,gBAAsB;;;ACjBtB;AAEA;;;ACqBA,SAAS,OAAO,CAAC,SAAwC;AAAA,EACxD,OAAQ,SAAwC,UAAU,YACvD,YACA;AAAA;AAGG,SAAS,gBAAgB,CAC/B,WACA,MACoD;AAAA,EACpD,MAAM,QAAQ;AAAA,IACb,aAAa;AAAA,IACb,MAAM,UAAU;AAAA,IAChB,QAAQ,eAAe,QAAQ,UAAU,OAAO;AAAA,IAChD,IAAI,UAAU;AAAA,IACd,MAAM,IAAI,KAAK,UAAU,UAAU,EAAE,YAAY;AAAA,IACjD,iBAAiB;AAAA,IACjB,MAAM,UAAU;AAAA,EACjB;AAAA,EACA,OAAO;AAAA,IACN,MAAM,KAAK,UAAU,KAAK;AAAA,IAC1B,SAAS;AAAA,MACR,gBAAgB;AAAA,IACjB;AAAA,EACD;AAAA;;;AC/CD;AAcA,SAAS,aAAa,CAAC,KAA6B;AAAA,EACnD,MAAM,MAAM,IAAI;AAAA,EAChB,IAAI,IAAI,UAAU;AAAA,IAEjB,OAAO,cAAc,OAAO,KAAK,IAAI,UAAU,QAAQ,CAAC;AAAA,EACzD;AAAA,EACA,OAAO,IAAI,SAAS;AAAA;AAGd,SAAS,eAAe,CAC9B,WACA,KACoD;AAAA,EACpD,MAAM,OAAO,KAAK,UAAU;AAAA,IAC3B,QAAQ;AAAA,SACH,UAAU;AAAA,MACd,OAAO,UAAU;AAAA,MACjB,WAAW,UAAU;AAAA,IACtB;AAAA,EACD,CAAC;AAAA,EACD,MAAM,UAAkC;AAAA,IACvC,gBAAgB;AAAA,EACjB;AAAA,EACA,MAAM,QAAQ,cAAc,GAAG;AAAA,EAC/B,IAAI;AAAA,IAAO,QAAQ,gBAAgB,UAAU;AAAA,EAC7C,OAAO,EAAE,MAAM,QAAQ;AAAA;;;ACrBjB,IAAM,kBAAkB;AAExB,SAAS,YAAY,CAAC,WAG3B;AAAA,EACD,MAAM,QAAQ;AAAA,IACb,MAAM,UAAU;AAAA,IAChB,MAAM,UAAU;AAAA,IAChB,IAAI,UAAU;AAAA,IACd,IAAI,IAAI,KAAK,UAAU,UAAU,EAAE,QAAQ;AAAA,IAC3C,GAAG;AAAA,EACJ;AAAA,EACA,OAAO;AAAA,IACN,MAAM,KAAK,UAAU,CAAC,KAAK,CAAC;AAAA,IAC5B,SAAS;AAAA,MACR,gBAAgB;AAAA,IACjB;AAAA,EACD;AAAA;;;ACrBM,SAAS,QAAQ,CACvB,WACA,KACoD;AAAA,EACpD,MAAM,MAAM,IAAI;AAAA,EAOhB,MAAM,UAAkC;AAAA,IACvC,gBAAgB,IAAI,eAAe;AAAA,OAC/B,IAAI,WAAW,CAAC;AAAA,EACrB;AAAA,EACA,IAAI,IAAI,aAAa,YAAY,IAAI,OAAO;AAAA,IAC3C,QAAQ,gBAAgB,UAAU,IAAI;AAAA,EACvC,EAAO,SAAI,IAAI,aAAa,WAAW,IAAI,WAAW;AAAA,IACrD,QAAQ,gBAAgB,SAAS,IAAI;AAAA,EACtC;AAAA,EACA,OAAO;AAAA,IACN,MAAM,KAAK,UAAU,UAAU,OAAO;AAAA,IACtC;AAAA,EACD;AAAA;;;ACtCD;AA0BO,SAAS,qBAAqB,CACpC,WACA,eACoD;AAAA,EACpD,MAAM,aAAa,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI;AAAA,EAC/C,MAAM,UAAmC;AAAA,IACxC,MAAM,UAAU;AAAA,IAChB,WAAW,IAAI,KAAK,aAAa,IAAI,EAAE,YAAY;AAAA,IACnD,MAAM,UAAU;AAAA,EACjB;AAAA,EACA,MAAM,OAAO,KAAK,UAAU,OAAO;AAAA,EACnC,MAAM,aAAa,KAAK,MAAM,eAAe;AAAA,IAC5C,IAAI,UAAU;AAAA,IACd,kBAAkB;AAAA,EACnB,CAAC;AAAA,EACD,OAAO;AAAA,IACN;AAAA,IACA,SAAS;AAAA,MACR,gBAAgB;AAAA,SACb;AAAA,IACJ;AAAA,EACD;AAAA;;;AC/CD,0BAAS;AAiBT,SAAS,cAAa,CAAC,KAA6B;AAAA,EACnD,MAAM,MAAM,IAAI;AAAA,EAKhB,IAAI,IAAI,UAAU;AAAA,IAKjB,OAAO,eAAc,OAAO,KAAK,IAAI,UAAU,QAAQ,CAAC;AAAA,EACzD;AAAA,EACA,OAAO,IAAI,SAAS;AAAA;AAGd,SAAS,YAAY,CAC3B,WACA,KACoD;AAAA,EACpD,MAAM,OAAO,KAAK,UAAU;AAAA,IAC3B,SAAS,UAAU;AAAA,IACnB,SAAS;AAAA,MACR,gBAAgB,UAAU;AAAA,IAC3B;AAAA,EACD,CAAC;AAAA,EACD,MAAM,UAAkC;AAAA,IACvC,gBAAgB;AAAA,EACjB;AAAA,EACA,MAAM,QAAQ,eAAc,GAAG;AAAA,EAC/B,IAAI;AAAA,IAAO,QAAQ,gBAAgB,UAAU;AAAA,EAC7C,OAAO,EAAE,MAAM,QAAQ;AAAA;;;ANjCxB,SAAS,SAAS,CACjB,WACA,KACA,eACoB;AAAA,EACpB,QAAQ,IAAI;AAAA,SACN;AAAA,MACJ,OAAO,aAAa,SAAS;AAAA,SACzB;AAAA,MACJ,OAAO,aAAa,WAAW,GAAG;AAAA,SAC9B;AAAA,MACJ,OAAO,gBAAgB,WAAW,GAAG;AAAA,SACjC;AAAA,MACJ,OAAO,iBAAiB,WAAW,GAAG;AAAA,SAClC;AAAA,MACJ,OAAO,SAAS,WAAW,GAAG;AAAA,SAC1B;AAAA,MACJ,OAAO,sBAAsB,WAAW,aAAa;AAAA;AAAA,MAErD,OAAO,KAAK,6DAA6D;AAAA,QACxE,QAAQ,IAAI;AAAA,QACZ,WAAW,IAAI;AAAA,MAChB,CAAC;AAAA,MACD,OAAO,sBAAsB,WAAW,aAAa;AAAA;AAAA;AAejD,SAAS,cAAc,CAC7B,WACA,KACA,eACoB;AAAA,EACpB,MAAM,SAAS,UAAU,WAAW,KAAK,aAAa;AAAA,EACtD,MAAM,aAAa,uBAAuB,UAAU,IAAI,OAAO,IAAI;AAAA,EACnE,IAAI,YAAY;AAAA,IACf,OAAO,UAAU,KAAK,OAAO,YAAY,WAAW;AAAA,EACrD;AAAA,EACA,OAAO;AAAA;;;AOjDR,mBAAS;AAIT,IAAI,UAAU;AAOd,SAAS,UAAU,CAAC,MAAyB,QAAQ,KAAyB;AAAA,EAC7E,MAAM,OAAO,IAAI,sBAAsB,KAAK;AAAA,EAC5C,OAAO,QAAQ,KAAK,SAAS,IAAI,OAAO;AAAA;AAMlC,SAAS,cAAc,GAAS;AAAA,EACtC,IAAI,CAAC,WAAW;AAAA,IAAG;AAAA,EACnB,WAAW;AAAA;;;ACnCZ;AACA;AAEA,mBAAS;AACT;AASA,IAAM,mBAAmB;AACzB,IAAM,sBAAsB;AAC5B,IAAM,cAAc;AAOpB,eAAsB,eAAe,CACpC,KACA,MACuB;AAAA,EACvB,IAAI;AAAA,EACJ,IAAI;AAAA,IACH,SAAS,IAAI,IAAI,GAAG;AAAA,IACnB,MAAM;AAAA,IACP,OAAO;AAAA;AAAA,EAER,IAAI,OAAO,aAAa;AAAA,IAAU,OAAO;AAAA,EAEzC,IAAI,CAAC,mBAAmB,GAAG;AAAA,IAC1B,IAAI;AAAA,IACJ,IAAI;AAAA,MACH,UAAU,MAAM,mBAAmB,GAAG;AAAA,MACrC,MAAM;AAAA,MACP,OAAO;AAAA;AAAA,IAER,IAAI;AAAA,MAAS,OAAO;AAAA,EACrB;AAAA,EAEA,MAAM,MAAM,OAAO;AAAA,EACnB,MAAM,OACL,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI;AAAA,EAC/D,MAAM,UAAU,MAAM,WAAW,IAAI;AAAA,EACrC,MAAM,YAAY,MAAM,aAAa;AAAA,EAErC,OAAO,IAAI,QAAqB,CAAC,YAAY;AAAA,IAC5C,MAAM,OAAmC,CAAC;AAAA,IAC1C,IAAI,UAAU;AAAA,IACd,MAAM,SAAS,CAAC,YAAyB;AAAA,MACxC,IAAI;AAAA,QAAS;AAAA,MACb,UAAU;AAAA,MACV,aAAa,KAAK;AAAA,MAClB,IAAI;AAAA,QACH,KAAK,QAAQ,QAAQ;AAAA,QACpB,MAAM;AAAA,MAGR,QAAQ,OAAO;AAAA;AAAA,IAEhB,MAAM,QAAQ,WAAW,MAAM,OAAO,IAAI,GAAG,SAAS;AAAA,IACtD,IAAI;AAAA,IACJ,IAAI;AAAA,MACH,QAAQ,QAAQ;AAAA,QACf;AAAA,QACA,MAAM,OAAO,OAAO,IAAI,KAAK;AAAA,WACzB,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE,YAAY,KAAK;AAAA,QAGzC,oBAAoB;AAAA,MACrB,CAAC;AAAA,MACA,MAAM;AAAA,MACP,OAAO,IAAI;AAAA,MACX;AAAA;AAAA,IAED,KAAK,SAAS;AAAA,IACd,MAAM,KAAK,iBAAiB,MAAM;AAAA,MACjC,IAAI;AAAA,QACH,MAAM,UAAU,IAAI,KAAK,MAAM,mBAAmB,EAAE,QAAQ;AAAA,QAC5D,OAAO,OAAO,MAAM,QAAQ,QAAQ,CAAC,IAAI,OAAO,OAAO;AAAA,QACtD,MAAM;AAAA,QACP,OAAO,IAAI;AAAA;AAAA,KAEZ;AAAA,IACD,MAAM,KAAK,SAAS,MAAM,OAAO,IAAI,CAAC;AAAA,GACtC;AAAA;AAQF,eAAsB,oBAAoB,CACzC,IACA,MACgB;AAAA,EAChB,MAAM,QAAQ,MAAM,SAAS;AAAA,EAC7B,MAAM,MAAM,MAAM,GAChB,WAAW,UAAU,EACrB,OAAO,CAAC,MAAM,KAAK,CAAC,EACpB,MAAM,UAAU,KAAK,QAAQ,EAC7B,MAAM,OAAO,QAAQ,SAAS,EAC9B,MAAM,CAAC,OACP,GAAG,GAAG;AAAA,IACL,GAAG,4BAA4B,MAAM,IAAI;AAAA,IACzC,GACC,4BACA,KACA,qCAA2C,sBAC5C;AAAA,EACD,CAAC,CACF,EACC,QAAQ,6CAA6C,EACrD,MAAM,WAAW,EACjB,QAAQ;AAAA,EAEV,MAAM,cAAc,IAAI;AAAA,EACxB,aAAa,IAAI,SAAS,KAAK;AAAA,IAC9B,IAAI;AAAA,IACJ,IAAI;AAAA,MACH,SAAS,IAAI,IAAI,GAAG,EAAE;AAAA,MACrB,MAAM;AAAA,MACP;AAAA;AAAA,IAED,MAAM,QAAQ,YAAY,IAAI,MAAM,KAAK,EAAE,KAAK,KAAK,CAAC,EAAE;AAAA,IACxD,MAAM,IAAI,KAAK,EAAE;AAAA,IACjB,YAAY,IAAI,QAAQ,KAAK;AAAA,EAC9B;AAAA,EAEA,YAAY,UAAU,KAAK,UAAU,aAAa;AAAA,IACjD,MAAM,UAAU,MAAM,MAAM,GAAG;AAAA,IAC/B,MAAM,GACJ,YAAY,UAAU,EACtB,IAAI;AAAA,MACJ,0BAA0B;AAAA,MAC1B,0BAA0B,IAAI;AAAA,IAC/B,CAAC,EACA,MAAM,MAAM,MAAM,GAAG,EACrB,QAAQ;AAAA,IACV,QAAO,MAAM,kCAAkC;AAAA,MAC9C;AAAA,MACA,WAAW,SAAS,YAAY,KAAK;AAAA,IACtC,CAAC;AAAA,EACF;AAAA;;;AT3GD,IAAM,aAAa;AACnB,IAAM,aAAa;AACnB,IAAM,kBAAkB,CAAC,IAAI,KAAK,KAAK,MAAM,OAAO,OAAO,MAAM;AACjE,IAAM,oBAAoB;AAcnB,IAAM,yBAAiC,wBAAwB;AAC/D,IAAM,iBAAyB,yBAAyB;AAuC/D,SAAS,gBAAgB,CAAC,SAAyB;AAAA,EAElD,OAAO,gBAAgB,KAAK,IAAI,SAAS,gBAAgB,SAAS,CAAC;AAAA;AAOpE,IAAM,sBAAsB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAeA,SAAS,WAAW,CAAC,SAA0B;AAAA,EAC9C,MAAM,OAAO,QAAQ,YAAY;AAAA,EAEjC,IAAI,SAAS;AAAA,IAAW,OAAO;AAAA,EAC/B,IAAI,SAAS,QAAQ,SAAS;AAAA,IAAO,OAAO;AAAA,EAE5C,IAAI,qBAAqB,KAAK,IAAI;AAAA,IAAG,OAAO;AAAA,EAC5C,IAAI,qBAAqB,KAAK,IAAI;AAAA,IAAG,OAAO;AAAA,EAC5C,IAAI,kBAAkB,KAAK,IAAI;AAAA,IAAG,OAAO;AAAA,EAGzC,MAAM,SAAS,KAAK,MAAM,eAAe;AAAA,EACzC,IAAI,QAAQ;AAAA,IAEX,MAAM,QAAQ,OAAO;AAAA,IAErB,IAAI,uBAAuB,KAAK,KAAK,GAAG;AAAA,MACvC,WAAW,KAAK;AAAA,QAAqB,IAAI,EAAE,KAAK,KAAK;AAAA,UAAG,OAAO;AAAA,IAChE;AAAA,IAEA,MAAM,MAAM,MAAM,MAAM,mCAAmC;AAAA,IAC3D,IAAI,KAAK;AAAA,MAER,MAAM,IAAI,OAAO,SAAS,IAAI,IAAK,EAAE;AAAA,MAErC,MAAM,IAAI,OAAO,SAAS,IAAI,IAAK,EAAE;AAAA,MACrC,MAAM,SAAS,GAAI,KAAK,IAAK,OAAQ,IAAI,OAAS,KAAK,IAAK,OAAQ,IAAI;AAAA,MACxE,WAAW,KAAK;AAAA,QAAqB,IAAI,EAAE,KAAK,MAAM;AAAA,UAAG,OAAO;AAAA,IACjE;AAAA,IACA,OAAO;AAAA,EACR;AAAA,EAIA,MAAM,QAAQ,KAAK,MAAM,iBAAiB;AAAA,EAC1C,IAAI,OAAO;AAAA,IAEV,MAAM,QAAQ,MAAM;AAAA,IACpB,IAAI,uBAAuB,KAAK,KAAK,GAAG;AAAA,MACvC,WAAW,KAAK;AAAA,QAAqB,IAAI,EAAE,KAAK,KAAK;AAAA,UAAG,OAAO;AAAA,IAChE;AAAA,IACA,MAAM,MAAM,MAAM,MAAM,mCAAmC;AAAA,IAC3D,IAAI,KAAK;AAAA,MAER,MAAM,IAAI,OAAO,SAAS,IAAI,IAAK,EAAE;AAAA,MAErC,MAAM,IAAI,OAAO,SAAS,IAAI,IAAK,EAAE;AAAA,MACrC,MAAM,SAAS,GAAI,KAAK,IAAK,OAAQ,IAAI,OAAS,KAAK,IAAK,OAAQ,IAAI;AAAA,MACxE,WAAW,KAAK;AAAA,QAAqB,IAAI,EAAE,KAAK,MAAM;AAAA,UAAG,OAAO;AAAA,IACjE;AAAA,IACA,OAAO;AAAA,EACR;AAAA,EAEA,WAAW,KAAK,qBAAqB;AAAA,IACpC,IAAI,EAAE,KAAK,IAAI;AAAA,MAAG,OAAO;AAAA,EAC1B;AAAA,EACA,OAAO;AAAA;AASR,SAAS,eAAe,CAAC,KAAsB;AAAA,EAC9C,IAAI;AAAA,EACJ,IAAI;AAAA,IACH,SAAS,IAAI,IAAI,GAAG;AAAA,IACnB,MAAM;AAAA,IACP,OAAO;AAAA;AAAA,EAER,IAAI,OAAO,aAAa,WAAW,OAAO,aAAa,UAAU;AAAA,IAChE,OAAO;AAAA,EACR;AAAA,EAGA,MAAM,MAAM,OAAO,SAAS,YAAY;AAAA,EACxC,MAAM,OACL,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI;AAAA,EAE/D,IAAI,SAAS;AAAA,IAAa,OAAO;AAAA,EACjC,OAAO,YAAY,IAAI;AAAA;AAIxB,IAAM,4BAA4B,KAAK;AAEhC,SAAS,kBAAkB,GAAY;AAAA,EAC7C,OAAO,QAAQ,IAAI,qCAAqC;AAAA;AAUzD,eAAe,gBAAgB,CAAC,UAA8C;AAAA,EAC7E,OAAO,UAAU,UAAU,EAAE,KAAK,KAAK,CAAC;AAAA;AAGzC,IAAI,gBAA6B;AAQ1B,SAAS,qBAAqB,CAAC,IAA8B;AAAA,EACnE,gBAAgB,MAAM;AAAA;AAGvB,IAAM,aAAa;AA6BnB,eAAsB,kBAAkB,CAAC,KAAqC;AAAA,EAC7E,IAAI,gBAAgB,GAAG,GAAG;AAAA,IACzB,OAAO,2CAA2C;AAAA,EACnD;AAAA,EAEA,IAAI;AAAA,EACJ,IAAI;AAAA,IACH,SAAS,IAAI,IAAI,GAAG;AAAA,IACnB,MAAM;AAAA,IACP,OAAO,yCAAyC;AAAA;AAAA,EAEjD,IAAI,OAAO,aAAa,WAAW,OAAO,aAAa,UAAU;AAAA,IAChE,OAAO,gDAAgD;AAAA,EACxD;AAAA,EAEA,MAAM,MAAM,OAAO,SAAS,YAAY;AAAA,EACxC,MAAM,WACL,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI;AAAA,EAE/D,IAAI;AAAA,EACJ,IAAI;AAAA,IACH,WAAW,MAAM,cAAc,QAAQ;AAAA,IACtC,OAAO,KAAK;AAAA,IACb,MAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IAC3D,OAAO,kDAAkD,QAAQ;AAAA;AAAA,EAElE,IAAI,SAAS,WAAW,GAAG;AAAA,IAC1B,OAAO,gEAAgE;AAAA,EACxE;AAAA,EACA,aAAa,aAAa,UAAU;AAAA,IACnC,IAAI,YAAY,OAAO,GAAG;AAAA,MACzB,OAAO,gEAAgE,WAAW;AAAA,IACnF;AAAA,EACD;AAAA,EACA,OAAO;AAAA;AAuBD,IAAM,oBAA4B;AASzC,eAAe,aAAa,CAC3B,KACA,MACA,SACA,WACsB;AAAA,EACtB,MAAM,QAAQ,YAAY,IAAI;AAAA,EAC9B,IAAI,SAAS;AAAA,EACb,IAAI,aAA4B;AAAA,EAChC,IAAI,QAAuB;AAAA,EAC3B,IAAI,KAAK;AAAA,EACT,IAAI,eAAe;AAAA,EACnB,IAAI,kBAAiD;AAAA,EACrD,IAAI;AAAA,IACH,SAAS,MAAM,IAAK,OAAO;AAAA,MAC1B,IAAI,CAAC,mBAAmB,GAAG;AAAA,QAC1B,MAAM,UAAU,MAAM,mBAAmB,MAAM;AAAA,QAC/C,IAAI,SAAS;AAAA,UACZ,QAAO,KAAK,oCAAoC;AAAA,YAC/C,KAAK;AAAA,YACL,QAAQ;AAAA,UACT,CAAC;AAAA,UACD,OAAO;AAAA,YACN,IAAI;AAAA,YACJ,YAAY;AAAA,YACZ,OAAO;AAAA,YACP,YAAY,KAAK,MAAM,YAAY,IAAI,IAAI,KAAK;AAAA,YAChD,cAAc;AAAA,YACd,iBAAiB;AAAA,UAClB;AAAA,QACD;AAAA,MACD;AAAA,MACA,IAAI,OAAO,mBAAmB;AAAA,QAC7B,OAAO;AAAA,UACN,IAAI;AAAA,UACJ;AAAA,UACA,OAAO,gCAAgC;AAAA,UACvC,YAAY,KAAK,MAAM,YAAY,IAAI,IAAI,KAAK;AAAA,UAChD,cAAc;AAAA,UACd,iBAAiB;AAAA,QAClB;AAAA,MACD;AAAA,MAEA,MAAM,MAAM,MAAM,MAAM,QAAQ;AAAA,QAC/B,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,QAAQ,YAAY,QAAQ,SAAS;AAAA,MACtC,CAAC;AAAA,MACD,aAAa,IAAI;AAAA,MAEjB,MAAM,WAAW,IAAI,QAAQ,IAAI,UAAU;AAAA,MAC3C,IAAI,IAAI,UAAU,OAAO,IAAI,SAAS,OAAO,UAAU;AAAA,QACtD,SAAS,IAAI,IAAI,UAAU,MAAM,EAAE,SAAS;AAAA,QAC5C;AAAA,MACD;AAAA,MAEA,KAAK,IAAI;AAAA,MAET,MAAM,MAAM,MAAM,IAAI,YAAY;AAAA,MAClC,MAAM,YAAY,IAAI,aAAa,OAAO,IAAI,MAAM,GAAG,IAAI,IAAI;AAAA,MAC/D,eAAe,OAAO,KAAK,SAAS,EAAE,SAAS,MAAM;AAAA,MACrD,kBAAkB,OAAO,YAAY,IAAI,QAAQ,QAAQ,CAAC;AAAA,MAC1D;AAAA,IACD;AAAA,IACC,OAAO,KAAK;AAAA,IACb,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA;AAAA,EAExD,OAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,KAAK,MAAM,YAAY,IAAI,IAAI,KAAK;AAAA,IAChD,cAAc,gBAAgB;AAAA,IAC9B;AAAA,EACD;AAAA;AASM,IAAM,yBAKc;AAE3B,eAAe,WAAW,CACzB,IACA,WACA,KAME;AAAA,EACF,QAAQ,MAAM,YAAY,eACzB,WACA,KACA,wBAAwB,GAAG,CAC5B;AAAA,EACA,MAAM,IAAI,MAAM,cAAc,IAAI,KAAK,MAAM,SAAS,IAAI,UAAU;AAAA,EAEpE,MAAM,UAAU,UAAU,UAAU;AAAA,EACpC,MAAM,GACJ,WAAW,oBAAoB,EAC/B,OAAO;AAAA,IACP,WAAW,UAAU;AAAA,IACrB,YAAY,UAAU;AAAA,IACtB;AAAA,IACA,aAAa,EAAE;AAAA,IACf,kBAAkB,EAAE;AAAA,IACpB,eAAe,EAAE;AAAA,IACjB,eAAe,EAAE;AAAA,IACjB,aAAa,EAAE;AAAA,EAChB,CAAC,EACA,QAAQ;AAAA,EAEV,OAAO;AAAA,IACN,IAAI,EAAE;AAAA,IACN,YAAY,EAAE;AAAA,IACd,OAAO,EAAE;AAAA,IACT,YAAY,EAAE;AAAA,EACf;AAAA;AAKD,SAAS,kBAAkB,CAAC,KAA6B;AAAA,EACxD,MAAM,MAAM,IAAI;AAAA,EAChB,OAAO;AAAA,IACN,IAAI,WAAW;AAAA,IACf,YAAY,IAAI;AAAA,IAChB,MAAM,IAAI;AAAA,IACV,cAAc;AAAA,IACd,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,SAAS;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,IAAI;AAAA,MAChB,SAAS,IAAI,YAAY;AAAA,IAC1B;AAAA,IACA,WAAW,QAAQ,IAAI,MAAM,IAAI,QAAQ;AAAA,IACzC,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,WAAW;AAAA,IACX,WAAW;AAAA,IACX,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,YAAY;AAAA,EACb;AAAA;AASD,eAAsB,gBAAgB,CACrC,IACA,KAC6B;AAAA,EAC7B,MAAM,UAAU,mBAAmB,GAAG;AAAA,EACtC,QAAQ,MAAM,YAAY,eACzB,SACA,KACA,wBAAwB,GAAG,CAC5B;AAAA,EACA,MAAM,IAAI,MAAM,cAAc,IAAI,KAAK,MAAM,SAAS,IAAI,UAAU;AAAA,EACpE,MAAM,WAAW,MAAM,GACrB,WAAW,oBAAoB,EAC/B,OAAO;AAAA,IACP,WAAW;AAAA,IACX,YAAY,IAAI;AAAA,IAChB,SAAS;AAAA,IACT,aAAa,EAAE;AAAA,IACf,kBAAkB,EAAE;AAAA,IACpB,eAAe,EAAE;AAAA,IACjB,eAAe,EAAE;AAAA,IACjB,aAAa,EAAE;AAAA,EAChB,CAAC,EACA,UAAU,IAAI,EACd,wBAAwB;AAAA,EAC1B,OAAO;AAAA,IACN,IAAI,EAAE;AAAA,IACN,YAAY,EAAE;AAAA,IACd,OAAO,EAAE;AAAA,IACT,YAAY,EAAE;AAAA,IACd,YAAY,SAAS;AAAA,EACtB;AAAA;AAGD,eAAe,eAAe,CAC7B,IACA,WACgB;AAAA,EAChB,MAAM,GAAG,YAAY,EAAE,QAAQ,OAAO,OAAO;AAAA,IAC5C,MAAM,SAAS,MAAM,GACnB,YAAY,gBAAgB,EAC5B,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,cAAc,IAAI;AAAA,MAClB,SAAS,UAAU,UAAU;AAAA,MAC7B,WAAW;AAAA,MACX,cAAc;AAAA,IACf,CAAC,EAKA,MAAM,MAAM,KAAK,UAAU,EAAE,EAC7B,MAAM,UAAU,KAAK,SAAS,EAC9B,iBAAiB;AAAA,IACnB,IAAI,OAAO,OAAO,kBAAkB,CAAC,MAAM,GAAG;AAAA,MAC7C,QAAO,KAAK,2BAA2B;AAAA,QACtC,UAAU,UAAU;AAAA,QACpB,WAAW,UAAU;AAAA,QACrB,SAAS;AAAA,MACV,CAAC;AAAA,MACD;AAAA,IACD;AAAA,IACA,MAAM,GACJ,YAAY,UAAU,EACtB,IAAI;AAAA,MACJ,kBAAkB,IAAI;AAAA,MACtB,iBAAiB,IAAI;AAAA,MACrB,kBAAkB;AAAA,MAClB,YAAY;AAAA,MACZ,YAAY,IAAI;AAAA,IACjB,CAAC,EACA,MAAM,MAAM,KAAK,UAAU,UAAU,EACrC,QAAQ;AAAA,IAMV,eAAe;AAAA,GACf;AAAA;AAGF,eAAe,YAAY,CAC1B,IACA,WACA,KACA,SACgB;AAAA,EAChB,MAAM,UAAU,UAAU,UAAU;AAAA,EACpC,MAAM,SAAS,WAAW,IAAI;AAAA,EAC9B,MAAM,SAAS,SACZ,OACA,IAAI,KAAK,KAAK,IAAI,IAAI,iBAAiB,UAAU,OAAO,IAAI,IAAI;AAAA,EAEnE,MAAM,GAAG,YAAY,EAAE,QAAQ,OAAO,OAAO;AAAA,IAC5C,MAAM,SAAS,MAAM,GACnB,YAAY,gBAAgB,EAC5B,IAAI;AAAA,MACJ;AAAA,MACA,iBAAiB,UAAU,IAAI;AAAA,MAC/B,QAAQ,SAAS,SAAS;AAAA,MAC1B,WAAW,SAAS,IAAI,OAAS;AAAA,MACjC,WAAW;AAAA,MACX,cAAc;AAAA,IACf,CAAC,EAGA,MAAM,MAAM,KAAK,UAAU,EAAE,EAC7B,MAAM,UAAU,KAAK,SAAS,EAC9B,iBAAiB;AAAA,IACnB,IAAI,OAAO,OAAO,kBAAkB,CAAC,MAAM,GAAG;AAAA,MAC7C,QAAO,KAAK,2BAA2B;AAAA,QACtC,UAAU,UAAU;AAAA,QACpB,WAAW,UAAU;AAAA,QACrB,SAAS;AAAA,MACV,CAAC;AAAA,MACD;AAAA,IACD;AAAA,IAKA,MAAM,YAAY,MAAM;AAAA;AAAA;AAAA;AAAA,mBAIP,QAAQ,MAAM,GAAG,GAAG;AAAA;AAAA,gBAEvB,IAAI;AAAA;AAAA,IAEhB,QAAQ,EAAE;AAAA,IACZ,MAAM,cACL,UAAU,KAAK,IAAI,oBAAoB,IAAI,mBAAmB;AAAA,IAC/D,MAAM,oBAAoB,eAAe;AAAA,IAEzC,IAAI,mBAAmB;AAAA,MAItB,MAAM,GACJ,YAAY,UAAU,EACtB,IAAI;AAAA,QACJ,QAAQ;AAAA,QACR,mBAAmB,IAAI;AAAA,QACvB,YAAY,IAAI;AAAA,MACjB,CAAC,EACA,MAAM,MAAM,KAAK,IAAI,EAAE,EACvB,QAAQ;AAAA,MACV,QAAO,KACN,+DACA;AAAA,QACC,SAAS,IAAI;AAAA,QACb,UAAU;AAAA,MACX,CACD;AAAA,IACD;AAAA,GACA;AAAA;AA0BF,eAAe,aAAa,CAC3B,IACA,OACA,WACA,SACkB;AAAA,EAClB,IAAI,MAAM,eAAe;AAAA,IACxB,MAAM,eAAe;AAAA,IACrB,OAAO;AAAA,EACR;AAAA,EACA,MAAM,gBAAgB;AAAA,EAKtB,MAAM,eAAe,aAAa,IAAI,OAAO,WAAW,OAAO;AAAA,EAC/D,MAAM,eAAe;AAAA,EACrB,IAAI;AAAA,IACH,OAAO,MAAM;AAAA,YACZ;AAAA,IACD,IAAI,MAAM,iBAAiB;AAAA,MAAc,MAAM,eAAe;AAAA;AAAA;AAIhE,eAAe,YAAY,CAC1B,IACA,OACA,WACA,SACkB;AAAA,EAClB,IAAI,eAAe;AAAA,EACnB,IAAI;AAAA,IACH,IAAI,iBAAiB;AAAA,IACrB,UAAS;AAAA,MAMR,IAAI,CAAC,MAAM;AAAA,QAAS;AAAA,MACpB,MAAM,eAAe;AAAA,MACrB,MAAM,SAAS,MAAM,qBACpB,IACA,OACA,WACA,cACD;AAAA,MACA,gBAAgB,OAAO;AAAA,MAQvB,IAAI,CAAC,MAAM,gBAAgB,CAAC,OAAO;AAAA,QAAa;AAAA,MAChD,iBAAiB;AAAA,IAClB;AAAA,YACC;AAAA,IACD,MAAM,gBAAgB;AAAA;AAAA,EAEvB,OAAO;AAAA;AAmCR,eAAe,oBAAoB,CAClC,IACA,OACA,WACA,SACuB;AAAA,EAGvB,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK,MAAM,aAAa,UAAU,CAAC;AAAA,EACjE,MAAM,cAAc,aAAa;AAAA,EACjC,QAAQ,UAAU,WAAW,gBAAgB,MAAM,GACjD,YAAY,EACZ,QAAQ,OAAO,OAAO;AAAA,IACtB,MAAM,OAAO,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAOT,KAAI,IAAI,SAAS;AAAA,MACxB,QAAQ,EAAE;AAAA,IACb,MAAM,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAOX,KAAI,IAAI,WAAW;AAAA,MAC1B,QAAQ,EAAE;AAAA,IAEb,MAAM,OAAO,CAAC,GAAG,KAAK,MAAM,GAAG,OAAO,IAAI;AAAA,IAC1C,IAAI,KAAK,WAAW,GAAG;AAAA,MACtB,OAAO,EAAE,UAAU,MAAM,WAAW,GAAG,aAAa,EAAE;AAAA,IACvD;AAAA,IASA,MAAM,MAAM,IAAI;AAAA,IAChB,MAAM,YAAY,IAAI,KAAK,IAAI,QAAQ,IAAI,cAAc;AAAA,IACzD,MAAM,GACJ,YAAY,gBAAgB,EAC5B,IAAI;AAAA,MACJ,WAAW;AAAA,MACX,cAAc;AAAA,MACd,iBAAiB;AAAA,IAClB,CAAC,EACA,MACA,MACA,MACA,KAAK,IAAI,CAAC,MAAM,EAAE,EAAE,CACrB,EACC,QAAQ;AAAA,IACV,OAAO;AAAA,MACN,UAAU;AAAA,MACV,WAAW,KAAK,KAAK;AAAA,MACrB,aAAa,OAAO,KAAK;AAAA,IAC1B;AAAA,GACA;AAAA,EAEF,IAAI,SAAS,WAAW,GAAG;AAAA,IAC1B,OAAO,EAAE,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG,aAAa,MAAM;AAAA,EACrE;AAAA,EAEA,MAAM,UAAU,IAAI;AAAA,EACpB,WAAW,OAAO,UAAU;AAAA,IAC3B,MAAM,MAAM,QAAQ,IAAI,IAAI,UAAU;AAAA,IACtC,IAAI;AAAA,MAAK,IAAI,KAAK,GAAG;AAAA,IAChB;AAAA,cAAQ,IAAI,IAAI,YAAY,CAAC,GAAG,CAAC;AAAA,EACvC;AAAA,EAEA,MAAM,SAAS,MAAM,KAAK,QAAQ,KAAK,CAAC;AAAA,EACxC,MAAM,OAAO,MAAM,GACjB,WAAW,UAAU,EACrB,UAAU,EACV,MAAM,MAAM,MAAM,MAAM,EACxB,QAAQ;AAAA,EACV,MAAM,UAAU,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAAA,EAElD,IAAI,aAAa;AAAA,EACjB,IAAI,WAAW;AAAA,EACf,MAAM,cAAwB,CAAC;AAAA,EAC/B,WAAW,SAAS,QAAQ;AAAA,IAC3B,MAAM,MAAM,QAAQ,IAAI,KAAK;AAAA,IAE7B,MAAM,OAAO,QAAQ,IAAI,KAAK;AAAA,IAC9B,IAAI,CAAC,OAAO,IAAI,WAAW,UAAU;AAAA,MACpC,YAAY,KAAK;AAAA,MACjB,YAAY,KAAK,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAAA,MACzC;AAAA,IACD;AAAA,IACA,cAAc,KAAK;AAAA,IACnB,cAAc,IAAI,OAAO,KAAK,IAAI;AAAA,EACnC;AAAA,EAEA,IAAI,YAAY,SAAS,GAAG;AAAA,IAI3B,MAAM,GACJ,YAAY,gBAAgB,EAC5B,IAAI,EAAE,iBAAiB,IAAI,MAAQ,WAAW,MAAM,cAAc,KAAK,CAAC,EACxE,MAAM,MAAM,MAAM,WAAW,EAC7B,QAAQ;AAAA,EACX;AAAA,EASA,MAAM,oBAAoB,KAAK,IAC9B,GAAG,SAAS,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,CACxD;AAAA,EACA,MAAM,WAAW,OAAO,OACvB,CAAC,KAAK,OAAO,OAAO,MAAM,UAAU,IAAI,EAAE,GAAG,YAAY,IACzD,CACD;AAAA,EACA,MAAM,cAAc,OAAO,OAC1B,CAAC,KAAK,OAAO,OAAO,QAAQ,IAAI,EAAE,GAAG,eAAe,IACpD,CACD;AAAA,EACA,QAAO,KAAK,uBAAuB;AAAA,IAClC,OAAO;AAAA,IACP;AAAA,IACA,SAAS,SAAS;AAAA,IAClB;AAAA,IACA;AAAA,IACA,0BAA0B,KAAK,IAAI,IAAI;AAAA,IACvC,WAAW;AAAA,IACX;AAAA,EACD,CAAC;AAAA,EAED,OAAO;AAAA,IACN,SAAS,SAAS;AAAA,IAClB;AAAA,IACA;AAAA,IACA,aAAa,aAAa,aAAa,eAAe;AAAA,EACvD;AAAA;AAaD,SAAS,aAAa,CACrB,IACA,OACA,KACA,MACO;AAAA,EACP,IAAI,KAAK,MAAM,UAAU,IAAI,IAAI,EAAE;AAAA,EACnC,IAAI,CAAC,IAAI;AAAA,IACR,KAAK,EAAE,KAAK,OAAO,CAAC,GAAG,UAAU,EAAE;AAAA,IACnC,MAAM,UAAU,IAAI,IAAI,IAAI,EAAE;AAAA,EAC/B,EAAO;AAAA,IACN,GAAG,MAAM;AAAA;AAAA,EAEV,GAAG,MAAM,KAAK,GAAG,IAAI;AAAA,EACrB,QAAQ,IAAI,OAAO,IAAI,EAAE;AAAA;AAW1B,SAAS,OAAO,CACf,IACA,OACA,OACO;AAAA,EACP,MAAM,KAAK,MAAM,UAAU,IAAI,KAAK;AAAA,EACpC,IAAI,CAAC;AAAA,IAAI;AAAA,EACT,MAAM,MAAM,GAAG,IAAI,eAAe;AAAA,EAClC,OACC,MAAM,WACN,GAAG,IAAI,WAAW,YAClB,GAAG,WAAW,OACd,GAAG,MAAM,SAAS,GACjB;AAAA,IACD,MAAM,MAAM,GAAG,MAAM,MAAM;AAAA,IAC3B,IAAI,CAAC;AAAA,MAAK;AAAA,IACV,GAAG;AAAA,IACH,MAAM,aAAa,OAAO,IAAI,OAAO,IAAI,GAAG;AAAA,IAC5C,MAAM,aAAa,IAAI,UAAU;AAAA,IAC5B,WAAW,QAAQ,MAAM;AAAA,MAC7B,MAAM,aAAa,OAAO,UAAU;AAAA,KACpC;AAAA,EACF;AAAA;AAKD,eAAe,MAAM,CACpB,IACA,OACA,IACA,KACgB;AAAA,EAChB,IAAI;AAAA,IACH,MAAM,SAAS,MAAM,YAAY,IAAI,KAAK,GAAG,GAAG;AAAA,IAChD,IAAI,OAAO,IAAI;AAAA,MACd,MAAM,gBAAgB,IAAI,GAAG;AAAA,IAC9B,EAAO;AAAA,MACN,MAAM,MAAM,OAAO,SAAS,QAAQ,OAAO,cAAc;AAAA,MACzD,MAAM,aAAa,IAAI,KAAK,GAAG,KAAK,GAAG;AAAA;AAAA,IAEvC,OAAO,KAAK;AAAA,IACb,QAAO,MAAM,4BAA4B;AAAA,MACxC,UAAU,IAAI;AAAA,MACd,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACvD,CAAC;AAAA,IACD,MAAM,aACL,IACA,KACA,GAAG,KACH,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAChD;AAAA,YACC;AAAA,IACD,GAAG;AAAA,IACH,QAAQ,IAAI,OAAO,GAAG,IAAI,EAAE;AAAA;AAAA;AAmB9B,eAAe,YAAY,CAAC,IAAqC;AAAA,EAIhE,MAAM,gBAAgB,EAAE;AAAA,EACxB,MAAM;AAAA;AAAA;AAAA,GAGJ,QAAQ,EAAE;AAAA,EACZ,MAAM;AAAA;AAAA;AAAA,GAGJ,QAAQ,EAAE;AAAA,EACZ,MAAM;AAAA;AAAA;AAAA,GAGJ,QAAQ,EAAE;AAAA,EACZ,MAAM;AAAA;AAAA;AAAA,GAGJ,QAAQ,EAAE;AAAA;AAGb,eAAsB,YAAY,CACjC,MAC+B;AAAA,EAC/B,MAAM,YAAY,WAAW,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE;AAAA,EACnE,MAAM,KAAK,YAAY;AAAA,EACvB,MAAM,QAAsB;AAAA,IAC3B,SAAS;AAAA,IACT,WAAW,IAAI;AAAA,IACf,eAAe;AAAA,IACf,cAAc;AAAA,IACd,cAAc;AAAA,IACd,cAAc,IAAI;AAAA,EACnB;AAAA,EACA,MAAM,iBAAiB,MAAM,kBAAkB;AAAA,EAC/C,MAAM,sBAAsB,MAAM,uBAAuB,KAAK;AAAA,EAE9D,QAAO,KAAK,qBAAqB,EAAE,IAAI,UAAU,CAAC;AAAA,EAKlD,MAAM,YAAY,kBAAkB;AAAA,EACpC,MAAM,UAAU,MAAM,OACrB,uBACA,MAAM;AAAA,IACL,IAAI,CAAC,MAAM;AAAA,MAAS;AAAA,IACf,cAAc,IAAI,OAAO,WAAW,QAAQ,EAAE,MAAM,CAAC,QACzD,QAAO,MAAM,0BAA0B;AAAA,MACtC,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACvD,CAAC,CACF;AAAA,KAED,EAAE,kBAAkB,UAAU,CAC/B;AAAA,EACA,MAAM,cAAc,MAAM,OACzB,oBACA,MAAM;AAAA,IACL,IAAI,CAAC,MAAM;AAAA,MAAS;AAAA,IAMf,cAAc,IAAI,OAAO,WAAW,SAAS,EAAE,MAAM,CAAC,QAC1D,QAAO,MAAM,0BAA0B;AAAA,MACtC,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACvD,CAAC,CACF;AAAA,KAED,EAAE,kBAAkB,UAAU,CAC/B;AAAA,EAKA,QAAO,KAAK,sCAAsC;AAAA,IACjD,UAAU,CAAC,uBAAuB,kBAAkB;AAAA,IACpD,IAAI,cAAc,SAAS;AAAA,EAC5B,CAAC;AAAA,EAID,MAAM,OAAO,YAAY,MAAM;AAAA,IAC9B,IAAI,CAAC,MAAM;AAAA,MAAS;AAAA,IACf,cAAc,IAAI,OAAO,WAAW,MAAM,EAAE,MAAM,CAAC,QACvD,QAAO,MAAM,+BAA+B;AAAA,MAC3C,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACvD,CAAC,CACF;AAAA,KACE,cAAc;AAAA,EAGZ,cAAc,IAAI,OAAO,WAAW,SAAS;AAAA,EAGlD,MAAM,YAAY,YAAY,MAAM;AAAA,IACnC,IAAI,CAAC,MAAM;AAAA,MAAS;AAAA,IACf,aAAa,EAAE,EAAE,MAAM,CAAC,QAC5B,QAAO,MAAM,8BAA8B;AAAA,MAC1C,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACvD,CAAC,CACF;AAAA,KACE,mBAAmB;AAAA,EAGtB,MAAM,gBAAgB,YAAY,MAAM;AAAA,IACvC,IAAI,CAAC,MAAM;AAAA,MAAS;AAAA,IACf,qBAAqB,EAAE,EAAE,MAAM,CAAC,QACpC,QAAO,MAAM,0CAA0C;AAAA,MACtD,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACvD,CAAC,CACF;AAAA,KACE,yBAAyB;AAAA,EAE5B,OAAO,YAAY;AAAA,IAIlB,MAAM,UAAU;AAAA,IAChB,cAAc,IAAI;AAAA,IAClB,cAAc,SAAS;AAAA,IACvB,cAAc,aAAa;AAAA,IAC3B,MAAM,QAAQ;AAAA,IACd,MAAM,YAAY;AAAA,IAElB,MAAM,cAAc,IAAI,IAAI,MAAM,YAAY;AAAA,IAC9C,MAAM,cAAc,YAAY;AAAA,IAIhC,MAAM,gBAAgB,MAAM,gBAAgB,QAAQ,QAAQ,GAAG,MAC9D,MAAM,EACP;AAAA,IACA,MAAM,UAAU,QAAQ,IAAI,CAAC,cAAc,GAAG,WAAW,CAAC;AAAA,IAK1D,MAAM,aACL,MAAM,uBAAuB,yBAAyB;AAAA,IACvD,IAAI,WAAW;AAAA,IACf,IAAI;AAAA,IACJ,MAAM,UAAU,IAAI,QAAc,CAAC,YAAY;AAAA,MAC9C,QAAQ,WAAW,MAAM;AAAA,QACxB,WAAW;AAAA,QACX,QAAQ;AAAA,SACN,UAAU;AAAA,KACb;AAAA,IACD,MAAM,QAAQ,KAAK,CAAC,SAAS,OAAO,CAAC;AAAA,IACrC,aAAa,KAAK;AAAA,IAElB,MAAM,YAAY,WAAW,MAAM,aAAa,OAAO;AAAA,IACvD,MAAM,UAAU,cAAc;AAAA,IAC9B,QAAO,KAAK,qBAAqB;AAAA,MAChC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACD,CAAC;AAAA;AAAA;",
17
- "debugId": "12212061F8671F0B64756E2164756E21",
16
+ "mappings": ";AAAA;AACA,mBAAS;AACT;AAAA;AAAA;AAAA;AAOA;AACA;AACA,mBAAS;AACT;AACA;AAAA;AAAA;AAIA,gBAAsB;;;ACjBtB;AAEA;;;ACqBA,SAAS,OAAO,CAAC,SAAwC;AAAA,EACxD,OAAQ,SAAwC,UAAU,YACvD,YACA;AAAA;AAGG,SAAS,gBAAgB,CAC/B,WACA,MACoD;AAAA,EACpD,MAAM,QAAQ;AAAA,IACb,aAAa;AAAA,IACb,MAAM,UAAU;AAAA,IAChB,QAAQ,eAAe,QAAQ,UAAU,OAAO;AAAA,IAChD,IAAI,UAAU;AAAA,IACd,MAAM,IAAI,KAAK,UAAU,UAAU,EAAE,YAAY;AAAA,IACjD,iBAAiB;AAAA,IACjB,MAAM,UAAU;AAAA,EACjB;AAAA,EACA,OAAO;AAAA,IACN,MAAM,KAAK,UAAU,KAAK;AAAA,IAC1B,SAAS;AAAA,MACR,gBAAgB;AAAA,IACjB;AAAA,EACD;AAAA;;;AC/CD;AAcA,SAAS,aAAa,CAAC,KAA6B;AAAA,EACnD,MAAM,MAAM,IAAI;AAAA,EAChB,IAAI,IAAI,UAAU;AAAA,IAEjB,OAAO,cAAc,OAAO,KAAK,IAAI,UAAU,QAAQ,CAAC;AAAA,EACzD;AAAA,EACA,OAAO,IAAI,SAAS;AAAA;AAGd,SAAS,eAAe,CAC9B,WACA,KACoD;AAAA,EACpD,MAAM,OAAO,KAAK,UAAU;AAAA,IAC3B,QAAQ;AAAA,SACH,UAAU;AAAA,MACd,OAAO,UAAU;AAAA,MACjB,WAAW,UAAU;AAAA,IACtB;AAAA,EACD,CAAC;AAAA,EACD,MAAM,UAAkC;AAAA,IACvC,gBAAgB;AAAA,EACjB;AAAA,EACA,MAAM,QAAQ,cAAc,GAAG;AAAA,EAC/B,IAAI;AAAA,IAAO,QAAQ,gBAAgB,UAAU;AAAA,EAC7C,OAAO,EAAE,MAAM,QAAQ;AAAA;;;ACrBjB,IAAM,kBAAkB;AAExB,SAAS,YAAY,CAAC,WAG3B;AAAA,EACD,MAAM,QAAQ;AAAA,IACb,MAAM,UAAU;AAAA,IAChB,MAAM,UAAU;AAAA,IAChB,IAAI,UAAU;AAAA,IACd,IAAI,IAAI,KAAK,UAAU,UAAU,EAAE,QAAQ;AAAA,IAC3C,GAAG;AAAA,EACJ;AAAA,EACA,OAAO;AAAA,IACN,MAAM,KAAK,UAAU,CAAC,KAAK,CAAC;AAAA,IAC5B,SAAS;AAAA,MACR,gBAAgB;AAAA,IACjB;AAAA,EACD;AAAA;;;ACrBM,SAAS,QAAQ,CACvB,WACA,KACoD;AAAA,EACpD,MAAM,MAAM,IAAI;AAAA,EAOhB,MAAM,UAAkC;AAAA,IACvC,gBAAgB,IAAI,eAAe;AAAA,OAC/B,IAAI,WAAW,CAAC;AAAA,EACrB;AAAA,EACA,IAAI,IAAI,aAAa,YAAY,IAAI,OAAO;AAAA,IAC3C,QAAQ,gBAAgB,UAAU,IAAI;AAAA,EACvC,EAAO,SAAI,IAAI,aAAa,WAAW,IAAI,WAAW;AAAA,IACrD,QAAQ,gBAAgB,SAAS,IAAI;AAAA,EACtC;AAAA,EACA,OAAO;AAAA,IACN,MAAM,KAAK,UAAU,UAAU,OAAO;AAAA,IACtC;AAAA,EACD;AAAA;;;ACtCD;AA0BO,SAAS,qBAAqB,CACpC,WACA,eACoD;AAAA,EACpD,MAAM,aAAa,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI;AAAA,EAC/C,MAAM,UAAmC;AAAA,IACxC,MAAM,UAAU;AAAA,IAChB,WAAW,IAAI,KAAK,aAAa,IAAI,EAAE,YAAY;AAAA,IACnD,MAAM,UAAU;AAAA,EACjB;AAAA,EACA,MAAM,OAAO,KAAK,UAAU,OAAO;AAAA,EACnC,MAAM,aAAa,KAAK,MAAM,eAAe;AAAA,IAC5C,IAAI,UAAU;AAAA,IACd,kBAAkB;AAAA,EACnB,CAAC;AAAA,EACD,OAAO;AAAA,IACN;AAAA,IACA,SAAS;AAAA,MACR,gBAAgB;AAAA,SACb;AAAA,IACJ;AAAA,EACD;AAAA;;;AC/CD,0BAAS;AAiBT,SAAS,cAAa,CAAC,KAA6B;AAAA,EACnD,MAAM,MAAM,IAAI;AAAA,EAKhB,IAAI,IAAI,UAAU;AAAA,IAKjB,OAAO,eAAc,OAAO,KAAK,IAAI,UAAU,QAAQ,CAAC;AAAA,EACzD;AAAA,EACA,OAAO,IAAI,SAAS;AAAA;AAGd,SAAS,YAAY,CAC3B,WACA,KACoD;AAAA,EACpD,MAAM,OAAO,KAAK,UAAU;AAAA,IAC3B,SAAS,UAAU;AAAA,IACnB,SAAS;AAAA,MACR,gBAAgB,UAAU;AAAA,IAC3B;AAAA,EACD,CAAC;AAAA,EACD,MAAM,UAAkC;AAAA,IACvC,gBAAgB;AAAA,EACjB;AAAA,EACA,MAAM,QAAQ,eAAc,GAAG;AAAA,EAC/B,IAAI;AAAA,IAAO,QAAQ,gBAAgB,UAAU;AAAA,EAC7C,OAAO,EAAE,MAAM,QAAQ;AAAA;;;ANjCxB,SAAS,SAAS,CACjB,WACA,KACA,eACoB;AAAA,EACpB,QAAQ,IAAI;AAAA,SACN;AAAA,MACJ,OAAO,aAAa,SAAS;AAAA,SACzB;AAAA,MACJ,OAAO,aAAa,WAAW,GAAG;AAAA,SAC9B;AAAA,MACJ,OAAO,gBAAgB,WAAW,GAAG;AAAA,SACjC;AAAA,MACJ,OAAO,iBAAiB,WAAW,GAAG;AAAA,SAClC;AAAA,MACJ,OAAO,SAAS,WAAW,GAAG;AAAA,SAC1B;AAAA,MACJ,OAAO,sBAAsB,WAAW,aAAa;AAAA;AAAA,MAErD,OAAO,KAAK,6DAA6D;AAAA,QACxE,QAAQ,IAAI;AAAA,QACZ,WAAW,IAAI;AAAA,MAChB,CAAC;AAAA,MACD,OAAO,sBAAsB,WAAW,aAAa;AAAA;AAAA;AAejD,SAAS,cAAc,CAC7B,WACA,KACA,eACoB;AAAA,EACpB,MAAM,SAAS,UAAU,WAAW,KAAK,aAAa;AAAA,EACtD,MAAM,aAAa,uBAAuB,UAAU,IAAI,OAAO,IAAI;AAAA,EACnE,IAAI,YAAY;AAAA,IACf,OAAO,UAAU,KAAK,OAAO,YAAY,WAAW;AAAA,EACrD;AAAA,EACA,OAAO;AAAA;;;AOjDR,mBAAS;AAIT,IAAI,UAAU;AAOd,SAAS,UAAU,CAAC,MAAyB,QAAQ,KAAyB;AAAA,EAC7E,MAAM,OAAO,IAAI,sBAAsB,KAAK;AAAA,EAC5C,OAAO,QAAQ,KAAK,SAAS,IAAI,OAAO;AAAA;AAMlC,SAAS,cAAc,GAAS;AAAA,EACtC,IAAI,CAAC,WAAW;AAAA,IAAG;AAAA,EACnB,WAAW;AAAA;;;ACnCZ;AACA;AAEA,mBAAS;AACT;AASA,IAAM,mBAAmB;AACzB,IAAM,sBAAsB;AAC5B,IAAM,cAAc;AAOpB,eAAsB,eAAe,CACpC,KACA,MACuB;AAAA,EACvB,IAAI;AAAA,EACJ,IAAI;AAAA,IACH,SAAS,IAAI,IAAI,GAAG;AAAA,IACnB,MAAM;AAAA,IACP,OAAO;AAAA;AAAA,EAER,IAAI,OAAO,aAAa;AAAA,IAAU,OAAO;AAAA,EAEzC,IAAI,CAAC,mBAAmB,GAAG;AAAA,IAC1B,IAAI;AAAA,IACJ,IAAI;AAAA,MACH,UAAU,MAAM,mBAAmB,GAAG;AAAA,MACrC,MAAM;AAAA,MACP,OAAO;AAAA;AAAA,IAER,IAAI;AAAA,MAAS,OAAO;AAAA,EACrB;AAAA,EAEA,MAAM,MAAM,OAAO;AAAA,EACnB,MAAM,OACL,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI;AAAA,EAC/D,MAAM,UAAU,MAAM,WAAW,IAAI;AAAA,EACrC,MAAM,YAAY,MAAM,aAAa;AAAA,EAErC,OAAO,IAAI,QAAqB,CAAC,YAAY;AAAA,IAC5C,MAAM,OAAmC,CAAC;AAAA,IAC1C,IAAI,UAAU;AAAA,IACd,MAAM,SAAS,CAAC,YAAyB;AAAA,MACxC,IAAI;AAAA,QAAS;AAAA,MACb,UAAU;AAAA,MACV,aAAa,KAAK;AAAA,MAClB,IAAI;AAAA,QACH,KAAK,QAAQ,QAAQ;AAAA,QACpB,MAAM;AAAA,MAGR,QAAQ,OAAO;AAAA;AAAA,IAEhB,MAAM,QAAQ,WAAW,MAAM,OAAO,IAAI,GAAG,SAAS;AAAA,IACtD,IAAI;AAAA,IACJ,IAAI;AAAA,MACH,QAAQ,QAAQ;AAAA,QACf;AAAA,QACA,MAAM,OAAO,OAAO,IAAI,KAAK;AAAA,WACzB,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE,YAAY,KAAK;AAAA,QAGzC,oBAAoB;AAAA,MACrB,CAAC;AAAA,MACA,MAAM;AAAA,MACP,OAAO,IAAI;AAAA,MACX;AAAA;AAAA,IAED,KAAK,SAAS;AAAA,IACd,MAAM,KAAK,iBAAiB,MAAM;AAAA,MACjC,IAAI;AAAA,QACH,MAAM,UAAU,IAAI,KAAK,MAAM,mBAAmB,EAAE,QAAQ;AAAA,QAC5D,OAAO,OAAO,MAAM,QAAQ,QAAQ,CAAC,IAAI,OAAO,OAAO;AAAA,QACtD,MAAM;AAAA,QACP,OAAO,IAAI;AAAA;AAAA,KAEZ;AAAA,IACD,MAAM,KAAK,SAAS,MAAM,OAAO,IAAI,CAAC;AAAA,GACtC;AAAA;AAQF,eAAsB,oBAAoB,CACzC,IACA,MACgB;AAAA,EAChB,MAAM,QAAQ,MAAM,SAAS;AAAA,EAC7B,MAAM,MAAM,MAAM,GAChB,WAAW,UAAU,EACrB,OAAO,CAAC,MAAM,KAAK,CAAC,EACpB,MAAM,UAAU,KAAK,QAAQ,EAC7B,MAAM,OAAO,QAAQ,SAAS,EAC9B,MAAM,CAAC,OACP,GAAG,GAAG;AAAA,IACL,GAAG,4BAA4B,MAAM,IAAI;AAAA,IACzC,GACC,4BACA,KACA,qCAA2C,sBAC5C;AAAA,EACD,CAAC,CACF,EACC,QAAQ,6CAA6C,EACrD,MAAM,WAAW,EACjB,QAAQ;AAAA,EAEV,MAAM,cAAc,IAAI;AAAA,EACxB,aAAa,IAAI,SAAS,KAAK;AAAA,IAC9B,IAAI;AAAA,IACJ,IAAI;AAAA,MACH,SAAS,IAAI,IAAI,GAAG,EAAE;AAAA,MACrB,MAAM;AAAA,MACP;AAAA;AAAA,IAED,MAAM,QAAQ,YAAY,IAAI,MAAM,KAAK,EAAE,KAAK,KAAK,CAAC,EAAE;AAAA,IACxD,MAAM,IAAI,KAAK,EAAE;AAAA,IACjB,YAAY,IAAI,QAAQ,KAAK;AAAA,EAC9B;AAAA,EAEA,YAAY,UAAU,KAAK,UAAU,aAAa;AAAA,IACjD,MAAM,UAAU,MAAM,MAAM,GAAG;AAAA,IAC/B,MAAM,GACJ,YAAY,UAAU,EACtB,IAAI;AAAA,MACJ,0BAA0B;AAAA,MAC1B,0BAA0B,IAAI;AAAA,IAC/B,CAAC,EACA,MAAM,MAAM,MAAM,GAAG,EACrB,QAAQ;AAAA,IACV,QAAO,MAAM,kCAAkC;AAAA,MAC9C;AAAA,MACA,WAAW,SAAS,YAAY,KAAK;AAAA,IACtC,CAAC;AAAA,EACF;AAAA;;;AT3GD,IAAM,aAAa;AACnB,IAAM,aAAa;AACnB,IAAM,kBAAkB,CAAC,IAAI,KAAK,KAAK,MAAM,OAAO,OAAO,MAAM;AACjE,IAAM,oBAAoB;AAcnB,IAAM,yBAAiC,wBAAwB;AAC/D,IAAM,iBAAyB,yBAAyB;AAuC/D,SAAS,gBAAgB,CAAC,SAAyB;AAAA,EAElD,OAAO,gBAAgB,KAAK,IAAI,SAAS,gBAAgB,SAAS,CAAC;AAAA;AAOpE,IAAM,sBAAsB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAeA,SAAS,WAAW,CAAC,SAA0B;AAAA,EAC9C,MAAM,OAAO,QAAQ,YAAY;AAAA,EAEjC,IAAI,SAAS;AAAA,IAAW,OAAO;AAAA,EAC/B,IAAI,SAAS,QAAQ,SAAS;AAAA,IAAO,OAAO;AAAA,EAE5C,IAAI,qBAAqB,KAAK,IAAI;AAAA,IAAG,OAAO;AAAA,EAC5C,IAAI,qBAAqB,KAAK,IAAI;AAAA,IAAG,OAAO;AAAA,EAC5C,IAAI,kBAAkB,KAAK,IAAI;AAAA,IAAG,OAAO;AAAA,EAGzC,MAAM,SAAS,KAAK,MAAM,eAAe;AAAA,EACzC,IAAI,QAAQ;AAAA,IAEX,MAAM,QAAQ,OAAO;AAAA,IAErB,IAAI,uBAAuB,KAAK,KAAK,GAAG;AAAA,MACvC,WAAW,KAAK;AAAA,QAAqB,IAAI,EAAE,KAAK,KAAK;AAAA,UAAG,OAAO;AAAA,IAChE;AAAA,IAEA,MAAM,MAAM,MAAM,MAAM,mCAAmC;AAAA,IAC3D,IAAI,KAAK;AAAA,MAER,MAAM,IAAI,OAAO,SAAS,IAAI,IAAK,EAAE;AAAA,MAErC,MAAM,IAAI,OAAO,SAAS,IAAI,IAAK,EAAE;AAAA,MACrC,MAAM,SAAS,GAAI,KAAK,IAAK,OAAQ,IAAI,OAAS,KAAK,IAAK,OAAQ,IAAI;AAAA,MACxE,WAAW,KAAK;AAAA,QAAqB,IAAI,EAAE,KAAK,MAAM;AAAA,UAAG,OAAO;AAAA,IACjE;AAAA,IACA,OAAO;AAAA,EACR;AAAA,EAIA,MAAM,QAAQ,KAAK,MAAM,iBAAiB;AAAA,EAC1C,IAAI,OAAO;AAAA,IAEV,MAAM,QAAQ,MAAM;AAAA,IACpB,IAAI,uBAAuB,KAAK,KAAK,GAAG;AAAA,MACvC,WAAW,KAAK;AAAA,QAAqB,IAAI,EAAE,KAAK,KAAK;AAAA,UAAG,OAAO;AAAA,IAChE;AAAA,IACA,MAAM,MAAM,MAAM,MAAM,mCAAmC;AAAA,IAC3D,IAAI,KAAK;AAAA,MAER,MAAM,IAAI,OAAO,SAAS,IAAI,IAAK,EAAE;AAAA,MAErC,MAAM,IAAI,OAAO,SAAS,IAAI,IAAK,EAAE;AAAA,MACrC,MAAM,SAAS,GAAI,KAAK,IAAK,OAAQ,IAAI,OAAS,KAAK,IAAK,OAAQ,IAAI;AAAA,MACxE,WAAW,KAAK;AAAA,QAAqB,IAAI,EAAE,KAAK,MAAM;AAAA,UAAG,OAAO;AAAA,IACjE;AAAA,IACA,OAAO;AAAA,EACR;AAAA,EAEA,WAAW,KAAK,qBAAqB;AAAA,IACpC,IAAI,EAAE,KAAK,IAAI;AAAA,MAAG,OAAO;AAAA,EAC1B;AAAA,EACA,OAAO;AAAA;AASR,SAAS,eAAe,CAAC,KAAsB;AAAA,EAC9C,IAAI;AAAA,EACJ,IAAI;AAAA,IACH,SAAS,IAAI,IAAI,GAAG;AAAA,IACnB,MAAM;AAAA,IACP,OAAO;AAAA;AAAA,EAER,IAAI,OAAO,aAAa,WAAW,OAAO,aAAa,UAAU;AAAA,IAChE,OAAO;AAAA,EACR;AAAA,EAGA,MAAM,MAAM,OAAO,SAAS,YAAY;AAAA,EACxC,MAAM,OACL,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI;AAAA,EAE/D,IAAI,SAAS;AAAA,IAAa,OAAO;AAAA,EACjC,OAAO,YAAY,IAAI;AAAA;AAIxB,IAAM,4BAA4B,KAAK;AAEhC,SAAS,kBAAkB,GAAY;AAAA,EAC7C,OAAO,QAAQ,IAAI,qCAAqC;AAAA;AAUzD,eAAe,gBAAgB,CAAC,UAA8C;AAAA,EAC7E,OAAO,UAAU,UAAU,EAAE,KAAK,KAAK,CAAC;AAAA;AAGzC,IAAI,gBAA6B;AAQ1B,SAAS,qBAAqB,CAAC,IAA8B;AAAA,EACnE,gBAAgB,MAAM;AAAA;AAGvB,IAAM,aAAa;AA6BnB,eAAsB,kBAAkB,CAAC,KAAqC;AAAA,EAC7E,IAAI,gBAAgB,GAAG,GAAG;AAAA,IACzB,OAAO,2CAA2C;AAAA,EACnD;AAAA,EAEA,IAAI;AAAA,EACJ,IAAI;AAAA,IACH,SAAS,IAAI,IAAI,GAAG;AAAA,IACnB,MAAM;AAAA,IACP,OAAO,yCAAyC;AAAA;AAAA,EAEjD,IAAI,OAAO,aAAa,WAAW,OAAO,aAAa,UAAU;AAAA,IAChE,OAAO,gDAAgD;AAAA,EACxD;AAAA,EAEA,MAAM,MAAM,OAAO,SAAS,YAAY;AAAA,EACxC,MAAM,WACL,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI;AAAA,EAE/D,IAAI;AAAA,EACJ,IAAI;AAAA,IACH,WAAW,MAAM,cAAc,QAAQ;AAAA,IACtC,OAAO,KAAK;AAAA,IACb,MAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IAC3D,OAAO,kDAAkD,QAAQ;AAAA;AAAA,EAElE,IAAI,SAAS,WAAW,GAAG;AAAA,IAC1B,OAAO,gEAAgE;AAAA,EACxE;AAAA,EACA,aAAa,aAAa,UAAU;AAAA,IACnC,IAAI,YAAY,OAAO,GAAG;AAAA,MACzB,OAAO,gEAAgE,WAAW;AAAA,IACnF;AAAA,EACD;AAAA,EACA,OAAO;AAAA;AAuBD,IAAM,oBAA4B;AASzC,eAAe,aAAa,CAC3B,KACA,MACA,SACA,WACsB;AAAA,EACtB,MAAM,QAAQ,YAAY,IAAI;AAAA,EAC9B,IAAI,SAAS;AAAA,EACb,IAAI,aAA4B;AAAA,EAChC,IAAI,QAAuB;AAAA,EAC3B,IAAI,KAAK;AAAA,EACT,IAAI,eAAe;AAAA,EACnB,IAAI,kBAAiD;AAAA,EACrD,IAAI;AAAA,IACH,SAAS,MAAM,IAAK,OAAO;AAAA,MAC1B,IAAI,CAAC,mBAAmB,GAAG;AAAA,QAC1B,MAAM,UAAU,MAAM,mBAAmB,MAAM;AAAA,QAC/C,IAAI,SAAS;AAAA,UACZ,QAAO,KAAK,oCAAoC;AAAA,YAC/C,KAAK;AAAA,YACL,QAAQ;AAAA,UACT,CAAC;AAAA,UACD,OAAO;AAAA,YACN,IAAI;AAAA,YACJ,YAAY;AAAA,YACZ,OAAO;AAAA,YACP,YAAY,KAAK,MAAM,YAAY,IAAI,IAAI,KAAK;AAAA,YAChD,cAAc;AAAA,YACd,iBAAiB;AAAA,UAClB;AAAA,QACD;AAAA,MACD;AAAA,MACA,IAAI,OAAO,mBAAmB;AAAA,QAC7B,OAAO;AAAA,UACN,IAAI;AAAA,UACJ;AAAA,UACA,OAAO,gCAAgC;AAAA,UACvC,YAAY,KAAK,MAAM,YAAY,IAAI,IAAI,KAAK;AAAA,UAChD,cAAc;AAAA,UACd,iBAAiB;AAAA,QAClB;AAAA,MACD;AAAA,MAEA,MAAM,MAAM,MAAM,MAAM,QAAQ;AAAA,QAC/B,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,QAAQ,YAAY,QAAQ,SAAS;AAAA,MACtC,CAAC;AAAA,MACD,aAAa,IAAI;AAAA,MAEjB,MAAM,WAAW,IAAI,QAAQ,IAAI,UAAU;AAAA,MAC3C,IAAI,IAAI,UAAU,OAAO,IAAI,SAAS,OAAO,UAAU;AAAA,QACtD,SAAS,IAAI,IAAI,UAAU,MAAM,EAAE,SAAS;AAAA,QAC5C;AAAA,MACD;AAAA,MAEA,KAAK,IAAI;AAAA,MAET,MAAM,MAAM,MAAM,IAAI,YAAY;AAAA,MAClC,MAAM,YAAY,IAAI,aAAa,OAAO,IAAI,MAAM,GAAG,IAAI,IAAI;AAAA,MAC/D,eAAe,OAAO,KAAK,SAAS,EAAE,SAAS,MAAM;AAAA,MACrD,kBAAkB,OAAO,YAAY,IAAI,QAAQ,QAAQ,CAAC;AAAA,MAC1D;AAAA,IACD;AAAA,IACC,OAAO,KAAK;AAAA,IACb,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA;AAAA,EAExD,OAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,KAAK,MAAM,YAAY,IAAI,IAAI,KAAK;AAAA,IAChD,cAAc,gBAAgB;AAAA,IAC9B;AAAA,EACD;AAAA;AASM,IAAM,yBAKc;AAE3B,eAAe,WAAW,CACzB,IACA,WACA,KAME;AAAA,EACF,QAAQ,MAAM,YAAY,eACzB,WACA,KACA,wBAAwB,GAAG,CAC5B;AAAA,EACA,MAAM,IAAI,MAAM,cAAc,IAAI,KAAK,MAAM,SAAS,IAAI,UAAU;AAAA,EAEpE,MAAM,UAAU,UAAU,UAAU;AAAA,EACpC,MAAM,GACJ,WAAW,oBAAoB,EAC/B,OAAO;AAAA,IACP,WAAW,UAAU;AAAA,IACrB,YAAY,UAAU;AAAA,IACtB;AAAA,IACA,aAAa,EAAE;AAAA,IACf,kBAAkB,EAAE;AAAA,IACpB,eAAe,EAAE;AAAA,IACjB,eAAe,EAAE;AAAA,IACjB,aAAa,EAAE;AAAA,EAChB,CAAC,EACA,QAAQ;AAAA,EAEV,OAAO;AAAA,IACN,IAAI,EAAE;AAAA,IACN,YAAY,EAAE;AAAA,IACd,OAAO,EAAE;AAAA,IACT,YAAY,EAAE;AAAA,EACf;AAAA;AAKD,SAAS,kBAAkB,CAAC,KAA6B;AAAA,EACxD,MAAM,MAAM,IAAI;AAAA,EAChB,OAAO;AAAA,IACN,IAAI,WAAW;AAAA,IACf,YAAY,IAAI;AAAA,IAChB,MAAM,IAAI;AAAA,IACV,cAAc;AAAA,IACd,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,SAAS;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT,YAAY,IAAI;AAAA,MAChB,SAAS,IAAI,YAAY;AAAA,IAC1B;AAAA,IACA,WAAW,QAAQ,IAAI,MAAM,IAAI,QAAQ;AAAA,IACzC,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,WAAW;AAAA,IACX,WAAW;AAAA,IACX,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,YAAY;AAAA,EACb;AAAA;AASD,eAAsB,gBAAgB,CACrC,IACA,KAC6B;AAAA,EAC7B,MAAM,UAAU,mBAAmB,GAAG;AAAA,EACtC,QAAQ,MAAM,YAAY,eACzB,SACA,KACA,wBAAwB,GAAG,CAC5B;AAAA,EACA,MAAM,IAAI,MAAM,cAAc,IAAI,KAAK,MAAM,SAAS,IAAI,UAAU;AAAA,EACpE,MAAM,WAAW,MAAM,GACrB,WAAW,oBAAoB,EAC/B,OAAO;AAAA,IACP,WAAW;AAAA,IACX,YAAY,IAAI;AAAA,IAChB,SAAS;AAAA,IACT,aAAa,EAAE;AAAA,IACf,kBAAkB,EAAE;AAAA,IACpB,eAAe,EAAE;AAAA,IACjB,eAAe,EAAE;AAAA,IACjB,aAAa,EAAE;AAAA,EAChB,CAAC,EACA,UAAU,IAAI,EACd,wBAAwB;AAAA,EAC1B,OAAO;AAAA,IACN,IAAI,EAAE;AAAA,IACN,YAAY,EAAE;AAAA,IACd,OAAO,EAAE;AAAA,IACT,YAAY,EAAE;AAAA,IACd,YAAY,SAAS;AAAA,EACtB;AAAA;AAGD,eAAe,eAAe,CAC7B,IACA,WACgB;AAAA,EAChB,MAAM,GAAG,YAAY,EAAE,QAAQ,OAAO,OAAO;AAAA,IAC5C,MAAM,SAAS,MAAM,GACnB,YAAY,gBAAgB,EAC5B,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,cAAc,IAAI;AAAA,MAClB,SAAS,UAAU,UAAU;AAAA,MAC7B,WAAW;AAAA,MACX,cAAc;AAAA,IACf,CAAC,EAKA,MAAM,MAAM,KAAK,UAAU,EAAE,EAC7B,MAAM,UAAU,KAAK,SAAS,EAC9B,iBAAiB;AAAA,IACnB,IAAI,OAAO,OAAO,kBAAkB,CAAC,MAAM,GAAG;AAAA,MAC7C,QAAO,KAAK,2BAA2B;AAAA,QACtC,UAAU,UAAU;AAAA,QACpB,WAAW,UAAU;AAAA,QACrB,SAAS;AAAA,MACV,CAAC;AAAA,MACD;AAAA,IACD;AAAA,IACA,MAAM,GACJ,YAAY,UAAU,EACtB,IAAI;AAAA,MACJ,kBAAkB,IAAI;AAAA,MACtB,iBAAiB,IAAI;AAAA,MACrB,kBAAkB;AAAA,MAClB,YAAY;AAAA,MACZ,YAAY,IAAI;AAAA,IACjB,CAAC,EACA,MAAM,MAAM,KAAK,UAAU,UAAU,EACrC,QAAQ;AAAA,IAMV,eAAe;AAAA,GACf;AAAA;AAGF,eAAe,YAAY,CAC1B,IACA,WACA,KACA,SACgB;AAAA,EAChB,MAAM,UAAU,UAAU,UAAU;AAAA,EACpC,MAAM,SAAS,WAAW,IAAI;AAAA,EAC9B,MAAM,SAAS,SACZ,OACA,IAAI,KAAK,KAAK,IAAI,IAAI,iBAAiB,UAAU,OAAO,IAAI,IAAI;AAAA,EAEnE,MAAM,GAAG,YAAY,EAAE,QAAQ,OAAO,OAAO;AAAA,IAC5C,MAAM,SAAS,MAAM,GACnB,YAAY,gBAAgB,EAC5B,IAAI;AAAA,MACJ;AAAA,MACA,iBAAiB,UAAU,IAAI;AAAA,MAC/B,QAAQ,SAAS,SAAS;AAAA,MAC1B,WAAW,SAAS,IAAI,OAAS;AAAA,MACjC,WAAW;AAAA,MACX,cAAc;AAAA,IACf,CAAC,EAGA,MAAM,MAAM,KAAK,UAAU,EAAE,EAC7B,MAAM,UAAU,KAAK,SAAS,EAC9B,iBAAiB;AAAA,IACnB,IAAI,OAAO,OAAO,kBAAkB,CAAC,MAAM,GAAG;AAAA,MAC7C,QAAO,KAAK,2BAA2B;AAAA,QACtC,UAAU,UAAU;AAAA,QACpB,WAAW,UAAU;AAAA,QACrB,SAAS;AAAA,MACV,CAAC;AAAA,MACD;AAAA,IACD;AAAA,IAKA,MAAM,YAAY,MAAM;AAAA;AAAA;AAAA;AAAA,mBAIP,QAAQ,MAAM,GAAG,GAAG;AAAA;AAAA,gBAEvB,IAAI;AAAA;AAAA,IAEhB,QAAQ,EAAE;AAAA,IACZ,MAAM,cACL,UAAU,KAAK,IAAI,oBAAoB,IAAI,mBAAmB;AAAA,IAC/D,MAAM,oBAAoB,eAAe;AAAA,IAEzC,IAAI,mBAAmB;AAAA,MAItB,MAAM,GACJ,YAAY,UAAU,EACtB,IAAI;AAAA,QACJ,QAAQ;AAAA,QACR,mBAAmB,IAAI;AAAA,QACvB,YAAY,IAAI;AAAA,MACjB,CAAC,EACA,MAAM,MAAM,KAAK,IAAI,EAAE,EACvB,QAAQ;AAAA,MACV,QAAO,KACN,+DACA;AAAA,QACC,SAAS,IAAI;AAAA,QACb,UAAU;AAAA,MACX,CACD;AAAA,IACD;AAAA,GACA;AAAA;AA0BF,eAAe,aAAa,CAC3B,IACA,OACA,WACA,SACkB;AAAA,EAClB,IAAI,MAAM,eAAe;AAAA,IACxB,MAAM,eAAe;AAAA,IACrB,OAAO;AAAA,EACR;AAAA,EACA,MAAM,gBAAgB;AAAA,EAKtB,MAAM,eAAe,aAAa,IAAI,OAAO,WAAW,OAAO;AAAA,EAC/D,MAAM,eAAe;AAAA,EACrB,IAAI;AAAA,IACH,OAAO,MAAM;AAAA,YACZ;AAAA,IACD,IAAI,MAAM,iBAAiB;AAAA,MAAc,MAAM,eAAe;AAAA;AAAA;AAIhE,eAAe,YAAY,CAC1B,IACA,OACA,WACA,SACkB;AAAA,EAClB,IAAI,eAAe;AAAA,EACnB,IAAI;AAAA,IACH,IAAI,iBAAiB;AAAA,IACrB,UAAS;AAAA,MAMR,IAAI,CAAC,MAAM;AAAA,QAAS;AAAA,MACpB,MAAM,eAAe;AAAA,MACrB,MAAM,SAAS,MAAM,qBACpB,IACA,OACA,WACA,cACD;AAAA,MACA,gBAAgB,OAAO;AAAA,MAQvB,IAAI,CAAC,MAAM,gBAAgB,CAAC,OAAO;AAAA,QAAa;AAAA,MAChD,iBAAiB;AAAA,IAClB;AAAA,YACC;AAAA,IACD,MAAM,gBAAgB;AAAA;AAAA,EAEvB,OAAO;AAAA;AAmCR,eAAe,oBAAoB,CAClC,IACA,OACA,WACA,SACuB;AAAA,EAGvB,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK,MAAM,aAAa,UAAU,CAAC;AAAA,EACjE,MAAM,cAAc,aAAa;AAAA,EACjC,QAAQ,UAAU,WAAW,gBAAgB,MAAM,GACjD,YAAY,EACZ,QAAQ,OAAO,OAAO;AAAA,IACtB,MAAM,OAAO,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAOT,KAAI,IAAI,SAAS;AAAA,MACxB,QAAQ,EAAE;AAAA,IACb,MAAM,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAOX,KAAI,IAAI,WAAW;AAAA,MAC1B,QAAQ,EAAE;AAAA,IAEb,MAAM,OAAO,CAAC,GAAG,KAAK,MAAM,GAAG,OAAO,IAAI;AAAA,IAC1C,IAAI,KAAK,WAAW,GAAG;AAAA,MACtB,OAAO,EAAE,UAAU,MAAM,WAAW,GAAG,aAAa,EAAE;AAAA,IACvD;AAAA,IASA,MAAM,MAAM,IAAI;AAAA,IAChB,MAAM,YAAY,IAAI,KAAK,IAAI,QAAQ,IAAI,cAAc;AAAA,IACzD,MAAM,GACJ,YAAY,gBAAgB,EAC5B,IAAI;AAAA,MACJ,WAAW;AAAA,MACX,cAAc;AAAA,MACd,iBAAiB;AAAA,IAClB,CAAC,EACA,MACA,MACA,MACA,KAAK,IAAI,CAAC,MAAM,EAAE,EAAE,CACrB,EACC,QAAQ;AAAA,IACV,OAAO;AAAA,MACN,UAAU;AAAA,MACV,WAAW,KAAK,KAAK;AAAA,MACrB,aAAa,OAAO,KAAK;AAAA,IAC1B;AAAA,GACA;AAAA,EAEF,IAAI,SAAS,WAAW,GAAG;AAAA,IAC1B,OAAO,EAAE,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG,aAAa,MAAM;AAAA,EACrE;AAAA,EAEA,MAAM,UAAU,IAAI;AAAA,EACpB,WAAW,OAAO,UAAU;AAAA,IAC3B,MAAM,MAAM,QAAQ,IAAI,IAAI,UAAU;AAAA,IACtC,IAAI;AAAA,MAAK,IAAI,KAAK,GAAG;AAAA,IAChB;AAAA,cAAQ,IAAI,IAAI,YAAY,CAAC,GAAG,CAAC;AAAA,EACvC;AAAA,EAEA,MAAM,SAAS,MAAM,KAAK,QAAQ,KAAK,CAAC;AAAA,EACxC,MAAM,OAAO,MAAM,GACjB,WAAW,UAAU,EACrB,UAAU,EACV,MAAM,MAAM,MAAM,MAAM,EACxB,QAAQ;AAAA,EACV,MAAM,UAAU,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAAA,EAElD,IAAI,aAAa;AAAA,EACjB,IAAI,WAAW;AAAA,EACf,MAAM,cAAwB,CAAC;AAAA,EAC/B,WAAW,SAAS,QAAQ;AAAA,IAC3B,MAAM,MAAM,QAAQ,IAAI,KAAK;AAAA,IAE7B,MAAM,OAAO,QAAQ,IAAI,KAAK;AAAA,IAC9B,IAAI,CAAC,OAAO,IAAI,WAAW,UAAU;AAAA,MACpC,YAAY,KAAK;AAAA,MACjB,YAAY,KAAK,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAAA,MACzC;AAAA,IACD;AAAA,IACA,cAAc,KAAK;AAAA,IACnB,cAAc,IAAI,OAAO,KAAK,IAAI;AAAA,EACnC;AAAA,EAEA,IAAI,YAAY,SAAS,GAAG;AAAA,IAI3B,MAAM,GACJ,YAAY,gBAAgB,EAC5B,IAAI,EAAE,iBAAiB,IAAI,MAAQ,WAAW,MAAM,cAAc,KAAK,CAAC,EACxE,MAAM,MAAM,MAAM,WAAW,EAC7B,QAAQ;AAAA,EACX;AAAA,EASA,MAAM,oBAAoB,KAAK,IAC9B,GAAG,SAAS,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,CACxD;AAAA,EACA,MAAM,WAAW,OAAO,OACvB,CAAC,KAAK,OAAO,OAAO,MAAM,UAAU,IAAI,EAAE,GAAG,YAAY,IACzD,CACD;AAAA,EACA,MAAM,cAAc,OAAO,OAC1B,CAAC,KAAK,OAAO,OAAO,QAAQ,IAAI,EAAE,GAAG,eAAe,IACpD,CACD;AAAA,EACA,QAAO,KAAK,uBAAuB;AAAA,IAClC,OAAO;AAAA,IACP;AAAA,IACA,SAAS,SAAS;AAAA,IAClB;AAAA,IACA;AAAA,IACA,0BAA0B,KAAK,IAAI,IAAI;AAAA,IACvC,WAAW;AAAA,IACX;AAAA,EACD,CAAC;AAAA,EAED,OAAO;AAAA,IACN,SAAS,SAAS;AAAA,IAClB;AAAA,IACA;AAAA,IACA,aAAa,aAAa,aAAa,eAAe;AAAA,EACvD;AAAA;AAaD,SAAS,aAAa,CACrB,IACA,OACA,KACA,MACO;AAAA,EACP,IAAI,KAAK,MAAM,UAAU,IAAI,IAAI,EAAE;AAAA,EACnC,IAAI,CAAC,IAAI;AAAA,IACR,KAAK,EAAE,KAAK,OAAO,CAAC,GAAG,UAAU,EAAE;AAAA,IACnC,MAAM,UAAU,IAAI,IAAI,IAAI,EAAE;AAAA,EAC/B,EAAO;AAAA,IACN,GAAG,MAAM;AAAA;AAAA,EAEV,GAAG,MAAM,KAAK,GAAG,IAAI;AAAA,EACrB,QAAQ,IAAI,OAAO,IAAI,EAAE;AAAA;AAW1B,SAAS,OAAO,CACf,IACA,OACA,OACO;AAAA,EACP,MAAM,KAAK,MAAM,UAAU,IAAI,KAAK;AAAA,EACpC,IAAI,CAAC;AAAA,IAAI;AAAA,EACT,MAAM,MAAM,GAAG,IAAI,eAAe;AAAA,EAClC,OACC,MAAM,WACN,GAAG,IAAI,WAAW,YAClB,GAAG,WAAW,OACd,GAAG,MAAM,SAAS,GACjB;AAAA,IACD,MAAM,MAAM,GAAG,MAAM,MAAM;AAAA,IAC3B,IAAI,CAAC;AAAA,MAAK;AAAA,IACV,GAAG;AAAA,IACH,MAAM,aAAa,OAAO,IAAI,OAAO,IAAI,GAAG;AAAA,IAC5C,MAAM,aAAa,IAAI,UAAU;AAAA,IAC5B,WAAW,QAAQ,MAAM;AAAA,MAC7B,MAAM,aAAa,OAAO,UAAU;AAAA,KACpC;AAAA,EACF;AAAA;AAKD,eAAe,MAAM,CACpB,IACA,OACA,IACA,KACgB;AAAA,EAChB,IAAI;AAAA,IACH,MAAM,SAAS,MAAM,YAAY,IAAI,KAAK,GAAG,GAAG;AAAA,IAChD,IAAI,OAAO,IAAI;AAAA,MACd,MAAM,gBAAgB,IAAI,GAAG;AAAA,IAC9B,EAAO;AAAA,MACN,MAAM,MAAM,OAAO,SAAS,QAAQ,OAAO,cAAc;AAAA,MACzD,MAAM,aAAa,IAAI,KAAK,GAAG,KAAK,GAAG;AAAA;AAAA,IAEvC,OAAO,KAAK;AAAA,IACb,QAAO,MAAM,4BAA4B;AAAA,MACxC,UAAU,IAAI;AAAA,MACd,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACvD,CAAC;AAAA,IACD,MAAM,aACL,IACA,KACA,GAAG,KACH,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAChD;AAAA,YACC;AAAA,IACD,GAAG;AAAA,IACH,QAAQ,IAAI,OAAO,GAAG,IAAI,EAAE;AAAA;AAAA;AAmB9B,eAAe,YAAY,CAAC,IAAqC;AAAA,EAIhE,MAAM,gBAAgB,EAAE;AAAA,EACxB,MAAM;AAAA;AAAA;AAAA,GAGJ,QAAQ,EAAE;AAAA,EACZ,MAAM;AAAA;AAAA;AAAA,GAGJ,QAAQ,EAAE;AAAA,EAGZ,MAAM;AAAA;AAAA;AAAA,GAGJ,QAAQ,EAAE;AAAA,EACZ,MAAM;AAAA;AAAA;AAAA,GAGJ,QAAQ,EAAE;AAAA,EACZ,MAAM;AAAA;AAAA;AAAA,GAGJ,QAAQ,EAAE;AAAA;AAGb,eAAsB,YAAY,CACjC,MAC+B;AAAA,EAC/B,MAAM,YAAY,WAAW,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE;AAAA,EACnE,MAAM,KAAK,YAAY;AAAA,EACvB,MAAM,QAAsB;AAAA,IAC3B,SAAS;AAAA,IACT,WAAW,IAAI;AAAA,IACf,eAAe;AAAA,IACf,cAAc;AAAA,IACd,cAAc;AAAA,IACd,cAAc,IAAI;AAAA,EACnB;AAAA,EACA,MAAM,iBAAiB,MAAM,kBAAkB;AAAA,EAC/C,MAAM,sBAAsB,MAAM,uBAAuB,KAAK;AAAA,EAE9D,QAAO,KAAK,qBAAqB,EAAE,IAAI,UAAU,CAAC;AAAA,EAKlD,MAAM,YAAY,kBAAkB;AAAA,EACpC,MAAM,UAAU,MAAM,OACrB,uBACA,MAAM;AAAA,IACL,IAAI,CAAC,MAAM;AAAA,MAAS;AAAA,IACf,cAAc,IAAI,OAAO,WAAW,QAAQ,EAAE,MAAM,CAAC,QACzD,QAAO,MAAM,0BAA0B;AAAA,MACtC,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACvD,CAAC,CACF;AAAA,KAED,EAAE,kBAAkB,UAAU,CAC/B;AAAA,EACA,MAAM,cAAc,MAAM,OACzB,oBACA,MAAM;AAAA,IACL,IAAI,CAAC,MAAM;AAAA,MAAS;AAAA,IAMf,cAAc,IAAI,OAAO,WAAW,SAAS,EAAE,MAAM,CAAC,QAC1D,QAAO,MAAM,0BAA0B;AAAA,MACtC,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACvD,CAAC,CACF;AAAA,KAED,EAAE,kBAAkB,UAAU,CAC/B;AAAA,EAKA,QAAO,KAAK,sCAAsC;AAAA,IACjD,UAAU,CAAC,uBAAuB,kBAAkB;AAAA,IACpD,IAAI,cAAc,SAAS;AAAA,EAC5B,CAAC;AAAA,EAID,MAAM,OAAO,YAAY,MAAM;AAAA,IAC9B,IAAI,CAAC,MAAM;AAAA,MAAS;AAAA,IACf,cAAc,IAAI,OAAO,WAAW,MAAM,EAAE,MAAM,CAAC,QACvD,QAAO,MAAM,+BAA+B;AAAA,MAC3C,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACvD,CAAC,CACF;AAAA,KACE,cAAc;AAAA,EAGZ,cAAc,IAAI,OAAO,WAAW,SAAS;AAAA,EAGlD,MAAM,YAAY,YAAY,MAAM;AAAA,IACnC,IAAI,CAAC,MAAM;AAAA,MAAS;AAAA,IACf,aAAa,EAAE,EAAE,MAAM,CAAC,QAC5B,QAAO,MAAM,8BAA8B;AAAA,MAC1C,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACvD,CAAC,CACF;AAAA,KACE,mBAAmB;AAAA,EAGtB,MAAM,gBAAgB,YAAY,MAAM;AAAA,IACvC,IAAI,CAAC,MAAM;AAAA,MAAS;AAAA,IACf,qBAAqB,EAAE,EAAE,MAAM,CAAC,QACpC,QAAO,MAAM,0CAA0C;AAAA,MACtD,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACvD,CAAC,CACF;AAAA,KACE,yBAAyB;AAAA,EAE5B,OAAO,YAAY;AAAA,IAIlB,MAAM,UAAU;AAAA,IAChB,cAAc,IAAI;AAAA,IAClB,cAAc,SAAS;AAAA,IACvB,cAAc,aAAa;AAAA,IAC3B,MAAM,QAAQ;AAAA,IACd,MAAM,YAAY;AAAA,IAElB,MAAM,cAAc,IAAI,IAAI,MAAM,YAAY;AAAA,IAC9C,MAAM,cAAc,YAAY;AAAA,IAIhC,MAAM,gBAAgB,MAAM,gBAAgB,QAAQ,QAAQ,GAAG,MAC9D,MAAM,EACP;AAAA,IACA,MAAM,UAAU,QAAQ,IAAI,CAAC,cAAc,GAAG,WAAW,CAAC;AAAA,IAK1D,MAAM,aACL,MAAM,uBAAuB,yBAAyB;AAAA,IACvD,IAAI,WAAW;AAAA,IACf,IAAI;AAAA,IACJ,MAAM,UAAU,IAAI,QAAc,CAAC,YAAY;AAAA,MAC9C,QAAQ,WAAW,MAAM;AAAA,QACxB,WAAW;AAAA,QACX,QAAQ;AAAA,SACN,UAAU;AAAA,KACb;AAAA,IACD,MAAM,QAAQ,KAAK,CAAC,SAAS,OAAO,CAAC;AAAA,IACrC,aAAa,KAAK;AAAA,IAElB,MAAM,YAAY,WAAW,MAAM,aAAa,OAAO;AAAA,IACvD,MAAM,UAAU,cAAc;AAAA,IAC9B,QAAO,KAAK,qBAAqB;AAAA,MAChC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACD,CAAC;AAAA;AAAA;",
17
+ "debugId": "7A336C92BEB8938764756E2164756E21",
18
18
  "names": []
19
19
  }
@@ -23,7 +23,7 @@ import { createHash } from "node:crypto";
23
23
  // package.json
24
24
  var package_default = {
25
25
  name: "@secondlayer/subgraphs",
26
- version: "8.0.2",
26
+ version: "8.0.3",
27
27
  description: "Describe the Stacks data you want as one TypeScript file; it fills itself and survives reorgs.",
28
28
  license: "MIT",
29
29
  repository: {
@@ -79,7 +79,7 @@ var package_default = {
79
79
  prepublishOnly: "bun run build"
80
80
  },
81
81
  dependencies: {
82
- "@secondlayer/shared": "^15.0.1",
82
+ "@secondlayer/shared": "^15.0.2",
83
83
  "@secondlayer/stacks": "^6.5.4",
84
84
  "@secondlayer/verify": "^0.6.1",
85
85
  esbuild: "^0.28.2",
@@ -2103,5 +2103,5 @@ export {
2103
2103
  replayWebhook
2104
2104
  };
2105
2105
 
2106
- //# debugId=C4585E8FA353CC0264756E2164756E21
2106
+ //# debugId=39B901D4E6180ED664756E2164756E21
2107
2107
  //# sourceMappingURL=replay.js.map
@@ -16,6 +16,6 @@
16
16
  "import type {\n\tChainApplyEnvelope,\n\tSbtcDepositEvent,\n\tSbtcWithdrawalEvent,\n\tSbtcWithdrawalSweptConfirmedEvent,\n} from \"@secondlayer/shared\";\nimport type {\n\tDatabase,\n\tInsertWebhookOutbox,\n\tSbtcEventTopic,\n\tWebhook,\n} from \"@secondlayer/shared/db\";\nimport type { ChainTrigger } from \"@secondlayer/shared/schemas/webhooks\";\nimport type { Kysely } from \"kysely\";\nimport type { SubgraphFilter } from \"../types.ts\";\nimport type { BlockData } from \"./batch-loader.ts\";\nimport { indexEventTypesForFilterTypes } from \"./block-source.ts\";\nimport {\n\ttype ChainDataReader,\n\ttype SbtcEventRow,\n\ttype SettlementScanRow,\n\tchainDataReader,\n\tdatabaseChainDataReader,\n} from \"./chain-data-reader.ts\";\nimport { decoderNamesForIndexEventTypes } from \"./decoder-bound.ts\";\nimport {\n\ttype MatchedTx,\n\ttype TraitContracts,\n\tmatchSources,\n} from \"./source-matcher.ts\";\n\n/** Trigger types that match a whole transaction (not an individual event). */\nconst TX_LEVEL_TRIGGER_TYPES = new Set([\"contract_call\", \"contract_deploy\"]);\n\n/**\n * `BlockData.block.timestamp` → the `webhook_outbox.block_time` the emitters\n * below stamp on a row. Unix seconds on every real block source\n * (`PostgresBlockSource` reads it off `blocks`; `PublicApiBlockSource`\n * reconstructs it from the Index API's `block_time`). Undefined/NaN/non-\n * positive (a test's minimal block fixture, or the 0-timestamp bulk-import\n * artifact `decode/health.ts` also guards against) means \"unknown\" — leave\n * `block_time` null rather than writing an Invalid Date or a 1970 sentinel.\n */\nexport function blockTimeOf(block: { timestamp: number }): Date | undefined {\n\treturn Number.isFinite(block.timestamp) && block.timestamp > 0\n\t\t? new Date(block.timestamp * 1000)\n\t\t: undefined;\n}\n\n/** Fired on a Bitcoin confirmation, async to Stacks blocks — handled by the\n * scan-based `emitSbtcSettlementOutbox`, NOT the per-block path. Listed in\n * SBTC_TRIGGER_TYPES so the per-block matcher skips it, but deliberately absent\n * from SBTC_TRIGGER_TO_TOPIC (it has no `sbtc_events` topic). */\nconst SETTLEMENT_TRIGGER_TYPE = \"sbtc_withdrawal_swept_confirmed\";\n\n/**\n * sBTC trigger types — matched via the `sbtc_events` table, NOT via\n * `decoded_events`. Excluded from the chain-event sources map so the\n * `matchSources` engine never sees them; `emitSbtcOutbox` handles them\n * with a dedicated query + match loop.\n */\nconst SBTC_TRIGGER_TYPES = new Set([\n\t\"sbtc_deposit\",\n\t\"sbtc_withdrawal_create\",\n\t\"sbtc_withdrawal_accept\",\n\t\"sbtc_withdrawal_reject\",\n\tSETTLEMENT_TRIGGER_TYPE,\n]);\n\nfunction isSbtcTriggerType(type: string): boolean {\n\treturn SBTC_TRIGGER_TYPES.has(type);\n}\n\nconst SBTC_TRIGGER_TO_TOPIC: Record<string, SbtcEventTopic> = {\n\tsbtc_deposit: \"completed-deposit\",\n\tsbtc_withdrawal_create: \"withdrawal-create\",\n\tsbtc_withdrawal_accept: \"withdrawal-accept\",\n\tsbtc_withdrawal_reject: \"withdrawal-reject\",\n};\n\n/**\n * Pure matching core for direct chain-level webhooks. A single evaluator\n * loop serves ALL chain webhooks: it reads canonical blocks off the public\n * Index/Streams clock (via `PublicApiBlockSource`), runs the same\n * `matchSources` engine the subgraph runtime uses, and routes matches back to\n * the originating webhook. Everything here is pure/sync (DB only for trait\n * resolution) so it's trivially testable.\n *\n * Source keys are `\"{webhookId}#{triggerIndex}\"` — `matchSources` echoes\n * the key as `MatchedTx.sourceName`, letting the emitter recover which\n * webhook (and which trigger) matched. `keyMeta` carries the readable\n * trigger type for the outbox `event_type` / payload.\n */\n\nexport interface TriggerKeyMeta {\n\twebhookId: string;\n\ttriggerIndex: number;\n\ttriggerType: ChainTrigger[\"type\"];\n}\n\nexport interface ChainSourcesMap {\n\tsources: Record<string, SubgraphFilter>;\n\tkeyMeta: Map<string, TriggerKeyMeta>;\n}\n\nfunction sourceKey(webhookId: string, triggerIndex: number): string {\n\treturn `${webhookId}#${triggerIndex}`;\n}\n\nfunction toAmount(v: string | number | undefined): bigint | undefined {\n\treturn v === undefined ? undefined : BigInt(v);\n}\n\n/**\n * Convert a stored `ChainTrigger` (JSON; amounts as string/number) to the\n * runtime `SubgraphFilter` the matcher expects (amounts as bigint). Field names\n * are identical across the two shapes, so this is a copy plus amount coercion.\n */\nexport function chainTriggerToFilter(trigger: ChainTrigger): SubgraphFilter {\n\tconst t = trigger as ChainTrigger & {\n\t\tminAmount?: string | number;\n\t\tmaxAmount?: string | number;\n\t};\n\t// Spread copies all set keys; amounts (string|number) are then overwritten\n\t// with bigint where present. An absent optional amount isn't in the spread,\n\t// so there's nothing to strip.\n\tconst filter = { ...trigger } as Record<string, unknown>;\n\tconst minAmount = toAmount(t.minAmount);\n\tconst maxAmount = toAmount(t.maxAmount);\n\tif (minAmount !== undefined) filter.minAmount = minAmount;\n\tif (maxAmount !== undefined) filter.maxAmount = maxAmount;\n\treturn filter as unknown as SubgraphFilter;\n}\n\nfunction triggersOf(sub: Webhook): ChainTrigger[] {\n\treturn (sub.triggers ?? []) as ChainTrigger[];\n}\n\n/** Build the `matchSources` input from every active chain webhook. */\nexport function buildSourcesMap(chainSubs: Webhook[]): ChainSourcesMap {\n\tconst sources: Record<string, SubgraphFilter> = {};\n\tconst keyMeta = new Map<string, TriggerKeyMeta>();\n\tfor (const sub of chainSubs) {\n\t\ttriggersOf(sub).forEach((trigger, triggerIndex) => {\n\t\t\t// sBTC triggers are handled by emitSbtcOutbox — skip them here so\n\t\t\t// matchSources never tries to find sbtc_events in decoded_events.\n\t\t\tif (isSbtcTriggerType(trigger.type)) return;\n\t\t\tconst key = sourceKey(sub.id, triggerIndex);\n\t\t\tsources[key] = chainTriggerToFilter(trigger);\n\t\t\tkeyMeta.set(key, {\n\t\t\t\twebhookId: sub.id,\n\t\t\t\ttriggerIndex,\n\t\t\t\ttriggerType: trigger.type,\n\t\t\t});\n\t\t});\n\t}\n\treturn { sources, keyMeta };\n}\n\n/** The Index event types the loader must fetch to satisfy all chain triggers. */\nexport function referencedEventTypes(chainSubs: Webhook[]): string[] {\n\tconst filterTypes = new Set<string>();\n\tfor (const sub of chainSubs) {\n\t\tfor (const trigger of triggersOf(sub)) {\n\t\t\t// sBTC events live in sbtc_events, not in the Index event stream.\n\t\t\tif (!isSbtcTriggerType(trigger.type)) filterTypes.add(trigger.type);\n\t\t}\n\t}\n\treturn indexEventTypesForFilterTypes([...filterTypes]);\n}\n\n/** Decoder checkpoint names feeding the event types these chain subs read. */\nexport function referencedDecoderNames(chainSubs: Webhook[]): string[] {\n\treturn decoderNamesForIndexEventTypes(referencedEventTypes(chainSubs));\n}\n\n/**\n * True when some active chain webhook has a tx-level trigger\n * (contract_call/contract_deploy) — the only trigger types whose match needs\n * a REAL transaction (`function_args`, `raw_result`, etc., read in\n * `emitChainOutbox`'s TX_LEVEL branch below). Every other trigger type matches\n * off decoded events, which the block source can synthesize a minimal tx for\n * from joined event context instead of fetching every transaction in the\n * range. Mirrors `needsTransactionData` in block-source.ts for subgraphs —\n * same rule, chain-webhook triggers instead of subgraph source filters.\n */\nexport function chainSubsNeedTransactions(chainSubs: Webhook[]): boolean {\n\treturn chainSubs.some((sub) =>\n\t\ttriggersOf(sub).some((trigger) => TX_LEVEL_TRIGGER_TYPES.has(trigger.type)),\n\t);\n}\n\n/** Distinct traits referenced across all chain triggers. */\nexport function referencedTraits(chainSubs: Webhook[]): string[] {\n\tconst traits = new Set<string>();\n\tfor (const sub of chainSubs) {\n\t\tfor (const trigger of triggersOf(sub)) {\n\t\t\tconst trait = (trigger as { trait?: string }).trait;\n\t\t\tif (trait) traits.add(trait);\n\t\t}\n\t}\n\treturn [...traits];\n}\n\n/**\n * `opts.reader` wins; an explicit `opts.sourceDb` (test seam) reads those\n * tables; otherwise the stack's own reader (`chainDataReader`): the source\n * plane, or the hosted Index API on a tenant with no local chain.\n */\nfunction readerFor(opts?: {\n\tsourceDb?: Kysely<Database>;\n\treader?: ChainDataReader;\n}): ChainDataReader {\n\tif (opts?.reader) return opts.reader;\n\tif (opts?.sourceDb) return databaseChainDataReader(opts.sourceDb);\n\treturn chainDataReader();\n}\n\n/**\n * Resolve each referenced trait to its conforming contract-id set as of\n * `asOfBlock`, from the contract registry (`CONTRACT_REGISTRY_ENABLED` populates\n * it). Empty map when no trigger is trait-scoped → no reads. Membership only\n * grows, so the evaluator resolves this once per batch, not per block.\n *\n * `contracts` is a SOURCE-plane table; the evaluator/replay run on the TARGET\n * handle (an empty same-named copy exists there post-split), so this never\n * reads `db` — see `ChainDataReader`.\n */\nexport async function buildTraitContracts(\n\tchainSubs: Webhook[],\n\tasOfBlock: number,\n\topts?: { sourceDb?: Kysely<Database>; reader?: ChainDataReader },\n): Promise<TraitContracts> {\n\tconst traits = referencedTraits(chainSubs);\n\tif (traits.length === 0) return new Map();\n\tconst reader = readerFor(opts);\n\tconst resolved: TraitContracts = new Map();\n\tfor (const trait of traits) {\n\t\tconst ids = await reader.traitContractIds(trait, asOfBlock);\n\t\tresolved.set(trait, new Set(ids));\n\t}\n\treturn resolved;\n}\n\n/** Run the matcher for one block. Thin wrapper for symmetry/testability. */\nexport function evaluateBlock(\n\tblock: BlockData,\n\tsources: Record<string, SubgraphFilter>,\n\ttraitContracts: TraitContracts,\n): MatchedTx[] {\n\treturn matchSources(\n\t\tsources,\n\t\tblock.txs,\n\t\tblock.events,\n\t\ttraitContracts,\n\t\tnew Map(),\n\t\tblock.vmEvents ?? [],\n\t);\n}\n\n// ── Outbox emission ─────────────────────────────────────────────────────────\n\n// Apply-envelope shape is single-sourced as `ChainApplyEnvelope` in\n// `@secondlayer/shared` (shared with the SDK consumer); reorg emits a matching\n// `ChainReorgRollbackEnvelope`, see `handleChainReorg`.\n\n/**\n * Stable dedup identity for a chain delivery — (webhook, tx, event,\n * block_hash). A tx-level match (contract_call/deploy) has no event, so\n * `eventIndex = -1`. `block_hash` is included so a tx that survives a reorg\n * (same tx_id, NEW canonical block) re-delivers an `apply` after its rollback,\n * instead of being suppressed forever; re-processing the SAME canonical block is\n * still idempotent (same hash → same key).\n */\nfunction chainDedupKey(\n\twebhookId: string,\n\ttxId: string,\n\teventIndex: number,\n\tblockHash: string,\n\treplayId?: string,\n\tclock: DeliveryClock = \"classic\",\n): string {\n\t// vm rows are keyed by ordinal — a second clock. Namespace them so\n\t// a print at event_index N and a map_set at ordinal N in the same\n\t// tx are two deliveries, not one suppressed by the dedup constraint.\n\t// Classic keys are byte-identical to before (existing rows stay idempotent).\n\tconst ordinal = clock === \"vm\" ? `vm:${eventIndex}` : `${eventIndex}`;\n\tconst base = `chain:${webhookId}:${txId}:${ordinal}:${blockHash}`;\n\t// Replay keys are namespaced so a re-delivery doesn't collide with the\n\t// already-emitted live apply row (whose outbox entry may be long gone), while\n\t// re-running the SAME replay range stays idempotent (same replayId → same key).\n\treturn replayId ? `replay:${replayId}:${base}` : base;\n}\n\n/** Which ordinal `event_index` carries: classic `events.event_index` or the\n * opt-in `vm_events.ordinal`. Never mixed. */\ntype DeliveryClock = \"classic\" | \"vm\";\n\nconst VM_TRIGGER_TYPES = new Set<string>([\n\t\"nested_contract_call\",\n\t\"var_set\",\n\t\"map_set\",\n\t\"map_insert\",\n\t\"map_delete\",\n]);\n\nfunction clockFor(triggerType: string): DeliveryClock {\n\treturn VM_TRIGGER_TYPES.has(triggerType) ? \"vm\" : \"classic\";\n}\n\nfunction applyRow(\n\tmeta: TriggerKeyMeta,\n\tblockHeight: number,\n\tblockHash: string,\n\ttxId: string,\n\teventIndex: number,\n\tevent: Record<string, unknown>,\n\treplayId?: string,\n\tblockTime?: Date,\n): InsertWebhookOutbox {\n\tconst clock = clockFor(meta.triggerType);\n\tconst payload: ChainApplyEnvelope = {\n\t\taction: \"apply\",\n\t\tblock_hash: blockHash,\n\t\tblock_height: blockHeight,\n\t\tblock_time: blockTime ? blockTime.toISOString() : null,\n\t\ttx_id: txId,\n\t\tcanonical: true,\n\t\ttrigger: meta.triggerType,\n\t\tevent,\n\t};\n\treturn {\n\t\twebhook_id: meta.webhookId,\n\t\tkind: \"chain\",\n\t\tblock_height: blockHeight,\n\t\ttx_id: txId,\n\t\trow_pk:\n\t\t\tclock === \"vm\"\n\t\t\t\t? { tx_id: txId, event_index: eventIndex, clock }\n\t\t\t\t: { tx_id: txId, event_index: eventIndex },\n\t\tevent_type: `chain.${meta.triggerType}.apply`,\n\t\tpayload,\n\t\tdedup_key: chainDedupKey(\n\t\t\tmeta.webhookId,\n\t\t\ttxId,\n\t\t\teventIndex,\n\t\t\tblockHash,\n\t\t\treplayId,\n\t\t\tclock,\n\t\t),\n\t\t...(replayId ? { is_replay: true, replay_id: replayId } : {}),\n\t\t...(blockTime ? { block_time: blockTime } : {}),\n\t};\n}\n\n/**\n * Turn one block's matches into `webhook_outbox` rows (apply envelope). For\n * tx-level triggers (contract_call/deploy) we emit ONE row per matched tx\n * (`event_index = -1`); for event-level triggers, one row per matched event.\n * The `(webhook_id, dedup_key)` unique constraint makes re-processing a\n * block idempotent, so the emitter never double-delivers. Returns rows written.\n */\nexport async function emitChainOutbox(\n\tdb: Kysely<Database>,\n\tmatches: MatchedTx[],\n\tkeyMeta: Map<string, TriggerKeyMeta>,\n\tblockHeight: number,\n\tblockHash: string,\n\tblockTime?: Date,\n\topts?: { replayId?: string },\n): Promise<number> {\n\tconst replayId = opts?.replayId;\n\tconst rows: InsertWebhookOutbox[] = [];\n\tfor (const match of matches) {\n\t\tconst meta = keyMeta.get(match.sourceName);\n\t\tif (!meta) continue;\n\t\tconst txId = match.tx.tx_id;\n\t\tif (TX_LEVEL_TRIGGER_TYPES.has(meta.triggerType)) {\n\t\t\trows.push(\n\t\t\t\tapplyRow(\n\t\t\t\t\tmeta,\n\t\t\t\t\tblockHeight,\n\t\t\t\t\tblockHash,\n\t\t\t\t\ttxId,\n\t\t\t\t\t-1,\n\t\t\t\t\t{\n\t\t\t\t\t\ttx_id: txId,\n\t\t\t\t\t\ttype: match.tx.type,\n\t\t\t\t\t\tsender: match.tx.sender,\n\t\t\t\t\t\tstatus: match.tx.status,\n\t\t\t\t\t\tcontract_id: match.tx.contract_id ?? null,\n\t\t\t\t\t\tfunction_name: match.tx.function_name ?? null,\n\t\t\t\t\t\tfunction_args: match.tx.function_args ?? null,\n\t\t\t\t\t\tresult_hex: match.tx.raw_result ?? null,\n\t\t\t\t\t},\n\t\t\t\t\treplayId,\n\t\t\t\t\tblockTime,\n\t\t\t\t),\n\t\t\t);\n\t\t} else {\n\t\t\tfor (const event of match.events) {\n\t\t\t\trows.push(\n\t\t\t\t\tapplyRow(\n\t\t\t\t\t\tmeta,\n\t\t\t\t\t\tblockHeight,\n\t\t\t\t\t\tblockHash,\n\t\t\t\t\t\ttxId,\n\t\t\t\t\t\tevent.event_index,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttx_id: txId,\n\t\t\t\t\t\t\ttype: event.type,\n\t\t\t\t\t\t\tevent_index: event.event_index,\n\t\t\t\t\t\t\tdata: event.data,\n\t\t\t\t\t\t},\n\t\t\t\t\t\treplayId,\n\t\t\t\t\t\tblockTime,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\tif (rows.length === 0) return 0;\n\t// Net-inserted (not built) so callers count genuinely new deliveries — a\n\t// re-processed block or a re-run replay returns 0.\n\tconst result = await db\n\t\t.insertInto(\"webhook_outbox\")\n\t\t.values(rows)\n\t\t.onConflict((oc) => oc.columns([\"webhook_id\", \"dedup_key\"]).doNothing())\n\t\t.executeTakeFirst();\n\treturn Number(result.numInsertedOrUpdatedRows ?? 0);\n}\n\n// ── sBTC event matching ──────────────────────────────────────────────────────\n\nfunction sbtcSubsOf(chainSubs: Webhook[]): Webhook[] {\n\treturn chainSubs.filter((sub) =>\n\t\ttriggersOf(sub).some((t) => isSbtcTriggerType(t.type)),\n\t);\n}\n\nfunction sbtcTopicsOf(sbtcSubs: Webhook[]): SbtcEventTopic[] {\n\tconst topics = new Set<SbtcEventTopic>();\n\tfor (const sub of sbtcSubs) {\n\t\tfor (const trigger of triggersOf(sub)) {\n\t\t\tconst topic = SBTC_TRIGGER_TO_TOPIC[trigger.type];\n\t\t\tif (topic) topics.add(topic);\n\t\t}\n\t}\n\treturn [...topics];\n}\n\n/**\n * The sBTC rows every active sBTC trigger could match over [from, to], grouped\n * by height: one read per batch, not per block. Empty (no read) when no\n * webhook has an sBTC block trigger. Throws on a read failure so the caller\n * stops with its cursor before the batch instead of skipping deliveries.\n */\nexport async function loadSbtcEventsForRange(\n\tchainSubs: Webhook[],\n\tfromHeight: number,\n\ttoHeight: number,\n\topts?: { sourceDb?: Kysely<Database>; reader?: ChainDataReader },\n): Promise<Map<number, SbtcEventRow[]>> {\n\tconst byHeight = new Map<number, SbtcEventRow[]>();\n\tconst topics = sbtcTopicsOf(sbtcSubsOf(chainSubs));\n\tif (topics.length === 0) return byHeight;\n\tconst rows = await readerFor(opts).sbtcEvents(fromHeight, toHeight, topics);\n\tfor (const row of rows) {\n\t\tconst height = Number(row.block_height);\n\t\tconst list = byHeight.get(height);\n\t\tif (list) list.push(row);\n\t\telse byHeight.set(height, [row]);\n\t}\n\treturn byHeight;\n}\n\nfunction toAmountBigInt(v: string | number | undefined): bigint | undefined {\n\treturn v === undefined ? undefined : BigInt(v);\n}\n\nfunction matchSbtcTrigger(trigger: ChainTrigger, row: SbtcEventRow): boolean {\n\tconst expectedTopic = SBTC_TRIGGER_TO_TOPIC[trigger.type];\n\tif (!expectedTopic || row.topic !== expectedTopic) return false;\n\n\tif (trigger.type === \"sbtc_deposit\") {\n\t\tif (trigger.sender && row.sender !== trigger.sender) return false;\n\t\tif (trigger.bitcoinTxid && row.bitcoin_txid !== trigger.bitcoinTxid)\n\t\t\treturn false;\n\t\tif (trigger.requestId !== undefined && row.request_id !== trigger.requestId)\n\t\t\treturn false;\n\t\tconst min = toAmountBigInt(trigger.minAmount);\n\t\tconst max = toAmountBigInt(trigger.maxAmount);\n\t\tif (min !== undefined || max !== undefined) {\n\t\t\tif (row.amount === null) return false;\n\t\t\tconst amt = BigInt(row.amount);\n\t\t\tif (min !== undefined && amt < min) return false;\n\t\t\tif (max !== undefined && amt > max) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tif (trigger.type === \"sbtc_withdrawal_create\") {\n\t\tif (trigger.sender && row.sender !== trigger.sender) return false;\n\t\tif (trigger.requestId !== undefined && row.request_id !== trigger.requestId)\n\t\t\treturn false;\n\t\tconst min = toAmountBigInt(trigger.minAmount);\n\t\tconst max = toAmountBigInt(trigger.maxAmount);\n\t\tif (min !== undefined || max !== undefined) {\n\t\t\tif (row.amount === null) return false;\n\t\t\tconst amt = BigInt(row.amount);\n\t\t\tif (min !== undefined && amt < min) return false;\n\t\t\tif (max !== undefined && amt > max) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tif (trigger.type === \"sbtc_withdrawal_accept\") {\n\t\tif (trigger.requestId !== undefined && row.request_id !== trigger.requestId)\n\t\t\treturn false;\n\t\tif (trigger.sweepTxid && row.sweep_txid !== trigger.sweepTxid) return false;\n\t\treturn true;\n\t}\n\n\tif (trigger.type === \"sbtc_withdrawal_reject\") {\n\t\tif (trigger.requestId !== undefined && row.request_id !== trigger.requestId)\n\t\t\treturn false;\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nfunction buildSbtcEventPayload(\n\ttriggerType: ChainTrigger[\"type\"],\n\trow: SbtcEventRow,\n): SbtcDepositEvent | SbtcWithdrawalEvent {\n\tif (triggerType === \"sbtc_deposit\") {\n\t\treturn {\n\t\t\ttopic: \"completed-deposit\",\n\t\t\trequest_id: row.request_id ?? 0,\n\t\t\tsender: row.sender,\n\t\t\tamount: row.amount ?? \"0\",\n\t\t\tbitcoin_txid: row.bitcoin_txid,\n\t\t\tblock_height: row.block_height,\n\t\t\ttx_id: row.tx_id,\n\t\t} satisfies SbtcDepositEvent;\n\t}\n\treturn {\n\t\ttopic: row.topic as\n\t\t\t| \"withdrawal-create\"\n\t\t\t| \"withdrawal-accept\"\n\t\t\t| \"withdrawal-reject\",\n\t\trequest_id: row.request_id ?? 0,\n\t\tsender: row.sender,\n\t\tamount: row.amount,\n\t\tsweep_txid: row.sweep_txid,\n\t\tsettlement_confirmed: false,\n\t\tblock_height: row.block_height,\n\t\ttx_id: row.tx_id,\n\t} satisfies SbtcWithdrawalEvent;\n}\n\n/**\n * Match active sBTC chain webhooks against `sbtc_events` for one block\n * and write apply-envelope rows to `webhook_outbox`. Runs alongside\n * `emitChainOutbox` (which handles decoded_events). Same dedup-key scheme —\n * re-processing the same block is idempotent.\n *\n * `opts.rows` is this block's slice of `loadSbtcEventsForRange` (the batched\n * read); without it the block is read on its own. `sbtc_events` is a\n * SOURCE-plane table and `db` is the TARGET handle (an empty same-named table\n * exists there post-split), so rows never come from `db`.\n */\nexport async function emitSbtcOutbox(\n\tdb: Kysely<Database>,\n\tchainSubs: Webhook[],\n\tblockHeight: number,\n\tblockHash: string,\n\tblockTime?: Date,\n\topts?: {\n\t\treplayId?: string;\n\t\tsourceDb?: Kysely<Database>;\n\t\treader?: ChainDataReader;\n\t\trows?: SbtcEventRow[];\n\t},\n): Promise<number> {\n\tconst sbtcSubs = sbtcSubsOf(chainSubs);\n\tif (sbtcSubs.length === 0) return 0;\n\n\tconst sbtcRows =\n\t\topts?.rows ??\n\t\t(\n\t\t\tawait loadSbtcEventsForRange(sbtcSubs, blockHeight, blockHeight, opts)\n\t\t).get(blockHeight) ??\n\t\t[];\n\tif (sbtcRows.length === 0) return 0;\n\n\tconst replayId = opts?.replayId;\n\tconst outboxRows: InsertWebhookOutbox[] = [];\n\n\tfor (const sub of sbtcSubs) {\n\t\ttriggersOf(sub).forEach((trigger, triggerIndex) => {\n\t\t\tif (!isSbtcTriggerType(trigger.type)) return;\n\t\t\tconst meta: TriggerKeyMeta = {\n\t\t\t\twebhookId: sub.id,\n\t\t\t\ttriggerIndex,\n\t\t\t\ttriggerType: trigger.type,\n\t\t\t};\n\t\t\tfor (const row of sbtcRows) {\n\t\t\t\tif (!matchSbtcTrigger(trigger, row)) continue;\n\t\t\t\tconst event = buildSbtcEventPayload(trigger.type, row);\n\t\t\t\toutboxRows.push(\n\t\t\t\t\tapplyRow(\n\t\t\t\t\t\tmeta,\n\t\t\t\t\t\tblockHeight,\n\t\t\t\t\t\tblockHash,\n\t\t\t\t\t\trow.tx_id,\n\t\t\t\t\t\trow.event_index,\n\t\t\t\t\t\tevent as unknown as Record<string, unknown>,\n\t\t\t\t\t\treplayId,\n\t\t\t\t\t\tblockTime,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t}\n\n\tif (outboxRows.length === 0) return 0;\n\tconst result = await db\n\t\t.insertInto(\"webhook_outbox\")\n\t\t.values(outboxRows)\n\t\t.onConflict((oc) => oc.columns([\"webhook_id\", \"dedup_key\"]).doNothing())\n\t\t.executeTakeFirst();\n\treturn Number(result.numInsertedOrUpdatedRows ?? 0);\n}\n\n/**\n * Emit the `sbtc_withdrawal_swept_confirmed` webhook. Unlike the per-block sBTC\n * path, this fires on a BITCOIN confirmation (async to Stacks blocks), so it\n * scans `sbtc_settlements` on its own cadence rather than per Stacks block.\n *\n * - Reads/advances a dedicated `last_settlement_scan_at` watermark on `db` (the\n * target/control plane). Null cursor → fast-forward to `now`, emit nothing\n * (forward-only, no historical backfill — mirrors the block cursor).\n * - Scans confirmed settlements with `confirmed_at > cursor` from the SOURCE\n * plane (`sbtc_settlements` is source), joined to the Stacks accept event +\n * block for the envelope anchor.\n * - Per-sub forward-only (`confirmed_at > sub.created_at`) + optional\n * requestId/sweepTxid filters; dedup on `(webhook_id, sweep_txid)` so a\n * reorg→un-confirm→re-confirm never double-fires.\n */\nexport async function emitSbtcSettlementOutbox(\n\tdb: Kysely<Database>,\n\tchainSubs: Webhook[],\n\topts?: {\n\t\tsourceDb?: Kysely<Database>;\n\t\treader?: ChainDataReader;\n\t\tnow?: Date;\n\t},\n): Promise<number> {\n\tconst settlementSubs = chainSubs.filter((sub) =>\n\t\ttriggersOf(sub).some((t) => t.type === SETTLEMENT_TRIGGER_TYPE),\n\t);\n\tif (settlementSubs.length === 0) return 0;\n\n\tconst now = opts?.now ?? new Date();\n\tconst state = await db\n\t\t.selectFrom(\"trigger_evaluator_state\")\n\t\t.select(\"last_settlement_scan_at\")\n\t\t.where(\"id\", \"=\", true)\n\t\t.executeTakeFirst();\n\n\t// Uninitialized → fast-forward, emit nothing (forward-only).\n\tconst cursor = state?.last_settlement_scan_at ?? null;\n\tif (cursor === null) {\n\t\tawait db\n\t\t\t.updateTable(\"trigger_evaluator_state\")\n\t\t\t.set({ last_settlement_scan_at: now })\n\t\t\t.where(\"id\", \"=\", true)\n\t\t\t.execute();\n\t\treturn 0;\n\t}\n\n\tconst rows = await readerFor(opts).settlementsConfirmedAfter(cursor);\n\tif (rows.length === 0) return 0;\n\n\tconst outboxRows: InsertWebhookOutbox[] = [];\n\tlet maxConfirmedAt = cursor;\n\tfor (const row of rows) {\n\t\tconst confirmedAt = row.confirmed_at;\n\t\tif (confirmedAt && confirmedAt > maxConfirmedAt)\n\t\t\tmaxConfirmedAt = confirmedAt;\n\t\tif (!confirmedAt) continue;\n\t\tfor (const sub of settlementSubs) {\n\t\t\t// Forward-only: a sub only receives settlements confirmed after it existed.\n\t\t\tif (confirmedAt <= sub.created_at) continue;\n\t\t\tconst trigger = triggersOf(sub).find(\n\t\t\t\t(t) => t.type === SETTLEMENT_TRIGGER_TYPE,\n\t\t\t);\n\t\t\tif (!trigger || trigger.type !== SETTLEMENT_TRIGGER_TYPE) continue;\n\t\t\tif (\n\t\t\t\ttrigger.requestId !== undefined &&\n\t\t\t\ttrigger.requestId !== Number(row.request_id)\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (\n\t\t\t\ttrigger.sweepTxid !== undefined &&\n\t\t\t\ttrigger.sweepTxid !== row.sweep_txid\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\toutboxRows.push(settlementApplyRow(sub.id, row));\n\t\t}\n\t}\n\n\tif (outboxRows.length > 0) {\n\t\tawait db\n\t\t\t.insertInto(\"webhook_outbox\")\n\t\t\t.values(outboxRows)\n\t\t\t.onConflict((oc) => oc.columns([\"webhook_id\", \"dedup_key\"]).doNothing())\n\t\t\t.execute();\n\t}\n\n\t// Advance the watermark past every settlement scanned this pass (even ones\n\t// filtered out per-sub — they're in the past for any future subscriber).\n\tawait db\n\t\t.updateTable(\"trigger_evaluator_state\")\n\t\t.set({ last_settlement_scan_at: maxConfirmedAt })\n\t\t.where(\"id\", \"=\", true)\n\t\t.execute();\n\n\treturn outboxRows.length;\n}\n\nfunction settlementApplyRow(\n\twebhookId: string,\n\trow: SettlementScanRow,\n): InsertWebhookOutbox {\n\tconst blockTime = blockTimeOf({ timestamp: Number(row.block_timestamp) });\n\tconst event: SbtcWithdrawalSweptConfirmedEvent = {\n\t\ttopic: \"withdrawal-swept-confirmed\",\n\t\trequest_id: Number(row.request_id),\n\t\tsweep_txid: row.sweep_txid,\n\t\tbtc_confirmations: row.btc_confirmations,\n\t\tbtc_block_height: row.btc_block_height,\n\t\tconfirmed_at: row.confirmed_at ? row.confirmed_at.toISOString() : null,\n\t\tamount: row.amount,\n\t\tsender: row.sender,\n\t};\n\tconst payload: ChainApplyEnvelope = {\n\t\taction: \"apply\",\n\t\tblock_hash: row.block_hash,\n\t\tblock_height: Number(row.stacks_block_height),\n\t\tblock_time: blockTime ? blockTime.toISOString() : null,\n\t\ttx_id: row.tx_id,\n\t\tcanonical: true,\n\t\ttrigger: SETTLEMENT_TRIGGER_TYPE,\n\t\tevent,\n\t};\n\treturn {\n\t\twebhook_id: webhookId,\n\t\tkind: \"chain\",\n\t\tblock_height: Number(row.stacks_block_height),\n\t\ttx_id: row.tx_id,\n\t\trow_pk: { sweep_txid: row.sweep_txid },\n\t\tevent_type: `chain.${SETTLEMENT_TRIGGER_TYPE}.apply`,\n\t\tpayload,\n\t\t// Settlement fires on a Bitcoin confirmation, not a Stacks block — dedup on\n\t\t// the sweep so a reorg→un-confirm→re-confirm cycle never re-delivers.\n\t\tdedup_key: `settlement:${webhookId}:${row.sweep_txid}`,\n\t\t...(blockTime ? { block_time: blockTime } : {}),\n\t};\n}\n"
17
17
  ],
18
18
  "mappings": "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",
19
- "debugId": "C4585E8FA353CC0264756E2164756E21",
19
+ "debugId": "39B901D4E6180ED664756E2164756E21",
20
20
  "names": []
21
21
  }