{"version":3,"sources":["../src/transport.ts","../src/runtime.ts","../src/utils.ts","../src/signals.ts","../src/remote-config.ts","../src/fingerprint.ts","../src/initReplay.ts"],"names":["buf","record","frames","options"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { ReplayBatchEnvelope } from \"./schema\";\nimport type { WebReplayConfig } from \"./types\";\n\nexport interface IdentifyPayload {\n  distinctId?: string;\n  email?: string;\n  name?: string;\n  plan?: string;\n  customProps?: Record<string, unknown>;\n}\n\ninterface ApiSuccess<T> {\n  ok: true;\n  data: T;\n}\ninterface ApiError {\n  ok: false;\n  error: { code: string; message: string };\n}\ntype ApiResponse<T> = ApiSuccess<T> | ApiError;\n\nexport interface BatchSender {\n  (envelope: ReplayBatchEnvelope, useBeacon?: boolean): Promise<void>;\n  setIdentify: (identify: IdentifyPayload | undefined) => void;\n  setFingerprint: (fp: string) => void;\n  /** Bind the sender to THIS page load's session. Re-attaches a persisted\n   *  identity only when the same session resumed; a fresh session is cleared to\n   *  anonymous. Call once, before any setIdentify. */\n  bindSession: (sessionId: string, resumed: boolean) => void;\n  /** Unload-reliable send for the final flush: a keepalive fetch (survives page\n   *  teardown AND sets the api-key header, so it authenticates even where ?k=\n   *  isn't accepted), falling back to sendBeacon. Fire-and-forget. */\n  sendFinal: (envelope: ReplayBatchEnvelope) => void;\n}\n\n/**\n * Worker source (as a string so it bundles with a plain `tsc` build —\n * no separate worker chunk to load). It gzips a JSON string off the\n * main thread using the native Compression Streams API and returns the\n * bytes as a transferable ArrayBuffer. Zero dependencies.\n */\nconst GZIP_WORKER_SRC = `self.onmessage=async(e)=>{var d=e.data,id=d.id,json=d.json;try{var cs=new CompressionStream('gzip');var stream=new Blob([json]).stream().pipeThrough(cs);var buf=await new Response(stream).arrayBuffer();self.postMessage({id:id,buffer:buf},[buf])}catch(err){self.postMessage({id:id,error:(err&&err.message)||String(err)})}};`;\n\ninterface GzipWorker {\n  compress(json: string): Promise<ArrayBuffer>;\n  terminate(): void;\n}\n\n/** Build an inline gzip worker, or null if the environment lacks\n *  Worker / Blob / Compression Streams (older Safari, JSDOM, SSR). */\nfunction createGzipWorker(): GzipWorker | null {\n  const g = globalThis as {\n    Worker?: unknown;\n    Blob?: unknown;\n    URL?: { createObjectURL?: unknown };\n    CompressionStream?: unknown;\n  };\n  if (\n    typeof g.Worker === \"undefined\" ||\n    typeof g.Blob === \"undefined\" ||\n    typeof g.URL === \"undefined\" ||\n    typeof g.URL.createObjectURL === \"undefined\" ||\n    typeof g.CompressionStream === \"undefined\"\n  ) {\n    return null;\n  }\n  let worker: Worker;\n  try {\n    const url = URL.createObjectURL(\n      new Blob([GZIP_WORKER_SRC], { type: \"text/javascript\" }),\n    );\n    worker = new Worker(url);\n    URL.revokeObjectURL(url);\n  } catch {\n    return null;\n  }\n  let seq = 0;\n  const pending = new Map<\n    number,\n    { resolve: (b: ArrayBuffer) => void; reject: (e: unknown) => void }\n  >();\n  worker.onmessage = (e: MessageEvent) => {\n    const { id, buffer, error } = e.data as {\n      id: number;\n      buffer?: ArrayBuffer;\n      error?: string;\n    };\n    const p = pending.get(id);\n    if (!p) return;\n    pending.delete(id);\n    if (error || !buffer) p.reject(new Error(error ?? \"gzip failed\"));\n    else p.resolve(buffer);\n  };\n  worker.onerror = () => {\n    for (const [, p] of pending) p.reject(new Error(\"gzip worker error\"));\n    pending.clear();\n  };\n  return {\n    compress: (json) =>\n      new Promise<ArrayBuffer>((resolve, reject) => {\n        const id = ++seq;\n        pending.set(id, { resolve, reject });\n        worker.postMessage({ id, json });\n      }),\n    terminate: () => worker.terminate(),\n  };\n}\n\n/** Main-thread gzip fallback for when a worker can't be created but the\n *  Compression Streams API is still available. */\nasync function gzipMainThread(json: string): Promise<ArrayBuffer | null> {\n  const CS = (\n    globalThis as {\n      CompressionStream?: new (format: string) => ReadableWritablePair;\n    }\n  ).CompressionStream;\n  if (\n    !CS ||\n    typeof Blob === \"undefined\" ||\n    typeof Response === \"undefined\"\n  ) {\n    return null;\n  }\n  try {\n    const stream = new Blob([json]).stream().pipeThrough(new CS(\"gzip\"));\n    return await new Response(\n      stream as unknown as BodyInit,\n    ).arrayBuffer();\n  } catch {\n    return null;\n  }\n}\n\n/** Retry a failed replay batch a few times before giving up. Transient failures\n *  (network/CORS rejection, 5xx, 429) are retried; a 4xx or a 2xx-but-rejected is\n *  terminal. On a hard outage the caller re-queues the batch for the next flush. */\nconst MAX_SEND_ATTEMPTS = 3;\nconst SEND_BACKOFF_MS = 300;\n\n/** Where the current tab's identify() payload is stashed, TAGGED with the session\n *  id it belongs to. A reload re-attaches it ONLY when the same session resumed\n *  (bindSession checks the sid) — so it closes the \"identify lost on reload\" gap\n *  without leaking identity into a DIFFERENT session that happens to share the\n *  tab (a post-inactivity rollover, or a logged-out visitor on a shared machine).\n *  sessionStorage (per-tab, cleared on tab-close) also keeps identity from\n *  sticking to the browser forever with no logout hook. */\nconst IDENTIFY_STORAGE_KEY = \"replay:identify\";\n\ninterface StoredIdentify {\n  sid: string;\n  payload: IdentifyPayload;\n}\n\nfunction loadStoredIdentify(): StoredIdentify | null {\n  try {\n    const raw = sessionStorage.getItem(IDENTIFY_STORAGE_KEY);\n    if (!raw) return null;\n    const s = JSON.parse(raw) as Partial<StoredIdentify>;\n    if (\n      s &&\n      typeof s.sid === \"string\" &&\n      s.payload &&\n      typeof s.payload === \"object\" &&\n      (s.payload.distinctId || s.payload.email)\n    ) {\n      return { sid: s.sid, payload: s.payload };\n    }\n  } catch {\n    /* sessionStorage blocked / corrupt — start anonymous */\n  }\n  return null;\n}\n\nfunction persistIdentify(\n  sid: string | undefined,\n  payload: IdentifyPayload | undefined,\n): void {\n  try {\n    if (!sid || !payload || (!payload.distinctId && !payload.email)) {\n      sessionStorage.removeItem(IDENTIFY_STORAGE_KEY);\n      return;\n    }\n    sessionStorage.setItem(IDENTIFY_STORAGE_KEY, JSON.stringify({ sid, payload }));\n  } catch {\n    /* ignore — identity just won't survive this reload */\n  }\n}\n\nexport function createBatchSender(config: WebReplayConfig): BatchSender {\n  const endpoint = new URL(\"/v1/replay/batch\", config.apiHost).toString();\n  const fetchImpl = config.fetchImpl ?? window.fetch.bind(window);\n  // Identity is seeded by bindSession() (called from initReplay once the session\n  // id + resumed flag are known) — NOT unconditionally at construction, so a\n  // fresh session never inherits a prior session's user. See bindSession.\n  let currentIdentify: IdentifyPayload | undefined;\n  let currentSessionId: string | undefined;\n\n  let currentFingerprint: string | undefined;\n\n  // Lazily-created gzip worker. `undefined` = not tried yet, `null` =\n  // tried and unavailable (env lacks Worker/CompressionStream).\n  let gzipWorker: GzipWorker | null | undefined;\n\n  // Compress the JSON body. Prefers the off-main-thread worker, falls\n  // back to main-thread gzip, then to uncompressed — so a missing API\n  // never blocks a send.\n  const compressBody = async (\n    json: string,\n  ): Promise<{ body: BodyInit; gzip: boolean }> => {\n    if (gzipWorker === undefined) gzipWorker = createGzipWorker();\n    if (gzipWorker) {\n      try {\n        const buf = await gzipWorker.compress(json);\n        return { body: buf, gzip: true };\n      } catch {\n        // Worker died — stop using it and fall through.\n        gzipWorker.terminate();\n        gzipWorker = null;\n      }\n    }\n    const buf = await gzipMainThread(json);\n    if (buf) return { body: buf, gzip: true };\n    return { body: json, gzip: false };\n  };\n\n  const send: BatchSender = async (\n    envelope: ReplayBatchEnvelope,\n    useBeacon = false,\n  ): Promise<void> => {\n    const json = JSON.stringify({\n      envelope,\n      identify: currentIdentify,\n      fingerprint: currentFingerprint,\n    });\n\n    if (useBeacon && \"sendBeacon\" in navigator) {\n      // sendBeacon is sync and can't set headers, so it stays uncompressed and\n      // the key rides as ?k= — it only fires on unload where the last small\n      // batch isn't worth the async gzip round-trip.\n      // The Blob MUST be text/plain, not application/json: the ingest host is\n      // cross-origin to every customer site, and a non-CORS-safelisted\n      // content-type (application/json) turns the POST into a PREFLIGHTED\n      // request — which sendBeacon cannot satisfy, so the browser blocks it\n      // (\"CORS error\"/provisional headers) and the tail batch is dropped.\n      // text/plain is safelisted → no preflight; the backend parses it as JSON.\n      const url = `${endpoint}?${new URLSearchParams({ k: config.apiKey }).toString()}`;\n      navigator.sendBeacon(url, new Blob([json], { type: \"text/plain\" }));\n      return;\n    }\n\n    const { body, gzip } = await compressBody(json);\n    const headers: Record<string, string> = {\n      \"content-type\": \"application/json\",\n      \"x-replay-api-key\": config.apiKey,\n    };\n    // Content-Encoding: gzip lets the server (express body-parser)\n    // transparently inflate before JSON parsing.\n    if (gzip) headers[\"content-encoding\"] = \"gzip\";\n\n    // Retry transient failures with exponential backoff. A fetch rejection\n    // (network/CORS) or a 5xx/429 is transient; a 4xx or a 2xx-but-rejected is\n    // terminal (retrying won't help), so we surface those immediately. After the\n    // last attempt the error propagates and the caller re-queues the batch.\n    let lastError: unknown;\n    for (let attempt = 1; attempt <= MAX_SEND_ATTEMPTS; attempt += 1) {\n      try {\n        const response = await fetchImpl(endpoint, {\n          method: \"POST\",\n          headers,\n          body,\n        });\n        if (response.ok) {\n          const payload = (await response.json()) as ApiResponse<{\n            accepted: boolean;\n          }>;\n          if (!payload.ok || !payload.data.accepted) {\n            throw new Error(\"Replay batch rejected by server\");\n          }\n          return; // delivered\n        }\n        // Only 5xx / 429 are worth retrying; any other status is terminal.\n        if (response.status < 500 && response.status !== 429) {\n          throw new Error(`Replay batch failed with status ${response.status}`);\n        }\n        lastError = new Error(\n          `Replay batch failed with status ${response.status}`,\n        );\n      } catch (e) {\n        // Terminal errors thrown above must not burn retries — re-throw them.\n        if (\n          e instanceof Error &&\n          (e.message.startsWith(\"Replay batch failed with status\") ||\n            e.message === \"Replay batch rejected by server\")\n        ) {\n          throw e;\n        }\n        // Otherwise it's a network/CORS fetch rejection → retryable.\n        lastError = e;\n      }\n      if (attempt < MAX_SEND_ATTEMPTS) {\n        await new Promise((r) =>\n          setTimeout(r, SEND_BACKOFF_MS * 2 ** (attempt - 1)),\n        );\n      }\n    }\n    throw lastError instanceof Error\n      ? lastError\n      : new Error(\"Replay batch send failed after retries\");\n  };\n\n  send.bindSession = (sessionId, resumed) => {\n    currentSessionId = sessionId;\n    // Re-attach a persisted identity ONLY when this page load resumed the SAME\n    // session it was captured under. A freshly minted session (new tab, or a\n    // post-inactivity rollover in the same tab) starts anonymous until the host\n    // re-identifies — otherwise it would inherit the previous session's\n    // (possibly logged-out or different) user. Ties identity to the session's\n    // lifetime, matching the reference tracker's per-session user id.\n    const stored = loadStoredIdentify();\n    if (resumed && stored && stored.sid === sessionId) {\n      currentIdentify = stored.payload;\n    } else {\n      currentIdentify = undefined;\n      persistIdentify(undefined, undefined); // drop any stale prior-session identity\n    }\n  };\n  send.setIdentify = (identify) => {\n    if (!identify) {\n      currentIdentify = undefined;\n      persistIdentify(currentSessionId, undefined);\n      return;\n    }\n    // REPLACE (not merge) when the distinctId changes — a shallow merge would\n    // ship the previous user's email/name/plan/customProps under the new user's\n    // id (cross-user PII contamination). Merge only for a same-user trait update\n    // or a trait-only call (no distinctId).\n    const prev = currentIdentify;\n    const switchingUser =\n      !!identify.distinctId &&\n      !!prev?.distinctId &&\n      identify.distinctId !== prev.distinctId;\n    currentIdentify = switchingUser\n      ? { ...identify }\n      : { ...(prev ?? {}), ...identify };\n    // Persist (tagged with this session) so a reload of the SAME session\n    // re-attaches it; bindSession guards against a different session reusing it.\n    persistIdentify(currentSessionId, currentIdentify);\n  };\n  send.setFingerprint = (fp) => {\n    currentFingerprint = fp;\n  };\n  const beaconFallback = (json: string) => {\n    try {\n      if (typeof navigator !== \"undefined\" && navigator.sendBeacon) {\n        // Beacon can't set headers, so the key rides as ?k= (the backend accepts\n        // either). Kept < 55KB per chunk by the caller so it isn't dropped. The\n        // Blob is text/plain (a CORS-safelisted type) so this cross-origin beacon\n        // isn't preflighted — application/json would be, and sendBeacon can't do\n        // a preflight, so the browser would CORS-block it.\n        const url = `${endpoint}?${new URLSearchParams({ k: config.apiKey }).toString()}`;\n        navigator.sendBeacon(url, new Blob([json], { type: \"text/plain\" }));\n      }\n    } catch {\n      /* nothing left to try — the page is going away */\n    }\n  };\n  send.sendFinal = (envelope) => {\n    const json = JSON.stringify({\n      envelope,\n      identify: currentIdentify,\n      fingerprint: currentFingerprint,\n    });\n    // Primary: keepalive fetch. It survives the unload and, unlike sendBeacon,\n    // sets the x-replay-api-key HEADER. Only fall back to a beacon if the fetch\n    // rejects/throws while the page is still alive (no double-send on success).\n    try {\n      void fetchImpl(endpoint, {\n        method: \"POST\",\n        headers: {\n          \"content-type\": \"application/json\",\n          \"x-replay-api-key\": config.apiKey,\n        },\n        body: json,\n        keepalive: true,\n      }).catch(() => beaconFallback(json));\n    } catch {\n      beaconFallback(json);\n    }\n  };\n\n  return send;\n}\n","import type {\n  ReplayBatchEnvelope,\n  ReplayEvent,\n  ReplaySdkDescriptor,\n} from \"./schema\";\nimport type { WebReplayConfig } from \"./types\";\n\ninterface SessionRuntime {\n  sessionId: string;\n  segmentId: string;\n  startedAt: number;\n  /** True when this page load RESUMED an existing session (same tab, within the\n   *  inactivity window) instead of minting a fresh one — a reload or same-tab\n   *  back/forward. The caller records a resume as a navigation, not a new\n   *  session_start, so the original entry page is preserved. */\n  resumed: boolean;\n  /** Re-anchor a FRESH session's clock to NOW. Called at the visibility-gated\n   *  start so the timeline begins when the page is first VISIBLE, not when a\n   *  hidden / prerendered tab happened to construct the runtime. The caller only\n   *  invokes it for !resumed sessions, so a reload keeps its original startedAt\n   *  (offset continuity across the load). */\n  beginFreshClock: () => void;\n  sdk: ReplaySdkDescriptor;\n  makeEventId: () => string;\n  push: (event: ReplayEvent) => void;\n  drain: () => ReplayEvent[];\n  /** Put un-sent events back at the FRONT of the buffer after a failed send, so\n   *  the next flush retries them instead of dropping the batch. Bounded. */\n  requeue: (events: ReplayEvent[]) => void;\n  /** Mark genuine USER activity (an interaction) so a subsequent reload within\n   *  the inactivity window continues this session. Cheap + throttled — safe to\n   *  call on every pointer/scroll/key event. */\n  touch: () => void;\n  /** The inactivity window (ms). Governs BOTH the reload resume-vs-fresh decision\n   *  AND the live idle-timeout that ends a session with no meaningful activity. */\n  inactivityMs: number;\n  /** Start a BRAND-NEW session in place — mint a fresh sessionId/segmentId, reset\n   *  the clock to now, zero the sequence, and drop any residual buffer. Called\n   *  when a user returns after the session was ended for inactivity, so the\n   *  return is a new session (new id) rather than a continuation of a stale one.\n   *  The transport's identify/fingerprint state is untouched — it's the same\n   *  anonymous/identified person. */\n  rotate: () => void;\n  nextSequence: () => number;\n  pageContext: () => ReplayBatchEnvelope[\"page\"];\n  startAutoFlush: (flush: () => Promise<void>) => void;\n  stopAutoFlush: () => void;\n  /** Deliver everything buffered on page-hide/unload, CHUNKED so each piece\n   *  stays under the beacon/keepalive ~64KB cap. A single oversized final batch\n   *  is silently dropped by the browser → the session's closing frames never\n   *  persist (a blank/frozen replay tail). Each chunk goes through the\n   *  transport's unload-reliable sendFinal (keepalive-fetch, beacon fallback). */\n  flushFinal: (sendFinal: (envelope: ReplayBatchEnvelope) => void) => void;\n}\n\n/** Conservative per-chunk byte budget for the final flush. sendBeacon and\n *  keepalive fetch both cap the body near 64KB; 55KB leaves headroom for the\n *  envelope wrapper. rrweb payloads are ~ASCII so string length ≈ byte length. */\nconst MAX_FINAL_CHUNK_BYTES = 55_000;\n\nfunction safeTimezone(): string | undefined {\n  try {\n    return Intl.DateTimeFormat().resolvedOptions().timeZone;\n  } catch {\n    return undefined;\n  }\n}\n\nfunction pageContext(): ReplayBatchEnvelope[\"page\"] {\n  return {\n    url: window.location.href,\n    title: document.title,\n    referrer: document.referrer,\n    userAgent: navigator.userAgent,\n    viewport: { width: window.innerWidth, height: window.innerHeight },\n    screen: { width: window.screen.width, height: window.screen.height },\n    timezone: safeTimezone(),\n    language: navigator.language,\n  };\n}\n\n/** Monotonic within a page load — guarantees two ids minted back-to-back\n *  (e.g. sessionId then segmentId) differ even if every RANDOM source below is\n *  degenerate. */\nlet idSeq = 0;\n\n/** A collision-resistant id. The old version was pure `crypto.getRandomValues`,\n *  which a hostile/headless client can STUB to return constant bytes — a crawler\n *  did exactly that and produced the SAME ses_/seg_ id on two different sites,\n *  merging their recordings server-side. So the id no longer trusts the RNG\n *  alone: it also folds in a high-resolution timestamp, a per-page monotonic\n *  counter, and Math.random (a separate PRNG). A collision now requires the\n *  wall clock, the counter, Math.random AND crypto to ALL coincide — which they\n *  can't for two distinct sessions. `crypto.randomUUID`/`getRandomValues` still\n *  supply the bulk of the entropy on a healthy client. */\nfunction shortId(prefix: string): string {\n  idSeq = (idSeq + 1) & 0xffffff;\n  let rnd = \"\";\n  try {\n    const c = globalThis.crypto;\n    if (c && typeof c.randomUUID === \"function\") {\n      rnd = c.randomUUID().replace(/-/g, \"\");\n    } else if (c && typeof c.getRandomValues === \"function\") {\n      const b = new Uint8Array(12);\n      c.getRandomValues(b);\n      rnd = Array.from(b, (x) => x.toString(16).padStart(2, \"0\")).join(\"\");\n    }\n  } catch {\n    /* crypto unavailable — the non-crypto sources below still keep it unique */\n  }\n  const now =\n    Date.now().toString(36) +\n    (typeof performance !== \"undefined\" && performance.now\n      ? Math.floor(performance.now() * 1000).toString(36)\n      : \"\");\n  const jitter =\n    idSeq.toString(36) + Math.floor(Math.random() * 0x100000000).toString(36);\n  return `${prefix}${now}${jitter}${rnd}`;\n}\n\n/** Hard cap on buffered events so a sustained ingest outage (every flush failing\n *  and re-queuing) can't grow the buffer without bound. A few MB of rrweb. */\nconst MAX_BUFFERED_EVENTS = 20000;\n\n/** Where a session's identity lives BETWEEN page loads. sessionStorage is\n *  per-tab: it survives a reload/same-tab navigation but is cleared when the tab\n *  closes — so a reload CONTINUES the session while a brand-new tab starts a\n *  fresh one. This is a deliberate per-tab session model: each tab is its own\n *  session, and what ties a person's tabs together is the shared anonymous id\n *  (see fingerprint.ts, in per-origin localStorage), which the backend uses to\n *  stitch the tabs' sessions to one user. Cross-tab session sharing — one\n *  session spanning several open tabs — is intentionally NOT done here; it would\n *  need a per-tab id in the capture format plus a tab-aware player, and is\n *  tracked as separate future work. */\nconst SESSION_STORAGE_KEY = \"replay:ses\";\n\n/** Default inactivity window: a reload only continues the session if the last\n *  user interaction was within this long. 30 min is the session-analytics norm.\n *  Overridable via config.sessionInactivityMs. */\nconst DEFAULT_INACTIVITY_MS = 30 * 60 * 1000;\n\n/** Don't persist the last-activity marker on every pointer/scroll event — once\n *  every few seconds keeps the reload window accurate at negligible cost. The\n *  window (minutes) dwarfs this staleness, so it never changes a resume verdict. */\nconst ACTIVITY_PERSIST_THROTTLE_MS = 5000;\n\ninterface PersistedSession {\n  /** sessionId */\n  sid: string;\n  /** original session start — kept across reloads so offsetMs stays monotonic */\n  st: number;\n  /** last USER-activity timestamp — drives the inactivity/resume decision */\n  la: number;\n}\n\nfunction readPersistedSession(): PersistedSession | null {\n  try {\n    const raw = sessionStorage.getItem(SESSION_STORAGE_KEY);\n    if (!raw) return null;\n    const p = JSON.parse(raw) as Partial<PersistedSession>;\n    if (\n      typeof p.sid === \"string\" &&\n      typeof p.st === \"number\" &&\n      typeof p.la === \"number\"\n    ) {\n      return { sid: p.sid, st: p.st, la: p.la };\n    }\n  } catch {\n    /* sessionStorage blocked (private mode) or corrupt JSON — treat as no prior\n       session; we just mint a fresh one, recording is otherwise unaffected. */\n  }\n  return null;\n}\n\nfunction writePersistedSession(p: PersistedSession): void {\n  try {\n    sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(p));\n  } catch {\n    /* sessionStorage unavailable/full — the session simply won't survive a\n       reload; nothing else breaks. */\n  }\n}\n\nexport function createSessionRuntime(config: WebReplayConfig): SessionRuntime {\n  const now = Date.now();\n  const inactivityMs = config.sessionInactivityMs ?? DEFAULT_INACTIVITY_MS;\n\n  // Decide this page load's session identity:\n  //   1. an explicit config.sessionId always wins (host-controlled).\n  //   2. otherwise resume the tab's stored session if the last USER interaction\n  //      was within the inactivity window (reload / same-tab back-forward) —\n  //      reusing its original startedAt so offsets stay monotonic across loads.\n  //   3. otherwise mint a fresh session.\n  let sessionId: string;\n  let startedAt: number;\n  let lastActivityAt: number;\n  let resumed = false;\n  if (config.sessionId) {\n    sessionId = config.sessionId;\n    startedAt = now;\n    lastActivityAt = now;\n  } else {\n    const prior = readPersistedSession();\n    if (prior && now - prior.la < inactivityMs) {\n      sessionId = prior.sid;\n      startedAt = prior.st;\n      lastActivityAt = prior.la;\n      resumed = true;\n    } else {\n      sessionId = shortId(\"ses_\");\n      startedAt = now;\n      lastActivityAt = now;\n    }\n  }\n  // Persist right away so even an instant reload (before any interaction) still\n  // resumes, and so `st` is pinned to this session's true origin.\n  writePersistedSession({ sid: sessionId, st: startedAt, la: lastActivityAt });\n\n  let segmentId = shortId(\"seg_\");\n  const buffer: ReplayEvent[] = [];\n  let sequence = 0;\n  let timer: number | undefined;\n  let lastActivityPersist = now;\n\n  const sdk: ReplaySdkDescriptor = {\n    name: config.sdk?.name ?? \"@replay/web-sdk\",\n    version: config.sdk?.version ?? \"0.1.0\",\n    platform: config.sdk?.platform ?? \"web\",\n    ...(config.revId ? { revId: config.revId } : {}),\n  };\n\n  return {\n    // Getters, not snapshots — rotate() reassigns the identity mid-flight (a\n    // return after an inactivity end), and every reader (flush's envelope, the\n    // controller's `sessionId`) must see the CURRENT session, not the one that\n    // existed at init.\n    get sessionId() {\n      return sessionId;\n    },\n    get segmentId() {\n      return segmentId;\n    },\n    // Live getter — `beginFreshClock()` can re-anchor it at the visibility-gated\n    // start, and the emit()/minDuration reads must see the updated value.\n    get startedAt() {\n      return startedAt;\n    },\n    resumed,\n    inactivityMs,\n    beginFreshClock: () => {\n      startedAt = Date.now();\n      lastActivityAt = startedAt;\n      lastActivityPersist = startedAt;\n      writePersistedSession({ sid: sessionId, st: startedAt, la: startedAt });\n    },\n    rotate: () => {\n      sessionId = shortId(\"ses_\");\n      segmentId = shortId(\"seg_\");\n      startedAt = Date.now();\n      lastActivityAt = startedAt;\n      lastActivityPersist = startedAt;\n      sequence = 0;\n      // The ended session was flushed before we got here; drop any residual so\n      // the new session starts clean (its first batch must be full_snapshot-led).\n      buffer.length = 0;\n      writePersistedSession({ sid: sessionId, st: startedAt, la: startedAt });\n    },\n    sdk,\n    makeEventId: () => globalThis.crypto.randomUUID(),\n    push: (event) => {\n      buffer.push(event);\n    },\n    drain: () => buffer.splice(0, buffer.length),\n    requeue: (events) => {\n      if (events.length === 0) return;\n      // Prepend the un-sent (older) events ahead of anything captured during the\n      // failed send, preserving order — without spreading a possibly-large array\n      // into unshift() (which can overflow the call stack).\n      const tail = buffer.splice(0, buffer.length);\n      for (let i = 0; i < events.length; i += 1) buffer.push(events[i]);\n      for (let i = 0; i < tail.length; i += 1) buffer.push(tail[i]);\n      // Bound memory during a sustained outage: keep the OLDEST events — the rrweb\n      // FullSnapshot lives there and losing it makes the whole recording\n      // unplayable — dropping the newest beyond the cap.\n      if (buffer.length > MAX_BUFFERED_EVENTS) buffer.length = MAX_BUFFERED_EVENTS;\n    },\n    touch: () => {\n      const t = Date.now();\n      lastActivityAt = t;\n      // Throttle the write — in-memory lastActivityAt is always current; only the\n      // persisted copy lags (<= throttle), which the minutes-long window absorbs.\n      if (t - lastActivityPersist >= ACTIVITY_PERSIST_THROTTLE_MS) {\n        lastActivityPersist = t;\n        writePersistedSession({ sid: sessionId, st: startedAt, la: t });\n      }\n    },\n    nextSequence: () => {\n      sequence += 1;\n      return sequence;\n    },\n    pageContext,\n    startAutoFlush: (flush) => {\n      const flushIntervalMs = config.flushIntervalMs ?? 3000;\n      timer = window.setInterval(() => {\n        void flush();\n      }, flushIntervalMs);\n    },\n    stopAutoFlush: () => {\n      if (timer !== undefined) window.clearInterval(timer);\n    },\n    flushFinal: (sendFinal) => {\n      const events = buffer.splice(0, buffer.length);\n      if (events.length === 0) return;\n      let chunk: ReplayEvent[] = [];\n      let chunkBytes = 0;\n      const ship = () => {\n        if (chunk.length === 0) return;\n        sequence += 1;\n        sendFinal({\n          projectId: config.projectId,\n          sessionId,\n          segmentId,\n          sequence,\n          sentAt: Date.now(),\n          sdk,\n          page: pageContext(),\n          events: chunk,\n        });\n        chunk = [];\n        chunkBytes = 0;\n      };\n      for (let i = 0; i < events.length; i += 1) {\n        const ev = events[i];\n        const evBytes = JSON.stringify(ev).length;\n        // Close the current chunk before an event that would overflow it — but\n        // never emit an empty chunk, so a single event over the cap still ships\n        // alone (the best we can do without async compression on unload).\n        if (chunkBytes + evBytes > MAX_FINAL_CHUNK_BYTES && chunk.length > 0) {\n          ship();\n        }\n        chunk.push(ev);\n        chunkBytes += evBytes;\n      }\n      ship();\n    },\n  };\n}\n","/**\n * Convert a single console.log argument into something JSON-safe.\n *\n * We preserve structure (objects stay objects, arrays stay arrays) so the\n * dashboard can render a collapsible tree instead of a stringified blob.\n * Errors keep their stack trace. Functions, DOM nodes, and circular refs\n * fall back to a readable label so they don't explode JSON.stringify.\n */\nexport function serializeConsoleArg(value: unknown): unknown {\n  if (value instanceof Error) {\n    return {\n      __type: \"Error\",\n      name: value.name,\n      message: value.message,\n      stack: value.stack,\n    };\n  }\n  if (typeof value === \"function\")\n    return `[Function ${value.name || \"anonymous\"}]`;\n  if (typeof value === \"undefined\") return \"undefined\";\n  if (typeof value === \"symbol\") return value.toString();\n  if (typeof value === \"bigint\") return `${value.toString()}n`;\n  if (value === null) return null;\n  if (typeof value !== \"object\") return value;\n  if (value instanceof Date)\n    return { __type: \"Date\", iso: value.toISOString() };\n  if (value instanceof RegExp)\n    return { __type: \"RegExp\", source: value.toString() };\n  if (typeof Node !== \"undefined\" && value instanceof Node) {\n    const el = value as Element;\n    return `[${el.tagName?.toLowerCase() ?? \"Node\"}${el.id ? \"#\" + el.id : \"\"}]`;\n  }\n  // Strip circular refs with a WeakSet — JSON.stringify throws otherwise.\n  const seen = new WeakSet();\n  try {\n    return JSON.parse(\n      JSON.stringify(value, (_k, v) => {\n        if (typeof v === \"object\" && v !== null) {\n          if (seen.has(v)) return \"[Circular]\";\n          seen.add(v);\n        }\n        if (typeof v === \"bigint\") return `${v.toString()}n`;\n        if (typeof v === \"function\")\n          return `[Function ${(v as { name?: string }).name || \"anonymous\"}]`;\n        return v;\n      }),\n    );\n  } catch {\n    return String(value);\n  }\n}\n\n/**\n * Format a serialized arg for the human-readable `message` string the\n * console panel falls back to when it doesn't render the tree. Strings\n * pass through; objects/arrays become compact JSON; primitives use String().\n */\nexport function formatConsoleArg(value: unknown): string {\n  if (value == null) return String(value);\n  if (typeof value === \"string\") return value;\n  if (typeof value === \"number\" || typeof value === \"boolean\")\n    return String(value);\n  if (typeof value === \"object\") {\n    try {\n      return JSON.stringify(value);\n    } catch {\n      return \"[Unserialisable]\";\n    }\n  }\n  return String(value);\n}\n\nexport function toHeaderRecord(headers: Headers): Record<string, string> {\n  const record: Record<string, string> = {};\n  headers.forEach((value, key) => {\n    record[key] = value;\n  });\n  return record;\n}\n\n/**\n * Header names whose *values* are masked before any network event\n * leaves the browser. Case-insensitive. Covers cookies, auth tokens,\n * and the common API-key / CSRF header conventions — matching the\n * reference tracker's default ignore-list, extended with the API-key\n * variants we see most.\n */\nexport const DEFAULT_SENSITIVE_HEADERS = [\n  \"cookie\",\n  \"set-cookie\",\n  \"authorization\",\n  \"proxy-authorization\",\n  \"www-authenticate\",\n  \"x-api-key\",\n  \"api-key\",\n  \"x-auth-token\",\n  \"x-access-token\",\n  \"x-csrf-token\",\n  \"x-xsrf-token\",\n  \"x-amz-security-token\",\n];\n\nconst REDACTED_HEADER = \"[redacted]\";\n\n/**\n * Return a copy of `headers` with sensitive values masked. We keep the\n * key (so you can still see that an Authorization header WAS sent) but\n * never ship its value. The built-in deny-list is always applied;\n * `extra` lets a workspace add its own header names on top. Redaction\n * is ON by default — there is no opt-out that ships raw credentials.\n */\nexport function redactHeaders(\n  headers: Record<string, string>,\n  extra?: string[],\n): Record<string, string> {\n  const deny = new Set(\n    [...DEFAULT_SENSITIVE_HEADERS, ...(extra ?? [])].map((h) =>\n      h.toLowerCase(),\n    ),\n  );\n  const out: Record<string, string> = {};\n  for (const [k, v] of Object.entries(headers)) {\n    out[k] = deny.has(k.toLowerCase()) ? REDACTED_HEADER : v;\n  }\n  return out;\n}\n\nexport function withRedactedUrl(\n  url: string,\n  patterns: Array<string | RegExp> | undefined,\n): string {\n  if (!patterns || patterns.length === 0) return url;\n  let result = url;\n  for (const p of patterns) {\n    if (typeof p === \"string\") {\n      // Replace `key=value` substrings (treat string as a key name).\n      result = result.replace(\n        new RegExp(`\\\\b${p}[^&]*`, \"gi\"),\n        `${p}[REDACTED]`,\n      );\n    } else {\n      result = result.replace(p, \"[REDACTED]\");\n    }\n  }\n  return result;\n}\n\n/** Query-string keys whose VALUES are ALWAYS scrubbed from any captured URL,\n *  with zero configuration — credentials that must never be stored server-side.\n *  Matched case-insensitively. Mirrors the reference tracker's default URL\n *  sanitizer (tokens leaking into stored nav/entry URLs is a real exposure). */\nexport const DEFAULT_SENSITIVE_QUERY_KEYS = [\n  \"jwt\", \"token\", \"access_token\", \"refresh_token\", \"id_token\", \"auth\",\n  \"authorization\", \"password\", \"passwd\", \"pwd\", \"secret\", \"api_key\", \"apikey\",\n  \"invitation\", \"invite\", \"reset-password\", \"reset_password\", \"otp\", \"sig\",\n  \"signature\", \"code\", \"state\",\n];\n\nconst CC_RE = /\\b(?:\\d[ -]?){13,19}\\b/g;\n\nfunction luhnValid(num: string): boolean {\n  let sum = 0;\n  let alt = false;\n  for (let i = num.length - 1; i >= 0; i -= 1) {\n    let d = num.charCodeAt(i) - 48;\n    if (alt) {\n      d *= 2;\n      if (d > 9) d -= 9;\n    }\n    sum += d;\n    alt = !alt;\n  }\n  return sum % 10 === 0;\n}\n\n/** Mask any 13–19 digit run that passes the Luhn check (a real card number),\n *  leaving other long digit strings (order ids, timestamps) intact. */\nexport function scrubCreditCards(text: string): string {\n  return text.replace(CC_RE, (m) => {\n    const digits = m.replace(/\\D/g, \"\");\n    return digits.length >= 13 && digits.length <= 19 && luhnValid(digits)\n      ? \"[REDACTED_CC]\"\n      : m;\n  });\n}\n\n/** Parse a possibly-relative URL, mutate its query, and re-serialize preserving\n *  absolute-vs-relative form. Returns the input unchanged on parse failure. */\nfunction editQuery(url: string, edit: (q: URLSearchParams) => boolean): string {\n  try {\n    const absolute = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(url);\n    const u = new URL(url, \"http://_local_\");\n    if (!edit(u.searchParams)) return url;\n    return absolute ? u.toString() : u.pathname + u.search + u.hash;\n  } catch {\n    return url;\n  }\n}\n\n/** Redact a URL before it is stored. Always masks the built-in sensitive query\n *  keys; then applies the workspace policy: strip all query params except an\n *  allowlist, custom redact patterns, and a Luhn-checked credit-card scrub. */\nexport function redactUrlForStorage(\n  url: string,\n  policy?: {\n    strip?: boolean;\n    allowed?: string[];\n    blockCC?: boolean;\n    patterns?: Array<string | RegExp>;\n  },\n): string {\n  let out = editQuery(url, (q) => {\n    const keys: string[] = [];\n    q.forEach((_v, k) => keys.push(k));\n    let changed = false;\n    for (const k of keys) {\n      if (DEFAULT_SENSITIVE_QUERY_KEYS.includes(k.toLowerCase())) {\n        q.set(k, \"[REDACTED]\");\n        changed = true;\n      }\n    }\n    return changed;\n  });\n  if (policy?.strip) {\n    const allow = new Set((policy.allowed ?? []).map((a) => a.toLowerCase()));\n    out = editQuery(out, (q) => {\n      const keys: string[] = [];\n      q.forEach((_v, k) => keys.push(k));\n      let changed = false;\n      for (const k of keys) {\n        if (!allow.has(k.toLowerCase())) {\n          q.delete(k);\n          changed = true;\n        }\n      }\n      return changed;\n    });\n  }\n  if (policy?.patterns && policy.patterns.length > 0) {\n    out = withRedactedUrl(out, policy.patterns);\n  }\n  if (policy?.blockCC) out = scrubCreditCards(out);\n  return out;\n}\n\n/**\n * Derive the dashboard app host from the ingest/API host, mirroring the mobile\n * SDKs: `https://api.replayfy.app` → `https://app.replayfy.app`. A host that does\n * not start with `api.` (self-hosted / custom) is returned unchanged.\n */\nexport function dashboardHostFromApiHost(apiHost: string): string {\n  try {\n    const u = new URL(apiHost);\n    if (u.hostname.startsWith(\"api.\")) {\n      u.hostname = \"app.\" + u.hostname.slice(4);\n    }\n    return u.origin;\n  } catch {\n    return apiHost.replace(/\\/+$/, \"\");\n  }\n}\n","import { parse } from \"error-stack-parser-es\";\nimport type {\n  ConsoleEventData,\n  ErrorEventData,\n  NavigationEventData,\n  NetworkEventData,\n  StackFrame,\n} from \"./schema\";\nimport type { WebReplayConfig } from \"./types\";\nimport {\n  formatConsoleArg,\n  redactHeaders,\n  serializeConsoleArg,\n  toHeaderRecord,\n  redactUrlForStorage,\n} from \"./utils\";\n\ntype StopHandle = () => void;\n\nexport function createConsoleCapture(\n  onEvent: (data: ConsoleEventData) => void,\n): StopHandle {\n  const methods: Array<ConsoleEventData[\"level\"]> = [\n    \"log\",\n    \"info\",\n    \"warn\",\n    \"error\",\n    \"debug\",\n  ];\n  const originals = new Map<\n    ConsoleEventData[\"level\"],\n    (...args: unknown[]) => void\n  >();\n\n  // Flood guard: a console.log in a tight loop shouldn't drown the session in\n  // events. Cap captured messages per rolling window (the real console is still\n  // called, so devtools output is unchanged) — parity with the reference tracker.\n  const THROTTLE_LIMIT = 30;\n  const THROTTLE_WINDOW_MS = 1000;\n  let windowStart = Date.now();\n  let windowCount = 0;\n\n  for (const level of methods) {\n    originals.set(level, console[level].bind(console));\n    console[level] = (...args: unknown[]) => {\n      const now = Date.now();\n      if (now - windowStart > THROTTLE_WINDOW_MS) {\n        windowStart = now;\n        windowCount = 0;\n      }\n      windowCount += 1;\n      if (windowCount <= THROTTLE_LIMIT) {\n        const serialized = args.map((arg) => serializeConsoleArg(arg));\n        onEvent({\n          level,\n          // formatConsoleArg renders each arg as JSON when it's an object —\n          // gives us a real `{\"foo\":1,\"bar\":2}` in `message` instead of the\n          // `[object Object]` you get from Array.prototype.join.\n          message: serialized.map(formatConsoleArg).join(\" \"),\n          args: serialized,\n          stack: level === \"error\" ? new Error().stack : undefined,\n        });\n      }\n      originals.get(level)?.(...args);\n    };\n  }\n\n  return () => {\n    for (const level of methods) {\n      const original = originals.get(level);\n      if (original) {\n        console[level] = original;\n      }\n    }\n  };\n}\n\n/**\n * Parse an Error's stack into normalised frames. Wrapped because\n * `parse()` throws on malformed / empty stacks (cross-origin \"Script\n * error.\", synthetic errors) — we degrade to no frames rather than\n * losing the whole error.\n */\nfunction framesFromError(error: Error): StackFrame[] {\n  try {\n    return parse(error).map((f) => ({\n      functionName: f.functionName,\n      fileName: f.fileName,\n      lineNumber: f.lineNumber,\n      columnNumber: f.columnNumber,\n    }));\n  } catch {\n    return [];\n  }\n}\n\n/**\n * Split a stackless error string like \"TypeError: x is undefined\" into\n * {name, message}. Only treats the prefix as an error name when it\n * genuinely looks like one (single identifier, or *Error suffix) — so a\n * message that merely contains a URL (\"failed: https://…\") isn't\n * mis-split. This is deliberately stricter than the reference, which\n * naively splits on the first \":\" and mangles such messages.\n */\nfunction splitErrorName(raw: string): { name: string; message: string } {\n  const idx = raw.indexOf(\":\");\n  if (idx > 0) {\n    const prefix = raw.slice(0, idx).trim();\n    const looksLikeName =\n      /Error$/.test(prefix) ||\n      (/^[A-Za-z_$][\\w$]*$/.test(prefix) && !prefix.includes(\"/\"));\n    if (looksLikeName) {\n      return { name: prefix, message: raw.slice(idx + 1).trim() };\n    }\n  }\n  return { name: \"Error\", message: raw };\n}\n\n/**\n * Build an ErrorEventData from an arbitrary caught/thrown value. Shared by the\n * public captureException so a developer-reported error is byte-identical to an\n * uncaught one (same name/message/stack/frames parsing) apart from `handled`.\n */\nexport function errorDataFromValue(\n  value: unknown,\n  handled: boolean,\n  metadata?: Record<string, unknown>,\n): ErrorEventData {\n  const meta = metadata ? { metadata } : {};\n  if (value instanceof Error) {\n    return {\n      kind: \"error\",\n      name: value.name || \"Error\",\n      message: value.message || String(value),\n      stack: value.stack,\n      frames: framesFromError(value),\n      handled,\n      ...meta,\n    };\n  }\n  // Non-Error thrown value: serialise best-effort; there is no stack to parse.\n  let raw: string;\n  try {\n    raw = typeof value === \"string\" ? value : JSON.stringify(value);\n  } catch {\n    raw = String(value);\n  }\n  const { name, message } = splitErrorName(raw || \"\");\n  return {\n    kind: \"error\",\n    name: name || \"Error\",\n    message: message || raw || String(value),\n    frames: [],\n    handled,\n    ...meta,\n  };\n}\n\nexport function createErrorCapture(\n  onEvent: (data: ErrorEventData) => void,\n): StopHandle {\n  const onError = (event: ErrorEvent) => {\n    // Preferred path: a real Error object with a parseable stack.\n    if (event.error instanceof Error) {\n      const err = event.error;\n      onEvent({\n        kind: \"error\",\n        name: err.name || \"Error\",\n        message: err.message || event.message,\n        stack: err.stack,\n        frames: framesFromError(err),\n      });\n      return;\n    }\n    // Fallback: no Error object (thrown non-Error, or a cross-origin\n    // \"Script error.\" with details stripped). Synthesize one frame from\n    // the event's filename/line/column so the throw site is still known.\n    const { name, message } = splitErrorName(event.message || \"\");\n    const frames: StackFrame[] = [];\n    if (event.filename || event.lineno || event.colno) {\n      frames.push({\n        fileName: event.filename || undefined,\n        lineNumber: event.lineno || undefined,\n        columnNumber: event.colno || undefined,\n      });\n    }\n    onEvent({ kind: \"error\", name, message, frames });\n  };\n\n  const onRejection = (event: PromiseRejectionEvent) => {\n    const reason = event.reason;\n    if (reason instanceof Error) {\n      onEvent({\n        kind: \"unhandledrejection\",\n        name: reason.name || \"UnhandledRejection\",\n        message: reason.message,\n        stack: reason.stack,\n        frames: framesFromError(reason),\n      });\n      return;\n    }\n    // Non-Error rejection value — serialise it best-effort for the\n    // message; there is no stack to parse.\n    let message: string;\n    try {\n      message = typeof reason === \"string\" ? reason : JSON.stringify(reason);\n    } catch {\n      message = String(reason);\n    }\n    onEvent({\n      kind: \"unhandledrejection\",\n      name: \"UnhandledRejection\",\n      message: message || String(reason),\n      frames: [],\n    });\n  };\n\n  // Attach to the top window AND every SAME-ORIGIN iframe, so uncaught errors /\n  // rejections thrown inside embedded editors, widget hosts, and micro-frontends\n  // are captured too (they'd otherwise be invisible). Cross-origin frames are\n  // inaccessible and silently skipped.\n  const attached = new Set<Window>();\n  const attach = (w: Window | null) => {\n    if (!w || attached.has(w)) return;\n    try {\n      w.addEventListener(\"error\", onError);\n      w.addEventListener(\"unhandledrejection\", onRejection);\n      attached.add(w);\n    } catch {\n      /* cross-origin window — inaccessible */\n    }\n  };\n  const attachFrame = (frame: HTMLIFrameElement) => {\n    try {\n      // Reading contentWindow.document throws for cross-origin — the same-origin gate.\n      if (frame.contentWindow?.document) attach(frame.contentWindow);\n    } catch {\n      /* cross-origin — skip */\n    }\n  };\n  attach(window);\n  const frames = document.getElementsByTagName(\"iframe\");\n  for (let i = 0; i < frames.length; i += 1) attachFrame(frames[i]);\n\n  // Catch iframes added later; wait for load so contentWindow is ready.\n  let mo: MutationObserver | undefined;\n  try {\n    mo = new MutationObserver((records) => {\n      for (const rec of records) {\n        rec.addedNodes.forEach((n) => {\n          if (n instanceof HTMLIFrameElement) {\n            attachFrame(n);\n            n.addEventListener(\"load\", () => attachFrame(n), { once: true });\n          } else if (n instanceof Element) {\n            n.querySelectorAll(\"iframe\").forEach((f) =>\n              attachFrame(f as HTMLIFrameElement),\n            );\n          }\n        });\n      }\n    });\n    mo.observe(document.documentElement, { childList: true, subtree: true });\n  } catch {\n    /* document not ready */\n  }\n\n  return () => {\n    mo?.disconnect();\n    for (const w of attached) {\n      try {\n        w.removeEventListener(\"error\", onError);\n        w.removeEventListener(\"unhandledrejection\", onRejection);\n      } catch {\n        /* window gone */\n      }\n    }\n    attached.clear();\n  };\n}\n\nexport function createNavigationCapture(\n  onEvent: (data: NavigationEventData) => void,\n): StopHandle {\n  const originalPushState = history.pushState.bind(history);\n  const originalReplaceState = history.replaceState.bind(history);\n  let currentUrl = window.location.href;\n\n  const emit = (trigger: NavigationEventData[\"trigger\"]) => {\n    const nextUrl = window.location.href;\n    // Skip no-op emits: a pushState/replaceState that doesn't change the URL\n    // (common — routers re-push the same route) shouldn't create a screen event.\n    // 'load' always emits (it's the entry).\n    if (trigger !== \"load\" && nextUrl === currentUrl) return;\n    onEvent({\n      // Scrub credentials out of the stored URLs (tokens/reset-links routinely\n      // ride in the query string). Default key scrub — always on, no config.\n      from: redactUrlForStorage(currentUrl),\n      to: redactUrlForStorage(nextUrl),\n      trigger,\n      // Human-readable screen name so the dashboard can label screens by title,\n      // not just an opaque URL (parity with the reference tracker's page location).\n      title: document.title || undefined,\n    });\n    currentUrl = nextUrl;\n  };\n\n  history.pushState = (...args) => {\n    originalPushState(...args);\n    emit(\"pushState\");\n  };\n\n  history.replaceState = (...args) => {\n    originalReplaceState(...args);\n    emit(\"replaceState\");\n  };\n\n  const onPopState = () => emit(\"popstate\");\n  const onHashChange = () => emit(\"hashchange\");\n\n  window.addEventListener(\"popstate\", onPopState);\n  window.addEventListener(\"hashchange\", onHashChange);\n  emit(\"load\");\n\n  return () => {\n    history.pushState = originalPushState;\n    history.replaceState = originalReplaceState;\n    window.removeEventListener(\"popstate\", onPopState);\n    window.removeEventListener(\"hashchange\", onHashChange);\n  };\n}\n\nexport function createViewportCapture(onEvent: () => void): StopHandle {\n  window.addEventListener(\"resize\", onEvent);\n  return () => {\n    window.removeEventListener(\"resize\", onEvent);\n  };\n}\n\n/**\n * Rage / dead click detector.\n *\n * Rage clicks = ≥3 clicks on roughly the same coordinates within 1 s.\n *   Users do this when something they tap doesn't respond — a clear signal\n *   the page is broken or unresponsive.\n *\n * Dead clicks = a click that produced no visible mutation in the next\n *   ~500 ms. We can't introspect React renders, but we can listen for the\n *   browser's MutationObserver — if zero mutations fire, we call it dead.\n *\n * Both fire as custom rrweb events ({ kind: 'rage_click' | 'dead_click' }).\n * The persistence service increments session.rageCount / deadCount based\n * on these.\n */\ntype ClickEmit = (\n  data:\n    | { kind: \"rage_click\"; x: number; y: number; selector: string; count: number }\n    | { kind: \"dead_click\"; x: number; y: number; selector: string }\n    | {\n        kind: \"click\";\n        selector: string;\n        label: string;\n        nx: number;\n        ny: number;\n        uiId: string;\n      },\n) => void;\n\nexport function createRageDeadClickCapture(onEvent: ClickEmit): StopHandle {\n  const recent: Array<{ x: number; y: number; ts: number }> = [];\n  const PROXIMITY_PX = 24;\n  const RAGE_WINDOW_MS = 1000;\n  const DEAD_OBSERVE_MS = 500;\n\n  // ONE shared observer with a dirty-timestamp — not a fresh observer per click.\n  // A click is \"dead\" only if nothing mutated AND the URL didn't change within\n  // the window (a navigation IS a response).\n  let lastMutation = 0;\n  const observer = new MutationObserver(() => {\n    lastMutation = Date.now();\n  });\n  try {\n    observer.observe(document.documentElement, {\n      childList: true,\n      subtree: true,\n      attributes: true,\n      characterData: true,\n    });\n  } catch {\n    /* document not ready — best effort */\n  }\n\n  const onClick = (ev: MouseEvent) => {\n    const now = Date.now();\n    // Resolve the raw target to the meaningful clickable ancestor; null = the\n    // element (or an ancestor) is masked, so we emit NO identity for it.\n    const target = resolveClickable(ev.target);\n    if (!target) return;\n    const selector = cssPath(target);\n\n    // Semantic click event — for heatmaps / click funnels. Emitted ONLY for a\n    // genuinely interactive target, so a bare container / body / padding click\n    // (whose label is empty) never lands in the funnel with the CSS selector\n    // standing in for \"Text\". Rage/dead detection below still runs on ANY click\n    // — frustration on a dead zone is itself a real signal.\n    // Mirrors our mobile TapEventData (selector + label + content-normalized\n    // coords 0..1e4 + a stable uiId bucket).\n    if (isInteractiveEl(target)) {\n      const label = targetLabel(target);\n      const nx = normCoord(\n        ev.pageX,\n        document.documentElement.scrollWidth || window.innerWidth,\n      );\n      const ny = normCoord(\n        ev.pageY,\n        document.documentElement.scrollHeight || window.innerHeight,\n      );\n      onEvent({\n        kind: \"click\",\n        selector,\n        label,\n        nx,\n        ny,\n        uiId: hashId(`${location.pathname}#${selector}#${label}`),\n      });\n    }\n\n    // Rage: ≥3 clicks within PROXIMITY_PX in RAGE_WINDOW_MS.\n    while (recent.length > 0 && now - recent[0].ts > RAGE_WINDOW_MS)\n      recent.shift();\n    recent.push({ x: ev.clientX, y: ev.clientY, ts: now });\n    const close = recent.filter(\n      (r) =>\n        Math.abs(r.x - ev.clientX) < PROXIMITY_PX &&\n        Math.abs(r.y - ev.clientY) < PROXIMITY_PX,\n    );\n    if (close.length >= 3) {\n      onEvent({\n        kind: \"rage_click\",\n        x: ev.clientX,\n        y: ev.clientY,\n        selector,\n        count: close.length,\n      });\n      recent.length = 0;\n    }\n\n    // Dead-click: no mutation AND no navigation within the window.\n    const hrefBefore = location.href;\n    window.setTimeout(() => {\n      const mutated = lastMutation >= now;\n      const navigated = location.href !== hrefBefore;\n      if (!mutated && !navigated) {\n        onEvent({ kind: \"dead_click\", x: ev.clientX, y: ev.clientY, selector });\n      }\n    }, DEAD_OBSERVE_MS);\n  };\n\n  document.addEventListener(\"click\", onClick, true);\n  return () => {\n    document.removeEventListener(\"click\", onClick, true);\n    observer.disconnect();\n  };\n}\n\n/**\n * Web performance capture.\n *\n * We delegate the Core Web Vitals math to Google's `web-vitals`\n * library (the same code Lighthouse + PageSpeed Insights use), so the\n * numbers we report are canonical:\n *\n *   • LCP   (Largest Contentful Paint, ms)   — `onLCP`\n *   • CLS   (Cumulative Layout Shift, score) — `onCLS`, with the\n *            official session-window aggregation (1s gap / 5s cap)\n *            instead of the monotonic sum we used to do\n *   • INP   (Interaction to Next Paint, ms)  — `onINP`. Replaces FID\n *            (Google deprecated FID in March 2024; CrUX no longer\n *            reports it)\n *   • FCP   (First Contentful Paint, ms)     — `onFCP`\n *   • TTFB  (Time to First Byte, ms)         — `onTTFB`\n *\n * We still own:\n *   • Long Animation Frames (LoAF) — richer than the old Long Tasks\n *     API: carries blocking time + attribution to the specific script\n *     that caused the jank. Falls back to Long Tasks where LoAF is\n *     unsupported (Firefox/Safari).\n *   • Page-load timings — navigation milestones (TTFB, DOM interactive,\n *     DCL, load, first paint / FCP) from the Navigation Timing API.\n *   • Resource timings — per-asset load breakdown (DNS/TCP/TTFB/download)\n *     from the Resource Timing API.\n *   • Memory snapshots — periodic `performance.memory` poll\n *\n * `reportAllChanges: true` means we get every high-water-mark update\n * as the user interacts, not just the final value on pagehide. Our\n * persistence path takes the max across batches, which is exactly\n * the right merge for LCP/INP/CLS (they only grow). Web-vitals also\n * handles bfcache restoration so a back/forward navigation resets\n * the metric cleanly.\n */\ntype PerfMetric =\n  | \"lcp\"\n  | \"cls\"\n  | \"fid\"\n  | \"inp\"\n  | \"fcp\"\n  | \"ttfb\"\n  | \"long_task\"\n  | \"long_animation_frame\"\n  | \"page_load\"\n  | \"resource\"\n  | \"memory\";\n\ntype PerfEmit = (data: {\n  kind: \"perf\";\n  metric: PerfMetric;\n  value: number;\n  /** Unit hint for the UI. e.g. \"ms\", \"bytes\", \"score\". */\n  unit?: \"ms\" | \"bytes\" | \"score\";\n  /** web.dev rating bucket — surfaced unchanged so the dashboard\n   *  doesn't have to re-derive it. Only present for Core Vitals. */\n  rating?: \"good\" | \"needs-improvement\" | \"poor\";\n  /** Absolute timestamp in ms — useful for memory series rendering. */\n  ts?: number;\n  /** Structured payload for multi-field metrics (LoAF script\n   *  attribution, page-load milestones, per-resource timing). */\n  detail?: Record<string, number | string | undefined>;\n}) => void;\n\n/** Options for the performance capture — the ingest host (so we don't\n *  record our own batch calls as resources) and the resource-timing\n *  knobs from config. */\nexport interface PerfCaptureOptions {\n  apiHost?: string;\n  captureResourceTimings?: boolean;\n  resourceMinDurationMs?: number;\n}\n\n/** One script's attribution inside a Long Animation Frame entry. The\n *  DOM lib in our TS version predates LoAF, so we type it ourselves. */\ninterface LoAFScript {\n  name?: string;\n  duration?: number;\n  invoker?: string;\n  invokerType?: string;\n  sourceURL?: string;\n  sourceFunctionName?: string;\n}\ninterface LoAFEntry extends PerformanceEntry {\n  duration: number;\n  blockingDuration?: number;\n  scripts?: LoAFScript[];\n}\n\n// Lazy-require web-vitals so SSR / non-browser environments that\n// happen to import this module don't crash at module-eval time.\n// We re-import inside the function body when window exists.\nexport function createPerformanceCapture(\n  onEvent: PerfEmit,\n  options: PerfCaptureOptions = {},\n): StopHandle {\n  if (typeof window === \"undefined\") return () => {};\n  const observers: PerformanceObserver[] = [];\n  const timers: number[] = [];\n  const supportsEntry = (t: string) =>\n    typeof PerformanceObserver !== \"undefined\" &&\n    Array.isArray(PerformanceObserver.supportedEntryTypes) &&\n    PerformanceObserver.supportedEntryTypes.includes(t);\n\n  // Web-vitals subscribes to the underlying PerformanceObserver entries\n  // for us and handles all the canonical-aggregation logic. Each `onX`\n  // callback fires with `{ name, value, delta, rating, ... }`. We\n  // forward each one through our `perf` event channel.\n  //\n  // `reportAllChanges` is set so we report incremental updates (each\n  // new max) rather than waiting for pagehide. That gives the\n  // dashboard a near-live picture if the user is sitting on a session.\n  void import(\"web-vitals\").then(({ onLCP, onCLS, onINP, onFCP, onTTFB }) => {\n    onLCP(\n      (m) =>\n        onEvent({\n          kind: \"perf\",\n          metric: \"lcp\",\n          value: Math.round(m.value),\n          unit: \"ms\",\n          rating: m.rating,\n        }),\n      { reportAllChanges: true },\n    );\n    onCLS(\n      (m) =>\n        onEvent({\n          kind: \"perf\",\n          metric: \"cls\",\n          // CLS is a small fractional score (typically 0.0–1.0). We\n          // round to 4dp here; the backend stores it scaled ×1000 to\n          // fit in an indexable Int. The session-window logic is done\n          // by web-vitals internally; we just forward the result.\n          value: Number(m.value.toFixed(4)),\n          unit: \"score\",\n          rating: m.rating,\n        }),\n      { reportAllChanges: true },\n    );\n    onINP(\n      (m) =>\n        onEvent({\n          kind: \"perf\",\n          metric: \"inp\",\n          value: Math.round(m.value),\n          unit: \"ms\",\n          rating: m.rating,\n        }),\n      { reportAllChanges: true },\n    );\n    onFCP((m) =>\n      onEvent({\n        kind: \"perf\",\n        metric: \"fcp\",\n        value: Math.round(m.value),\n        unit: \"ms\",\n        rating: m.rating,\n      }),\n    );\n    onTTFB((m) =>\n      onEvent({\n        kind: \"perf\",\n        metric: \"ttfb\",\n        value: Math.round(m.value),\n        unit: \"ms\",\n        rating: m.rating,\n      }),\n    );\n  }).catch(() => {\n    /* web-vitals not available — fail silently rather than break the SDK */\n  });\n\n  /**\n   * Defensive observer creator. Browsers throw if a type is unknown\n   * (Firefox lacks `longtask` for example), so we wrap it.\n   */\n  const safeObserve = (\n    type: string,\n    cb: (list: PerformanceObserverEntryList) => void,\n    options: PerformanceObserverInit = { type, buffered: true } as PerformanceObserverInit,\n  ) => {\n    try {\n      const obs = new PerformanceObserver((list) => cb(list));\n      obs.observe(options);\n      observers.push(obs);\n    } catch {\n      /* unsupported entry type — silently skip */\n    }\n  };\n\n  // Jank — prefer the modern Long Animation Frames API, which attributes\n  // the slow frame to the specific script (source URL + function) that\n  // blocked the main thread. That attribution is what lets the AI say\n  // \"checkout froze because analytics.js ran 240ms\", not just \"a frame\n  // was slow\". Fall back to the older Long Tasks API where LoAF is\n  // unsupported (Firefox/Safari) — coarser, no attribution.\n  if (supportsEntry(\"long-animation-frame\")) {\n    safeObserve(\"long-animation-frame\", (list) => {\n      for (const e of list.getEntries()) {\n        const entry = e as LoAFEntry;\n        // Attribute to the single longest script in the frame — that's\n        // the culprit; shipping the whole scripts[] array would bloat\n        // every jank event for little extra signal.\n        let top: LoAFScript | undefined;\n        for (const s of entry.scripts ?? []) {\n          if (!top || (s.duration ?? 0) > (top.duration ?? 0)) top = s;\n        }\n        onEvent({\n          kind: \"perf\",\n          metric: \"long_animation_frame\",\n          value: Math.round(entry.duration),\n          unit: \"ms\",\n          ts: Date.now(),\n          detail: {\n            blockingDuration: Math.round(entry.blockingDuration ?? 0),\n            scriptDuration:\n              top && typeof top.duration === \"number\"\n                ? Math.round(top.duration)\n                : undefined,\n            scriptSource: top?.sourceURL || undefined,\n            scriptFunction: top?.sourceFunctionName || undefined,\n            scriptInvoker: top?.invoker || undefined,\n          },\n        });\n      }\n    });\n  } else {\n    safeObserve(\"longtask\", (list) => {\n      for (const entry of list.getEntries()) {\n        onEvent({\n          kind: \"perf\",\n          metric: \"long_task\",\n          value: Math.round(entry.duration),\n          unit: \"ms\",\n          ts: Date.now(),\n        });\n      }\n    });\n  }\n\n  // Page-load milestones — one shot per navigation, read from the\n  // Navigation Timing API (PerformanceNavigationTiming, the non-\n  // deprecated successor to `performance.timing`). Values are ms from\n  // navigation start. Paired with the paint entries for FP/FCP.\n  let pageLoadSent = false;\n  const emitPageLoad = () => {\n    if (pageLoadSent) return;\n    const nav = performance.getEntriesByType(\"navigation\")[0] as\n      | PerformanceNavigationTiming\n      | undefined;\n    // loadEventEnd is 0 until the load event fully settles — wait for it.\n    if (!nav || nav.loadEventEnd === 0) return;\n    pageLoadSent = true;\n    const paints = performance.getEntriesByType(\"paint\");\n    const fp = paints.find((p) => p.name === \"first-paint\")?.startTime;\n    const fcp = paints.find(\n      (p) => p.name === \"first-contentful-paint\",\n    )?.startTime;\n    onEvent({\n      kind: \"perf\",\n      metric: \"page_load\",\n      value: Math.round(nav.loadEventEnd),\n      unit: \"ms\",\n      ts: Date.now(),\n      detail: {\n        ttfb: Math.round(nav.responseStart),\n        responseEnd: Math.round(nav.responseEnd),\n        domInteractive: Math.round(nav.domInteractive),\n        domContentLoaded: Math.round(nav.domContentLoadedEventEnd),\n        load: Math.round(nav.loadEventEnd),\n        firstPaint: fp !== undefined ? Math.round(fp) : undefined,\n        firstContentfulPaint:\n          fcp !== undefined ? Math.round(fcp) : undefined,\n        transferSize: nav.transferSize,\n        navigationType: nav.type,\n      },\n    });\n  };\n  if (document.readyState === \"complete\") {\n    // load already fired — loadEventEnd is set a tick later, so defer.\n    timers.push(window.setTimeout(emitPageLoad, 0));\n  } else {\n    window.addEventListener(\n      \"load\",\n      () => timers.push(window.setTimeout(emitPageLoad, 0)),\n      { once: true },\n    );\n  }\n\n  // Resource timings — per-asset load breakdown. Highest-volume perf\n  // channel, so we skip our own ingest calls and data: URIs, and honour\n  // the `resourceMinDurationMs` floor from config to trim volume.\n  const captureResources = options.captureResourceTimings !== false;\n  const minResourceMs = options.resourceMinDurationMs ?? 0;\n  let ownHost: string | undefined;\n  try {\n    ownHost = options.apiHost ? new URL(options.apiHost).host : undefined;\n  } catch {\n    ownHost = undefined;\n  }\n  if (captureResources) {\n    safeObserve(\"resource\", (list) => {\n      for (const e of list.getEntries()) {\n        const entry = e as PerformanceResourceTiming;\n        if (entry.duration < minResourceMs) continue;\n        const url = entry.name;\n        if (url.startsWith(\"data:\")) continue;\n        // Never record the SDK's own ingest/config/presence traffic. Mirrors the\n        // reference tracker's resource-timing rule (isServiceURL): skip anything\n        // whose URL starts with our configured ingest origin, so /v1/sdk/config\n        // and /v1/replay/batch never surface as page-resource perf events. The\n        // host-only `ownHost` check stays as a fallback for an apiHost that\n        // carries a path/port a bare startsWith wouldn't match.\n        if (options.apiHost && url.startsWith(options.apiHost)) continue;\n        if (ownHost && url.includes(ownHost)) continue;\n        onEvent({\n          kind: \"perf\",\n          metric: \"resource\",\n          value: Math.round(entry.duration),\n          unit: \"ms\",\n          ts: Math.round(entry.startTime + performance.timeOrigin),\n          detail: {\n            name: url.slice(0, 512),\n            initiatorType: entry.initiatorType,\n            ttfb: Math.round(\n              Math.max(0, entry.responseStart - entry.requestStart),\n            ),\n            dnsLookup: Math.round(\n              Math.max(0, entry.domainLookupEnd - entry.domainLookupStart),\n            ),\n            tcp: Math.round(\n              Math.max(0, entry.connectEnd - entry.connectStart),\n            ),\n            contentDownload: Math.round(\n              Math.max(0, entry.responseEnd - entry.responseStart),\n            ),\n            transferSize: entry.transferSize,\n            encodedBodySize: entry.encodedBodySize,\n            decodedBodySize: entry.decodedBodySize,\n            // Heuristic: served from cache when nothing came over the\n            // wire but the body decoded to something.\n            cached:\n              entry.transferSize === 0 && entry.decodedBodySize > 0 ? 1 : 0,\n          },\n        });\n      }\n    });\n  }\n\n  // Memory — Chrome/Edge only. Sampled every 10s + once at startup.\n  // The API isn't standardised so we feature-detect carefully.\n  type PerfMemoryLike = { usedJSHeapSize?: number };\n  const perfMem = (performance as Performance & { memory?: PerfMemoryLike }).memory;\n  const sampleMemory = () => {\n    const used = perfMem?.usedJSHeapSize;\n    if (typeof used === \"number\") {\n      onEvent({ kind: \"perf\", metric: \"memory\", value: used, unit: \"bytes\", ts: Date.now() });\n    }\n  };\n  if (perfMem) {\n    sampleMemory();\n    const id = window.setInterval(sampleMemory, 10_000);\n    timers.push(id);\n  }\n\n  return () => {\n    for (const obs of observers) {\n      try { obs.disconnect(); } catch { /* already disconnected */ }\n    }\n    for (const id of timers) window.clearInterval(id);\n    // web-vitals doesn't expose an unsubscribe (the observers it\n    // installs live for the page lifetime, which matches our session\n    // lifetime). No cleanup needed.\n  };\n}\n\n/** Meaningful clickable element types — mirrors the reference tracker's getTarget. */\nconst CLICKABLE_TAGS = new Set([\n  \"BUTTON\", \"A\", \"SELECT\", \"LI\", \"TR\", \"TH\", \"TD\",\n  \"INPUT\", \"TEXTAREA\", \"SUMMARY\", \"OPTION\", \"LABEL\",\n]);\n\nconst INTERACTIVE_ROLES = new Set([\n  \"button\", \"link\", \"tab\", \"menuitem\", \"menuitemcheckbox\", \"menuitemradio\",\n  \"checkbox\", \"radio\", \"option\", \"switch\",\n]);\n\n/** True when the node is a GENUINELY interactive control — a clickable tag, an\n *  ARIA interactive role, an onclick handler attr, a focusable tabindex, or a\n *  contenteditable region. Used both to climb to the meaningful click target AND\n *  to decide whether a click earns a semantic (funnel/heatmap) event: a click on\n *  a bare container / body / padding is NOT emitted, so the funnel's element\n *  \"Text\" is never a CSS selector standing in for an empty label. */\nfunction isInteractiveEl(node: Element): boolean {\n  if (CLICKABLE_TAGS.has(node.tagName)) return true;\n  const role = node.getAttribute(\"role\");\n  if (role && INTERACTIVE_ROLES.has(role)) return true;\n  if (node.hasAttribute(\"onclick\")) return true;\n  if (node.hasAttribute(\"tabindex\")) return true;\n  if ((node as HTMLElement).isContentEditable) return true;\n  return false;\n}\n\n/** rrweb-style privacy classes/attrs that mark a subtree as blocked/masked. */\nfunction isMaskedNode(node: Element): boolean {\n  const c = node.classList;\n  return (\n    (!!c && (c.contains(\"rr-block\") || c.contains(\"rr-ignore\") || c.contains(\"rr-mask\"))) ||\n    node.getAttribute(\"data-rr-block\") === \"true\" ||\n    node.getAttribute(\"data-replay-block\") === \"true\"\n  );\n}\n\n/** Walk from the raw event target up to the nearest MEANINGFUL clickable element\n *  (control, [role=button], [onclick], [tabindex], or clickable tag), climbing\n *  out of SVG internals to the owning <svg>. Returns null if the target or any\n *  ancestor on the way is masked — we then emit no identity for that click. */\nfunction resolveClickable(raw: EventTarget | null): Element | null {\n  let el: Element | null = raw instanceof Element ? raw : null;\n  if (el && el.namespaceURI === \"http://www.w3.org/2000/svg\") {\n    const owner = el.closest(\"svg\");\n    if (owner) el = owner;\n  }\n  let node: Element | null = el;\n  let depth = 0;\n  while (node && depth < 12) {\n    if (isMaskedNode(node)) return null;\n    if (isInteractiveEl(node)) return node;\n    node = node.parentElement;\n    depth += 1;\n  }\n  return el;\n}\n\n// Reject hashed / utility class tokens (e.g. \"css-1a2b3c\", \"sc-bdVaJa\") so the\n// selector prefers stable, human-authored classes.\nconst WORD_LIKE_CLASS = /^[a-zA-Z][a-zA-Z-]{2,}$/;\nconst DATA_ID_ATTRS = [\"data-testid\", \"data-test\", \"data-qa\", \"data-cy\"];\n\nfunction cssEscape(s: string): string {\n  try {\n    const g = window as unknown as { CSS?: { escape?: (v: string) => string } };\n    if (g.CSS?.escape) return g.CSS.escape(s);\n  } catch {\n    /* fall through */\n  }\n  return s.replace(/([^a-zA-Z0-9_-])/g, \"\\\\$1\");\n}\n\n/** A reasonably-unique, stable CSS path: id → data-* test id → word-like class →\n *  tag:nth-of-type, up to a few ancestors. Far more stable than tag + first-two\n *  classes (parity with the reference tracker's getCSSPath). */\nfunction cssPath(el: Element | null): string {\n  if (!el) return \"\";\n  const segs: string[] = [];\n  let node: Element | null = el;\n  let depth = 0;\n  while (node && node.nodeType === 1 && depth < 5) {\n    if (node.id) {\n      segs.unshift(`#${cssEscape(node.id)}`);\n      break; // an id is unique enough — stop climbing\n    }\n    let seg = node.tagName.toLowerCase();\n    const dataAttr = DATA_ID_ATTRS.find((a) => node!.hasAttribute(a));\n    if (dataAttr) {\n      seg += `[${dataAttr}=\"${cssEscape(node.getAttribute(dataAttr) ?? \"\")}\"]`;\n      segs.unshift(seg);\n      break;\n    }\n    const className =\n      typeof (node as HTMLElement).className === \"string\"\n        ? (node as HTMLElement).className\n        : \"\";\n    const cls = className.split(/\\s+/).find((c) => WORD_LIKE_CLASS.test(c));\n    if (cls) {\n      seg += `.${cssEscape(cls)}`;\n    } else if (node.parentElement) {\n      const siblings = Array.prototype.filter.call(\n        node.parentElement.children,\n        (c: Element) => c.tagName === node!.tagName,\n      ) as Element[];\n      if (siblings.length > 1) {\n        seg += `:nth-of-type(${siblings.indexOf(node) + 1})`;\n      }\n    }\n    segs.unshift(seg);\n    node = node.parentElement;\n    depth += 1;\n  }\n  return segs.join(\" > \").slice(0, 200);\n}\n\nfunction normSpaces(s: string): string {\n  return s.replace(/\\s+/g, \" \").trim();\n}\n\n/** A human label for a clicked element — attribute label, input placeholder, or\n *  short trimmed text. NEVER an input's actual value (that's user data), except a\n *  submit button's caption. Capped at 100 chars. */\nfunction targetLabel(el: Element | null): string {\n  if (!el) return \"\";\n  const cap = (s: string) => normSpaces(s).slice(0, 100);\n\n  // 1. Author-intent labels on the element itself. `name` is deliberately NOT\n  //    here — it is rarely human-facing and used to win over visible text, so a\n  //    <button name=\"submit\">Start free</button> was mislabelled \"submit\".\n  const direct =\n    el.getAttribute(\"aria-label\") ||\n    el.getAttribute(\"data-label\") ||\n    el.getAttribute(\"title\");\n  if (direct && normSpaces(direct)) return cap(direct);\n\n  // 2. aria-labelledby → the referenced element(s') text.\n  const labelledby = el.getAttribute(\"aria-labelledby\");\n  if (labelledby) {\n    const doc = el.ownerDocument;\n    const txt = labelledby\n      .split(/\\s+/)\n      .map((id) => (doc ? doc.getElementById(id)?.textContent ?? \"\" : \"\"))\n      .join(\" \");\n    if (normSpaces(txt)) return cap(txt);\n  }\n\n  const tag = el.tagName;\n\n  // 3. Form controls — resolve their human label, NEVER the typed value.\n  if (tag === \"INPUT\" || tag === \"TEXTAREA\" || tag === \"SELECT\") {\n    const input = el as HTMLInputElement;\n    const doc = el.ownerDocument;\n    const forLabel =\n      input.id && doc\n        ? doc.querySelector(`label[for=\"${cssEscape(input.id)}\"]`)\n        : null;\n    const wrap = el.closest(\"label\");\n    const lbl = (forLabel || wrap)?.textContent;\n    if (lbl && normSpaces(lbl)) return cap(lbl);\n    const ph = el.getAttribute(\"placeholder\");\n    if (ph && normSpaces(ph)) return cap(ph);\n    if (tag === \"INPUT\") {\n      const type = (input.type || \"\").toLowerCase();\n      if (type === \"submit\" || type === \"button\" || type === \"reset\")\n        return cap(input.value || type);\n      if (type === \"image\")\n        return cap(el.getAttribute(\"alt\") || input.value || \"image\");\n    }\n    if (tag === \"SELECT\") {\n      const opt = (el as unknown as HTMLSelectElement).selectedOptions?.[0]\n        ?.textContent;\n      if (opt && normSpaces(opt)) return cap(opt);\n    }\n    // Never leak the typed value; fall back to the field name or control kind.\n    return cap(el.getAttribute(\"name\") || tag.toLowerCase());\n  }\n\n  // 4. Visible text — the primary path for buttons and links.\n  const text = (el as HTMLElement).innerText || el.textContent || \"\";\n  if (normSpaces(text)) return cap(text);\n\n  // 5. Icon / image controls with no text: a descendant image's alt, a\n  //    labelled descendant, or the element's own alt.\n  const imgAlt = el.querySelector(\"img[alt]\")?.getAttribute(\"alt\");\n  if (imgAlt && normSpaces(imgAlt)) return cap(imgAlt);\n  const descLabelled =\n    el.querySelector(\"[aria-label]\")?.getAttribute(\"aria-label\") ||\n    el.querySelector(\"[title]\")?.getAttribute(\"title\") ||\n    el.querySelector(\"[alt]\")?.getAttribute(\"alt\");\n  if (descLabelled && normSpaces(descLabelled)) return cap(descLabelled);\n  const ownAlt = el.getAttribute(\"alt\");\n  if (ownAlt && normSpaces(ownAlt)) return cap(ownAlt);\n\n  // 6. Final sane fallback — a role/tag word, NEVER the CSS selector and NEVER\n  //    empty (the empty return is exactly what made the dashboard fall back to\n  //    the selector as the element \"Text\").\n  const role = el.getAttribute(\"role\");\n  if (role) return role;\n  const t = tag.toLowerCase();\n  return t === \"a\" ? \"link\" : t;\n}\n\n/** Content-normalized coordinate in 0..10000 (like the reference tracker), so a\n *  click maps to the same heatmap bucket across viewport sizes. */\nfunction normCoord(page: number, extent: number): number {\n  if (!extent || extent <= 0) return 0;\n  return Math.max(0, Math.min(10000, Math.round((page / extent) * 10000)));\n}\n\n/** djb2 hash → short base36 id. Buckets clicks on the same logical target across\n *  sessions (route # selector # label) for heatmaps/funnels. */\nfunction hashId(s: string): string {\n  let h = 5381;\n  for (let i = 0; i < s.length; i += 1) h = ((h << 5) + h) ^ s.charCodeAt(i);\n  return (h >>> 0).toString(36);\n}\n\n/**\n * Snapshot the browser's idea of network quality right now. Falls back to\n * undefined on Safari/Firefox where Network Information API isn't exposed —\n * we just store whatever Chrome/Edge give us. Cheap (synchronous lookup).\n */\nfunction snapshotConnection(): { rtt?: number; effectiveType?: string } {\n  type ConnLike = { rtt?: number; effectiveType?: string };\n  const c = (navigator as Navigator & { connection?: ConnLike }).connection;\n  if (!c) return {};\n  return { rtt: c.rtt, effectiveType: c.effectiveType };\n}\n\nexport function createNetworkCapture(\n  config: WebReplayConfig,\n  onEvent: (data: NetworkEventData) => void,\n  /** Live URL-redaction policy (strip/allowlist/blockCC) — read fresh per\n   *  request so a remote-config update applies WITHOUT re-installing the capture\n   *  (the network patches are installed once). Cheap: a closure read. */\n  getUrlPolicy?: () => {\n    strip?: boolean;\n    allowed?: string[];\n    blockCC?: boolean;\n  },\n): StopHandle {\n  const originalFetch = (config.fetchImpl ?? window.fetch).bind(window);\n  const originalXhrOpen = XMLHttpRequest.prototype.open;\n  const originalXhrSend = XMLHttpRequest.prototype.send;\n  const originalSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;\n\n  const MAX_BODY = config.maxBodyBytes ?? 8 * 1024;\n  // The full URL-redaction policy for THIS request: always-on default key scrub\n  // (inside redactUrlForStorage) + host redactUrls + the live remote policy.\n  const urlPolicy = () => ({\n    patterns: config.redactUrls,\n    ...(getUrlPolicy?.() ?? {}),\n  });\n  // Apply the host body sanitizer, if any. null → drop the body.\n  const redactBody = (\n    body: string | undefined,\n    direction: \"request\" | \"response\",\n    url: string,\n  ): string | undefined => {\n    if (body === undefined || !config.sanitizeBody) return body;\n    try {\n      const out = config.sanitizeBody({ url, direction, body });\n      return out === null ? undefined : (out ?? body);\n    } catch {\n      return body;\n    }\n  };\n\n  // Never record the SDK's OWN ingest/config/presence traffic. Matches the\n  // batch endpoint (/v1/replay*) and anything on the configured ingest host\n  // (/v1/sdk/config, /v1/mobile/*, presence). Recording our own /v1/sdk/config\n  // request would attribute the SDK's request latency to the host page — the\n  // client's site looks like it made a slow API call it never made, corrupting\n  // the storyline. Used by the fetch, XHR and sendBeacon capture paths below.\n  const isOwnIngest = (u: string) =>\n    u.indexOf(\"/v1/replay\") !== -1 ||\n    (!!config.apiHost && u.indexOf(config.apiHost) === 0);\n\n  window.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {\n    // Skip our own ingest/config request entirely (no capture, no body clone) —\n    // just pass through to the real fetch.\n    const ownUrl = input instanceof Request ? input.url : String(input);\n    if (isOwnIngest(ownUrl)) return originalFetch(input, init);\n    const startedAt = Date.now();\n    const request = input instanceof Request ? input : new Request(input, init);\n    const requestId = globalThis.crypto.randomUUID();\n\n    // Best-effort request body capture — string/JSON only, capped.\n    let requestBody: string | undefined;\n    try {\n      if (typeof init?.body === \"string\")\n        requestBody = String(init.body).slice(0, MAX_BODY);\n      else if (init?.body instanceof URLSearchParams)\n        requestBody = init.body.toString().slice(0, MAX_BODY);\n    } catch {\n      /* ignore */\n    }\n\n    try {\n      const response = await originalFetch(input, init);\n      // Clone the response so we can read the body without breaking the caller.\n      let responseBody: string | undefined;\n      try {\n        const ct = response.headers.get(\"content-type\") ?? \"\";\n        if (/json|text|xml|javascript|html/i.test(ct)) {\n          const clone = response.clone();\n          const text = await clone.text();\n          responseBody = text.slice(0, MAX_BODY);\n        }\n      } catch {\n        /* response body unreadable */\n      }\n\n      const conn = snapshotConnection();\n      onEvent({\n        requestId,\n        transport: \"fetch\",\n        method: request.method,\n        url: redactUrlForStorage(request.url, urlPolicy()),\n        startedAt,\n        endedAt: Date.now(),\n        durationMs: Date.now() - startedAt,\n        statusCode: response.status,\n        ok: response.ok,\n        requestHeaders: config.captureHeaders\n          ? redactHeaders(\n              toHeaderRecord(request.headers),\n              config.redactHeaderNames,\n            )\n          : undefined,\n        responseHeaders: config.captureHeaders\n          ? redactHeaders(\n              toHeaderRecord(response.headers),\n              config.redactHeaderNames,\n            )\n          : undefined,\n        requestBody: redactBody(requestBody, \"request\", request.url),\n        responseBody: redactBody(responseBody, \"response\", request.url),\n        connectionRtt: conn.rtt,\n        connectionEffectiveType: conn.effectiveType,\n      });\n      return response;\n    } catch (error) {\n      const conn = snapshotConnection();\n      onEvent({\n        requestId,\n        transport: \"fetch\",\n        method: request.method,\n        url: redactUrlForStorage(request.url, urlPolicy()),\n        startedAt,\n        endedAt: Date.now(),\n        durationMs: Date.now() - startedAt,\n        error: error instanceof Error ? error.message : String(error),\n        connectionRtt: conn.rtt,\n        connectionEffectiveType: conn.effectiveType,\n      });\n      throw error;\n    }\n  };\n\n  XMLHttpRequest.prototype.open = function open(\n    method: string,\n    url: string | URL,\n    ...rest: unknown[]\n  ) {\n    Reflect.set(this, \"__replay_request_meta__\", {\n      requestId: globalThis.crypto.randomUUID(),\n      method,\n      url: String(url),\n      startedAt: 0,\n      headers: {} as Record<string, string>,\n    });\n    const [asyncFlag, username, password] = rest as [\n      boolean?,\n      string?,\n      string?,\n    ];\n    if (typeof asyncFlag === \"boolean\") {\n      return originalXhrOpen.call(\n        this,\n        method,\n        String(url),\n        asyncFlag,\n        username,\n        password,\n      );\n    }\n\n    return originalXhrOpen.call(this, method, String(url), true);\n  };\n\n  XMLHttpRequest.prototype.setRequestHeader = function setRequestHeader(\n    name: string,\n    value: string,\n  ) {\n    const meta = Reflect.get(this, \"__replay_request_meta__\") as\n      | { headers?: Record<string, string> }\n      | undefined;\n    if (meta?.headers) {\n      meta.headers[name] = value;\n    }\n    return originalSetRequestHeader.call(this, name, value);\n  };\n\n  XMLHttpRequest.prototype.send = function send(\n    ...args: Parameters<XMLHttpRequest[\"send\"]>\n  ) {\n    const meta = Reflect.get(this, \"__replay_request_meta__\") as\n      | {\n          requestId: string;\n          method: string;\n          url: string;\n          startedAt: number;\n          headers: Record<string, string>;\n        }\n      | undefined;\n\n    if (meta && !isOwnIngest(meta.url)) {\n      meta.startedAt = Date.now();\n      const finalize = () => {\n        const conn = snapshotConnection();\n        // Best-effort response body — only for text-ish content types.\n        let responseBody: string | undefined;\n        try {\n          const ct = this.getResponseHeader(\"content-type\") ?? \"\";\n          if (\n            /json|text|xml|javascript|html/i.test(ct) &&\n            typeof this.responseText === \"string\"\n          ) {\n            responseBody = this.responseText.slice(0, MAX_BODY);\n          }\n        } catch {\n          /* unreadable */\n        }\n        // Parse response headers from getAllResponseHeaders() — comes back as one\n        // big newline-separated string. Cheap to parse.\n        const responseHeaders: Record<string, string> = {};\n        if (config.captureHeaders) {\n          try {\n            for (const line of (this.getAllResponseHeaders() || \"\").split(\n              /\\r?\\n/,\n            )) {\n              const idx = line.indexOf(\":\");\n              if (idx > 0)\n                responseHeaders[line.slice(0, idx).trim().toLowerCase()] = line\n                  .slice(idx + 1)\n                  .trim();\n            }\n          } catch {\n            /* ignore */\n          }\n        }\n        onEvent({\n          requestId: meta.requestId,\n          transport: \"xhr\",\n          method: meta.method,\n          url: redactUrlForStorage(meta.url, urlPolicy()),\n          startedAt: meta.startedAt,\n          endedAt: Date.now(),\n          durationMs: Date.now() - meta.startedAt,\n          statusCode: this.status,\n          ok: this.status >= 200 && this.status < 400,\n          requestHeaders: config.captureHeaders\n            ? redactHeaders(meta.headers, config.redactHeaderNames)\n            : undefined,\n          responseHeaders: config.captureHeaders\n            ? redactHeaders(responseHeaders, config.redactHeaderNames)\n            : undefined,\n          responseBody,\n          connectionRtt: conn.rtt,\n          connectionEffectiveType: conn.effectiveType,\n        });\n      };\n\n      this.addEventListener(\"loadend\", finalize, { once: true });\n      this.addEventListener(\n        \"error\",\n        () => {\n          const conn = snapshotConnection();\n          onEvent({\n            requestId: meta.requestId,\n            transport: \"xhr\",\n            method: meta.method,\n            url: redactUrlForStorage(meta.url, urlPolicy()),\n            startedAt: meta.startedAt,\n            endedAt: Date.now(),\n            durationMs: Date.now() - meta.startedAt,\n            error: \"XMLHttpRequest failed\",\n            connectionRtt: conn.rtt,\n            connectionEffectiveType: conn.effectiveType,\n          });\n        },\n        { once: true },\n      );\n    }\n\n    return originalXhrSend.apply(this, args);\n  };\n\n  // navigator.sendBeacon capture (analytics pings, unload telemetry) — the\n  // reference tracker patches it too. Skip OUR OWN ingest beacons (the unload\n  // path) so we never record ourselves.\n  const originalSendBeacon =\n    typeof navigator !== \"undefined\" && navigator.sendBeacon\n      ? navigator.sendBeacon.bind(navigator)\n      : undefined;\n  if (originalSendBeacon) {\n    navigator.sendBeacon = (\n      url: string | URL,\n      data?: BodyInit | null,\n    ): boolean => {\n      const urlStr = String(url);\n      const ok = originalSendBeacon(url, data ?? undefined);\n      try {\n        if (!isOwnIngest(urlStr)) {\n          let body: string | undefined;\n          if (typeof data === \"string\") body = data.slice(0, MAX_BODY);\n          else if (data instanceof URLSearchParams)\n            body = data.toString().slice(0, MAX_BODY);\n          const at = Date.now();\n          onEvent({\n            requestId: globalThis.crypto.randomUUID(),\n            transport: \"beacon\",\n            method: \"POST\",\n            url: redactUrlForStorage(urlStr, urlPolicy()),\n            statusCode: ok ? 200 : undefined,\n            startedAt: at,\n            endedAt: at,\n            durationMs: 0,\n            ok,\n            requestBody: body,\n          });\n        }\n      } catch {\n        /* never let capture break the caller's beacon */\n      }\n      return ok;\n    };\n  }\n\n  return () => {\n    window.fetch = originalFetch;\n    XMLHttpRequest.prototype.open = originalXhrOpen;\n    XMLHttpRequest.prototype.send = originalXhrSend;\n    XMLHttpRequest.prototype.setRequestHeader = originalSetRequestHeader;\n    if (originalSendBeacon) navigator.sendBeacon = originalSendBeacon;\n  };\n}\n","import type { WebReplayConfig } from \"./types\";\n\n/**\n * Shape of /v1/sdk/config. Mirrors the server's `SdkConfigResponse` —\n * keep in sync when you add fields on either side.\n */\nexport interface SdkRemoteConfig {\n  workspaceId: number;\n  /** The workspace has spent its plan's session allowance — do not record or\n   *  upload anything. A hard gate that beats every \"always record\" override. */\n  shouldNotRecord?: boolean;\n  capture: {\n    console: boolean;\n    network: boolean;\n    networkHeaders: boolean;\n    networkBodies: boolean;\n    errors: boolean;\n    headers: boolean; // legacy alias for networkHeaders\n    canvas: boolean;\n    iframe: boolean;\n    performance: boolean;\n    autoplayNext: boolean;\n    minDurationMs: number;\n    trigger: \"always\" | \"identified\" | \"sample\";\n  };\n  privacy: {\n    maskAllInputs: boolean;\n    maskSelectors: string[];\n    maskInputTypes: string[];\n    blockSelectors: string[];\n    redactUrlPatterns: string[];\n    blockCreditCardText: boolean;\n    stripQueryParams: boolean;\n    allowedQueryParams: string[];\n    allowedHosts: string[];\n  };\n  sampling: {\n    rate: number;\n    alwaysRecordErrors: boolean;\n    alwaysRecordIdentified: boolean;\n    alwaysRecordOnUrls: string[];\n  };\n  retentionDays: number;\n}\n\ninterface ApiOk<T> {\n  ok: true;\n  data: T;\n}\ninterface ApiErr {\n  ok: false;\n  error: { message: string };\n}\n\nexport async function fetchRemoteConfig(\n  config: WebReplayConfig,\n): Promise<SdkRemoteConfig | null> {\n  try {\n    const fetchImpl = config.fetchImpl ?? window.fetch.bind(window);\n    const url = new URL(\"/v1/sdk/config\", config.apiHost).toString();\n    const r = await fetchImpl(url, {\n      headers: { \"x-replay-api-key\": config.apiKey },\n    });\n    if (!r.ok) return null;\n    const body = (await r.json()) as ApiOk<SdkRemoteConfig> | ApiErr;\n    if (!body.ok) return null;\n    return body.data;\n  } catch {\n    return null;\n  }\n}\n","/**\n * A stable per-browser anonymous id. On first visit we mint a RANDOM id and\n * persist it under localStorage, so repeated visits on the same browser keep the\n * same id (and the API can collapse N sessions into 1 anonymous user). A random\n * id — not a hash of the environment — is what makes this correct at scale: a\n * pure environment fingerprint (UA/screen/tz/…) collapses every identically\n * configured browser (a whole corporate fleet, default Chrome on one laptop\n * model) into ONE anonymous user. The environment hash survives only as the\n * fallback for when localStorage is unavailable (private mode), where we have no\n * stored id to reuse and a deterministic-ish id still beats a fresh random one\n * per page load.\n *\n * When identify() is called later with a different email but the same anonymous\n * id, the server treats that as a separate EndUser — a different account on the\n * same browser is a legitimately different person.\n */\n\nconst STORAGE_KEY = \"replay:fp\";\n\nexport interface BrowserFingerprint {\n  fp: string;\n  cached: boolean;\n}\n\nexport function getBrowserFingerprint(): BrowserFingerprint {\n  let storageOk = true;\n  try {\n    const existing = localStorage.getItem(STORAGE_KEY);\n    if (existing) return { fp: existing, cached: true };\n  } catch {\n    // localStorage blocked (private mode / disabled). We can neither read a\n    // prior id nor persist a new random one, so fall back to the environment\n    // hash — deterministic across this browser's page loads without storage.\n    storageOk = false;\n  }\n  if (!storageOk) return { fp: computeFingerprint(), cached: false };\n  // First visit with working storage: mint a collision-free random id + persist.\n  const fp = randomAnonId();\n  try {\n    localStorage.setItem(STORAGE_KEY, fp);\n  } catch {\n    /* ignore — return the id for this page load anyway */\n  }\n  return { fp, cached: false };\n}\n\n/** Persist a host-supplied anonymous id (setAnonymousId) so it survives reloads\n *  and future getBrowserFingerprint() calls return it. */\nexport function setStoredFingerprint(id: string): void {\n  try {\n    localStorage.setItem(STORAGE_KEY, id);\n  } catch {\n    /* storage unavailable — the id still applies for this page load via setFingerprint */\n  }\n}\n\n/** A random, collision-free anonymous id. Falls back to the environment hash if\n *  crypto is somehow unavailable, so we always return a usable id. */\nfunction randomAnonId(): string {\n  try {\n    const bytes = new Uint8Array(16);\n    globalThis.crypto.getRandomValues(bytes);\n    return (\n      \"fp_\" + Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\")\n    );\n  } catch {\n    return computeFingerprint();\n  }\n}\n\nfunction computeFingerprint(): string {\n  const parts: string[] = [];\n  try {\n    parts.push(`ua:${navigator.userAgent}`);\n  } catch {}\n  try {\n    parts.push(`lang:${navigator.language}`);\n  } catch {}\n  try {\n    parts.push(`tz:${Intl.DateTimeFormat().resolvedOptions().timeZone}`);\n  } catch {}\n  try {\n    parts.push(`scr:${screen.width}x${screen.height}x${screen.colorDepth}`);\n  } catch {}\n  try {\n    parts.push(`dpr:${window.devicePixelRatio}`);\n  } catch {}\n  try {\n    parts.push(\n      `platform:${(navigator as unknown as { platform?: string }).platform ?? \"\"}`,\n    );\n  } catch {}\n  try {\n    parts.push(`touch:${\"ontouchstart\" in window ? \"1\" : \"0\"}`);\n  } catch {}\n  try {\n    parts.push(canvasFingerprint());\n  } catch {\n    parts.push(\"canvas:err\");\n  }\n  return \"fp_\" + djb2(parts.join(\"|\"));\n}\n\nfunction canvasFingerprint(): string {\n  const c = document.createElement(\"canvas\");\n  c.width = 200;\n  c.height = 50;\n  const ctx = c.getContext(\"2d\");\n  if (!ctx) return \"canvas:no-ctx\";\n  ctx.textBaseline = \"top\";\n  ctx.font = \"14px 'Arial'\";\n  ctx.fillStyle = \"#f60\";\n  ctx.fillRect(0, 0, 100, 25);\n  ctx.fillStyle = \"#069\";\n  ctx.fillText(\"Replay-fp,0123!\", 2, 2);\n  ctx.strokeStyle = \"rgba(102,204,0,0.7)\";\n  ctx.strokeText(\"Replay-fp,0123!\", 4, 17);\n  try {\n    return \"canvas:\" + djb2(c.toDataURL());\n  } catch {\n    return \"canvas:err\";\n  }\n}\n\nfunction djb2(s: string): string {\n  let h = 5381;\n  for (let i = 0; i < s.length; i++) h = ((h << 5) + h) ^ s.charCodeAt(i);\n  // Force unsigned and to a short hex string.\n  return (h >>> 0).toString(36);\n}\n","import {\n  type ConsoleEventData,\n  type ErrorEventData,\n  type NavigationEventData,\n  type NetworkEventData,\n  type ReplayBatchEnvelope,\n  type ReplayEvent,\n  type SessionEndEventData,\n  type SessionStartEventData,\n  type SnapshotEventData,\n  type ViewportEventData,\n} from \"./schema\";\nimport { record, addCustomEvent } from \"rrweb\";\nimport type { eventWithTime } from \"rrweb\";\nimport { createBatchSender, type IdentifyPayload } from \"./transport\";\nimport { createSessionRuntime } from \"./runtime\";\nimport {\n  createConsoleCapture,\n  createErrorCapture,\n  createNavigationCapture,\n  createNetworkCapture,\n  createPerformanceCapture,\n  createRageDeadClickCapture,\n  createViewportCapture,\n  errorDataFromValue,\n} from \"./signals\";\nimport { fetchRemoteConfig } from \"./remote-config\";\nimport { getBrowserFingerprint, setStoredFingerprint } from \"./fingerprint\";\nimport { redactUrlForStorage, dashboardHostFromApiHost } from \"./utils\";\nimport type { ReplayController, WebReplayConfig } from \"./types\";\n\ninterface CaptureSlot {\n  stop: () => void;\n}\n\nexport function initReplay(config: WebReplayConfig): ReplayController {\n  if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n    throw new Error(\"initReplay must run in a browser context\");\n  }\n\n  // Honor Do-Not-Track when the customer opts in: install NOTHING and return an\n  // inert controller, so no data is captured or sent.\n  if (config.respectDoNotTrack) {\n    const dnt =\n      navigator.doNotTrack === \"1\" ||\n      (window as unknown as { doNotTrack?: string }).doNotTrack === \"1\" ||\n      (navigator as unknown as { msDoNotTrack?: string }).msDoNotTrack === \"1\";\n    if (dnt) {\n      const noop = () => {};\n      return {\n        sessionId: \"\",\n        flush: async () => {},\n        identify: noop,\n        track: noop,\n        captureException: noop,\n        setAnonymousId: noop,\n        setMetadata: noop,\n        stop: async () => {},\n        urlForCurrentSession: () => null,\n      };\n    }\n  }\n\n  const session = createSessionRuntime(config);\n  const sendBatch = createBatchSender(config);\n  const { fp: fingerprint } = getBrowserFingerprint();\n  sendBatch.setFingerprint(fingerprint);\n  // Bind identity to THIS session: re-attach a persisted identify() only when the\n  // same session resumed (reload); a fresh/rolled-over session starts anonymous.\n  // Must run BEFORE the config/runtime identify() below so they replace/merge\n  // over the correct base rather than a stale prior-session identity.\n  sendBatch.bindSession(session.sessionId, session.resumed);\n  const captures: Record<string, CaptureSlot | null> = {\n    console: null,\n    network: null,\n    errors: null,\n    navigation: null,\n    viewport: null,\n    rrweb: null,\n  };\n  let sampled = true;\n  // The workspace has spent its plan's session allowance (remote shouldNotRecord).\n  // A HARD gate, separate from `sampled`, because the always-record overrides\n  // below flip `sampled` back on for errors/identified users — and a maxed plan\n  // must not record even those. Nothing flips this back within a page load.\n  let blocked = false;\n\n  // Visibility gate + snapshot-ordering flags. Following the reference tracker:\n  // defer the ENTIRE session start until the tab is first VISIBLE (never record a\n  // hidden / prerendered tab), and only let a batch ship once the session's DOM\n  // snapshot exists — so a batch never creates a server-side session before its\n  // full_snapshot is in it.\n  //  - `started`      : the visibility-gated start has run (tab was/became visible).\n  //  - `snapshotReady`: rrweb's first full_snapshot has been buffered.\n  //  - `rrwebFailed`  : record() threw, so no snapshot will ever arrive.\n  // flush()/finalFlush() ship nothing until `started && (snapshotReady ||\n  // rrwebFailed)`. Net effect: a tab that loads hidden and is closed while still\n  // hidden creates NO session, and a started session's first batch always carries\n  // the snapshot (or rrweb is known-failed and the no-replay session ships for the\n  // backend to keep-if-analytics / reap-if-empty).\n  let started = false;\n  let snapshotReady = false;\n  let rrwebFailed = false;\n  // ── Inactivity end + session rotation ──────────────────────────────────────\n  // `idle` = the session was ENDED after sessionInactivityMs with no MEANINGFUL\n  // activity (interaction / navigation / track — not background network/perf/\n  // heartbeat). While idle, emit() drops everything so a page that keeps polling\n  // its API can't extend a session nobody is in. The next meaningful activity\n  // rotates to a fresh session. `lastMeaningfulAt` is only bumped by markMeaningful().\n  let idle = false;\n  let lastMeaningfulAt = Date.now();\n  let idleTimer: number | undefined;\n\n  if (config.distinctId)\n    sendBatch.setIdentify({ distinctId: config.distinctId });\n\n\n  const emit = <TData>(\n    event: Omit<ReplayEvent<TData>, \"id\" | \"offsetMs\" | \"source\">,\n  ) => {\n    // Session was ended for inactivity and nobody's back yet — drop everything\n    // (background network/perf/console/heartbeat) so it can't extend a dead\n    // session. resumeFromIdle() clears `idle` before re-emitting into the fresh one.\n    if (idle) return;\n    session.push({\n      id: session.makeEventId(),\n      // Clamp to >= 0. Some events timestamp themselves off performance\n      // timeOrigin (paint timing, web vitals via PerformanceObserver), which\n      // can predate session.startedAt when the SDK initialises after the page\n      // has already loaded — yielding a negative offset. The server's\n      // offset_ms column is an unsigned int, so a single negative offset\n      // rejects the whole batch insert and silently drops those events.\n      offsetMs: Math.max(0, event.ts - session.startedAt),\n      source: session.sdk.platform,\n      ...event,\n    });\n  };\n\n  // Console sink. One capture, two destinations:\n  //   1. our `type: \"console\"` event → the queryable session_events\n  //      store the AI reads (full serialized args live here).\n  //   2. a compact marker teed into the rrweb stream via addCustomEvent\n  //      so the player can render console frame-aligned with the DOM.\n  // We ship only level+message into rrweb (not the heavy args) to avoid\n  // duplicating the full payload, and only while rrweb is recording —\n  // addCustomEvent throws if no recording is active.\n  const emitConsole = (d: ConsoleEventData) => {\n    emit({ ts: Date.now(), type: \"console\", data: d });\n    if (captures.rrweb) {\n      try {\n        addCustomEvent(\"console\", { level: d.level, message: d.message });\n      } catch {\n        /* rrweb not recording / plugin unavailable — skip the tee */\n      }\n    }\n  };\n\n  const emitSessionStart = () => {\n    const data: SessionStartEventData = {\n      // Scrub credentials (jwt/token/password/reset-password/…) out of the entry\n      // URL + referrer before they're stored — magic-link / OAuth / reset flows\n      // routinely carry them in the query string. Fires before remote config, so\n      // only the always-on default key scrub applies here (the critical case).\n      href: redactUrlForStorage(window.location.href),\n      path: window.location.pathname,\n      referrer: redactUrlForStorage(document.referrer),\n      title: document.title || undefined,\n    };\n    emit({ ts: Date.now(), type: \"session_start\", data });\n  };\n\n  // Last time rrweb emitted ANYTHING (full or incremental). Drives the\n  // idle-aware heartbeat: on a busy page rrweb is already streaming, so the\n  // forced 30s full snapshot is pure overhead — we only force one once the page\n  // has gone quiet (where the stream would otherwise end and a mid-join viewer\n  // would have no base).\n  let lastRrwebActivityAt = Date.now();\n  const emitSnapshot = (rrwebEvent: eventWithTime) => {\n    lastRrwebActivityAt = Date.now();\n    // The session becomes shippable the moment its first FULL snapshot (type 2)\n    // is buffered — every later incremental is a diff against it, so a batch sent\n    // before this would create an unplayable \"no replay\" session server-side.\n    if (rrwebEvent.type === 2) snapshotReady = true;\n    const data: SnapshotEventData = { recorder: \"rrweb\", rrwebEvent };\n    emit({\n      ts: rrwebEvent.timestamp,\n      type: rrwebEvent.type === 2 ? \"full_snapshot\" : \"incremental_snapshot\",\n      data,\n    });\n  };\n\n  const emitViewport = () => {\n    const data: ViewportEventData = {\n      width: window.innerWidth,\n      height: window.innerHeight,\n    };\n    emit({ ts: Date.now(), type: \"viewport\", data });\n  };\n\n  const emitSessionEnd = (reason: SessionEndEventData[\"reason\"]) => {\n    emit({ ts: Date.now(), type: \"session_end\", data: { reason } });\n  };\n\n  const flush = async () => {\n    if (!sampled || blocked) {\n      session.drain();\n      return;\n    }\n    // Visibility + snapshot gate: hold (keep buffering, don't ship) until the\n    // gated start has run AND rrweb's snapshot is buffered (or rrweb is known to\n    // have failed). This is what guarantees the first batch that creates the\n    // server-side session carries the full_snapshot — never a snapshot-less \"no\n    // replay\" row — and that a not-yet-visible tab ships nothing at all.\n    if (!started || (!snapshotReady && !rrwebFailed)) return;\n    // minDuration gate: hold (keep buffering, don't ship) until the session has\n    // lived past minDurationMs, so bounce sessions shorter than the minimum are\n    // never uploaded (they're discarded on unload). 0 disables. Bounded by the\n    // runtime buffer cap.\n    if (minDurationMs > 0 && Date.now() - session.startedAt < minDurationMs) {\n      return;\n    }\n    const events = session.drain();\n    if (events.length === 0) return;\n    const envelope: ReplayBatchEnvelope = {\n      projectId: config.projectId,\n      sessionId: session.sessionId,\n      segmentId: session.segmentId,\n      sequence: session.nextSequence(),\n      sentAt: Date.now(),\n      sdk: session.sdk,\n      page: session.pageContext(),\n      events,\n    };\n    const nextEnvelope = config.beforeSend\n      ? (config.beforeSend({ envelope })?.envelope ?? null)\n      : envelope;\n    if (!nextEnvelope) return;\n    try {\n      await sendBatch(nextEnvelope);\n    } catch {\n      // Send ultimately failed (network down, ingest outage, server error). Put\n      // the events back so the NEXT flush retries them rather than dropping the\n      // batch — dropping the first batch loses the rrweb FullSnapshot and makes\n      // the whole recording unplayable (\"no replay frames\"). Bounded in\n      // requeue(), so a sustained outage can't grow the buffer without limit.\n      session.requeue(events);\n    }\n  };\n\n  const scheduleFlush = () => {\n    void flush();\n  };\n\n  // End the current session because there's been no MEANINGFUL activity for\n  // sessionInactivityMs. Ship its closing batch (with session_end), then gate\n  // emit() so the page's background polling can't keep the dead session alive.\n  const endForIdle = () => {\n    if (idle || !started) return;\n    emitSessionEnd(\"inactivity\");\n    void flush(); // drains synchronously into the send before we gate below\n    idle = true;\n  };\n\n  // A user came back after an inactivity end → the return is a NEW session, not\n  // a continuation. Rotate identity, re-open with session_start + a fresh rrweb\n  // FullSnapshot (its base), and resume. Same anon/identified user (transport\n  // identify/fingerprint state is untouched).\n  const resumeFromIdle = () => {\n    if (!idle) return;\n    idle = false;\n    session.rotate();\n    snapshotReady = false; // the new session must ship its own full_snapshot first\n    emitSessionStart();\n    if (captures.rrweb) {\n      try {\n        record.takeFullSnapshot(true);\n      } catch {\n        /* recorder inactive — the session ships as no-replay (rrwebFailed gate) */\n      }\n    }\n    emitViewport();\n    lastMeaningfulAt = Date.now();\n    scheduleFlush();\n  };\n\n  // The ONLY signal that resets the inactivity clock: genuine engagement —\n  // interactions, real navigations, and explicit track/identify/exception calls.\n  // Deliberately NOT background network/perf/console/heartbeat or app-driven DOM\n  // re-renders, so a page that merely keeps polling its API ages out. Also\n  // revives a session that was already ended.\n  const markMeaningful = () => {\n    lastMeaningfulAt = Date.now();\n    session.touch();\n    if (idle) resumeFromIdle();\n  };\n\n  const syncCapture = (\n    key: string,\n    want: boolean,\n    install: () => (() => void) | undefined,\n  ) => {\n    const slot = captures[key];\n    if (want && !slot) {\n      const stop = install();\n      captures[key] = stop ? { stop } : null;\n      return;\n    }\n    if (!want && slot) {\n      try {\n        slot.stop();\n      } catch {\n        /* ignore */\n      }\n      captures[key] = null;\n    }\n  };\n\n  // Track the privacy options the rrweb recorder was installed with so we\n  // can detect a divergence when remote config arrives and tear-down +\n  // re-install with the new settings. Without this, a user who flips\n  // `maskAllInputs` in Settings would still see plaintext inputs in the\n  // current session — the recorder was already running.\n  let installedPrivacy: {\n    maskAllInputs?: boolean;\n    maskTextSelector?: string;\n    blockSelector?: string;\n    recordCanvas?: boolean;\n    recordCrossOriginIframes?: boolean;\n    maskInputOptionsKey?: string;\n  } | null = null;\n\n  // URL redaction policy applied to outgoing network events. The network\n  // capture reads this when serialising each event so query-strings can\n  // be stripped / allowlisted, and credit-card-looking text scrubbed,\n  // before they leave the browser.\n  let urlRedactionPolicy: {\n    strip: boolean;\n    allowed: string[];\n    blockCC: boolean;\n  } = { strip: false, allowed: [], blockCC: false };\n  // Read live per-request by createNetworkCapture via the getUrlPolicy closure,\n  // so a remote-config privacy update applies without re-installing the capture.\n\n  // Sampling overrides — populated when /v1/sdk/config arrives. Referenced\n  // inside error + identify handlers so they can flip a dropped session\n  // back into recording.\n  let sampleOverrides: {\n    alwaysRecordErrors: boolean;\n    alwaysRecordIdentified: boolean;\n  } | null = null;\n  let minDurationMs = 0;\n\n  const installCaptures = (effective: {\n    console: boolean;\n    network: boolean;\n    errors: boolean;\n    /** Web vitals + long tasks + memory. Defaults to ON locally,\n     *  but the workspace can flip it off via Settings → Recording. */\n    performance?: boolean;\n    captureHeaders: boolean;\n    captureBodies?: boolean;\n    maskAllInputs?: boolean;\n    /** rrweb maskInputOptions — e.g. { password: true, email: true } */\n    maskInputOptions?: Record<string, boolean>;\n    maskTextSelector?: string;\n    blockSelector?: string;\n    recordCanvas?: boolean;\n    recordCrossOriginIframes?: boolean;\n    blockCreditCardText?: boolean;\n    stripQueryParams?: boolean;\n    allowedQueryParams?: string[];\n    redactUrls?: Array<string | RegExp>;\n    /** Phase-1 callers set this — start console/network/errors but defer\n     *  rrweb until phase 2 (after remote config or 300ms timeout) so we\n     *  don't lose the FullSnapshot to a stop+restart. */\n    skipRrweb?: boolean;\n  }) => {\n    if (effective.skipRrweb) {\n      // Bypass rrweb install; install the non-rrweb captures only.\n      syncCapture(\"console\", effective.console, () =>\n        createConsoleCapture(emitConsole),\n      );\n      syncCapture(\"network\", effective.network, () =>\n        createNetworkCapture(\n          {\n            ...config,\n            captureHeaders: effective.captureHeaders,\n            redactUrls: effective.redactUrls ?? config.redactUrls,\n          },\n          (d: NetworkEventData) =>\n            emit({ ts: d.startedAt, type: \"network\", data: d }),\n          // Live URL-redaction policy — read per request so the remote\n          // strip/allowlist/blockCC applies without re-installing the capture.\n          () => urlRedactionPolicy,\n        ),\n      );\n      syncCapture(\"errors\", effective.errors, () =>\n        createErrorCapture((d: ErrorEventData) => {\n          if (!blocked && !sampled && sampleOverrides?.alwaysRecordErrors) sampled = true;\n          emit({ ts: Date.now(), type: \"error\", data: d });\n        }),\n      );\n      syncCapture(\"navigation\", true, () =>\n        createNavigationCapture((d: NavigationEventData) => {\n          markMeaningful(); // a real route change revives an idle session\n          emit({ ts: Date.now(), type: \"navigation\", data: d });\n        }),\n      );\n      syncCapture(\"viewport\", true, () =>\n        createViewportCapture(() => {\n          emitViewport();\n          scheduleFlush();\n        }),\n      );\n      syncCapture(\"rageDead\", true, () =>\n        createRageDeadClickCapture((d) =>\n          emit({ ts: Date.now(), type: \"custom\", data: d }),\n        ),\n      );\n      // Performance signals (LCP/CLS/FID/longtask/memory) — ride along\n      // even in the rrweb-skipped phase-1 branch so we don't miss the\n      // initial paint window. Each metric becomes a `kind: \"perf\"`\n      // custom event; the backend extracts them later.\n      syncCapture(\"performance\", effective.performance !== false, () =>\n        createPerformanceCapture(\n          (d) => emit({ ts: d.ts ?? Date.now(), type: \"performance\", data: d }),\n          {\n            apiHost: config.apiHost,\n            captureResourceTimings: config.captureResourceTimings,\n            resourceMinDurationMs: config.resourceMinDurationMs,\n          },\n        ),\n      );\n      return;\n    }\n    const nextPrivacy = {\n      maskAllInputs: effective.maskAllInputs ?? config.maskAllInputs ?? true, // safe default\n      maskTextSelector: effective.maskTextSelector ?? config.maskTextSelector,\n      blockSelector: effective.blockSelector ?? config.blockSelector,\n      // Host config can force these on without waiting for remote config.\n      recordCanvas: effective.recordCanvas ?? config.recordCanvas ?? false,\n      recordCrossOriginIframes:\n        effective.recordCrossOriginIframes ??\n        config.recordCrossOriginIframes ??\n        false,\n      // Serialise input-type masks so the change-detection below can use a\n      // simple string equality check.\n      maskInputOptionsKey: Object.keys(\n        effective.maskInputOptions ?? { password: true },\n      )\n        .sort()\n        .join(\",\"),\n    };\n    const privacyChanged =\n      installedPrivacy !== null &&\n      (installedPrivacy.maskAllInputs !== nextPrivacy.maskAllInputs ||\n        installedPrivacy.maskTextSelector !== nextPrivacy.maskTextSelector ||\n        installedPrivacy.blockSelector !== nextPrivacy.blockSelector ||\n        installedPrivacy.recordCanvas !== nextPrivacy.recordCanvas ||\n        installedPrivacy.recordCrossOriginIframes !==\n          nextPrivacy.recordCrossOriginIframes ||\n        installedPrivacy.maskInputOptionsKey !==\n          nextPrivacy.maskInputOptionsKey);\n    if (privacyChanged && captures.rrweb) {\n      // Stop the old recorder; new snapshot will fire on re-record so the\n      // server gets a fresh full snapshot with the new privacy applied.\n      captures.rrweb.stop();\n      captures.rrweb = null;\n    }\n    if (!captures.rrweb) {\n      // Only pass options to rrweb when we have a value. Some option names\n      // are version-sensitive (rrweb 2.0-alpha tightened canvas/iframe\n      // option validation) — passing `false` explicitly can throw on init.\n      // Letting them default to rrweb's own defaults is safer.\n      const rrwebOpts: Record<string, unknown> = { emit: emitSnapshot };\n      // Re-emit a full snapshot periodically. rrweb only snapshots once on\n      // record(); if THAT batch is lost (network blip / ingest outage), the\n      // recording is unplayable — incremental mutations with no base to apply\n      // them to. A periodic checkout self-heals a lost initial snapshot and lets\n      // a live viewer join mid-session. Paired with the flush re-queue.\n      rrwebOpts.checkoutEveryNms = 120000;\n      // Default privacy floor for VISIBLE TEXT: mask email addresses in every\n      // text node (opt out with maskTextEmails:false), and optionally long digit\n      // runs (maskTextNumbers). maskAllInputs already covers input VALUES; this\n      // covers free-text PII the reference tracker masks by default.\n      const maskEmails = config.maskTextEmails !== false;\n      if (maskEmails || config.maskTextNumbers) {\n        rrwebOpts.maskTextFn = (text: string): string => {\n          let t = text;\n          if (maskEmails)\n            t = t.replace(/[\\w.+-]+@[\\w-]+\\.[\\w.-]+/g, \"[email]\");\n          if (config.maskTextNumbers)\n            t = t.replace(/\\b\\d{5,}\\b/g, (m) =>\n              \"•\".repeat(Math.min(m.length, 12)),\n            );\n          return t;\n        };\n      }\n      if (typeof nextPrivacy.maskAllInputs === \"boolean\")\n        rrwebOpts.maskAllInputs = nextPrivacy.maskAllInputs;\n      if (nextPrivacy.maskTextSelector)\n        rrwebOpts.maskTextSelector = nextPrivacy.maskTextSelector;\n      if (nextPrivacy.blockSelector)\n        rrwebOpts.blockSelector = nextPrivacy.blockSelector;\n      if (nextPrivacy.recordCanvas) rrwebOpts.recordCanvas = true;\n      if (nextPrivacy.recordCrossOriginIframes)\n        rrwebOpts.recordCrossOriginIframes = true;\n      // Always-on input-type masks (password by default, plus anything the\n      // workspace's mask rules implied via `input[type=\"X\"]` selectors).\n      // This wins even when maskAllInputs is false.\n      if (\n        effective.maskInputOptions &&\n        Object.keys(effective.maskInputOptions).length > 0\n      ) {\n        rrwebOpts.maskInputOptions = effective.maskInputOptions;\n      } else {\n        rrwebOpts.maskInputOptions = { password: true };\n      }\n      let stop: (() => void) | undefined;\n      let heartbeat: ReturnType<typeof setInterval> | undefined;\n      try {\n        stop = record(rrwebOpts as Parameters<typeof record>[0]);\n        // rrweb only snapshots on ACTIVITY, so an idle page stops emitting and\n        // the replay stream ends at the last DOM mutation — far short of the real\n        // wall-clock session — while a lost/absent base leaves the whole recording\n        // unplayable (\"no replay frames\"). Force a full snapshot on a wall-clock\n        // TIMER (every 30s, regardless of activity): this keeps the stream\n        // spanning the whole session (idle included) and guarantees a FRESH BASE\n        // exists within 30s of any point — self-healing a lost initial snapshot,\n        // surviving the privacy-driven restart below (which doesn't re-snapshot),\n        // and enabling live mid-join. The SDK analog of the reference tracker's\n        // periodic keepalive.\n        heartbeat = setInterval(() => {\n          // Never force a snapshot while the tab is HIDDEN. A backgrounded tab has\n          // no visible activity to record, so forcing keepalive snapshots there\n          // just pads the session with a dead idle tail (the frameless-long-session\n          // phantom). The reference tracker likewise lets hidden time drive a\n          // restart, not blind timers. It resumes forcing once the tab is visible.\n          if (document.visibilityState === \"hidden\") return;\n          // Idle-aware: skip the forced full snapshot when rrweb already emitted\n          // within the last interval (the page is active and self-heals via its\n          // own stream + the 2-min checkout). Only force one when the page has\n          // gone quiet — keeping the self-heal for idle pages without\n          // re-serializing a busy large-DOM app every 30s.\n          if (Date.now() - lastRrwebActivityAt < 30_000) return;\n          try {\n            record.takeFullSnapshot(true);\n          } catch {\n            /* recorder not active — ignore */\n          }\n        }, 30_000);\n        // Priority-flush the initial FullSnapshot now instead of waiting for the\n        // 3s auto-flush, so the recording is playable ASAP and the most important\n        // batch (the base) is the first one persisted + retried.\n        scheduleFlush();\n      } catch (e) {\n        // Surface in console + telemetry, but don't break the whole SDK —\n        // we still want console/network/errors capture even if rrweb fails.\n        // eslint-disable-next-line no-console\n        console.error(\"[replay-sdk] rrweb.record failed:\", e);\n        // No snapshot will ever arrive, so release the flush hold — otherwise the\n        // session (console/network/errors, no replay) would buffer forever and\n        // never ship. It ships as a no-replay session; the backend keeps it only\n        // if it carries analytics/signal, otherwise reaps it.\n        rrwebFailed = true;\n      }\n      if (stop) {\n        const stopRec = stop;\n        captures.rrweb = {\n          stop: () => {\n            if (heartbeat) clearInterval(heartbeat);\n            stopRec();\n          },\n        };\n      } else if (heartbeat) {\n        clearInterval(heartbeat);\n      }\n      installedPrivacy = nextPrivacy;\n    }\n\n    // Remember the URL-redaction policy so other captures (network\n    // mostly) can use it to strip query params + credit-card text.\n    urlRedactionPolicy = {\n      strip: !!effective.stripQueryParams,\n      allowed: effective.allowedQueryParams ?? [],\n      blockCC: !!effective.blockCreditCardText,\n    };\n    syncCapture(\"console\", effective.console, () =>\n      createConsoleCapture((d: ConsoleEventData) =>\n        emit({ ts: Date.now(), type: \"console\", data: d }),\n      ),\n    );\n    syncCapture(\"network\", effective.network, () =>\n      createNetworkCapture(\n        {\n          ...config,\n          captureHeaders: effective.captureHeaders,\n          redactUrls: effective.redactUrls ?? config.redactUrls,\n        },\n        (d: NetworkEventData) =>\n          emit({ ts: d.startedAt, type: \"network\", data: d }),\n        () => urlRedactionPolicy,\n      ),\n    );\n    syncCapture(\"errors\", effective.errors, () =>\n      createErrorCapture((d: ErrorEventData) => {\n        // If sampling-out dropped this session, but the workspace policy\n        // says \"always record errors\", flip sampled back on the moment an\n        // error fires. The current event + any in the buffer will ship\n        // on the next flush.\n        if (!blocked && !sampled && sampleOverrides?.alwaysRecordErrors) {\n          sampled = true;\n        }\n        emit({ ts: Date.now(), type: \"error\", data: d });\n      }),\n    );\n    syncCapture(\"navigation\", true, () =>\n      createNavigationCapture((d: NavigationEventData) => {\n        markMeaningful(); // a real route change revives an idle session\n        emit({ ts: Date.now(), type: \"navigation\", data: d });\n      }),\n    );\n    syncCapture(\"viewport\", true, () =>\n      createViewportCapture(() => {\n        emitViewport();\n        scheduleFlush();\n      }),\n    );\n    // Rage + dead-click detector emits as custom events; the persistence\n    // worker counts these into session.rageCount / deadCount.\n    syncCapture(\"rageDead\", true, () =>\n      createRageDeadClickCapture((d) =>\n        emit({ ts: Date.now(), type: \"custom\", data: d }),\n      ),\n    );\n    // Performance signals — LCP/CLS/FID via PerformanceObserver,\n    // long tasks for jank, and periodic heap-size snapshots. Each\n    // metric is wrapped as a `kind: \"perf\"` rrweb-style event; the\n    // persistence service treats the `type: \"performance\"` channel\n    // exactly like custom rage-click events.\n    syncCapture(\"performance\", effective.performance !== false, () =>\n      createPerformanceCapture(\n        (d) => emit({ ts: d.ts ?? Date.now(), type: \"performance\", data: d }),\n        {\n          // Give the resource-timing observer our own ingest origin (same options\n          // the phase-1 install passes) so its isServiceURL check can always skip\n          // /v1/sdk/config etc. even if the perf slot is re-created via this path.\n          apiHost: config.apiHost,\n          captureResourceTimings: config.captureResourceTimings,\n          resourceMinDurationMs: config.resourceMinDurationMs,\n        },\n      ),\n    );\n  };\n\n  // The visibility-gated start. Following the reference tracker, NOTHING is\n  // emitted, installed, or flushed until the tab is first VISIBLE — a tab that\n  // loads hidden (background-opened, prerendered) records nothing until the user\n  // actually looks at it, and one closed while still hidden never creates a\n  // session. Runs at most once (the `started` guard).\n  const startCapture = () => {\n    if (started) return;\n    started = true;\n    // A FRESH session anchors its clock to NOW (first-visible) so the timeline\n    // begins when the page is seen, not when a hidden tab constructed the\n    // runtime. A resumed session keeps its original startedAt (offset continuity).\n    if (!session.resumed) session.beginFreshClock();\n\n    // A fresh session opens with session_start (sets the entry page). A RESUMED\n    // session — a reload or same-tab back/forward within the inactivity window —\n    // instead records the reload as a page navigation, so the original entry page\n    // is preserved and the reload shows on the timeline as a page transition\n    // rather than a second \"session start\".\n    if (session.resumed) {\n      emit({\n        ts: Date.now(),\n        type: \"navigation\",\n        data: {\n          to: window.location.href,\n          trigger: \"load\",\n        } satisfies NavigationEventData,\n      });\n    } else {\n      emitSessionStart();\n    }\n    emitViewport();\n\n    // We install captures in *two phases* to avoid losing the rrweb\n    // FullSnapshot. Phase 1 starts everything EXCEPT rrweb. Phase 2 runs\n    // after remote config arrives (or 300ms timeout, whichever's first) and\n    // starts rrweb with the final privacy/canvas options.\n    //\n    // Why split? rrweb only fires FullSnapshot on initial `record()`. If we\n    // started it in phase 1 with stale config, then stopped+restarted in\n    // phase 2 because `recordCanvas` flipped, the new instance does NOT\n    // re-emit a FullSnapshot (rrweb 2.0-alpha quirk). The Replayer then\n    // has incremental snapshots with nothing to apply them to → blank\n    // screen with \"no replay frames\" in the dashboard.\n    installCaptures({\n      console: config.captureConsole !== false,\n      network: config.captureNetwork !== false,\n      errors: config.captureErrors !== false,\n      // Default-on in phase 1 so we don't miss the LCP window while remote\n      // config is in flight. If remote arrives and says off, the next\n      // installCaptures call disables it.\n      performance: true,\n      captureHeaders: config.captureHeaders ?? false,\n      maskAllInputs: config.maskAllInputs ?? true,\n      // Phase 1 deliberately skips rrweb — see installCaptures internals.\n      skipRrweb: true,\n    });\n\n    // Promise race: whichever fires first wins. We never wait > 300ms for\n    // remote config — a slow /v1/sdk/config request shouldn't delay\n    // recording.\n    const remotePromise = fetchRemoteConfig(config);\n    const timeoutPromise = new Promise<null>((r) =>\n      setTimeout(() => r(null), 300),\n    );\n    void Promise.race([remotePromise, timeoutPromise]).then(async (remote) => {\n      // If the race was won by the timeout, await the actual remote in the\n      // background so it can still adjust mid-session — but start recording\n      // NOW using local config as the source of truth.\n      if (remote === null) {\n        installCaptures({\n          console: config.captureConsole !== false,\n          network: config.captureNetwork !== false,\n          errors: config.captureErrors !== false,\n          performance: true,\n          captureHeaders: config.captureHeaders ?? false,\n          maskAllInputs: config.maskAllInputs ?? true,\n        });\n        const lateRemote = await remotePromise.catch(() => null);\n        if (lateRemote) applyRemoteConfig(lateRemote);\n        return;\n      }\n      applyRemoteConfig(remote);\n    });\n\n    // Start the periodic flush now (not while hidden). Its first tick and any\n    // scheduleFlush() are still held by the snapshot gate until the base exists.\n    session.startAutoFlush(flush);\n  };\n\n  function applyRemoteConfig(\n    remote: NonNullable<Awaited<ReturnType<typeof fetchRemoteConfig>>>,\n  ) {\n    // ---- Hard cap gate ----------------------------------------------\n    // The workspace has spent its plan's session allowance. Record NOTHING and\n    // ship NOTHING — this beats every \"always record\" override below (a maxed\n    // plan doesn't record errors or identified users either). The server also\n    // rejects any batch that slips through, but honouring the flag here is what\n    // saves the upload: the device does no work at all.\n    if (remote.shouldNotRecord) {\n      blocked = true;\n      sampled = false;\n      return;\n    }\n\n    // Host-configured URL/route EXCLUSION — the \"don't record this screen\" opt-out\n    // for web. A deny-list of path globs (e.g. \"/settings/billing\", \"/admin/**\")\n    // beats every \"always record\" override and the sample roll; like\n    // shouldNotRecord, an excluded URL does NO capture work and ships nothing.\n    // NOTE (SPA follow-up): this is evaluated at init/config time. A single-page\n    // app that CLIENT-navigates into an excluded route mid-session is not yet\n    // re-gated — that needs a navigation hook that pauses/resumes capture.\n    if (\n      (config.excludeUrls ?? []).some((g) =>\n        matchesGlob(g, window.location.href),\n      )\n    ) {\n      blocked = true;\n      sampled = false;\n      return;\n    }\n\n    // ---- Sampling decision ------------------------------------------\n    // Start by rolling the sample rate. The \"always record\" overrides\n    // below can flip the decision back on for this particular session.\n    const url = window.location.href;\n    const urlForced = (remote.sampling.alwaysRecordOnUrls ?? []).some((g) =>\n      matchesGlob(g, url),\n    );\n    const triggerAllowsRecord =\n      remote.capture.trigger !== \"identified\" || !!config.distinctId;\n    const sampledIn = urlForced || Math.random() <= remote.sampling.rate;\n    sampled = sampledIn && triggerAllowsRecord;\n    if (!sampled) {\n      // Still install the rest of the captures so identify() can flip\n      // sampling on later. We just won't ship the batches.\n    }\n\n    // ---- Capture toggles --------------------------------------------\n    // maskSelectors/blockSelectors arrive as arrays of CSS selectors;\n    // rrweb takes a single comma-joined string for each.\n    const maskTextSelector =\n      (remote.privacy.maskSelectors ?? []).join(\", \") || undefined;\n    const blockSelector =\n      (remote.privacy.blockSelectors ?? []).join(\", \") || undefined;\n\n    // Build rrweb's maskInputOptions from the server-derived input-type\n    // list. `password` is always included even when the customer disables\n    // maskAllInputs — that's the security floor.\n    const maskInputOptions: Record<string, boolean> = {};\n    for (const t of remote.privacy.maskInputTypes ?? [\"password\"]) {\n      maskInputOptions[t] = true;\n    }\n\n    installCaptures({\n      console: remote.capture.console,\n      network: remote.capture.network,\n      errors: remote.capture.errors,\n      performance: remote.capture.performance,\n      captureHeaders: remote.capture.networkHeaders ?? remote.capture.headers,\n      captureBodies: remote.capture.networkBodies,\n      maskAllInputs: remote.privacy.maskAllInputs,\n      maskInputOptions,\n      maskTextSelector,\n      blockSelector,\n      recordCanvas: remote.capture.canvas,\n      recordCrossOriginIframes: remote.capture.iframe,\n      blockCreditCardText: remote.privacy.blockCreditCardText,\n      stripQueryParams: remote.privacy.stripQueryParams,\n      allowedQueryParams: remote.privacy.allowedQueryParams,\n      redactUrls: remote.privacy.redactUrlPatterns.map(\n        (p) => new RegExp(p, \"i\"),\n      ),\n    });\n\n    // Remember the rules so identify()-triggered re-evaluation can flip\n    // sampling on later when alwaysRecordIdentified=true.\n    sampleOverrides = {\n      alwaysRecordErrors: remote.sampling.alwaysRecordErrors,\n      alwaysRecordIdentified: remote.sampling.alwaysRecordIdentified,\n    };\n    minDurationMs = remote.capture.minDurationMs ?? 0;\n  } // end applyRemoteConfig\n\n  // Tiny glob matcher — supports `**` (matches anything) and `*` (matches\n  // anything not /). Enough for `/checkout/**` style patterns.\n  function matchesGlob(glob: string, url: string): boolean {\n    try {\n      const path = new URL(url).pathname;\n      const rx =\n        \"^\" +\n        glob\n          .replace(/[.+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n          .replace(/\\*\\*/g, \"::DOUBLE::\")\n          .replace(/\\*/g, \"[^/]*\")\n          .replace(/::DOUBLE::/g, \".*\") +\n        \"$\";\n      return new RegExp(rx).test(path);\n    } catch {\n      return false;\n    }\n  }\n\n  // Deliver the tail reliably as the page goes away. visibilitychange:hidden is\n  // the signal that fires FIRST on a tab close (and the only one guaranteed when\n  // a mobile tab is backgrounded / on bfcache), so the closing frames are\n  // usually shipped while the page is still alive; pagehide + beforeunload mop\n  // up anything left. Each call drains the buffer, so the later ones are no-ops\n  // when an earlier one already sent — no duplicate batches.\n  const finalFlush = (reason: SessionEndEventData[\"reason\"]) => {\n    // Never create a server-side session on the way out for a tab that never\n    // visibly started, or whose snapshot never arrived (and rrweb didn't fail) —\n    // same gate flush() uses. A load-hidden-then-closed tab and a pre-snapshot\n    // bounce both ship nothing.\n    if (!started || (!snapshotReady && !rrwebFailed)) return;\n    // Discard a bounce session that never reached minDuration — don't ship its\n    // held buffer on the way out.\n    if (minDurationMs > 0 && Date.now() - session.startedAt < minDurationMs) {\n      return;\n    }\n    emitSessionEnd(reason);\n    session.flushFinal(sendBatch.sendFinal);\n  };\n  document.addEventListener(\"visibilitychange\", () => {\n    if (document.visibilityState === \"hidden\") finalFlush(\"visibility_hidden\");\n  });\n  window.addEventListener(\"pagehide\", () => finalFlush(\"unload\"));\n  window.addEventListener(\"beforeunload\", () => finalFlush(\"unload\"));\n\n  // Keep the session's last-activity marker fresh on genuine USER interaction —\n  // deliberately NOT the SDK's own heartbeat/perf events, so an idle tab that's\n  // only emitting keepalive snapshots still ages out of the resume window. These\n  // are passive + capture so they never delay the page's own handlers, and the\n  // write behind touch() is throttled, so this is effectively free on the hot\n  // pointer/scroll path.\n  const onUserActivity = () => markMeaningful();\n  const activityEvents = [\n    \"pointerdown\",\n    \"keydown\",\n    \"scroll\",\n    \"touchstart\",\n  ] as const;\n  for (const evt of activityEvents) {\n    window.addEventListener(evt, onUserActivity, {\n      passive: true,\n      capture: true,\n    });\n  }\n\n  // Live inactivity timeout: end the session after `inactivityMs` with no\n  // meaningful activity (GA's session model + the reference tracker's own\n  // \"stop session after inactivity timeout\" TODO). Poll at a fraction of the\n  // window (≤30s) — cheap, and precise enough since the window is minutes.\n  // sessionInactivityMs = 0 (or huge) effectively disables it.\n  if (session.inactivityMs > 0) {\n    const checkEvery = Math.min(\n      30_000,\n      Math.max(1_000, Math.floor(session.inactivityMs / 4)),\n    );\n    idleTimer = window.setInterval(() => {\n      if (!idle && started && Date.now() - lastMeaningfulAt >= session.inactivityMs) {\n        endForIdle();\n      }\n    }, checkEvery);\n  }\n\n  // Kick off the visibility-gated start. If the tab is already visible, start\n  // synchronously — unchanged behavior for the overwhelmingly common case. If it\n  // loaded hidden (background-opened tab / prerender, which report \"hidden\"),\n  // defer the entire start to the first time it becomes visible, then unregister,\n  // so a hidden tab is never recorded and — if it's closed while still hidden —\n  // no session is ever created.\n  if (document.visibilityState !== \"hidden\") {\n    startCapture();\n  } else {\n    const onFirstVisible = () => {\n      if (document.visibilityState !== \"hidden\") {\n        document.removeEventListener(\"visibilitychange\", onFirstVisible);\n        startCapture();\n      }\n    };\n    document.addEventListener(\"visibilitychange\", onFirstVisible);\n  }\n\n  const identify: ReplayController[\"identify\"] = (idOrPayload, props) => {\n    const payload: IdentifyPayload =\n      typeof idOrPayload === \"string\"\n        ? { distinctId: idOrPayload, ...(props ?? {}) }\n        : { ...idOrPayload };\n    sendBatch.setIdentify(payload);\n    markMeaningful(); // identify is engagement — revives an idle session\n    // Emit a DISCRETE, timestamped identify marker into the stream (parity with\n    // the reference tracker's UserID message) so the exact moment of anon→known\n    // is a first-class timeline event, not just an attribute on later batches.\n    if (payload.distinctId || payload.email) {\n      emit({\n        ts: Date.now(),\n        type: \"custom\",\n        data: {\n          kind: \"identify\",\n          distinctId: payload.distinctId ?? payload.email,\n          ...(payload.email ? { email: payload.email } : {}),\n        },\n      });\n    }\n    // Workspace policy: \"always record identified users\" flips a\n    // previously-dropped session back into recording the moment the\n    // customer calls identify(). Saves an \"I had this user but no\n    // session\" support ticket.\n    if (\n      !blocked &&\n      !sampled &&\n      sampleOverrides?.alwaysRecordIdentified &&\n      payload.distinctId\n    ) {\n      sampled = true;\n    }\n    void flush();\n  };\n\n  // Host-supplied anonymous/device id — override the SDK's generated fingerprint\n  // so the same person is one anonymous user across the customer's systems.\n  // Persisted so it survives reloads.\n  const setAnonymousId: ReplayController[\"setAnonymousId\"] = (id) => {\n    if (!id || typeof id !== \"string\") return;\n    const trimmed = id.trim().slice(0, 200);\n    if (!trimmed) return;\n    setStoredFingerprint(trimmed);\n    sendBatch.setFingerprint(trimmed);\n  };\n\n  // Free-form session trait, independent of user identity. Captured into the\n  // stream as a custom event so it's queryable + timeline-visible.\n  const setMetadata: ReplayController[\"setMetadata\"] = (key, value) => {\n    if (!key || typeof key !== \"string\") return;\n    emit({\n      ts: Date.now(),\n      type: \"custom\",\n      data: {\n        kind: \"session_metadata\",\n        key: key.trim().slice(0, 80),\n        value: typeof value === \"string\" ? value.slice(0, 500) : String(value),\n      },\n    });\n    void flush();\n  };\n\n  // Custom event tracking. Rides along in the batch as a `custom`\n  // event with `kind: \"track\"` so the backend can pluck names into a\n  // denormalised `Session.eventNames[]` without breaking older\n  // consumers that already match `kind: \"rage_click\" | \"dead_click\"`.\n  const track: ReplayController[\"track\"] = (name, properties) => {\n    if (!name || typeof name !== \"string\") return;\n    const safeName = name.trim().slice(0, 80);\n    if (!safeName) return;\n    markMeaningful(); // a tracked event is engagement — revives an idle session\n    emit({\n      ts: Date.now(),\n      type: \"custom\",\n      data: {\n        kind: \"track\",\n        name: safeName,\n        // Cap properties to keep batches small. Stringify defensively\n        // so we don't ship Functions / DOM nodes.\n        properties: properties ? safeProps(properties) : undefined,\n      },\n    });\n  };\n\n  // Report a developer-caught exception as the same `error` event the automatic\n  // window handlers emit, marked handled (so the dashboard classifies it as an\n  // \"exception\" vs an uncaught \"crash\"). Mirrors track()'s emit path.\n  const captureException: ReplayController[\"captureException\"] = (\n    error,\n    opts,\n  ) => {\n    // Same policy as the automatic error path: if sampling-out dropped this\n    // session but the workspace says \"always record errors\", a reported\n    // exception flips recording back on — otherwise the handled error the\n    // feature exists to surface would be discarded on the next flush.\n    if (!blocked && !sampled && sampleOverrides?.alwaysRecordErrors) {\n      sampled = true;\n    }\n    markMeaningful(); // an explicitly-reported exception is engagement\n    emit({\n      ts: Date.now(),\n      type: \"error\",\n      data: errorDataFromValue(error, opts?.handled ?? true, opts?.metadata),\n    });\n  };\n\n  return {\n    // Getter — rotate() (inactivity return) changes the id mid-flight, so a host\n    // reading `replay.sessionId` must see the CURRENT session, not the init one.\n    get sessionId() {\n      return session.sessionId;\n    },\n    flush,\n    identify,\n    track,\n    captureException,\n    setAnonymousId,\n    setMetadata,\n    // Deep link to THIS session in the dashboard — the private, authed\n    // /recordings/<id> route (NOT a public share link). Read the live session id\n    // (it rotates on inactivity), and derive the app host from apiHost.\n    urlForCurrentSession: () =>\n      session.sessionId\n        ? `${dashboardHostFromApiHost(config.apiHost)}/recordings/${session.sessionId}`\n        : null,\n    stop: async () => {\n      if (idleTimer !== undefined) window.clearInterval(idleTimer);\n      for (const k of Object.keys(captures)) {\n        const slot = captures[k];\n        if (slot) {\n          try {\n            slot.stop();\n          } catch {\n            /* ignore */\n          }\n          captures[k] = null;\n        }\n      }\n      for (const evt of activityEvents) {\n        window.removeEventListener(evt, onUserActivity, {\n          capture: true,\n        } as EventListenerOptions);\n      }\n      session.stopAutoFlush();\n      emitSessionEnd(\"manual\");\n      await flush();\n    },\n  };\n}\n\n/**\n * Coerce arbitrary properties into a JSON-safe shape before shipping\n * with a track() event. We keep:\n *   - primitives (string/number/boolean/null)\n *   - arrays of primitives\n *   - plain objects one level deep\n * Anything else (DOM nodes, functions, circular structures) is\n * dropped. Caps at 20 keys + 200 chars per value so a single noisy\n * call can't blow the batch size budget.\n */\nfunction safeProps(p: Record<string, unknown>): Record<string, unknown> {\n  const out: Record<string, unknown> = {};\n  let i = 0;\n  for (const k of Object.keys(p)) {\n    if (i >= 20) break;\n    i++;\n    const v = p[k];\n    if (v === null || typeof v === \"boolean\" || typeof v === \"number\") {\n      out[k] = v;\n    } else if (typeof v === \"string\") {\n      out[k] = v.slice(0, 200);\n    } else if (Array.isArray(v)) {\n      out[k] = v.slice(0, 20).map((x) =>\n        typeof x === \"string\" ? x.slice(0, 200) : x,\n      );\n    } else if (v && typeof v === \"object\") {\n      // Flatten one level — { from: \"free\", to: \"pro\" } is the\n      // typical track() payload. Anything deeper gets toString'd.\n      try {\n        out[k] = JSON.parse(JSON.stringify(v));\n      } catch {\n        out[k] = String(v).slice(0, 200);\n      }\n    }\n  }\n  return out;\n}\n"]}