@hanzo/event 0.3.49 → 0.3.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/attribution.ts","../src/org.ts","../src/scrub.ts","../src/throwable.ts","../src/anon.js","../src/storage.ts","../src/link.ts","../package.json","../src/version.ts","../src/core.ts","../src/cookie.ts","../src/consent.ts","../src/react.tsx"],"names":["get","set","normalizeError","PAGEVIEW","read","createContext","useEffect","createElement","useContext","useRef","Component","useSyncExternalStore"],"mappings":"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","file":"react.cjs","sourcesContent":["// Pure attribution helpers: parse first-touch UTM/referrer/refCode from a URL,\n// derive the acquisition channel, and compute the ISO week for the signup cohort.\n// No I/O, no globals — trivially testable.\n\nimport type { Attribution } from './types'\n\nconst SOCIAL_HOSTS = [\n 'facebook.', 'instagram.', 'twitter.', 'x.com', 't.co', 'linkedin.',\n 'reddit.', 'youtube.', 'tiktok.', 'pinterest.', 'news.ycombinator.com',\n]\nconst SEARCH_HOSTS = ['google.', 'bing.', 'duckduckgo.', 'yahoo.', 'baidu.', 'ecosia.']\n\n/** parseAttribution reads UTM params + ref/refCode from a query string and pairs\n * them with the referrer. `search` is a location.search value (\"?utm_source=…\"). */\nexport function parseAttribution(search: string, referrer: string): Attribution {\n const q = new URLSearchParams(search || '')\n const get = (k: string) => {\n const v = q.get(k)\n return v ? v.trim() : undefined\n }\n const a: Attribution = {\n utm: {\n source: get('utm_source'),\n medium: get('utm_medium'),\n campaign: get('utm_campaign'),\n term: get('utm_term'),\n content: get('utm_content'),\n },\n referrer: referrer ? referrer.trim() : undefined,\n refCode: get('ref') || get('refCode') || get('ref_code') || undefined,\n }\n a.channel = deriveChannel(a)\n return a\n}\n\n/** deriveChannel classifies the visit: paid | referral | social | organic | direct. */\nexport function deriveChannel(a: Attribution): string {\n const medium = (a.utm.medium || '').toLowerCase()\n if (/(cpc|ppc|paid|paidsearch|display|cpm)/.test(medium)) return 'paid'\n if (a.utm.source || a.utm.campaign) return 'campaign'\n if (a.refCode) return 'referral'\n const host = hostOf(a.referrer)\n if (!host) return 'direct'\n if (SOCIAL_HOSTS.some((h) => host.includes(h))) return 'social'\n if (SEARCH_HOSTS.some((h) => host.includes(h))) return 'organic'\n return 'referral'\n}\n\n/** hostOf extracts a bare lowercase host from a URL; \"\" when unparseable. */\nexport function hostOf(raw?: string): string {\n if (!raw) return ''\n let s = raw.trim()\n const scheme = s.indexOf('://')\n if (scheme >= 0) s = s.slice(scheme + 3)\n const cut = s.search(/[/?#]/)\n if (cut >= 0) s = s.slice(0, cut)\n const at = s.indexOf('@')\n if (at >= 0) s = s.slice(at + 1)\n const colon = s.indexOf(':')\n if (colon >= 0) s = s.slice(0, colon)\n return s.toLowerCase().trim()\n}\n\n/** hasAttribution reports whether anything was captured (so we don't persist an\n * empty first-touch that would shadow a later real one). */\nexport function hasAttribution(a: Attribution): boolean {\n return Boolean(\n a.utm.source || a.utm.medium || a.utm.campaign || a.utm.term ||\n a.utm.content || a.refCode || (a.referrer && hostOf(a.referrer)),\n )\n}\n\n/** isoWeek returns the ISO-8601 week label, e.g. \"2026-W28\". */\nexport function isoWeek(d: Date): string {\n // Copy to UTC midnight; ISO week: Thursday-anchored.\n const date = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()))\n const day = date.getUTCDay() || 7\n date.setUTCDate(date.getUTCDate() + 4 - day)\n const yearStart = new Date(Date.UTC(date.getUTCFullYear(), 0, 1))\n const week = Math.ceil(((date.getTime() - yearStart.getTime()) / 86400000 + 1) / 7)\n return `${date.getUTCFullYear()}-W${String(week).padStart(2, '0')}`\n}\n","/**\n * Which org owns a host's telemetry.\n *\n * A surface should not have to LEARN its key. It already knows the domain it is\n * served from, and a domain belongs to exactly one brand, so the key is derivable\n * and asking a surface to carry one is asking it to restate something already\n * true. This module answers `orgOf(location.hostname)` and hands back that org's\n * publishable key, which is what lets a static export report correctly while\n * configuring nothing.\n *\n * This is the SAME question `hanzo.id` answers at runtime for the identity hosts\n * (`pkgs/shared/src/ingest.ts`): one image serves every brand, so the key cannot\n * be a property of the build. It was, and the bill is on record — Lux's, Zoo's,\n * Osage's and Pars' visitors were all filed in HANZO's project, because one\n * build-time key was inlined for every brand. That is the white-label boundary\n * crossed in the direction that shows up latest. The marketing sites carry the\n * identical defect in its other form: each commits its OWN key literal, so the\n * fleet holds N copies of a value with one source, and a site added tomorrow\n * reports nothing until somebody remembers to paste one in.\n *\n * A `pk-` is PUBLISHABLE: it authorizes a write into one org and mints no reading\n * principal. It is readable in devtools on every deployed page that sends an\n * event, so stating it here exposes nothing that serving the page did not. What\n * it does buy is that correct attribution becomes the DEFAULT rather than\n * something each surface opts into.\n *\n * Keyed by ORG, never by host: a brand's facts repeat on every alias it owns\n * (`lux.id`, `id.lux.network`), and a key stated per host would have to be\n * repeated too — so the day someone adds an alias and forgets the key, that host\n * silently stops reporting. Stated once per org, a new alias inherits its brand's\n * key by naming its brand's domain, which is all an alias ever says.\n */\n\n/** One publishable key per org. */\nexport type Keyring = Readonly<Record<string, string>>\n\n/**\n * Each org's registrable domains. A host matches a domain when it IS that domain\n * or a subdomain of it, so `explore.lux.network` needs no entry of its own.\n *\n * An org absent from this table resolves to undefined, and that is deliberate:\n * `osage`, `pars` and `bootnode` have no project of their own yet, and reporting\n * NOTHING is the honest answer. Filing them under a brand that is not theirs is\n * the defect this module exists to prevent — it is silent, it reads as working,\n * and it is only visible later in someone else's warehouse.\n */\nexport const ORG_DOMAIN: Readonly<Record<string, readonly string[]>> = Object.freeze({\n // A brand's domains are not a pattern — `hanzoskills.com` is Hanzo's and does\n // not end in `hanzo.ai`, while `hanzo.works` is a registrable domain of its own\n // rather than a subdomain of anything here. Each is stated because each is a\n // separate fact, which is the whole reason this is a table.\n hanzo: Object.freeze([\n 'hanzo.ai',\n 'hanzo.agency',\n 'hanzo.app',\n 'hanzo.bot',\n 'hanzo.chat',\n 'hanzo.codes',\n 'hanzo.id',\n 'hanzo.industries',\n 'hanzo.market',\n 'hanzo.network',\n 'hanzo.sh',\n 'hanzo.team',\n 'hanzo.ventures',\n 'hanzo.works',\n 'hanzoskills.com',\n ]),\n lux: Object.freeze([\n 'lux.network',\n 'lux.exchange',\n 'lux.market',\n 'lux.finance',\n 'lux.financial',\n 'lux.credit',\n 'lux.fund',\n 'lux.id',\n ]),\n zoo: Object.freeze(['zoo.ngo', 'zoo.network', 'zoolabs.id', 'zoolabs.io']),\n})\n\n/**\n * Each org's publishable key, and a copy: the values live in universe at\n * infra/k8s/id/configmap.yaml as SPA_INGEST_KEYRING, which serves them to the\n * identity hosts, and this table is what a statically exported page carries when\n * it cannot ask. The two must say the same thing. Add an org the day its project\n * exists, never before.\n *\n * A key is only as real as the project it names, and these had stopped naming\n * one: all three answered `403 ingest_key_unknown` against /v1/event, so every\n * page that fell back to this table reported nowhere while looking fine. The\n * copy drifted silently because nothing compares it to the keyring. If you\n * recreate a project, move BOTH.\n */\nexport const ORG_KEY: Keyring = Object.freeze({\n hanzo: 'pk-rM_CdaF2MQckGCrla113SrR1oH4zvqN8xh2I95Z9tY8',\n lux: 'pk-gUZp6ZVfhJzSwK-rb4oLbVkpCnMBx5uSCpxf_5yEhQk',\n zoo: 'pk-3TKpKnERV9AQSsBUERWkZejC1O1mUxc1jRzsP3MPbs4',\n})\n\n/** `pk-` is publishable; `sk-` is not, and there is no third thing. Checked at the\n * one point a key becomes something a page will send, so a mistyped entry fails\n * closed rather than putting a secret in every visitor's tab. */\nconst PUBLISHABLE = 'pk-'\n\n/** Strip the port and case a hostname the way a domain compares. */\nconst normalize = (host: string): string =>\n host.trim().toLowerCase().replace(/\\.$/, '').split(':')[0] ?? ''\n\n/**\n * The org that owns a host, or undefined when no brand claims it.\n *\n * Longest match wins, so a brand owning both a domain and a subdomain of another\n * brand's cannot be decided by table order. Pure and total.\n */\nexport function orgOf(host: string): string | undefined {\n const h = normalize(host)\n if (!h) return undefined\n let best: string | undefined\n let bestLen = 0\n for (const [org, domains] of Object.entries(ORG_DOMAIN)) {\n for (const d of domains) {\n if ((h === d || h.endsWith(`.${d}`)) && d.length > bestLen) {\n best = org\n bestLen = d.length\n }\n }\n }\n return best\n}\n\n/**\n * The publishable key for a host, or undefined when there is not exactly one to\n * give.\n *\n * Deliberately WITHOUT a fallback: returning Hanzo's key for an unrecognised host\n * is precisely the defect described above. Undefined is the honest answer and the\n * caller reports nothing.\n *\n * `keyring` is a parameter so the identity runtime — which receives its keyring\n * from `/config.json` because one image serves every brand — resolves through\n * this SAME function rather than a second copy of it.\n */\nexport function keyFor(host: string, keyring: Keyring = ORG_KEY): string | undefined {\n const org = orgOf(host)\n if (!org) return undefined\n const key = keyring[org]\n if (typeof key !== 'string') return undefined\n const trimmed = key.trim()\n return trimmed.startsWith(PUBLISHABLE) ? trimmed : undefined\n}\n\n/** The key for the page this code is running on; undefined off a browser. */\nexport function keyForPage(keyring: Keyring = ORG_KEY): string | undefined {\n if (typeof location === 'undefined') return undefined\n return keyFor(location.hostname, keyring)\n}\n","// Client-side redaction for error text — a faithful port of the server's\n// errortracking scrub (o11y pkg/modules/errortracking/implerrortracking/scrub.go),\n// applied BEFORE anything leaves the browser. Two layers, default-secure:\n//\n// - Secret shapes are ALWAYS redacted (sk-… keys, bearer/JWT tokens, DB DSNs,\n// PANs, cloud keys). There is no mode that ships a secret off-device.\n// - PII (email/IP) is scrubbed UNLESS capturePII is explicitly enabled.\n//\n// The server scrubs again — this is defense in depth, not a substitute — but the\n// point is that a Hanzo browser never emits a raw secret/email/IP in the first\n// place. Pure, no I/O.\n\nconst REDACTED = '[redacted]'\nconst EMAIL_MARK = '[email]'\nconst IP_MARK = '[ip]'\n\n// Secret patterns mirror scrub.go's secretPatterns. Order matters (broad DSN/PAN\n// rules run last). All are applied unconditionally.\nconst SECRET_PATTERNS: RegExp[] = [\n /-----BEGIN[ A-Z]*PRIVATE KEY-----[\\s\\S]*?-----END[ A-Z]*PRIVATE KEY-----/g,\n /eyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{6,}\\.[A-Za-z0-9_-]{6,}/g, // JWT\n /\\bbearer\\s+[A-Za-z0-9._~+/-]{12,}=*/gi, // bearer token\n /\\b(?:sk|pk|rk)-[A-Za-z0-9]{2,}-?[A-Za-z0-9]{12,}/g, // openai-style\n /\\b(?:sk|pk)_(?:live|test)_[A-Za-z0-9]{16,}/g, // stripe\n /\\bhk-[A-Za-z0-9]{16,}/g, // hanzo key\n /\\bAKIA[0-9A-Z]{16}\\b/g, // aws access key id\n /\\bASIA[0-9A-Z]{16}\\b/g, // aws sts key id\n /\\bAIza[0-9A-Za-z_-]{20,}/g, // google api key\n /\\bgh[posru]_[A-Za-z0-9]{20,}/g, // github token\n /\\bxox[baprs]-[A-Za-z0-9-]{10,}/g, // slack token\n // Creds in a URL/DSN. The repetition is BOUNDED on purpose: the unbounded form\n // ([^\\s:@/]+:[^\\s@/]+@) backtracks quadratically on colon-rich text with no\n // terminating '@' — an HTML error page pasted into an error message took 4.9s\n // at 32KB and >60s at 128KB, freezing the main thread from inside captureError.\n // Real userinfo is far below these caps, so bounding costs nothing.\n /[a-zA-Z][a-zA-Z0-9+.-]{0,32}:\\/\\/[^\\s:@/]{1,256}:[^\\s@/]{1,256}@/g,\n]\n\n/** Candidate card numbers. Gated by Luhn below — the bare digit-run pattern is a\n * false-positive cannon that redacts every millisecond epoch, order id and\n * phone number it sees (\"request 1753468800000 timed out\" became\n * \"request [redacted]timed out\"), which destroys the readability of the very\n * error messages this client exists to deliver. */\nconst RE_PAN = /\\b(?:\\d[ -]?){13,19}\\b/g\n\n/** luhn reports whether a digit string satisfies the Luhn checksum. Every real\n * card number does, so gating redaction on it removes the false positives\n * WITHOUT introducing a false negative — the safe direction for a redactor. */\nfunction luhn(digits: string): boolean {\n let sum = 0\n let alt = false\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = digits.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/** redactPAN removes digit runs that actually check out as card numbers. */\nfunction redactPAN(s: string): string {\n return s.replace(RE_PAN, (m) => {\n const digits = m.replace(/[ -]/g, '')\n if (digits.length < 13 || digits.length > 19) return m\n return luhn(digits) ? REDACTED : m\n })\n}\n\n// Bounded to the RFC 5321 maxima (local-part 64, domain 255) for the same reason\n// as the creds-in-URL rule: the unbounded form backtracks quadratically across a\n// long run of local-part-legal characters that never reaches an '@' — measured at\n// 20ms on an 8KB worst case, on the main thread, per captured error. No real\n// address is excluded by these caps.\nconst RE_EMAIL = /[A-Za-z0-9._%+-]{1,64}@[A-Za-z0-9.-]{1,255}\\.[A-Za-z]{2,24}/g\nconst RE_IPV4 = /\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b/g\nconst RE_IPV6 = /\\b(?:[0-9A-Fa-f]{1,4}:){2,7}[0-9A-Fa-f]{1,4}\\b/g\n\n// A CREDENTIAL IN A QUERY PARAM HAS NO SHAPE TO MATCH.\n//\n// Every pattern above recognises a secret by what it LOOKS like — a JWT's three\n// dots, `sk-`, `AKIA`, `ghp_`. An OAuth `code`, a `state`, a password-reset\n// nonce and an invite token are opaque random strings, indistinguishable from a\n// page id, so none of them match and all of them survive.\n//\n// That matters because the client stamps `url: window.location.href` on EVERY\n// event, not just pageviews. So one visit to `/callback?code=…&state=…` puts a\n// live authorization code on the wire, once per event, in cleartext — and the\n// code is exchangeable until it is redeemed.\n//\n// The fix is to redact by the NAME the value is filed under rather than by the\n// value's shape, which is the only signal available for an opaque token. The\n// name half is bounded (`{1,32}`) and the value half stops at the first\n// separator, so neither half can backtrack across a long string — the same\n// discipline the creds-in-URL pattern above documents.\nconst CREDENTIAL_PARAMS = [\n 'code', 'state', 'token', 'access_token', 'id_token', 'refresh_token',\n 'auth', 'authorization', 'secret', 'client_secret', 'password', 'passwd', 'pwd',\n 'api_key', 'apikey', 'key', 'session', 'session_id', 'sid',\n 'sig', 'signature', 'nonce', 'otp', 'invite', 'invitation',\n 'reset_token', 'confirmation_token', 'magic', 'ticket', 'assertion',\n]\nconst RE_CREDENTIAL_PARAM = new RegExp(\n '([?&#;](?:' + CREDENTIAL_PARAMS.join('|') + ')=)[^&#;\\\\s]{1,4096}',\n 'gi',\n)\n\n/** redactCredentialParams removes the VALUE of any query parameter whose NAME\n * says it carries a credential, leaving the name so the URL still reads. */\nexport function redactCredentialParams(s: string): string {\n return s.replace(RE_CREDENTIAL_PARAM, (_m, prefix: string) => prefix + REDACTED)\n}\n\n// A 256-bit secret written as unpadded base64url is exactly 43 characters of\n// [A-Za-z0-9_-] — the shape of a share-link secret, and of any other opaque key\n// minted the same way. The run must stand alone — nothing of the same alphabet\n// on either side, a percent-escape such as the `%23` of an encoded `#` counting\n// as a boundary — so it never fires inside a longer token, and it must mix upper\n// and lower case, which a random 32 bytes does with near certainty and an\n// ordinary word or slug does not. No lookbehind, so it runs on every engine the\n// client ships to.\nconst RE_SECRET43 = /(^|[^A-Za-z0-9_-]|%[0-9A-Fa-f]{2})((?=[A-Za-z0-9_-]{0,42}[a-z])(?=[A-Za-z0-9_-]{0,42}[A-Z])[A-Za-z0-9_-]{43})(?![A-Za-z0-9_-])/g\n\n/** redactSecrets removes known secret shapes. Always applied. */\nexport function redactSecrets(s: string): string {\n s = redactCredentialParams(s)\n for (const re of SECRET_PATTERNS) s = s.replace(re, REDACTED)\n s = s.replace(RE_SECRET43, (_m, lead: string) => lead + REDACTED)\n return redactPAN(s)\n}\n\n/** withoutFragment returns a URL with its fragment removed. A browser never\n * sends the fragment to any server — it is where an app keeps what must stay\n * on the device, a share link's secret among them — so the client does not\n * send it either. */\nexport function withoutFragment(url: string): string {\n const at = url.indexOf('#')\n return at < 0 ? url : url.slice(0, at)\n}\n\n/** scrubPII masks emails and IPs. Applied unless PII capture is enabled. */\nexport function scrubPII(s: string): string {\n s = s.replace(RE_EMAIL, EMAIL_MARK)\n s = s.replace(RE_IPV6, IP_MARK)\n s = s.replace(RE_IPV4, IP_MARK)\n return s\n}\n\n/** Longest free-text field this module will scrub. Every pattern here is a regex\n * run synchronously on the main thread, and the input is attacker-influenced —\n * `throw new Error(await res.text())` against an HTML error page is a one-line\n * way to hand us 128KB. Bounding the INPUT bounds the work regardless of which\n * pattern is pathological. 8KB is far beyond any real error message. */\nexport const MAX_SCRUB_LEN = 8192\n\n/** truncate caps a string at MAX_SCRUB_LEN, marking that it was cut so a reader\n * never mistakes a truncated message for the whole one. */\nexport function truncate(s: string, max = MAX_SCRUB_LEN): string {\n return s.length > max ? s.slice(0, max) + '… [truncated]' : s\n}\n\n/** scrubText applies the redaction policy to a free-text field. Input is capped\n * first: unbounded text is a denial-of-service surface, not just a size problem. */\nexport function scrubText(s: string | undefined, capturePII = false): string {\n if (!s) return s ?? ''\n s = truncate(s)\n s = redactSecrets(s)\n if (!capturePII) s = scrubPII(s)\n return s\n}\n","// Pure throwable parsing: coerce anything thrown into {name, message, stack} and\n// parse a browser stack into frames. No I/O, no globals.\n\nimport type { SentryFrame } from './types'\n\nconst MAX_FRAMES = 50\n/** Max stack lines examined, and max length of a line worth examining. Guards the\n * frame regexes against a hostile `stack` string (see framesFromStack). */\nconst MAX_LINES = 500\nconst MAX_LINE_LEN = 2048\n\nconst V8_FRAME = /^\\s*at\\s+(?:(.+?)\\s+\\()?(?:(.+?):(\\d+):(\\d+)|([^)]+))\\)?\\s*$/\nconst MOZ_FRAME = /^\\s*(?:(.*?)@)?(.+?):(\\d+):(\\d+)\\s*$/\n\n/** inApp marks a frame as the app's own code (vs vendor/runtime) for grouping. */\nfunction inApp(file: string): boolean {\n if (!file) return false\n return !(\n file.includes('node_modules') ||\n file.startsWith('webpack-internal') ||\n file.startsWith('webpack://') ||\n file.startsWith('chrome-extension://') ||\n file.startsWith('moz-extension://')\n )\n}\n\n/**\n * framesFromStack parses a browser Error.stack into Sentry frames, OLDEST-FIRST\n * (Sentry orders caller->callee; the crash site is last — matching the server's\n * pickCrashFrame). Handles both V8 (\"at fn (file:li:co)\") and\n * Firefox/Safari (\"fn@file:li:co\"). Unparseable lines are skipped.\n */\nexport function framesFromStack(stack: string | undefined): SentryFrame[] {\n if (!stack) return []\n // Both frame regexes use lazy nested quantifiers, which backtrack badly on a\n // long line that never matches. A stack is attacker-influenced (a thrown value\n // can carry any `stack` string), so bound the work: skip absurd lines and stop\n // after MAX_LINES. Only the innermost MAX_FRAMES are kept anyway.\n const lines = stack.split('\\n', MAX_LINES)\n const frames: SentryFrame[] = []\n for (const raw of lines) {\n if (raw.length > MAX_LINE_LEN) continue\n const line = raw.trimEnd()\n if (!line) continue\n // Header lines like \"TypeError: x is not a function\" match neither frame\n // regex (no \"at \" prefix, no trailing :line:col) and are skipped naturally.\n let fn: string | undefined\n let file = ''\n let lineno = 0\n let colno = 0\n const v = V8_FRAME.exec(line)\n if (v) {\n fn = v[1]\n if (v[2]) {\n file = v[2]\n lineno = Number(v[3]) || 0\n colno = Number(v[4]) || 0\n } else {\n file = (v[5] || '').trim()\n }\n } else {\n const f = MOZ_FRAME.exec(line)\n if (!f) continue\n fn = f[1]\n file = f[2]\n lineno = Number(f[3]) || 0\n colno = Number(f[4]) || 0\n }\n if (!file && !fn) continue\n frames.push({\n function: fn || '<anonymous>',\n filename: file,\n abs_path: file,\n lineno,\n colno,\n in_app: inApp(file),\n })\n }\n // Reverse to oldest-first and cap to the innermost MAX_FRAMES.\n frames.reverse()\n if (frames.length > MAX_FRAMES) return frames.slice(frames.length - MAX_FRAMES)\n return frames\n}\n\n/** normalizeError coerces an unknown throwable into {name, message, stack}. */\nexport function normalizeError(err: unknown): { name: string; message: string; stack?: string } {\n if (err instanceof Error) {\n // `name`, `message` and `stack` are ordinary getters, and the thrown object is\n // the least trustworthy input this library handles — any of them may throw.\n // Losing the whole report to a hostile getter is not acceptable.\n const name = read(err, 'name')\n const message = read(err, 'message')\n const stack = read(err, 'stack')\n return {\n name: typeof name === 'string' && name ? name : 'Error',\n message: typeof message === 'string' && message ? message : str(err),\n stack: typeof stack === 'string' ? stack : undefined,\n }\n }\n if (typeof err === 'string') return { name: 'Error', message: err }\n try {\n return { name: 'Error', message: JSON.stringify(err) ?? str(err) }\n } catch {\n return { name: 'Error', message: str(err) }\n }\n}\n\n/** read pulls a property off a possibly-hostile value without letting a throwing\n * getter escape. */\nfunction read(o: unknown, k: string): unknown {\n try {\n return (o as Record<string, unknown>)[k]\n } catch {\n return undefined\n }\n}\n\n/** str coerces to a string without letting a throwing toString/Symbol.toPrimitive\n * escape. */\nfunction str(v: unknown): string {\n try {\n return String(v)\n } catch {\n return '[unstringifiable]'\n }\n}\n","/*! anon.js — THE anonymous-identity chain. ONE implementation, two distributions.\n *\n * One browser is ONE person on every Hanzo surface, whichever client a page\n * happens to have loaded. There were once three implementations writing TWO keys —\n * `hz_anon_id` and `hz_id` — so the same visitor was several people depending on\n * which snippet the surface shipped.\n *\n * The two call sites:\n * 1. src/storage.ts — the bundled npm client; IMPORTS this file.\n * 2. hanzoai/cloud apps/analytics/tag.js — the tag served at\n * /v1/event.js; vendors this file and its tag.go serves the marked region\n * with the tag as one asset, so cloud holds no second copy either.\n *\n * (2) has no bundler and cannot import anything, which is why the chain lives in a\n * file that is plain ES5 rather than in a .ts: the region between the BEGIN and END\n * markers is COPIED VERBATIM. Keep it ES5, dependency-free, `hz`-prefixed (it is\n * spliced into other people's scopes) and unformatted — a reformat here is a diff\n * against the vendored copy. After editing, resync that copy:\n *\n * curl -fsSL https://unpkg.com/@hanzo/event/src/anon.js -o apps/analytics/anon.js\n */\n\n/* ── BEGIN hz anon chain — copied VERBATIM into hanzoai/cloud ──────────────── */\n\n/** The ONE anonymous-id key, on every surface and in every distribution.\n *\n * It names what it is, not who ships it: this value is visible to anyone who opens\n * their own cookie jar, and a vendor's name has no business there. Identity is IAM's\n * concern whether or not the visitor has said who they are. */\nvar HZ_ANON_KEY = 'iam-anon-id'\n\n/** Keys an id may already be living under. READ, never written.\n *\n * Each was canonical once — `hz_anon_id` most recently, and `hz_id` before it, when a\n * no-build tag wrote a second identity space and one page could hold two people.\n * Adopting an id already in the wild is what makes this a rename rather than an\n * erasure: minting over one detaches a returning visitor from their own history.\n * They are never written, so they leave with the cookies that hold them. */\nvar HZ_ANON_ADOPT = ['hz_anon_id', 'hz_id']\n\n/** The registrable domain the cookie is scoped to, so docs, cloud, console,\n * studio, pay, id and www all read the ONE id. localStorage cannot do this: it is\n * ORIGIN-scoped, which is what made one journey arrive as several strangers. */\nvar HZ_ANON_DOMAIN = 'hanzo.ai'\n\n/** Two years, rewritten on every read, so the cookie rolls forward with the\n * visitor instead of expiring two years after first touch. Safari caps a\n * SCRIPT-written cookie at 7 days no matter what this says, so the rewrite is\n * what keeps a returning Safari visitor: each read re-arms the 7-day window. */\nvar HZ_ANON_MAX_AGE = 2 * 365 * 24 * 60 * 60\n\n/** Last resort for a browser that refuses cookies AND localStorage: without it\n * every event in a page load would mint an id of its own. */\nvar hzAnonMemo\n\n/**\n * hzUuidv7 mints a time-ordered UUIDv7 (RFC 9562 §5.7) for `now` in epoch ms.\n *\n * It has to be v7, and this is the only minter any distribution may use. The\n * session rollups on the event plane derive a session's start instant FROM THE ID\n * and admit only ids whose version nibble is 7, so a crypto.randomUUID() (v4) id\n * is not merely unordered there — it is DISCARDED, silently, and the rollup stays\n * empty. Without crypto only the ENTROPY degrades; the shape is always a valid v7.\n */\nfunction hzUuidv7(now) {\n var b = new Uint8Array(16)\n var i\n var c = typeof crypto !== 'undefined' ? crypto : undefined\n if (c && typeof c.getRandomValues === 'function') c.getRandomValues(b)\n else for (i = 0; i < 16; i++) b[i] = (Math.random() * 256) | 0\n var t = Math.floor(now === undefined ? Date.now() : now)\n for (i = 5; i >= 0; i--) {\n b[i] = t % 256\n t = Math.floor(t / 256)\n }\n b[6] = 0x70 | (b[6] & 0x0f) // version 7\n b[8] = 0x80 | (b[8] & 0x3f) // variant 0b10\n var h = ''\n for (i = 0; i < 16; i++) {\n h += (b[i] + 0x100).toString(16).slice(1)\n if (i === 3 || i === 5 || i === 7 || i === 9) h += '-'\n }\n return h\n}\n\n/** The cookie jar, or null wherever there is no document to read one from. */\nfunction hzAnonJar() {\n try {\n if (typeof document === 'undefined' || typeof document.cookie !== 'string') return null\n return document\n } catch (e) {\n return null // sandboxed frame with an opaque origin\n }\n}\n\n/** localStorage, or null when the browser refuses it (Safari private mode). */\nfunction hzAnonStore() {\n try {\n if (typeof window === 'undefined' || !window.localStorage) return null\n return window.localStorage\n } catch (e) {\n return null\n }\n}\n\n/** One stored value, or '' — a jar can read as well as refuse to. */\nfunction hzAnonItem(store, name) {\n try {\n return (store && store.getItem(name)) || ''\n } catch (e) {\n return ''\n }\n}\n\n/** The value of cookie `name`, or ''. */\nfunction hzAnonCookie(name) {\n var d = hzAnonJar()\n if (!d) return ''\n var parts = d.cookie.split(';')\n for (var i = 0; i < parts.length; i++) {\n var eq = parts[i].indexOf('=')\n if (eq < 0 || parts[i].slice(0, eq).trim() !== name) continue\n var v = parts[i].slice(eq + 1).trim()\n if (!v) continue\n try {\n return decodeURIComponent(v)\n } catch (e) {\n return v // not percent-encoded — take it as written\n }\n }\n return ''\n}\n\n/** Writes `name` on the registrable domain, for as long as the browser allows. */\nfunction hzAnonWrite(name, value) {\n var d = hzAnonJar()\n if (!d) return\n var host = ''\n var secure = false\n try {\n if (typeof window !== 'undefined' && window.location) {\n host = window.location.hostname || ''\n // A Secure cookie is refused outright by a non-secure origin, which would\n // strand http://localhost dev on the localStorage path.\n secure = window.location.protocol === 'https:'\n }\n } catch (e) {\n /* location unreachable — write a host-only, non-secure cookie */\n }\n // encodeURIComponent leaves a UUID byte-identical while making any value that is\n // not one unable to forge a `;` and inject an attribute.\n var c = name + '=' + encodeURIComponent(value)\n c += '; Path=/; Max-Age=' + HZ_ANON_MAX_AGE + '; SameSite=Lax'\n // Off hanzo.ai (localhost, previews, other registrable domains) the attribute\n // would be rejected and the whole cookie dropped, so it stays host-only there.\n // Prefixing both sides with '.' matches the domain itself and its subdomains\n // while refusing a suffix that merely ends in the same letters (evilhanzo.ai).\n if (('.' + host).slice(-(HZ_ANON_DOMAIN.length + 1)) === '.' + HZ_ANON_DOMAIN) {\n c += '; Domain=' + HZ_ANON_DOMAIN\n }\n if (secure) c += '; Secure'\n try {\n d.cookie = c\n } catch (e) {\n /* cookies refused — localStorage still carries the id */\n }\n}\n\n/**\n * hzAnonId returns the stable anonymous id for this browser, '' during SSR.\n *\n * Resolution is strictly ADDITIVE — every id that already exists is ADOPTED, and\n * only a browser holding none of them is given a new one:\n *\n * cookie · localStorage iam-anon-id · adopted keys · in-memory · mint\n *\n * Minting over an id resets a returning visitor and detaches them from their own\n * history, so the order is the migration: the cookie is the shared home, the two\n * localStorage keys are what the three implementations wrote before it existed,\n * and each is read until nothing is left to adopt.\n *\n * localStorage keeps being written, so a rollback finds everyone where it left\n * them, and a browser that refuses cookies still holds one id per origin.\n */\n/**\n * hzAnonAdopted returns an id already living under a key that used to be canonical,\n * from the cookie jar first — that is the copy shared across subdomains, so a visitor\n * who arrived on one host is the same person on the next.\n */\nfunction hzAnonAdopted(s) {\n for (var i = 0; i < HZ_ANON_ADOPT.length; i++) {\n var id = hzAnonCookie(HZ_ANON_ADOPT[i]) || hzAnonItem(s, HZ_ANON_ADOPT[i])\n if (id) return id\n }\n return ''\n}\n\nfunction hzAnonId() {\n if (typeof window === 'undefined') return '' // SSR / prerender: no browser to identify\n var s = hzAnonStore()\n var id =\n hzAnonCookie(HZ_ANON_KEY) ||\n hzAnonItem(s, HZ_ANON_KEY) ||\n hzAnonAdopted(s) ||\n hzAnonMemo ||\n hzUuidv7()\n hzAnonMemo = id\n hzAnonWrite(HZ_ANON_KEY, id)\n try {\n if (s && s.getItem(HZ_ANON_KEY) !== id) s.setItem(HZ_ANON_KEY, id)\n } catch (e) {\n /* quota exhausted, or a private-mode jar that reads but refuses writes */\n }\n return id\n}\n\n/**\n * hzAnonAdopt makes `id` this browser's anonymous id, replacing whatever it held.\n *\n * A visitor who followed a link from another Hanzo host arrives carrying the id that\n * host minted; keeping the local one splits one journey into two strangers. The\n * caller has already checked the shape.\n */\nfunction hzAnonAdopt(id) {\n hzAnonMemo = id\n hzAnonWrite(HZ_ANON_KEY, id)\n try {\n var s = hzAnonStore()\n if (s) s.setItem(HZ_ANON_KEY, id)\n } catch (e) {\n /* quota exhausted or a read-only jar — the cookie and memo still carry it */\n }\n}\n\n/* ── END hz anon chain ─────────────────────────────────────────────────────── */\n\nexport { hzAnonId, hzAnonAdopt, hzUuidv7 }\n","// SSR-safe browser storage for stable identifiers and first-touch state. Every\n// accessor no-ops (returns undefined) when there is no window/localStorage, so the\n// client imports cleanly in a Next.js server component.\n//\n// The anonymous id is the one value that must outlive an ORIGIN, and it is also\n// the one value the OTHER two distributions must agree with, so its chain lives in\n// ./anon.js and this file only calls it. Everything else here stays origin-local.\n\nimport { hzAnonAdopt, hzAnonId } from './anon.js'\nimport type { Attribution, Cohort } from './types'\nimport { uuidv7 } from './uid'\n\nconst KEY = {\n session: 'hz_session',\n firstTouch: 'hz_first_touch',\n cohort: 'hz_cohort',\n} as const\n\n/** 30-minute inactivity window defines a session (PostHog/GA convention). */\nconst SESSION_TTL_MS = 30 * 60 * 1000\n\nfunction ls(): Storage | undefined {\n try {\n if (typeof window === 'undefined' || !window.localStorage) return undefined\n return window.localStorage\n } catch {\n return undefined // Safari private mode / blocked storage\n }\n}\n\n/**\n * Stable anonymous id, shared by every *.hanzo.ai surface AND by every Hanzo\n * client on the page — the npm client and the hosted tag both run the one\n * chain in ./anon.js, so which snippet a surface loaded no longer decides who the\n * visitor is.\n *\n * It lives in a first-party cookie on the registrable domain because localStorage\n * is ORIGIN-scoped: docs, cloud and console each minted their own id for the same\n * person, so one marketing → docs → signup → checkout journey arrived as several\n * strangers — 463 anonymous identities carried 545 events in a week, about 1.2\n * events each.\n */\nexport function anonId(): string | undefined {\n return hzAnonId() || undefined // '' during SSR / prerender\n}\n\ninterface SessionState {\n id: string\n last: number\n}\n\n/**\n * Current session id, rotated after SESSION_TTL_MS of inactivity.\n *\n * Minted at `now`, so the v7 timestamp the id carries IS the session's start\n * instant — which is what the session rollups partition and order on. Passing the\n * caller's clock rather than reading Date.now() again keeps the id's embedded time\n * and the recorded `last` from disagreeing.\n */\nexport function sessionId(now = Date.now()): string | undefined {\n const s = ls()\n if (!s) return undefined\n let state: SessionState | null = null\n try {\n state = JSON.parse(s.getItem(KEY.session) || 'null')\n } catch {\n state = null\n }\n if (!state || now - state.last > SESSION_TTL_MS) {\n state = { id: uuidv7(now), last: now }\n } else {\n state.last = now\n }\n s.setItem(KEY.session, JSON.stringify(state))\n return state.id\n}\n\n/** Make `id` the current session, as if it had begun now. The session a link\n * carries is the one the visitor is already in, so the journey stays one session\n * across the hop instead of splitting at the host boundary. */\nexport function adoptSession(id: string, now = Date.now()): void {\n const s = ls()\n if (s) s.setItem(KEY.session, JSON.stringify({ id, last: now }))\n}\n\n/** Make `id` the browser's anonymous id, replacing the one it held. */\nexport function adoptAnonId(id: string): void {\n hzAnonAdopt(id)\n}\n\n/** Read the persisted first-touch attribution. */\nexport function getFirstTouch(): Attribution | undefined {\n const s = ls()\n if (!s) return undefined\n try {\n const v = s.getItem(KEY.firstTouch)\n return v ? (JSON.parse(v) as Attribution) : undefined\n } catch {\n return undefined\n }\n}\n\n/** Persist first-touch attribution ONCE — never overwrite an existing record. */\nexport function setFirstTouchOnce(a: Attribution): Attribution {\n const s = ls()\n const existing = getFirstTouch()\n if (existing) return existing\n if (s) s.setItem(KEY.firstTouch, JSON.stringify(a))\n return a\n}\n\n/** Read persisted cohort dimensions. */\nexport function getCohort(): Cohort | undefined {\n const s = ls()\n if (!s) return undefined\n try {\n const v = s.getItem(KEY.cohort)\n return v ? (JSON.parse(v) as Cohort) : undefined\n } catch {\n return undefined\n }\n}\n\n/** Merge + persist cohort dimensions (signupWeek set once). */\nexport function mergeCohort(patch: Cohort): Cohort {\n const s = ls()\n const cur = getCohort() || {}\n const next: Cohort = {\n signupWeek: cur.signupWeek || patch.signupWeek,\n channel: patch.channel || cur.channel,\n refCode: cur.refCode || patch.refCode,\n }\n if (s) s.setItem(KEY.cohort, JSON.stringify(next))\n return next\n}\n","// Cross-domain visitor continuity.\n//\n// Cookies and localStorage stop at the registrable domain, so a visitor who goes\n// hanzo.ai -> hanzo.id (sign-in) -> back arrived as separate people on each host, and\n// the journey across the sign-in redirect could not be read. A link between two\n// Hanzo hosts therefore carries the visitor's identity in three short query\n// parameters, and the destination adopts them before its first pageview and\n// removes them from the address bar.\n//\n// hz_aid anonymous id hz_sid session id hz_ft first-touch attribution\n//\n// They are appended ONLY when the destination host belongs to a brand in ORG_DOMAIN:\n// an id handed to a host outside the table would be handed to a stranger.\n\nimport { orgOf } from './org'\nimport type { Attribution } from './types'\n\nexport const LINK_PARAMS = { anon: 'hz_aid', session: 'hz_sid', firstTouch: 'hz_ft' } as const\n\n/** Ids are v7 UUIDs; anything else in a URL is someone else's input and is refused. */\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\n\nexport const isId = (v: string | null | undefined): v is string => !!v && UUID.test(v)\n\n/** What a link carries. Any field may be absent. */\nexport interface LinkState {\n anonId?: string\n sessionId?: string\n firstTouch?: Attribution\n}\n\n/** First touch as a compact tuple: utm source, medium, campaign, term, content, refCode,\n * referrer, channel. Short because it rides a URL; a tuple because keys cost bytes. */\nexport function encodeFirstTouch(a: Attribution): string {\n return JSON.stringify([\n a.utm.source, a.utm.medium, a.utm.campaign, a.utm.term, a.utm.content,\n a.refCode, a.referrer, a.channel,\n ].map((v) => v ?? ''))\n}\n\nexport function decodeFirstTouch(raw: string | null | undefined): Attribution | undefined {\n if (!raw || raw.length > 1024) return undefined\n try {\n const t: unknown = JSON.parse(raw)\n if (!Array.isArray(t) || t.length !== 8 || t.some((v) => typeof v !== 'string')) return undefined\n const [source, medium, campaign, term, content, refCode, referrer, channel] = t as string[]\n const u = (v: string) => v || undefined\n return {\n utm: { source: u(source), medium: u(medium), campaign: u(campaign), term: u(term), content: u(content) },\n refCode: u(refCode),\n referrer: u(referrer),\n channel: u(channel),\n }\n } catch {\n return undefined\n }\n}\n\n/** linkUrl returns `url` with the visitor's identity appended when its host is\n * Hanzo-owned and is not `fromHost`; otherwise `url` unchanged. Relative URLs\n * resolve against `base`. Never throws. */\nexport function linkUrl(url: string, state: LinkState, fromHost: string, base?: string): string {\n let u: URL\n try {\n u = new URL(url, base)\n } catch {\n return url\n }\n if (u.protocol !== 'https:' && u.protocol !== 'http:') return url\n if (!orgOf(u.hostname) || u.hostname === fromHost) return url\n const set = (k: string, v: string | undefined) => v && u.searchParams.set(k, v)\n if (isId(state.anonId)) set(LINK_PARAMS.anon, state.anonId)\n if (isId(state.sessionId)) set(LINK_PARAMS.session, state.sessionId)\n if (state.firstTouch) set(LINK_PARAMS.firstTouch, encodeFirstTouch(state.firstTouch))\n return u.toString()\n}\n\n/** readLink parses what a link carried out of a location.search value. Invalid\n * values are dropped, not repaired. */\nexport function readLink(search: string): LinkState {\n const q = new URLSearchParams(search || '')\n const a = q.get(LINK_PARAMS.anon)\n const s = q.get(LINK_PARAMS.session)\n return {\n anonId: isId(a) ? a : undefined,\n sessionId: isId(s) ? s : undefined,\n firstTouch: decodeFirstTouch(q.get(LINK_PARAMS.firstTouch)),\n }\n}\n\n/** stripLink returns the path, query and hash of `href` without the link parameters, or\n * undefined when there were none. */\nexport function stripLink(href: string): string | undefined {\n const u = new URL(href)\n let hit = false\n for (const k of Object.values(LINK_PARAMS)) {\n if (u.searchParams.has(k)) {\n u.searchParams.delete(k)\n hit = true\n }\n }\n return hit ? u.pathname + u.search + u.hash : undefined\n}\n","{\n \"name\": \"@hanzo/event\",\n \"version\": \"0.3.49\",\n \"description\": \"Hanzo Event \\u2014 the ONE telemetry client. Emits pageview/event/identify/group to the Hanzo Cloud event stream (POST /v1/event), AND reports errors to Sentry as real Sentry envelopes \\u2014 the error plane needs a DSN, without one nothing reaches Sentry. First-touch attribution, beacon-on-unload, auto error capture, client-side secret/PII scrubbing, a shared event + goal vocabulary. Subsumes @sentry.\",\n \"publishConfig\": {\n \"registry\": \"https://registry.npmjs.org/\",\n \"access\": \"public\",\n \"scope\": \"@hanzo\"\n },\n \"author\": \"Hanzo AI <dev@hanzo.ai>\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"sideEffects\": false,\n \"files\": [\n \"dist\",\n \"src\",\n \"README.md\",\n \"TAXONOMY.md\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/hanzoai/ui.git\",\n \"directory\": \"pkg/event\"\n },\n \"keywords\": [\n \"analytics\",\n \"product-analytics\",\n \"telemetry\",\n \"events\",\n \"error-tracking\",\n \"sentry\",\n \"attribution\",\n \"funnel\",\n \"hanzo\"\n ],\n \"scripts\": {\n \"prepublishOnly\": \"node ../../scripts/guard-publish.mjs\",\n \"build\": \"tsup && tsc --emitDeclarationOnly --declaration --outDir dist && node ../../scripts/dts.mjs\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"typecheck\": \"tsc --noEmit -p tsconfig.json\",\n \"clean\": \"rm -rf dist\"\n },\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./react\": {\n \"import\": {\n \"types\": \"./dist/react.d.ts\",\n \"default\": \"./dist/react.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/react.d.cts\",\n \"default\": \"./dist/react.cjs\"\n }\n }\n },\n \"peerDependencies\": {\n \"react\": \">=19.2.8\"\n },\n \"peerDependenciesMeta\": {\n \"react\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@types/node\": \"catalog:\",\n \"@types/react\": \"catalog:\",\n \"react\": \"catalog:\",\n \"tsup\": \"catalog:\",\n \"typescript\": \"catalog:\",\n \"vitest\": \"catalog:\"\n },\n \"dependencies\": {\n \"@hanzo/events\": \"catalog:\"\n }\n}\n","// The library version, stamped on every event (`libraryVersion`) and on the\n// Sentry `sdk` block. It lives alone so `sentry.ts` can read it without importing\n// `core.ts` — core imports sentry, so the reverse would be an import cycle.\n//\n// Read from package.json rather than restated, because a version restated is a\n// version that drifts: 0.3.38 and 0.3.39 both shipped while this file still said\n// 0.3.37, so every event those builds sent named a library that was two releases\n// behind. `resolveJsonModule` inlines the literal at build time, and tsup shakes\n// the rest of the manifest out.\nimport { version } from '../package.json'\n\nexport const VERSION: string = version\n","// The framework-agnostic event client. ONE API surface over TWO orthogonal\n// planes, sharing one session and one identity:\n//\n// 1. EVENT STREAM — buffered pageview/event/identify/group, flushed as ONE\n// batch to the Hanzo Cloud entry point:\n// POST {host}/v1/event body: { batch: [Event, …] } -> { accepted, dropped }\n// Cloud resolves the tenant server-side (validated session, or the signed\n// publishable key) and stamps it; the client NEVER sends the org.\n//\n// Errors ride the same pipe: a captured exception is ONE event of type 'error'\n// carrying {type, message, frames|stack, handled} plus release, environment,\n// site, product and level. The server files it on the error plane and groups it\n// into an issue. There is no second endpoint, DSN or envelope.\n//\n// Auth is orthogonal — the SAME body to the SAME endpoint, differing only in how the\n// caller proves its tenant:\n//\n// • cookie/session app (host:'') — same-origin credentials ride the request.\n// • bearer app (getToken) — Authorization: Bearer <jwt>.\n// • publishable-key app (ingestKey: 'pk-…') — ?ingest_key=pk-… on the query, on\n// the fetch and the beacon alike, with a text/plain body. Write-only and safe\n// to ship in a bundle; the endpoint resolves it to an org server-side. The query\n// is the carrier neither send needs a header for, which is what keeps both\n// CORS-simple and therefore sendable from a customer's own origin.\n//\n// The wire is the canonical `Event` (== the cloud CaptureEvent).\n\nimport {\n parseAttribution,\n hasAttribution,\n deriveChannel,\n} from './attribution'\nimport { keyForPage } from './org'\nimport { PAGEVIEW } from './events'\nimport { scrubText, withoutFragment } from './scrub'\nimport { framesFromStack, normalizeError as normalizeThrowable } from './throwable'\nimport {\n adoptAnonId,\n adoptSession,\n anonId,\n sessionId,\n getFirstTouch,\n setFirstTouchOnce,\n getCohort,\n mergeCohort,\n} from './storage'\nimport { uuidv7 } from './uid'\nimport { linkUrl, readLink, stripLink } from './link'\nimport type {\n AnalyticsConfig,\n Attribution,\n CaptureErrorOptions,\n Cohort,\n EventKind,\n Exception,\n Transport,\n WireEvent,\n} from './types'\nimport { VERSION } from './version'\n\nexport { VERSION }\n\nconst EVENT_PATH = '/v1/event' // the ONE canonical ingestion entry point\nconst DEFAULT_HOST = 'https://api.hanzo.ai' // the one edge; cookie apps pass host:''\n// The beacon body's type. text/plain is CORS-SAFELISTED, which is the whole\n// property: a safelisted type makes the POST a SIMPLE request, and a simple\n// request needs no preflight. An unloading document does not get a second round\n// trip, so cross-origin a preflighted beacon is never sent at all. The endpoint reads\n// the raw body and dispatches on its first non-space byte, so the type names the\n// CORS class and nothing else.\nconst BEACON_CONTENT_TYPE = 'text/plain'\n\n/** readEnv reads an inlined build-time variable, guarded for SSR. */\nfunction readEnv(name: string): string | undefined {\n try {\n if (typeof process !== 'undefined' && process.env) return process.env[name] || undefined\n } catch {\n /* no process */\n }\n return undefined\n}\n\n/** appendQuery adds a single query param to a URL string — used to carry a\n * publishable key on either send (?ingest_key=…). */\nfunction appendQuery(url: string, key: string, value: string): string {\n return url + (url.includes('?') ? '&' : '?') + key + '=' + encodeURIComponent(value)\n}\n\n/** Normalize anything thrown (Error | string | unknown) into an Exception. */\n/** normalizeError adapts the hostile-input-safe normalizer (sentry.ts) to the\n * stream's Exception shape: a thrown object may define `name`/`message`/`stack`\n * as throwing getters. */\nfunction normalizeError(err: unknown): Exception {\n const n = normalizeThrowable(err)\n const frames = framesFromStack(n.stack)\n .slice(-50)\n .map((f) => ({ function: f.function, file: f.filename, line: f.lineno, column: f.colno }))\n return { type: n.name, message: n.message, stack: n.stack, frames }\n}\n\n// React Native defines a `window` but no `document` (and no `window.location`),\n// so `typeof window !== 'undefined'` alone took the browser path there and\n// `init()` threw on `window.location.search`. Requiring `document` makes RN read\n// as non-browser: `init()` returns early (skips attribution + the visibility/\n// unload listeners RN doesn't have), while `capture()`/`flush()` — which are NOT\n// gated on this and post through plain `fetch` — still emit. So the client is\n// inert-safe under SSR/Node and live on RN, without a second transport.\nconst isBrowser = () => typeof window !== 'undefined' && typeof document !== 'undefined'\n\n/** serializeBatch stringifies a batch, salvaging what it can. `properties` is\n * arbitrary caller data — a DOM node, a React synthetic event, an axios error are\n * all circular, and a getter on one can throw — so a whole batch must never be\n * lost to a single poisoned event. Falls back to per-event serialization, then to\n * keeping the event and dropping its properties. Returns null only when nothing\n * at all survives. */\nfunction serializeBatch(batch: WireEvent[]): string | null {\n try {\n return JSON.stringify({ batch })\n } catch {\n /* one bad event — salvage the rest below */\n }\n const parts: string[] = []\n for (const e of batch) {\n try {\n parts.push(JSON.stringify(e))\n } catch {\n try {\n // Keep the event (identity, session, type all matter); drop the payload\n // that could not be serialized, and say so rather than lying by omission.\n parts.push(JSON.stringify({ ...e, properties: { $unserializable: true } }))\n } catch {\n /* unsalvageable — drop this ONE event, never the batch */\n }\n }\n }\n return parts.length > 0 ? '{\"batch\":[' + parts.join(',') + ']}' : null\n}\n\n/** DefaultTransport: fetch(keepalive) for authenticated/normal sends;\n * navigator.sendBeacon for page-unload beacons.\n *\n * A publishable key rides the ?ingest_key query on BOTH, which is what keeps\n * both CORS-simple: the query is the one carrier neither send needs a header\n * for, and a simple request leaves the browser from any origin — permission is\n * asked to READ a cross-origin response, never to send one. That is what lets a\n * bundled client run on a customer's own page. A JWT is first-party by\n * construction, so it keeps Authorization and the session it travels with.\n *\n * `contentType` names the FETCH request's Content-Type (the error plane sets the\n * envelope type there, and keeps the header carrier with it). The beacon body is\n * always BEACON_CONTENT_TYPE: its type is a CORS class, not a payload\n * description, and a beacon that is not a simple request is never sent. */\nclass DefaultTransport implements Transport {\n send(\n url: string,\n body: string,\n opts: {\n beacon: boolean\n token?: string\n ingestKey?: string\n contentType?: string\n debug?: boolean\n },\n ): void {\n if (opts.beacon && isBrowser() && typeof navigator.sendBeacon === 'function') {\n const beaconUrl = opts.ingestKey ? appendQuery(url, 'ingest_key', opts.ingestKey) : url\n try {\n // The answer is whether the agent QUEUED the batch — false for a body past\n // the beacon size limit, or a full queue. Only a queued batch ends the\n // send; a refused one falls through to the keepalive fetch below.\n const queued = navigator.sendBeacon(\n beaconUrl,\n new Blob([body], { type: BEACON_CONTENT_TYPE }),\n )\n if (queued) return\n if (opts.debug) console.warn('[event] beacon refused, falling back to fetch')\n } catch {\n /* fall through to fetch */\n }\n }\n if (typeof fetch !== 'function') return\n // A publishable key makes the send a CORS SIMPLE request: the key rides the\n // query, the body is text/plain, and nothing asks for credentials. That is what\n // lets a bundled client run on a customer's own page — every send from there is\n // cross-origin, and an Authorization header or a JSON type preflights the POST\n // for an origin that cannot pass one. A JWT is first-party by construction, so\n // it keeps the header and the session it travels with, and so does the error\n // plane, which names its own envelope type.\n const simple = opts.ingestKey !== undefined && opts.contentType === undefined\n const headers: Record<string, string> = {\n 'Content-Type': simple ? BEACON_CONTENT_TYPE : (opts.contentType ?? 'application/json'),\n }\n const bearer = simple ? undefined : (opts.ingestKey ?? opts.token)\n if (bearer) headers.Authorization = `Bearer ${bearer}`\n void fetch(simple ? appendQuery(url, 'ingest_key', opts.ingestKey!) : url, {\n method: 'POST',\n headers,\n body,\n keepalive: true,\n credentials: simple ? 'omit' : 'include',\n })\n .then((res) => {\n // Telemetry loss never throws into the app — but silence is how this\n // client lost the fleet's errors in the first place. Under `debug`, say\n // so. A rejected ingest (the CORS allowlist 403s non-production origins,\n // so local dev NEVER reports) is otherwise indistinguishable from success.\n if (!res.ok && opts.debug) {\n console.warn('[event] ingest rejected', res.status, url.split('?')[0])\n }\n })\n .catch((e: unknown) => {\n if (opts.debug) console.warn('[event] ingest failed', url.split('?')[0], e)\n })\n }\n}\n\nexport class Analytics {\n private cfg: Required<\n Pick<AnalyticsConfig, 'product' | 'batchSize' | 'flushIntervalMs' | 'enabled' | 'captureErrors'>\n > &\n AnalyticsConfig\n private transport: Transport\n private queue: WireEvent[] = []\n private timer: ReturnType<typeof setTimeout> | null = null\n private personId?: string\n private attribution: Attribution = { utm: {} }\n private cohort: Cohort = {}\n private started = false\n /** The view pageview() last counted — path + location. */\n private counted?: string\n /** Guards against an error thrown *inside* the error path re-entering it. */\n private reentrant = false\n\n constructor(config: AnalyticsConfig) {\n this.cfg = {\n host: DEFAULT_HOST,\n batchSize: 20,\n flushIntervalMs: 5000,\n enabled: true,\n captureErrors: true,\n ...config,\n // The publishable key resolves from ONE live source, never a literal baked\n // beside the code. Most specific first:\n // 1. an explicit `ingestKey` in config;\n // 2. NEXT_PUBLIC_PUBLISHABLE_KEY, the inlined build-time env the fleet\n // carries end to end — KMS `deploy/PUBLISHABLE_KEY` -> the PUBLISHABLE_KEY\n // build-arg -> the NEXT_PUBLIC_ prefix Next inlines.\n //\n // 3. the org that owns the HOST this page is served from (`org.ts`).\n //\n // Step 3 fires only when a surface configured NOTHING, so it never overrides\n // the KMS chain above — it replaces going dark with reporting to the right\n // brand. That is what a static export needs: `output: export` inlines no env,\n // so before this the only way to report was to commit a key literal, and the\n // fleet grew one copy per site of a value with a single source.\n //\n // A surface no brand claims still has no key, and the edge REFUSES an\n // unattributed event (401 `ingest_key_required`) — the reserved `$public`\n // tenant that once caught keyless beacons is retired, and anonymous ingest is\n // refused at every edge on every brand host. So there is no quiet fallback to\n // rely on: an event lands in the org a credential names, or it does not land.\n ingestKey:\n config.ingestKey ?? readEnv('NEXT_PUBLIC_PUBLISHABLE_KEY') ?? keyForPage(),\n }\n this.transport = config.transport ?? new DefaultTransport()\n }\n\n /** adopt gives this client a credential it does not have. The key belongs to\n * the stream, not to whichever caller happened to ask for the handle first,\n * so a later caller carrying one hands it over. Present fields are never overwritten: the first caller's key stays. */\n adopt(config: AnalyticsConfig): void {\n if (config.ingestKey && !this.cfg.ingestKey) this.cfg.ingestKey = config.ingestKey\n if (config.getToken && !this.cfg.getToken) this.cfg.getToken = config.getToken\n }\n\n /** init is idempotent and browser-only for its side effects: capture first-touch\n * attribution, hydrate cohort, register the unload flush, and (unless opted out)\n * auto-capture unhandled errors. Safe to call from a React effect on every\n * render. */\n init(): void {\n if (this.started || !this.cfg.enabled) return\n this.started = true\n if (!isBrowser()) return\n\n // A link from another Hanzo host carries the visitor with it. Adopt it FIRST, so\n // the first pageview is already the same person, session and first touch.\n const linked = readLink(window.location.search)\n if (linked.anonId) adoptAnonId(linked.anonId)\n if (linked.sessionId) adoptSession(linked.sessionId)\n const clean = stripLink(window.location.href)\n if (clean !== undefined) {\n try {\n window.history.replaceState(window.history.state, '', clean)\n } catch {\n /* a sandboxed frame may refuse; the params are then simply visible */\n }\n }\n\n const parsed = parseAttribution(window.location.search, document.referrer)\n // The first touch the link carries is the visit's real origin. Without it this\n // host's own \"first touch\" would be the referring Hanzo page, which says nothing.\n const first = linked.firstTouch && !getFirstTouch() ? setFirstTouchOnce(linked.firstTouch) : undefined\n this.attribution =\n first ?? (hasAttribution(parsed) ? setFirstTouchOnce(parsed) : getFirstTouch() ?? parsed)\n this.cohort = mergeCohort({\n channel: this.attribution.channel ?? deriveChannel(this.attribution),\n refCode: this.attribution.refCode,\n })\n\n const flushHidden = () => {\n if (document.visibilityState === 'hidden') this.flush(true)\n }\n window.addEventListener('visibilitychange', flushHidden)\n window.addEventListener('pagehide', () => this.flush(true))\n\n // Unhandled errors and rejected promises are reported as type:'error' events.\n if (this.cfg.captureErrors) {\n window.addEventListener('error', (e: ErrorEvent) => {\n this.captureError(e.error ?? e.message, { handled: false })\n })\n window.addEventListener('unhandledrejection', (e: PromiseRejectionEvent) => {\n this.captureError(e.reason, { handled: false })\n })\n }\n }\n\n /** link returns `url` carrying this visitor's anonymous id, session and first\n * touch when the destination is a Hanzo-owned host, so the journey continues\n * across the hop. Any other URL comes back unchanged. */\n link(url: string): string {\n if (!isBrowser()) return url\n if (!this.started) this.init()\n return linkUrl(\n url,\n { anonId: anonId(), sessionId: sessionId(), firstTouch: this.attribution },\n window.location.hostname,\n window.location.href,\n )\n }\n\n /** authorize decorates an OAuth authorize URL for the redirect to IAM and flushes\n * what is queued, because the page is about to unload. Assign the result to\n * `location`. */\n authorize(url: string): string {\n const out = this.link(url)\n this.flush(true)\n return out\n }\n\n /** identify binds the current visitor to a stable person id (post-login). */\n identify(personId: string, traits?: Record<string, unknown>): void {\n this.personId = personId\n this.enqueue('identify', undefined, { properties: traits })\n }\n\n /** group associates the visitor with an org/team (analytics grouping, not the\n * server tenant — the server still derives tenant from the session). */\n group(groupId: string, traits?: Record<string, unknown>): void {\n this.enqueue('group', undefined, { groupId, properties: traits })\n }\n\n /** pageview records a $pageview for the current (or given) location, once per\n * view. A view is the path plus the full location, so a query or hash change\n * is a new one and a repeat call for the same place is not. */\n pageview(path?: string, properties?: Record<string, unknown>): void {\n // No `url` here: build() reads window.location.href for every event, in the\n // same tick, so this recomputed it to the identical value. Only `path` is\n // passed, because a route change fires before window.location has caught up\n // and the caller's value has to win.\n const p = path ?? (isBrowser() ? window.location.pathname : undefined)\n // Counting a page once is the client's rule, not each caller's. A page holds\n // several emitters that each correctly believe they count the first view —\n // the provider's autoPageview, a router hook, a nav autocapture — and per\n // emitter state cannot see the others. On the stream they are one page.\n const view = (p ?? '') + '\\0' + (isBrowser() ? window.location.href : '')\n if (view === this.counted) return\n this.counted = view\n this.enqueue('pageview', PAGEVIEW, { path: p, properties })\n }\n\n /** capture records a named product event with optional properties. Commerce\n * fields (productId/quantity/revenue/currency) may be passed for order events. */\n capture(\n event: string,\n properties?: Record<string, unknown>,\n commerce?: Pick<WireEvent, 'productId' | 'quantity' | 'revenue' | 'currency'>,\n ): void {\n this.enqueue('event', event, { properties, ...commerce })\n }\n\n /** captureError reports a caught error, an unhandled rejection, a React render\n * error, or a manual report as ONE event of type 'error' on the one stream.\n * It carries the exception (type, message, frames, stack, handled) and the\n * release, environment, site, product and level that group and scope it, and\n * flushes promptly (a crash may unload the page moments later). Never throws\n * back into the app. */\n captureError(err: unknown, context?: CaptureErrorOptions): void {\n // A failure inside the error path must not recurse through the global handlers.\n if (this.reentrant) return\n this.reentrant = true\n try {\n const handled = context?.handled ?? true\n const ex = normalizeError(err)\n ex.handled = handled\n this.enqueue('error', undefined, {\n error: ex,\n level: context?.level ?? (handled ? 'error' : 'fatal'),\n release: this.cfg.release ?? readEnv('NEXT_PUBLIC_HANZO_RELEASE'),\n environment: this.cfg.environment ?? readEnv('NODE_ENV'),\n site: isBrowser() ? window.location.hostname : undefined,\n properties: context?.properties,\n })\n this.flush()\n } catch {\n /* the error path never takes the app down */\n } finally {\n this.reentrant = false\n }\n }\n\n /** setCohort persists cohort dimensions (e.g. signupWeek at signup) so they ride\n * every subsequent event. */\n setCohort(patch: Cohort): void {\n this.cohort = mergeCohort(patch)\n }\n\n /** flush drains the buffer to the server as ONE batch through the ONE ingest\n * endpoint POST /v1/event, body { batch: [Event…] }. beacon=true selects the\n * unload-safe transport. Auth is orthogonal to the wire:\n *\n * • publishable key set → rides ?ingest_key=pk-… on both sends, keeping each\n * a CORS-simple request that any origin may send.\n * • else a bearer JWT rides Authorization (fetch only — sendBeacon cannot\n * carry a header, so token apps fall back to keepalive fetch on unload).\n * • else a cookie app rides same-origin credentials (beacon carries the\n * cookie fine).\n */\n flush(beacon = false): void {\n if (!this.cfg.enabled || this.queue.length === 0) return\n const batch = this.queue\n this.queue = []\n this.clearTimer()\n\n // A publishable key and a bearer JWT are mutually exclusive credentials, and the\n // BEARER WINS. It names a real principal and resolves to THAT person's org;\n // a pk- names one org for everybody holding it. So the key is what attributes\n // a visitor nobody has vouched for, and it must never displace someone who\n // has been.\n //\n // The precedence used to run the other way, which was survivable only while\n // the key had to be passed in code. Once it also resolves from the build env,\n // key-wins means setting one variable silently blanks every signed-in user's\n // token and re-files their events under whichever org minted the key — on a\n // console served to several brands from one bundle, that is a cross-tenant\n // leak introduced by an env var.\n const token = this.cfg.getToken?.() ?? undefined\n const key = token ? undefined : this.cfg.ingestKey?.trim() || undefined\n // Only a bearer JWT blocks the beacon: sendBeacon cannot set an Authorization\n // header. A pk- rides ?ingest_key; a cookie rides credentials.\n const useBeacon = beacon && !token\n const body = serializeBatch(batch)\n if (body === null) {\n if (this.cfg.debug) console.debug('[event] flush → dropped, batch unserializable')\n return\n }\n if (this.cfg.debug) console.debug('[event] flush →', EVENT_PATH, batch.length)\n this.transport.send(this.cfg.host + EVENT_PATH, body, {\n beacon: useBeacon,\n token,\n ingestKey: key,\n debug: this.cfg.debug,\n })\n }\n\n // ── internals ────────────────────────────────────────────────────────────\n\n private enqueue(kind: EventKind, event: string | undefined, extra: Partial<WireEvent>): void {\n if (!this.cfg.enabled) return\n if (!this.started) this.init()\n this.queue.push(this.build(kind, event, extra))\n if (this.queue.length >= this.cfg.batchSize) this.flush()\n else this.schedule()\n }\n\n private build(kind: EventKind, event: string | undefined, extra: Partial<WireEvent>): WireEvent {\n const anon = anonId()\n const wire: WireEvent = {\n messageId: uuidv7(),\n type: kind,\n event,\n timestamp: new Date().toISOString(),\n distinctId: this.personId ?? anon,\n anonymousId: anon,\n personId: this.personId,\n sessionId: sessionId(),\n product: this.cfg.product,\n referrer: this.attribution.referrer,\n utm: this.attribution.utm,\n refCode: this.cohort.refCode ?? this.attribution.refCode,\n channel: this.cohort.channel ?? this.attribution.channel,\n signupWeek: this.cohort.signupWeek,\n // Where the event happened, stamped for every kind rather than only for\n // pageviews. An interaction is reported against the page it happened on,\n // and autocapture ($click/$input/$change) reaches the wire through\n // capture(), which supplies no location — so every click arrived with an\n // empty url and path, and `host`, derived from url, was empty with them.\n // That is unattributable to a page, which is the one thing a heatmap\n // needs. Read here, at the single point every event is built, so it\n // cannot go missing from a call site again.\n //\n // Before `...extra`: pageview() passes an explicit path for route\n // changes that fire before window.location has caught up, and that value\n // has to win over the one read here.\n url: isBrowser() ? window.location.href : undefined,\n path: isBrowser() ? window.location.pathname : undefined,\n library: '@hanzo/event',\n libraryVersion: VERSION,\n ...extra,\n }\n\n // A location is free text an attacker (or an ordinary product flow) controls,\n // and it is now stamped on EVERY event rather than only pageviews — so the\n // one field that is always a URL gets the same policy the error plane has\n // always applied to error text. A password-reset, invite or magic link puts\n // a JWT in the query and an address in `?email=`; without this, one click on\n // that page ships both to the warehouse in cleartext, and every later click\n // repeats it.\n //\n // AFTER `...extra`, deliberately. A call site can pass its own location —\n // pageview() passes `path`, and until this commit it passed `url` too — and\n // `extra` merges over the fields read above, so scrubbing at the read would\n // have left the highest-volume event emitting a raw location while looking\n // scrubbed. Applied to the ASSEMBLED record, the guarantee holds for every\n // call site, including ones not written yet.\n //\n // `scrubText` is the SAME policy as the error plane (secrets always,\n // PII unless capturePII) rather than a second URL-specific redactor: one\n // definition of \"must not leave the browser\", already tested, mirroring the\n // server's. Guarded on presence so an absent field stays absent instead of\n // becoming the empty string that `host` derivation reads as a page.\n //\n // The fragment goes first and whole: nothing after `#` is ever the server's\n // (see withoutFragment), so it is dropped rather than scrubbed.\n const capturePII = this.cfg.capturePII ?? false\n if (wire.url) wire.url = scrubText(withoutFragment(wire.url), capturePII)\n if (wire.path) wire.path = scrubText(withoutFragment(wire.path), capturePII)\n if (wire.referrer) wire.referrer = scrubText(withoutFragment(wire.referrer), capturePII)\n return wire\n }\n\n private schedule(): void {\n if (this.timer || !this.cfg.enabled) return\n this.timer = setTimeout(() => {\n this.timer = null\n this.flush()\n }, this.cfg.flushIntervalMs)\n }\n\n private clearTimer(): void {\n if (this.timer) {\n clearTimeout(this.timer)\n this.timer = null\n }\n }\n}\n\n// ── one stream, one client ──────────────────────────────────────────────────\n//\n// A page has ONE event stream per (host, product): one queue, one anon id, one\n// credential. Two clients on it split the batch and double the pageview, and\n// the half built by the caller that had no key is refused at the edge — so the\n// same page is both over- and under-counted, and neither number says so.\n//\n// Two callers ask for that stream on any real page and both are right to: the\n// app mounts a provider, and the component library mounts its own telemetry.\n// Neither can see the other, so the fix cannot live in either. It lives here,\n// where the stream is: asking twice returns the same client.\n//\n// The registry is on the PAGE, under a `Symbol.for` slot, not in module scope.\n// `@hanzo/event` and `@hanzo/event/react` are separate bundles that each carry\n// a copy of this module, so a module-scope map is per-copy and the two copies\n// never see each other's — which is exactly how the duplicate arises. A\n// well-known symbol is the one slot every copy resolves to the same value.\n//\n// Browser only. A server process serves many visitors, and one client shared\n// across requests would carry one visitor's personId into the next.\nconst CLIENTS = Symbol.for('hanzo.event.clients')\n\nfunction registry(): Map<string, Analytics> {\n const g = globalThis as unknown as Record<symbol, Map<string, Analytics> | undefined>\n const existing = g[CLIENTS]\n if (existing) return existing\n const fresh = new Map<string, Analytics>()\n g[CLIENTS] = fresh\n return fresh\n}\n\n/** resetClients drops the page's clients, so the next `createAnalytics` for a\n * stream builds a fresh one.\n *\n * A real page loads once and never needs this. A TEST RUNNER is what it exists\n * for: one document, many mounts, each meant to be its own page. The second one\n * gets a client that already counted this location, so its pageview is\n * correctly suppressed and the suite reads it as \"nothing was emitted\".\n *\n * It is exported so a suite calls this instead of reaching for the slot itself.\n * A consumer that deletes the registry from its own code path takes the\n * guarantee with it: `<Provider/>` unmount/remount is not a new page, and the\n * fresh client it would get counts the same view again. */\nexport function resetClients(): void {\n const g = globalThis as unknown as Record<symbol, Map<string, Analytics> | undefined>\n delete g[CLIENTS]\n}\n\n/** createAnalytics returns the client for a stream, building it on first ask.\n * This is the ONE way to get a client: `new Analytics` bypasses the registry\n * and is for tests and for a deliberately separate instance. */\nexport function createAnalytics(config: AnalyticsConfig): Analytics {\n // A disabled client emits nothing, so it can double nothing and does not take\n // the stream. Callers reach their answer at different moments — a provider\n // whose ownership resolves in an effect renders once saying `false` before it\n // has decided anything — and the client built in that moment must not become\n // the one the page keeps. Registering it would silence the page, and adopting\n // `enabled` from a later caller would let one surface overrule another's\n // reading of consent. Neither: it is simply not the stream's client.\n if (!isBrowser() || config.enabled === false) return new Analytics(config)\n const key = (config.host ?? DEFAULT_HOST) + '\\0' + config.product\n const clients = registry()\n const existing = clients.get(key)\n if (existing) {\n existing.adopt(config)\n return existing\n }\n const fresh = new Analytics(config)\n clients.set(key, fresh)\n return fresh\n}\n\n// Re-export the hydrate helpers so consumers can read persisted cohort/attribution\n// (e.g. to send refCode to the referrals API) without reaching into storage.\nexport { getCohort, getFirstTouch }\n","// First-party cookies for consent, the ad click and the browser ids the ad\n// platforms match on. Set on the registrable domain so every subdomain of a site\n// reads the same choice and the same click; on localhost or an address it stays\n// on the host.\n\nconst DAY = 86_400\n\n/** The domain attribute for this host, or '' to keep the cookie on the host. */\nfunction domain(): string {\n const h = window.location.hostname\n if (h === 'localhost' || /^[\\d.]+$/.test(h) || h.includes(':')) return ''\n const parts = h.split('.')\n return parts.length > 2 ? `; Domain=.${parts.slice(-2).join('.')}` : `; Domain=.${h}`\n}\n\n/** Reads one cookie, or undefined. */\nexport function get(name: string): string | undefined {\n if (typeof document === 'undefined') return undefined\n const hit = document.cookie.split('; ').find((c) => c.startsWith(`${name}=`))\n return hit ? decodeURIComponent(hit.slice(name.length + 1)) : undefined\n}\n\n/** Writes one cookie for `days`. */\nexport function set(name: string, value: string, days: number): void {\n if (typeof document === 'undefined') return\n const secure = window.location.protocol === 'https:' ? '; Secure' : ''\n document.cookie = `${name}=${encodeURIComponent(value)}; Max-Age=${days * DAY}; Path=/; SameSite=Lax${domain()}${secure}`\n}\n","// Cookie consent: what a visitor lets a site measure and share, and the rule for\n// what a visitor who has not chosen is presumed to allow.\n//\n// Three categories. Analytics is our own stream and GA4. Marketing is the ad\n// platforms measuring the conversions they bought (Google Ads, Meta, LinkedIn,\n// X, TikTok) and every server-side send. Ads is those platforms using the visit\n// for audiences; off, Google's ad_personalization is denied and Meta runs under\n// Limited Data Use.\n//\n// THE DEFAULT depends on where the visitor is. In the EU, UK and Switzerland,\n// and anywhere else that is not a US state, nothing is allowed until they say\n// so: a visitor with no stored choice has allowed nothing. In the US the default\n// is on and the choice is an opt-out (\"Do not sell or share my personal\n// information\"). Global Privacy Control, and Do Not Track, turn marketing and\n// ads off in every region whatever is stored: California reads GPC as the opt-out\n// of sale and sharing.\n//\n// There is no geo lookup. The page cannot ask a server where the visitor is, so\n// the zone is the browser's own time zone, and a zone that is not a US zone is\n// treated as opt-in. Wrong in the safe direction: a US visitor on a foreign\n// clock is asked, and a European is never presumed to have agreed.\n//\n// The choice is a first-party cookie, `hz_consent`, on the registrable domain\n// for 13 months: the granted categories, comma separated. cloud reads the same\n// string off each event's `consent` property.\n\nimport { get, set } from './cookie'\n\nexport const CONSENT_COOKIE = 'hz_consent'\n\n/** Fired on `window` whenever a choice is stored. */\nexport const CONSENT_EVENT = 'hzconsent'\n\nexport interface Choice {\n analytics: boolean\n marketing: boolean\n ads: boolean\n}\n\nexport type Region = 'opt-in' | 'opt-out'\n\ntype Nav = { doNotTrack?: string; msDoNotTrack?: string; globalPrivacyControl?: boolean }\n\nconst US =\n /^(America\\/(New_York|Chicago|Denver|Los_Angeles|Phoenix|Anchorage|Adak|Boise|Detroit|Juneau|Sitka|Nome|Yakutat|Menominee|Metlakatla|Indiana\\/.*|Kentucky\\/.*|North_Dakota\\/.*)|Pacific\\/Honolulu|US\\/.*)$/\n\n/** Whether the browser sends Global Privacy Control. */\nexport function gpc(): boolean {\n if (typeof navigator === 'undefined') return false\n return (navigator as unknown as Nav).globalPrivacyControl === true\n}\n\n/** Whether the browser sends Global Privacy Control or Do Not Track. */\nexport function refused(): boolean {\n if (typeof window === 'undefined') return false\n const n = navigator as unknown as Nav\n const dnt = n.doNotTrack ?? (window as unknown as Nav).doNotTrack ?? n.msDoNotTrack\n return gpc() || dnt === '1' || dnt === 'yes'\n}\n\n/** Which rule applies to this visitor. */\nexport function region(): Region {\n try {\n const zone = Intl.DateTimeFormat().resolvedOptions().timeZone ?? ''\n return US.test(zone) ? 'opt-out' : 'opt-in'\n } catch {\n return 'opt-in'\n }\n}\n\n/** Whether the visitor has stored a choice. */\nexport function stored(): boolean {\n return get(CONSENT_COOKIE) !== undefined\n}\n\n/** The visitor's choice: the stored one, else the regional default, with GPC applied. */\nexport function read(): Choice {\n const kept = get(CONSENT_COOKIE)\n const on =\n kept !== undefined\n ? kept.split(',')\n : region() === 'opt-in' || refused()\n ? []\n : ['analytics', 'marketing', 'ads']\n const has = (k: string) => on.includes(k)\n return { analytics: has('analytics'), marketing: has('marketing') && !gpc(), ads: has('ads') && !gpc() }\n}\n\n/** Whether the consent banner must be shown: an opt-in visitor who has not chosen. */\nexport function asks(): boolean {\n return typeof document !== 'undefined' && region() === 'opt-in' && !stored()\n}\n\n/** The choice as the `consent` property and the cookie spell it. */\nexport function render(c: Choice): string {\n return (['analytics', 'marketing', 'ads'] as const).filter((k) => c[k]).join(',')\n}\n\n/**\n * Stores a choice and tells the page. The tags react without a reload: a\n * category just allowed loads its libraries, and Google's consent state is\n * updated. An ad library already running cannot be unloaded, so a choice that\n * withdraws marketing takes effect for what has not loaded yet and for every\n * later page.\n */\nexport function save(c: Choice): void {\n const out: Choice = { analytics: c.analytics, marketing: c.marketing && !gpc(), ads: c.ads && !gpc() }\n set(CONSENT_COOKIE, render(out), 395)\n if (typeof window !== 'undefined') window.dispatchEvent(new Event(CONSENT_EVENT))\n}\n\n/** Accept every category. */\nexport const acceptAll = (): void => save({ analytics: true, marketing: true, ads: true })\n\n/** Refuse every optional category. */\nexport const rejectAll = (): void => save({ analytics: false, marketing: false, ads: false })\n","// React bindings for @hanzo/event — a provider, an accessor hook, a route-change\n// pageview hook, and an error boundary. Framework-neutral: it takes the current\n// path as an argument (the Next app wires usePathname(); a Vite/router app passes\n// its own), so this file never imports next/*.\n//\n// 'use client'\n// import { AnalyticsProvider, useAnalytics, usePageview, ErrorBoundary } from '@hanzo/event/react'\n//\n// <AnalyticsProvider config={{ product: 'console' }}>…</AnalyticsProvider>\n// const a = useAnalytics(); usePageview(usePathname())\n\nimport {\n Component,\n createContext,\n createElement,\n useContext,\n useEffect,\n useRef,\n useSyncExternalStore,\n type ErrorInfo,\n type ReactNode,\n} from 'react'\nimport { Analytics, createAnalytics } from './core'\nimport type { AnalyticsConfig } from './types'\nimport { CONSENT_EVENT, read, render, type Choice } from './consent'\n\nconst Ctx = createContext<Analytics | null>(null)\n\nexport interface AnalyticsProviderProps {\n /** Provide a pre-built client, or a config to build one. */\n client?: Analytics\n config?: AnalyticsConfig\n /** Fire a pageview for the initial load (default true). */\n autoPageview?: boolean\n children: ReactNode\n}\n\nexport function AnalyticsProvider(props: AnalyticsProviderProps) {\n const { client, config, autoPageview = true, children } = props\n // No memo. createAnalytics returns the client for a stream, so asking on every\n // render hands back the same object — the identity a memo used to be here to\n // preserve. Memoizing construction is what made a config change unreachable\n // (deps held `client` alone) while adding `config` would have built a client\n // per render, since call sites pass an object literal.\n if (!client && !config) throw new Error('AnalyticsProvider requires `client` or `config`')\n const instance = client ?? createAnalytics(config as AnalyticsConfig)\n\n useEffect(() => {\n instance.init()\n if (autoPageview) instance.pageview()\n }, [instance, autoPageview])\n\n return createElement(Ctx.Provider, { value: instance }, children)\n}\n\n/** useAnalytics returns the client. Outside a provider it returns a no-op-safe\n * null-guarded proxy so calls never throw during SSR/tests. */\nexport function useAnalytics(): Analytics {\n const a = useContext(Ctx)\n if (!a) return noop\n return a\n}\n\n/** usePageview fires a pageview on every route CHANGE (not the initial mount —\n * the provider's autoPageview covers that, so pages are counted exactly once). */\nexport function usePageview(path: string | null | undefined): void {\n const a = useContext(Ctx)\n const first = useRef(true)\n useEffect(() => {\n if (first.current) {\n first.current = false\n return\n }\n if (a && path) a.pageview(path)\n }, [a, path])\n}\n\n// A shared no-op client for use outside a provider — keeps call sites total.\nconst noop = new Analytics({ product: 'unknown', enabled: false })\n\nexport interface ErrorBoundaryProps {\n children: ReactNode\n /** Rendered when a child throws. A function receives the error + a reset. */\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode)\n /** Explicit client; defaults to the one from AnalyticsProvider. */\n client?: Analytics\n}\n\ninterface ErrorBoundaryState {\n error: Error | null\n}\n\n/** ErrorBoundary reports React render errors to the client as error events —\n * React swallows these before window.onerror sees them, so a boundary is the\n * ONLY way to capture them. This is the React half of the @sentry replacement.\n * Pair it with AnalyticsProvider (it reads the client from context), or pass an\n * explicit `client`. */\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n static contextType = Ctx\n declare context: React.ContextType<typeof Ctx>\n state: ErrorBoundaryState = { error: null }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { error }\n }\n\n componentDidCatch(error: Error, info: ErrorInfo): void {\n const client = this.props.client ?? this.context ?? undefined\n client?.captureError(error, {\n handled: false,\n properties: { componentStack: info.componentStack, react: true },\n })\n }\n\n private reset = () => this.setState({ error: null })\n\n render(): ReactNode {\n const { error } = this.state\n if (error === null) return this.props.children\n const { fallback } = this.props\n if (typeof fallback === 'function') return fallback(error, this.reset)\n return fallback ?? null\n }\n}\n\nconst listen = (on: () => void) => {\n window.addEventListener(CONSENT_EVENT, on)\n return () => window.removeEventListener(CONSENT_EVENT, on)\n}\n\n/**\n * The visitor's consent, live: what a region presumes until they choose, then\n * what they chose, re-rendering the moment they do. `enabled: choice.analytics`\n * on the provider's config is how a stream that started silent for an EU visitor\n * starts on Accept, with no reload.\n */\nexport function useConsent(): Choice {\n const kept = useSyncExternalStore(listen, () => render(read()), () => '')\n return {\n analytics: kept.includes('analytics'),\n marketing: kept.includes('marketing'),\n ads: kept.includes('ads'),\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/attribution.ts","../src/org.ts","../src/scrub.ts","../src/throwable.ts","../src/anon.js","../src/storage.ts","../src/link.ts","../package.json","../src/version.ts","../src/core.ts","../src/cookie.ts","../src/consent.ts","../src/react.tsx"],"names":["get","set","normalizeError","PAGEVIEW","read","createContext","useEffect","createElement","useContext","useRef","Component","useSyncExternalStore"],"mappings":"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","file":"react.cjs","sourcesContent":["// Pure attribution helpers: parse first-touch UTM/referrer/refCode from a URL,\n// derive the acquisition channel, and compute the ISO week for the signup cohort.\n// No I/O, no globals — trivially testable.\n\nimport type { Attribution } from './types'\n\nconst SOCIAL_HOSTS = [\n 'facebook.', 'instagram.', 'twitter.', 'x.com', 't.co', 'linkedin.',\n 'reddit.', 'youtube.', 'tiktok.', 'pinterest.', 'news.ycombinator.com',\n]\nconst SEARCH_HOSTS = ['google.', 'bing.', 'duckduckgo.', 'yahoo.', 'baidu.', 'ecosia.']\n\n/** parseAttribution reads UTM params + ref/refCode from a query string and pairs\n * them with the referrer. `search` is a location.search value (\"?utm_source=…\"). */\nexport function parseAttribution(search: string, referrer: string): Attribution {\n const q = new URLSearchParams(search || '')\n const get = (k: string) => {\n const v = q.get(k)\n return v ? v.trim() : undefined\n }\n const a: Attribution = {\n utm: {\n source: get('utm_source'),\n medium: get('utm_medium'),\n campaign: get('utm_campaign'),\n term: get('utm_term'),\n content: get('utm_content'),\n },\n referrer: referrer ? referrer.trim() : undefined,\n refCode: get('ref') || get('refCode') || get('ref_code') || undefined,\n }\n a.channel = deriveChannel(a)\n return a\n}\n\n/** deriveChannel classifies the visit: paid | referral | social | organic | direct. */\nexport function deriveChannel(a: Attribution): string {\n const medium = (a.utm.medium || '').toLowerCase()\n if (/(cpc|ppc|paid|paidsearch|display|cpm)/.test(medium)) return 'paid'\n if (a.utm.source || a.utm.campaign) return 'campaign'\n if (a.refCode) return 'referral'\n const host = hostOf(a.referrer)\n if (!host) return 'direct'\n if (SOCIAL_HOSTS.some((h) => host.includes(h))) return 'social'\n if (SEARCH_HOSTS.some((h) => host.includes(h))) return 'organic'\n return 'referral'\n}\n\n/** hostOf extracts a bare lowercase host from a URL; \"\" when unparseable. */\nexport function hostOf(raw?: string): string {\n if (!raw) return ''\n let s = raw.trim()\n const scheme = s.indexOf('://')\n if (scheme >= 0) s = s.slice(scheme + 3)\n const cut = s.search(/[/?#]/)\n if (cut >= 0) s = s.slice(0, cut)\n const at = s.indexOf('@')\n if (at >= 0) s = s.slice(at + 1)\n const colon = s.indexOf(':')\n if (colon >= 0) s = s.slice(0, colon)\n return s.toLowerCase().trim()\n}\n\n/** hasAttribution reports whether anything was captured (so we don't persist an\n * empty first-touch that would shadow a later real one). */\nexport function hasAttribution(a: Attribution): boolean {\n return Boolean(\n a.utm.source || a.utm.medium || a.utm.campaign || a.utm.term ||\n a.utm.content || a.refCode || (a.referrer && hostOf(a.referrer)),\n )\n}\n\n/** isoWeek returns the ISO-8601 week label, e.g. \"2026-W28\". */\nexport function isoWeek(d: Date): string {\n // Copy to UTC midnight; ISO week: Thursday-anchored.\n const date = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()))\n const day = date.getUTCDay() || 7\n date.setUTCDate(date.getUTCDate() + 4 - day)\n const yearStart = new Date(Date.UTC(date.getUTCFullYear(), 0, 1))\n const week = Math.ceil(((date.getTime() - yearStart.getTime()) / 86400000 + 1) / 7)\n return `${date.getUTCFullYear()}-W${String(week).padStart(2, '0')}`\n}\n","/**\n * Which org owns a host's telemetry.\n *\n * A surface should not have to LEARN its key. It already knows the domain it is\n * served from, and a domain belongs to exactly one brand, so the key is derivable\n * and asking a surface to carry one is asking it to restate something already\n * true. This module answers `orgOf(location.hostname)` and hands back that org's\n * publishable key, which is what lets a static export report correctly while\n * configuring nothing.\n *\n * This is the SAME question `hanzo.id` answers at runtime for the identity hosts\n * (`pkgs/shared/src/ingest.ts`): one image serves every brand, so the key cannot\n * be a property of the build. It was, and the bill is on record — Lux's, Zoo's,\n * Osage's and Pars' visitors were all filed in HANZO's project, because one\n * build-time key was inlined for every brand. That is the white-label boundary\n * crossed in the direction that shows up latest. The marketing sites carry the\n * identical defect in its other form: each commits its OWN key literal, so the\n * fleet holds N copies of a value with one source, and a site added tomorrow\n * reports nothing until somebody remembers to paste one in.\n *\n * A `pk-` is PUBLISHABLE: it authorizes a write into one org and mints no reading\n * principal. It is readable in devtools on every deployed page that sends an\n * event, so stating it here exposes nothing that serving the page did not. What\n * it does buy is that correct attribution becomes the DEFAULT rather than\n * something each surface opts into.\n *\n * Keyed by ORG, never by host: a brand's facts repeat on every alias it owns\n * (`lux.id`, `id.lux.network`), and a key stated per host would have to be\n * repeated too — so the day someone adds an alias and forgets the key, that host\n * silently stops reporting. Stated once per org, a new alias inherits its brand's\n * key by naming its brand's domain, which is all an alias ever says.\n */\n\n/** One publishable key per org. */\nexport type Keyring = Readonly<Record<string, string>>\n\n/**\n * Each org's registrable domains. A host matches a domain when it IS that domain\n * or a subdomain of it, so `explore.lux.network` needs no entry of its own.\n *\n * An org absent from this table resolves to undefined, and that is deliberate:\n * `osage`, `pars` and `bootnode` have no project of their own yet, and reporting\n * NOTHING is the honest answer. Filing them under a brand that is not theirs is\n * the defect this module exists to prevent — it is silent, it reads as working,\n * and it is only visible later in someone else's warehouse.\n */\nexport const ORG_DOMAIN: Readonly<Record<string, readonly string[]>> = Object.freeze({\n // A brand's domains are not a pattern — `hanzoskills.com` is Hanzo's and does\n // not end in `hanzo.ai`, while `hanzo.works` is a registrable domain of its own\n // rather than a subdomain of anything here. Each is stated because each is a\n // separate fact, which is the whole reason this is a table.\n hanzo: Object.freeze([\n 'hanzo.ai',\n 'hanzo.agency',\n 'hanzo.app',\n 'hanzo.bot',\n 'hanzo.chat',\n 'hanzo.codes',\n 'hanzo.id',\n 'hanzo.industries',\n 'hanzo.market',\n 'hanzo.network',\n 'hanzo.sh',\n 'hanzo.team',\n 'hanzo.ventures',\n 'hanzo.works',\n 'hanzoskills.com',\n ]),\n lux: Object.freeze([\n 'lux.network',\n 'lux.exchange',\n 'lux.market',\n 'lux.finance',\n 'lux.financial',\n 'lux.credit',\n 'lux.fund',\n 'lux.id',\n ]),\n zoo: Object.freeze(['zoo.ngo', 'zoo.network', 'zoolabs.id', 'zoolabs.io']),\n})\n\n/**\n * Each org's publishable key, and a copy: the values live in universe at\n * infra/k8s/id/configmap.yaml as SPA_INGEST_KEYRING, which serves them to the\n * identity hosts, and this table is what a statically exported page carries when\n * it cannot ask. The two must say the same thing. Add an org the day its project\n * exists, never before.\n *\n * A key is only as real as the project it names, and these had stopped naming\n * one: all three answered `403 ingest_key_unknown` against /v1/event, so every\n * page that fell back to this table reported nowhere while looking fine. The\n * copy drifted silently because nothing compares it to the keyring. If you\n * recreate a project, move BOTH.\n */\nexport const ORG_KEY: Keyring = Object.freeze({\n hanzo: 'pk-CmfLA2K6kvsPflrS9DSkt06H_kSoQB_21sjedt6VJdc',\n lux: 'pk-gUZp6ZVfhJzSwK-rb4oLbVkpCnMBx5uSCpxf_5yEhQk',\n zoo: 'pk-3TKpKnERV9AQSsBUERWkZejC1O1mUxc1jRzsP3MPbs4',\n})\n\n/**\n * The publishable key of each site's project, which is how cloud finds the site's\n * tag set and the project its events are filed under. Each site is ONE project with its\n * own key. A `pk-` is public by design (it ships in every page); it names a site,\n * never a platform id. A host absent here falls back to its org's key for events and\n * has no tag config unless `start` is given a key.\n */\nexport const SITE_KEY: Readonly<Record<string, string>> = Object.freeze({\n 'hanzo.ai': 'pk-CmfLA2K6kvsPflrS9DSkt06H_kSoQB_21sjedt6VJdc',\n 'www.hanzo.ai': 'pk-CmfLA2K6kvsPflrS9DSkt06H_kSoQB_21sjedt6VJdc',\n 'hanzo.app': 'pk-wlnXN2a9_vmCm60yTFtQ629Q8TyuaxBNZbY1RWT72gQ',\n 'hanzo.team': 'pk-NCzD2FiHpZv8KUpkCX4olT1LJOJsMxBC_Z8NkiQsOFQ',\n 'pay.hanzo.ai': 'pk-eX6kv7JZNoiYn1WkeJH3tT_8OvkVYScmCXnLMwxTKf8',\n 'platform.hanzo.ai': 'pk-My1RpZLEUnTj8vAdPbWKYdDUuhxZJ4dVjHcwjZN4rZ8',\n 'docs.hanzo.ai': 'pk-jukhtjMT2ymoeBDAeFjINQWlBv-v9sNn1TPztiCrrwk',\n 'hanzo.bot': 'pk-W5d7Mn7ZukT7igyscIy6Pqe8JpA0Ge604Yn4xNR4JCU',\n 'hanzo.chat': 'pk-ATxWeB2jNyRSxDgqnkGoDj3CCbzrmTxSktUh9zlrO-E',\n 'hanzo.id': 'pk-_GVF3KlaqprlPHDumBMRFeFU1lIGOaarQfgimNVDIo8',\n 'hanzo.industries': 'pk-Vh1wvL2HqIAv9qpVvmrznTI9uMHrTD-jyIC-vnlBsgY',\n 'hanzo.market': 'pk-DN3xQFa0H61epUVg9OkiOYLzCdteNt9hE6f-S-ednjQ',\n 'hanzo.network': 'pk-YJ2eiA_7ckLStMPte8Ar8FsmRp_ycmeIeRbpGprZYmM',\n 'hanzo.agency': 'pk-26a2clOaJFe24aKJZ0PkI-GWR9F4EEa8rthHzgy_Efw',\n 'console.hanzo.ai': 'pk-oFNXoiO1wOD8PqGdHYyiSq6jaNCdrd7TpztGpwM2ZiQ',\n 'admin.hanzo.ai': 'pk-RYZwxkomW-tlAnEu2DKo_kAzcxFbSF2YiYcsUY48QL0',\n 'bot.hanzo.ai': 'pk-W5d7Mn7ZukT7igyscIy6Pqe8JpA0Ge604Yn4xNR4JCU',\n 'cloud.hanzo.ai': 'pk-RAfEGHPoNdCEU9fnA_cPd_Xo9Tci44rlYQV9xuJ1Ob0',\n})\n\n/** The project key of the site a host is: its own entry, `www.` stripped, a `*.hanzo.app` site under hanzo.app. */\nexport function siteKey(host: string): string | undefined {\n const h = normalize(host).replace(/^www\\./, '')\n return SITE_KEY[h] ?? (h.endsWith('.hanzo.app') ? SITE_KEY['hanzo.app'] : undefined)\n}\n\n/** `pk-` is publishable; `sk-` is not, and there is no third thing. Checked at the\n * one point a key becomes something a page will send, so a mistyped entry fails\n * closed rather than putting a secret in every visitor's tab. */\nconst PUBLISHABLE = 'pk-'\n\n/** Strip the port and case a hostname the way a domain compares. */\nconst normalize = (host: string): string =>\n host.trim().toLowerCase().replace(/\\.$/, '').split(':')[0] ?? ''\n\n/**\n * The org that owns a host, or undefined when no brand claims it.\n *\n * Longest match wins, so a brand owning both a domain and a subdomain of another\n * brand's cannot be decided by table order. Pure and total.\n */\nexport function orgOf(host: string): string | undefined {\n const h = normalize(host)\n if (!h) return undefined\n let best: string | undefined\n let bestLen = 0\n for (const [org, domains] of Object.entries(ORG_DOMAIN)) {\n for (const d of domains) {\n if ((h === d || h.endsWith(`.${d}`)) && d.length > bestLen) {\n best = org\n bestLen = d.length\n }\n }\n }\n return best\n}\n\n/**\n * The publishable key for a host, or undefined when there is not exactly one to\n * give.\n *\n * Deliberately WITHOUT a fallback: returning Hanzo's key for an unrecognised host\n * is precisely the defect described above. Undefined is the honest answer and the\n * caller reports nothing.\n *\n * `keyring` is a parameter so the identity runtime — which receives its keyring\n * from `/config.json` because one image serves every brand — resolves through\n * this SAME function rather than a second copy of it.\n */\nexport function keyFor(host: string, keyring: Keyring = ORG_KEY): string | undefined {\n if (keyring === ORG_KEY) {\n const site = siteKey(host)\n if (site) return site\n }\n const org = orgOf(host)\n if (!org) return undefined\n const key = keyring[org]\n if (typeof key !== 'string') return undefined\n const trimmed = key.trim()\n return trimmed.startsWith(PUBLISHABLE) ? trimmed : undefined\n}\n\n/** The key for the page this code is running on; undefined off a browser. */\nexport function keyForPage(keyring: Keyring = ORG_KEY): string | undefined {\n if (typeof location === 'undefined') return undefined\n return keyFor(location.hostname, keyring)\n}\n","// Client-side redaction for error text — a faithful port of the server's\n// errortracking scrub (o11y pkg/modules/errortracking/implerrortracking/scrub.go),\n// applied BEFORE anything leaves the browser. Two layers, default-secure:\n//\n// - Secret shapes are ALWAYS redacted (sk-… keys, bearer/JWT tokens, DB DSNs,\n// PANs, cloud keys). There is no mode that ships a secret off-device.\n// - PII (email/IP) is scrubbed UNLESS capturePII is explicitly enabled.\n//\n// The server scrubs again — this is defense in depth, not a substitute — but the\n// point is that a Hanzo browser never emits a raw secret/email/IP in the first\n// place. Pure, no I/O.\n\nconst REDACTED = '[redacted]'\nconst EMAIL_MARK = '[email]'\nconst IP_MARK = '[ip]'\n\n// Secret patterns mirror scrub.go's secretPatterns. Order matters (broad DSN/PAN\n// rules run last). All are applied unconditionally.\nconst SECRET_PATTERNS: RegExp[] = [\n /-----BEGIN[ A-Z]*PRIVATE KEY-----[\\s\\S]*?-----END[ A-Z]*PRIVATE KEY-----/g,\n /eyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{6,}\\.[A-Za-z0-9_-]{6,}/g, // JWT\n /\\bbearer\\s+[A-Za-z0-9._~+/-]{12,}=*/gi, // bearer token\n /\\b(?:sk|pk|rk)-[A-Za-z0-9]{2,}-?[A-Za-z0-9]{12,}/g, // openai-style\n /\\b(?:sk|pk)_(?:live|test)_[A-Za-z0-9]{16,}/g, // stripe\n /\\bhk-[A-Za-z0-9]{16,}/g, // hanzo key\n /\\bAKIA[0-9A-Z]{16}\\b/g, // aws access key id\n /\\bASIA[0-9A-Z]{16}\\b/g, // aws sts key id\n /\\bAIza[0-9A-Za-z_-]{20,}/g, // google api key\n /\\bgh[posru]_[A-Za-z0-9]{20,}/g, // github token\n /\\bxox[baprs]-[A-Za-z0-9-]{10,}/g, // slack token\n // Creds in a URL/DSN. The repetition is BOUNDED on purpose: the unbounded form\n // ([^\\s:@/]+:[^\\s@/]+@) backtracks quadratically on colon-rich text with no\n // terminating '@' — an HTML error page pasted into an error message took 4.9s\n // at 32KB and >60s at 128KB, freezing the main thread from inside captureError.\n // Real userinfo is far below these caps, so bounding costs nothing.\n /[a-zA-Z][a-zA-Z0-9+.-]{0,32}:\\/\\/[^\\s:@/]{1,256}:[^\\s@/]{1,256}@/g,\n]\n\n/** Candidate card numbers. Gated by Luhn below — the bare digit-run pattern is a\n * false-positive cannon that redacts every millisecond epoch, order id and\n * phone number it sees (\"request 1753468800000 timed out\" became\n * \"request [redacted]timed out\"), which destroys the readability of the very\n * error messages this client exists to deliver. */\nconst RE_PAN = /\\b(?:\\d[ -]?){13,19}\\b/g\n\n/** luhn reports whether a digit string satisfies the Luhn checksum. Every real\n * card number does, so gating redaction on it removes the false positives\n * WITHOUT introducing a false negative — the safe direction for a redactor. */\nfunction luhn(digits: string): boolean {\n let sum = 0\n let alt = false\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = digits.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/** redactPAN removes digit runs that actually check out as card numbers. */\nfunction redactPAN(s: string): string {\n return s.replace(RE_PAN, (m) => {\n const digits = m.replace(/[ -]/g, '')\n if (digits.length < 13 || digits.length > 19) return m\n return luhn(digits) ? REDACTED : m\n })\n}\n\n// Bounded to the RFC 5321 maxima (local-part 64, domain 255) for the same reason\n// as the creds-in-URL rule: the unbounded form backtracks quadratically across a\n// long run of local-part-legal characters that never reaches an '@' — measured at\n// 20ms on an 8KB worst case, on the main thread, per captured error. No real\n// address is excluded by these caps.\nconst RE_EMAIL = /[A-Za-z0-9._%+-]{1,64}@[A-Za-z0-9.-]{1,255}\\.[A-Za-z]{2,24}/g\nconst RE_IPV4 = /\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b/g\nconst RE_IPV6 = /\\b(?:[0-9A-Fa-f]{1,4}:){2,7}[0-9A-Fa-f]{1,4}\\b/g\n\n// A CREDENTIAL IN A QUERY PARAM HAS NO SHAPE TO MATCH.\n//\n// Every pattern above recognises a secret by what it LOOKS like — a JWT's three\n// dots, `sk-`, `AKIA`, `ghp_`. An OAuth `code`, a `state`, a password-reset\n// nonce and an invite token are opaque random strings, indistinguishable from a\n// page id, so none of them match and all of them survive.\n//\n// That matters because the client stamps `url: window.location.href` on EVERY\n// event, not just pageviews. So one visit to `/callback?code=…&state=…` puts a\n// live authorization code on the wire, once per event, in cleartext — and the\n// code is exchangeable until it is redeemed.\n//\n// The fix is to redact by the NAME the value is filed under rather than by the\n// value's shape, which is the only signal available for an opaque token. The\n// name half is bounded (`{1,32}`) and the value half stops at the first\n// separator, so neither half can backtrack across a long string — the same\n// discipline the creds-in-URL pattern above documents.\nconst CREDENTIAL_PARAMS = [\n 'code', 'state', 'token', 'access_token', 'id_token', 'refresh_token',\n 'auth', 'authorization', 'secret', 'client_secret', 'password', 'passwd', 'pwd',\n 'api_key', 'apikey', 'key', 'session', 'session_id', 'sid',\n 'sig', 'signature', 'nonce', 'otp', 'invite', 'invitation',\n 'reset_token', 'confirmation_token', 'magic', 'ticket', 'assertion',\n]\nconst RE_CREDENTIAL_PARAM = new RegExp(\n '([?&#;](?:' + CREDENTIAL_PARAMS.join('|') + ')=)[^&#;\\\\s]{1,4096}',\n 'gi',\n)\n\n/** redactCredentialParams removes the VALUE of any query parameter whose NAME\n * says it carries a credential, leaving the name so the URL still reads. */\nexport function redactCredentialParams(s: string): string {\n return s.replace(RE_CREDENTIAL_PARAM, (_m, prefix: string) => prefix + REDACTED)\n}\n\n// A 256-bit secret written as unpadded base64url is exactly 43 characters of\n// [A-Za-z0-9_-] — the shape of a share-link secret, and of any other opaque key\n// minted the same way. The run must stand alone — nothing of the same alphabet\n// on either side, a percent-escape such as the `%23` of an encoded `#` counting\n// as a boundary — so it never fires inside a longer token, and it must mix upper\n// and lower case, which a random 32 bytes does with near certainty and an\n// ordinary word or slug does not. No lookbehind, so it runs on every engine the\n// client ships to.\nconst RE_SECRET43 = /(^|[^A-Za-z0-9_-]|%[0-9A-Fa-f]{2})((?=[A-Za-z0-9_-]{0,42}[a-z])(?=[A-Za-z0-9_-]{0,42}[A-Z])[A-Za-z0-9_-]{43})(?![A-Za-z0-9_-])/g\n\n/** redactSecrets removes known secret shapes. Always applied. */\nexport function redactSecrets(s: string): string {\n s = redactCredentialParams(s)\n for (const re of SECRET_PATTERNS) s = s.replace(re, REDACTED)\n s = s.replace(RE_SECRET43, (_m, lead: string) => lead + REDACTED)\n return redactPAN(s)\n}\n\n/** withoutFragment returns a URL with its fragment removed. A browser never\n * sends the fragment to any server — it is where an app keeps what must stay\n * on the device, a share link's secret among them — so the client does not\n * send it either. */\nexport function withoutFragment(url: string): string {\n const at = url.indexOf('#')\n return at < 0 ? url : url.slice(0, at)\n}\n\n/** scrubPII masks emails and IPs. Applied unless PII capture is enabled. */\nexport function scrubPII(s: string): string {\n s = s.replace(RE_EMAIL, EMAIL_MARK)\n s = s.replace(RE_IPV6, IP_MARK)\n s = s.replace(RE_IPV4, IP_MARK)\n return s\n}\n\n/** Longest free-text field this module will scrub. Every pattern here is a regex\n * run synchronously on the main thread, and the input is attacker-influenced —\n * `throw new Error(await res.text())` against an HTML error page is a one-line\n * way to hand us 128KB. Bounding the INPUT bounds the work regardless of which\n * pattern is pathological. 8KB is far beyond any real error message. */\nexport const MAX_SCRUB_LEN = 8192\n\n/** truncate caps a string at MAX_SCRUB_LEN, marking that it was cut so a reader\n * never mistakes a truncated message for the whole one. */\nexport function truncate(s: string, max = MAX_SCRUB_LEN): string {\n return s.length > max ? s.slice(0, max) + '… [truncated]' : s\n}\n\n/** scrubText applies the redaction policy to a free-text field. Input is capped\n * first: unbounded text is a denial-of-service surface, not just a size problem. */\nexport function scrubText(s: string | undefined, capturePII = false): string {\n if (!s) return s ?? ''\n s = truncate(s)\n s = redactSecrets(s)\n if (!capturePII) s = scrubPII(s)\n return s\n}\n","// Pure throwable parsing: coerce anything thrown into {name, message, stack} and\n// parse a browser stack into frames. No I/O, no globals.\n\nimport type { SentryFrame } from './types'\n\nconst MAX_FRAMES = 50\n/** Max stack lines examined, and max length of a line worth examining. Guards the\n * frame regexes against a hostile `stack` string (see framesFromStack). */\nconst MAX_LINES = 500\nconst MAX_LINE_LEN = 2048\n\nconst V8_FRAME = /^\\s*at\\s+(?:(.+?)\\s+\\()?(?:(.+?):(\\d+):(\\d+)|([^)]+))\\)?\\s*$/\nconst MOZ_FRAME = /^\\s*(?:(.*?)@)?(.+?):(\\d+):(\\d+)\\s*$/\n\n/** inApp marks a frame as the app's own code (vs vendor/runtime) for grouping. */\nfunction inApp(file: string): boolean {\n if (!file) return false\n return !(\n file.includes('node_modules') ||\n file.startsWith('webpack-internal') ||\n file.startsWith('webpack://') ||\n file.startsWith('chrome-extension://') ||\n file.startsWith('moz-extension://')\n )\n}\n\n/**\n * framesFromStack parses a browser Error.stack into Sentry frames, OLDEST-FIRST\n * (Sentry orders caller->callee; the crash site is last — matching the server's\n * pickCrashFrame). Handles both V8 (\"at fn (file:li:co)\") and\n * Firefox/Safari (\"fn@file:li:co\"). Unparseable lines are skipped.\n */\nexport function framesFromStack(stack: string | undefined): SentryFrame[] {\n if (!stack) return []\n // Both frame regexes use lazy nested quantifiers, which backtrack badly on a\n // long line that never matches. A stack is attacker-influenced (a thrown value\n // can carry any `stack` string), so bound the work: skip absurd lines and stop\n // after MAX_LINES. Only the innermost MAX_FRAMES are kept anyway.\n const lines = stack.split('\\n', MAX_LINES)\n const frames: SentryFrame[] = []\n for (const raw of lines) {\n if (raw.length > MAX_LINE_LEN) continue\n const line = raw.trimEnd()\n if (!line) continue\n // Header lines like \"TypeError: x is not a function\" match neither frame\n // regex (no \"at \" prefix, no trailing :line:col) and are skipped naturally.\n let fn: string | undefined\n let file = ''\n let lineno = 0\n let colno = 0\n const v = V8_FRAME.exec(line)\n if (v) {\n fn = v[1]\n if (v[2]) {\n file = v[2]\n lineno = Number(v[3]) || 0\n colno = Number(v[4]) || 0\n } else {\n file = (v[5] || '').trim()\n }\n } else {\n const f = MOZ_FRAME.exec(line)\n if (!f) continue\n fn = f[1]\n file = f[2]\n lineno = Number(f[3]) || 0\n colno = Number(f[4]) || 0\n }\n if (!file && !fn) continue\n frames.push({\n function: fn || '<anonymous>',\n filename: file,\n abs_path: file,\n lineno,\n colno,\n in_app: inApp(file),\n })\n }\n // Reverse to oldest-first and cap to the innermost MAX_FRAMES.\n frames.reverse()\n if (frames.length > MAX_FRAMES) return frames.slice(frames.length - MAX_FRAMES)\n return frames\n}\n\n/** normalizeError coerces an unknown throwable into {name, message, stack}. */\nexport function normalizeError(err: unknown): { name: string; message: string; stack?: string } {\n if (err instanceof Error) {\n // `name`, `message` and `stack` are ordinary getters, and the thrown object is\n // the least trustworthy input this library handles — any of them may throw.\n // Losing the whole report to a hostile getter is not acceptable.\n const name = read(err, 'name')\n const message = read(err, 'message')\n const stack = read(err, 'stack')\n return {\n name: typeof name === 'string' && name ? name : 'Error',\n message: typeof message === 'string' && message ? message : str(err),\n stack: typeof stack === 'string' ? stack : undefined,\n }\n }\n if (typeof err === 'string') return { name: 'Error', message: err }\n try {\n return { name: 'Error', message: JSON.stringify(err) ?? str(err) }\n } catch {\n return { name: 'Error', message: str(err) }\n }\n}\n\n/** read pulls a property off a possibly-hostile value without letting a throwing\n * getter escape. */\nfunction read(o: unknown, k: string): unknown {\n try {\n return (o as Record<string, unknown>)[k]\n } catch {\n return undefined\n }\n}\n\n/** str coerces to a string without letting a throwing toString/Symbol.toPrimitive\n * escape. */\nfunction str(v: unknown): string {\n try {\n return String(v)\n } catch {\n return '[unstringifiable]'\n }\n}\n","/*! anon.js — THE anonymous-identity chain. ONE implementation, two distributions.\n *\n * One browser is ONE person on every Hanzo surface, whichever client a page\n * happens to have loaded. There were once three implementations writing TWO keys —\n * `hz_anon_id` and `hz_id` — so the same visitor was several people depending on\n * which snippet the surface shipped.\n *\n * The two call sites:\n * 1. src/storage.ts — the bundled npm client; IMPORTS this file.\n * 2. hanzoai/cloud apps/analytics/tag.js — the tag served at\n * /v1/event.js; vendors this file and its tag.go serves the marked region\n * with the tag as one asset, so cloud holds no second copy either.\n *\n * (2) has no bundler and cannot import anything, which is why the chain lives in a\n * file that is plain ES5 rather than in a .ts: the region between the BEGIN and END\n * markers is COPIED VERBATIM. Keep it ES5, dependency-free, `hz`-prefixed (it is\n * spliced into other people's scopes) and unformatted — a reformat here is a diff\n * against the vendored copy. After editing, resync that copy:\n *\n * curl -fsSL https://unpkg.com/@hanzo/event/src/anon.js -o apps/analytics/anon.js\n */\n\n/* ── BEGIN hz anon chain — copied VERBATIM into hanzoai/cloud ──────────────── */\n\n/** The ONE anonymous-id key, on every surface and in every distribution.\n *\n * It names what it is, not who ships it: this value is visible to anyone who opens\n * their own cookie jar, and a vendor's name has no business there. Identity is IAM's\n * concern whether or not the visitor has said who they are. */\nvar HZ_ANON_KEY = 'iam-anon-id'\n\n/** Keys an id may already be living under. READ, never written.\n *\n * Each was canonical once — `hz_anon_id` most recently, and `hz_id` before it, when a\n * no-build tag wrote a second identity space and one page could hold two people.\n * Adopting an id already in the wild is what makes this a rename rather than an\n * erasure: minting over one detaches a returning visitor from their own history.\n * They are never written, so they leave with the cookies that hold them. */\nvar HZ_ANON_ADOPT = ['hz_anon_id', 'hz_id']\n\n/** The registrable domain the cookie is scoped to, so docs, cloud, console,\n * studio, pay, id and www all read the ONE id. localStorage cannot do this: it is\n * ORIGIN-scoped, which is what made one journey arrive as several strangers. */\nvar HZ_ANON_DOMAIN = 'hanzo.ai'\n\n/** Two years, rewritten on every read, so the cookie rolls forward with the\n * visitor instead of expiring two years after first touch. Safari caps a\n * SCRIPT-written cookie at 7 days no matter what this says, so the rewrite is\n * what keeps a returning Safari visitor: each read re-arms the 7-day window. */\nvar HZ_ANON_MAX_AGE = 2 * 365 * 24 * 60 * 60\n\n/** Last resort for a browser that refuses cookies AND localStorage: without it\n * every event in a page load would mint an id of its own. */\nvar hzAnonMemo\n\n/**\n * hzUuidv7 mints a time-ordered UUIDv7 (RFC 9562 §5.7) for `now` in epoch ms.\n *\n * It has to be v7, and this is the only minter any distribution may use. The\n * session rollups on the event plane derive a session's start instant FROM THE ID\n * and admit only ids whose version nibble is 7, so a crypto.randomUUID() (v4) id\n * is not merely unordered there — it is DISCARDED, silently, and the rollup stays\n * empty. Without crypto only the ENTROPY degrades; the shape is always a valid v7.\n */\nfunction hzUuidv7(now) {\n var b = new Uint8Array(16)\n var i\n var c = typeof crypto !== 'undefined' ? crypto : undefined\n if (c && typeof c.getRandomValues === 'function') c.getRandomValues(b)\n else for (i = 0; i < 16; i++) b[i] = (Math.random() * 256) | 0\n var t = Math.floor(now === undefined ? Date.now() : now)\n for (i = 5; i >= 0; i--) {\n b[i] = t % 256\n t = Math.floor(t / 256)\n }\n b[6] = 0x70 | (b[6] & 0x0f) // version 7\n b[8] = 0x80 | (b[8] & 0x3f) // variant 0b10\n var h = ''\n for (i = 0; i < 16; i++) {\n h += (b[i] + 0x100).toString(16).slice(1)\n if (i === 3 || i === 5 || i === 7 || i === 9) h += '-'\n }\n return h\n}\n\n/** The cookie jar, or null wherever there is no document to read one from. */\nfunction hzAnonJar() {\n try {\n if (typeof document === 'undefined' || typeof document.cookie !== 'string') return null\n return document\n } catch (e) {\n return null // sandboxed frame with an opaque origin\n }\n}\n\n/** localStorage, or null when the browser refuses it (Safari private mode). */\nfunction hzAnonStore() {\n try {\n if (typeof window === 'undefined' || !window.localStorage) return null\n return window.localStorage\n } catch (e) {\n return null\n }\n}\n\n/** One stored value, or '' — a jar can read as well as refuse to. */\nfunction hzAnonItem(store, name) {\n try {\n return (store && store.getItem(name)) || ''\n } catch (e) {\n return ''\n }\n}\n\n/** The value of cookie `name`, or ''. */\nfunction hzAnonCookie(name) {\n var d = hzAnonJar()\n if (!d) return ''\n var parts = d.cookie.split(';')\n for (var i = 0; i < parts.length; i++) {\n var eq = parts[i].indexOf('=')\n if (eq < 0 || parts[i].slice(0, eq).trim() !== name) continue\n var v = parts[i].slice(eq + 1).trim()\n if (!v) continue\n try {\n return decodeURIComponent(v)\n } catch (e) {\n return v // not percent-encoded — take it as written\n }\n }\n return ''\n}\n\n/** Writes `name` on the registrable domain, for as long as the browser allows. */\nfunction hzAnonWrite(name, value) {\n var d = hzAnonJar()\n if (!d) return\n var host = ''\n var secure = false\n try {\n if (typeof window !== 'undefined' && window.location) {\n host = window.location.hostname || ''\n // A Secure cookie is refused outright by a non-secure origin, which would\n // strand http://localhost dev on the localStorage path.\n secure = window.location.protocol === 'https:'\n }\n } catch (e) {\n /* location unreachable — write a host-only, non-secure cookie */\n }\n // encodeURIComponent leaves a UUID byte-identical while making any value that is\n // not one unable to forge a `;` and inject an attribute.\n var c = name + '=' + encodeURIComponent(value)\n c += '; Path=/; Max-Age=' + HZ_ANON_MAX_AGE + '; SameSite=Lax'\n // Off hanzo.ai (localhost, previews, other registrable domains) the attribute\n // would be rejected and the whole cookie dropped, so it stays host-only there.\n // Prefixing both sides with '.' matches the domain itself and its subdomains\n // while refusing a suffix that merely ends in the same letters (evilhanzo.ai).\n if (('.' + host).slice(-(HZ_ANON_DOMAIN.length + 1)) === '.' + HZ_ANON_DOMAIN) {\n c += '; Domain=' + HZ_ANON_DOMAIN\n }\n if (secure) c += '; Secure'\n try {\n d.cookie = c\n } catch (e) {\n /* cookies refused — localStorage still carries the id */\n }\n}\n\n/**\n * hzAnonId returns the stable anonymous id for this browser, '' during SSR.\n *\n * Resolution is strictly ADDITIVE — every id that already exists is ADOPTED, and\n * only a browser holding none of them is given a new one:\n *\n * cookie · localStorage iam-anon-id · adopted keys · in-memory · mint\n *\n * Minting over an id resets a returning visitor and detaches them from their own\n * history, so the order is the migration: the cookie is the shared home, the two\n * localStorage keys are what the three implementations wrote before it existed,\n * and each is read until nothing is left to adopt.\n *\n * localStorage keeps being written, so a rollback finds everyone where it left\n * them, and a browser that refuses cookies still holds one id per origin.\n */\n/**\n * hzAnonAdopted returns an id already living under a key that used to be canonical,\n * from the cookie jar first — that is the copy shared across subdomains, so a visitor\n * who arrived on one host is the same person on the next.\n */\nfunction hzAnonAdopted(s) {\n for (var i = 0; i < HZ_ANON_ADOPT.length; i++) {\n var id = hzAnonCookie(HZ_ANON_ADOPT[i]) || hzAnonItem(s, HZ_ANON_ADOPT[i])\n if (id) return id\n }\n return ''\n}\n\nfunction hzAnonId() {\n if (typeof window === 'undefined') return '' // SSR / prerender: no browser to identify\n var s = hzAnonStore()\n var id =\n hzAnonCookie(HZ_ANON_KEY) ||\n hzAnonItem(s, HZ_ANON_KEY) ||\n hzAnonAdopted(s) ||\n hzAnonMemo ||\n hzUuidv7()\n hzAnonMemo = id\n hzAnonWrite(HZ_ANON_KEY, id)\n try {\n if (s && s.getItem(HZ_ANON_KEY) !== id) s.setItem(HZ_ANON_KEY, id)\n } catch (e) {\n /* quota exhausted, or a private-mode jar that reads but refuses writes */\n }\n return id\n}\n\n/**\n * hzAnonAdopt makes `id` this browser's anonymous id, replacing whatever it held.\n *\n * A visitor who followed a link from another Hanzo host arrives carrying the id that\n * host minted; keeping the local one splits one journey into two strangers. The\n * caller has already checked the shape.\n */\nfunction hzAnonAdopt(id) {\n hzAnonMemo = id\n hzAnonWrite(HZ_ANON_KEY, id)\n try {\n var s = hzAnonStore()\n if (s) s.setItem(HZ_ANON_KEY, id)\n } catch (e) {\n /* quota exhausted or a read-only jar — the cookie and memo still carry it */\n }\n}\n\n/* ── END hz anon chain ─────────────────────────────────────────────────────── */\n\nexport { hzAnonId, hzAnonAdopt, hzUuidv7 }\n","// SSR-safe browser storage for stable identifiers and first-touch state. Every\n// accessor no-ops (returns undefined) when there is no window/localStorage, so the\n// client imports cleanly in a Next.js server component.\n//\n// The anonymous id is the one value that must outlive an ORIGIN, and it is also\n// the one value the OTHER two distributions must agree with, so its chain lives in\n// ./anon.js and this file only calls it. Everything else here stays origin-local.\n\nimport { hzAnonAdopt, hzAnonId } from './anon.js'\nimport type { Attribution, Cohort } from './types'\nimport { uuidv7 } from './uid'\n\nconst KEY = {\n session: 'hz_session',\n firstTouch: 'hz_first_touch',\n cohort: 'hz_cohort',\n} as const\n\n/** 30-minute inactivity window defines a session (PostHog/GA convention). */\nconst SESSION_TTL_MS = 30 * 60 * 1000\n\nfunction ls(): Storage | undefined {\n try {\n if (typeof window === 'undefined' || !window.localStorage) return undefined\n return window.localStorage\n } catch {\n return undefined // Safari private mode / blocked storage\n }\n}\n\n/**\n * Stable anonymous id, shared by every *.hanzo.ai surface AND by every Hanzo\n * client on the page — the npm client and the hosted tag both run the one\n * chain in ./anon.js, so which snippet a surface loaded no longer decides who the\n * visitor is.\n *\n * It lives in a first-party cookie on the registrable domain because localStorage\n * is ORIGIN-scoped: docs, cloud and console each minted their own id for the same\n * person, so one marketing → docs → signup → checkout journey arrived as several\n * strangers — 463 anonymous identities carried 545 events in a week, about 1.2\n * events each.\n */\nexport function anonId(): string | undefined {\n return hzAnonId() || undefined // '' during SSR / prerender\n}\n\ninterface SessionState {\n id: string\n last: number\n}\n\n/**\n * Current session id, rotated after SESSION_TTL_MS of inactivity.\n *\n * Minted at `now`, so the v7 timestamp the id carries IS the session's start\n * instant — which is what the session rollups partition and order on. Passing the\n * caller's clock rather than reading Date.now() again keeps the id's embedded time\n * and the recorded `last` from disagreeing.\n */\nexport function sessionId(now = Date.now()): string | undefined {\n const s = ls()\n if (!s) return undefined\n let state: SessionState | null = null\n try {\n state = JSON.parse(s.getItem(KEY.session) || 'null')\n } catch {\n state = null\n }\n if (!state || now - state.last > SESSION_TTL_MS) {\n state = { id: uuidv7(now), last: now }\n } else {\n state.last = now\n }\n s.setItem(KEY.session, JSON.stringify(state))\n return state.id\n}\n\n/** Make `id` the current session, as if it had begun now. The session a link\n * carries is the one the visitor is already in, so the journey stays one session\n * across the hop instead of splitting at the host boundary. */\nexport function adoptSession(id: string, now = Date.now()): void {\n const s = ls()\n if (s) s.setItem(KEY.session, JSON.stringify({ id, last: now }))\n}\n\n/** Make `id` the browser's anonymous id, replacing the one it held. */\nexport function adoptAnonId(id: string): void {\n hzAnonAdopt(id)\n}\n\n/** Read the persisted first-touch attribution. */\nexport function getFirstTouch(): Attribution | undefined {\n const s = ls()\n if (!s) return undefined\n try {\n const v = s.getItem(KEY.firstTouch)\n return v ? (JSON.parse(v) as Attribution) : undefined\n } catch {\n return undefined\n }\n}\n\n/** Persist first-touch attribution ONCE — never overwrite an existing record. */\nexport function setFirstTouchOnce(a: Attribution): Attribution {\n const s = ls()\n const existing = getFirstTouch()\n if (existing) return existing\n if (s) s.setItem(KEY.firstTouch, JSON.stringify(a))\n return a\n}\n\n/** Read persisted cohort dimensions. */\nexport function getCohort(): Cohort | undefined {\n const s = ls()\n if (!s) return undefined\n try {\n const v = s.getItem(KEY.cohort)\n return v ? (JSON.parse(v) as Cohort) : undefined\n } catch {\n return undefined\n }\n}\n\n/** Merge + persist cohort dimensions (signupWeek set once). */\nexport function mergeCohort(patch: Cohort): Cohort {\n const s = ls()\n const cur = getCohort() || {}\n const next: Cohort = {\n signupWeek: cur.signupWeek || patch.signupWeek,\n channel: patch.channel || cur.channel,\n refCode: cur.refCode || patch.refCode,\n }\n if (s) s.setItem(KEY.cohort, JSON.stringify(next))\n return next\n}\n","// Cross-domain visitor continuity.\n//\n// Cookies and localStorage stop at the registrable domain, so a visitor who goes\n// hanzo.ai -> hanzo.id (sign-in) -> back arrived as separate people on each host, and\n// the journey across the sign-in redirect could not be read. A link between two\n// Hanzo hosts therefore carries the visitor's identity in three short query\n// parameters, and the destination adopts them before its first pageview and\n// removes them from the address bar.\n//\n// hz_aid anonymous id hz_sid session id hz_ft first-touch attribution\n//\n// They are appended ONLY when the destination host belongs to a brand in ORG_DOMAIN:\n// an id handed to a host outside the table would be handed to a stranger.\n\nimport { orgOf } from './org'\nimport type { Attribution } from './types'\n\nexport const LINK_PARAMS = { anon: 'hz_aid', session: 'hz_sid', firstTouch: 'hz_ft' } as const\n\n/** Ids are v7 UUIDs; anything else in a URL is someone else's input and is refused. */\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\n\nexport const isId = (v: string | null | undefined): v is string => !!v && UUID.test(v)\n\n/** What a link carries. Any field may be absent. */\nexport interface LinkState {\n anonId?: string\n sessionId?: string\n firstTouch?: Attribution\n}\n\n/** First touch as a compact tuple: utm source, medium, campaign, term, content, refCode,\n * referrer, channel. Short because it rides a URL; a tuple because keys cost bytes. */\nexport function encodeFirstTouch(a: Attribution): string {\n return JSON.stringify([\n a.utm.source, a.utm.medium, a.utm.campaign, a.utm.term, a.utm.content,\n a.refCode, a.referrer, a.channel,\n ].map((v) => v ?? ''))\n}\n\nexport function decodeFirstTouch(raw: string | null | undefined): Attribution | undefined {\n if (!raw || raw.length > 1024) return undefined\n try {\n const t: unknown = JSON.parse(raw)\n if (!Array.isArray(t) || t.length !== 8 || t.some((v) => typeof v !== 'string')) return undefined\n const [source, medium, campaign, term, content, refCode, referrer, channel] = t as string[]\n const u = (v: string) => v || undefined\n return {\n utm: { source: u(source), medium: u(medium), campaign: u(campaign), term: u(term), content: u(content) },\n refCode: u(refCode),\n referrer: u(referrer),\n channel: u(channel),\n }\n } catch {\n return undefined\n }\n}\n\n/** linkUrl returns `url` with the visitor's identity appended when its host is\n * Hanzo-owned and is not `fromHost`; otherwise `url` unchanged. Relative URLs\n * resolve against `base`. Never throws. */\nexport function linkUrl(url: string, state: LinkState, fromHost: string, base?: string): string {\n let u: URL\n try {\n u = new URL(url, base)\n } catch {\n return url\n }\n if (u.protocol !== 'https:' && u.protocol !== 'http:') return url\n if (!orgOf(u.hostname) || u.hostname === fromHost) return url\n const set = (k: string, v: string | undefined) => v && u.searchParams.set(k, v)\n if (isId(state.anonId)) set(LINK_PARAMS.anon, state.anonId)\n if (isId(state.sessionId)) set(LINK_PARAMS.session, state.sessionId)\n if (state.firstTouch) set(LINK_PARAMS.firstTouch, encodeFirstTouch(state.firstTouch))\n return u.toString()\n}\n\n/** readLink parses what a link carried out of a location.search value. Invalid\n * values are dropped, not repaired. */\nexport function readLink(search: string): LinkState {\n const q = new URLSearchParams(search || '')\n const a = q.get(LINK_PARAMS.anon)\n const s = q.get(LINK_PARAMS.session)\n return {\n anonId: isId(a) ? a : undefined,\n sessionId: isId(s) ? s : undefined,\n firstTouch: decodeFirstTouch(q.get(LINK_PARAMS.firstTouch)),\n }\n}\n\n/** stripLink returns the path, query and hash of `href` without the link parameters, or\n * undefined when there were none. */\nexport function stripLink(href: string): string | undefined {\n const u = new URL(href)\n let hit = false\n for (const k of Object.values(LINK_PARAMS)) {\n if (u.searchParams.has(k)) {\n u.searchParams.delete(k)\n hit = true\n }\n }\n return hit ? u.pathname + u.search + u.hash : undefined\n}\n","{\n \"name\": \"@hanzo/event\",\n \"version\": \"0.3.52\",\n \"description\": \"Hanzo Event \\u2014 the ONE telemetry client. Emits pageview/event/identify/group to the Hanzo Cloud event stream (POST /v1/event), AND reports errors to Sentry as real Sentry envelopes \\u2014 the error plane needs a DSN, without one nothing reaches Sentry. First-touch attribution, beacon-on-unload, auto error capture, client-side secret/PII scrubbing, a shared event + goal vocabulary. Subsumes @sentry.\",\n \"publishConfig\": {\n \"registry\": \"https://registry.npmjs.org/\",\n \"access\": \"public\",\n \"scope\": \"@hanzo\"\n },\n \"author\": \"Hanzo AI <dev@hanzo.ai>\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"sideEffects\": false,\n \"files\": [\n \"dist\",\n \"src\",\n \"README.md\",\n \"TAXONOMY.md\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/hanzoai/ui.git\",\n \"directory\": \"pkg/event\"\n },\n \"keywords\": [\n \"analytics\",\n \"product-analytics\",\n \"telemetry\",\n \"events\",\n \"error-tracking\",\n \"sentry\",\n \"attribution\",\n \"funnel\",\n \"hanzo\"\n ],\n \"scripts\": {\n \"prepublishOnly\": \"node ../../scripts/guard-publish.mjs\",\n \"build\": \"tsup && tsc --emitDeclarationOnly --declaration --outDir dist && node ../../scripts/dts.mjs\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"typecheck\": \"tsc --noEmit -p tsconfig.json\",\n \"clean\": \"rm -rf dist\"\n },\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./react\": {\n \"import\": {\n \"types\": \"./dist/react.d.ts\",\n \"default\": \"./dist/react.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/react.d.cts\",\n \"default\": \"./dist/react.cjs\"\n }\n }\n },\n \"peerDependencies\": {\n \"react\": \">=19.2.8\"\n },\n \"peerDependenciesMeta\": {\n \"react\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@types/node\": \"catalog:\",\n \"@types/react\": \"catalog:\",\n \"react\": \"catalog:\",\n \"tsup\": \"catalog:\",\n \"typescript\": \"catalog:\",\n \"vitest\": \"catalog:\"\n },\n \"dependencies\": {\n \"@hanzo/events\": \"catalog:\"\n }\n}\n","// The library version, stamped on every event (`libraryVersion`) and on the\n// Sentry `sdk` block. It lives alone so `sentry.ts` can read it without importing\n// `core.ts` — core imports sentry, so the reverse would be an import cycle.\n//\n// Read from package.json rather than restated, because a version restated is a\n// version that drifts: 0.3.38 and 0.3.39 both shipped while this file still said\n// 0.3.37, so every event those builds sent named a library that was two releases\n// behind. `resolveJsonModule` inlines the literal at build time, and tsup shakes\n// the rest of the manifest out.\nimport { version } from '../package.json'\n\nexport const VERSION: string = version\n","// The framework-agnostic event client. ONE API surface over TWO orthogonal\n// planes, sharing one session and one identity:\n//\n// 1. EVENT STREAM — buffered pageview/event/identify/group, flushed as ONE\n// batch to the Hanzo Cloud entry point:\n// POST {host}/v1/event body: { batch: [Event, …] } -> { accepted, dropped }\n// Cloud resolves the tenant server-side (validated session, or the signed\n// publishable key) and stamps it; the client NEVER sends the org.\n//\n// Errors ride the same pipe: a captured exception is ONE event of type 'error'\n// carrying {type, message, frames|stack, handled} plus release, environment,\n// site, product and level. The server files it on the error plane and groups it\n// into an issue. There is no second endpoint, DSN or envelope.\n//\n// Auth is orthogonal — the SAME body to the SAME endpoint, differing only in how the\n// caller proves its tenant:\n//\n// • cookie/session app (host:'') — same-origin credentials ride the request.\n// • bearer app (getToken) — Authorization: Bearer <jwt>.\n// • publishable-key app (ingestKey: 'pk-…') — ?ingest_key=pk-… on the query, on\n// the fetch and the beacon alike, with a text/plain body. Write-only and safe\n// to ship in a bundle; the endpoint resolves it to an org server-side. The query\n// is the carrier neither send needs a header for, which is what keeps both\n// CORS-simple and therefore sendable from a customer's own origin.\n//\n// The wire is the canonical `Event` (== the cloud CaptureEvent).\n\nimport {\n parseAttribution,\n hasAttribution,\n deriveChannel,\n} from './attribution'\nimport { keyForPage } from './org'\nimport { PAGEVIEW } from './events'\nimport { scrubText, withoutFragment } from './scrub'\nimport { framesFromStack, normalizeError as normalizeThrowable } from './throwable'\nimport {\n adoptAnonId,\n adoptSession,\n anonId,\n sessionId,\n getFirstTouch,\n setFirstTouchOnce,\n getCohort,\n mergeCohort,\n} from './storage'\nimport { uuidv7 } from './uid'\nimport { linkUrl, readLink, stripLink } from './link'\nimport type {\n AnalyticsConfig,\n Attribution,\n CaptureErrorOptions,\n Cohort,\n EventKind,\n Exception,\n Transport,\n WireEvent,\n} from './types'\nimport { VERSION } from './version'\n\nexport { VERSION }\n\nconst EVENT_PATH = '/v1/event' // the ONE canonical ingestion entry point\nconst DEFAULT_HOST = 'https://api.hanzo.ai' // the one edge; cookie apps pass host:''\n// The beacon body's type. text/plain is CORS-SAFELISTED, which is the whole\n// property: a safelisted type makes the POST a SIMPLE request, and a simple\n// request needs no preflight. An unloading document does not get a second round\n// trip, so cross-origin a preflighted beacon is never sent at all. The endpoint reads\n// the raw body and dispatches on its first non-space byte, so the type names the\n// CORS class and nothing else.\nconst BEACON_CONTENT_TYPE = 'text/plain'\n\n/** readEnv reads an inlined build-time variable, guarded for SSR. */\nfunction readEnv(name: string): string | undefined {\n try {\n if (typeof process !== 'undefined' && process.env) return process.env[name] || undefined\n } catch {\n /* no process */\n }\n return undefined\n}\n\n/** appendQuery adds a single query param to a URL string — used to carry a\n * publishable key on either send (?ingest_key=…). */\nfunction appendQuery(url: string, key: string, value: string): string {\n return url + (url.includes('?') ? '&' : '?') + key + '=' + encodeURIComponent(value)\n}\n\n/** Normalize anything thrown (Error | string | unknown) into an Exception. */\n/** normalizeError adapts the hostile-input-safe normalizer (sentry.ts) to the\n * stream's Exception shape: a thrown object may define `name`/`message`/`stack`\n * as throwing getters. */\nfunction normalizeError(err: unknown): Exception {\n const n = normalizeThrowable(err)\n const frames = framesFromStack(n.stack)\n .slice(-50)\n .map((f) => ({ function: f.function, file: f.filename, line: f.lineno, column: f.colno }))\n return { type: n.name, message: n.message, stack: n.stack, frames }\n}\n\n// React Native defines a `window` but no `document` (and no `window.location`),\n// so `typeof window !== 'undefined'` alone took the browser path there and\n// `init()` threw on `window.location.search`. Requiring `document` makes RN read\n// as non-browser: `init()` returns early (skips attribution + the visibility/\n// unload listeners RN doesn't have), while `capture()`/`flush()` — which are NOT\n// gated on this and post through plain `fetch` — still emit. So the client is\n// inert-safe under SSR/Node and live on RN, without a second transport.\n/** The screen and language a page view carries, for the readers that derive device and locale. */\nconst viewport = (): Record<string, string> =>\n isBrowser()\n ? { screen: `${window.screen?.width ?? 0}x${window.screen?.height ?? 0}`, language: navigator.language || '' }\n : {}\n\nconst isBrowser = () => typeof window !== 'undefined' && typeof document !== 'undefined'\n\n/** serializeBatch stringifies a batch, salvaging what it can. `properties` is\n * arbitrary caller data — a DOM node, a React synthetic event, an axios error are\n * all circular, and a getter on one can throw — so a whole batch must never be\n * lost to a single poisoned event. Falls back to per-event serialization, then to\n * keeping the event and dropping its properties. Returns null only when nothing\n * at all survives. */\nfunction serializeBatch(batch: WireEvent[]): string | null {\n try {\n return JSON.stringify({ batch })\n } catch {\n /* one bad event — salvage the rest below */\n }\n const parts: string[] = []\n for (const e of batch) {\n try {\n parts.push(JSON.stringify(e))\n } catch {\n try {\n // Keep the event (identity, session, type all matter); drop the payload\n // that could not be serialized, and say so rather than lying by omission.\n parts.push(JSON.stringify({ ...e, properties: { $unserializable: true } }))\n } catch {\n /* unsalvageable — drop this ONE event, never the batch */\n }\n }\n }\n return parts.length > 0 ? '{\"batch\":[' + parts.join(',') + ']}' : null\n}\n\n/** DefaultTransport: fetch(keepalive) for authenticated/normal sends;\n * navigator.sendBeacon for page-unload beacons.\n *\n * A publishable key rides the ?ingest_key query on BOTH, which is what keeps\n * both CORS-simple: the query is the one carrier neither send needs a header\n * for, and a simple request leaves the browser from any origin — permission is\n * asked to READ a cross-origin response, never to send one. That is what lets a\n * bundled client run on a customer's own page. A JWT is first-party by\n * construction, so it keeps Authorization and the session it travels with.\n *\n * `contentType` names the FETCH request's Content-Type (the error plane sets the\n * envelope type there, and keeps the header carrier with it). The beacon body is\n * always BEACON_CONTENT_TYPE: its type is a CORS class, not a payload\n * description, and a beacon that is not a simple request is never sent. */\nclass DefaultTransport implements Transport {\n send(\n url: string,\n body: string,\n opts: {\n beacon: boolean\n token?: string\n ingestKey?: string\n contentType?: string\n debug?: boolean\n },\n ): void {\n if (opts.beacon && isBrowser() && typeof navigator.sendBeacon === 'function') {\n const beaconUrl = opts.ingestKey ? appendQuery(url, 'ingest_key', opts.ingestKey) : url\n try {\n // The answer is whether the agent QUEUED the batch — false for a body past\n // the beacon size limit, or a full queue. Only a queued batch ends the\n // send; a refused one falls through to the keepalive fetch below.\n const queued = navigator.sendBeacon(\n beaconUrl,\n new Blob([body], { type: BEACON_CONTENT_TYPE }),\n )\n if (queued) return\n if (opts.debug) console.warn('[event] beacon refused, falling back to fetch')\n } catch {\n /* fall through to fetch */\n }\n }\n if (typeof fetch !== 'function') return\n // A publishable key makes the send a CORS SIMPLE request: the key rides the\n // query, the body is text/plain, and nothing asks for credentials. That is what\n // lets a bundled client run on a customer's own page — every send from there is\n // cross-origin, and an Authorization header or a JSON type preflights the POST\n // for an origin that cannot pass one. A JWT is first-party by construction, so\n // it keeps the header and the session it travels with, and so does the error\n // plane, which names its own envelope type.\n const simple = opts.ingestKey !== undefined && opts.token === undefined && opts.contentType === undefined\n const headers: Record<string, string> = {\n 'Content-Type': simple ? BEACON_CONTENT_TYPE : (opts.contentType ?? 'application/json'),\n }\n // A signed-in page sends the key (which project) in the query AND the person's bearer\n // (who) in the header; the bearer never replaces the key.\n const bearer = simple ? undefined : (opts.token ?? opts.ingestKey)\n if (bearer) headers.Authorization = `Bearer ${bearer}`\n void fetch(opts.ingestKey ? appendQuery(url, 'ingest_key', opts.ingestKey) : url, {\n method: 'POST',\n headers,\n body,\n keepalive: true,\n credentials: simple ? 'omit' : 'include',\n })\n .then((res) => {\n // Telemetry loss never throws into the app — but silence is how this\n // client lost the fleet's errors in the first place. Under `debug`, say\n // so. A rejected ingest (the CORS allowlist 403s non-production origins,\n // so local dev NEVER reports) is otherwise indistinguishable from success.\n if (!res.ok && opts.debug) {\n console.warn('[event] ingest rejected', res.status, url.split('?')[0])\n }\n })\n .catch((e: unknown) => {\n if (opts.debug) console.warn('[event] ingest failed', url.split('?')[0], e)\n })\n }\n}\n\nexport class Analytics {\n private cfg: Required<\n Pick<AnalyticsConfig, 'product' | 'batchSize' | 'flushIntervalMs' | 'enabled' | 'captureErrors'>\n > &\n AnalyticsConfig\n private transport: Transport\n private queue: WireEvent[] = []\n private timer: ReturnType<typeof setTimeout> | null = null\n private personId?: string\n private attribution: Attribution = { utm: {} }\n private cohort: Cohort = {}\n private started = false\n /** The view pageview() last counted — path + location. */\n private counted?: string\n /** Guards against an error thrown *inside* the error path re-entering it. */\n private reentrant = false\n\n constructor(config: AnalyticsConfig) {\n this.cfg = {\n host: DEFAULT_HOST,\n batchSize: 20,\n flushIntervalMs: 5000,\n enabled: true,\n captureErrors: true,\n ...config,\n // The publishable key resolves from ONE live source, never a literal baked\n // beside the code. Most specific first:\n // 1. an explicit `ingestKey` in config;\n // 2. NEXT_PUBLIC_PUBLISHABLE_KEY, the inlined build-time env the fleet\n // carries end to end — KMS `deploy/PUBLISHABLE_KEY` -> the PUBLISHABLE_KEY\n // build-arg -> the NEXT_PUBLIC_ prefix Next inlines.\n //\n // 3. the org that owns the HOST this page is served from (`org.ts`).\n //\n // Step 3 fires only when a surface configured NOTHING, so it never overrides\n // the KMS chain above — it replaces going dark with reporting to the right\n // brand. That is what a static export needs: `output: export` inlines no env,\n // so before this the only way to report was to commit a key literal, and the\n // fleet grew one copy per site of a value with a single source.\n //\n // A surface no brand claims still has no key, and the edge REFUSES an\n // unattributed event (401 `ingest_key_required`) — the reserved `$public`\n // tenant that once caught keyless beacons is retired, and anonymous ingest is\n // refused at every edge on every brand host. So there is no quiet fallback to\n // rely on: an event lands in the org a credential names, or it does not land.\n ingestKey:\n config.ingestKey ?? readEnv('NEXT_PUBLIC_PUBLISHABLE_KEY') ?? keyForPage(),\n }\n this.transport = config.transport ?? new DefaultTransport()\n }\n\n /** adopt gives this client a credential it does not have. The key belongs to\n * the stream, not to whichever caller happened to ask for the handle first,\n * so a later caller carrying one hands it over. Present fields are never overwritten: the first caller's key stays. */\n adopt(config: AnalyticsConfig): void {\n if (config.ingestKey && !this.cfg.ingestKey) this.cfg.ingestKey = config.ingestKey\n if (config.getToken && !this.cfg.getToken) this.cfg.getToken = config.getToken\n }\n\n /** init is idempotent and browser-only for its side effects: capture first-touch\n * attribution, hydrate cohort, register the unload flush, and (unless opted out)\n * auto-capture unhandled errors. Safe to call from a React effect on every\n * render. */\n init(): void {\n if (this.started || !this.cfg.enabled) return\n this.started = true\n if (!isBrowser()) return\n\n // A link from another Hanzo host carries the visitor with it. Adopt it FIRST, so\n // the first pageview is already the same person, session and first touch.\n const linked = readLink(window.location.search)\n if (linked.anonId) adoptAnonId(linked.anonId)\n if (linked.sessionId) adoptSession(linked.sessionId)\n const clean = stripLink(window.location.href)\n if (clean !== undefined) {\n try {\n window.history.replaceState(window.history.state, '', clean)\n } catch {\n /* a sandboxed frame may refuse; the params are then simply visible */\n }\n }\n\n const parsed = parseAttribution(window.location.search, document.referrer)\n // The first touch the link carries is the visit's real origin. Without it this\n // host's own \"first touch\" would be the referring Hanzo page, which says nothing.\n const first = linked.firstTouch && !getFirstTouch() ? setFirstTouchOnce(linked.firstTouch) : undefined\n this.attribution =\n first ?? (hasAttribution(parsed) ? setFirstTouchOnce(parsed) : getFirstTouch() ?? parsed)\n this.cohort = mergeCohort({\n channel: this.attribution.channel ?? deriveChannel(this.attribution),\n refCode: this.attribution.refCode,\n })\n\n const flushHidden = () => {\n if (document.visibilityState === 'hidden') this.flush(true)\n }\n window.addEventListener('visibilitychange', flushHidden)\n window.addEventListener('pagehide', () => this.flush(true))\n\n // Unhandled errors and rejected promises are reported as type:'error' events.\n if (this.cfg.captureErrors) {\n window.addEventListener('error', (e: ErrorEvent) => {\n this.captureError(e.error ?? e.message, { handled: false })\n })\n window.addEventListener('unhandledrejection', (e: PromiseRejectionEvent) => {\n this.captureError(e.reason, { handled: false })\n })\n }\n }\n\n /** link returns `url` carrying this visitor's anonymous id, session and first\n * touch when the destination is a Hanzo-owned host, so the journey continues\n * across the hop. Any other URL comes back unchanged. */\n link(url: string): string {\n if (!isBrowser()) return url\n if (!this.started) this.init()\n return linkUrl(\n url,\n { anonId: anonId(), sessionId: sessionId(), firstTouch: this.attribution },\n window.location.hostname,\n window.location.href,\n )\n }\n\n /** authorize decorates an OAuth authorize URL for the redirect to IAM and flushes\n * what is queued, because the page is about to unload. Assign the result to\n * `location`. */\n authorize(url: string): string {\n const out = this.link(url)\n this.flush(true)\n return out\n }\n\n /** identify binds the current visitor to a stable person id (post-login). */\n identify(personId: string, traits?: Record<string, unknown>): void {\n this.personId = personId\n this.enqueue('identify', undefined, { properties: traits })\n }\n\n /** group associates the visitor with an org/team (analytics grouping, not the\n * server tenant — the server still derives tenant from the session). */\n group(groupId: string, traits?: Record<string, unknown>): void {\n this.enqueue('group', undefined, { groupId, properties: traits })\n }\n\n /** pageview records a $pageview for the current (or given) location, once per\n * view. A view is the path plus the full location, so a query or hash change\n * is a new one and a repeat call for the same place is not. */\n pageview(path?: string, properties?: Record<string, unknown>): void {\n // No `url` here: build() reads window.location.href for every event, in the\n // same tick, so this recomputed it to the identical value. Only `path` is\n // passed, because a route change fires before window.location has caught up\n // and the caller's value has to win.\n const p = path ?? (isBrowser() ? window.location.pathname : undefined)\n // Counting a page once is the client's rule, not each caller's. A page holds\n // several emitters that each correctly believe they count the first view —\n // the provider's autoPageview, a router hook, a nav autocapture — and per\n // emitter state cannot see the others. On the stream they are one page.\n const view = (p ?? '') + '\\0' + (isBrowser() ? window.location.href : '')\n if (view === this.counted) return\n this.counted = view\n this.enqueue('pageview', PAGEVIEW, { path: p, properties: { ...viewport(), ...properties } })\n }\n\n /** capture records a named product event with optional properties. Commerce\n * fields (productId/quantity/revenue/currency) may be passed for order events. */\n capture(\n event: string,\n properties?: Record<string, unknown>,\n commerce?: Pick<WireEvent, 'productId' | 'quantity' | 'revenue' | 'currency'>,\n ): void {\n this.enqueue('event', event, { properties, ...commerce })\n }\n\n /** captureError reports a caught error, an unhandled rejection, a React render\n * error, or a manual report as ONE event of type 'error' on the one stream.\n * It carries the exception (type, message, frames, stack, handled) and the\n * release, environment, site, product and level that group and scope it, and\n * flushes promptly (a crash may unload the page moments later). Never throws\n * back into the app. */\n captureError(err: unknown, context?: CaptureErrorOptions): void {\n // A failure inside the error path must not recurse through the global handlers.\n if (this.reentrant) return\n this.reentrant = true\n try {\n const handled = context?.handled ?? true\n const ex = normalizeError(err)\n ex.handled = handled\n this.enqueue('error', undefined, {\n error: ex,\n level: context?.level ?? (handled ? 'error' : 'fatal'),\n release: this.cfg.release ?? readEnv('NEXT_PUBLIC_HANZO_RELEASE'),\n environment: this.cfg.environment ?? readEnv('NODE_ENV'),\n site: isBrowser() ? window.location.hostname : undefined,\n properties: context?.properties,\n })\n this.flush()\n } catch {\n /* the error path never takes the app down */\n } finally {\n this.reentrant = false\n }\n }\n\n /** setCohort persists cohort dimensions (e.g. signupWeek at signup) so they ride\n * every subsequent event. */\n setCohort(patch: Cohort): void {\n this.cohort = mergeCohort(patch)\n }\n\n /** flush drains the buffer to the server as ONE batch through the ONE ingest\n * endpoint POST /v1/event, body { batch: [Event…] }. beacon=true selects the\n * unload-safe transport. Auth is orthogonal to the wire:\n *\n * • publishable key set → rides ?ingest_key=pk-… on both sends, keeping each\n * a CORS-simple request that any origin may send.\n * • else a bearer JWT rides Authorization (fetch only — sendBeacon cannot\n * carry a header, so token apps fall back to keepalive fetch on unload).\n * • else a cookie app rides same-origin credentials (beacon carries the\n * cookie fine).\n */\n flush(beacon = false): void {\n if (!this.cfg.enabled || this.queue.length === 0) return\n const batch = this.queue\n this.queue = []\n this.clearTimer()\n\n // Two kinds of credential, and both ride when both are held: the publishable key\n // names the project, the bearer names the person. The bearer never replaces the key.\n const token = this.cfg.getToken?.() ?? undefined\n const key = this.cfg.ingestKey?.trim() || undefined\n // Only a bearer JWT blocks the beacon: sendBeacon cannot set an Authorization\n // header. A pk- rides ?ingest_key; a cookie rides credentials.\n const useBeacon = beacon && !token\n const body = serializeBatch(batch)\n if (body === null) {\n if (this.cfg.debug) console.debug('[event] flush → dropped, batch unserializable')\n return\n }\n if (this.cfg.debug) console.debug('[event] flush →', EVENT_PATH, batch.length)\n this.transport.send(this.cfg.host + EVENT_PATH, body, {\n beacon: useBeacon,\n token,\n ingestKey: key,\n debug: this.cfg.debug,\n })\n }\n\n // ── internals ────────────────────────────────────────────────────────────\n\n private enqueue(kind: EventKind, event: string | undefined, extra: Partial<WireEvent>): void {\n if (!this.cfg.enabled) return\n if (!this.started) this.init()\n this.queue.push(this.build(kind, event, extra))\n if (this.queue.length >= this.cfg.batchSize) this.flush()\n else this.schedule()\n }\n\n private build(kind: EventKind, event: string | undefined, extra: Partial<WireEvent>): WireEvent {\n const anon = anonId()\n const wire: WireEvent = {\n messageId: uuidv7(),\n type: kind,\n event,\n timestamp: new Date().toISOString(),\n distinctId: this.personId ?? anon,\n anonymousId: anon,\n personId: this.personId,\n sessionId: sessionId(),\n product: this.cfg.product,\n referrer: this.attribution.referrer,\n utm: this.attribution.utm,\n refCode: this.cohort.refCode ?? this.attribution.refCode,\n channel: this.cohort.channel ?? this.attribution.channel,\n signupWeek: this.cohort.signupWeek,\n // Where the event happened, stamped for every kind rather than only for\n // pageviews. An interaction is reported against the page it happened on,\n // and autocapture ($click/$input/$change) reaches the wire through\n // capture(), which supplies no location — so every click arrived with an\n // empty url and path, and `host`, derived from url, was empty with them.\n // That is unattributable to a page, which is the one thing a heatmap\n // needs. Read here, at the single point every event is built, so it\n // cannot go missing from a call site again.\n //\n // Before `...extra`: pageview() passes an explicit path for route\n // changes that fire before window.location has caught up, and that value\n // has to win over the one read here.\n url: isBrowser() ? window.location.href : undefined,\n path: isBrowser() ? window.location.pathname : undefined,\n library: '@hanzo/event',\n libraryVersion: VERSION,\n ...extra,\n }\n\n // A location is free text an attacker (or an ordinary product flow) controls,\n // and it is now stamped on EVERY event rather than only pageviews — so the\n // one field that is always a URL gets the same policy the error plane has\n // always applied to error text. A password-reset, invite or magic link puts\n // a JWT in the query and an address in `?email=`; without this, one click on\n // that page ships both to the warehouse in cleartext, and every later click\n // repeats it.\n //\n // AFTER `...extra`, deliberately. A call site can pass its own location —\n // pageview() passes `path`, and until this commit it passed `url` too — and\n // `extra` merges over the fields read above, so scrubbing at the read would\n // have left the highest-volume event emitting a raw location while looking\n // scrubbed. Applied to the ASSEMBLED record, the guarantee holds for every\n // call site, including ones not written yet.\n //\n // `scrubText` is the SAME policy as the error plane (secrets always,\n // PII unless capturePII) rather than a second URL-specific redactor: one\n // definition of \"must not leave the browser\", already tested, mirroring the\n // server's. Guarded on presence so an absent field stays absent instead of\n // becoming the empty string that `host` derivation reads as a page.\n //\n // The fragment goes first and whole: nothing after `#` is ever the server's\n // (see withoutFragment), so it is dropped rather than scrubbed.\n const capturePII = this.cfg.capturePII ?? false\n if (wire.url) wire.url = scrubText(withoutFragment(wire.url), capturePII)\n if (wire.path) wire.path = scrubText(withoutFragment(wire.path), capturePII)\n if (wire.referrer) wire.referrer = scrubText(withoutFragment(wire.referrer), capturePII)\n return wire\n }\n\n private schedule(): void {\n if (this.timer || !this.cfg.enabled) return\n this.timer = setTimeout(() => {\n this.timer = null\n this.flush()\n }, this.cfg.flushIntervalMs)\n }\n\n private clearTimer(): void {\n if (this.timer) {\n clearTimeout(this.timer)\n this.timer = null\n }\n }\n}\n\n// ── one stream, one client ──────────────────────────────────────────────────\n//\n// A page has ONE event stream per (host, product): one queue, one anon id, one\n// credential. Two clients on it split the batch and double the pageview, and\n// the half built by the caller that had no key is refused at the edge — so the\n// same page is both over- and under-counted, and neither number says so.\n//\n// Two callers ask for that stream on any real page and both are right to: the\n// app mounts a provider, and the component library mounts its own telemetry.\n// Neither can see the other, so the fix cannot live in either. It lives here,\n// where the stream is: asking twice returns the same client.\n//\n// The registry is on the PAGE, under a `Symbol.for` slot, not in module scope.\n// `@hanzo/event` and `@hanzo/event/react` are separate bundles that each carry\n// a copy of this module, so a module-scope map is per-copy and the two copies\n// never see each other's — which is exactly how the duplicate arises. A\n// well-known symbol is the one slot every copy resolves to the same value.\n//\n// Browser only. A server process serves many visitors, and one client shared\n// across requests would carry one visitor's personId into the next.\nconst CLIENTS = Symbol.for('hanzo.event.clients')\n\nfunction registry(): Map<string, Analytics> {\n const g = globalThis as unknown as Record<symbol, Map<string, Analytics> | undefined>\n const existing = g[CLIENTS]\n if (existing) return existing\n const fresh = new Map<string, Analytics>()\n g[CLIENTS] = fresh\n return fresh\n}\n\n/** resetClients drops the page's clients, so the next `createAnalytics` for a\n * stream builds a fresh one.\n *\n * A real page loads once and never needs this. A TEST RUNNER is what it exists\n * for: one document, many mounts, each meant to be its own page. The second one\n * gets a client that already counted this location, so its pageview is\n * correctly suppressed and the suite reads it as \"nothing was emitted\".\n *\n * It is exported so a suite calls this instead of reaching for the slot itself.\n * A consumer that deletes the registry from its own code path takes the\n * guarantee with it: `<Provider/>` unmount/remount is not a new page, and the\n * fresh client it would get counts the same view again. */\nexport function resetClients(): void {\n const g = globalThis as unknown as Record<symbol, Map<string, Analytics> | undefined>\n delete g[CLIENTS]\n}\n\n/** createAnalytics returns the client for a stream, building it on first ask.\n * This is the ONE way to get a client: `new Analytics` bypasses the registry\n * and is for tests and for a deliberately separate instance. */\nexport function createAnalytics(config: AnalyticsConfig): Analytics {\n // A disabled client emits nothing, so it can double nothing and does not take\n // the stream. Callers reach their answer at different moments — a provider\n // whose ownership resolves in an effect renders once saying `false` before it\n // has decided anything — and the client built in that moment must not become\n // the one the page keeps. Registering it would silence the page, and adopting\n // `enabled` from a later caller would let one surface overrule another's\n // reading of consent. Neither: it is simply not the stream's client.\n if (!isBrowser() || config.enabled === false) return new Analytics(config)\n const key = (config.host ?? DEFAULT_HOST) + '\\0' + config.product\n const clients = registry()\n const existing = clients.get(key)\n if (existing) {\n existing.adopt(config)\n return existing\n }\n const fresh = new Analytics(config)\n clients.set(key, fresh)\n return fresh\n}\n\n// Re-export the hydrate helpers so consumers can read persisted cohort/attribution\n// (e.g. to send refCode to the referrals API) without reaching into storage.\nexport { getCohort, getFirstTouch }\n","// First-party cookies for consent, the ad click and the browser ids the ad\n// platforms match on. Set on the registrable domain so every subdomain of a site\n// reads the same choice and the same click; on localhost or an address it stays\n// on the host.\n\nconst DAY = 86_400\n\n/** The domain attribute for this host, or '' to keep the cookie on the host. */\nfunction domain(): string {\n const h = window.location.hostname\n if (h === 'localhost' || /^[\\d.]+$/.test(h) || h.includes(':')) return ''\n const parts = h.split('.')\n return parts.length > 2 ? `; Domain=.${parts.slice(-2).join('.')}` : `; Domain=.${h}`\n}\n\n/** Reads one cookie, or undefined. */\nexport function get(name: string): string | undefined {\n if (typeof document === 'undefined') return undefined\n const hit = document.cookie.split('; ').find((c) => c.startsWith(`${name}=`))\n return hit ? decodeURIComponent(hit.slice(name.length + 1)) : undefined\n}\n\n/** Writes one cookie for `days`. */\nexport function set(name: string, value: string, days: number): void {\n if (typeof document === 'undefined') return\n const secure = window.location.protocol === 'https:' ? '; Secure' : ''\n document.cookie = `${name}=${encodeURIComponent(value)}; Max-Age=${days * DAY}; Path=/; SameSite=Lax${domain()}${secure}`\n}\n","// Cookie consent: what a visitor lets a site measure and share, and the rule for\n// what a visitor who has not chosen is presumed to allow.\n//\n// Three categories. Analytics is our own stream and GA4. Marketing is the ad\n// platforms measuring the conversions they bought (Google Ads, Meta, LinkedIn,\n// X, TikTok) and every server-side send. Ads is those platforms using the visit\n// for audiences; off, Google's ad_personalization is denied and Meta runs under\n// Limited Data Use.\n//\n// THE DEFAULT depends on where the visitor is. In the EU, UK and Switzerland,\n// and anywhere else that is not a US state, nothing is allowed until they say\n// so: a visitor with no stored choice has allowed nothing. In the US the default\n// is on and the choice is an opt-out (\"Do not sell or share my personal\n// information\"). Global Privacy Control, and Do Not Track, turn marketing and\n// ads off in every region whatever is stored: California reads GPC as the opt-out\n// of sale and sharing.\n//\n// The region comes from cloud. The site's tag config (`GET /v1/project/tags`) answers\n// with the rule that binds this visitor, resolved at the edge from where the request\n// came from (`serve`). Until it answers, and if it never does, the zone is the browser's\n// own time zone and a zone that is not a US zone is treated as opt-in: wrong in the\n// safe direction, a US visitor on a foreign clock is asked and a European is never\n// presumed to have agreed.\n//\n// The policy has a version. A choice is stored beside the version it was made under\n// (`hz_consent_v`); when the policy changes, the stored choice no longer counts and the\n// visitor is asked again.\n//\n// The choice is a first-party cookie, `hz_consent`, on the registrable domain\n// for 13 months: the granted categories, comma separated. cloud reads the same\n// string off each event's `consent` property.\n\nimport { get, set } from './cookie'\n\nexport const CONSENT_COOKIE = 'hz_consent'\n\n/** The policy version the stored choice was made under. */\nexport const CONSENT_VERSION_COOKIE = 'hz_consent_v'\n\n/** Fired on `window` when cloud's rule for this visitor arrives. */\nexport const POLICY_EVENT = 'hzpolicy'\n\n/** Fired on `window` whenever a choice is stored. */\nexport const CONSENT_EVENT = 'hzconsent'\n\nexport interface Choice {\n analytics: boolean\n marketing: boolean\n ads: boolean\n}\n\nexport type Region = 'opt-in' | 'opt-out'\n\n/** The rule cloud resolved for this visitor. */\nexport interface Policy {\n region: string\n mode: Region\n defaults: Choice\n gpc: boolean\n version: number\n notice?: string\n}\n\nlet served: Policy | undefined\n\n/** Takes cloud's rule for this visitor and tells the page, so a banner drawn early redraws. */\nexport function serve(p: unknown): void {\n if (p == null) {\n served = undefined\n return\n }\n const d = p as Partial<Policy>\n if ( (d.mode !== 'opt-in' && d.mode !== 'opt-out') || !d.defaults) return\n served = {\n region: String(d.region ?? ''),\n mode: d.mode,\n defaults: { analytics: !!d.defaults.analytics, marketing: !!d.defaults.marketing, ads: !!d.defaults.ads },\n gpc: d.gpc === true,\n version: Number(d.version) || 0,\n notice: typeof d.notice === 'string' ? d.notice : undefined,\n }\n if (typeof window !== 'undefined') window.dispatchEvent(new Event(POLICY_EVENT))\n}\n\n/** The rule cloud resolved, once it has answered. */\nexport const policy = (): Policy | undefined => served\n\ntype Nav = { doNotTrack?: string; msDoNotTrack?: string; globalPrivacyControl?: boolean }\n\nconst US =\n /^(America\\/(New_York|Chicago|Denver|Los_Angeles|Phoenix|Anchorage|Adak|Boise|Detroit|Juneau|Sitka|Nome|Yakutat|Menominee|Metlakatla|Indiana\\/.*|Kentucky\\/.*|North_Dakota\\/.*)|Pacific\\/Honolulu|US\\/.*)$/\n\n/** Whether the browser sends Global Privacy Control. */\nexport function gpc(): boolean {\n if (typeof navigator === 'undefined') return false\n return (navigator as unknown as Nav).globalPrivacyControl === true\n}\n\n/** Whether the browser sends Global Privacy Control or Do Not Track. */\nexport function refused(): boolean {\n if (typeof window === 'undefined') return false\n const n = navigator as unknown as Nav\n const dnt = n.doNotTrack ?? (window as unknown as Nav).doNotTrack ?? n.msDoNotTrack\n return gpc() || dnt === '1' || dnt === 'yes'\n}\n\n/** Which rule applies to this visitor. */\nexport function region(): Region {\n if (served) return served.mode\n try {\n const zone = Intl.DateTimeFormat().resolvedOptions().timeZone ?? ''\n return US.test(zone) ? 'opt-out' : 'opt-in'\n } catch {\n return 'opt-in'\n }\n}\n\n/** Whether the visitor has stored a choice. */\nexport function stored(): boolean {\n if (get(CONSENT_COOKIE) === undefined) return false\n return !served || get(CONSENT_VERSION_COOKIE) === String(served.version)\n}\n\n/** The visitor's choice: the stored one, else the regional default, with GPC applied. */\nexport function read(): Choice {\n const kept = stored() ? get(CONSENT_COOKIE) : undefined\n const on =\n kept !== undefined\n ? kept.split(',')\n : served\n ? (['analytics', 'marketing', 'ads'] as const).filter((k) => served!.defaults[k])\n : region() === 'opt-in'\n ? []\n : gpc()\n ? ['analytics']\n : ['analytics', 'marketing', 'ads']\n const has = (k: string) => on.includes(k)\n return { analytics: has('analytics'), marketing: has('marketing') && !gpc(), ads: has('ads') && !gpc() }\n}\n\n/** Whether the consent banner must be shown: an opt-in visitor who has not chosen. */\nexport function asks(): boolean {\n return typeof document !== 'undefined' && region() === 'opt-in' && !stored()\n}\n\n/** Whether a small notice must be shown: an opt-out visitor who has not yet seen it. */\nexport function notices(): boolean {\n return typeof document !== 'undefined' && region() === 'opt-out' && !stored()\n}\n\n/** The choice as the `consent` property and the cookie spell it. */\nexport function render(c: Choice): string {\n return (['analytics', 'marketing', 'ads'] as const).filter((k) => c[k]).join(',')\n}\n\n/**\n * Stores a choice and tells the page. The tags react without a reload: a\n * category just allowed loads its libraries, and Google's consent state is\n * updated. An ad library already running cannot be unloaded, so a choice that\n * withdraws marketing takes effect for what has not loaded yet and for every\n * later page.\n */\nexport function save(c: Choice): void {\n const out: Choice = { analytics: c.analytics, marketing: c.marketing && !gpc(), ads: c.ads && !gpc() }\n set(CONSENT_COOKIE, render(out), 395)\n set(CONSENT_VERSION_COOKIE, String(served?.version ?? 0), 395)\n if (typeof window !== 'undefined') window.dispatchEvent(new Event(CONSENT_EVENT))\n}\n\n/** Accept every category. */\nexport const acceptAll = (): void => save({ analytics: true, marketing: true, ads: true })\n\n/** Refuse every optional category. */\nexport const rejectAll = (): void => save({ analytics: false, marketing: false, ads: false })\n","// React bindings for @hanzo/event — a provider, an accessor hook, a route-change\n// pageview hook, and an error boundary. Framework-neutral: it takes the current\n// path as an argument (the Next app wires usePathname(); a Vite/router app passes\n// its own), so this file never imports next/*.\n//\n// 'use client'\n// import { AnalyticsProvider, useAnalytics, usePageview, ErrorBoundary } from '@hanzo/event/react'\n//\n// <AnalyticsProvider config={{ product: 'console' }}>…</AnalyticsProvider>\n// const a = useAnalytics(); usePageview(usePathname())\n\nimport {\n Component,\n createContext,\n createElement,\n useContext,\n useEffect,\n useRef,\n useSyncExternalStore,\n type ErrorInfo,\n type ReactNode,\n} from 'react'\nimport { Analytics, createAnalytics } from './core'\nimport type { AnalyticsConfig } from './types'\nimport { CONSENT_EVENT, POLICY_EVENT, read, render, type Choice } from './consent'\n\nconst Ctx = createContext<Analytics | null>(null)\n\nexport interface AnalyticsProviderProps {\n /** Provide a pre-built client, or a config to build one. */\n client?: Analytics\n config?: AnalyticsConfig\n /** Fire a pageview for the initial load (default true). */\n autoPageview?: boolean\n children: ReactNode\n}\n\nexport function AnalyticsProvider(props: AnalyticsProviderProps) {\n const { client, config, autoPageview = true, children } = props\n // No memo. createAnalytics returns the client for a stream, so asking on every\n // render hands back the same object — the identity a memo used to be here to\n // preserve. Memoizing construction is what made a config change unreachable\n // (deps held `client` alone) while adding `config` would have built a client\n // per render, since call sites pass an object literal.\n if (!client && !config) throw new Error('AnalyticsProvider requires `client` or `config`')\n const instance = client ?? createAnalytics(config as AnalyticsConfig)\n\n useEffect(() => {\n instance.init()\n if (autoPageview) instance.pageview()\n }, [instance, autoPageview])\n\n return createElement(Ctx.Provider, { value: instance }, children)\n}\n\n/** useAnalytics returns the client. Outside a provider it returns a no-op-safe\n * null-guarded proxy so calls never throw during SSR/tests. */\nexport function useAnalytics(): Analytics {\n const a = useContext(Ctx)\n if (!a) return noop\n return a\n}\n\n/** usePageview fires a pageview on every route CHANGE (not the initial mount —\n * the provider's autoPageview covers that, so pages are counted exactly once). */\nexport function usePageview(path: string | null | undefined): void {\n const a = useContext(Ctx)\n const first = useRef(true)\n useEffect(() => {\n if (first.current) {\n first.current = false\n return\n }\n if (a && path) a.pageview(path)\n }, [a, path])\n}\n\n// A shared no-op client for use outside a provider — keeps call sites total.\nconst noop = new Analytics({ product: 'unknown', enabled: false })\n\nexport interface ErrorBoundaryProps {\n children: ReactNode\n /** Rendered when a child throws. A function receives the error + a reset. */\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode)\n /** Explicit client; defaults to the one from AnalyticsProvider. */\n client?: Analytics\n}\n\ninterface ErrorBoundaryState {\n error: Error | null\n}\n\n/** ErrorBoundary reports React render errors to the client as error events —\n * React swallows these before window.onerror sees them, so a boundary is the\n * ONLY way to capture them. This is the React half of the @sentry replacement.\n * Pair it with AnalyticsProvider (it reads the client from context), or pass an\n * explicit `client`. */\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n static contextType = Ctx\n declare context: React.ContextType<typeof Ctx>\n state: ErrorBoundaryState = { error: null }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { error }\n }\n\n componentDidCatch(error: Error, info: ErrorInfo): void {\n const client = this.props.client ?? this.context ?? undefined\n client?.captureError(error, {\n handled: false,\n properties: { componentStack: info.componentStack, react: true },\n })\n }\n\n private reset = () => this.setState({ error: null })\n\n render(): ReactNode {\n const { error } = this.state\n if (error === null) return this.props.children\n const { fallback } = this.props\n if (typeof fallback === 'function') return fallback(error, this.reset)\n return fallback ?? null\n }\n}\n\nconst listen = (on: () => void) => {\n window.addEventListener(CONSENT_EVENT, on)\n window.addEventListener(POLICY_EVENT, on)\n return () => {\n window.removeEventListener(CONSENT_EVENT, on)\n window.removeEventListener(POLICY_EVENT, on)\n }\n}\n\n/**\n * The visitor's consent, live: what a region presumes until they choose, then\n * what they chose, re-rendering the moment they do. `enabled: choice.analytics`\n * on the provider's config is how a stream that started silent for an EU visitor\n * starts on Accept, with no reload.\n */\nexport function useConsent(): Choice {\n const kept = useSyncExternalStore(listen, () => render(read()), () => '')\n return {\n analytics: kept.includes('analytics'),\n marketing: kept.includes('marketing'),\n ads: kept.includes('ads'),\n }\n}\n"]}