@secondlayer/subgraphs 5.0.0 → 5.0.1

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.
@@ -8,10 +8,13 @@ import { Kysely } from "kysely";
8
8
  * double-dispatch prevention.
9
9
  *
10
10
  * Must exceed the maximum possible in-flight delivery time so a slow-but-alive
11
- * receiver's row is never re-claimed mid-delivery (duplicate dispatch). The max
12
- * webhook timeout is 300_000ms (see shared/schemas/webhooks.ts:307).
11
+ * receiver's row is never re-claimed mid-delivery (duplicate dispatch). Derived
12
+ * from the configurable timeout ceiling (`WEBHOOK_TIMEOUT_MS_CEILING`, default
13
+ * 300_000ms — see `webhookTimeoutMsCeiling` in shared/schemas/webhooks.ts) so a
14
+ * raised ceiling can never create a delivery window shorter than a webhook's
15
+ * own timeout.
13
16
  */
14
- declare const MAX_WEBHOOK_TIMEOUT_MS = 3e5;
17
+ declare const MAX_WEBHOOK_TIMEOUT_MS: number;
15
18
  declare const LOCK_WINDOW_MS: number;
16
19
  interface ResolvedAddress {
17
20
  address: string;
@@ -35,19 +38,22 @@ declare function __setDnsLookupForTest(fn: DnsLookupFn | null): void;
35
38
  * pinning (resolve once, connect to that literal IP, keep the original `Host`
36
39
  * header/SNI) was attempted per plan f053 via a custom undici `Agent` with
37
40
  * `connect.lookup` passed as `fetch()`'s `dispatcher` — the standard Node
38
- * ecosystem pattern for this. Empirically, under Bun 1.3.10, that hook is
41
+ * ecosystem pattern for this. Empirically, under Bun 1.3.10, that hook was
39
42
  * silently never invoked (confirmed with a throwaway smoke test hitting a
40
43
  * real local HTTP server: `lookupCalled` stayed `false` and the connection
41
44
  * failed even though the dispatcher was passed) — Bun's `fetch()` does not
42
45
  * implement undici's `connect.lookup` dispatcher hook, whether reached via
43
46
  * the global `fetch` or `import { fetch } from "undici"` (Bun overrides
44
47
  * "undici"'s `fetch` with its own native implementation regardless of
45
- * an installed real `undici` package). So a second DNS answer between this
46
- * check and `fetch()`'s own resolution (true rebinding, not just a one-time
47
- * private answer) could in theory still slip through. This closes the
48
- * practical rebinding gap (attacker's hostname resolves private at delivery
49
- * time) without adding a dependency; a network-level egress allowlist/proxy
50
- * is the recommended defense-in-depth for the remaining TOCTOU sliver.
48
+ * an installed real `undici` package). Re-tested under Bun 1.4.2 (plan 043):
49
+ * identical result — `lookupCalled` still stays `false` via both the global
50
+ * `fetch` and `import { fetch } from "undici"`, so the gap remains unfixed at
51
+ * this version too. So a second DNS answer between this check and `fetch()`'s
52
+ * own resolution (true rebinding, not just a one-time private answer) could
53
+ * in theory still slip through. This closes the practical rebinding gap
54
+ * (attacker's hostname resolves private at delivery time) without adding a
55
+ * dependency; a network-level egress allowlist/proxy is the recommended
56
+ * defense-in-depth for the remaining TOCTOU sliver.
51
57
  */
52
58
  declare function checkEgressAllowed(url: string): Promise<string | null>;
53
59
  /** The wire result of one POST attempt (no DB side effect) — shared by the
@@ -7,6 +7,9 @@ import {
7
7
  import { getWebhookSigningSecret } from "@secondlayer/shared/db/queries/webhooks";
8
8
  import { logger as logger2 } from "@secondlayer/shared/logger";
9
9
  import { listen, targetListenerUrl } from "@secondlayer/shared/queue/listener";
10
+ import {
11
+ webhookTimeoutMsCeiling
12
+ } from "@secondlayer/shared/schemas/webhooks";
10
13
  import { sql as sql2 } from "kysely";
11
14
 
12
15
  // src/runtime/formats/index.ts
@@ -351,7 +354,7 @@ var BATCH_SIZE = 50;
351
354
  var LIVE_SHARE = 0.9;
352
355
  var BACKOFF_SECONDS = [30, 120, 600, 3600, 21600, 86400, 259200];
353
356
  var CIRCUIT_THRESHOLD = 20;
354
- var MAX_WEBHOOK_TIMEOUT_MS = 300000;
357
+ var MAX_WEBHOOK_TIMEOUT_MS = webhookTimeoutMsCeiling();
355
358
  var LOCK_WINDOW_MS = MAX_WEBHOOK_TIMEOUT_MS + 60000;
356
359
  function nextDelaySeconds(attempt) {
357
360
  return BACKOFF_SECONDS[Math.min(attempt, BACKOFF_SECONDS.length - 1)];
@@ -363,7 +366,10 @@ var PRIVATE_V4_PATTERNS = [
363
366
  /^192\.168\./,
364
367
  /^169\.254\./,
365
368
  /^0\./,
366
- /^100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\./
369
+ /^100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\./,
370
+ /^198\.(1[89])\./,
371
+ /^(22[4-9]|23[0-9])\./,
372
+ /^(24[0-9]|25[0-5])\./
367
373
  ];
368
374
  function isPrivateIp(address) {
369
375
  const host = address.toLowerCase();
@@ -375,6 +381,8 @@ function isPrivateIp(address) {
375
381
  return true;
376
382
  if (/^fe[89ab][0-9a-f]:/.test(host))
377
383
  return true;
384
+ if (/^ff[0-9a-f]{2}:/.test(host))
385
+ return true;
378
386
  const mapped = host.match(/^::ffff:(.+)$/);
379
387
  if (mapped) {
380
388
  const inner = mapped[1];
@@ -394,6 +402,25 @@ function isPrivateIp(address) {
394
402
  }
395
403
  return false;
396
404
  }
405
+ const nat64 = host.match(/^64:ff9b::(.+)$/);
406
+ if (nat64) {
407
+ const inner = nat64[1];
408
+ if (/^\d+\.\d+\.\d+\.\d+$/.test(inner)) {
409
+ for (const p of PRIVATE_V4_PATTERNS)
410
+ if (p.test(inner))
411
+ return true;
412
+ }
413
+ const hex = inner.match(/^([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);
414
+ if (hex) {
415
+ const a = Number.parseInt(hex[1], 16);
416
+ const b = Number.parseInt(hex[2], 16);
417
+ const dotted = `${a >> 8 & 255}.${a & 255}.${b >> 8 & 255}.${b & 255}`;
418
+ for (const p of PRIVATE_V4_PATTERNS)
419
+ if (p.test(dotted))
420
+ return true;
421
+ }
422
+ return false;
423
+ }
397
424
  for (const p of PRIVATE_V4_PATTERNS) {
398
425
  if (p.test(host))
399
426
  return true;
@@ -578,6 +605,7 @@ function buildTestOutboxRow(sub) {
578
605
  failed_at: null,
579
606
  locked_by: null,
580
607
  locked_until: null,
608
+ last_error: null,
581
609
  created_at: now
582
610
  };
583
611
  }
@@ -605,13 +633,21 @@ async function deliverTestEvent(db, sub) {
605
633
  }
606
634
  async function settleDelivered(db, outboxRow) {
607
635
  await db.transaction().execute(async (tx) => {
608
- await tx.updateTable("webhook_outbox").set({
636
+ const result = await tx.updateTable("webhook_outbox").set({
609
637
  status: "delivered",
610
638
  delivered_at: new Date,
611
639
  attempt: outboxRow.attempt + 1,
612
640
  locked_by: null,
613
641
  locked_until: null
614
- }).where("id", "=", outboxRow.id).execute();
642
+ }).where("id", "=", outboxRow.id).where("status", "=", "pending").executeTakeFirst();
643
+ if (Number(result.numUpdatedRows ?? 0) === 0) {
644
+ logger2.info("webhook.settle.orphaned", {
645
+ outboxId: outboxRow.id,
646
+ webhookId: outboxRow.webhook_id,
647
+ outcome: "delivered"
648
+ });
649
+ return;
650
+ }
615
651
  await tx.updateTable("webhooks").set({
616
652
  last_delivery_at: new Date,
617
653
  last_success_at: new Date,
@@ -626,14 +662,22 @@ async function settleFailed(db, outboxRow, sub, errText) {
626
662
  const isDead = attempt >= sub.max_retries;
627
663
  const nextAt = isDead ? null : new Date(Date.now() + nextDelaySeconds(outboxRow.attempt) * 1000);
628
664
  await db.transaction().execute(async (tx) => {
629
- await tx.updateTable("webhook_outbox").set({
665
+ const result = await tx.updateTable("webhook_outbox").set({
630
666
  attempt,
631
667
  next_attempt_at: nextAt ?? new Date,
632
668
  status: isDead ? "dead" : "pending",
633
669
  failed_at: isDead ? new Date : null,
634
670
  locked_by: null,
635
671
  locked_until: null
636
- }).where("id", "=", outboxRow.id).execute();
672
+ }).where("id", "=", outboxRow.id).where("status", "=", "pending").executeTakeFirst();
673
+ if (Number(result.numUpdatedRows ?? 0) === 0) {
674
+ logger2.info("webhook.settle.orphaned", {
675
+ outboxId: outboxRow.id,
676
+ webhookId: outboxRow.webhook_id,
677
+ outcome: "failed"
678
+ });
679
+ return;
680
+ }
637
681
  const incResult = await sql2`
638
682
  UPDATE webhooks
639
683
  SET circuit_failures = circuit_failures + 1,
@@ -850,5 +894,5 @@ export {
850
894
  startEmitter
851
895
  };
852
896
 
853
- //# debugId=D84E68FAE42C8C7164756E2164756E21
897
+ //# debugId=98ABC6AECB995F9064756E2164756E21
854
898
  //# sourceMappingURL=emitter.js.map
@@ -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/webhook-state.ts", "../src/runtime/emitter-matcher.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\tgetTargetDb,\n} from \"@secondlayer/shared/db\";\nimport { getWebhookSigningSecret } from \"@secondlayer/shared/db/queries/webhooks\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport { listen, targetListenerUrl } from \"@secondlayer/shared/queue/listener\";\nimport type { WebhookTestResult } from \"@secondlayer/shared/schemas/webhooks\";\nimport { type Kysely, sql } from \"kysely\";\nimport { buildForFormat } from \"./formats/index.ts\";\nimport { refreshMatcher } from \"./webhook-state.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). The max\n * webhook timeout is 300_000ms (see shared/schemas/webhooks.ts:307).\n */\nexport const MAX_WEBHOOK_TIMEOUT_MS = 300_000;\nexport const LOCK_WINDOW_MS: number = MAX_WEBHOOK_TIMEOUT_MS + 60_000; // 6 min: max timeout + settle margin\n\ninterface RunningState {\n\trunning: boolean;\n\tinFlightBySub: Map<string, number>;\n\tclaimInFlight: boolean;\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];\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`, IPv6 loopback (`::1`),\n * unspecified (`::`), unique-local (`fc00::/7`), link-local (`fe80::/10`), and\n * IPv4-mapped IPv6 (`::ffff:127.0.0.1`, `::ffff:7f00:0001`).\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)\n\tif (/^f[cd][0-9a-f]{2}:/.test(host)) return true;\n\tif (/^fe[89ab][0-9a-f]:/.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\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\nfunction 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 is\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). So a second DNS answer between this\n * check and `fetch()`'s own resolution (true rebinding, not just a one-time\n * private answer) could in theory still slip through. This closes the\n * practical rebinding gap (attacker's hostname resolves private at delivery\n * time) without adding a dependency; a network-level egress allowlist/proxy\n * is the recommended 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, shaped to the\n * webhook's kind so `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\tsubgraph_name: sub.subgraph_name ?? null,\n\t\ttable_name: sub.table_name ?? null,\n\t\tblock_height: 0,\n\t\ttx_id: null,\n\t\trow_pk: null,\n\t\tevent_type:\n\t\t\tsub.kind === \"chain\"\n\t\t\t\t? \"chain.test.apply\"\n\t\t\t\t: `${sub.subgraph_name ?? \"subgraph\"}.${sub.table_name ?? \"test\"}.created`,\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\tdelivered_at: null,\n\t\tfailed_at: null,\n\t\tlocked_by: null,\n\t\tlocked_until: 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\tawait 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.where(\"id\", \"=\", outboxRow.id)\n\t\t\t.execute();\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\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\tawait 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.where(\"id\", \"=\", outboxRow.id)\n\t\t\t.execute();\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\nasync function claimAndDrain(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\temitterId: string,\n): Promise<number> {\n\tif (state.claimInFlight) return 0;\n\tstate.claimInFlight = true;\n\ttry {\n\t\t// FOR UPDATE SKIP LOCKED — multiple emitters split the batch.\n\t\t// 90/10 live vs replay so a big replay doesn't starve live emits.\n\t\tconst liveLimit = Math.max(1, Math.round(BATCH_SIZE * LIVE_SHARE));\n\t\tconst replayLimit = BATCH_SIZE - liveLimit;\n\t\tconst claimed = await db.transaction().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 combined = [...live.rows, ...replay.rows];\n\t\t\tif (combined.length === 0) return [];\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.\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\tcombined.map((r) => r.id),\n\t\t\t\t)\n\t\t\t\t.execute();\n\t\t\treturn combined;\n\t\t});\n\n\t\tif (claimed.length === 0) return 0;\n\n\t\t// Hydrate each claimed row's sub once, then dispatch with per-sub\n\t\t// concurrency cap enforced via in-memory semaphore.\n\t\tconst bySubId = new Map<string, WebhookOutbox[]>();\n\t\tfor (const row of claimed) {\n\t\t\tconst arr = bySubId.get(row.webhook_id);\n\t\t\tif (arr) arr.push(row);\n\t\t\telse bySubId.set(row.webhook_id, [row]);\n\t\t}\n\n\t\tconst subIds = Array.from(bySubId.keys());\n\t\tconst subs = await db\n\t\t\t.selectFrom(\"webhooks\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"in\", subIds)\n\t\t\t.execute();\n\t\tconst subById = new Map(subs.map((s) => [s.id, s]));\n\n\t\tawait Promise.all(\n\t\t\tsubIds.map((subId) =>\n\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\t\t\tdrainForSub(db, state, subById.get(subId)!, bySubId.get(subId)!),\n\t\t\t),\n\t\t);\n\n\t\treturn claimed.length;\n\t} finally {\n\t\tstate.claimInFlight = false;\n\t}\n}\n\nasync function drainForSub(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\tsub: Webhook,\n\trows: WebhookOutbox[],\n): Promise<void> {\n\tif (sub.status !== \"active\") return;\n\tconst cap = sub.concurrency || 4;\n\tconst counter = () => state.inFlightBySub.get(sub.id) ?? 0;\n\tconst inc = () => state.inFlightBySub.set(sub.id, counter() + 1);\n\tconst dec = () => state.inFlightBySub.set(sub.id, Math.max(0, counter() - 1));\n\n\tconst queue = [...rows];\n\tconst workers: Promise<void>[] = [];\n\tconst slots = Math.min(cap, queue.length);\n\n\tfor (let i = 0; i < slots; i++) {\n\t\tworkers.push(\n\t\t\t(async () => {\n\t\t\t\twhile (state.running && queue.length > 0) {\n\t\t\t\t\tconst row = queue.shift();\n\t\t\t\t\tif (!row) break;\n\t\t\t\t\tinc();\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = await dispatchOne(db, row, sub);\n\t\t\t\t\t\tif (result.ok) {\n\t\t\t\t\t\t\tawait settleDelivered(db, row);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst err = result.error ?? `HTTP ${result.statusCode ?? \"?\"}`;\n\t\t\t\t\t\t\tawait settleFailed(db, row, sub, err);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tlogger.error(\"Emitter dispatch crashed\", {\n\t\t\t\t\t\t\toutboxId: row.id,\n\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tawait settleFailed(\n\t\t\t\t\t\t\tdb,\n\t\t\t\t\t\t\trow,\n\t\t\t\t\t\t\tsub,\n\t\t\t\t\t\t\terr instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdec();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})(),\n\t\t);\n\t}\n\tawait Promise.all(workers);\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}\n\nasync function runRetention(db: Kysely<Database>): Promise<void> {\n\t// delivered outbox >7d, deliveries >30d, dead outbox >90d\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}\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\tinFlightBySub: new Map(),\n\t\tclaimInFlight: false,\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// Bootstrap matcher from active subs. Retry with backoff — if this\n\t// stays broken, fail loud rather than run with an empty matcher (which\n\t// would silently drop every block's outbox emissions until the next\n\t// webhook CRUD fired `webhooks:changed`).\n\tconst MATCHER_BOOT_ATTEMPTS = 5;\n\tlet lastErr: unknown = null;\n\tfor (let i = 0; i < MATCHER_BOOT_ATTEMPTS; i++) {\n\t\ttry {\n\t\t\tawait refreshMatcher(db);\n\t\t\tlastErr = null;\n\t\t\tbreak;\n\t\t} catch (err) {\n\t\t\tlastErr = err;\n\t\t\tconst delayMs = 500 * 2 ** i; // 500ms, 1s, 2s, 4s, 8s\n\t\t\tlogger.warn(\"[emitter] matcher refresh failed, retrying\", {\n\t\t\t\tattempt: i + 1,\n\t\t\t\tdelayMs,\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t});\n\t\t\tawait new Promise((r) => setTimeout(r, delayMs));\n\t\t}\n\t}\n\tif (lastErr) {\n\t\tthrow new Error(\n\t\t\t`[emitter] matcher refresh failed ${MATCHER_BOOT_ATTEMPTS}×; aborting boot: ${\n\t\t\t\tlastErr instanceof Error ? lastErr.message : String(lastErr)\n\t\t\t}`,\n\t\t);\n\t}\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).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\tvoid refreshMatcher(db).catch((err) =>\n\t\t\t\tlogger.error(\"[emitter] matcher refresh 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\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).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);\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\treturn async () => {\n\t\tstate.running = false;\n\t\tclearInterval(poll);\n\t\tclearInterval(retention);\n\t\tawait stopNew();\n\t\tawait stopChanged();\n\t\tlogger.info(\"[emitter] stopped\", { id: emitterId });\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\tgetTargetDb,\n} from \"@secondlayer/shared/db\";\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 { refreshMatcher } from \"./webhook-state.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\ninterface RunningState {\n\trunning: boolean;\n\tinFlightBySub: Map<string, number>;\n\tclaimInFlight: boolean;\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\nfunction 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, shaped to the\n * webhook's kind so `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\tsubgraph_name: sub.subgraph_name ?? null,\n\t\ttable_name: sub.table_name ?? null,\n\t\tblock_height: 0,\n\t\ttx_id: null,\n\t\trow_pk: null,\n\t\tevent_type:\n\t\t\tsub.kind === \"chain\"\n\t\t\t\t? \"chain.test.apply\"\n\t\t\t\t: `${sub.subgraph_name ?? \"subgraph\"}.${sub.table_name ?? \"test\"}.created`,\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\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\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\nasync function claimAndDrain(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\temitterId: string,\n): Promise<number> {\n\tif (state.claimInFlight) return 0;\n\tstate.claimInFlight = true;\n\ttry {\n\t\t// FOR UPDATE SKIP LOCKED — multiple emitters split the batch.\n\t\t// 90/10 live vs replay so a big replay doesn't starve live emits.\n\t\tconst liveLimit = Math.max(1, Math.round(BATCH_SIZE * LIVE_SHARE));\n\t\tconst replayLimit = BATCH_SIZE - liveLimit;\n\t\tconst claimed = await db.transaction().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 combined = [...live.rows, ...replay.rows];\n\t\t\tif (combined.length === 0) return [];\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.\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\tcombined.map((r) => r.id),\n\t\t\t\t)\n\t\t\t\t.execute();\n\t\t\treturn combined;\n\t\t});\n\n\t\tif (claimed.length === 0) return 0;\n\n\t\t// Hydrate each claimed row's sub once, then dispatch with per-sub\n\t\t// concurrency cap enforced via in-memory semaphore.\n\t\tconst bySubId = new Map<string, WebhookOutbox[]>();\n\t\tfor (const row of claimed) {\n\t\t\tconst arr = bySubId.get(row.webhook_id);\n\t\t\tif (arr) arr.push(row);\n\t\t\telse bySubId.set(row.webhook_id, [row]);\n\t\t}\n\n\t\tconst subIds = Array.from(bySubId.keys());\n\t\tconst subs = await db\n\t\t\t.selectFrom(\"webhooks\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"in\", subIds)\n\t\t\t.execute();\n\t\tconst subById = new Map(subs.map((s) => [s.id, s]));\n\n\t\tawait Promise.all(\n\t\t\tsubIds.map((subId) =>\n\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\t\t\tdrainForSub(db, state, subById.get(subId)!, bySubId.get(subId)!),\n\t\t\t),\n\t\t);\n\n\t\treturn claimed.length;\n\t} finally {\n\t\tstate.claimInFlight = false;\n\t}\n}\n\nasync function drainForSub(\n\tdb: Kysely<Database>,\n\tstate: RunningState,\n\tsub: Webhook,\n\trows: WebhookOutbox[],\n): Promise<void> {\n\tif (sub.status !== \"active\") return;\n\tconst cap = sub.concurrency || 4;\n\tconst counter = () => state.inFlightBySub.get(sub.id) ?? 0;\n\tconst inc = () => state.inFlightBySub.set(sub.id, counter() + 1);\n\tconst dec = () => state.inFlightBySub.set(sub.id, Math.max(0, counter() - 1));\n\n\tconst queue = [...rows];\n\tconst workers: Promise<void>[] = [];\n\tconst slots = Math.min(cap, queue.length);\n\n\tfor (let i = 0; i < slots; i++) {\n\t\tworkers.push(\n\t\t\t(async () => {\n\t\t\t\twhile (state.running && queue.length > 0) {\n\t\t\t\t\tconst row = queue.shift();\n\t\t\t\t\tif (!row) break;\n\t\t\t\t\tinc();\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = await dispatchOne(db, row, sub);\n\t\t\t\t\t\tif (result.ok) {\n\t\t\t\t\t\t\tawait settleDelivered(db, row);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst err = result.error ?? `HTTP ${result.statusCode ?? \"?\"}`;\n\t\t\t\t\t\t\tawait settleFailed(db, row, sub, err);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tlogger.error(\"Emitter dispatch crashed\", {\n\t\t\t\t\t\t\toutboxId: row.id,\n\t\t\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tawait settleFailed(\n\t\t\t\t\t\t\tdb,\n\t\t\t\t\t\t\trow,\n\t\t\t\t\t\t\tsub,\n\t\t\t\t\t\t\terr instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tdec();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})(),\n\t\t);\n\t}\n\tawait Promise.all(workers);\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}\n\nasync function runRetention(db: Kysely<Database>): Promise<void> {\n\t// delivered outbox >7d, deliveries >30d, dead outbox >90d\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}\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\tinFlightBySub: new Map(),\n\t\tclaimInFlight: false,\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// Bootstrap matcher from active subs. Retry with backoff — if this\n\t// stays broken, fail loud rather than run with an empty matcher (which\n\t// would silently drop every block's outbox emissions until the next\n\t// webhook CRUD fired `webhooks:changed`).\n\tconst MATCHER_BOOT_ATTEMPTS = 5;\n\tlet lastErr: unknown = null;\n\tfor (let i = 0; i < MATCHER_BOOT_ATTEMPTS; i++) {\n\t\ttry {\n\t\t\tawait refreshMatcher(db);\n\t\t\tlastErr = null;\n\t\t\tbreak;\n\t\t} catch (err) {\n\t\t\tlastErr = err;\n\t\t\tconst delayMs = 500 * 2 ** i; // 500ms, 1s, 2s, 4s, 8s\n\t\t\tlogger.warn(\"[emitter] matcher refresh failed, retrying\", {\n\t\t\t\tattempt: i + 1,\n\t\t\t\tdelayMs,\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t});\n\t\t\tawait new Promise((r) => setTimeout(r, delayMs));\n\t\t}\n\t}\n\tif (lastErr) {\n\t\tthrow new Error(\n\t\t\t`[emitter] matcher refresh failed ${MATCHER_BOOT_ATTEMPTS}×; aborting boot: ${\n\t\t\t\tlastErr instanceof Error ? lastErr.message : String(lastErr)\n\t\t\t}`,\n\t\t);\n\t}\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).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\tvoid refreshMatcher(db).catch((err) =>\n\t\t\t\tlogger.error(\"[emitter] matcher refresh 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\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).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);\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\treturn async () => {\n\t\tstate.running = false;\n\t\tclearInterval(poll);\n\t\tclearInterval(retention);\n\t\tawait stopNew();\n\t\tawait stopChanged();\n\t\tlogger.info(\"[emitter] stopped\", { id: emitterId });\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\nexport {\n\tbuildStandardWebhooks,\n\tbuildInngest,\n\tbuildTrigger,\n\tbuildCloudflare,\n\tbuildCloudEvents,\n\tbuildRaw,\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\": \"<subgraph>.<table>.<created|updated|deleted>\",\n * \"source\": \"secondlayer:<subgraph_name>\",\n * \"id\": <outbox.id>, // UUID, used for dedup\n * \"time\": <ISO 8601>,\n * \"datacontenttype\": \"application/json\",\n * \"data\": { ...row }\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\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:${outboxRow.subgraph_name}`,\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
  "import type { Database, Webhook } from \"@secondlayer/shared/db\";\nimport type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\nimport { WebhookMatcher } from \"./emitter-matcher.ts\";\n\n/**\n * Singleton matcher populated at processor startup and hot-reloaded via\n * `pg_notify('webhooks:changed')`. The block-processor reads from it\n * to decide which outbox rows to emit for each flushed write.\n */\n\nexport const matcher = new WebhookMatcher();\n\nexport async function refreshMatcher(db: Kysely<Database>): Promise<number> {\n\tconst rows = await sql<Webhook>`\n\t\tSELECT * FROM webhooks WHERE status = 'active'\n\t`.execute(db);\n\tmatcher.setAll(rows.rows);\n\treturn matcher.size();\n}\n",
14
14
  "import type { Webhook } from \"@secondlayer/shared/db\";\n\n/**\n * Webhook matcher — holds the active-webhooks cache keyed by\n * `(subgraph_name, table_name)` and evaluates each sub's scalar-only\n * JSONB filter against a row.\n *\n * Filter DSL (v1): scalar operators over string/number/boolean columns.\n * { column: value } → column === value\n * { column: { eq: value } } → column === value\n * { column: { neq: value } } → column !== value\n * { column: { gt|gte|lt|lte: N } } → numeric compare\n * { column: { in: [a, b, c] } } → column ∈ set\n * { } → match all\n *\n * Nested objects, arrays, and non-scalar values are rejected with `false`\n * (never match) — subscribers get logged warnings at sub create time.\n *\n * Multiple conditions AND together. OR is deliberately absent in v1.\n */\n\nexport type FilterPrimitive = string | number | boolean;\nexport type FilterOperator =\n\t| { eq: FilterPrimitive }\n\t| { neq: FilterPrimitive }\n\t| { gt: number | string }\n\t| { gte: number | string }\n\t| { lt: number | string }\n\t| { lte: number | string }\n\t| { in: FilterPrimitive[] };\n\nexport type FilterClause = FilterPrimitive | FilterOperator;\nexport type WebhookFilter = Record<string, FilterClause>;\n\nfunction isPrimitive(v: unknown): v is FilterPrimitive {\n\tconst t = typeof v;\n\treturn t === \"string\" || t === \"number\" || t === \"boolean\";\n}\n\n/**\n * Coerce a value to BigInt for arbitrary-precision compare — avoids the\n * silent precision loss of `Number()` on integers past 2^53. Returns\n * `null` for non-integer numerics, which is fine because the filter DSL\n * is documented as scalar-only + integer-amount-aware (Stacks uses\n * uint128 bigint columns everywhere).\n */\nfunction coerceBigInt(v: unknown): bigint | null {\n\tif (typeof v === \"bigint\") return v;\n\tif (typeof v === \"number\") {\n\t\tif (!Number.isFinite(v)) return null;\n\t\tif (!Number.isInteger(v)) return null;\n\t\treturn BigInt(v);\n\t}\n\tif (typeof v === \"string\" && /^-?\\d+$/.test(v)) {\n\t\ttry {\n\t\t\treturn BigInt(v);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\treturn null;\n}\n\n/**\n * Float compare fallback — used when a value isn't a clean integer\n * (rare in subgraph columns but defensible for user-supplied filters).\n */\nfunction coerceFloat(v: unknown): number | null {\n\tif (typeof v === \"number\" && Number.isFinite(v)) return v;\n\tif (typeof v === \"bigint\") return Number(v);\n\tif (typeof v === \"string\" && v !== \"\" && !Number.isNaN(Number(v))) {\n\t\treturn Number(v);\n\t}\n\treturn null;\n}\n\nfunction compareNumeric(a: unknown, b: unknown): 0 | 1 | -1 | null {\n\tconst ba = coerceBigInt(a);\n\tconst bb = coerceBigInt(b);\n\tif (ba !== null && bb !== null) {\n\t\tif (ba === bb) return 0;\n\t\treturn ba > bb ? 1 : -1;\n\t}\n\tconst fa = coerceFloat(a);\n\tconst fb = coerceFloat(b);\n\tif (fa === null || fb === null) return null;\n\tif (fa === fb) return 0;\n\treturn fa > fb ? 1 : -1;\n}\n\nfunction matchClause(rowValue: unknown, clause: FilterClause): boolean {\n\t// Reject non-primitive row values — `{ value: {...} }` should not\n\t// match `filter: { value: \"[object Object]\" }` via loose stringify.\n\t// Bigints are not primitives in the JSON sense but are supported\n\t// scalar inputs from subgraph rows.\n\tconst rowIsPrimitive = isPrimitive(rowValue) || typeof rowValue === \"bigint\";\n\n\tif (isPrimitive(clause)) {\n\t\tif (!rowIsPrimitive) return false;\n\t\tif (\n\t\t\ttypeof clause === \"number\" ||\n\t\t\ttypeof rowValue === \"number\" ||\n\t\t\ttypeof rowValue === \"bigint\"\n\t\t) {\n\t\t\tconst cmp = compareNumeric(rowValue, clause);\n\t\t\tif (cmp !== null) return cmp === 0;\n\t\t}\n\t\treturn rowValue === clause || String(rowValue) === String(clause);\n\t}\n\n\tif (clause === null || typeof clause !== \"object\" || Array.isArray(clause)) {\n\t\treturn false;\n\t}\n\n\tconst keys = Object.keys(clause);\n\tif (keys.length !== 1) return false;\n\tconst op = keys[0];\n\n\tconst c = clause as Record<string, unknown>;\n\tswitch (op) {\n\t\tcase \"eq\":\n\t\t\treturn matchClause(rowValue, c.eq as FilterPrimitive);\n\t\tcase \"neq\":\n\t\t\treturn !matchClause(rowValue, c.neq as FilterPrimitive);\n\t\tcase \"gt\":\n\t\tcase \"gte\":\n\t\tcase \"lt\":\n\t\tcase \"lte\": {\n\t\t\tif (!rowIsPrimitive) return false;\n\t\t\tconst cmp = compareNumeric(rowValue, c[op]);\n\t\t\tif (cmp === null) return false;\n\t\t\tif (op === \"gt\") return cmp > 0;\n\t\t\tif (op === \"gte\") return cmp >= 0;\n\t\t\tif (op === \"lt\") return cmp < 0;\n\t\t\treturn cmp <= 0;\n\t\t}\n\t\tcase \"in\": {\n\t\t\tconst list = c.in;\n\t\t\tif (!Array.isArray(list)) return false;\n\t\t\tif (!rowIsPrimitive) return false;\n\t\t\treturn list.some(\n\t\t\t\t(item) => isPrimitive(item) && matchClause(rowValue, item),\n\t\t\t);\n\t\t}\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function matchesFilter(\n\tfilter: WebhookFilter | null | undefined,\n\trow: Record<string, unknown>,\n): boolean {\n\tif (!filter || Object.keys(filter).length === 0) return true;\n\tfor (const [col, clause] of Object.entries(filter)) {\n\t\tif (!matchClause(row[col], clause)) return false;\n\t}\n\treturn true;\n}\n\n// ── Cache keyed by (subgraph_name, table_name) ──────────────────────────\n\ntype MatcherKey = string;\n\nfunction key(subgraphName: string, tableName: string): MatcherKey {\n\treturn `${subgraphName}\u0000${tableName}`;\n}\n\nexport class WebhookMatcher {\n\tprivate readonly byKey = new Map<MatcherKey, Webhook[]>();\n\tprivate readonly byId = new Map<string, Webhook>();\n\n\t/** Replace the entire cache with a fresh snapshot. */\n\tsetAll(subs: Webhook[]): void {\n\t\tthis.byKey.clear();\n\t\tthis.byId.clear();\n\t\tfor (const sub of subs) {\n\t\t\tif (sub.status !== \"active\") continue;\n\t\t\t// This matcher keys on (subgraph, table) row writes; chain\n\t\t\t// webhooks react to raw chain events and never flow through it.\n\t\t\tif (sub.kind !== \"subgraph\" || !sub.subgraph_name || !sub.table_name)\n\t\t\t\tcontinue;\n\t\t\tthis.byId.set(sub.id, sub);\n\t\t\tconst k = key(sub.subgraph_name, sub.table_name);\n\t\t\tconst arr = this.byKey.get(k);\n\t\t\tif (arr) arr.push(sub);\n\t\t\telse this.byKey.set(k, [sub]);\n\t\t}\n\t}\n\n\t/** Returns active subs for a (subgraph, table) whose filter matches the row. */\n\tmatch(\n\t\tsubgraphName: string,\n\t\ttableName: string,\n\t\trow: Record<string, unknown>,\n\t): Webhook[] {\n\t\tconst bucket = this.byKey.get(key(subgraphName, tableName));\n\t\tif (!bucket) return [];\n\t\tconst hits: Webhook[] = [];\n\t\tfor (const sub of bucket) {\n\t\t\tif (matchesFilter(sub.filter as WebhookFilter, row)) hits.push(sub);\n\t\t}\n\t\treturn hits;\n\t}\n\n\thas(subgraphName: string, tableName: string): boolean {\n\t\treturn this.byKey.has(key(subgraphName, tableName));\n\t}\n\n\tsize(): number {\n\t\treturn this.byId.size;\n\t}\n\n\tget(id: string): Webhook | undefined {\n\t\treturn this.byId.get(id);\n\t}\n}\n"
15
15
  ],
16
- "mappings": "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",
17
- "debugId": "D84E68FAE42C8C7164756E2164756E21",
16
+ "mappings": "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",
17
+ "debugId": "98ABC6AECB995F9064756E2164756E21",
18
18
  "names": []
19
19
  }
@@ -34,6 +34,20 @@ interface BlockSource {
34
34
  * the range is empty. Optional — only event-scoped sources support it. */
35
35
  nextDataHeight?(afterHeight: number, untilHeight: number): Promise<number | null>;
36
36
  }
37
+ /** Thrown by {@link replayWebhook} when a replay is already running for the
38
+ * webhook. The route maps this to 409; `force` does not bypass it — a forced
39
+ * re-delivery still has to wait for the previous replay to finish. */
40
+ declare class ReplayInProgressError extends Error {
41
+ constructor();
42
+ }
43
+ /**
44
+ * Test-only seam: directly mark (or clear) a webhook as having an in-flight
45
+ * replay. Two real concurrent `replayWebhook` calls race the same DB fetch,
46
+ * so which one wins the guard isn't deterministic in a test; this lets a test
47
+ * exercise the guard (and the route's 409 mapping) without that race.
48
+ * Production code never calls this.
49
+ */
50
+ declare function __setReplayInFlightForTest(webhookId: string, inFlight: boolean): void;
37
51
  interface ReplayInput {
38
52
  accountId: string;
39
53
  webhookId: string;
@@ -61,4 +75,4 @@ declare function replayWebhook(input: ReplayInput): Promise<ReplayResult>;
61
75
  declare function replayChainWebhook(db: Kysely3<Database3>, sub: Webhook, input: ReplayInput, opts?: {
62
76
  source?: BlockSource
63
77
  }): Promise<ReplayResult>;
64
- export { ReplayInput, ReplayResult, replayChainWebhook, replayWebhook };
78
+ export { ReplayInProgressError, ReplayInput, ReplayResult, __setReplayInFlightForTest, replayChainWebhook, replayWebhook };
@@ -1006,6 +1006,31 @@ async function emitSbtcOutbox(db, chainSubs, blockHeight, blockHash, opts) {
1006
1006
 
1007
1007
  // src/runtime/replay.ts
1008
1008
  var BATCH_SIZE = 500;
1009
+ var WEBHOOK_REPLAY_MAX_BLOCKS_DEFAULT = 1e5;
1010
+ function webhookReplayMaxBlocks() {
1011
+ const raw = process.env.WEBHOOK_REPLAY_MAX_BLOCKS;
1012
+ if (raw === undefined)
1013
+ return WEBHOOK_REPLAY_MAX_BLOCKS_DEFAULT;
1014
+ const parsed = Number.parseInt(raw, 10);
1015
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : WEBHOOK_REPLAY_MAX_BLOCKS_DEFAULT;
1016
+ }
1017
+ function formatBlockCount(n) {
1018
+ return n % 1000 === 0 ? `${n / 1000}k` : `${n}`;
1019
+ }
1020
+ var inFlightReplays = new Set;
1021
+
1022
+ class ReplayInProgressError extends Error {
1023
+ constructor() {
1024
+ super("replay already in progress for this webhook");
1025
+ this.name = "ReplayInProgressError";
1026
+ }
1027
+ }
1028
+ function __setReplayInFlightForTest(webhookId, inFlight) {
1029
+ if (inFlight)
1030
+ inFlightReplays.add(webhookId);
1031
+ else
1032
+ inFlightReplays.delete(webhookId);
1033
+ }
1009
1034
  function replayDedupKey(subgraphName, tableName, row, replayId) {
1010
1035
  const canonical = `replay:${replayId}:${subgraphName}:${tableName}:${stableStringify(row)}`;
1011
1036
  return createHash("sha256").update(canonical).digest("hex").slice(0, 32);
@@ -1032,67 +1057,76 @@ async function replayWebhook(input) {
1032
1057
  if (input.fromBlock > input.toBlock) {
1033
1058
  throw new Error("fromBlock must be <= toBlock");
1034
1059
  }
1035
- if (input.toBlock - input.fromBlock > 1e5) {
1036
- throw new Error("replay range exceeds 100k blocks");
1060
+ const maxBlocks = webhookReplayMaxBlocks();
1061
+ if (input.toBlock - input.fromBlock > maxBlocks) {
1062
+ throw new Error(`replay range exceeds ${formatBlockCount(maxBlocks)} blocks`);
1037
1063
  }
1038
1064
  const db = getTargetDb();
1039
1065
  const sub = await getWebhook(db, input.accountId, input.webhookId);
1040
1066
  if (!sub)
1041
1067
  throw new Error("Webhook not found");
1042
- if (sub.kind === "chain") {
1043
- return replayChainWebhook(db, sub, input);
1044
- }
1045
- const subgraphName = sub.subgraph_name;
1046
- const tableName = sub.table_name;
1047
- if (sub.kind !== "subgraph" || !subgraphName || !tableName) {
1048
- throw new Error("replay is only supported for subgraph or chain webhooks");
1068
+ if (inFlightReplays.has(sub.id)) {
1069
+ throw new ReplayInProgressError;
1049
1070
  }
1050
- const schema = await resolveSchemaName(db, subgraphName);
1051
- const replayId = deterministicReplayId(sub.id, input.fromBlock, input.toBlock, input.replayIdSuffix);
1052
- let scanned = 0;
1053
- let enqueued = 0;
1054
- let lastId = 0n;
1055
- while (true) {
1056
- const { rows } = await sql`SELECT * FROM ${sql.raw(`"${schema}"."${tableName}"`)}
1057
- WHERE _block_height >= ${sql.lit(input.fromBlock)}
1058
- AND _block_height <= ${sql.lit(input.toBlock)}
1059
- AND _id > ${sql.lit(lastId)}
1060
- ORDER BY _id ASC
1061
- LIMIT ${sql.lit(BATCH_SIZE)}`.execute(db);
1062
- if (rows.length === 0)
1063
- break;
1064
- scanned += rows.length;
1065
- const inserts = rows.map((row) => ({
1066
- webhook_id: sub.id,
1067
- subgraph_name: subgraphName,
1068
- table_name: tableName,
1069
- block_height: Number(row._block_height),
1070
- tx_id: row._tx_id ?? null,
1071
- row_pk: {
1072
- blockHeight: Number(row._block_height),
1073
- txId: row._tx_id ?? "",
1074
- replayId
1075
- },
1076
- event_type: `${subgraphName}.${tableName}.replay`,
1077
- payload: row,
1078
- dedup_key: replayDedupKey(subgraphName, tableName, row, replayId),
1079
- is_replay: true
1080
- }));
1081
- const result = await db.insertInto("webhook_outbox").values(inserts).onConflict((oc) => oc.columns(["webhook_id", "dedup_key"]).doNothing()).executeTakeFirst();
1082
- enqueued += Number(result.numInsertedOrUpdatedRows ?? 0);
1083
- lastId = BigInt(String(rows[rows.length - 1]?._id));
1084
- if (rows.length < BATCH_SIZE)
1085
- break;
1071
+ inFlightReplays.add(sub.id);
1072
+ try {
1073
+ if (sub.kind === "chain") {
1074
+ return await replayChainWebhook(db, sub, input);
1075
+ }
1076
+ const subgraphName = sub.subgraph_name;
1077
+ const tableName = sub.table_name;
1078
+ if (sub.kind !== "subgraph" || !subgraphName || !tableName) {
1079
+ throw new Error("replay is only supported for subgraph or chain webhooks");
1080
+ }
1081
+ const schema = await resolveSchemaName(db, subgraphName);
1082
+ const replayId = deterministicReplayId(sub.id, input.fromBlock, input.toBlock, input.replayIdSuffix);
1083
+ let scanned = 0;
1084
+ let enqueued = 0;
1085
+ let lastId = 0n;
1086
+ while (true) {
1087
+ const { rows } = await sql`SELECT * FROM ${sql.raw(`"${schema}"."${tableName}"`)}
1088
+ WHERE _block_height >= ${sql.lit(input.fromBlock)}
1089
+ AND _block_height <= ${sql.lit(input.toBlock)}
1090
+ AND _id > ${sql.lit(lastId)}
1091
+ ORDER BY _id ASC
1092
+ LIMIT ${sql.lit(BATCH_SIZE)}`.execute(db);
1093
+ if (rows.length === 0)
1094
+ break;
1095
+ scanned += rows.length;
1096
+ const inserts = rows.map((row) => ({
1097
+ webhook_id: sub.id,
1098
+ subgraph_name: subgraphName,
1099
+ table_name: tableName,
1100
+ block_height: Number(row._block_height),
1101
+ tx_id: row._tx_id ?? null,
1102
+ row_pk: {
1103
+ blockHeight: Number(row._block_height),
1104
+ txId: row._tx_id ?? "",
1105
+ replayId
1106
+ },
1107
+ event_type: `${subgraphName}.${tableName}.replay`,
1108
+ payload: row,
1109
+ dedup_key: replayDedupKey(subgraphName, tableName, row, replayId),
1110
+ is_replay: true
1111
+ }));
1112
+ const result = await db.insertInto("webhook_outbox").values(inserts).onConflict((oc) => oc.columns(["webhook_id", "dedup_key"]).doNothing()).executeTakeFirst();
1113
+ enqueued += Number(result.numInsertedOrUpdatedRows ?? 0);
1114
+ lastId = BigInt(String(rows[rows.length - 1]?._id));
1115
+ if (rows.length < BATCH_SIZE)
1116
+ break;
1117
+ }
1118
+ logger2.info("Replay enqueued", {
1119
+ webhook: sub.name,
1120
+ replayId,
1121
+ scanned,
1122
+ enqueued,
1123
+ fromBlock: input.fromBlock,
1124
+ toBlock: input.toBlock
1125
+ });
1126
+ return { replayId, enqueuedCount: enqueued, scannedCount: scanned };
1127
+ } finally {
1128
+ inFlightReplays.delete(sub.id);
1086
1129
  }
1087
- logger2.info("Replay enqueued", {
1088
- webhook: sub.name,
1089
- replayId,
1090
- scanned,
1091
- enqueued,
1092
- fromBlock: input.fromBlock,
1093
- toBlock: input.toBlock
1094
- });
1095
- return { replayId, enqueuedCount: enqueued, scannedCount: scanned };
1096
1130
  }
1097
1131
  var CHAIN_REPLAY_BATCH = 200;
1098
1132
  async function replayChainWebhook(db, sub, input, opts) {
@@ -1132,9 +1166,11 @@ async function replayChainWebhook(db, sub, input, opts) {
1132
1166
  return { replayId, enqueuedCount: enqueued, scannedCount: scanned };
1133
1167
  }
1134
1168
  export {
1169
+ ReplayInProgressError,
1170
+ __setReplayInFlightForTest,
1135
1171
  replayChainWebhook,
1136
1172
  replayWebhook
1137
1173
  };
1138
1174
 
1139
- //# debugId=12B00680B3E69AE464756E2164756E21
1175
+ //# debugId=8038149B4D7A86CB64756E2164756E21
1140
1176
  //# sourceMappingURL=replay.js.map
@@ -2,7 +2,7 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/runtime/replay.ts", "../src/schema/utils.ts", "../src/runtime/block-source.ts", "../src/runtime/batch-loader.ts", "../src/runtime/observer-http-source.ts", "../src/runtime/reconstruct.ts", "../src/runtime/trigger-evaluator.ts", "../src/runtime/decoder-bound.ts", "../src/runtime/source-matcher.ts"],
4
4
  "sourcesContent": [
5
- "import { createHash } from \"node:crypto\";\nimport { type Database, getTargetDb } from \"@secondlayer/shared/db\";\nimport type { Webhook } from \"@secondlayer/shared/db\";\nimport { getWebhook } from \"@secondlayer/shared/db/queries/webhooks\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport { type Kysely, sql } from \"kysely\";\nimport { pgSchemaName as defaultSchemaName } from \"../schema/utils.ts\";\nimport {\n\ttype BlockSource,\n\tPublicApiBlockSource,\n\tbuildHttpClient,\n} from \"./block-source.ts\";\nimport {\n\tbuildSourcesMap,\n\tbuildTraitContracts,\n\temitChainOutbox,\n\temitSbtcOutbox,\n\tevaluateBlock,\n\treferencedEventTypes,\n} from \"./trigger-evaluator.ts\";\n\n/**\n * Replay historical subgraph rows as new outbox entries for a single\n * webhook. Rows are marked `is_replay=TRUE` so the emitter can\n * prioritize live deliveries (90/10 split) and the delivery log can\n * tag replays distinctly.\n *\n * Idempotency: `replayId` is deterministic over `(webhook_id,\n * fromBlock, toBlock)`, so re-running the same replay range is a no-op\n * thanks to the unique `(webhook_id, dedup_key)` constraint. A\n * user who actually wants to re-deliver the same range passes a\n * distinct `replayIdSuffix` (e.g. a timestamp) to get a fresh key.\n */\n\nconst BATCH_SIZE = 500;\n\nfunction replayDedupKey(\n\tsubgraphName: string,\n\ttableName: string,\n\trow: Record<string, unknown>,\n\treplayId: string,\n): string {\n\tconst canonical = `replay:${replayId}:${subgraphName}:${tableName}:${stableStringify(row)}`;\n\treturn createHash(\"sha256\").update(canonical).digest(\"hex\").slice(0, 32);\n}\n\nfunction stableStringify(obj: Record<string, unknown>): string {\n\tconst keys = Object.keys(obj).sort();\n\treturn JSON.stringify(\n\t\tkeys.reduce<Record<string, unknown>>((acc, k) => {\n\t\t\tacc[k] = obj[k];\n\t\t\treturn acc;\n\t\t}, {}),\n\t);\n}\n\nexport interface ReplayInput {\n\taccountId: string;\n\twebhookId: string;\n\tfromBlock: number;\n\ttoBlock: number;\n\t/** Force re-delivery by appending a unique suffix to the replay id. */\n\treplayIdSuffix?: string;\n}\n\nfunction deterministicReplayId(\n\twebhookId: string,\n\tfromBlock: number,\n\ttoBlock: number,\n\tsuffix?: string,\n): string {\n\tconst canonical = `${webhookId}:${fromBlock}:${toBlock}${suffix ? `:${suffix}` : \"\"}`;\n\treturn createHash(\"sha256\").update(canonical).digest(\"hex\").slice(0, 16);\n}\n\nexport interface ReplayResult {\n\treplayId: string;\n\tenqueuedCount: number;\n\tscannedCount: number;\n}\n\nasync function resolveSchemaName(\n\tdb: Kysely<Database>,\n\tsubgraphName: string,\n): Promise<string> {\n\tconst row = await db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.select(\"schema_name\")\n\t\t.where(\"name\", \"=\", subgraphName)\n\t\t.executeTakeFirst();\n\tif (!row) {\n\t\tthrow new Error(\n\t\t\t`Subgraph \"${subgraphName}\" not registered — cannot replay its rows. Deploy the subgraph first.`,\n\t\t);\n\t}\n\treturn row.schema_name ?? defaultSchemaName(subgraphName);\n}\n\nexport async function replayWebhook(input: ReplayInput): Promise<ReplayResult> {\n\tif (input.fromBlock > input.toBlock) {\n\t\tthrow new Error(\"fromBlock must be <= toBlock\");\n\t}\n\tif (input.toBlock - input.fromBlock > 100_000) {\n\t\tthrow new Error(\"replay range exceeds 100k blocks\");\n\t}\n\n\tconst db = getTargetDb();\n\tconst sub = await getWebhook(db, input.accountId, input.webhookId);\n\tif (!sub) throw new Error(\"Webhook not found\");\n\n\t// Chain subs have no processed table — they react to raw chain events. Replay\n\t// re-runs the pure matcher over the canonical block range instead of scanning\n\t// rows.\n\tif (sub.kind === \"chain\") {\n\t\treturn replayChainWebhook(db, sub, input);\n\t}\n\n\tconst subgraphName = sub.subgraph_name;\n\tconst tableName = sub.table_name;\n\tif (sub.kind !== \"subgraph\" || !subgraphName || !tableName) {\n\t\tthrow new Error(\"replay is only supported for subgraph or chain webhooks\");\n\t}\n\n\tconst schema = await resolveSchemaName(db, subgraphName);\n\tconst replayId = deterministicReplayId(\n\t\tsub.id,\n\t\tinput.fromBlock,\n\t\tinput.toBlock,\n\t\tinput.replayIdSuffix,\n\t);\n\n\tlet scanned = 0;\n\tlet enqueued = 0;\n\t// Keyset pagination, not a positional skip-count: `_created_at` is written\n\t// as the literal NOW() (one value per transaction, so identical for every\n\t// row in a block), which makes (_block_height, _created_at) non-unique.\n\t// Paging by skip-count over a non-unique sort lets tied rows reorder\n\t// between pages and drop rows silently. `_id` is BIGSERIAL and total.\n\tlet lastId = 0n;\n\n\twhile (true) {\n\t\tconst { rows } = await sql<\n\t\t\tRecord<string, unknown>\n\t\t>`SELECT * FROM ${sql.raw(`\"${schema}\".\"${tableName}\"`)}\n\t\t\tWHERE _block_height >= ${sql.lit(input.fromBlock)}\n\t\t\t\tAND _block_height <= ${sql.lit(input.toBlock)}\n\t\t\t\tAND _id > ${sql.lit(lastId)}\n\t\t\tORDER BY _id ASC\n\t\t\tLIMIT ${sql.lit(BATCH_SIZE)}`.execute(db);\n\n\t\tif (rows.length === 0) break;\n\t\tscanned += rows.length;\n\n\t\tconst inserts = rows.map((row) => ({\n\t\t\twebhook_id: sub.id,\n\t\t\tsubgraph_name: subgraphName,\n\t\t\ttable_name: tableName,\n\t\t\tblock_height: Number(row._block_height),\n\t\t\ttx_id: (row._tx_id as string | undefined) ?? null,\n\t\t\trow_pk: {\n\t\t\t\tblockHeight: Number(row._block_height),\n\t\t\t\ttxId: row._tx_id ?? \"\",\n\t\t\t\treplayId,\n\t\t\t},\n\t\t\tevent_type: `${subgraphName}.${tableName}.replay`,\n\t\t\tpayload: row,\n\t\t\tdedup_key: replayDedupKey(subgraphName, tableName, row, replayId),\n\t\t\tis_replay: true,\n\t\t}));\n\n\t\tconst result = await db\n\t\t\t.insertInto(\"webhook_outbox\")\n\t\t\t.values(inserts)\n\t\t\t.onConflict((oc) => oc.columns([\"webhook_id\", \"dedup_key\"]).doNothing())\n\t\t\t.executeTakeFirst();\n\t\tenqueued += Number(result.numInsertedOrUpdatedRows ?? 0);\n\n\t\tlastId = BigInt(String(rows[rows.length - 1]?._id));\n\t\tif (rows.length < BATCH_SIZE) break;\n\t}\n\n\tlogger.info(\"Replay enqueued\", {\n\t\twebhook: sub.name,\n\t\treplayId,\n\t\tscanned,\n\t\tenqueued,\n\t\tfromBlock: input.fromBlock,\n\t\ttoBlock: input.toBlock,\n\t});\n\n\treturn { replayId, enqueuedCount: enqueued, scannedCount: scanned };\n}\n\nconst CHAIN_REPLAY_BATCH = 200;\n\n/**\n * Replay a chain webhook by re-running the pure matcher over a historical\n * canonical block range and emitting fresh apply rows. Unlike subgraph replay\n * there is no processed table to scan — the matcher is range-driven, so we\n * reload canonical blocks off the public Index/Streams clock and re-match.\n *\n * Rows are emitted with `is_replay=TRUE` and replay-namespaced dedup keys, and —\n * critically — this never advances `trigger_evaluator_state`: replay is\n * historical and must not move the live forward cursor.\n */\nexport async function replayChainWebhook(\n\tdb: Kysely<Database>,\n\tsub: Webhook,\n\tinput: ReplayInput,\n\topts?: { source?: BlockSource },\n): Promise<ReplayResult> {\n\tconst replayId = deterministicReplayId(\n\t\tsub.id,\n\t\tinput.fromBlock,\n\t\tinput.toBlock,\n\t\tinput.replayIdSuffix,\n\t);\n\n\tconst { sources, keyMeta } = buildSourcesMap([sub]);\n\tconst source =\n\t\topts?.source ??\n\t\tnew PublicApiBlockSource(buildHttpClient(), referencedEventTypes([sub]));\n\n\tlet scanned = 0;\n\tlet enqueued = 0;\n\tfor (\n\t\tlet from = input.fromBlock;\n\t\tfrom <= input.toBlock;\n\t\tfrom += CHAIN_REPLAY_BATCH\n\t) {\n\t\tconst to = Math.min(from + CHAIN_REPLAY_BATCH - 1, input.toBlock);\n\t\tconst blocks = await source.loadBlockRange(from, to);\n\t\t// Trait membership only grows; resolve once per batch as of its top height.\n\t\tconst traitContracts = await buildTraitContracts([sub], to);\n\t\tfor (let h = from; h <= to; h++) {\n\t\t\tconst bd = blocks.get(h);\n\t\t\tif (!bd) continue;\n\t\t\tscanned++;\n\t\t\tconst matches = evaluateBlock(bd, sources, traitContracts);\n\t\t\tif (matches.length > 0) {\n\t\t\t\tenqueued += await emitChainOutbox(\n\t\t\t\t\tdb,\n\t\t\t\t\tmatches,\n\t\t\t\t\tkeyMeta,\n\t\t\t\t\th,\n\t\t\t\t\tbd.block.hash,\n\t\t\t\t\t{\n\t\t\t\t\t\treplayId,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t\t// sBTC lifecycle triggers (deposit/withdrawal-create/accept/reject) match\n\t\t\t// against `sbtc_events`, not decoded_events — mirror the live loop so a\n\t\t\t// replay over a historical range backfills sBTC webhooks too. (Settlement\n\t\t\t// `swept_confirmed` is cursor/confirmed_at driven, not block-keyed, so it\n\t\t\t// emits nothing here — documented forward-only.)\n\t\t\tenqueued += await emitSbtcOutbox(db, [sub], h, bd.block.hash, {\n\t\t\t\treplayId,\n\t\t\t});\n\t\t}\n\t}\n\n\tlogger.info(\"Chain replay enqueued\", {\n\t\twebhook: sub.name,\n\t\treplayId,\n\t\tscanned,\n\t\tenqueued,\n\t\tfromBlock: input.fromBlock,\n\t\ttoBlock: input.toBlock,\n\t});\n\n\treturn { replayId, enqueuedCount: enqueued, scannedCount: scanned };\n}\n",
5
+ "import { createHash } from \"node:crypto\";\nimport { type Database, getTargetDb } from \"@secondlayer/shared/db\";\nimport type { Webhook } from \"@secondlayer/shared/db\";\nimport { getWebhook } from \"@secondlayer/shared/db/queries/webhooks\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport { type Kysely, sql } from \"kysely\";\nimport { pgSchemaName as defaultSchemaName } from \"../schema/utils.ts\";\nimport {\n\ttype BlockSource,\n\tPublicApiBlockSource,\n\tbuildHttpClient,\n} from \"./block-source.ts\";\nimport {\n\tbuildSourcesMap,\n\tbuildTraitContracts,\n\temitChainOutbox,\n\temitSbtcOutbox,\n\tevaluateBlock,\n\treferencedEventTypes,\n} from \"./trigger-evaluator.ts\";\n\n/**\n * Replay historical subgraph rows as new outbox entries for a single\n * webhook. Rows are marked `is_replay=TRUE` so the emitter can\n * prioritize live deliveries (90/10 split) and the delivery log can\n * tag replays distinctly.\n *\n * Idempotency: `replayId` is deterministic over `(webhook_id,\n * fromBlock, toBlock)`, so re-running the same replay range is a no-op\n * thanks to the unique `(webhook_id, dedup_key)` constraint. A\n * user who actually wants to re-deliver the same range passes a\n * distinct `replayIdSuffix` (e.g. a timestamp) to get a fresh key.\n */\n\nconst BATCH_SIZE = 500;\n\n/** Default cap on blocks per replay call — overridable via\n * `WEBHOOK_REPLAY_MAX_BLOCKS` for an operator who wants a tighter (or, for a\n * trusted self-host, looser) limit. Read live, not baked in at import. */\nconst WEBHOOK_REPLAY_MAX_BLOCKS_DEFAULT = 100_000;\n\nfunction webhookReplayMaxBlocks(): number {\n\tconst raw = process.env.WEBHOOK_REPLAY_MAX_BLOCKS;\n\tif (raw === undefined) return WEBHOOK_REPLAY_MAX_BLOCKS_DEFAULT;\n\tconst parsed = Number.parseInt(raw, 10);\n\treturn Number.isFinite(parsed) && parsed > 0\n\t\t? parsed\n\t\t: WEBHOOK_REPLAY_MAX_BLOCKS_DEFAULT;\n}\n\n/** Renders a block count the way the original hardcoded message did\n * (\"100k blocks\") for round thousands, falling back to the raw number for a\n * ceiling that isn't a clean multiple of 1000. */\nfunction formatBlockCount(n: number): string {\n\treturn n % 1000 === 0 ? `${n / 1000}k` : `${n}`;\n}\n\n/**\n * One in-flight replay per webhook at a time. Replay is a synchronous scan\n * (the route awaits it fully before responding), so two concurrent requests\n * for the same webhook would otherwise interleave their scans against the\n * same dedup keyspace. In-memory per-process — replay already isn't\n * horizontally coordinated (see `BATCH_SIZE` keyset pagination above), so\n * this matches its existing single-process assumption.\n */\nconst inFlightReplays = new Set<string>();\n\n/** Thrown by {@link replayWebhook} when a replay is already running for the\n * webhook. The route maps this to 409; `force` does not bypass it — a forced\n * re-delivery still has to wait for the previous replay to finish. */\nexport class ReplayInProgressError extends Error {\n\tconstructor() {\n\t\tsuper(\"replay already in progress for this webhook\");\n\t\tthis.name = \"ReplayInProgressError\";\n\t}\n}\n\n/**\n * Test-only seam: directly mark (or clear) a webhook as having an in-flight\n * replay. Two real concurrent `replayWebhook` calls race the same DB fetch,\n * so which one wins the guard isn't deterministic in a test; this lets a test\n * exercise the guard (and the route's 409 mapping) without that race.\n * Production code never calls this.\n */\nexport function __setReplayInFlightForTest(\n\twebhookId: string,\n\tinFlight: boolean,\n): void {\n\tif (inFlight) inFlightReplays.add(webhookId);\n\telse inFlightReplays.delete(webhookId);\n}\n\nfunction replayDedupKey(\n\tsubgraphName: string,\n\ttableName: string,\n\trow: Record<string, unknown>,\n\treplayId: string,\n): string {\n\tconst canonical = `replay:${replayId}:${subgraphName}:${tableName}:${stableStringify(row)}`;\n\treturn createHash(\"sha256\").update(canonical).digest(\"hex\").slice(0, 32);\n}\n\nfunction stableStringify(obj: Record<string, unknown>): string {\n\tconst keys = Object.keys(obj).sort();\n\treturn JSON.stringify(\n\t\tkeys.reduce<Record<string, unknown>>((acc, k) => {\n\t\t\tacc[k] = obj[k];\n\t\t\treturn acc;\n\t\t}, {}),\n\t);\n}\n\nexport interface ReplayInput {\n\taccountId: string;\n\twebhookId: string;\n\tfromBlock: number;\n\ttoBlock: number;\n\t/** Force re-delivery by appending a unique suffix to the replay id. */\n\treplayIdSuffix?: string;\n}\n\nfunction deterministicReplayId(\n\twebhookId: string,\n\tfromBlock: number,\n\ttoBlock: number,\n\tsuffix?: string,\n): string {\n\tconst canonical = `${webhookId}:${fromBlock}:${toBlock}${suffix ? `:${suffix}` : \"\"}`;\n\treturn createHash(\"sha256\").update(canonical).digest(\"hex\").slice(0, 16);\n}\n\nexport interface ReplayResult {\n\treplayId: string;\n\tenqueuedCount: number;\n\tscannedCount: number;\n}\n\nasync function resolveSchemaName(\n\tdb: Kysely<Database>,\n\tsubgraphName: string,\n): Promise<string> {\n\tconst row = await db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.select(\"schema_name\")\n\t\t.where(\"name\", \"=\", subgraphName)\n\t\t.executeTakeFirst();\n\tif (!row) {\n\t\tthrow new Error(\n\t\t\t`Subgraph \"${subgraphName}\" not registered — cannot replay its rows. Deploy the subgraph first.`,\n\t\t);\n\t}\n\treturn row.schema_name ?? defaultSchemaName(subgraphName);\n}\n\nexport async function replayWebhook(input: ReplayInput): Promise<ReplayResult> {\n\tif (input.fromBlock > input.toBlock) {\n\t\tthrow new Error(\"fromBlock must be <= toBlock\");\n\t}\n\tconst maxBlocks = webhookReplayMaxBlocks();\n\tif (input.toBlock - input.fromBlock > maxBlocks) {\n\t\tthrow new Error(\n\t\t\t`replay range exceeds ${formatBlockCount(maxBlocks)} blocks`,\n\t\t);\n\t}\n\n\tconst db = getTargetDb();\n\tconst sub = await getWebhook(db, input.accountId, input.webhookId);\n\tif (!sub) throw new Error(\"Webhook not found\");\n\n\tif (inFlightReplays.has(sub.id)) {\n\t\tthrow new ReplayInProgressError();\n\t}\n\tinFlightReplays.add(sub.id);\n\ttry {\n\t\t// Chain subs have no processed table — they react to raw chain events.\n\t\t// Replay re-runs the pure matcher over the canonical block range instead\n\t\t// of scanning rows.\n\t\tif (sub.kind === \"chain\") {\n\t\t\treturn await replayChainWebhook(db, sub, input);\n\t\t}\n\n\t\tconst subgraphName = sub.subgraph_name;\n\t\tconst tableName = sub.table_name;\n\t\tif (sub.kind !== \"subgraph\" || !subgraphName || !tableName) {\n\t\t\tthrow new Error(\n\t\t\t\t\"replay is only supported for subgraph or chain webhooks\",\n\t\t\t);\n\t\t}\n\n\t\tconst schema = await resolveSchemaName(db, subgraphName);\n\t\tconst replayId = deterministicReplayId(\n\t\t\tsub.id,\n\t\t\tinput.fromBlock,\n\t\t\tinput.toBlock,\n\t\t\tinput.replayIdSuffix,\n\t\t);\n\n\t\tlet scanned = 0;\n\t\tlet enqueued = 0;\n\t\t// Keyset pagination, not a positional skip-count: `_created_at` is written\n\t\t// as the literal NOW() (one value per transaction, so identical for every\n\t\t// row in a block), which makes (_block_height, _created_at) non-unique.\n\t\t// Paging by skip-count over a non-unique sort lets tied rows reorder\n\t\t// between pages and drop rows silently. `_id` is BIGSERIAL and total.\n\t\tlet lastId = 0n;\n\n\t\twhile (true) {\n\t\t\tconst { rows } = await sql<\n\t\t\t\tRecord<string, unknown>\n\t\t\t>`SELECT * FROM ${sql.raw(`\"${schema}\".\"${tableName}\"`)}\n\t\t\t\tWHERE _block_height >= ${sql.lit(input.fromBlock)}\n\t\t\t\t\tAND _block_height <= ${sql.lit(input.toBlock)}\n\t\t\t\t\tAND _id > ${sql.lit(lastId)}\n\t\t\t\tORDER BY _id ASC\n\t\t\t\tLIMIT ${sql.lit(BATCH_SIZE)}`.execute(db);\n\n\t\t\tif (rows.length === 0) break;\n\t\t\tscanned += rows.length;\n\n\t\t\tconst inserts = rows.map((row) => ({\n\t\t\t\twebhook_id: sub.id,\n\t\t\t\tsubgraph_name: subgraphName,\n\t\t\t\ttable_name: tableName,\n\t\t\t\tblock_height: Number(row._block_height),\n\t\t\t\ttx_id: (row._tx_id as string | undefined) ?? null,\n\t\t\t\trow_pk: {\n\t\t\t\t\tblockHeight: Number(row._block_height),\n\t\t\t\t\ttxId: row._tx_id ?? \"\",\n\t\t\t\t\treplayId,\n\t\t\t\t},\n\t\t\t\tevent_type: `${subgraphName}.${tableName}.replay`,\n\t\t\t\tpayload: row,\n\t\t\t\tdedup_key: replayDedupKey(subgraphName, tableName, row, replayId),\n\t\t\t\tis_replay: true,\n\t\t\t}));\n\n\t\t\tconst result = await db\n\t\t\t\t.insertInto(\"webhook_outbox\")\n\t\t\t\t.values(inserts)\n\t\t\t\t.onConflict((oc) => oc.columns([\"webhook_id\", \"dedup_key\"]).doNothing())\n\t\t\t\t.executeTakeFirst();\n\t\t\tenqueued += Number(result.numInsertedOrUpdatedRows ?? 0);\n\n\t\t\tlastId = BigInt(String(rows[rows.length - 1]?._id));\n\t\t\tif (rows.length < BATCH_SIZE) break;\n\t\t}\n\n\t\tlogger.info(\"Replay enqueued\", {\n\t\t\twebhook: sub.name,\n\t\t\treplayId,\n\t\t\tscanned,\n\t\t\tenqueued,\n\t\t\tfromBlock: input.fromBlock,\n\t\t\ttoBlock: input.toBlock,\n\t\t});\n\n\t\treturn { replayId, enqueuedCount: enqueued, scannedCount: scanned };\n\t} finally {\n\t\tinFlightReplays.delete(sub.id);\n\t}\n}\n\nconst CHAIN_REPLAY_BATCH = 200;\n\n/**\n * Replay a chain webhook by re-running the pure matcher over a historical\n * canonical block range and emitting fresh apply rows. Unlike subgraph replay\n * there is no processed table to scan — the matcher is range-driven, so we\n * reload canonical blocks off the public Index/Streams clock and re-match.\n *\n * Rows are emitted with `is_replay=TRUE` and replay-namespaced dedup keys, and —\n * critically — this never advances `trigger_evaluator_state`: replay is\n * historical and must not move the live forward cursor.\n */\nexport async function replayChainWebhook(\n\tdb: Kysely<Database>,\n\tsub: Webhook,\n\tinput: ReplayInput,\n\topts?: { source?: BlockSource },\n): Promise<ReplayResult> {\n\tconst replayId = deterministicReplayId(\n\t\tsub.id,\n\t\tinput.fromBlock,\n\t\tinput.toBlock,\n\t\tinput.replayIdSuffix,\n\t);\n\n\tconst { sources, keyMeta } = buildSourcesMap([sub]);\n\tconst source =\n\t\topts?.source ??\n\t\tnew PublicApiBlockSource(buildHttpClient(), referencedEventTypes([sub]));\n\n\tlet scanned = 0;\n\tlet enqueued = 0;\n\tfor (\n\t\tlet from = input.fromBlock;\n\t\tfrom <= input.toBlock;\n\t\tfrom += CHAIN_REPLAY_BATCH\n\t) {\n\t\tconst to = Math.min(from + CHAIN_REPLAY_BATCH - 1, input.toBlock);\n\t\tconst blocks = await source.loadBlockRange(from, to);\n\t\t// Trait membership only grows; resolve once per batch as of its top height.\n\t\tconst traitContracts = await buildTraitContracts([sub], to);\n\t\tfor (let h = from; h <= to; h++) {\n\t\t\tconst bd = blocks.get(h);\n\t\t\tif (!bd) continue;\n\t\t\tscanned++;\n\t\t\tconst matches = evaluateBlock(bd, sources, traitContracts);\n\t\t\tif (matches.length > 0) {\n\t\t\t\tenqueued += await emitChainOutbox(\n\t\t\t\t\tdb,\n\t\t\t\t\tmatches,\n\t\t\t\t\tkeyMeta,\n\t\t\t\t\th,\n\t\t\t\t\tbd.block.hash,\n\t\t\t\t\t{\n\t\t\t\t\t\treplayId,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t\t// sBTC lifecycle triggers (deposit/withdrawal-create/accept/reject) match\n\t\t\t// against `sbtc_events`, not decoded_events — mirror the live loop so a\n\t\t\t// replay over a historical range backfills sBTC webhooks too. (Settlement\n\t\t\t// `swept_confirmed` is cursor/confirmed_at driven, not block-keyed, so it\n\t\t\t// emits nothing here — documented forward-only.)\n\t\t\tenqueued += await emitSbtcOutbox(db, [sub], h, bd.block.hash, {\n\t\t\t\treplayId,\n\t\t\t});\n\t\t}\n\t}\n\n\tlogger.info(\"Chain replay enqueued\", {\n\t\twebhook: sub.name,\n\t\treplayId,\n\t\tscanned,\n\t\tenqueued,\n\t\tfromBlock: input.fromBlock,\n\t\ttoBlock: input.toBlock,\n\t});\n\n\treturn { replayId, enqueuedCount: enqueued, scannedCount: scanned };\n}\n",
6
6
  "// Re-export canonical pgSchemaName from shared\nexport { pgSchemaName } from \"@secondlayer/shared/db/queries/subgraphs\";\n\n/**\n * Double-quotes a Postgres identifier unless it's already a safe bare\n * identifier, escaping any embedded double quotes. Defense-in-depth for the\n * DDL emitters: every name reaching them (schema/table/column names, and the\n * composite names generator.ts builds from them) is validated upstream\n * (`SqlIdentifierSchema` / `SubgraphNameSchema`), so this is a no-op for every\n * currently-valid name — output stays byte-identical. It only changes\n * anything if a hostile name (embedded quote, semicolon, whitespace, ...)\n * somehow reached this far, turning it into an inert quoted identifier\n * instead of raw SQL.\n */\nexport function quotePgIdent(name: string): string {\n\tif (/^[a-z_][a-z0-9_]*$/i.test(name)) return name;\n\treturn `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\n/** `user_account` → `userAccount`. Column and variable names in every emitted\n * ORM surface go through this. */\nexport function snakeToCamel(name: string): string {\n\treturn name.replace(/_([a-z0-9])/g, (_, c: string) => c.toUpperCase());\n}\n\n/** `user_account` → `UserAccount`. Type/model names for one table must agree\n * across the Prisma, Drizzle, Kysely, and index-codegen emitters — a user can\n * import from more than one, so this lives here rather than per-generator. */\nexport function pascalCase(name: string): string {\n\tconst camel = snakeToCamel(name);\n\treturn camel.charAt(0).toUpperCase() + camel.slice(1);\n}\n",
7
7
  "import { getSourceDb } from \"@secondlayer/shared/db\";\nimport type { Transaction } from \"@secondlayer/shared/db\";\nimport {\n\ttype IndexEventRow,\n\ttype IndexHttpClient,\n\ttype IndexTransactionRow,\n\tcreateInternalIndexHttpClient,\n} from \"@secondlayer/shared/index-http\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport type { SubgraphDefinition, SubgraphFilter } from \"../types.ts\";\nimport { type BlockData, loadBlockRange } from \"./batch-loader.ts\";\nimport { ObserverHttpBlockSource } from \"./observer-http-source.ts\";\nimport {\n\treconstructBlock,\n\treconstructEvent,\n\treconstructTransaction,\n\treconstructTxFromEventRow,\n} from \"./reconstruct.ts\";\n\n/**\n * Where the subgraph runtime reads canonical chain data. Today it taps the\n * indexer Postgres directly (`PostgresBlockSource`); the re-point adds a\n * `PublicApiBlockSource` that consumes the Streams clock + Index data over\n * HTTP. `matchSources` / handlers / flush / outbox are unchanged — only the\n * loader + tip swap behind this seam.\n */\nexport interface BlockSource {\n\t/** Highest canonical block height available to process. */\n\tgetTip(): Promise<number>;\n\t/** Canonical block data for [fromHeight, toHeight], keyed by height. */\n\tloadBlockRange(\n\t\tfromHeight: number,\n\t\ttoHeight: number,\n\t): Promise<Map<number, BlockData>>;\n\t/** Sparse-scan probe: lowest height in (afterHeight, untilHeight] holding\n\t * an event this source's subgraph could match, or null when the rest of\n\t * the range is empty. Optional — only event-scoped sources support it. */\n\tnextDataHeight?(\n\t\tafterHeight: number,\n\t\tuntilHeight: number,\n\t): Promise<number | null>;\n}\n\n/** A (decoded event type, optional contract scope) pair the sparse probe\n * checks. Contract scoping is what makes token-subgraph reindexes leap over\n * everything that isn't their token. */\nexport type SparseProbeTarget = { eventType: string; contractId?: string };\n\n/** Sparse scanning is sound only when EVERY source is an event-type filter —\n * a contract_call/contract_deploy source matches transactions, which the\n * event probe can't see. */\nexport function canSparseScan(subgraph: SubgraphDefinition): boolean {\n\tif (Array.isArray(subgraph.sources)) return false;\n\tconst filters = sourceFilters(subgraph);\n\tif (filters.length === 0) return false;\n\treturn filters.every((f) => Boolean(EVENT_FILTER_TO_INDEX_TYPE[f.type]));\n}\n\n/** Probe targets for a subgraph's filters: decoded type + contract scope when\n * the filter pins one (assetIdentifier \"SP….contract::asset\" or contractId). */\nexport function sparseProbeTargets(\n\tsubgraph: SubgraphDefinition,\n): SparseProbeTarget[] {\n\tconst targets = new Map<string, SparseProbeTarget>();\n\tfor (const f of sourceFilters(subgraph)) {\n\t\tconst eventType = EVENT_FILTER_TO_INDEX_TYPE[f.type];\n\t\tif (!eventType) continue;\n\t\tconst scoped = f as { assetIdentifier?: string; contractId?: string };\n\t\tconst contractId =\n\t\t\tscoped.contractId ?? scoped.assetIdentifier?.split(\"::\")[0];\n\t\tconst key = `${eventType}|${contractId ?? \"\"}`;\n\t\ttargets.set(key, { eventType, ...(contractId ? { contractId } : {}) });\n\t}\n\treturn [...targets.values()];\n}\n\n/** Reads directly from the shared indexer Postgres (the original behavior). */\nexport class PostgresBlockSource implements BlockSource {\n\tasync getTip(): Promise<number> {\n\t\tconst progress = await getSourceDb()\n\t\t\t.selectFrom(\"index_progress\")\n\t\t\t.selectAll()\n\t\t\t.where(\"network\", \"=\", process.env.NETWORK ?? \"mainnet\")\n\t\t\t.executeTakeFirst();\n\t\treturn progress ? Number(progress.highest_seen_block) : 0;\n\t}\n\n\tloadBlockRange(\n\t\tfromHeight: number,\n\t\ttoHeight: number,\n\t): Promise<Map<number, BlockData>> {\n\t\treturn loadBlockRange(getSourceDb(), fromHeight, toHeight);\n\t}\n}\n\n// Subgraph source filter types that map to a decoded Index event_type. The\n// `_event` suffix is the runtime's raw form; print is keyed `print_event`.\nconst EVENT_FILTER_TO_INDEX_TYPE: Record<string, string> = {\n\tstx_transfer: \"stx_transfer\",\n\tstx_mint: \"stx_mint\",\n\tstx_burn: \"stx_burn\",\n\tstx_lock: \"stx_lock\",\n\tft_transfer: \"ft_transfer\",\n\tft_mint: \"ft_mint\",\n\tft_burn: \"ft_burn\",\n\tnft_transfer: \"nft_transfer\",\n\tnft_mint: \"nft_mint\",\n\tnft_burn: \"nft_burn\",\n\tprint_event: \"print\",\n\tnested_contract_call: \"nested_contract_call\",\n\tvar_set: \"var_set\",\n\tmap_set: \"map_set\",\n\tmap_insert: \"map_insert\",\n\tmap_delete: \"map_delete\",\n};\n\n// Tx-level source types — matched against /v1/index/transactions, not events.\nconst TX_SOURCE_TYPES = new Set([\"contract_call\", \"contract_deploy\"]);\n// Second clock (ordinal). Never part of a tx's classic event set: a\n// contract_call/contract_deploy source fetches every CLASSIC type, and vm\n// types are fetched only when a vm source names them.\nexport const VM_INDEX_EVENT_TYPES: ReadonlySet<string> = new Set([\n\t\"nested_contract_call\",\n\t\"var_set\",\n\t\"map_set\",\n\t\"map_insert\",\n\t\"map_delete\",\n]);\nconst CLASSIC_INDEX_EVENT_TYPES = [\n\t...new Set(Object.values(EVENT_FILTER_TO_INDEX_TYPE)),\n].filter((t) => !VM_INDEX_EVENT_TYPES.has(t));\n\nfunction sourceFilters(subgraph: SubgraphDefinition): SubgraphFilter[] {\n\tconst sources = subgraph.sources;\n\treturn Array.isArray(sources)\n\t\t? (sources as SubgraphFilter[])\n\t\t: Object.values(sources as Record<string, SubgraphFilter>);\n}\n\n/**\n * True when any source matches transactions (contract_call / contract_deploy):\n * the handler receives the full tx, so the loader must fetch real transactions.\n * Event-only subgraphs skip walkTransactions and synthesize the tx from joined\n * event context instead (the ~37x reindex over-fetch; see indexing-speed plan).\n */\nexport function needsTransactionData(subgraph: SubgraphDefinition): boolean {\n\treturn sourceFilters(subgraph).some((f) => TX_SOURCE_TYPES.has(f.type));\n}\n\n/** Build the (few) event-bearing txs from joined event context, one per tx_id —\n * the event-only replacement for draining every transaction in the range. */\nfunction synthesizeTxsFromEvents(events: IndexEventRow[]): Transaction[] {\n\tconst byId = new Map<string, Transaction>();\n\tfor (const e of events) {\n\t\tif (!byId.has(e.tx_id)) byId.set(e.tx_id, reconstructTxFromEventRow(e));\n\t}\n\treturn [...byId.values()];\n}\n\n/**\n * The Index event_types the loader must fetch for a set of source filter types.\n * A contract_call/contract_deploy source matches a tx and hands its FULL event\n * set to the handler, so when one is present we fetch every classic event type\n * (the matched tx's events must be complete); otherwise just the referenced\n * types. VM types ride a second clock and are fetched only when referenced.\n * Shared by the subgraph loader and the chain-trigger evaluator.\n */\nexport function indexEventTypesForFilterTypes(filterTypes: string[]): string[] {\n\tconst types = new Set<string>();\n\tif (filterTypes.some((t) => TX_SOURCE_TYPES.has(t))) {\n\t\tfor (const t of CLASSIC_INDEX_EVENT_TYPES) types.add(t);\n\t}\n\tfor (const t of filterTypes) {\n\t\tconst indexType = EVENT_FILTER_TO_INDEX_TYPE[t];\n\t\tif (indexType) types.add(indexType);\n\t}\n\treturn [...types];\n}\n\n/** Index event_types a subgraph's sources require. Empty when sources are absent. */\nexport function referencedIndexEventTypes(\n\tsubgraph: SubgraphDefinition,\n): string[] {\n\tif (!subgraph.sources) return [];\n\treturn indexEventTypesForFilterTypes(\n\t\tsourceFilters(subgraph).map((f) => f.type),\n\t);\n}\n\n/**\n * streams-index eligibility: every source must be a known event-type or\n * contract_call/contract_deploy filter (no array-style sources, which leak the\n * unreconstructable `_eventId`). Trait scope IS allowed — trait resolution\n * reads the contract registry on the platform DB (`targetDb`), which the\n * processor always holds, so it's source-independent. Everything else stays on\n * the DB tap.\n */\nexport function isStreamsIndexEligible(subgraph: SubgraphDefinition): boolean {\n\tif (Array.isArray(subgraph.sources)) return false;\n\tconst filters = sourceFilters(subgraph);\n\tif (filters.length === 0) return false;\n\tfor (const f of filters) {\n\t\tconst known =\n\t\t\tEVENT_FILTER_TO_INDEX_TYPE[f.type] || TX_SOURCE_TYPES.has(f.type);\n\t\tif (!known) return false;\n\t}\n\treturn true;\n}\n\n/** Streams clock + Index data plane, reconstructed into raw BlockData rows. */\nexport class PublicApiBlockSource implements BlockSource {\n\tconstructor(\n\t\tprivate readonly http: IndexHttpClient,\n\t\tprivate readonly eventTypes: string[],\n\t\t/** When set, enables the sparse-scan probe (event-scoped subgraphs). */\n\t\tprivate readonly probeTargets?: SparseProbeTarget[],\n\t\t/** False for event-only subgraphs → skip walkTransactions, synthesize the\n\t\t * tx from joined event context. Defaults true (safe / unchanged). */\n\t\tprivate readonly needsTransactions = true,\n\t) {}\n\n\t/** Lowest height in (after, until] any probe target hits, or null. */\n\tasync nextDataHeight(\n\t\tafterHeight: number,\n\t\tuntilHeight: number,\n\t): Promise<number | null> {\n\t\tif (!this.probeTargets?.length) return afterHeight + 1;\n\t\tconst hits = await Promise.all(\n\t\t\tthis.probeTargets.map((t) =>\n\t\t\t\tthis.http.firstEventHeight(\n\t\t\t\t\tt.eventType,\n\t\t\t\t\tafterHeight + 1,\n\t\t\t\t\tuntilHeight,\n\t\t\t\t\tt.contractId,\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t\tconst found = hits.filter((h): h is number => h !== null);\n\t\treturn found.length ? Math.min(...found) : null;\n\t}\n\n\tgetTip(): Promise<number> {\n\t\t// VM rows land with ingest. Decoded Index tip can lag; use the source\n\t\t// field when this loader fetches any vm type.\n\t\tif (this.eventTypes.some((t) => VM_INDEX_EVENT_TYPES.has(t))) {\n\t\t\treturn this.http.getIndexSourceTip();\n\t\t}\n\t\treturn this.http.getIndexTip();\n\t}\n\n\tasync loadBlockRange(\n\t\tfromHeight: number,\n\t\ttoHeight: number,\n\t): Promise<Map<number, BlockData>> {\n\t\t// Event-only subgraphs join tx context onto events (withTx) and skip the\n\t\t// walkTransactions over-fetch entirely; tx-level sources fetch real txs.\n\t\tconst withTx = !this.needsTransactions;\n\t\tconst [blocks, txRows, eventLists] = await Promise.all([\n\t\t\tthis.http.walkBlocks(fromHeight, toHeight),\n\t\t\tthis.needsTransactions\n\t\t\t\t? this.http.walkTransactions(fromHeight, toHeight)\n\t\t\t\t: Promise.resolve<IndexTransactionRow[]>([]),\n\t\t\tPromise.all(\n\t\t\t\tthis.eventTypes.map((t) =>\n\t\t\t\t\tthis.http.walkEvents(t, fromHeight, toHeight, withTx),\n\t\t\t\t),\n\t\t\t),\n\t\t]);\n\n\t\tconst map = new Map<number, BlockData>();\n\t\t// Seed every canonical height (incl. empty blocks) so catch-up doesn't\n\t\t// file them as gaps.\n\t\tfor (const b of blocks) {\n\t\t\tmap.set(b.block_height, {\n\t\t\t\tblock: reconstructBlock(b),\n\t\t\t\ttxs: [],\n\t\t\t\tevents: [],\n\t\t\t});\n\t\t}\n\t\t// For event-only subgraphs, materialize only the event-bearing txs from\n\t\t// joined event context instead of every transaction in the range.\n\t\tconst txs = this.needsTransactions\n\t\t\t? txRows.map(reconstructTransaction)\n\t\t\t: synthesizeTxsFromEvents(eventLists.flat());\n\t\tfor (const t of txs) {\n\t\t\tmap.get(t.block_height)?.txs.push(t);\n\t\t}\n\t\tfor (const list of eventLists) {\n\t\t\tfor (const e of list) {\n\t\t\t\tconst bd = map.get(e.block_height);\n\t\t\t\tif (!bd) continue;\n\t\t\t\t// vm rows ride their own clock: never merged into `events`, whose\n\t\t\t\t// order is classic event_index.\n\t\t\t\tif (VM_INDEX_EVENT_TYPES.has(e.event_type)) {\n\t\t\t\t\tbd.vmEvents ??= [];\n\t\t\t\t\tbd.vmEvents.push(reconstructEvent(e));\n\t\t\t\t} else {\n\t\t\t\t\tbd.events.push(reconstructEvent(e));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Canonical ordering — multi-type event walks merge here, per clock.\n\t\tfor (const bd of map.values()) {\n\t\t\tbd.txs.sort((a, b) => a.tx_index - b.tx_index);\n\t\t\tbd.events.sort((a, b) => a.event_index - b.event_index);\n\t\t\tbd.vmEvents?.sort((a, b) => a.event_index - b.event_index);\n\t\t}\n\t\treturn map;\n\t}\n}\n\n/**\n * Wraps a primary source and falls back to a secondary, per call, when the\n * primary throws. Use it to make the HTTP (Streams+Index) plane a SOFT dependency:\n * if api is unavailable, the processor reads the Postgres tap and keeps advancing\n * instead of stalling. Safe to mix mid-stream — both taps read the same canonical\n * chain at the same heights and the cursor is forward-only. Stateless (no breaker)\n * so it's failover-safe across replicas; the primary is retried every call and\n * resumes transparently once healthy.\n */\nexport class FallbackBlockSource implements BlockSource {\n\tconstructor(\n\t\tprivate readonly primary: BlockSource,\n\t\tprivate readonly fallback: BlockSource,\n\t) {}\n\n\tasync getTip(): Promise<number> {\n\t\ttry {\n\t\t\treturn await this.primary.getTip();\n\t\t} catch (err) {\n\t\t\tlogger.warn(\"block source primary getTip failed — using DB tap\", {\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t});\n\t\t\treturn this.fallback.getTip();\n\t\t}\n\t}\n\n\tasync loadBlockRange(\n\t\tfromHeight: number,\n\t\ttoHeight: number,\n\t): Promise<Map<number, BlockData>> {\n\t\ttry {\n\t\t\treturn await this.primary.loadBlockRange(fromHeight, toHeight);\n\t\t} catch (err) {\n\t\t\tlogger.warn(\"block source primary loadBlockRange failed — using DB tap\", {\n\t\t\t\tfrom: fromHeight,\n\t\t\t\tto: toHeight,\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t});\n\t\t\treturn this.fallback.loadBlockRange(fromHeight, toHeight);\n\t\t}\n\t}\n\n\t/** Probe via the primary only; a probe failure just means \"no skip\" —\n\t * the caller falls back to plain batch advancement. */\n\tasync nextDataHeight(\n\t\tafterHeight: number,\n\t\tuntilHeight: number,\n\t): Promise<number | null> {\n\t\tif (!this.primary.nextDataHeight) return afterHeight + 1;\n\t\ttry {\n\t\t\treturn await this.primary.nextDataHeight(afterHeight, untilHeight);\n\t\t} catch {\n\t\t\treturn afterHeight + 1;\n\t\t}\n\t}\n}\n\nconst postgresBlockSource = new PostgresBlockSource();\n\n/**\n * HTTP (Streams+Index) chain source for a set of decoded event types, wrapped so\n * it falls back to the Postgres tap when api is down. Used by the chain-trigger\n * evaluator (which isn't subgraph-scoped, so it can't go through resolveBlockSource).\n */\nexport function buildChainBlockSource(eventTypes: string[]): BlockSource {\n\treturn new FallbackBlockSource(\n\t\tnew PublicApiBlockSource(buildHttpClient(), eventTypes),\n\t\tpostgresBlockSource,\n\t);\n}\n\nexport function buildHttpClient(): IndexHttpClient {\n\treturn createInternalIndexHttpClient();\n}\n\n/**\n * Resolve the block source for a subgraph. `SUBGRAPH_SOURCE=streams-index`\n * opts eligible subgraphs onto the public Streams clock + Index data;\n * `SUBGRAPH_SOURCE=observer-http` pages internal observer-events (experimental).\n * Default stays on the Postgres tap.\n */\nexport function resolveBlockSource(subgraph?: SubgraphDefinition): BlockSource {\n\tif (process.env.SUBGRAPH_SOURCE === \"observer-http\") {\n\t\tconst baseUrl = process.env.OBSERVER_HTTP_URL;\n\t\tif (!baseUrl) {\n\t\t\tthrow new Error(\n\t\t\t\t\"SUBGRAPH_SOURCE=observer-http requires OBSERVER_HTTP_URL\",\n\t\t\t);\n\t\t}\n\t\treturn new ObserverHttpBlockSource({\n\t\t\tbaseUrl,\n\t\t\ttoken: process.env.OBSERVER_HTTP_EXPORT_TOKEN || null,\n\t\t});\n\t}\n\tif (\n\t\tprocess.env.SUBGRAPH_SOURCE === \"streams-index\" &&\n\t\tsubgraph &&\n\t\tisStreamsIndexEligible(subgraph)\n\t) {\n\t\t// Soft-depend on api: fall back to the Postgres tap per-call if the HTTP\n\t\t// plane is down, so the processor keeps advancing instead of stalling.\n\t\treturn new FallbackBlockSource(\n\t\t\tnew PublicApiBlockSource(\n\t\t\t\tbuildHttpClient(),\n\t\t\t\treferencedIndexEventTypes(subgraph),\n\t\t\t\tcanSparseScan(subgraph) ? sparseProbeTargets(subgraph) : undefined,\n\t\t\t\tneedsTransactionData(subgraph),\n\t\t\t),\n\t\t\tpostgresBlockSource,\n\t\t);\n\t}\n\tif (process.env.SUBGRAPH_SOURCE === \"streams-index\" && subgraph) {\n\t\tlogger.debug(\"Subgraph not streams-index eligible, using DB tap\", {\n\t\t\tsubgraph: subgraph.name,\n\t\t});\n\t}\n\treturn postgresBlockSource;\n}\n",
8
8
  "import type {\n\tBlock,\n\tDatabase,\n\tEvent,\n\tTransaction,\n} from \"@secondlayer/shared/db\";\nimport type { Kysely } from \"kysely\";\n\n/** A runtime event row. `clock: \"vm\"` marks an opt-in `vm_events` row whose\n * `event_index` is `ordinal` — a second ordinal that never sorts or\n * dedupes against classic `events.event_index`. */\nexport type RuntimeEvent = Event & { clock?: \"vm\" };\n\nexport interface BlockData {\n\tblock: Block;\n\ttxs: Transaction[];\n\t/** Classic `events` rows (Streams 1.0 clock). */\n\tevents: Event[];\n\t/** Opt-in `vm_events` rows on their own clock. Absent/empty on `\"*\"`\n\t * nodes and on archives collected without `storage`/`contract_calls`. */\n\tvmEvents?: RuntimeEvent[];\n}\n\n/** Stable synthetic id for a vm row. Distinct from the classic `tx#index`\n * so a print at event_index N and a map_set at ordinal N never share\n * an identity. */\nexport function vmEventId(txId: string, vmEventIndex: number): string {\n\treturn `${txId}#vm:${vmEventIndex}`;\n}\n\n/**\n * Load a range of blocks with their transactions and events in 4 parallel queries.\n * Returns a Map keyed by block height. Non-canonical blocks are excluded.\n */\nexport async function loadBlockRange(\n\tdb: Kysely<Database>,\n\tfromHeight: number,\n\ttoHeight: number,\n): Promise<Map<number, BlockData>> {\n\tconst [blocks, txs, events, vmRows] = await Promise.all([\n\t\tdb\n\t\t\t.selectFrom(\"blocks\")\n\t\t\t.selectAll()\n\t\t\t.where(\"height\", \">=\", fromHeight)\n\t\t\t.where(\"height\", \"<=\", toHeight)\n\t\t\t.where(\"canonical\", \"=\", true)\n\t\t\t.execute(),\n\t\tdb\n\t\t\t.selectFrom(\"transactions\")\n\t\t\t.selectAll()\n\t\t\t.where(\"block_height\", \">=\", fromHeight)\n\t\t\t.where(\"block_height\", \"<=\", toHeight)\n\t\t\t.execute(),\n\t\tdb\n\t\t\t.selectFrom(\"events\")\n\t\t\t.selectAll()\n\t\t\t.where(\"block_height\", \">=\", fromHeight)\n\t\t\t.where(\"block_height\", \"<=\", toHeight)\n\t\t\t.execute(),\n\t\tdb\n\t\t\t.selectFrom(\"vm_events\")\n\t\t\t.selectAll()\n\t\t\t.where(\"block_height\", \">=\", fromHeight)\n\t\t\t.where(\"block_height\", \"<=\", toHeight)\n\t\t\t.orderBy(\"ordinal\", \"asc\")\n\t\t\t.execute(),\n\t]);\n\n\t// Index by block height (coerce to number — bigint columns may return as string or number)\n\tconst txsByHeight = new Map<number, Transaction[]>();\n\tfor (const tx of txs) {\n\t\tconst h = Number(tx.block_height);\n\t\tconst list = txsByHeight.get(h) ?? [];\n\t\tlist.push(tx);\n\t\ttxsByHeight.set(h, list);\n\t}\n\n\tconst eventsByHeight = new Map<number, Event[]>();\n\tfor (const evt of events) {\n\t\tconst h = Number(evt.block_height);\n\t\tconst list = eventsByHeight.get(h) ?? [];\n\t\tlist.push(evt);\n\t\teventsByHeight.set(h, list);\n\t}\n\n\tconst vmByHeight = new Map<number, RuntimeEvent[]>();\n\tfor (const row of vmRows) {\n\t\tconst h = Number(row.block_height);\n\t\tconst list = vmByHeight.get(h) ?? [];\n\t\tlist.push({\n\t\t\tid: vmEventId(row.tx_id, Number(row.ordinal)),\n\t\t\ttx_id: row.tx_id,\n\t\t\tblock_height: h,\n\t\t\tevent_index: Number(row.ordinal),\n\t\t\ttype: row.type,\n\t\t\tdata: row.data,\n\t\t\tcreated_at: row.created_at,\n\t\t\tclock: \"vm\",\n\t\t} as RuntimeEvent);\n\t\tvmByHeight.set(h, list);\n\t}\n\n\tconst result = new Map<number, BlockData>();\n\tfor (const block of blocks) {\n\t\tconst h = Number(block.height);\n\t\tresult.set(h, {\n\t\t\tblock,\n\t\t\ttxs: txsByHeight.get(h) ?? [],\n\t\t\tevents: eventsByHeight.get(h) ?? [],\n\t\t\tvmEvents: vmByHeight.get(h) ?? [],\n\t\t});\n\t}\n\n\treturn result;\n}\n\n/**\n * Compute average events per block from a loaded batch.\n * Used for adaptive batch sizing.\n */\nexport function avgEventsPerBlock(batch: Map<number, BlockData>): number {\n\tif (batch.size === 0) return 0;\n\tlet totalEvents = 0;\n\tfor (const data of batch.values()) {\n\t\ttotalEvents += data.events.length;\n\t}\n\treturn totalEvents / batch.size;\n}\n",
@@ -12,7 +12,7 @@
12
12
  "import { decodeStreamsCursor, isEmptyRangeCursor } from \"@secondlayer/shared\";\nimport { type Database, getSourceDb } from \"@secondlayer/shared/db\";\nimport type { Kysely } from \"kysely\";\nimport type { SubgraphDefinition } from \"../types.ts\";\nimport {\n\tVM_INDEX_EVENT_TYPES,\n\tisStreamsIndexEligible,\n\treferencedIndexEventTypes,\n} from \"./block-source.ts\";\n\n/**\n * Decoder-progress bound for consumers that read decoded Index rows.\n *\n * Each decoded event type is produced by an independent decoder\n * (`decode.<event_type>.v1` — ADR-0008/0010). Index `getTip` tracks\n * `decode.ft_transfer.v1` (or ingestion, on the Postgres tap). A forward-only\n * cursor that processes a height before the decoder feeding a referenced type\n * has committed it misses the match and never revisits.\n *\n * Bound the tip by the MIN committed height over ONLY the decoders the\n * consumer actually reads. A stalled unreferenced decoder (idle pox4) must\n * never gate progress. A referenced decoder with no usable checkpoint stalls\n * the consumer rather than falling through to the raw tip.\n */\n\n/** ADR checkpoint name. Subgraphs does not depend on `@secondlayer/indexer`. */\nexport function decoderNameForEventType(indexEventType: string): string {\n\treturn `decode.${indexEventType}.v1`;\n}\n\nexport function decoderNamesForIndexEventTypes(eventTypes: string[]): string[] {\n\treturn eventTypes\n\t\t.filter((t) => !VM_INDEX_EVENT_TYPES.has(t))\n\t\t.map(decoderNameForEventType);\n}\n\nexport function decoderNamesForSubgraph(\n\tsubgraph: SubgraphDefinition,\n): string[] {\n\treturn decoderNamesForIndexEventTypes(referencedIndexEventTypes(subgraph));\n}\n\n/**\n * True when catch-up/reindex will load decoded Index rows (the race).\n * Postgres tap reads raw `events` at ingest and must not wait on decode.\n * Mirrors `resolveBlockSource`'s streams-index branch.\n */\nexport function usesDecodedIndexPlane(subgraph: SubgraphDefinition): boolean {\n\treturn (\n\t\tprocess.env.SUBGRAPH_SOURCE === \"streams-index\" &&\n\t\tisStreamsIndexEligible(subgraph)\n\t);\n}\n\n/**\n * Highest height at which this cursor has fully committed. Mid-block\n * (`H:n`, n not the empty-range sentinel) means the rest of H is still\n * in flight — floor is H-1. Sentinel `H:2147483647` means H is done.\n */\nexport function committedHeight(\n\tcursor: string | null | undefined,\n): number | null {\n\tif (!cursor) return null;\n\ttry {\n\t\tconst decoded = decodeStreamsCursor(cursor);\n\t\tif (isEmptyRangeCursor(decoded)) return decoded.block_height;\n\t\treturn Math.max(0, decoded.block_height - 1);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport type DecoderBound =\n\t| { kind: \"unbounded\" }\n\t| { kind: \"stall\"; missing: string[] }\n\t| { kind: \"height\"; height: number };\n\n/**\n * Data-availability floor for `decoderNames`. Reads SOURCE-plane\n * `decoder_checkpoints` (same rationale as trait resolution: the consumer\n * handle is often the TARGET, where those rows are empty).\n */\nexport async function decoderBoundTip(\n\tdecoderNames: string[],\n\topts?: { sourceDb?: Kysely<Database> },\n): Promise<DecoderBound> {\n\tif (decoderNames.length === 0) return { kind: \"unbounded\" };\n\tconst sourceDb = opts?.sourceDb ?? getSourceDb();\n\tconst rows = await sourceDb\n\t\t.selectFrom(\"decoder_checkpoints\")\n\t\t.select([\"decoder_name\", \"last_cursor\"])\n\t\t.where(\"decoder_name\", \"in\", decoderNames)\n\t\t.execute();\n\tconst byName = new Map(rows.map((r) => [r.decoder_name, r.last_cursor]));\n\tconst missing: string[] = [];\n\tconst heights: number[] = [];\n\tfor (const name of decoderNames) {\n\t\tconst height = committedHeight(byName.get(name));\n\t\tif (height === null) missing.push(name);\n\t\telse heights.push(height);\n\t}\n\tif (missing.length > 0) return { kind: \"stall\", missing };\n\treturn { kind: \"height\", height: Math.min(...heights) };\n}\n\nexport type BoundSourceTip =\n\t| { ok: true; tip: number; floor: number | null }\n\t| { ok: false; missing: string[] };\n\n/** Combine a raw block-source tip with the decoder floor. */\nexport async function boundSourceTip(\n\trawTip: number,\n\tdecoderNames: string[],\n\topts?: { sourceDb?: Kysely<Database> },\n): Promise<BoundSourceTip> {\n\tconst bound = await decoderBoundTip(decoderNames, opts);\n\tif (bound.kind === \"stall\") return { ok: false, missing: bound.missing };\n\tif (bound.kind === \"unbounded\") {\n\t\treturn { ok: true, tip: rawTip, floor: null };\n\t}\n\treturn {\n\t\tok: true,\n\t\ttip: Math.min(rawTip, bound.height),\n\t\tfloor: bound.height,\n\t};\n}\n",
13
13
  "import type { SubgraphFilter } from \"../types.ts\";\n\nexport interface MatchedTx {\n\ttx: TxRecord;\n\tevents: EventRecord[];\n\t/** Source object key — used for handler dispatch */\n\tsourceName: string;\n}\n\nexport type TxRecord = {\n\ttx_id: string;\n\ttype: string;\n\tsender: string;\n\tstatus: string;\n\t/** Position within the block — the runner sorts dispatch into chain order. */\n\ttx_index?: number;\n\tcontract_id?: string | null;\n\tfunction_name?: string | null;\n\tfunction_args?: unknown | null;\n\traw_result?: string | null;\n};\n\nexport type EventRecord = {\n\tid: string;\n\ttx_id: string;\n\ttype: string;\n\t/** Classic `event_index`, or `ordinal` when `clock === \"vm\"`. */\n\tevent_index: number;\n\tdata: unknown;\n\t/** Set on opt-in `vm_events` rows. Two clocks never sort or dedupe together. */\n\tclock?: \"vm\";\n};\n\n// ── Wildcard matching (shared with v1) ──────────────────────────────\n\nconst patternCache = new Map<string, RegExp>();\n\n/** Match a value against one pattern, or ANY pattern in a set. */\nfunction matchAny(value: string, pattern: string | readonly string[]): boolean {\n\treturn Array.isArray(pattern)\n\t\t? pattern.some((p) => matchPattern(value, p))\n\t\t: matchPattern(value, pattern as string);\n}\n\nfunction matchPattern(value: string, pattern: string): boolean {\n\tif (!pattern.includes(\"*\")) return value === pattern;\n\tlet re = patternCache.get(pattern);\n\tif (!re) {\n\t\tconst regex = pattern\n\t\t\t.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n\t\t\t.replace(/\\*/g, \".*\");\n\t\tre = new RegExp(`^${regex}$`);\n\t\tpatternCache.set(pattern, re);\n\t}\n\treturn re.test(value);\n}\n\n// Trait → set of conforming contract IDs, resolved per block by the caller\n// (block-processor) from the contract registry. Kept as injected data so this\n// module stays pure/sync/DB-less.\nexport type TraitContracts = Map<string, ReadonlySet<string>>;\nconst EMPTY_SET: ReadonlySet<string> = new Set();\n\n/**\n * True when a filter's optional `trait` admits this contract: no trait → always\n * allowed; trait set → the contract must be in the resolved conforming set.\n */\n/** Addresses discovered per source name (factory sets), resolved by the\n * caller as-of the block being processed. */\nexport type FactoryContracts = ReadonlyMap<string, ReadonlySet<string>>;\n\n/**\n * A factory-scoped source matches only contracts its factory has revealed.\n * Same shape as {@link traitAllows}: the set is injected, so this module\n * stays pure and sync.\n */\nfunction factoryAllows(\n\tfilter: { factory?: { from: string; field: string } },\n\tcontractId: string | undefined | null,\n\tfactoryContracts: FactoryContracts,\n): boolean {\n\tif (!filter.factory) return true;\n\tif (!contractId) return false;\n\treturn (factoryContracts.get(filter.factory.from) ?? EMPTY_SET).has(\n\t\tcontractId,\n\t);\n}\n\n/** Read a dotted path off a decoded payload (`\"data.pool\"`). */\nexport function readPath(payload: unknown, path: string): unknown {\n\tlet cur: unknown = payload;\n\tfor (const key of path.split(\".\")) {\n\t\tif (cur === null || typeof cur !== \"object\") return undefined;\n\t\tcur = (cur as Record<string, unknown>)[key];\n\t}\n\treturn cur;\n}\n\nfunction traitAllows(\n\tfilter: SubgraphFilter,\n\tcontractId: string | undefined | null,\n\ttraitContracts: TraitContracts,\n): boolean {\n\tconst trait = (filter as { trait?: string }).trait;\n\tif (!trait) return true;\n\tif (!contractId) return false;\n\treturn (traitContracts.get(trait) ?? EMPTY_SET).has(contractId);\n}\n\n/** Extract the contract id from an asset identifier (`<contract>::<token>`). */\nfunction assetContract(assetId: string | undefined): string | undefined {\n\treturn assetId?.split(\"::\")[0];\n}\n\n/**\n * Contract on a print payload. Legacy `smart_contract_event` rows use\n * `contract_identifier`; current `contract_event` rows use `contract_id`.\n * Matcher and runner must share this — a print that matches on `contract_id`\n * otherwise reaches the handler with `event.contractId === \"\"`.\n */\nexport function printContractId(\n\tdata: Record<string, unknown> | null | undefined,\n): string | undefined {\n\tif (!data) return undefined;\n\tconst id =\n\t\t(typeof data.contract_identifier === \"string\"\n\t\t\t? data.contract_identifier\n\t\t\t: undefined) ??\n\t\t(typeof data.contract_id === \"string\" ? data.contract_id : undefined);\n\treturn id || undefined;\n}\n\n// ── Per-filter-type matchers ────────────────────────────────────────\n\nfunction matchFilter(\n\tfilter: SubgraphFilter,\n\ttransactions: TxRecord[],\n\teventsByTx: Map<string, EventRecord[]>,\n\ttraitContracts: TraitContracts,\n\tfactoryContracts: FactoryContracts = new Map(),\n\tvmEventsByTx: Map<string, EventRecord[]> = new Map(),\n): { tx: TxRecord; events: EventRecord[] }[] {\n\tconst results: { tx: TxRecord; events: EventRecord[] }[] = [];\n\n\tswitch (filter.type) {\n\t\t// ── STX events ──\n\t\tcase \"stx_transfer\":\n\t\tcase \"stx_mint\":\n\t\tcase \"stx_burn\":\n\t\tcase \"stx_lock\": {\n\t\t\tconst eventType = `${filter.type}_event`;\n\t\t\tfor (const tx of transactions) {\n\t\t\t\tconst txEvents = eventsByTx.get(tx.tx_id) ?? [];\n\t\t\t\tconst matched = txEvents.filter((e) => e.type === eventType);\n\t\t\t\tif (matched.length === 0) continue;\n\n\t\t\t\t// Apply address filters\n\t\t\t\tconst filtered = matched.filter((e) => {\n\t\t\t\t\tconst data = e.data as Record<string, unknown> | null;\n\t\t\t\t\tif (!data) return false;\n\t\t\t\t\tif (\"sender\" in filter && filter.sender) {\n\t\t\t\t\t\tif (!matchPattern(data.sender as string, filter.sender))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (\"recipient\" in filter && filter.recipient) {\n\t\t\t\t\t\tif (!matchPattern(data.recipient as string, filter.recipient))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (\"lockedAddress\" in filter && filter.lockedAddress) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t!matchPattern(data.locked_address as string, filter.lockedAddress)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\t// Amount filters\n\t\t\t\t\tif (\"minAmount\" in filter && filter.minAmount !== undefined) {\n\t\t\t\t\t\tconst amount = BigInt(\n\t\t\t\t\t\t\t(data.amount ?? data.locked_amount ?? \"0\") as string,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (amount < filter.minAmount) return false;\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\t\"maxAmount\" in filter &&\n\t\t\t\t\t\t(filter as { maxAmount?: bigint }).maxAmount !== undefined\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst amount = BigInt((data.amount ?? \"0\") as string);\n\t\t\t\t\t\tif (amount > (filter as { maxAmount: bigint }).maxAmount)\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t});\n\n\t\t\t\tif (filtered.length > 0) {\n\t\t\t\t\tresults.push({ tx, events: filtered });\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\t// ── FT events ──\n\t\tcase \"ft_transfer\":\n\t\tcase \"ft_mint\":\n\t\tcase \"ft_burn\": {\n\t\t\tconst eventType = `${filter.type}_event`;\n\t\t\tfor (const tx of transactions) {\n\t\t\t\tconst txEvents = eventsByTx.get(tx.tx_id) ?? [];\n\t\t\t\tconst matched = txEvents.filter((e) => {\n\t\t\t\t\tif (e.type !== eventType) return false;\n\t\t\t\t\tconst data = e.data as Record<string, unknown> | null;\n\t\t\t\t\tif (!data) return false;\n\n\t\t\t\t\t// Asset identifier filter\n\t\t\t\t\tif (filter.assetIdentifier) {\n\t\t\t\t\t\tconst assetId = data.asset_identifier as string | undefined;\n\t\t\t\t\t\tif (!assetId || !matchPattern(assetId, filter.assetIdentifier))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\t// Trait scope — the asset's contract must conform.\n\t\t\t\t\tif (\n\t\t\t\t\t\t!traitAllows(\n\t\t\t\t\t\t\tfilter,\n\t\t\t\t\t\t\tassetContract(data.asset_identifier as string | undefined),\n\t\t\t\t\t\t\ttraitContracts,\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t// Address filters\n\t\t\t\t\tif (\"sender\" in filter && filter.sender) {\n\t\t\t\t\t\tif (!matchPattern(data.sender as string, filter.sender))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (\"recipient\" in filter && filter.recipient) {\n\t\t\t\t\t\tif (!matchPattern(data.recipient as string, filter.recipient))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\t// Amount filter\n\t\t\t\t\tif (filter.minAmount !== undefined) {\n\t\t\t\t\t\tconst amount = BigInt((data.amount ?? \"0\") as string);\n\t\t\t\t\t\tif (amount < filter.minAmount) return false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t});\n\n\t\t\t\tif (matched.length > 0) {\n\t\t\t\t\tresults.push({ tx, events: matched });\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\t// ── NFT events ──\n\t\tcase \"nft_transfer\":\n\t\tcase \"nft_mint\":\n\t\tcase \"nft_burn\": {\n\t\t\tconst eventType = `${filter.type}_event`;\n\t\t\tfor (const tx of transactions) {\n\t\t\t\tconst txEvents = eventsByTx.get(tx.tx_id) ?? [];\n\t\t\t\tconst matched = txEvents.filter((e) => {\n\t\t\t\t\tif (e.type !== eventType) return false;\n\t\t\t\t\tconst data = e.data as Record<string, unknown> | null;\n\t\t\t\t\tif (!data) return false;\n\n\t\t\t\t\tif (filter.assetIdentifier) {\n\t\t\t\t\t\tconst assetId = data.asset_identifier as string | undefined;\n\t\t\t\t\t\tif (!assetId || !matchPattern(assetId, filter.assetIdentifier))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\t!traitAllows(\n\t\t\t\t\t\t\tfilter,\n\t\t\t\t\t\t\tassetContract(data.asset_identifier as string | undefined),\n\t\t\t\t\t\t\ttraitContracts,\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t\t\treturn false;\n\t\t\t\t\tif (\"sender\" in filter && filter.sender) {\n\t\t\t\t\t\tif (!matchPattern(data.sender as string, filter.sender))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (\"recipient\" in filter && filter.recipient) {\n\t\t\t\t\t\tif (!matchPattern(data.recipient as string, filter.recipient))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t});\n\n\t\t\t\tif (matched.length > 0) {\n\t\t\t\t\tresults.push({ tx, events: matched });\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\t// ── Contract call ──\n\t\tcase \"contract_call\": {\n\t\t\tfor (const tx of transactions) {\n\t\t\t\tif (tx.type !== \"contract_call\") continue;\n\n\t\t\t\t// Contract filter\n\t\t\t\tif (filter.contractId) {\n\t\t\t\t\tif (!tx.contract_id || !matchAny(tx.contract_id, filter.contractId))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// Factory scope: only contracts this source's factory revealed.\n\t\t\t\tif (!factoryAllows(filter, tx.contract_id, factoryContracts)) continue;\n\t\t\t\t// Function filter\n\t\t\t\tif (filter.functionName) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!tx.function_name ||\n\t\t\t\t\t\t!matchPattern(tx.function_name, filter.functionName)\n\t\t\t\t\t)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// Caller filter\n\t\t\t\tif (filter.caller) {\n\t\t\t\t\tif (!matchPattern(tx.sender, filter.caller)) continue;\n\t\t\t\t}\n\t\t\t\t// Trait scope — the called contract must conform.\n\t\t\t\tif (!traitAllows(filter, tx.contract_id, traitContracts)) continue;\n\n\t\t\t\tconst txEvents = eventsByTx.get(tx.tx_id) ?? [];\n\t\t\t\tresults.push({ tx, events: txEvents });\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\t// ── Contract deploy ──\n\t\tcase \"contract_deploy\": {\n\t\t\tfor (const tx of transactions) {\n\t\t\t\tif (tx.type !== \"smart_contract\") continue;\n\n\t\t\t\tif (filter.deployer) {\n\t\t\t\t\tif (!matchPattern(tx.sender, filter.deployer)) continue;\n\t\t\t\t}\n\t\t\t\tif (filter.contractName) {\n\t\t\t\t\tconst name = tx.contract_id?.split(\".\")[1] ?? \"\";\n\t\t\t\t\tif (!matchPattern(name, filter.contractName)) continue;\n\t\t\t\t}\n\n\t\t\t\tconst txEvents = eventsByTx.get(tx.tx_id) ?? [];\n\t\t\t\tresults.push({ tx, events: txEvents });\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"nested_contract_call\":\n\t\tcase \"var_set\":\n\t\tcase \"map_set\":\n\t\tcase \"map_insert\":\n\t\tcase \"map_delete\": {\n\t\t\t// vm sources read the vm clock only. A classic tx-level source never\n\t\t\t// sees these rows, and a vm source never sees `events[]`.\n\t\t\tfor (const tx of transactions) {\n\t\t\t\tconst txEvents = vmEventsByTx.get(tx.tx_id) ?? [];\n\t\t\t\tconst matched = txEvents.filter((e) => {\n\t\t\t\t\tif (e.type !== filter.type) return false;\n\t\t\t\t\tconst data = e.data as Record<string, unknown> | null;\n\t\t\t\t\tif (!data) return false;\n\t\t\t\t\tconst contractId = printContractId(data);\n\t\t\t\t\tif (\"contractId\" in filter && filter.contractId) {\n\t\t\t\t\t\tif (!contractId || !matchAny(contractId, filter.contractId))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (!traitAllows(filter, contractId, traitContracts)) return false;\n\t\t\t\t\tif (!factoryAllows(filter, contractId, factoryContracts))\n\t\t\t\t\t\treturn false;\n\t\t\t\t\tif (filter.type === \"nested_contract_call\") {\n\t\t\t\t\t\tif (filter.functionName) {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\ttypeof data.function_name !== \"string\" ||\n\t\t\t\t\t\t\t\t!matchPattern(data.function_name, filter.functionName)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (filter.caller) {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\ttypeof data.caller !== \"string\" ||\n\t\t\t\t\t\t\t\t!matchPattern(data.caller, filter.caller)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (filter.sender) {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\ttypeof data.sender !== \"string\" ||\n\t\t\t\t\t\t\t\t!matchPattern(data.sender, filter.sender)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (filter.type === \"var_set\" && filter.varName) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof data.var_name !== \"string\" ||\n\t\t\t\t\t\t\t!matchPattern(data.var_name, filter.varName)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\t(filter.type === \"map_set\" ||\n\t\t\t\t\t\t\tfilter.type === \"map_insert\" ||\n\t\t\t\t\t\t\tfilter.type === \"map_delete\") &&\n\t\t\t\t\t\tfilter.map\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof data.map_name !== \"string\" ||\n\t\t\t\t\t\t\t!matchPattern(data.map_name, filter.map)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t});\n\t\t\t\tif (matched.length > 0) results.push({ tx, events: matched });\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\t// ── Print event ──\n\t\tcase \"print_event\": {\n\t\t\tfor (const tx of transactions) {\n\t\t\t\tconst txEvents = eventsByTx.get(tx.tx_id) ?? [];\n\t\t\t\tconst matched = txEvents.filter((e) => {\n\t\t\t\t\tif (e.type !== \"smart_contract_event\" && e.type !== \"contract_event\")\n\t\t\t\t\t\treturn false;\n\t\t\t\t\tconst data = e.data as Record<string, unknown> | null;\n\t\t\t\t\tif (!data) return false;\n\t\t\t\t\tif (data.topic !== \"print\") return false;\n\n\t\t\t\t\tconst contractId = printContractId(data);\n\t\t\t\t\tif (filter.contractId) {\n\t\t\t\t\t\tif (!contractId || !matchAny(contractId, filter.contractId))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (!traitAllows(filter, contractId, traitContracts)) return false;\n\t\t\t\t\tif (!factoryAllows(filter, contractId, factoryContracts))\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t// Topic filter — check the decoded Clarity value's topic field\n\t\t\t\t\t// At this stage data.value is still raw hex; topic filtering happens\n\t\t\t\t\t// after decode in the runner. For now, skip topic filtering here.\n\t\t\t\t\t// The runner will filter by topic after decoding.\n\t\t\t\t\treturn true;\n\t\t\t\t});\n\n\t\t\t\tif (matched.length > 0) {\n\t\t\t\t\tresults.push({ tx, events: matched });\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn results;\n}\n\n/**\n * Match named filters against a block's transactions and events.\n * Returns matches with sourceName = the object key from sources.\n */\nexport function matchSources(\n\tsources: Record<string, SubgraphFilter>,\n\ttransactions: TxRecord[],\n\tevents: EventRecord[],\n\ttraitContracts: TraitContracts = new Map(),\n\tfactoryContracts: FactoryContracts = new Map(),\n\t/** Opt-in `vm_events` rows (second clock). Only vm-typed sources read them. */\n\tvmEvents: EventRecord[] = [],\n): MatchedTx[] {\n\t// Index events by txId — one map per clock.\n\tconst eventsByTx = new Map<string, EventRecord[]>();\n\tfor (const event of events) {\n\t\tconst list = eventsByTx.get(event.tx_id) ?? [];\n\t\tlist.push(event);\n\t\teventsByTx.set(event.tx_id, list);\n\t}\n\tconst vmEventsByTx = new Map<string, EventRecord[]>();\n\tfor (const event of vmEvents) {\n\t\tconst list = vmEventsByTx.get(event.tx_id) ?? [];\n\t\tlist.push(event);\n\t\tvmEventsByTx.set(event.tx_id, list);\n\t}\n\n\tconst seen = new Set<string>();\n\tconst results: MatchedTx[] = [];\n\n\tfor (const [sourceName, filter] of Object.entries(sources)) {\n\t\tconst matches = matchFilter(\n\t\t\tfilter,\n\t\t\ttransactions,\n\t\t\teventsByTx,\n\t\t\ttraitContracts,\n\t\t\tfactoryContracts,\n\t\t\tvmEventsByTx,\n\t\t);\n\t\tfor (const match of matches) {\n\t\t\tconst dedupeKey = `${match.tx.tx_id}:${sourceName}`;\n\t\t\tif (!seen.has(dedupeKey)) {\n\t\t\t\tseen.add(dedupeKey);\n\t\t\t\tresults.push({ ...match, sourceName });\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n}\n"
14
14
  ],
15
- "mappings": "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",
16
- "debugId": "12B00680B3E69AE464756E2164756E21",
15
+ "mappings": "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",
16
+ "debugId": "8038149B4D7A86CB64756E2164756E21",
17
17
  "names": []
18
18
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@secondlayer/subgraphs",
3
- "version": "5.0.0",
3
+ "version": "5.0.1",
4
4
  "description": "Describe the Stacks data you want as one TypeScript file; it fills itself and survives reorgs.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -51,7 +51,7 @@
51
51
  "prepublishOnly": "bun run build"
52
52
  },
53
53
  "dependencies": {
54
- "@secondlayer/shared": "^11.8.0",
54
+ "@secondlayer/shared": "^11.8.1",
55
55
  "@secondlayer/stacks": "^6.1.0",
56
56
  "esbuild": "^0.28.2",
57
57
  "kysely": "0.28.17",