@mushi-mushi/core 0.5.0 → 0.7.0

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.
package/CONTRIBUTING.md CHANGED
@@ -33,6 +33,10 @@ pnpm lint # ESLint
33
33
  pnpm format # Prettier
34
34
  ```
35
35
 
36
+ Ad-hoc screenshots captured during UI reviews can live temporarily at the repo
37
+ root, but root-level `*.png` files are intentionally ignored. Canonical
38
+ screenshots that should be versioned belong under `docs/screenshots/`.
39
+
36
40
  ### Working on a single package
37
41
 
38
42
  ```bash
package/SECURITY.md CHANGED
@@ -48,3 +48,77 @@ We will acknowledge receipt within 48 hours and aim to release a patch within 7
48
48
  - **Rotate API keys** regularly via the admin console
49
49
  - **Enable SSO** for team projects (Enterprise tier)
50
50
  - **Review audit logs** periodically for suspicious activity
51
+
52
+ ## Supply-chain hardening (how this package is protected)
53
+
54
+ Mushi Mushi is built and published with the controls below. Consumers can
55
+ verify each control independently — the goal is to make tampering both
56
+ difficult and detectable.
57
+
58
+ ### Publish-time controls
59
+
60
+ | Control | What it does | How to verify |
61
+ |---|---|---|
62
+ | **npm Trusted Publisher (OIDC)** | Every release is published from `.github/workflows/release.yml` on `master` using a short-lived OIDC token. Long-lived `NPM_TOKEN` is not used for publishing. | `npm view @mushi-mushi/<pkg> --json` shows `"trustedPublisher"` populated for recent versions. |
63
+ | **npm provenance attestations** | Every published tarball ships a [Sigstore provenance attestation](https://docs.npmjs.com/generating-provenance-statements) cryptographically linking the tarball to the exact GitHub Actions run that built it. | `npm audit signatures` (run inside any project that depends on `@mushi-mushi/*`) reports `verified registry signatures` and `verified attestations`. The npm web UI shows a "Built and signed on GitHub Actions" badge on each version. |
64
+ | **Pre-publish workspace-protocol guard** | Aborts the publish if `workspace:*` ranges leaked into the tarball (the bug class behind the v0.1.0 incident). | `scripts/check-workspace-protocol.mjs` runs before `changeset publish` in `pnpm release`. |
65
+ | **Post-publish tarball verification** | Re-downloads each just-published tarball and asserts it doesn't contain `workspace:*`. | See the "Verify published tarballs do not contain workspace:*" step in `release.yml`. |
66
+ | **Post-publish `npm audit signatures`** | Re-installs each published version and validates registry signatures + provenance against npm's transparency log. | See the "Audit signatures of installed dependencies" step in `release.yml`. |
67
+
68
+ ### Build-time controls
69
+
70
+ | Control | What it does |
71
+ |---|---|
72
+ | **All third-party GitHub Actions pinned to commit SHAs** | Every `uses:` in every workflow under `.github/workflows/` is pinned to a 40-character commit SHA with a version comment. Floating tags (`@v4`, `@main`) are mutable and were the entry point for the [tj-actions/changed-files compromise (CVE-2025-30066)](https://github.com/step-security/harden-runner#detected-attacks). |
73
+ | **Harden-Runner egress audit on every job** | [step-security/harden-runner](https://github.com/step-security/harden-runner) records every outbound network call, file write, and process spawn on every CI runner. Detects exfiltration attempts in real time — caught the tj-actions, NX, Shai-Hulud, and Axios attacks for other projects. |
74
+ | **OpenSSF Scorecard** | Weekly + on-push score of the repo's security posture (Pinned-Dependencies, Token-Permissions, Branch-Protection, Code-Review, Dangerous-Workflow, Maintained, SAST, Security-Policy, Signed-Releases, Vulnerabilities). Public results at [scorecard.dev](https://scorecard.dev/viewer/?uri=github.com/kensaurus/mushi-mushi). |
75
+ | **Server-side secret scan (Gitleaks)** | Every PR and every push to `master` runs Gitleaks across the diff / full tree. Belt-and-suspenders to the local pre-commit hook (`scripts/check-no-secrets.mjs`) which can be bypassed with `--no-verify`. |
76
+ | **Local pre-commit secret scanner** | `scripts/check-no-secrets.mjs` runs as a git hook installed by `pnpm install`, blocking commits that look like AWS / Stripe / GitHub / Anthropic / OpenAI / Slack / Supabase keys. |
77
+ | **CodeQL `security-extended`** | Semantic analysis of every TypeScript / JavaScript change finds injection sinks, taint flows, prototype pollution, etc. Runs on every PR, push, and weekly cron. |
78
+ | **Dependency review on PRs** | `actions/dependency-review-action` blocks the PR if it adds or upgrades a dep with a high-severity advisory. |
79
+ | **`pnpm audit --prod --audit-level=high`** | Weekly cron + every push to `master` fails on any high/critical advisory in production deps. |
80
+
81
+ ### Install-time controls (protect the project's own dependency graph)
82
+
83
+ | Control | What it does |
84
+ |---|---|
85
+ | **`min-release-age` (npm) / `minimumReleaseAge` (pnpm)** | Refuses to resolve any dep version published less than 7 days ago. The Axios 1.14.1 / 0.30.4 compromise (Mar 2026) was detected and removed within ~5 hours; Shai-Hulud (Sep 2025) within <12 hours — a 7-day cooldown blocks every publicly-disclosed 2025–2026 npm supply-chain attack outright. |
86
+ | **`strictDepBuilds: true`** | Fails the install if any transitive dep tries to run a `postinstall` hook the workspace hasn't pre-approved (`onlyBuiltDependencies` allow-list). |
87
+ | **`blockExoticSubdeps: true`** | Refuses to resolve transitive deps from git URLs, tarball URLs, or filesystem paths — anything that didn't go through the npm registry's signing pipeline. |
88
+ | **Dependabot with cooldown** | Routine dep upgrades wait 7 days; security advisories bypass the cooldown automatically. |
89
+ | **`pnpm audit signatures`-style verification** | The release pipeline re-runs `npm audit signatures` against each published version after the publish, with `--audit-level=high`. |
90
+
91
+ ### Verifying a Mushi Mushi tarball before installing
92
+
93
+ ```bash
94
+ # 1. Check provenance attestation matches the public GitHub Actions run
95
+ npm view @mushi-mushi/core --json | jq '.signatures, .dist'
96
+
97
+ # 2. Inside your own project after install
98
+ npm audit signatures
99
+
100
+ # Expected: every @mushi-mushi/* package reports
101
+ # "verified registry signature"
102
+ # "verified attestation"
103
+ ```
104
+
105
+ If `npm audit signatures` reports any `@mushi-mushi/*` package as unsigned
106
+ or with an invalid attestation, **stop the install and email
107
+ kensaurus@gmail.com immediately** — that's the symptom of either a
108
+ registry compromise or a tampered tarball, and we want to know within
109
+ hours, not days.
110
+
111
+ ### What this hardening does NOT cover
112
+
113
+ - **Self-hosted deployments.** Once the package is on your machine, the
114
+ security of your `node_modules`, build pipeline, and runtime is your
115
+ responsibility. The hardening above protects the path from source to
116
+ registry; it cannot protect a tarball after it has been downloaded.
117
+ - **Compromise of `kensaurus@gmail.com`.** A trusted-publisher rule still
118
+ lets the legitimate maintainer publish from any branch they push. If
119
+ you find yourself with admin access to this repo, treat
120
+ `.github/workflows/release.yml` as a tier-0 secret.
121
+ - **First-party bugs.** Provenance proves *who* built the tarball and
122
+ *when*; it does not prove the code is bug-free. CodeQL + tests cover
123
+ that surface, but no automation catches everything — please continue
124
+ to report issues to the address above.
package/dist/index.cjs CHANGED
@@ -49,11 +49,12 @@ function createApiClient(options) {
49
49
  ok: false,
50
50
  error: {
51
51
  code: `HTTP_${response.status}`,
52
- message: errorBody.message || `HTTP ${response.status} error`
52
+ message: errorBody.error?.message || errorBody.message || `HTTP ${response.status} error`
53
53
  }
54
54
  };
55
55
  }
56
- const data = await response.json();
56
+ const payload = await response.json();
57
+ const data = payload && typeof payload === "object" && "ok" in payload && "data" in payload ? payload.data : payload;
57
58
  return { ok: true, data };
58
59
  } catch (error) {
59
60
  clearTimeout(timer);
@@ -76,6 +77,9 @@ function createApiClient(options) {
76
77
  },
77
78
  async getReportStatus(reportId) {
78
79
  return request("GET", `/v1/reports/${reportId}/status`);
80
+ },
81
+ async getSdkConfig() {
82
+ return request("GET", "/v1/sdk/config");
79
83
  }
80
84
  };
81
85
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api-client.ts","../src/region.ts","../src/pre-filter.ts","../src/logger.ts","../src/queue-crypto.ts","../src/queue.ts","../src/environment.ts","../src/reporter-token.ts","../src/fingerprint.ts","../src/session.ts","../src/rate-limiter.ts","../src/pii-scrubber.ts"],"names":["getBackoffDelay","sleep"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { MushiApiClient, MushiApiResponse, MushiReport, MushiReportStatus } from './types';\n\nexport interface ApiClientOptions {\n projectId: string;\n apiKey: string;\n /**\n * Override the API endpoint. Defaults to the canonical Cloud URL\n * (DEFAULT_API_ENDPOINT). Self-hosted users MUST set this.\n */\n apiEndpoint?: string;\n timeout?: number;\n maxRetries?: number;\n}\n\n// V5.3 (M-cross-cutting): canonical Cloud URL — the older `api.mushimushi.dev`\n// hostname was never wired up. Self-hosted users MUST override `apiEndpoint`.\nexport const DEFAULT_API_ENDPOINT = 'https://dxptnwrhwsqckaftyymj.supabase.co/functions/v1/api';\nconst DEFAULT_TIMEOUT = 10_000;\nconst DEFAULT_MAX_RETRIES = 2;\n\nexport function createApiClient(options: ApiClientOptions): MushiApiClient {\n const {\n projectId,\n apiKey,\n apiEndpoint = DEFAULT_API_ENDPOINT,\n timeout = DEFAULT_TIMEOUT,\n maxRetries = DEFAULT_MAX_RETRIES,\n } = options;\n\n let baseUrl = apiEndpoint.replace(/\\/$/, '');\n\n async function request<T>(\n method: string,\n path: string,\n body?: unknown,\n retries = maxRetries,\n ): Promise<MushiApiResponse<T>> {\n const url = `${baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'X-Mushi-Api-Key': apiKey,\n 'X-Mushi-Project': projectId,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timer);\n\n // C7: data residency — follow a one-shot redirect when the\n // gateway tells us the project lives in a different region. Cache the\n // new base URL so subsequent calls go straight to the right cluster.\n if (response.status === 307 || response.status === 308) {\n const target = response.headers.get('Location');\n if (target && retries > 0) {\n const targetBase = target.replace(/\\/v1\\/.*$/, '').replace(/\\/$/, '');\n if (targetBase !== baseUrl) {\n baseUrl = targetBase;\n return request<T>(method, path, body, retries - 1);\n }\n }\n }\n\n if (!response.ok) {\n const errorBody = await response.json().catch(() => ({}));\n if (response.status >= 500 && retries > 0) {\n await sleep(getBackoffDelay(maxRetries - retries));\n return request<T>(method, path, body, retries - 1);\n }\n return {\n ok: false,\n error: {\n code: `HTTP_${response.status}`,\n message:\n (errorBody as { message?: string }).message || `HTTP ${response.status} error`,\n },\n };\n }\n\n const data = (await response.json()) as T;\n return { ok: true, data };\n } catch (error) {\n clearTimeout(timer);\n\n if (retries > 0 && isRetryable(error)) {\n await sleep(getBackoffDelay(maxRetries - retries));\n return request<T>(method, path, body, retries - 1);\n }\n\n return {\n ok: false,\n error: {\n code: 'NETWORK_ERROR',\n message: error instanceof Error ? error.message : 'Unknown network error',\n },\n };\n }\n }\n\n return {\n async submitReport(report: MushiReport) {\n return request<{ reportId: string }>('POST', '/v1/reports', report);\n },\n\n async getReportStatus(reportId: string) {\n return request<{ status: MushiReportStatus }>('GET', `/v1/reports/${reportId}/status`);\n },\n };\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction getBackoffDelay(attempt: number): number {\n return Math.min(1000 * 2 ** attempt + Math.random() * 500, 10_000);\n}\n\nfunction isRetryable(error: unknown): boolean {\n if (error instanceof DOMException && error.name === 'AbortError') return true;\n if (error instanceof TypeError) return true; // network failures\n return false;\n}\n","/**\n * C7: Data residency region resolution.\n *\n * The SDK supports four regional clouds:\n * - 'us' → United States (default; legacy `dxptnwrhwsqckaftyymj`)\n * - 'eu' → European Union (Frankfurt)\n * - 'jp' → Japan (Tokyo)\n * - 'self' → self-hosted / BYO Supabase\n *\n * Customers choose a region at project creation time, and the gateway will\n * 307-redirect any cross-region calls to the correct host. The SDK caches\n * the resolved hostname in `localStorage` (browser) so that subsequent\n * sessions skip the redirect.\n */\n\nexport type MushiRegion = 'us' | 'eu' | 'jp' | 'self';\n\nexport const REGION_ENDPOINTS: Record<Exclude<MushiRegion, 'self'>, string> = {\n us: 'https://api.us.mushimushi.dev/functions/v1/api',\n eu: 'https://api.eu.mushimushi.dev/functions/v1/api',\n jp: 'https://api.jp.mushimushi.dev/functions/v1/api',\n};\n\nconst ROUTING_CACHE_KEY = 'mushi_region_v1';\nconst ROUTING_CACHE_TTL_MS = 24 * 60 * 60 * 1000;\n\ninterface RegionCacheEntry {\n region: MushiRegion;\n endpoint: string;\n ts: number;\n}\n\n/**\n * Resolve the regional endpoint for a project. Looks up the public\n * `region_routing` table on the legacy US gateway (the catalog of record),\n * then caches the result.\n *\n * Falls back to the explicit `apiEndpoint` if anything goes wrong — failure\n * here must never block report submission.\n */\nexport async function resolveRegionEndpoint(opts: {\n projectId: string;\n apiEndpoint: string;\n region?: MushiRegion;\n storage?: Storage;\n fetcher?: typeof fetch;\n}): Promise<string> {\n const explicit = opts.region;\n if (explicit && explicit !== 'self' && REGION_ENDPOINTS[explicit]) {\n return REGION_ENDPOINTS[explicit];\n }\n\n const storage = opts.storage ?? safeLocalStorage();\n const cached = readCache(storage, opts.projectId);\n if (cached) return cached;\n\n try {\n const fetcher = opts.fetcher ?? fetch;\n const url = `${opts.apiEndpoint.replace(/\\/$/, '')}/v1/region/resolve?project_id=${encodeURIComponent(opts.projectId)}`;\n const res = await fetcher(url, { method: 'GET' });\n if (!res.ok) return opts.apiEndpoint;\n const body = (await res.json()) as { region?: MushiRegion; endpoint?: string };\n if (!body.region || !body.endpoint) return opts.apiEndpoint;\n writeCache(storage, opts.projectId, { region: body.region, endpoint: body.endpoint, ts: Date.now() });\n return body.endpoint;\n } catch {\n return opts.apiEndpoint;\n }\n}\n\nfunction safeLocalStorage(): Storage | undefined {\n try {\n return typeof globalThis !== 'undefined' && 'localStorage' in globalThis\n ? (globalThis as { localStorage: Storage }).localStorage\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction readCache(storage: Storage | undefined, projectId: string): string | null {\n if (!storage) return null;\n try {\n const raw = storage.getItem(`${ROUTING_CACHE_KEY}:${projectId}`);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as RegionCacheEntry;\n if (Date.now() - parsed.ts > ROUTING_CACHE_TTL_MS) return null;\n return parsed.endpoint;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(storage: Storage | undefined, projectId: string, entry: RegionCacheEntry): void {\n if (!storage) return;\n try {\n storage.setItem(`${ROUTING_CACHE_KEY}:${projectId}`, JSON.stringify(entry));\n } catch {\n /* no-op: quota exceeded etc. */\n }\n}\n","import type { MushiPreFilterConfig } from './types';\n\nexport interface PreFilterResult {\n passed: boolean;\n reason?: string;\n}\n\nconst DEFAULT_MIN_LENGTH = 10;\nconst DEFAULT_MAX_LENGTH = 2000;\n\nconst SPAM_PATTERNS: RegExp[] = [\n /^(.)\\1{10,}$/, // repeated single character\n /^[A-Z\\s!?]{20,}$/, // all caps shouting\n /^[\\d\\s]+$/, // numbers only\n /^[^a-zA-Z\\u00C0-\\u024F\\u4E00-\\u9FFF\\u3040-\\u309F\\u30A0-\\u30FF]{10,}$/, // no real letters\n /\\b(test|asdf|qwerty|lorem ipsum)\\b/i, // common test strings\n];\n\nconst GIBBERISH_PATTERN = /^[bcdfghjklmnpqrstvwxz]{6,}/i; // consonant-only strings\n\nexport function createPreFilter(config: MushiPreFilterConfig = {}) {\n const {\n enabled = true,\n blockObviousSpam = true,\n minDescriptionLength = DEFAULT_MIN_LENGTH,\n maxDescriptionLength = DEFAULT_MAX_LENGTH,\n } = config;\n\n function check(description: string): PreFilterResult {\n if (!enabled) {\n return { passed: true };\n }\n\n const trimmed = description.trim();\n\n if (trimmed.length < minDescriptionLength) {\n return { passed: false, reason: `Too short (min ${minDescriptionLength} characters)` };\n }\n\n if (trimmed.length > maxDescriptionLength) {\n return { passed: false, reason: `Too long (max ${maxDescriptionLength} characters)` };\n }\n\n if (blockObviousSpam) {\n for (const pattern of SPAM_PATTERNS) {\n if (pattern.test(trimmed)) {\n return { passed: false, reason: 'Detected as spam' };\n }\n }\n\n if (GIBBERISH_PATTERN.test(trimmed)) {\n return { passed: false, reason: 'Detected as gibberish' };\n }\n\n const words = trimmed.split(/\\s+/).filter((w) => w.length > 1);\n if (words.length < 2) {\n return { passed: false, reason: 'Description needs at least 2 words' };\n }\n }\n\n return { passed: true };\n }\n\n function truncate(description: string): string {\n const trimmed = description.trim();\n if (trimmed.length <= maxDescriptionLength) return trimmed;\n return trimmed.slice(0, maxDescriptionLength) + '...';\n }\n\n return { check, truncate };\n}\n","/**\n * FILE: logger.ts\n * PURPOSE: Zero-dependency structured logger for the mushi-mushi SDK ecosystem.\n *\n * OVERVIEW:\n * - Production-grade logging with levels, scoped namespaces, and child loggers\n * - JSON output for server/production, pretty-formatted output for development\n * - Automatic environment detection (browser vs Node vs Deno)\n * - Structured metadata on every log entry\n * - No external dependencies — safe to ship in any SDK bundle\n *\n * USAGE:\n * import { createLogger } from '@mushi-mushi/core'\n * const log = createLogger({ scope: 'mushi:api' })\n * log.info('Request received', { method: 'POST', path: '/v1/reports' })\n * const child = log.child('ingest', { reportId: 'abc' })\n * child.warn('Slow query', { latencyMs: 420 })\n *\n * TECHNICAL DETAILS:\n * - Log levels: debug(10) < info(20) < warn(30) < error(40) < fatal(50) < silent(99)\n * - Format auto-detected: JSON in production/server, pretty in development\n * - Pretty format uses ANSI colors when supported (Node/Deno TTY)\n * - Child loggers inherit parent scope + metadata, can override level\n * - Timestamps are ISO 8601 with millisecond precision\n */\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'silent'\n\nexport type LogFormat = 'json' | 'pretty' | 'auto'\n\nexport interface LoggerOptions {\n scope: string\n level?: LogLevel\n meta?: Record<string, unknown>\n format?: LogFormat\n}\n\nexport interface Logger {\n debug(msg: string, meta?: Record<string, unknown>): void\n info(msg: string, meta?: Record<string, unknown>): void\n warn(msg: string, meta?: Record<string, unknown>): void\n error(msg: string, meta?: Record<string, unknown>): void\n fatal(msg: string, meta?: Record<string, unknown>): void\n child(scope: string, meta?: Record<string, unknown>): Logger\n setLevel(level: LogLevel): void\n}\n\nexport interface LogEntry {\n ts: string\n level: LogLevel\n scope: string\n msg: string\n [key: string]: unknown\n}\n\nconst LEVEL_VALUE: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n fatal: 50,\n silent: 99,\n}\n\nconst LEVEL_LABEL: Record<string, string> = {\n debug: 'DBG',\n info: 'INF',\n warn: 'WRN',\n error: 'ERR',\n fatal: 'FTL',\n}\n\nconst ANSI = {\n reset: '\\x1b[0m',\n dim: '\\x1b[2m',\n bold: '\\x1b[1m',\n cyan: '\\x1b[36m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n red: '\\x1b[31m',\n magenta: '\\x1b[35m',\n white: '\\x1b[37m',\n bgRed: '\\x1b[41m',\n} as const\n\nconst LEVEL_COLOR: Record<string, string> = {\n debug: ANSI.dim,\n info: ANSI.green,\n warn: ANSI.yellow,\n error: ANSI.red,\n fatal: `${ANSI.bgRed}${ANSI.white}${ANSI.bold}`,\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nfunction detectFormat(): 'json' | 'pretty' {\n try {\n if (typeof (globalThis as any).Deno !== 'undefined') return 'json'\n } catch { /* not Deno */ }\n\n const proc = typeof (globalThis as any).process !== 'undefined'\n ? (globalThis as any).process\n : undefined\n\n if (proc?.env) {\n if (proc.env.NODE_ENV === 'production') return 'json'\n if (proc.env.LOG_FORMAT === 'json') return 'json'\n if (proc.env.LOG_FORMAT === 'pretty') return 'pretty'\n if (proc.stdout?.isTTY) return 'pretty'\n }\n\n if (typeof (globalThis as any).window !== 'undefined') return 'pretty'\n\n return 'json'\n}\n/* eslint-enable @typescript-eslint/no-explicit-any */\n\nfunction flattenMeta(meta: Record<string, unknown>): string {\n const parts: string[] = []\n for (const [k, v] of Object.entries(meta)) {\n if (v === undefined || v === null) continue\n if (typeof v === 'object') {\n parts.push(`${k}=${JSON.stringify(v)}`)\n } else {\n parts.push(`${k}=${String(v)}`)\n }\n }\n return parts.join(' ')\n}\n\nfunction formatPretty(entry: LogEntry): string {\n const { ts, level, scope, msg, ...rest } = entry\n const time = ts.slice(11, 23)\n const color = LEVEL_COLOR[level] ?? ''\n const label = LEVEL_LABEL[level] ?? level.toUpperCase()\n const metaStr = Object.keys(rest).length > 0 ? ` ${ANSI.dim}${flattenMeta(rest)}${ANSI.reset}` : ''\n\n return `${ANSI.dim}${time}${ANSI.reset} ${color}${label}${ANSI.reset} ${ANSI.cyan}[${scope}]${ANSI.reset} ${msg}${metaStr}`\n}\n\nfunction formatJson(entry: LogEntry): string {\n return JSON.stringify(entry)\n}\n\nfunction emit(level: LogLevel, formatted: string): void {\n switch (level) {\n case 'error':\n case 'fatal':\n console.error(formatted)\n break\n case 'warn':\n console.warn(formatted)\n break\n default:\n console.log(formatted)\n }\n}\n\nfunction buildLogger(\n scope: string,\n minLevel: LogLevel,\n baseMeta: Record<string, unknown>,\n formatter: (entry: LogEntry) => string,\n): Logger {\n let currentLevel = minLevel\n\n function log(level: LogLevel, msg: string, meta?: Record<string, unknown>): void {\n if (LEVEL_VALUE[level] < LEVEL_VALUE[currentLevel]) return\n\n const entry: LogEntry = {\n ts: new Date().toISOString(),\n level,\n scope,\n msg,\n ...baseMeta,\n ...meta,\n }\n\n emit(level, formatter(entry))\n }\n\n return {\n debug: (msg, meta?) => log('debug', msg, meta),\n info: (msg, meta?) => log('info', msg, meta),\n warn: (msg, meta?) => log('warn', msg, meta),\n error: (msg, meta?) => log('error', msg, meta),\n fatal: (msg, meta?) => log('fatal', msg, meta),\n\n child(childScope: string, childMeta?: Record<string, unknown>): Logger {\n return buildLogger(\n `${scope}:${childScope}`,\n currentLevel,\n { ...baseMeta, ...childMeta },\n formatter,\n )\n },\n\n setLevel(level: LogLevel) {\n currentLevel = level\n },\n }\n}\n\n/**\n * Create a structured logger instance.\n *\n * @example\n * const log = createLogger({ scope: 'mushi:api', level: 'info' })\n * log.info('Server started', { port: 3000 })\n *\n * const child = log.child('auth', { userId: 'u-123' })\n * child.warn('Token expired')\n */\nexport function createLogger(options: LoggerOptions): Logger {\n const {\n scope,\n level = 'info',\n meta = {},\n format = 'auto',\n } = options\n\n const resolvedFormat = format === 'auto' ? detectFormat() : format\n const formatter = resolvedFormat === 'json' ? formatJson : formatPretty\n\n return buildLogger(scope, level, meta, formatter)\n}\n\n/**\n * Noop logger that discards all output.\n * Useful when logging should be completely disabled.\n */\nexport const noopLogger: Logger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n fatal: () => {},\n child: () => noopLogger,\n setLevel: () => {},\n}\n","/**\n * AES-GCM at-rest encryption for the offline queue (Wave S1 / D-16).\n *\n * Why this exists: on shared devices (kiosks, support-agent laptops) a\n * queued bug report sits in plaintext IndexedDB until the next flush.\n * Browser extensions, other tabs on the same origin, and forensic tools\n * with disk access can all read it. For a QA/bug-reporting SDK that\n * encourages users to paste sensitive data into descriptions, that's\n * unacceptable.\n *\n * Design:\n * - Generate a non-extractable AES-GCM key on first call (256-bit).\n * - Persist the `CryptoKey` object itself (Web Crypto allows IDB round-\n * trip of `CryptoKey` without ever serialising the raw bytes).\n * - Use a 12-byte random IV per payload; prepend it to ciphertext so\n * decrypt() needs no out-of-band state.\n * - Never block the caller — all errors bubble up so the queue can fall\n * back to plaintext storage with a debug log (see queue.ts).\n *\n * The key is tied to the browser origin (same-origin IDB). It does NOT\n * protect against an attacker with admin shell on the device: the browser\n * WILL decrypt on demand for anyone with origin access. That's the same\n * guarantee every origin-bound browser secret has and is the correct\n * threat model for offline bug reports.\n */\n\nconst KEY_DB = 'mushi-mushi-keyring';\nconst KEY_STORE = 'keys';\nconst KEY_RECORD_ID = 'offline-queue/v1';\n\nlet cachedKey: CryptoKey | null = null;\nlet cachedKeyPromise: Promise<CryptoKey> | null = null;\n\nfunction hasWebCrypto(): boolean {\n return (\n typeof globalThis !== 'undefined' &&\n typeof (globalThis as unknown as { crypto?: Crypto }).crypto !== 'undefined' &&\n typeof (globalThis as unknown as { crypto: Crypto }).crypto.subtle !== 'undefined' &&\n typeof indexedDB !== 'undefined'\n );\n}\n\nfunction openKeyDb(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.open(KEY_DB, 1);\n req.onupgradeneeded = () => {\n const db = req.result;\n if (!db.objectStoreNames.contains(KEY_STORE)) {\n db.createObjectStore(KEY_STORE);\n }\n };\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n });\n}\n\nasync function loadKey(): Promise<CryptoKey | null> {\n const db = await openKeyDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(KEY_STORE, 'readonly');\n const req = tx.objectStore(KEY_STORE).get(KEY_RECORD_ID);\n req.onsuccess = () => resolve((req.result as CryptoKey) ?? null);\n req.onerror = () => reject(req.error);\n });\n}\n\nasync function storeKey(key: CryptoKey): Promise<void> {\n const db = await openKeyDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(KEY_STORE, 'readwrite');\n tx.objectStore(KEY_STORE).put(key, KEY_RECORD_ID);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\n/**\n * Lazily get (or generate once + persist) the AES-GCM key for this origin.\n * `extractable: false` — so a script-level attacker can't `exportKey()` and\n * ship the raw bytes to their server, only use it via `encrypt`/`decrypt`.\n */\nexport async function getOfflineQueueKey(): Promise<CryptoKey> {\n if (cachedKey) return cachedKey;\n if (cachedKeyPromise) return cachedKeyPromise;\n if (!hasWebCrypto()) {\n throw new Error('Web Crypto + IndexedDB required for offline queue encryption');\n }\n cachedKeyPromise = (async () => {\n const existing = await loadKey();\n if (existing) {\n cachedKey = existing;\n return existing;\n }\n const key = await crypto.subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt'],\n );\n await storeKey(key);\n cachedKey = key;\n return key;\n })();\n return cachedKeyPromise;\n}\n\nexport interface EncryptedPayload {\n /** Magic marker so decrypt() can tell encrypted vs legacy plaintext rows. */\n readonly _mme: 1;\n readonly iv: string;\n readonly ct: string;\n}\n\nfunction bytesToB64(bytes: Uint8Array): string {\n let s = '';\n for (const b of bytes) s += String.fromCharCode(b);\n return btoa(s);\n}\n\nfunction b64ToBytes(s: string): Uint8Array<ArrayBuffer> {\n const bin = atob(s);\n const out = new Uint8Array(new ArrayBuffer(bin.length));\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nexport async function encryptJson(plain: unknown): Promise<EncryptedPayload> {\n const key = await getOfflineQueueKey();\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const data = new TextEncoder().encode(JSON.stringify(plain));\n const cipher = new Uint8Array(await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, data));\n return { _mme: 1, iv: bytesToB64(iv), ct: bytesToB64(cipher) };\n}\n\nexport function isEncryptedPayload(v: unknown): v is EncryptedPayload {\n return (\n !!v &&\n typeof v === 'object' &&\n (v as EncryptedPayload)._mme === 1 &&\n typeof (v as EncryptedPayload).iv === 'string' &&\n typeof (v as EncryptedPayload).ct === 'string'\n );\n}\n\nexport async function decryptJson<T = unknown>(payload: EncryptedPayload): Promise<T> {\n const key = await getOfflineQueueKey();\n const iv = b64ToBytes(payload.iv);\n const ct = b64ToBytes(payload.ct);\n const plain = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, key, ct);\n return JSON.parse(new TextDecoder().decode(plain)) as T;\n}\n","import type { MushiApiClient, MushiOfflineConfig, MushiReport } from './types';\nimport { createLogger } from './logger';\nimport {\n encryptJson,\n decryptJson,\n isEncryptedPayload,\n type EncryptedPayload,\n} from './queue-crypto';\n\nconst queueLog = createLogger({ scope: 'mushi:queue', level: 'warn' });\n\n// Wave S1 / D-16: opaque at-rest wrapper. Each queue row is either:\n// - a legacy plaintext `MushiReport` (pre-encryption; still readable)\n// - an `EncryptedRecord` with a bare `id` (so count / delete can operate\n// without decrypting every row) plus the encrypted payload blob.\ninterface EncryptedRecord {\n id: string;\n queuedAt: string;\n payload: EncryptedPayload;\n}\n\ntype StoredRow = MushiReport | EncryptedRecord;\n\nconst DB_NAME = 'mushi-mushi';\nconst STORE_NAME = 'offline-reports';\nconst DB_VERSION = 1;\nconst LS_KEY = 'mushi_offline_queue';\nconst BATCH_SIZE = 10;\nconst MAX_BACKOFF_MS = 60_000;\n\nexport interface OfflineQueue {\n enqueue(report: MushiReport): Promise<void>;\n flush(client: MushiApiClient): Promise<{ sent: number; failed: number }>;\n size(): Promise<number>;\n clear(): Promise<void>;\n startAutoSync(client: MushiApiClient): void;\n stopAutoSync(): void;\n}\n\ntype StorageBackend = 'indexeddb' | 'localstorage' | 'none';\n\nexport function createOfflineQueue(config: MushiOfflineConfig = {}): OfflineQueue {\n const { enabled = true, maxQueueSize = 50, syncOnReconnect = true, encryptAtRest = true } = config;\n\n let syncCleanup: (() => void) | null = null;\n let backendType: StorageBackend | null = null;\n\n async function wrapForStorage(report: MushiReport): Promise<StoredRow> {\n const queuedAt = new Date().toISOString();\n if (!encryptAtRest) {\n return { ...report, queuedAt } as MushiReport;\n }\n try {\n const payload = await encryptJson(report);\n return { id: report.id, queuedAt, payload } satisfies EncryptedRecord;\n } catch (err) {\n // Encryption failure is non-fatal — queue integrity matters more than\n // at-rest confidentiality. We fall back to plaintext and warn.\n queueLog.warn('Offline queue: encryption failed, storing plaintext', { err: String(err) });\n return { ...report, queuedAt } as MushiReport;\n }\n }\n\n async function unwrapForSend(row: StoredRow): Promise<MushiReport | null> {\n if (isEncryptedRecord(row)) {\n try {\n return await decryptJson<MushiReport>(row.payload);\n } catch (err) {\n queueLog.warn('Offline queue: decrypt failed, dropping row', { err: String(err), id: row.id });\n return null;\n }\n }\n return row;\n }\n\n function isEncryptedRecord(row: StoredRow): row is EncryptedRecord {\n return !!(row as EncryptedRecord).payload && isEncryptedPayload((row as EncryptedRecord).payload);\n }\n\n function detectBackend(): StorageBackend {\n if (backendType) return backendType;\n if (typeof indexedDB !== 'undefined') {\n backendType = 'indexeddb';\n } else if (typeof localStorage !== 'undefined') {\n backendType = 'localstorage';\n } else {\n backendType = 'none';\n }\n return backendType;\n }\n\n // --- IndexedDB backend ---\n\n function openDb(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME, { keyPath: 'id' });\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => {\n backendType = 'localstorage';\n reject(request.error);\n };\n });\n }\n\n async function idbEnqueue(report: MushiReport): Promise<void> {\n const db = await openDb();\n const row = await wrapForStorage(report);\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite');\n tx.objectStore(STORE_NAME).put(row);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n async function idbGetAll(): Promise<StoredRow[]> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readonly');\n const request = tx.objectStore(STORE_NAME).getAll();\n request.onsuccess = () => resolve(request.result as StoredRow[]);\n request.onerror = () => reject(request.error);\n });\n }\n\n async function idbDelete(id: string): Promise<void> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite');\n tx.objectStore(STORE_NAME).delete(id);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n async function idbSize(): Promise<number> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readonly');\n const request = tx.objectStore(STORE_NAME).count();\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n }\n\n async function idbClear(): Promise<void> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite');\n tx.objectStore(STORE_NAME).clear();\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n // --- localStorage fallback ---\n\n function lsRead(): StoredRow[] {\n try {\n const raw = localStorage.getItem(LS_KEY);\n return raw ? (JSON.parse(raw) as StoredRow[]) : [];\n } catch {\n return [];\n }\n }\n\n function lsWrite(rows: StoredRow[]): void {\n try {\n localStorage.setItem(LS_KEY, JSON.stringify(rows));\n } catch {\n // localStorage full or unavailable\n }\n }\n\n async function lsEnqueue(report: MushiReport): Promise<void> {\n const rows = lsRead();\n rows.push(await wrapForStorage(report));\n lsWrite(rows);\n }\n\n function lsDelete(id: string): void {\n const rows = lsRead().filter((r) => r.id !== id);\n lsWrite(rows);\n }\n\n // --- Unified interface ---\n\n async function enqueue(report: MushiReport): Promise<void> {\n if (!enabled) return;\n\n const currentSize = await size();\n if (currentSize >= maxQueueSize) {\n queueLog.warn('Offline queue full — dropping report', { maxQueueSize });\n return;\n }\n\n const backend = detectBackend();\n if (backend === 'indexeddb') {\n try {\n await idbEnqueue(report);\n return;\n } catch {\n // IndexedDB failed, fall through to localStorage\n backendType = 'localstorage';\n }\n }\n\n if (backend === 'localstorage' || backendType === 'localstorage') {\n await lsEnqueue(report);\n return;\n }\n }\n\n function getBackoffDelay(attempt: number): number {\n return Math.min(1000 * 2 ** attempt + Math.random() * 500, MAX_BACKOFF_MS);\n }\n\n function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n async function flush(client: MushiApiClient): Promise<{ sent: number; failed: number }> {\n if (!enabled) return { sent: 0, failed: 0 };\n\n let rows: StoredRow[];\n const backend = detectBackend();\n\n if (backend === 'indexeddb') {\n try {\n rows = await idbGetAll();\n } catch {\n rows = lsRead();\n }\n } else {\n rows = lsRead();\n }\n\n const batch = rows.slice(0, BATCH_SIZE);\n let sent = 0;\n let failed = 0;\n\n for (let i = 0; i < batch.length; i++) {\n const row = batch[i];\n const rowId = (row as { id: string }).id;\n const report = await unwrapForSend(row);\n\n if (!report) {\n // Undecryptable row — drop so it doesn't re-poison the queue forever.\n try {\n if (backend === 'indexeddb') await idbDelete(rowId);\n else lsDelete(rowId);\n } catch {\n lsDelete(rowId);\n }\n failed++;\n continue;\n }\n\n const result = await client.submitReport(report);\n\n if (result.ok) {\n try {\n if (backend === 'indexeddb') await idbDelete(rowId);\n else lsDelete(rowId);\n } catch {\n lsDelete(rowId);\n }\n sent++;\n } else {\n failed++;\n if (i < batch.length - 1) {\n await sleep(getBackoffDelay(i));\n }\n }\n }\n\n return { sent, failed };\n }\n\n async function size(): Promise<number> {\n const backend = detectBackend();\n if (backend === 'indexeddb') {\n try {\n return await idbSize();\n } catch {\n return lsRead().length;\n }\n }\n return lsRead().length;\n }\n\n async function clear(): Promise<void> {\n const backend = detectBackend();\n if (backend === 'indexeddb') {\n try {\n await idbClear();\n } catch {\n // fall through\n }\n }\n try {\n localStorage.removeItem(LS_KEY);\n } catch {\n // unavailable\n }\n }\n\n function startAutoSync(client: MushiApiClient): void {\n if (!enabled || !syncOnReconnect || typeof window === 'undefined') return;\n\n const handler = () => {\n if (navigator.onLine) {\n flush(client).catch(() => {});\n }\n };\n\n window.addEventListener('online', handler);\n syncCleanup = () => window.removeEventListener('online', handler);\n }\n\n function stopAutoSync(): void {\n syncCleanup?.();\n syncCleanup = null;\n }\n\n return { enqueue, flush, size, clear, startAutoSync, stopAutoSync };\n}\n","import type { MushiEnvironment } from './types';\n\nexport function captureEnvironment(): MushiEnvironment {\n const nav = typeof navigator !== 'undefined' ? navigator : undefined;\n const win = typeof window !== 'undefined' ? window : undefined;\n const doc = typeof document !== 'undefined' ? document : undefined;\n\n const connection = nav && 'connection' in nav ? (nav as NavigatorWithConnection).connection : undefined;\n\n return {\n userAgent: nav?.userAgent ?? 'unknown',\n platform: nav?.platform ?? 'unknown',\n language: nav?.language ?? 'en',\n viewport: {\n width: win?.innerWidth ?? 0,\n height: win?.innerHeight ?? 0,\n },\n url: win?.location?.href ?? '',\n referrer: doc?.referrer ?? '',\n timestamp: new Date().toISOString(),\n timezone: Intl?.DateTimeFormat?.()?.resolvedOptions?.()?.timeZone ?? 'UTC',\n connection: connection\n ? {\n effectiveType: connection.effectiveType,\n downlink: connection.downlink,\n rtt: connection.rtt,\n }\n : undefined,\n deviceMemory: (nav as NavigatorWithDeviceMemory)?.deviceMemory,\n hardwareConcurrency: nav?.hardwareConcurrency,\n };\n}\n\ninterface NetworkInformation {\n effectiveType?: string;\n downlink?: number;\n rtt?: number;\n}\n\ninterface NavigatorWithConnection extends Navigator {\n connection?: NetworkInformation;\n}\n\ninterface NavigatorWithDeviceMemory extends Navigator {\n deviceMemory?: number;\n}\n","const STORAGE_KEY = 'mushi_reporter_token';\n\nexport function getReporterToken(): string {\n if (typeof localStorage !== 'undefined') {\n const existing = localStorage.getItem(STORAGE_KEY);\n if (existing) return existing;\n }\n\n const token = generateToken();\n\n if (typeof localStorage !== 'undefined') {\n try {\n localStorage.setItem(STORAGE_KEY, token);\n } catch {\n // localStorage full or unavailable — token is ephemeral\n }\n }\n\n return token;\n}\n\nfunction generateToken(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return `mushi_${crypto.randomUUID()}`;\n }\n\n const bytes = new Uint8Array(16);\n if (typeof crypto !== 'undefined') {\n crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n\n const hex = Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n return `mushi_${hex}`;\n}\n","/**\n * §3c — stable device fingerprint hash.\n *\n * Hashes a deliberately small set of long-lived device characteristics so\n * the same browser keeps the same hash across sessions, but moving to a\n * new browser/device produces a different one. This lets the server\n * detect cross-account abuse (same hash → many reporter accounts) without\n * needing fingerprint.js or any other entropy-heavy library.\n *\n * Privacy notes:\n * - We never send the raw inputs, only the SHA-256 hex digest.\n * - The set is intentionally low-entropy on purpose; this is \"is this the\n * same device\" not \"who is this user\". For high-stakes anti-fraud you\n * should still combine with server-side IP/geo signals.\n * - Cached in localStorage so subsequent calls are zero-cost.\n */\n\nconst CACHE_KEY = 'mushi_fingerprint_hash';\n\ninterface FingerprintInputs {\n userAgent: string;\n platform: string;\n language: string;\n timezone: string;\n screenWidth: number;\n screenHeight: number;\n pixelRatio: number;\n deviceMemory: number | undefined;\n hardwareConcurrency: number | undefined;\n}\n\nfunction collectInputs(): FingerprintInputs {\n const nav = typeof navigator !== 'undefined' ? navigator : undefined;\n const scr = typeof screen !== 'undefined' ? screen : undefined;\n const win = typeof window !== 'undefined' ? window : undefined;\n return {\n userAgent: nav?.userAgent ?? 'unknown',\n platform: nav?.platform ?? 'unknown',\n language: nav?.language ?? 'en',\n timezone: Intl?.DateTimeFormat?.()?.resolvedOptions?.()?.timeZone ?? 'UTC',\n screenWidth: scr?.width ?? 0,\n screenHeight: scr?.height ?? 0,\n pixelRatio: win?.devicePixelRatio ?? 1,\n deviceMemory: (nav as NavigatorWithDeviceMemory | undefined)?.deviceMemory,\n hardwareConcurrency: nav?.hardwareConcurrency,\n };\n}\n\ninterface NavigatorWithDeviceMemory extends Navigator {\n deviceMemory?: number;\n}\n\nasync function sha256Hex(input: string): Promise<string> {\n if (typeof crypto !== 'undefined' && crypto.subtle) {\n const buf = new TextEncoder().encode(input);\n const digest = await crypto.subtle.digest('SHA-256', buf);\n return Array.from(new Uint8Array(digest))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n }\n // Fallback (Node 18+ test envs, very old browsers): non-cryptographic but\n // good enough for the \"are these two requests from the same device\" use\n // case the server makes of this value.\n let hash = 0;\n for (let i = 0; i < input.length; i++) {\n hash = (hash << 5) - hash + input.charCodeAt(i);\n hash |= 0;\n }\n return `fbk_${(hash >>> 0).toString(16).padStart(8, '0')}`;\n}\n\n/**\n * Returns a stable per-device hash. Cached in localStorage; first call is\n * one SHA-256, subsequent calls are a localStorage read.\n *\n * Returns `null` outside browser-like environments (SSR, web workers\n * without crypto.subtle) so callers can omit the field gracefully.\n */\nexport async function getDeviceFingerprintHash(): Promise<string | null> {\n if (typeof localStorage !== 'undefined') {\n const cached = localStorage.getItem(CACHE_KEY);\n if (cached) return cached;\n }\n\n const inputs = collectInputs();\n const serialised = JSON.stringify(inputs);\n const hash = await sha256Hex(serialised);\n\n if (typeof localStorage !== 'undefined') {\n try {\n localStorage.setItem(CACHE_KEY, hash);\n } catch {\n // localStorage quota / private mode — caller still gets the hash.\n }\n }\n return hash;\n}\n\n/** Test/diagnostic helper — never include in shipped reports. */\nexport function _resetFingerprintCacheForTests(): void {\n if (typeof localStorage !== 'undefined') {\n try {\n localStorage.removeItem(CACHE_KEY);\n } catch {\n // ignore\n }\n }\n}\n","const SESSION_KEY = 'mushi_session_id';\n\nlet cachedSessionId: string | null = null;\n\nexport function getSessionId(): string {\n if (cachedSessionId) return cachedSessionId;\n\n if (typeof sessionStorage !== 'undefined') {\n const existing = sessionStorage.getItem(SESSION_KEY);\n if (existing) {\n cachedSessionId = existing;\n return existing;\n }\n }\n\n const id = generateSessionId();\n cachedSessionId = id;\n\n if (typeof sessionStorage !== 'undefined') {\n try {\n sessionStorage.setItem(SESSION_KEY, id);\n } catch {\n // sessionStorage unavailable\n }\n }\n\n return id;\n}\n\nfunction generateSessionId(): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).slice(2, 8);\n return `ms_${timestamp}_${random}`;\n}\n","export interface RateLimiterConfig {\n maxBurst?: number;\n refillRate?: number;\n refillIntervalMs?: number;\n}\n\nexport interface RateLimiter {\n tryConsume(): boolean;\n reset(): void;\n availableTokens(): number;\n}\n\nconst DEFAULT_MAX_BURST = 10;\nconst DEFAULT_REFILL_RATE = 1;\nconst DEFAULT_REFILL_INTERVAL_MS = 5_000;\n\nexport function createRateLimiter(config: RateLimiterConfig = {}): RateLimiter {\n const {\n maxBurst = DEFAULT_MAX_BURST,\n refillRate = DEFAULT_REFILL_RATE,\n refillIntervalMs = DEFAULT_REFILL_INTERVAL_MS,\n } = config;\n\n let tokens = maxBurst;\n let lastRefill = Date.now();\n\n function refill() {\n const now = Date.now();\n const elapsed = now - lastRefill;\n const refills = Math.floor(elapsed / refillIntervalMs);\n if (refills > 0) {\n tokens = Math.min(maxBurst, tokens + refills * refillRate);\n lastRefill = now;\n }\n }\n\n function tryConsume(): boolean {\n refill();\n if (tokens > 0) {\n tokens--;\n return true;\n }\n return false;\n }\n\n function reset(): void {\n tokens = maxBurst;\n lastRefill = Date.now();\n }\n\n function availableTokens(): number {\n refill();\n return tokens;\n }\n\n return { tryConsume, reset, availableTokens };\n}\n","export interface PiiScrubberConfig {\n emails?: boolean;\n phones?: boolean;\n creditCards?: boolean;\n ssns?: boolean;\n ipAddresses?: boolean;\n /**\n * Scrub vendor-shaped secret tokens (AWS access keys, Stripe keys,\n * Slack/GitHub PATs, OpenAI/Anthropic/Google keys, JWTs).\n *\n * Wave S1 / D-15: SDK parity with the server-side scrubber. The server\n * scrubs these on every LLM invocation; the SDK now scrubs them at\n * capture so they never hit the wire in the first place — important for\n * users who `console.log(stripeKey)` during dev and later ship bug\n * reports with the error text attached.\n */\n secretTokens?: boolean;\n /** IPv6 addresses. Defaults off for the same reason IPv4 does. */\n ipv6?: boolean;\n}\n\ninterface PiiPattern {\n key: keyof PiiScrubberConfig;\n regex: RegExp;\n replacement: string;\n}\n\n// Order matters: SSN → CC → vendor secrets → email → phone → IP. Secret\n// tokens are matched *before* the generic email/phone regex because some JWT\n// payloads contain `.` that could be mis-parsed as `xyz.abc.com`.\nconst ORDERED_PATTERNS: PiiPattern[] = [\n { key: 'ssns', regex: /\\b\\d{3}-\\d{2}-\\d{4}\\b/g, replacement: '[REDACTED_SSN]' },\n { key: 'creditCards', regex: /\\b(?:\\d[ -]*){12,18}\\d\\b/g, replacement: '[REDACTED_CC]' },\n\n // Vendor secret tokens — mirrors packages/server/.../pii-scrubber.ts exactly.\n { key: 'secretTokens', regex: /\\b(?:AKIA|ASIA)[0-9A-Z]{16}\\b/g, replacement: '[REDACTED_AWS_KEY]' },\n { key: 'secretTokens', regex: /(?:aws_secret_access_key|secret_access_key)[\"'\\s:=]+[A-Za-z0-9/+=]{40}\\b/gi, replacement: 'aws_secret_access_key=[REDACTED_AWS_SECRET]' },\n { key: 'secretTokens', regex: /\\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{24,}\\b/g, replacement: '[REDACTED_STRIPE_KEY]' },\n { key: 'secretTokens', regex: /\\bpk_(?:live|test)_[A-Za-z0-9]{24,}\\b/g, replacement: '[REDACTED_STRIPE_PK]' },\n { key: 'secretTokens', regex: /\\bxox[abpor]-[A-Za-z0-9-]{10,}\\b/g, replacement: '[REDACTED_SLACK_TOKEN]' },\n { key: 'secretTokens', regex: /\\bghp_[A-Za-z0-9]{36}\\b/g, replacement: '[REDACTED_GITHUB_PAT]' },\n { key: 'secretTokens', regex: /\\bgithub_pat_[A-Za-z0-9_]{80,}\\b/g, replacement: '[REDACTED_GITHUB_PAT]' },\n { key: 'secretTokens', regex: /\\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\\b/g, replacement: '[REDACTED_OPENAI_KEY]' },\n { key: 'secretTokens', regex: /\\bsk-ant-[A-Za-z0-9_-]{20,}\\b/g, replacement: '[REDACTED_ANTHROPIC_KEY]' },\n { key: 'secretTokens', regex: /\\bAIza[0-9A-Za-z_-]{35}\\b/g, replacement: '[REDACTED_GOOGLE_KEY]' },\n { key: 'secretTokens', regex: /\\beyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\b/g, replacement: '[REDACTED_JWT]' },\n\n { key: 'emails', regex: /\\b[A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z]{2,}\\b/g, replacement: '[REDACTED_EMAIL]' },\n { key: 'phones', regex: /(?:\\+\\d{1,3}[\\s.-])?\\(?\\d{2,4}\\)?[\\s.-]\\d{3,4}[\\s.-]\\d{3,4}\\b/g, replacement: '[REDACTED_PHONE]' },\n { key: 'ipAddresses', regex: /\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b/g, replacement: '[REDACTED_IP]' },\n { key: 'ipv6', regex: /\\b(?:[A-Fa-f0-9]{1,4}:){2,7}[A-Fa-f0-9]{0,4}\\b/g, replacement: '[REDACTED_IPV6]' },\n];\n\nconst DEFAULT_CONFIG: PiiScrubberConfig = {\n emails: true,\n phones: true,\n creditCards: true,\n ssns: true,\n ipAddresses: false,\n // Secret tokens default ON — if they leak into a bug report there's no\n // good reason to ship them to our servers. Cheaper to scrub client-side.\n secretTokens: true,\n ipv6: false,\n};\n\nexport function createPiiScrubber(config: PiiScrubberConfig = {}) {\n const merged = { ...DEFAULT_CONFIG, ...config };\n\n const activePatterns = ORDERED_PATTERNS.filter((p) => merged[p.key]);\n\n function scrub(text: string): string {\n if (!text) return text;\n let result = text;\n for (const { regex, replacement } of activePatterns) {\n result = result.replace(new RegExp(regex.source, regex.flags), replacement);\n }\n return result;\n }\n\n function scrubObject<T extends Record<string, unknown>>(obj: T, keys: string[]): T {\n const copy = { ...obj };\n for (const key of keys) {\n if (typeof copy[key] === 'string') {\n (copy as Record<string, unknown>)[key] = scrub(copy[key] as string);\n }\n }\n return copy;\n }\n\n return { scrub, scrubObject };\n}\n\nexport function scrubPii(text: string, config?: PiiScrubberConfig): string {\n return createPiiScrubber(config).scrub(text);\n}\n"]}
1
+ {"version":3,"sources":["../src/api-client.ts","../src/region.ts","../src/pre-filter.ts","../src/logger.ts","../src/queue-crypto.ts","../src/queue.ts","../src/environment.ts","../src/reporter-token.ts","../src/fingerprint.ts","../src/session.ts","../src/rate-limiter.ts","../src/pii-scrubber.ts"],"names":["getBackoffDelay","sleep"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { MushiApiClient, MushiApiResponse, MushiReport, MushiReportStatus, MushiRuntimeSdkConfig } from './types';\n\nexport interface ApiClientOptions {\n projectId: string;\n apiKey: string;\n /**\n * Override the API endpoint. Defaults to the canonical Cloud URL\n * (DEFAULT_API_ENDPOINT). Self-hosted users MUST set this.\n */\n apiEndpoint?: string;\n timeout?: number;\n maxRetries?: number;\n}\n\n// V5.3 (M-cross-cutting): canonical Cloud URL — the older `api.mushimushi.dev`\n// hostname was never wired up. Self-hosted users MUST override `apiEndpoint`.\nexport const DEFAULT_API_ENDPOINT = 'https://dxptnwrhwsqckaftyymj.supabase.co/functions/v1/api';\nconst DEFAULT_TIMEOUT = 10_000;\nconst DEFAULT_MAX_RETRIES = 2;\n\nexport function createApiClient(options: ApiClientOptions): MushiApiClient {\n const {\n projectId,\n apiKey,\n apiEndpoint = DEFAULT_API_ENDPOINT,\n timeout = DEFAULT_TIMEOUT,\n maxRetries = DEFAULT_MAX_RETRIES,\n } = options;\n\n let baseUrl = apiEndpoint.replace(/\\/$/, '');\n\n async function request<T>(\n method: string,\n path: string,\n body?: unknown,\n retries = maxRetries,\n ): Promise<MushiApiResponse<T>> {\n const url = `${baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'X-Mushi-Api-Key': apiKey,\n 'X-Mushi-Project': projectId,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timer);\n\n // C7: data residency — follow a one-shot redirect when the\n // gateway tells us the project lives in a different region. Cache the\n // new base URL so subsequent calls go straight to the right cluster.\n if (response.status === 307 || response.status === 308) {\n const target = response.headers.get('Location');\n if (target && retries > 0) {\n const targetBase = target.replace(/\\/v1\\/.*$/, '').replace(/\\/$/, '');\n if (targetBase !== baseUrl) {\n baseUrl = targetBase;\n return request<T>(method, path, body, retries - 1);\n }\n }\n }\n\n if (!response.ok) {\n const errorBody = await response.json().catch(() => ({}));\n if (response.status >= 500 && retries > 0) {\n await sleep(getBackoffDelay(maxRetries - retries));\n return request<T>(method, path, body, retries - 1);\n }\n return {\n ok: false,\n error: {\n code: `HTTP_${response.status}`,\n message:\n (errorBody as { message?: string; error?: { message?: string } }).error?.message ||\n (errorBody as { message?: string }).message ||\n `HTTP ${response.status} error`,\n },\n };\n }\n\n const payload = await response.json();\n const data = payload && typeof payload === 'object' && 'ok' in payload && 'data' in payload\n ? (payload as { data: T }).data\n : payload as T;\n return { ok: true, data };\n } catch (error) {\n clearTimeout(timer);\n\n if (retries > 0 && isRetryable(error)) {\n await sleep(getBackoffDelay(maxRetries - retries));\n return request<T>(method, path, body, retries - 1);\n }\n\n return {\n ok: false,\n error: {\n code: 'NETWORK_ERROR',\n message: error instanceof Error ? error.message : 'Unknown network error',\n },\n };\n }\n }\n\n return {\n async submitReport(report: MushiReport) {\n return request<{ reportId: string }>('POST', '/v1/reports', report);\n },\n\n async getReportStatus(reportId: string) {\n return request<{ status: MushiReportStatus }>('GET', `/v1/reports/${reportId}/status`);\n },\n\n async getSdkConfig() {\n return request<MushiRuntimeSdkConfig>('GET', '/v1/sdk/config');\n },\n };\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction getBackoffDelay(attempt: number): number {\n return Math.min(1000 * 2 ** attempt + Math.random() * 500, 10_000);\n}\n\nfunction isRetryable(error: unknown): boolean {\n if (error instanceof DOMException && error.name === 'AbortError') return true;\n if (error instanceof TypeError) return true; // network failures\n return false;\n}\n","/**\n * C7: Data residency region resolution.\n *\n * The SDK supports four regional clouds:\n * - 'us' → United States (default; legacy `dxptnwrhwsqckaftyymj`)\n * - 'eu' → European Union (Frankfurt)\n * - 'jp' → Japan (Tokyo)\n * - 'self' → self-hosted / BYO Supabase\n *\n * Customers choose a region at project creation time, and the gateway will\n * 307-redirect any cross-region calls to the correct host. The SDK caches\n * the resolved hostname in `localStorage` (browser) so that subsequent\n * sessions skip the redirect.\n */\n\nexport type MushiRegion = 'us' | 'eu' | 'jp' | 'self';\n\nexport const REGION_ENDPOINTS: Record<Exclude<MushiRegion, 'self'>, string> = {\n us: 'https://api.us.mushimushi.dev/functions/v1/api',\n eu: 'https://api.eu.mushimushi.dev/functions/v1/api',\n jp: 'https://api.jp.mushimushi.dev/functions/v1/api',\n};\n\nconst ROUTING_CACHE_KEY = 'mushi_region_v1';\nconst ROUTING_CACHE_TTL_MS = 24 * 60 * 60 * 1000;\n\ninterface RegionCacheEntry {\n region: MushiRegion;\n endpoint: string;\n ts: number;\n}\n\n/**\n * Resolve the regional endpoint for a project. Looks up the public\n * `region_routing` table on the legacy US gateway (the catalog of record),\n * then caches the result.\n *\n * Falls back to the explicit `apiEndpoint` if anything goes wrong — failure\n * here must never block report submission.\n */\nexport async function resolveRegionEndpoint(opts: {\n projectId: string;\n apiEndpoint: string;\n region?: MushiRegion;\n storage?: Storage;\n fetcher?: typeof fetch;\n}): Promise<string> {\n const explicit = opts.region;\n if (explicit && explicit !== 'self' && REGION_ENDPOINTS[explicit]) {\n return REGION_ENDPOINTS[explicit];\n }\n\n const storage = opts.storage ?? safeLocalStorage();\n const cached = readCache(storage, opts.projectId);\n if (cached) return cached;\n\n try {\n const fetcher = opts.fetcher ?? fetch;\n const url = `${opts.apiEndpoint.replace(/\\/$/, '')}/v1/region/resolve?project_id=${encodeURIComponent(opts.projectId)}`;\n const res = await fetcher(url, { method: 'GET' });\n if (!res.ok) return opts.apiEndpoint;\n const body = (await res.json()) as { region?: MushiRegion; endpoint?: string };\n if (!body.region || !body.endpoint) return opts.apiEndpoint;\n writeCache(storage, opts.projectId, { region: body.region, endpoint: body.endpoint, ts: Date.now() });\n return body.endpoint;\n } catch {\n return opts.apiEndpoint;\n }\n}\n\nfunction safeLocalStorage(): Storage | undefined {\n try {\n return typeof globalThis !== 'undefined' && 'localStorage' in globalThis\n ? (globalThis as { localStorage: Storage }).localStorage\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction readCache(storage: Storage | undefined, projectId: string): string | null {\n if (!storage) return null;\n try {\n const raw = storage.getItem(`${ROUTING_CACHE_KEY}:${projectId}`);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as RegionCacheEntry;\n if (Date.now() - parsed.ts > ROUTING_CACHE_TTL_MS) return null;\n return parsed.endpoint;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(storage: Storage | undefined, projectId: string, entry: RegionCacheEntry): void {\n if (!storage) return;\n try {\n storage.setItem(`${ROUTING_CACHE_KEY}:${projectId}`, JSON.stringify(entry));\n } catch {\n /* no-op: quota exceeded etc. */\n }\n}\n","import type { MushiPreFilterConfig } from './types';\n\nexport interface PreFilterResult {\n passed: boolean;\n reason?: string;\n}\n\nconst DEFAULT_MIN_LENGTH = 10;\nconst DEFAULT_MAX_LENGTH = 2000;\n\nconst SPAM_PATTERNS: RegExp[] = [\n /^(.)\\1{10,}$/, // repeated single character\n /^[A-Z\\s!?]{20,}$/, // all caps shouting\n /^[\\d\\s]+$/, // numbers only\n /^[^a-zA-Z\\u00C0-\\u024F\\u4E00-\\u9FFF\\u3040-\\u309F\\u30A0-\\u30FF]{10,}$/, // no real letters\n /\\b(test|asdf|qwerty|lorem ipsum)\\b/i, // common test strings\n];\n\nconst GIBBERISH_PATTERN = /^[bcdfghjklmnpqrstvwxz]{6,}/i; // consonant-only strings\n\nexport function createPreFilter(config: MushiPreFilterConfig = {}) {\n const {\n enabled = true,\n blockObviousSpam = true,\n minDescriptionLength = DEFAULT_MIN_LENGTH,\n maxDescriptionLength = DEFAULT_MAX_LENGTH,\n } = config;\n\n function check(description: string): PreFilterResult {\n if (!enabled) {\n return { passed: true };\n }\n\n const trimmed = description.trim();\n\n if (trimmed.length < minDescriptionLength) {\n return { passed: false, reason: `Too short (min ${minDescriptionLength} characters)` };\n }\n\n if (trimmed.length > maxDescriptionLength) {\n return { passed: false, reason: `Too long (max ${maxDescriptionLength} characters)` };\n }\n\n if (blockObviousSpam) {\n for (const pattern of SPAM_PATTERNS) {\n if (pattern.test(trimmed)) {\n return { passed: false, reason: 'Detected as spam' };\n }\n }\n\n if (GIBBERISH_PATTERN.test(trimmed)) {\n return { passed: false, reason: 'Detected as gibberish' };\n }\n\n const words = trimmed.split(/\\s+/).filter((w) => w.length > 1);\n if (words.length < 2) {\n return { passed: false, reason: 'Description needs at least 2 words' };\n }\n }\n\n return { passed: true };\n }\n\n function truncate(description: string): string {\n const trimmed = description.trim();\n if (trimmed.length <= maxDescriptionLength) return trimmed;\n return trimmed.slice(0, maxDescriptionLength) + '...';\n }\n\n return { check, truncate };\n}\n","/**\n * FILE: logger.ts\n * PURPOSE: Zero-dependency structured logger for the mushi-mushi SDK ecosystem.\n *\n * OVERVIEW:\n * - Production-grade logging with levels, scoped namespaces, and child loggers\n * - JSON output for server/production, pretty-formatted output for development\n * - Automatic environment detection (browser vs Node vs Deno)\n * - Structured metadata on every log entry\n * - No external dependencies — safe to ship in any SDK bundle\n *\n * USAGE:\n * import { createLogger } from '@mushi-mushi/core'\n * const log = createLogger({ scope: 'mushi:api' })\n * log.info('Request received', { method: 'POST', path: '/v1/reports' })\n * const child = log.child('ingest', { reportId: 'abc' })\n * child.warn('Slow query', { latencyMs: 420 })\n *\n * TECHNICAL DETAILS:\n * - Log levels: debug(10) < info(20) < warn(30) < error(40) < fatal(50) < silent(99)\n * - Format auto-detected: JSON in production/server, pretty in development\n * - Pretty format uses ANSI colors when supported (Node/Deno TTY)\n * - Child loggers inherit parent scope + metadata, can override level\n * - Timestamps are ISO 8601 with millisecond precision\n */\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'silent'\n\nexport type LogFormat = 'json' | 'pretty' | 'auto'\n\nexport interface LoggerOptions {\n scope: string\n level?: LogLevel\n meta?: Record<string, unknown>\n format?: LogFormat\n}\n\nexport interface Logger {\n debug(msg: string, meta?: Record<string, unknown>): void\n info(msg: string, meta?: Record<string, unknown>): void\n warn(msg: string, meta?: Record<string, unknown>): void\n error(msg: string, meta?: Record<string, unknown>): void\n fatal(msg: string, meta?: Record<string, unknown>): void\n child(scope: string, meta?: Record<string, unknown>): Logger\n setLevel(level: LogLevel): void\n}\n\nexport interface LogEntry {\n ts: string\n level: LogLevel\n scope: string\n msg: string\n [key: string]: unknown\n}\n\nconst LEVEL_VALUE: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n fatal: 50,\n silent: 99,\n}\n\nconst LEVEL_LABEL: Record<string, string> = {\n debug: 'DBG',\n info: 'INF',\n warn: 'WRN',\n error: 'ERR',\n fatal: 'FTL',\n}\n\nconst ANSI = {\n reset: '\\x1b[0m',\n dim: '\\x1b[2m',\n bold: '\\x1b[1m',\n cyan: '\\x1b[36m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n red: '\\x1b[31m',\n magenta: '\\x1b[35m',\n white: '\\x1b[37m',\n bgRed: '\\x1b[41m',\n} as const\n\nconst LEVEL_COLOR: Record<string, string> = {\n debug: ANSI.dim,\n info: ANSI.green,\n warn: ANSI.yellow,\n error: ANSI.red,\n fatal: `${ANSI.bgRed}${ANSI.white}${ANSI.bold}`,\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nfunction detectFormat(): 'json' | 'pretty' {\n try {\n if (typeof (globalThis as any).Deno !== 'undefined') return 'json'\n } catch { /* not Deno */ }\n\n const proc = typeof (globalThis as any).process !== 'undefined'\n ? (globalThis as any).process\n : undefined\n\n if (proc?.env) {\n if (proc.env.NODE_ENV === 'production') return 'json'\n if (proc.env.LOG_FORMAT === 'json') return 'json'\n if (proc.env.LOG_FORMAT === 'pretty') return 'pretty'\n if (proc.stdout?.isTTY) return 'pretty'\n }\n\n if (typeof (globalThis as any).window !== 'undefined') return 'pretty'\n\n return 'json'\n}\n/* eslint-enable @typescript-eslint/no-explicit-any */\n\nfunction flattenMeta(meta: Record<string, unknown>): string {\n const parts: string[] = []\n for (const [k, v] of Object.entries(meta)) {\n if (v === undefined || v === null) continue\n if (typeof v === 'object') {\n parts.push(`${k}=${JSON.stringify(v)}`)\n } else {\n parts.push(`${k}=${String(v)}`)\n }\n }\n return parts.join(' ')\n}\n\nfunction formatPretty(entry: LogEntry): string {\n const { ts, level, scope, msg, ...rest } = entry\n const time = ts.slice(11, 23)\n const color = LEVEL_COLOR[level] ?? ''\n const label = LEVEL_LABEL[level] ?? level.toUpperCase()\n const metaStr = Object.keys(rest).length > 0 ? ` ${ANSI.dim}${flattenMeta(rest)}${ANSI.reset}` : ''\n\n return `${ANSI.dim}${time}${ANSI.reset} ${color}${label}${ANSI.reset} ${ANSI.cyan}[${scope}]${ANSI.reset} ${msg}${metaStr}`\n}\n\nfunction formatJson(entry: LogEntry): string {\n return JSON.stringify(entry)\n}\n\nfunction emit(level: LogLevel, formatted: string): void {\n switch (level) {\n case 'error':\n case 'fatal':\n console.error(formatted)\n break\n case 'warn':\n console.warn(formatted)\n break\n default:\n console.log(formatted)\n }\n}\n\nfunction buildLogger(\n scope: string,\n minLevel: LogLevel,\n baseMeta: Record<string, unknown>,\n formatter: (entry: LogEntry) => string,\n): Logger {\n let currentLevel = minLevel\n\n function log(level: LogLevel, msg: string, meta?: Record<string, unknown>): void {\n if (LEVEL_VALUE[level] < LEVEL_VALUE[currentLevel]) return\n\n const entry: LogEntry = {\n ts: new Date().toISOString(),\n level,\n scope,\n msg,\n ...baseMeta,\n ...meta,\n }\n\n emit(level, formatter(entry))\n }\n\n return {\n debug: (msg, meta?) => log('debug', msg, meta),\n info: (msg, meta?) => log('info', msg, meta),\n warn: (msg, meta?) => log('warn', msg, meta),\n error: (msg, meta?) => log('error', msg, meta),\n fatal: (msg, meta?) => log('fatal', msg, meta),\n\n child(childScope: string, childMeta?: Record<string, unknown>): Logger {\n return buildLogger(\n `${scope}:${childScope}`,\n currentLevel,\n { ...baseMeta, ...childMeta },\n formatter,\n )\n },\n\n setLevel(level: LogLevel) {\n currentLevel = level\n },\n }\n}\n\n/**\n * Create a structured logger instance.\n *\n * @example\n * const log = createLogger({ scope: 'mushi:api', level: 'info' })\n * log.info('Server started', { port: 3000 })\n *\n * const child = log.child('auth', { userId: 'u-123' })\n * child.warn('Token expired')\n */\nexport function createLogger(options: LoggerOptions): Logger {\n const {\n scope,\n level = 'info',\n meta = {},\n format = 'auto',\n } = options\n\n const resolvedFormat = format === 'auto' ? detectFormat() : format\n const formatter = resolvedFormat === 'json' ? formatJson : formatPretty\n\n return buildLogger(scope, level, meta, formatter)\n}\n\n/**\n * Noop logger that discards all output.\n * Useful when logging should be completely disabled.\n */\nexport const noopLogger: Logger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n fatal: () => {},\n child: () => noopLogger,\n setLevel: () => {},\n}\n","/**\n * AES-GCM at-rest encryption for the offline queue (Wave S1 / D-16).\n *\n * Why this exists: on shared devices (kiosks, support-agent laptops) a\n * queued bug report sits in plaintext IndexedDB until the next flush.\n * Browser extensions, other tabs on the same origin, and forensic tools\n * with disk access can all read it. For a QA/bug-reporting SDK that\n * encourages users to paste sensitive data into descriptions, that's\n * unacceptable.\n *\n * Design:\n * - Generate a non-extractable AES-GCM key on first call (256-bit).\n * - Persist the `CryptoKey` object itself (Web Crypto allows IDB round-\n * trip of `CryptoKey` without ever serialising the raw bytes).\n * - Use a 12-byte random IV per payload; prepend it to ciphertext so\n * decrypt() needs no out-of-band state.\n * - Never block the caller — all errors bubble up so the queue can fall\n * back to plaintext storage with a debug log (see queue.ts).\n *\n * The key is tied to the browser origin (same-origin IDB). It does NOT\n * protect against an attacker with admin shell on the device: the browser\n * WILL decrypt on demand for anyone with origin access. That's the same\n * guarantee every origin-bound browser secret has and is the correct\n * threat model for offline bug reports.\n */\n\nconst KEY_DB = 'mushi-mushi-keyring';\nconst KEY_STORE = 'keys';\nconst KEY_RECORD_ID = 'offline-queue/v1';\n\nlet cachedKey: CryptoKey | null = null;\nlet cachedKeyPromise: Promise<CryptoKey> | null = null;\n\nfunction hasWebCrypto(): boolean {\n return (\n typeof globalThis !== 'undefined' &&\n typeof (globalThis as unknown as { crypto?: Crypto }).crypto !== 'undefined' &&\n typeof (globalThis as unknown as { crypto: Crypto }).crypto.subtle !== 'undefined' &&\n typeof indexedDB !== 'undefined'\n );\n}\n\nfunction openKeyDb(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.open(KEY_DB, 1);\n req.onupgradeneeded = () => {\n const db = req.result;\n if (!db.objectStoreNames.contains(KEY_STORE)) {\n db.createObjectStore(KEY_STORE);\n }\n };\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n });\n}\n\nasync function loadKey(): Promise<CryptoKey | null> {\n const db = await openKeyDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(KEY_STORE, 'readonly');\n const req = tx.objectStore(KEY_STORE).get(KEY_RECORD_ID);\n req.onsuccess = () => resolve((req.result as CryptoKey) ?? null);\n req.onerror = () => reject(req.error);\n });\n}\n\nasync function storeKey(key: CryptoKey): Promise<void> {\n const db = await openKeyDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(KEY_STORE, 'readwrite');\n tx.objectStore(KEY_STORE).put(key, KEY_RECORD_ID);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\n/**\n * Lazily get (or generate once + persist) the AES-GCM key for this origin.\n * `extractable: false` — so a script-level attacker can't `exportKey()` and\n * ship the raw bytes to their server, only use it via `encrypt`/`decrypt`.\n */\nexport async function getOfflineQueueKey(): Promise<CryptoKey> {\n if (cachedKey) return cachedKey;\n if (cachedKeyPromise) return cachedKeyPromise;\n if (!hasWebCrypto()) {\n throw new Error('Web Crypto + IndexedDB required for offline queue encryption');\n }\n cachedKeyPromise = (async () => {\n const existing = await loadKey();\n if (existing) {\n cachedKey = existing;\n return existing;\n }\n const key = await crypto.subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt'],\n );\n await storeKey(key);\n cachedKey = key;\n return key;\n })();\n return cachedKeyPromise;\n}\n\nexport interface EncryptedPayload {\n /** Magic marker so decrypt() can tell encrypted vs legacy plaintext rows. */\n readonly _mme: 1;\n readonly iv: string;\n readonly ct: string;\n}\n\nfunction bytesToB64(bytes: Uint8Array): string {\n let s = '';\n for (const b of bytes) s += String.fromCharCode(b);\n return btoa(s);\n}\n\nfunction b64ToBytes(s: string): Uint8Array<ArrayBuffer> {\n const bin = atob(s);\n const out = new Uint8Array(new ArrayBuffer(bin.length));\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nexport async function encryptJson(plain: unknown): Promise<EncryptedPayload> {\n const key = await getOfflineQueueKey();\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const data = new TextEncoder().encode(JSON.stringify(plain));\n const cipher = new Uint8Array(await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, data));\n return { _mme: 1, iv: bytesToB64(iv), ct: bytesToB64(cipher) };\n}\n\nexport function isEncryptedPayload(v: unknown): v is EncryptedPayload {\n return (\n !!v &&\n typeof v === 'object' &&\n (v as EncryptedPayload)._mme === 1 &&\n typeof (v as EncryptedPayload).iv === 'string' &&\n typeof (v as EncryptedPayload).ct === 'string'\n );\n}\n\nexport async function decryptJson<T = unknown>(payload: EncryptedPayload): Promise<T> {\n const key = await getOfflineQueueKey();\n const iv = b64ToBytes(payload.iv);\n const ct = b64ToBytes(payload.ct);\n const plain = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, key, ct);\n return JSON.parse(new TextDecoder().decode(plain)) as T;\n}\n","import type { MushiApiClient, MushiOfflineConfig, MushiReport } from './types';\nimport { createLogger } from './logger';\nimport {\n encryptJson,\n decryptJson,\n isEncryptedPayload,\n type EncryptedPayload,\n} from './queue-crypto';\n\nconst queueLog = createLogger({ scope: 'mushi:queue', level: 'warn' });\n\n// Wave S1 / D-16: opaque at-rest wrapper. Each queue row is either:\n// - a legacy plaintext `MushiReport` (pre-encryption; still readable)\n// - an `EncryptedRecord` with a bare `id` (so count / delete can operate\n// without decrypting every row) plus the encrypted payload blob.\ninterface EncryptedRecord {\n id: string;\n queuedAt: string;\n payload: EncryptedPayload;\n}\n\ntype StoredRow = MushiReport | EncryptedRecord;\n\nconst DB_NAME = 'mushi-mushi';\nconst STORE_NAME = 'offline-reports';\nconst DB_VERSION = 1;\nconst LS_KEY = 'mushi_offline_queue';\nconst BATCH_SIZE = 10;\nconst MAX_BACKOFF_MS = 60_000;\n\nexport interface OfflineQueue {\n enqueue(report: MushiReport): Promise<void>;\n flush(client: MushiApiClient): Promise<{ sent: number; failed: number }>;\n size(): Promise<number>;\n clear(): Promise<void>;\n startAutoSync(client: MushiApiClient): void;\n stopAutoSync(): void;\n}\n\ntype StorageBackend = 'indexeddb' | 'localstorage' | 'none';\n\nexport function createOfflineQueue(config: MushiOfflineConfig = {}): OfflineQueue {\n const { enabled = true, maxQueueSize = 50, syncOnReconnect = true, encryptAtRest = true } = config;\n\n let syncCleanup: (() => void) | null = null;\n let backendType: StorageBackend | null = null;\n\n async function wrapForStorage(report: MushiReport): Promise<StoredRow> {\n const queuedAt = new Date().toISOString();\n if (!encryptAtRest) {\n return { ...report, queuedAt } as MushiReport;\n }\n try {\n const payload = await encryptJson(report);\n return { id: report.id, queuedAt, payload } satisfies EncryptedRecord;\n } catch (err) {\n // Encryption failure is non-fatal — queue integrity matters more than\n // at-rest confidentiality. We fall back to plaintext and warn.\n queueLog.warn('Offline queue: encryption failed, storing plaintext', { err: String(err) });\n return { ...report, queuedAt } as MushiReport;\n }\n }\n\n async function unwrapForSend(row: StoredRow): Promise<MushiReport | null> {\n if (isEncryptedRecord(row)) {\n try {\n return await decryptJson<MushiReport>(row.payload);\n } catch (err) {\n queueLog.warn('Offline queue: decrypt failed, dropping row', { err: String(err), id: row.id });\n return null;\n }\n }\n return row;\n }\n\n function isEncryptedRecord(row: StoredRow): row is EncryptedRecord {\n return !!(row as EncryptedRecord).payload && isEncryptedPayload((row as EncryptedRecord).payload);\n }\n\n function detectBackend(): StorageBackend {\n if (backendType) return backendType;\n if (typeof indexedDB !== 'undefined') {\n backendType = 'indexeddb';\n } else if (typeof localStorage !== 'undefined') {\n backendType = 'localstorage';\n } else {\n backendType = 'none';\n }\n return backendType;\n }\n\n // --- IndexedDB backend ---\n\n function openDb(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME, { keyPath: 'id' });\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => {\n backendType = 'localstorage';\n reject(request.error);\n };\n });\n }\n\n async function idbEnqueue(report: MushiReport): Promise<void> {\n const db = await openDb();\n const row = await wrapForStorage(report);\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite');\n tx.objectStore(STORE_NAME).put(row);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n async function idbGetAll(): Promise<StoredRow[]> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readonly');\n const request = tx.objectStore(STORE_NAME).getAll();\n request.onsuccess = () => resolve(request.result as StoredRow[]);\n request.onerror = () => reject(request.error);\n });\n }\n\n async function idbDelete(id: string): Promise<void> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite');\n tx.objectStore(STORE_NAME).delete(id);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n async function idbSize(): Promise<number> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readonly');\n const request = tx.objectStore(STORE_NAME).count();\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n }\n\n async function idbClear(): Promise<void> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite');\n tx.objectStore(STORE_NAME).clear();\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n // --- localStorage fallback ---\n\n function lsRead(): StoredRow[] {\n try {\n const raw = localStorage.getItem(LS_KEY);\n return raw ? (JSON.parse(raw) as StoredRow[]) : [];\n } catch {\n return [];\n }\n }\n\n function lsWrite(rows: StoredRow[]): void {\n try {\n localStorage.setItem(LS_KEY, JSON.stringify(rows));\n } catch {\n // localStorage full or unavailable\n }\n }\n\n async function lsEnqueue(report: MushiReport): Promise<void> {\n const rows = lsRead();\n rows.push(await wrapForStorage(report));\n lsWrite(rows);\n }\n\n function lsDelete(id: string): void {\n const rows = lsRead().filter((r) => r.id !== id);\n lsWrite(rows);\n }\n\n // --- Unified interface ---\n\n async function enqueue(report: MushiReport): Promise<void> {\n if (!enabled) return;\n\n const currentSize = await size();\n if (currentSize >= maxQueueSize) {\n queueLog.warn('Offline queue full — dropping report', { maxQueueSize });\n return;\n }\n\n const backend = detectBackend();\n if (backend === 'indexeddb') {\n try {\n await idbEnqueue(report);\n return;\n } catch {\n // IndexedDB failed, fall through to localStorage\n backendType = 'localstorage';\n }\n }\n\n if (backend === 'localstorage' || backendType === 'localstorage') {\n await lsEnqueue(report);\n return;\n }\n }\n\n function getBackoffDelay(attempt: number): number {\n return Math.min(1000 * 2 ** attempt + Math.random() * 500, MAX_BACKOFF_MS);\n }\n\n function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n async function flush(client: MushiApiClient): Promise<{ sent: number; failed: number }> {\n if (!enabled) return { sent: 0, failed: 0 };\n\n let rows: StoredRow[];\n const backend = detectBackend();\n\n if (backend === 'indexeddb') {\n try {\n rows = await idbGetAll();\n } catch {\n rows = lsRead();\n }\n } else {\n rows = lsRead();\n }\n\n const batch = rows.slice(0, BATCH_SIZE);\n let sent = 0;\n let failed = 0;\n\n for (let i = 0; i < batch.length; i++) {\n const row = batch[i];\n const rowId = (row as { id: string }).id;\n const report = await unwrapForSend(row);\n\n if (!report) {\n // Undecryptable row — drop so it doesn't re-poison the queue forever.\n try {\n if (backend === 'indexeddb') await idbDelete(rowId);\n else lsDelete(rowId);\n } catch {\n lsDelete(rowId);\n }\n failed++;\n continue;\n }\n\n const result = await client.submitReport(report);\n\n if (result.ok) {\n try {\n if (backend === 'indexeddb') await idbDelete(rowId);\n else lsDelete(rowId);\n } catch {\n lsDelete(rowId);\n }\n sent++;\n } else {\n failed++;\n if (i < batch.length - 1) {\n await sleep(getBackoffDelay(i));\n }\n }\n }\n\n return { sent, failed };\n }\n\n async function size(): Promise<number> {\n const backend = detectBackend();\n if (backend === 'indexeddb') {\n try {\n return await idbSize();\n } catch {\n return lsRead().length;\n }\n }\n return lsRead().length;\n }\n\n async function clear(): Promise<void> {\n const backend = detectBackend();\n if (backend === 'indexeddb') {\n try {\n await idbClear();\n } catch {\n // fall through\n }\n }\n try {\n localStorage.removeItem(LS_KEY);\n } catch {\n // unavailable\n }\n }\n\n function startAutoSync(client: MushiApiClient): void {\n if (!enabled || !syncOnReconnect || typeof window === 'undefined') return;\n\n const handler = () => {\n if (navigator.onLine) {\n flush(client).catch(() => {});\n }\n };\n\n window.addEventListener('online', handler);\n syncCleanup = () => window.removeEventListener('online', handler);\n }\n\n function stopAutoSync(): void {\n syncCleanup?.();\n syncCleanup = null;\n }\n\n return { enqueue, flush, size, clear, startAutoSync, stopAutoSync };\n}\n","import type { MushiEnvironment } from './types';\n\nexport function captureEnvironment(): MushiEnvironment {\n const nav = typeof navigator !== 'undefined' ? navigator : undefined;\n const win = typeof window !== 'undefined' ? window : undefined;\n const doc = typeof document !== 'undefined' ? document : undefined;\n\n const connection = nav && 'connection' in nav ? (nav as NavigatorWithConnection).connection : undefined;\n\n return {\n userAgent: nav?.userAgent ?? 'unknown',\n platform: nav?.platform ?? 'unknown',\n language: nav?.language ?? 'en',\n viewport: {\n width: win?.innerWidth ?? 0,\n height: win?.innerHeight ?? 0,\n },\n url: win?.location?.href ?? '',\n referrer: doc?.referrer ?? '',\n timestamp: new Date().toISOString(),\n timezone: Intl?.DateTimeFormat?.()?.resolvedOptions?.()?.timeZone ?? 'UTC',\n connection: connection\n ? {\n effectiveType: connection.effectiveType,\n downlink: connection.downlink,\n rtt: connection.rtt,\n }\n : undefined,\n deviceMemory: (nav as NavigatorWithDeviceMemory)?.deviceMemory,\n hardwareConcurrency: nav?.hardwareConcurrency,\n };\n}\n\ninterface NetworkInformation {\n effectiveType?: string;\n downlink?: number;\n rtt?: number;\n}\n\ninterface NavigatorWithConnection extends Navigator {\n connection?: NetworkInformation;\n}\n\ninterface NavigatorWithDeviceMemory extends Navigator {\n deviceMemory?: number;\n}\n","const STORAGE_KEY = 'mushi_reporter_token';\n\nexport function getReporterToken(): string {\n if (typeof localStorage !== 'undefined') {\n const existing = localStorage.getItem(STORAGE_KEY);\n if (existing) return existing;\n }\n\n const token = generateToken();\n\n if (typeof localStorage !== 'undefined') {\n try {\n localStorage.setItem(STORAGE_KEY, token);\n } catch {\n // localStorage full or unavailable — token is ephemeral\n }\n }\n\n return token;\n}\n\nfunction generateToken(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return `mushi_${crypto.randomUUID()}`;\n }\n\n const bytes = new Uint8Array(16);\n if (typeof crypto !== 'undefined') {\n crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n\n const hex = Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n return `mushi_${hex}`;\n}\n","/**\n * §3c — stable device fingerprint hash.\n *\n * Hashes a deliberately small set of long-lived device characteristics so\n * the same browser keeps the same hash across sessions, but moving to a\n * new browser/device produces a different one. This lets the server\n * detect cross-account abuse (same hash → many reporter accounts) without\n * needing fingerprint.js or any other entropy-heavy library.\n *\n * Privacy notes:\n * - We never send the raw inputs, only the SHA-256 hex digest.\n * - The set is intentionally low-entropy on purpose; this is \"is this the\n * same device\" not \"who is this user\". For high-stakes anti-fraud you\n * should still combine with server-side IP/geo signals.\n * - Cached in localStorage so subsequent calls are zero-cost.\n */\n\nconst CACHE_KEY = 'mushi_fingerprint_hash';\n\ninterface FingerprintInputs {\n userAgent: string;\n platform: string;\n language: string;\n timezone: string;\n screenWidth: number;\n screenHeight: number;\n pixelRatio: number;\n deviceMemory: number | undefined;\n hardwareConcurrency: number | undefined;\n}\n\nfunction collectInputs(): FingerprintInputs {\n const nav = typeof navigator !== 'undefined' ? navigator : undefined;\n const scr = typeof screen !== 'undefined' ? screen : undefined;\n const win = typeof window !== 'undefined' ? window : undefined;\n return {\n userAgent: nav?.userAgent ?? 'unknown',\n platform: nav?.platform ?? 'unknown',\n language: nav?.language ?? 'en',\n timezone: Intl?.DateTimeFormat?.()?.resolvedOptions?.()?.timeZone ?? 'UTC',\n screenWidth: scr?.width ?? 0,\n screenHeight: scr?.height ?? 0,\n pixelRatio: win?.devicePixelRatio ?? 1,\n deviceMemory: (nav as NavigatorWithDeviceMemory | undefined)?.deviceMemory,\n hardwareConcurrency: nav?.hardwareConcurrency,\n };\n}\n\ninterface NavigatorWithDeviceMemory extends Navigator {\n deviceMemory?: number;\n}\n\nasync function sha256Hex(input: string): Promise<string> {\n if (typeof crypto !== 'undefined' && crypto.subtle) {\n const buf = new TextEncoder().encode(input);\n const digest = await crypto.subtle.digest('SHA-256', buf);\n return Array.from(new Uint8Array(digest))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n }\n // Fallback (Node 18+ test envs, very old browsers): non-cryptographic but\n // good enough for the \"are these two requests from the same device\" use\n // case the server makes of this value.\n let hash = 0;\n for (let i = 0; i < input.length; i++) {\n hash = (hash << 5) - hash + input.charCodeAt(i);\n hash |= 0;\n }\n return `fbk_${(hash >>> 0).toString(16).padStart(8, '0')}`;\n}\n\n/**\n * Returns a stable per-device hash. Cached in localStorage; first call is\n * one SHA-256, subsequent calls are a localStorage read.\n *\n * Returns `null` outside browser-like environments (SSR, web workers\n * without crypto.subtle) so callers can omit the field gracefully.\n */\nexport async function getDeviceFingerprintHash(): Promise<string | null> {\n if (typeof localStorage !== 'undefined') {\n const cached = localStorage.getItem(CACHE_KEY);\n if (cached) return cached;\n }\n\n const inputs = collectInputs();\n const serialised = JSON.stringify(inputs);\n const hash = await sha256Hex(serialised);\n\n if (typeof localStorage !== 'undefined') {\n try {\n localStorage.setItem(CACHE_KEY, hash);\n } catch {\n // localStorage quota / private mode — caller still gets the hash.\n }\n }\n return hash;\n}\n\n/** Test/diagnostic helper — never include in shipped reports. */\nexport function _resetFingerprintCacheForTests(): void {\n if (typeof localStorage !== 'undefined') {\n try {\n localStorage.removeItem(CACHE_KEY);\n } catch {\n // ignore\n }\n }\n}\n","const SESSION_KEY = 'mushi_session_id';\n\nlet cachedSessionId: string | null = null;\n\nexport function getSessionId(): string {\n if (cachedSessionId) return cachedSessionId;\n\n if (typeof sessionStorage !== 'undefined') {\n const existing = sessionStorage.getItem(SESSION_KEY);\n if (existing) {\n cachedSessionId = existing;\n return existing;\n }\n }\n\n const id = generateSessionId();\n cachedSessionId = id;\n\n if (typeof sessionStorage !== 'undefined') {\n try {\n sessionStorage.setItem(SESSION_KEY, id);\n } catch {\n // sessionStorage unavailable\n }\n }\n\n return id;\n}\n\nfunction generateSessionId(): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).slice(2, 8);\n return `ms_${timestamp}_${random}`;\n}\n","export interface RateLimiterConfig {\n maxBurst?: number;\n refillRate?: number;\n refillIntervalMs?: number;\n}\n\nexport interface RateLimiter {\n tryConsume(): boolean;\n reset(): void;\n availableTokens(): number;\n}\n\nconst DEFAULT_MAX_BURST = 10;\nconst DEFAULT_REFILL_RATE = 1;\nconst DEFAULT_REFILL_INTERVAL_MS = 5_000;\n\nexport function createRateLimiter(config: RateLimiterConfig = {}): RateLimiter {\n const {\n maxBurst = DEFAULT_MAX_BURST,\n refillRate = DEFAULT_REFILL_RATE,\n refillIntervalMs = DEFAULT_REFILL_INTERVAL_MS,\n } = config;\n\n let tokens = maxBurst;\n let lastRefill = Date.now();\n\n function refill() {\n const now = Date.now();\n const elapsed = now - lastRefill;\n const refills = Math.floor(elapsed / refillIntervalMs);\n if (refills > 0) {\n tokens = Math.min(maxBurst, tokens + refills * refillRate);\n lastRefill = now;\n }\n }\n\n function tryConsume(): boolean {\n refill();\n if (tokens > 0) {\n tokens--;\n return true;\n }\n return false;\n }\n\n function reset(): void {\n tokens = maxBurst;\n lastRefill = Date.now();\n }\n\n function availableTokens(): number {\n refill();\n return tokens;\n }\n\n return { tryConsume, reset, availableTokens };\n}\n","export interface PiiScrubberConfig {\n emails?: boolean;\n phones?: boolean;\n creditCards?: boolean;\n ssns?: boolean;\n ipAddresses?: boolean;\n /**\n * Scrub vendor-shaped secret tokens (AWS access keys, Stripe keys,\n * Slack/GitHub PATs, OpenAI/Anthropic/Google keys, JWTs).\n *\n * Wave S1 / D-15: SDK parity with the server-side scrubber. The server\n * scrubs these on every LLM invocation; the SDK now scrubs them at\n * capture so they never hit the wire in the first place — important for\n * users who `console.log(stripeKey)` during dev and later ship bug\n * reports with the error text attached.\n */\n secretTokens?: boolean;\n /** IPv6 addresses. Defaults off for the same reason IPv4 does. */\n ipv6?: boolean;\n}\n\ninterface PiiPattern {\n key: keyof PiiScrubberConfig;\n regex: RegExp;\n replacement: string;\n}\n\n// Order matters: SSN → CC → vendor secrets → email → phone → IP. Secret\n// tokens are matched *before* the generic email/phone regex because some JWT\n// payloads contain `.` that could be mis-parsed as `xyz.abc.com`.\nconst ORDERED_PATTERNS: PiiPattern[] = [\n { key: 'ssns', regex: /\\b\\d{3}-\\d{2}-\\d{4}\\b/g, replacement: '[REDACTED_SSN]' },\n { key: 'creditCards', regex: /\\b(?:\\d[ -]*){12,18}\\d\\b/g, replacement: '[REDACTED_CC]' },\n\n // Vendor secret tokens — mirrors packages/server/.../pii-scrubber.ts exactly.\n { key: 'secretTokens', regex: /\\b(?:AKIA|ASIA)[0-9A-Z]{16}\\b/g, replacement: '[REDACTED_AWS_KEY]' },\n { key: 'secretTokens', regex: /(?:aws_secret_access_key|secret_access_key)[\"'\\s:=]+[A-Za-z0-9/+=]{40}\\b/gi, replacement: 'aws_secret_access_key=[REDACTED_AWS_SECRET]' },\n { key: 'secretTokens', regex: /\\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{24,}\\b/g, replacement: '[REDACTED_STRIPE_KEY]' },\n { key: 'secretTokens', regex: /\\bpk_(?:live|test)_[A-Za-z0-9]{24,}\\b/g, replacement: '[REDACTED_STRIPE_PK]' },\n { key: 'secretTokens', regex: /\\bxox[abpor]-[A-Za-z0-9-]{10,}\\b/g, replacement: '[REDACTED_SLACK_TOKEN]' },\n { key: 'secretTokens', regex: /\\bghp_[A-Za-z0-9]{36}\\b/g, replacement: '[REDACTED_GITHUB_PAT]' },\n { key: 'secretTokens', regex: /\\bgithub_pat_[A-Za-z0-9_]{80,}\\b/g, replacement: '[REDACTED_GITHUB_PAT]' },\n { key: 'secretTokens', regex: /\\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\\b/g, replacement: '[REDACTED_OPENAI_KEY]' },\n { key: 'secretTokens', regex: /\\bsk-ant-[A-Za-z0-9_-]{20,}\\b/g, replacement: '[REDACTED_ANTHROPIC_KEY]' },\n { key: 'secretTokens', regex: /\\bAIza[0-9A-Za-z_-]{35}\\b/g, replacement: '[REDACTED_GOOGLE_KEY]' },\n { key: 'secretTokens', regex: /\\beyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\b/g, replacement: '[REDACTED_JWT]' },\n\n { key: 'emails', regex: /\\b[A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z]{2,}\\b/g, replacement: '[REDACTED_EMAIL]' },\n { key: 'phones', regex: /(?:\\+\\d{1,3}[\\s.-])?\\(?\\d{2,4}\\)?[\\s.-]\\d{3,4}[\\s.-]\\d{3,4}\\b/g, replacement: '[REDACTED_PHONE]' },\n { key: 'ipAddresses', regex: /\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b/g, replacement: '[REDACTED_IP]' },\n { key: 'ipv6', regex: /\\b(?:[A-Fa-f0-9]{1,4}:){2,7}[A-Fa-f0-9]{0,4}\\b/g, replacement: '[REDACTED_IPV6]' },\n];\n\nconst DEFAULT_CONFIG: PiiScrubberConfig = {\n emails: true,\n phones: true,\n creditCards: true,\n ssns: true,\n ipAddresses: false,\n // Secret tokens default ON — if they leak into a bug report there's no\n // good reason to ship them to our servers. Cheaper to scrub client-side.\n secretTokens: true,\n ipv6: false,\n};\n\nexport function createPiiScrubber(config: PiiScrubberConfig = {}) {\n const merged = { ...DEFAULT_CONFIG, ...config };\n\n const activePatterns = ORDERED_PATTERNS.filter((p) => merged[p.key]);\n\n function scrub(text: string): string {\n if (!text) return text;\n let result = text;\n for (const { regex, replacement } of activePatterns) {\n result = result.replace(new RegExp(regex.source, regex.flags), replacement);\n }\n return result;\n }\n\n function scrubObject<T extends Record<string, unknown>>(obj: T, keys: string[]): T {\n const copy = { ...obj };\n for (const key of keys) {\n if (typeof copy[key] === 'string') {\n (copy as Record<string, unknown>)[key] = scrub(copy[key] as string);\n }\n }\n return copy;\n }\n\n return { scrub, scrubObject };\n}\n\nexport function scrubPii(text: string, config?: PiiScrubberConfig): string {\n return createPiiScrubber(config).scrub(text);\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -2,6 +2,12 @@ interface MushiConfig {
2
2
  projectId: string;
3
3
  apiKey: string;
4
4
  apiEndpoint?: string;
5
+ /**
6
+ * Fetch non-secret widget/capture settings from the Mushi project at
7
+ * startup. Defaults to true so console changes apply without rebuilding
8
+ * host apps. Set false for fully static/offline deployments.
9
+ */
10
+ runtimeConfig?: boolean;
5
11
  sentry?: MushiSentryConfig;
6
12
  widget?: MushiWidgetConfig;
7
13
  capture?: MushiCaptureConfig;
@@ -27,6 +33,38 @@ interface MushiWidgetConfig {
27
33
  mode?: 'simple' | 'conversational';
28
34
  locale?: string;
29
35
  zIndex?: number;
36
+ /**
37
+ * Controls how, or whether, the default trigger is injected.
38
+ * `auto` preserves the historical floating stamp button.
39
+ */
40
+ trigger?: 'auto' | 'edge-tab' | 'attach' | 'manual' | 'hidden';
41
+ /** CSS selector used when `trigger` is `attach`. */
42
+ attachToSelector?: string;
43
+ /**
44
+ * Per-edge trigger offset in pixels. `auto` clears the corresponding edge.
45
+ * Defaults to the historical 24px gutter plus safe-area insets.
46
+ */
47
+ inset?: MushiWidgetInset;
48
+ respectSafeArea?: boolean;
49
+ /** Hide the launcher while any matching element exists in the document. */
50
+ hideOnSelector?: string;
51
+ /** Hide the launcher on matching pathnames. Strings are substring matches. */
52
+ hideOnRoutes?: string[];
53
+ environments?: Partial<Record<'production' | 'staging' | 'development', 'always' | 'never' | 'manual'>>;
54
+ /** Opt-in smart trigger behavior; planned to become the default in a later minor. */
55
+ smartHide?: boolean | MushiWidgetSmartHideConfig;
56
+ draggable?: boolean;
57
+ }
58
+ interface MushiWidgetInset {
59
+ top?: number | 'auto';
60
+ right?: number | 'auto';
61
+ bottom?: number | 'auto';
62
+ left?: number | 'auto';
63
+ }
64
+ interface MushiWidgetSmartHideConfig {
65
+ onMobile?: 'edge-tab' | 'hide' | false;
66
+ onScroll?: 'shrink' | 'hide' | false;
67
+ onIdleMs?: number;
30
68
  }
31
69
  interface MushiCaptureConfig {
32
70
  console?: boolean;
@@ -228,8 +266,14 @@ interface MushiSDKInstance {
228
266
  setMetadata(key: string, value: unknown): void;
229
267
  isOpen(): boolean;
230
268
  open(): void;
269
+ openWith(category: MushiReportCategory): void;
270
+ show(): void;
271
+ hide(): void;
272
+ attachTo(selectorOrElement: string | Element, options?: MushiWidgetConfig): () => void;
273
+ setTrigger(trigger: NonNullable<MushiWidgetConfig['trigger']>): void;
231
274
  close(): void;
232
275
  destroy(): void;
276
+ updateConfig(config: MushiRuntimeSdkConfig): void;
233
277
  /**
234
278
  * Wave G4 — unified `captureEvent` API. Submits a bug report
235
279
  * programmatically without opening the widget. Useful for adapters
@@ -275,6 +319,7 @@ interface MushiApiClient {
275
319
  getReportStatus(reportId: string): Promise<MushiApiResponse<{
276
320
  status: MushiReportStatus;
277
321
  }>>;
322
+ getSdkConfig(): Promise<MushiApiResponse<MushiRuntimeSdkConfig>>;
278
323
  }
279
324
  interface MushiApiResponse<T> {
280
325
  ok: boolean;
@@ -284,6 +329,16 @@ interface MushiApiResponse<T> {
284
329
  message: string;
285
330
  };
286
331
  }
332
+ interface MushiRuntimeSdkConfig {
333
+ enabled?: boolean;
334
+ version?: string | null;
335
+ widget?: MushiWidgetConfig;
336
+ capture?: MushiCaptureConfig;
337
+ native?: {
338
+ triggerMode?: 'shake' | 'button' | 'both' | 'none';
339
+ minDescriptionLength?: number;
340
+ };
341
+ }
287
342
 
288
343
  interface ApiClientOptions {
289
344
  projectId: string;
@@ -488,4 +543,4 @@ declare function createLogger(options: LoggerOptions): Logger;
488
543
  */
489
544
  declare const noopLogger: Logger;
490
545
 
491
- export { type ApiClientOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, type MushiApiClient, type MushiApiResponse, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiIntegrationsConfig, type MushiNetworkEntry, type MushiOfflineConfig, type MushiOnDeviceClassifier, type MushiOnDeviceClassifierInput, type MushiOnDeviceClassifierResult, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiProactiveConfig, type MushiRegion, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiRewardsConfig, type MushiSDKInstance, type MushiSelectedElement, type MushiSentryConfig, type MushiWidgetConfig, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, noopLogger, resolveRegionEndpoint, scrubPii };
546
+ export { type ApiClientOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, type MushiApiClient, type MushiApiResponse, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiIntegrationsConfig, type MushiNetworkEntry, type MushiOfflineConfig, type MushiOnDeviceClassifier, type MushiOnDeviceClassifierInput, type MushiOnDeviceClassifierResult, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiProactiveConfig, type MushiRegion, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiRewardsConfig, type MushiRuntimeSdkConfig, type MushiSDKInstance, type MushiSelectedElement, type MushiSentryConfig, type MushiWidgetConfig, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, noopLogger, resolveRegionEndpoint, scrubPii };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,12 @@ interface MushiConfig {
2
2
  projectId: string;
3
3
  apiKey: string;
4
4
  apiEndpoint?: string;
5
+ /**
6
+ * Fetch non-secret widget/capture settings from the Mushi project at
7
+ * startup. Defaults to true so console changes apply without rebuilding
8
+ * host apps. Set false for fully static/offline deployments.
9
+ */
10
+ runtimeConfig?: boolean;
5
11
  sentry?: MushiSentryConfig;
6
12
  widget?: MushiWidgetConfig;
7
13
  capture?: MushiCaptureConfig;
@@ -27,6 +33,38 @@ interface MushiWidgetConfig {
27
33
  mode?: 'simple' | 'conversational';
28
34
  locale?: string;
29
35
  zIndex?: number;
36
+ /**
37
+ * Controls how, or whether, the default trigger is injected.
38
+ * `auto` preserves the historical floating stamp button.
39
+ */
40
+ trigger?: 'auto' | 'edge-tab' | 'attach' | 'manual' | 'hidden';
41
+ /** CSS selector used when `trigger` is `attach`. */
42
+ attachToSelector?: string;
43
+ /**
44
+ * Per-edge trigger offset in pixels. `auto` clears the corresponding edge.
45
+ * Defaults to the historical 24px gutter plus safe-area insets.
46
+ */
47
+ inset?: MushiWidgetInset;
48
+ respectSafeArea?: boolean;
49
+ /** Hide the launcher while any matching element exists in the document. */
50
+ hideOnSelector?: string;
51
+ /** Hide the launcher on matching pathnames. Strings are substring matches. */
52
+ hideOnRoutes?: string[];
53
+ environments?: Partial<Record<'production' | 'staging' | 'development', 'always' | 'never' | 'manual'>>;
54
+ /** Opt-in smart trigger behavior; planned to become the default in a later minor. */
55
+ smartHide?: boolean | MushiWidgetSmartHideConfig;
56
+ draggable?: boolean;
57
+ }
58
+ interface MushiWidgetInset {
59
+ top?: number | 'auto';
60
+ right?: number | 'auto';
61
+ bottom?: number | 'auto';
62
+ left?: number | 'auto';
63
+ }
64
+ interface MushiWidgetSmartHideConfig {
65
+ onMobile?: 'edge-tab' | 'hide' | false;
66
+ onScroll?: 'shrink' | 'hide' | false;
67
+ onIdleMs?: number;
30
68
  }
31
69
  interface MushiCaptureConfig {
32
70
  console?: boolean;
@@ -228,8 +266,14 @@ interface MushiSDKInstance {
228
266
  setMetadata(key: string, value: unknown): void;
229
267
  isOpen(): boolean;
230
268
  open(): void;
269
+ openWith(category: MushiReportCategory): void;
270
+ show(): void;
271
+ hide(): void;
272
+ attachTo(selectorOrElement: string | Element, options?: MushiWidgetConfig): () => void;
273
+ setTrigger(trigger: NonNullable<MushiWidgetConfig['trigger']>): void;
231
274
  close(): void;
232
275
  destroy(): void;
276
+ updateConfig(config: MushiRuntimeSdkConfig): void;
233
277
  /**
234
278
  * Wave G4 — unified `captureEvent` API. Submits a bug report
235
279
  * programmatically without opening the widget. Useful for adapters
@@ -275,6 +319,7 @@ interface MushiApiClient {
275
319
  getReportStatus(reportId: string): Promise<MushiApiResponse<{
276
320
  status: MushiReportStatus;
277
321
  }>>;
322
+ getSdkConfig(): Promise<MushiApiResponse<MushiRuntimeSdkConfig>>;
278
323
  }
279
324
  interface MushiApiResponse<T> {
280
325
  ok: boolean;
@@ -284,6 +329,16 @@ interface MushiApiResponse<T> {
284
329
  message: string;
285
330
  };
286
331
  }
332
+ interface MushiRuntimeSdkConfig {
333
+ enabled?: boolean;
334
+ version?: string | null;
335
+ widget?: MushiWidgetConfig;
336
+ capture?: MushiCaptureConfig;
337
+ native?: {
338
+ triggerMode?: 'shake' | 'button' | 'both' | 'none';
339
+ minDescriptionLength?: number;
340
+ };
341
+ }
287
342
 
288
343
  interface ApiClientOptions {
289
344
  projectId: string;
@@ -488,4 +543,4 @@ declare function createLogger(options: LoggerOptions): Logger;
488
543
  */
489
544
  declare const noopLogger: Logger;
490
545
 
491
- export { type ApiClientOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, type MushiApiClient, type MushiApiResponse, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiIntegrationsConfig, type MushiNetworkEntry, type MushiOfflineConfig, type MushiOnDeviceClassifier, type MushiOnDeviceClassifierInput, type MushiOnDeviceClassifierResult, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiProactiveConfig, type MushiRegion, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiRewardsConfig, type MushiSDKInstance, type MushiSelectedElement, type MushiSentryConfig, type MushiWidgetConfig, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, noopLogger, resolveRegionEndpoint, scrubPii };
546
+ export { type ApiClientOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, type MushiApiClient, type MushiApiResponse, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiIntegrationsConfig, type MushiNetworkEntry, type MushiOfflineConfig, type MushiOnDeviceClassifier, type MushiOnDeviceClassifierInput, type MushiOnDeviceClassifierResult, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiProactiveConfig, type MushiRegion, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiRewardsConfig, type MushiRuntimeSdkConfig, type MushiSDKInstance, type MushiSelectedElement, type MushiSentryConfig, type MushiWidgetConfig, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, noopLogger, resolveRegionEndpoint, scrubPii };
package/dist/index.js CHANGED
@@ -47,11 +47,12 @@ function createApiClient(options) {
47
47
  ok: false,
48
48
  error: {
49
49
  code: `HTTP_${response.status}`,
50
- message: errorBody.message || `HTTP ${response.status} error`
50
+ message: errorBody.error?.message || errorBody.message || `HTTP ${response.status} error`
51
51
  }
52
52
  };
53
53
  }
54
- const data = await response.json();
54
+ const payload = await response.json();
55
+ const data = payload && typeof payload === "object" && "ok" in payload && "data" in payload ? payload.data : payload;
55
56
  return { ok: true, data };
56
57
  } catch (error) {
57
58
  clearTimeout(timer);
@@ -74,6 +75,9 @@ function createApiClient(options) {
74
75
  },
75
76
  async getReportStatus(reportId) {
76
77
  return request("GET", `/v1/reports/${reportId}/status`);
78
+ },
79
+ async getSdkConfig() {
80
+ return request("GET", "/v1/sdk/config");
77
81
  }
78
82
  };
79
83
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api-client.ts","../src/region.ts","../src/pre-filter.ts","../src/logger.ts","../src/queue-crypto.ts","../src/queue.ts","../src/environment.ts","../src/reporter-token.ts","../src/fingerprint.ts","../src/session.ts","../src/rate-limiter.ts","../src/pii-scrubber.ts"],"names":["getBackoffDelay","sleep"],"mappings":"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","file":"index.js","sourcesContent":["import type { MushiApiClient, MushiApiResponse, MushiReport, MushiReportStatus } from './types';\n\nexport interface ApiClientOptions {\n projectId: string;\n apiKey: string;\n /**\n * Override the API endpoint. Defaults to the canonical Cloud URL\n * (DEFAULT_API_ENDPOINT). Self-hosted users MUST set this.\n */\n apiEndpoint?: string;\n timeout?: number;\n maxRetries?: number;\n}\n\n// V5.3 (M-cross-cutting): canonical Cloud URL — the older `api.mushimushi.dev`\n// hostname was never wired up. Self-hosted users MUST override `apiEndpoint`.\nexport const DEFAULT_API_ENDPOINT = 'https://dxptnwrhwsqckaftyymj.supabase.co/functions/v1/api';\nconst DEFAULT_TIMEOUT = 10_000;\nconst DEFAULT_MAX_RETRIES = 2;\n\nexport function createApiClient(options: ApiClientOptions): MushiApiClient {\n const {\n projectId,\n apiKey,\n apiEndpoint = DEFAULT_API_ENDPOINT,\n timeout = DEFAULT_TIMEOUT,\n maxRetries = DEFAULT_MAX_RETRIES,\n } = options;\n\n let baseUrl = apiEndpoint.replace(/\\/$/, '');\n\n async function request<T>(\n method: string,\n path: string,\n body?: unknown,\n retries = maxRetries,\n ): Promise<MushiApiResponse<T>> {\n const url = `${baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'X-Mushi-Api-Key': apiKey,\n 'X-Mushi-Project': projectId,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timer);\n\n // C7: data residency — follow a one-shot redirect when the\n // gateway tells us the project lives in a different region. Cache the\n // new base URL so subsequent calls go straight to the right cluster.\n if (response.status === 307 || response.status === 308) {\n const target = response.headers.get('Location');\n if (target && retries > 0) {\n const targetBase = target.replace(/\\/v1\\/.*$/, '').replace(/\\/$/, '');\n if (targetBase !== baseUrl) {\n baseUrl = targetBase;\n return request<T>(method, path, body, retries - 1);\n }\n }\n }\n\n if (!response.ok) {\n const errorBody = await response.json().catch(() => ({}));\n if (response.status >= 500 && retries > 0) {\n await sleep(getBackoffDelay(maxRetries - retries));\n return request<T>(method, path, body, retries - 1);\n }\n return {\n ok: false,\n error: {\n code: `HTTP_${response.status}`,\n message:\n (errorBody as { message?: string }).message || `HTTP ${response.status} error`,\n },\n };\n }\n\n const data = (await response.json()) as T;\n return { ok: true, data };\n } catch (error) {\n clearTimeout(timer);\n\n if (retries > 0 && isRetryable(error)) {\n await sleep(getBackoffDelay(maxRetries - retries));\n return request<T>(method, path, body, retries - 1);\n }\n\n return {\n ok: false,\n error: {\n code: 'NETWORK_ERROR',\n message: error instanceof Error ? error.message : 'Unknown network error',\n },\n };\n }\n }\n\n return {\n async submitReport(report: MushiReport) {\n return request<{ reportId: string }>('POST', '/v1/reports', report);\n },\n\n async getReportStatus(reportId: string) {\n return request<{ status: MushiReportStatus }>('GET', `/v1/reports/${reportId}/status`);\n },\n };\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction getBackoffDelay(attempt: number): number {\n return Math.min(1000 * 2 ** attempt + Math.random() * 500, 10_000);\n}\n\nfunction isRetryable(error: unknown): boolean {\n if (error instanceof DOMException && error.name === 'AbortError') return true;\n if (error instanceof TypeError) return true; // network failures\n return false;\n}\n","/**\n * C7: Data residency region resolution.\n *\n * The SDK supports four regional clouds:\n * - 'us' → United States (default; legacy `dxptnwrhwsqckaftyymj`)\n * - 'eu' → European Union (Frankfurt)\n * - 'jp' → Japan (Tokyo)\n * - 'self' → self-hosted / BYO Supabase\n *\n * Customers choose a region at project creation time, and the gateway will\n * 307-redirect any cross-region calls to the correct host. The SDK caches\n * the resolved hostname in `localStorage` (browser) so that subsequent\n * sessions skip the redirect.\n */\n\nexport type MushiRegion = 'us' | 'eu' | 'jp' | 'self';\n\nexport const REGION_ENDPOINTS: Record<Exclude<MushiRegion, 'self'>, string> = {\n us: 'https://api.us.mushimushi.dev/functions/v1/api',\n eu: 'https://api.eu.mushimushi.dev/functions/v1/api',\n jp: 'https://api.jp.mushimushi.dev/functions/v1/api',\n};\n\nconst ROUTING_CACHE_KEY = 'mushi_region_v1';\nconst ROUTING_CACHE_TTL_MS = 24 * 60 * 60 * 1000;\n\ninterface RegionCacheEntry {\n region: MushiRegion;\n endpoint: string;\n ts: number;\n}\n\n/**\n * Resolve the regional endpoint for a project. Looks up the public\n * `region_routing` table on the legacy US gateway (the catalog of record),\n * then caches the result.\n *\n * Falls back to the explicit `apiEndpoint` if anything goes wrong — failure\n * here must never block report submission.\n */\nexport async function resolveRegionEndpoint(opts: {\n projectId: string;\n apiEndpoint: string;\n region?: MushiRegion;\n storage?: Storage;\n fetcher?: typeof fetch;\n}): Promise<string> {\n const explicit = opts.region;\n if (explicit && explicit !== 'self' && REGION_ENDPOINTS[explicit]) {\n return REGION_ENDPOINTS[explicit];\n }\n\n const storage = opts.storage ?? safeLocalStorage();\n const cached = readCache(storage, opts.projectId);\n if (cached) return cached;\n\n try {\n const fetcher = opts.fetcher ?? fetch;\n const url = `${opts.apiEndpoint.replace(/\\/$/, '')}/v1/region/resolve?project_id=${encodeURIComponent(opts.projectId)}`;\n const res = await fetcher(url, { method: 'GET' });\n if (!res.ok) return opts.apiEndpoint;\n const body = (await res.json()) as { region?: MushiRegion; endpoint?: string };\n if (!body.region || !body.endpoint) return opts.apiEndpoint;\n writeCache(storage, opts.projectId, { region: body.region, endpoint: body.endpoint, ts: Date.now() });\n return body.endpoint;\n } catch {\n return opts.apiEndpoint;\n }\n}\n\nfunction safeLocalStorage(): Storage | undefined {\n try {\n return typeof globalThis !== 'undefined' && 'localStorage' in globalThis\n ? (globalThis as { localStorage: Storage }).localStorage\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction readCache(storage: Storage | undefined, projectId: string): string | null {\n if (!storage) return null;\n try {\n const raw = storage.getItem(`${ROUTING_CACHE_KEY}:${projectId}`);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as RegionCacheEntry;\n if (Date.now() - parsed.ts > ROUTING_CACHE_TTL_MS) return null;\n return parsed.endpoint;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(storage: Storage | undefined, projectId: string, entry: RegionCacheEntry): void {\n if (!storage) return;\n try {\n storage.setItem(`${ROUTING_CACHE_KEY}:${projectId}`, JSON.stringify(entry));\n } catch {\n /* no-op: quota exceeded etc. */\n }\n}\n","import type { MushiPreFilterConfig } from './types';\n\nexport interface PreFilterResult {\n passed: boolean;\n reason?: string;\n}\n\nconst DEFAULT_MIN_LENGTH = 10;\nconst DEFAULT_MAX_LENGTH = 2000;\n\nconst SPAM_PATTERNS: RegExp[] = [\n /^(.)\\1{10,}$/, // repeated single character\n /^[A-Z\\s!?]{20,}$/, // all caps shouting\n /^[\\d\\s]+$/, // numbers only\n /^[^a-zA-Z\\u00C0-\\u024F\\u4E00-\\u9FFF\\u3040-\\u309F\\u30A0-\\u30FF]{10,}$/, // no real letters\n /\\b(test|asdf|qwerty|lorem ipsum)\\b/i, // common test strings\n];\n\nconst GIBBERISH_PATTERN = /^[bcdfghjklmnpqrstvwxz]{6,}/i; // consonant-only strings\n\nexport function createPreFilter(config: MushiPreFilterConfig = {}) {\n const {\n enabled = true,\n blockObviousSpam = true,\n minDescriptionLength = DEFAULT_MIN_LENGTH,\n maxDescriptionLength = DEFAULT_MAX_LENGTH,\n } = config;\n\n function check(description: string): PreFilterResult {\n if (!enabled) {\n return { passed: true };\n }\n\n const trimmed = description.trim();\n\n if (trimmed.length < minDescriptionLength) {\n return { passed: false, reason: `Too short (min ${minDescriptionLength} characters)` };\n }\n\n if (trimmed.length > maxDescriptionLength) {\n return { passed: false, reason: `Too long (max ${maxDescriptionLength} characters)` };\n }\n\n if (blockObviousSpam) {\n for (const pattern of SPAM_PATTERNS) {\n if (pattern.test(trimmed)) {\n return { passed: false, reason: 'Detected as spam' };\n }\n }\n\n if (GIBBERISH_PATTERN.test(trimmed)) {\n return { passed: false, reason: 'Detected as gibberish' };\n }\n\n const words = trimmed.split(/\\s+/).filter((w) => w.length > 1);\n if (words.length < 2) {\n return { passed: false, reason: 'Description needs at least 2 words' };\n }\n }\n\n return { passed: true };\n }\n\n function truncate(description: string): string {\n const trimmed = description.trim();\n if (trimmed.length <= maxDescriptionLength) return trimmed;\n return trimmed.slice(0, maxDescriptionLength) + '...';\n }\n\n return { check, truncate };\n}\n","/**\n * FILE: logger.ts\n * PURPOSE: Zero-dependency structured logger for the mushi-mushi SDK ecosystem.\n *\n * OVERVIEW:\n * - Production-grade logging with levels, scoped namespaces, and child loggers\n * - JSON output for server/production, pretty-formatted output for development\n * - Automatic environment detection (browser vs Node vs Deno)\n * - Structured metadata on every log entry\n * - No external dependencies — safe to ship in any SDK bundle\n *\n * USAGE:\n * import { createLogger } from '@mushi-mushi/core'\n * const log = createLogger({ scope: 'mushi:api' })\n * log.info('Request received', { method: 'POST', path: '/v1/reports' })\n * const child = log.child('ingest', { reportId: 'abc' })\n * child.warn('Slow query', { latencyMs: 420 })\n *\n * TECHNICAL DETAILS:\n * - Log levels: debug(10) < info(20) < warn(30) < error(40) < fatal(50) < silent(99)\n * - Format auto-detected: JSON in production/server, pretty in development\n * - Pretty format uses ANSI colors when supported (Node/Deno TTY)\n * - Child loggers inherit parent scope + metadata, can override level\n * - Timestamps are ISO 8601 with millisecond precision\n */\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'silent'\n\nexport type LogFormat = 'json' | 'pretty' | 'auto'\n\nexport interface LoggerOptions {\n scope: string\n level?: LogLevel\n meta?: Record<string, unknown>\n format?: LogFormat\n}\n\nexport interface Logger {\n debug(msg: string, meta?: Record<string, unknown>): void\n info(msg: string, meta?: Record<string, unknown>): void\n warn(msg: string, meta?: Record<string, unknown>): void\n error(msg: string, meta?: Record<string, unknown>): void\n fatal(msg: string, meta?: Record<string, unknown>): void\n child(scope: string, meta?: Record<string, unknown>): Logger\n setLevel(level: LogLevel): void\n}\n\nexport interface LogEntry {\n ts: string\n level: LogLevel\n scope: string\n msg: string\n [key: string]: unknown\n}\n\nconst LEVEL_VALUE: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n fatal: 50,\n silent: 99,\n}\n\nconst LEVEL_LABEL: Record<string, string> = {\n debug: 'DBG',\n info: 'INF',\n warn: 'WRN',\n error: 'ERR',\n fatal: 'FTL',\n}\n\nconst ANSI = {\n reset: '\\x1b[0m',\n dim: '\\x1b[2m',\n bold: '\\x1b[1m',\n cyan: '\\x1b[36m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n red: '\\x1b[31m',\n magenta: '\\x1b[35m',\n white: '\\x1b[37m',\n bgRed: '\\x1b[41m',\n} as const\n\nconst LEVEL_COLOR: Record<string, string> = {\n debug: ANSI.dim,\n info: ANSI.green,\n warn: ANSI.yellow,\n error: ANSI.red,\n fatal: `${ANSI.bgRed}${ANSI.white}${ANSI.bold}`,\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nfunction detectFormat(): 'json' | 'pretty' {\n try {\n if (typeof (globalThis as any).Deno !== 'undefined') return 'json'\n } catch { /* not Deno */ }\n\n const proc = typeof (globalThis as any).process !== 'undefined'\n ? (globalThis as any).process\n : undefined\n\n if (proc?.env) {\n if (proc.env.NODE_ENV === 'production') return 'json'\n if (proc.env.LOG_FORMAT === 'json') return 'json'\n if (proc.env.LOG_FORMAT === 'pretty') return 'pretty'\n if (proc.stdout?.isTTY) return 'pretty'\n }\n\n if (typeof (globalThis as any).window !== 'undefined') return 'pretty'\n\n return 'json'\n}\n/* eslint-enable @typescript-eslint/no-explicit-any */\n\nfunction flattenMeta(meta: Record<string, unknown>): string {\n const parts: string[] = []\n for (const [k, v] of Object.entries(meta)) {\n if (v === undefined || v === null) continue\n if (typeof v === 'object') {\n parts.push(`${k}=${JSON.stringify(v)}`)\n } else {\n parts.push(`${k}=${String(v)}`)\n }\n }\n return parts.join(' ')\n}\n\nfunction formatPretty(entry: LogEntry): string {\n const { ts, level, scope, msg, ...rest } = entry\n const time = ts.slice(11, 23)\n const color = LEVEL_COLOR[level] ?? ''\n const label = LEVEL_LABEL[level] ?? level.toUpperCase()\n const metaStr = Object.keys(rest).length > 0 ? ` ${ANSI.dim}${flattenMeta(rest)}${ANSI.reset}` : ''\n\n return `${ANSI.dim}${time}${ANSI.reset} ${color}${label}${ANSI.reset} ${ANSI.cyan}[${scope}]${ANSI.reset} ${msg}${metaStr}`\n}\n\nfunction formatJson(entry: LogEntry): string {\n return JSON.stringify(entry)\n}\n\nfunction emit(level: LogLevel, formatted: string): void {\n switch (level) {\n case 'error':\n case 'fatal':\n console.error(formatted)\n break\n case 'warn':\n console.warn(formatted)\n break\n default:\n console.log(formatted)\n }\n}\n\nfunction buildLogger(\n scope: string,\n minLevel: LogLevel,\n baseMeta: Record<string, unknown>,\n formatter: (entry: LogEntry) => string,\n): Logger {\n let currentLevel = minLevel\n\n function log(level: LogLevel, msg: string, meta?: Record<string, unknown>): void {\n if (LEVEL_VALUE[level] < LEVEL_VALUE[currentLevel]) return\n\n const entry: LogEntry = {\n ts: new Date().toISOString(),\n level,\n scope,\n msg,\n ...baseMeta,\n ...meta,\n }\n\n emit(level, formatter(entry))\n }\n\n return {\n debug: (msg, meta?) => log('debug', msg, meta),\n info: (msg, meta?) => log('info', msg, meta),\n warn: (msg, meta?) => log('warn', msg, meta),\n error: (msg, meta?) => log('error', msg, meta),\n fatal: (msg, meta?) => log('fatal', msg, meta),\n\n child(childScope: string, childMeta?: Record<string, unknown>): Logger {\n return buildLogger(\n `${scope}:${childScope}`,\n currentLevel,\n { ...baseMeta, ...childMeta },\n formatter,\n )\n },\n\n setLevel(level: LogLevel) {\n currentLevel = level\n },\n }\n}\n\n/**\n * Create a structured logger instance.\n *\n * @example\n * const log = createLogger({ scope: 'mushi:api', level: 'info' })\n * log.info('Server started', { port: 3000 })\n *\n * const child = log.child('auth', { userId: 'u-123' })\n * child.warn('Token expired')\n */\nexport function createLogger(options: LoggerOptions): Logger {\n const {\n scope,\n level = 'info',\n meta = {},\n format = 'auto',\n } = options\n\n const resolvedFormat = format === 'auto' ? detectFormat() : format\n const formatter = resolvedFormat === 'json' ? formatJson : formatPretty\n\n return buildLogger(scope, level, meta, formatter)\n}\n\n/**\n * Noop logger that discards all output.\n * Useful when logging should be completely disabled.\n */\nexport const noopLogger: Logger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n fatal: () => {},\n child: () => noopLogger,\n setLevel: () => {},\n}\n","/**\n * AES-GCM at-rest encryption for the offline queue (Wave S1 / D-16).\n *\n * Why this exists: on shared devices (kiosks, support-agent laptops) a\n * queued bug report sits in plaintext IndexedDB until the next flush.\n * Browser extensions, other tabs on the same origin, and forensic tools\n * with disk access can all read it. For a QA/bug-reporting SDK that\n * encourages users to paste sensitive data into descriptions, that's\n * unacceptable.\n *\n * Design:\n * - Generate a non-extractable AES-GCM key on first call (256-bit).\n * - Persist the `CryptoKey` object itself (Web Crypto allows IDB round-\n * trip of `CryptoKey` without ever serialising the raw bytes).\n * - Use a 12-byte random IV per payload; prepend it to ciphertext so\n * decrypt() needs no out-of-band state.\n * - Never block the caller — all errors bubble up so the queue can fall\n * back to plaintext storage with a debug log (see queue.ts).\n *\n * The key is tied to the browser origin (same-origin IDB). It does NOT\n * protect against an attacker with admin shell on the device: the browser\n * WILL decrypt on demand for anyone with origin access. That's the same\n * guarantee every origin-bound browser secret has and is the correct\n * threat model for offline bug reports.\n */\n\nconst KEY_DB = 'mushi-mushi-keyring';\nconst KEY_STORE = 'keys';\nconst KEY_RECORD_ID = 'offline-queue/v1';\n\nlet cachedKey: CryptoKey | null = null;\nlet cachedKeyPromise: Promise<CryptoKey> | null = null;\n\nfunction hasWebCrypto(): boolean {\n return (\n typeof globalThis !== 'undefined' &&\n typeof (globalThis as unknown as { crypto?: Crypto }).crypto !== 'undefined' &&\n typeof (globalThis as unknown as { crypto: Crypto }).crypto.subtle !== 'undefined' &&\n typeof indexedDB !== 'undefined'\n );\n}\n\nfunction openKeyDb(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.open(KEY_DB, 1);\n req.onupgradeneeded = () => {\n const db = req.result;\n if (!db.objectStoreNames.contains(KEY_STORE)) {\n db.createObjectStore(KEY_STORE);\n }\n };\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n });\n}\n\nasync function loadKey(): Promise<CryptoKey | null> {\n const db = await openKeyDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(KEY_STORE, 'readonly');\n const req = tx.objectStore(KEY_STORE).get(KEY_RECORD_ID);\n req.onsuccess = () => resolve((req.result as CryptoKey) ?? null);\n req.onerror = () => reject(req.error);\n });\n}\n\nasync function storeKey(key: CryptoKey): Promise<void> {\n const db = await openKeyDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(KEY_STORE, 'readwrite');\n tx.objectStore(KEY_STORE).put(key, KEY_RECORD_ID);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\n/**\n * Lazily get (or generate once + persist) the AES-GCM key for this origin.\n * `extractable: false` — so a script-level attacker can't `exportKey()` and\n * ship the raw bytes to their server, only use it via `encrypt`/`decrypt`.\n */\nexport async function getOfflineQueueKey(): Promise<CryptoKey> {\n if (cachedKey) return cachedKey;\n if (cachedKeyPromise) return cachedKeyPromise;\n if (!hasWebCrypto()) {\n throw new Error('Web Crypto + IndexedDB required for offline queue encryption');\n }\n cachedKeyPromise = (async () => {\n const existing = await loadKey();\n if (existing) {\n cachedKey = existing;\n return existing;\n }\n const key = await crypto.subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt'],\n );\n await storeKey(key);\n cachedKey = key;\n return key;\n })();\n return cachedKeyPromise;\n}\n\nexport interface EncryptedPayload {\n /** Magic marker so decrypt() can tell encrypted vs legacy plaintext rows. */\n readonly _mme: 1;\n readonly iv: string;\n readonly ct: string;\n}\n\nfunction bytesToB64(bytes: Uint8Array): string {\n let s = '';\n for (const b of bytes) s += String.fromCharCode(b);\n return btoa(s);\n}\n\nfunction b64ToBytes(s: string): Uint8Array<ArrayBuffer> {\n const bin = atob(s);\n const out = new Uint8Array(new ArrayBuffer(bin.length));\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nexport async function encryptJson(plain: unknown): Promise<EncryptedPayload> {\n const key = await getOfflineQueueKey();\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const data = new TextEncoder().encode(JSON.stringify(plain));\n const cipher = new Uint8Array(await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, data));\n return { _mme: 1, iv: bytesToB64(iv), ct: bytesToB64(cipher) };\n}\n\nexport function isEncryptedPayload(v: unknown): v is EncryptedPayload {\n return (\n !!v &&\n typeof v === 'object' &&\n (v as EncryptedPayload)._mme === 1 &&\n typeof (v as EncryptedPayload).iv === 'string' &&\n typeof (v as EncryptedPayload).ct === 'string'\n );\n}\n\nexport async function decryptJson<T = unknown>(payload: EncryptedPayload): Promise<T> {\n const key = await getOfflineQueueKey();\n const iv = b64ToBytes(payload.iv);\n const ct = b64ToBytes(payload.ct);\n const plain = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, key, ct);\n return JSON.parse(new TextDecoder().decode(plain)) as T;\n}\n","import type { MushiApiClient, MushiOfflineConfig, MushiReport } from './types';\nimport { createLogger } from './logger';\nimport {\n encryptJson,\n decryptJson,\n isEncryptedPayload,\n type EncryptedPayload,\n} from './queue-crypto';\n\nconst queueLog = createLogger({ scope: 'mushi:queue', level: 'warn' });\n\n// Wave S1 / D-16: opaque at-rest wrapper. Each queue row is either:\n// - a legacy plaintext `MushiReport` (pre-encryption; still readable)\n// - an `EncryptedRecord` with a bare `id` (so count / delete can operate\n// without decrypting every row) plus the encrypted payload blob.\ninterface EncryptedRecord {\n id: string;\n queuedAt: string;\n payload: EncryptedPayload;\n}\n\ntype StoredRow = MushiReport | EncryptedRecord;\n\nconst DB_NAME = 'mushi-mushi';\nconst STORE_NAME = 'offline-reports';\nconst DB_VERSION = 1;\nconst LS_KEY = 'mushi_offline_queue';\nconst BATCH_SIZE = 10;\nconst MAX_BACKOFF_MS = 60_000;\n\nexport interface OfflineQueue {\n enqueue(report: MushiReport): Promise<void>;\n flush(client: MushiApiClient): Promise<{ sent: number; failed: number }>;\n size(): Promise<number>;\n clear(): Promise<void>;\n startAutoSync(client: MushiApiClient): void;\n stopAutoSync(): void;\n}\n\ntype StorageBackend = 'indexeddb' | 'localstorage' | 'none';\n\nexport function createOfflineQueue(config: MushiOfflineConfig = {}): OfflineQueue {\n const { enabled = true, maxQueueSize = 50, syncOnReconnect = true, encryptAtRest = true } = config;\n\n let syncCleanup: (() => void) | null = null;\n let backendType: StorageBackend | null = null;\n\n async function wrapForStorage(report: MushiReport): Promise<StoredRow> {\n const queuedAt = new Date().toISOString();\n if (!encryptAtRest) {\n return { ...report, queuedAt } as MushiReport;\n }\n try {\n const payload = await encryptJson(report);\n return { id: report.id, queuedAt, payload } satisfies EncryptedRecord;\n } catch (err) {\n // Encryption failure is non-fatal — queue integrity matters more than\n // at-rest confidentiality. We fall back to plaintext and warn.\n queueLog.warn('Offline queue: encryption failed, storing plaintext', { err: String(err) });\n return { ...report, queuedAt } as MushiReport;\n }\n }\n\n async function unwrapForSend(row: StoredRow): Promise<MushiReport | null> {\n if (isEncryptedRecord(row)) {\n try {\n return await decryptJson<MushiReport>(row.payload);\n } catch (err) {\n queueLog.warn('Offline queue: decrypt failed, dropping row', { err: String(err), id: row.id });\n return null;\n }\n }\n return row;\n }\n\n function isEncryptedRecord(row: StoredRow): row is EncryptedRecord {\n return !!(row as EncryptedRecord).payload && isEncryptedPayload((row as EncryptedRecord).payload);\n }\n\n function detectBackend(): StorageBackend {\n if (backendType) return backendType;\n if (typeof indexedDB !== 'undefined') {\n backendType = 'indexeddb';\n } else if (typeof localStorage !== 'undefined') {\n backendType = 'localstorage';\n } else {\n backendType = 'none';\n }\n return backendType;\n }\n\n // --- IndexedDB backend ---\n\n function openDb(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME, { keyPath: 'id' });\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => {\n backendType = 'localstorage';\n reject(request.error);\n };\n });\n }\n\n async function idbEnqueue(report: MushiReport): Promise<void> {\n const db = await openDb();\n const row = await wrapForStorage(report);\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite');\n tx.objectStore(STORE_NAME).put(row);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n async function idbGetAll(): Promise<StoredRow[]> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readonly');\n const request = tx.objectStore(STORE_NAME).getAll();\n request.onsuccess = () => resolve(request.result as StoredRow[]);\n request.onerror = () => reject(request.error);\n });\n }\n\n async function idbDelete(id: string): Promise<void> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite');\n tx.objectStore(STORE_NAME).delete(id);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n async function idbSize(): Promise<number> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readonly');\n const request = tx.objectStore(STORE_NAME).count();\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n }\n\n async function idbClear(): Promise<void> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite');\n tx.objectStore(STORE_NAME).clear();\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n // --- localStorage fallback ---\n\n function lsRead(): StoredRow[] {\n try {\n const raw = localStorage.getItem(LS_KEY);\n return raw ? (JSON.parse(raw) as StoredRow[]) : [];\n } catch {\n return [];\n }\n }\n\n function lsWrite(rows: StoredRow[]): void {\n try {\n localStorage.setItem(LS_KEY, JSON.stringify(rows));\n } catch {\n // localStorage full or unavailable\n }\n }\n\n async function lsEnqueue(report: MushiReport): Promise<void> {\n const rows = lsRead();\n rows.push(await wrapForStorage(report));\n lsWrite(rows);\n }\n\n function lsDelete(id: string): void {\n const rows = lsRead().filter((r) => r.id !== id);\n lsWrite(rows);\n }\n\n // --- Unified interface ---\n\n async function enqueue(report: MushiReport): Promise<void> {\n if (!enabled) return;\n\n const currentSize = await size();\n if (currentSize >= maxQueueSize) {\n queueLog.warn('Offline queue full — dropping report', { maxQueueSize });\n return;\n }\n\n const backend = detectBackend();\n if (backend === 'indexeddb') {\n try {\n await idbEnqueue(report);\n return;\n } catch {\n // IndexedDB failed, fall through to localStorage\n backendType = 'localstorage';\n }\n }\n\n if (backend === 'localstorage' || backendType === 'localstorage') {\n await lsEnqueue(report);\n return;\n }\n }\n\n function getBackoffDelay(attempt: number): number {\n return Math.min(1000 * 2 ** attempt + Math.random() * 500, MAX_BACKOFF_MS);\n }\n\n function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n async function flush(client: MushiApiClient): Promise<{ sent: number; failed: number }> {\n if (!enabled) return { sent: 0, failed: 0 };\n\n let rows: StoredRow[];\n const backend = detectBackend();\n\n if (backend === 'indexeddb') {\n try {\n rows = await idbGetAll();\n } catch {\n rows = lsRead();\n }\n } else {\n rows = lsRead();\n }\n\n const batch = rows.slice(0, BATCH_SIZE);\n let sent = 0;\n let failed = 0;\n\n for (let i = 0; i < batch.length; i++) {\n const row = batch[i];\n const rowId = (row as { id: string }).id;\n const report = await unwrapForSend(row);\n\n if (!report) {\n // Undecryptable row — drop so it doesn't re-poison the queue forever.\n try {\n if (backend === 'indexeddb') await idbDelete(rowId);\n else lsDelete(rowId);\n } catch {\n lsDelete(rowId);\n }\n failed++;\n continue;\n }\n\n const result = await client.submitReport(report);\n\n if (result.ok) {\n try {\n if (backend === 'indexeddb') await idbDelete(rowId);\n else lsDelete(rowId);\n } catch {\n lsDelete(rowId);\n }\n sent++;\n } else {\n failed++;\n if (i < batch.length - 1) {\n await sleep(getBackoffDelay(i));\n }\n }\n }\n\n return { sent, failed };\n }\n\n async function size(): Promise<number> {\n const backend = detectBackend();\n if (backend === 'indexeddb') {\n try {\n return await idbSize();\n } catch {\n return lsRead().length;\n }\n }\n return lsRead().length;\n }\n\n async function clear(): Promise<void> {\n const backend = detectBackend();\n if (backend === 'indexeddb') {\n try {\n await idbClear();\n } catch {\n // fall through\n }\n }\n try {\n localStorage.removeItem(LS_KEY);\n } catch {\n // unavailable\n }\n }\n\n function startAutoSync(client: MushiApiClient): void {\n if (!enabled || !syncOnReconnect || typeof window === 'undefined') return;\n\n const handler = () => {\n if (navigator.onLine) {\n flush(client).catch(() => {});\n }\n };\n\n window.addEventListener('online', handler);\n syncCleanup = () => window.removeEventListener('online', handler);\n }\n\n function stopAutoSync(): void {\n syncCleanup?.();\n syncCleanup = null;\n }\n\n return { enqueue, flush, size, clear, startAutoSync, stopAutoSync };\n}\n","import type { MushiEnvironment } from './types';\n\nexport function captureEnvironment(): MushiEnvironment {\n const nav = typeof navigator !== 'undefined' ? navigator : undefined;\n const win = typeof window !== 'undefined' ? window : undefined;\n const doc = typeof document !== 'undefined' ? document : undefined;\n\n const connection = nav && 'connection' in nav ? (nav as NavigatorWithConnection).connection : undefined;\n\n return {\n userAgent: nav?.userAgent ?? 'unknown',\n platform: nav?.platform ?? 'unknown',\n language: nav?.language ?? 'en',\n viewport: {\n width: win?.innerWidth ?? 0,\n height: win?.innerHeight ?? 0,\n },\n url: win?.location?.href ?? '',\n referrer: doc?.referrer ?? '',\n timestamp: new Date().toISOString(),\n timezone: Intl?.DateTimeFormat?.()?.resolvedOptions?.()?.timeZone ?? 'UTC',\n connection: connection\n ? {\n effectiveType: connection.effectiveType,\n downlink: connection.downlink,\n rtt: connection.rtt,\n }\n : undefined,\n deviceMemory: (nav as NavigatorWithDeviceMemory)?.deviceMemory,\n hardwareConcurrency: nav?.hardwareConcurrency,\n };\n}\n\ninterface NetworkInformation {\n effectiveType?: string;\n downlink?: number;\n rtt?: number;\n}\n\ninterface NavigatorWithConnection extends Navigator {\n connection?: NetworkInformation;\n}\n\ninterface NavigatorWithDeviceMemory extends Navigator {\n deviceMemory?: number;\n}\n","const STORAGE_KEY = 'mushi_reporter_token';\n\nexport function getReporterToken(): string {\n if (typeof localStorage !== 'undefined') {\n const existing = localStorage.getItem(STORAGE_KEY);\n if (existing) return existing;\n }\n\n const token = generateToken();\n\n if (typeof localStorage !== 'undefined') {\n try {\n localStorage.setItem(STORAGE_KEY, token);\n } catch {\n // localStorage full or unavailable — token is ephemeral\n }\n }\n\n return token;\n}\n\nfunction generateToken(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return `mushi_${crypto.randomUUID()}`;\n }\n\n const bytes = new Uint8Array(16);\n if (typeof crypto !== 'undefined') {\n crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n\n const hex = Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n return `mushi_${hex}`;\n}\n","/**\n * §3c — stable device fingerprint hash.\n *\n * Hashes a deliberately small set of long-lived device characteristics so\n * the same browser keeps the same hash across sessions, but moving to a\n * new browser/device produces a different one. This lets the server\n * detect cross-account abuse (same hash → many reporter accounts) without\n * needing fingerprint.js or any other entropy-heavy library.\n *\n * Privacy notes:\n * - We never send the raw inputs, only the SHA-256 hex digest.\n * - The set is intentionally low-entropy on purpose; this is \"is this the\n * same device\" not \"who is this user\". For high-stakes anti-fraud you\n * should still combine with server-side IP/geo signals.\n * - Cached in localStorage so subsequent calls are zero-cost.\n */\n\nconst CACHE_KEY = 'mushi_fingerprint_hash';\n\ninterface FingerprintInputs {\n userAgent: string;\n platform: string;\n language: string;\n timezone: string;\n screenWidth: number;\n screenHeight: number;\n pixelRatio: number;\n deviceMemory: number | undefined;\n hardwareConcurrency: number | undefined;\n}\n\nfunction collectInputs(): FingerprintInputs {\n const nav = typeof navigator !== 'undefined' ? navigator : undefined;\n const scr = typeof screen !== 'undefined' ? screen : undefined;\n const win = typeof window !== 'undefined' ? window : undefined;\n return {\n userAgent: nav?.userAgent ?? 'unknown',\n platform: nav?.platform ?? 'unknown',\n language: nav?.language ?? 'en',\n timezone: Intl?.DateTimeFormat?.()?.resolvedOptions?.()?.timeZone ?? 'UTC',\n screenWidth: scr?.width ?? 0,\n screenHeight: scr?.height ?? 0,\n pixelRatio: win?.devicePixelRatio ?? 1,\n deviceMemory: (nav as NavigatorWithDeviceMemory | undefined)?.deviceMemory,\n hardwareConcurrency: nav?.hardwareConcurrency,\n };\n}\n\ninterface NavigatorWithDeviceMemory extends Navigator {\n deviceMemory?: number;\n}\n\nasync function sha256Hex(input: string): Promise<string> {\n if (typeof crypto !== 'undefined' && crypto.subtle) {\n const buf = new TextEncoder().encode(input);\n const digest = await crypto.subtle.digest('SHA-256', buf);\n return Array.from(new Uint8Array(digest))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n }\n // Fallback (Node 18+ test envs, very old browsers): non-cryptographic but\n // good enough for the \"are these two requests from the same device\" use\n // case the server makes of this value.\n let hash = 0;\n for (let i = 0; i < input.length; i++) {\n hash = (hash << 5) - hash + input.charCodeAt(i);\n hash |= 0;\n }\n return `fbk_${(hash >>> 0).toString(16).padStart(8, '0')}`;\n}\n\n/**\n * Returns a stable per-device hash. Cached in localStorage; first call is\n * one SHA-256, subsequent calls are a localStorage read.\n *\n * Returns `null` outside browser-like environments (SSR, web workers\n * without crypto.subtle) so callers can omit the field gracefully.\n */\nexport async function getDeviceFingerprintHash(): Promise<string | null> {\n if (typeof localStorage !== 'undefined') {\n const cached = localStorage.getItem(CACHE_KEY);\n if (cached) return cached;\n }\n\n const inputs = collectInputs();\n const serialised = JSON.stringify(inputs);\n const hash = await sha256Hex(serialised);\n\n if (typeof localStorage !== 'undefined') {\n try {\n localStorage.setItem(CACHE_KEY, hash);\n } catch {\n // localStorage quota / private mode — caller still gets the hash.\n }\n }\n return hash;\n}\n\n/** Test/diagnostic helper — never include in shipped reports. */\nexport function _resetFingerprintCacheForTests(): void {\n if (typeof localStorage !== 'undefined') {\n try {\n localStorage.removeItem(CACHE_KEY);\n } catch {\n // ignore\n }\n }\n}\n","const SESSION_KEY = 'mushi_session_id';\n\nlet cachedSessionId: string | null = null;\n\nexport function getSessionId(): string {\n if (cachedSessionId) return cachedSessionId;\n\n if (typeof sessionStorage !== 'undefined') {\n const existing = sessionStorage.getItem(SESSION_KEY);\n if (existing) {\n cachedSessionId = existing;\n return existing;\n }\n }\n\n const id = generateSessionId();\n cachedSessionId = id;\n\n if (typeof sessionStorage !== 'undefined') {\n try {\n sessionStorage.setItem(SESSION_KEY, id);\n } catch {\n // sessionStorage unavailable\n }\n }\n\n return id;\n}\n\nfunction generateSessionId(): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).slice(2, 8);\n return `ms_${timestamp}_${random}`;\n}\n","export interface RateLimiterConfig {\n maxBurst?: number;\n refillRate?: number;\n refillIntervalMs?: number;\n}\n\nexport interface RateLimiter {\n tryConsume(): boolean;\n reset(): void;\n availableTokens(): number;\n}\n\nconst DEFAULT_MAX_BURST = 10;\nconst DEFAULT_REFILL_RATE = 1;\nconst DEFAULT_REFILL_INTERVAL_MS = 5_000;\n\nexport function createRateLimiter(config: RateLimiterConfig = {}): RateLimiter {\n const {\n maxBurst = DEFAULT_MAX_BURST,\n refillRate = DEFAULT_REFILL_RATE,\n refillIntervalMs = DEFAULT_REFILL_INTERVAL_MS,\n } = config;\n\n let tokens = maxBurst;\n let lastRefill = Date.now();\n\n function refill() {\n const now = Date.now();\n const elapsed = now - lastRefill;\n const refills = Math.floor(elapsed / refillIntervalMs);\n if (refills > 0) {\n tokens = Math.min(maxBurst, tokens + refills * refillRate);\n lastRefill = now;\n }\n }\n\n function tryConsume(): boolean {\n refill();\n if (tokens > 0) {\n tokens--;\n return true;\n }\n return false;\n }\n\n function reset(): void {\n tokens = maxBurst;\n lastRefill = Date.now();\n }\n\n function availableTokens(): number {\n refill();\n return tokens;\n }\n\n return { tryConsume, reset, availableTokens };\n}\n","export interface PiiScrubberConfig {\n emails?: boolean;\n phones?: boolean;\n creditCards?: boolean;\n ssns?: boolean;\n ipAddresses?: boolean;\n /**\n * Scrub vendor-shaped secret tokens (AWS access keys, Stripe keys,\n * Slack/GitHub PATs, OpenAI/Anthropic/Google keys, JWTs).\n *\n * Wave S1 / D-15: SDK parity with the server-side scrubber. The server\n * scrubs these on every LLM invocation; the SDK now scrubs them at\n * capture so they never hit the wire in the first place — important for\n * users who `console.log(stripeKey)` during dev and later ship bug\n * reports with the error text attached.\n */\n secretTokens?: boolean;\n /** IPv6 addresses. Defaults off for the same reason IPv4 does. */\n ipv6?: boolean;\n}\n\ninterface PiiPattern {\n key: keyof PiiScrubberConfig;\n regex: RegExp;\n replacement: string;\n}\n\n// Order matters: SSN → CC → vendor secrets → email → phone → IP. Secret\n// tokens are matched *before* the generic email/phone regex because some JWT\n// payloads contain `.` that could be mis-parsed as `xyz.abc.com`.\nconst ORDERED_PATTERNS: PiiPattern[] = [\n { key: 'ssns', regex: /\\b\\d{3}-\\d{2}-\\d{4}\\b/g, replacement: '[REDACTED_SSN]' },\n { key: 'creditCards', regex: /\\b(?:\\d[ -]*){12,18}\\d\\b/g, replacement: '[REDACTED_CC]' },\n\n // Vendor secret tokens — mirrors packages/server/.../pii-scrubber.ts exactly.\n { key: 'secretTokens', regex: /\\b(?:AKIA|ASIA)[0-9A-Z]{16}\\b/g, replacement: '[REDACTED_AWS_KEY]' },\n { key: 'secretTokens', regex: /(?:aws_secret_access_key|secret_access_key)[\"'\\s:=]+[A-Za-z0-9/+=]{40}\\b/gi, replacement: 'aws_secret_access_key=[REDACTED_AWS_SECRET]' },\n { key: 'secretTokens', regex: /\\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{24,}\\b/g, replacement: '[REDACTED_STRIPE_KEY]' },\n { key: 'secretTokens', regex: /\\bpk_(?:live|test)_[A-Za-z0-9]{24,}\\b/g, replacement: '[REDACTED_STRIPE_PK]' },\n { key: 'secretTokens', regex: /\\bxox[abpor]-[A-Za-z0-9-]{10,}\\b/g, replacement: '[REDACTED_SLACK_TOKEN]' },\n { key: 'secretTokens', regex: /\\bghp_[A-Za-z0-9]{36}\\b/g, replacement: '[REDACTED_GITHUB_PAT]' },\n { key: 'secretTokens', regex: /\\bgithub_pat_[A-Za-z0-9_]{80,}\\b/g, replacement: '[REDACTED_GITHUB_PAT]' },\n { key: 'secretTokens', regex: /\\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\\b/g, replacement: '[REDACTED_OPENAI_KEY]' },\n { key: 'secretTokens', regex: /\\bsk-ant-[A-Za-z0-9_-]{20,}\\b/g, replacement: '[REDACTED_ANTHROPIC_KEY]' },\n { key: 'secretTokens', regex: /\\bAIza[0-9A-Za-z_-]{35}\\b/g, replacement: '[REDACTED_GOOGLE_KEY]' },\n { key: 'secretTokens', regex: /\\beyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\b/g, replacement: '[REDACTED_JWT]' },\n\n { key: 'emails', regex: /\\b[A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z]{2,}\\b/g, replacement: '[REDACTED_EMAIL]' },\n { key: 'phones', regex: /(?:\\+\\d{1,3}[\\s.-])?\\(?\\d{2,4}\\)?[\\s.-]\\d{3,4}[\\s.-]\\d{3,4}\\b/g, replacement: '[REDACTED_PHONE]' },\n { key: 'ipAddresses', regex: /\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b/g, replacement: '[REDACTED_IP]' },\n { key: 'ipv6', regex: /\\b(?:[A-Fa-f0-9]{1,4}:){2,7}[A-Fa-f0-9]{0,4}\\b/g, replacement: '[REDACTED_IPV6]' },\n];\n\nconst DEFAULT_CONFIG: PiiScrubberConfig = {\n emails: true,\n phones: true,\n creditCards: true,\n ssns: true,\n ipAddresses: false,\n // Secret tokens default ON — if they leak into a bug report there's no\n // good reason to ship them to our servers. Cheaper to scrub client-side.\n secretTokens: true,\n ipv6: false,\n};\n\nexport function createPiiScrubber(config: PiiScrubberConfig = {}) {\n const merged = { ...DEFAULT_CONFIG, ...config };\n\n const activePatterns = ORDERED_PATTERNS.filter((p) => merged[p.key]);\n\n function scrub(text: string): string {\n if (!text) return text;\n let result = text;\n for (const { regex, replacement } of activePatterns) {\n result = result.replace(new RegExp(regex.source, regex.flags), replacement);\n }\n return result;\n }\n\n function scrubObject<T extends Record<string, unknown>>(obj: T, keys: string[]): T {\n const copy = { ...obj };\n for (const key of keys) {\n if (typeof copy[key] === 'string') {\n (copy as Record<string, unknown>)[key] = scrub(copy[key] as string);\n }\n }\n return copy;\n }\n\n return { scrub, scrubObject };\n}\n\nexport function scrubPii(text: string, config?: PiiScrubberConfig): string {\n return createPiiScrubber(config).scrub(text);\n}\n"]}
1
+ {"version":3,"sources":["../src/api-client.ts","../src/region.ts","../src/pre-filter.ts","../src/logger.ts","../src/queue-crypto.ts","../src/queue.ts","../src/environment.ts","../src/reporter-token.ts","../src/fingerprint.ts","../src/session.ts","../src/rate-limiter.ts","../src/pii-scrubber.ts"],"names":["getBackoffDelay","sleep"],"mappings":";AAgBO,IAAM,oBAAA,GAAuB;AACpC,IAAM,eAAA,GAAkB,GAAA;AACxB,IAAM,mBAAA,GAAsB,CAAA;AAErB,SAAS,gBAAgB,OAAA,EAA2C;AACzE,EAAA,MAAM;AAAA,IACJ,SAAA;AAAA,IACA,MAAA;AAAA,IACA,WAAA,GAAc,oBAAA;AAAA,IACd,OAAA,GAAU,eAAA;AAAA,IACV,UAAA,GAAa;AAAA,GACf,GAAI,OAAA;AAEJ,EAAA,IAAI,OAAA,GAAU,WAAA,CAAY,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAE3C,EAAA,eAAe,OAAA,CACb,MAAA,EACA,IAAA,EACA,IAAA,EACA,UAAU,UAAA,EACoB;AAC9B,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA;AAC7B,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,OAAO,CAAA;AAE1D,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,QAChC,MAAA;AAAA,QACA,OAAA,EAAS;AAAA,UACP,cAAA,EAAgB,kBAAA;AAAA,UAChB,iBAAA,EAAmB,MAAA;AAAA,UACnB,iBAAA,EAAmB;AAAA,SACrB;AAAA,QACA,IAAA,EAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,GAAI,KAAA,CAAA;AAAA,QACpC,QAAQ,UAAA,CAAW;AAAA,OACpB,CAAA;AAED,MAAA,YAAA,CAAa,KAAK,CAAA;AAKlB,MAAA,IAAI,QAAA,CAAS,MAAA,KAAW,GAAA,IAAO,QAAA,CAAS,WAAW,GAAA,EAAK;AACtD,QAAA,MAAM,MAAA,GAAS,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA;AAC9C,QAAA,IAAI,MAAA,IAAU,UAAU,CAAA,EAAG;AACzB,UAAA,MAAM,UAAA,GAAa,OAAO,OAAA,CAAQ,WAAA,EAAa,EAAE,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AACpE,UAAA,IAAI,eAAe,OAAA,EAAS;AAC1B,YAAA,OAAA,GAAU,UAAA;AACV,YAAA,OAAO,OAAA,CAAW,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,UAAU,CAAC,CAAA;AAAA,UACnD;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,MAAM,SAAA,GAAY,MAAM,QAAA,CAAS,IAAA,GAAO,KAAA,CAAM,OAAO,EAAC,CAAE,CAAA;AACxD,QAAA,IAAI,QAAA,CAAS,MAAA,IAAU,GAAA,IAAO,OAAA,GAAU,CAAA,EAAG;AACzC,UAAA,MAAM,KAAA,CAAM,eAAA,CAAgB,UAAA,GAAa,OAAO,CAAC,CAAA;AACjD,UAAA,OAAO,OAAA,CAAW,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,UAAU,CAAC,CAAA;AAAA,QACnD;AACA,QAAA,OAAO;AAAA,UACL,EAAA,EAAI,KAAA;AAAA,UACJ,KAAA,EAAO;AAAA,YACL,IAAA,EAAM,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,CAAA;AAAA,YAC7B,OAAA,EACG,UAAiE,KAAA,EAAO,OAAA,IACxE,UAAmC,OAAA,IACpC,CAAA,KAAA,EAAQ,SAAS,MAAM,CAAA,MAAA;AAAA;AAC3B,SACF;AAAA,MACF;AAEA,MAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,IAAA,EAAK;AACpC,MAAA,MAAM,IAAA,GAAO,OAAA,IAAW,OAAO,OAAA,KAAY,QAAA,IAAY,QAAQ,OAAA,IAAW,MAAA,IAAU,OAAA,GAC/E,OAAA,CAAwB,IAAA,GACzB,OAAA;AACJ,MAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAK;AAAA,IAC1B,SAAS,KAAA,EAAO;AACd,MAAA,YAAA,CAAa,KAAK,CAAA;AAElB,MAAA,IAAI,OAAA,GAAU,CAAA,IAAK,WAAA,CAAY,KAAK,CAAA,EAAG;AACrC,QAAA,MAAM,KAAA,CAAM,eAAA,CAAgB,UAAA,GAAa,OAAO,CAAC,CAAA;AACjD,QAAA,OAAO,OAAA,CAAW,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,UAAU,CAAC,CAAA;AAAA,MACnD;AAEA,MAAA,OAAO;AAAA,QACL,EAAA,EAAI,KAAA;AAAA,QACJ,KAAA,EAAO;AAAA,UACL,IAAA,EAAM,eAAA;AAAA,UACN,OAAA,EAAS,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU;AAAA;AACpD,OACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAM,aAAa,MAAA,EAAqB;AACtC,MAAA,OAAO,OAAA,CAA8B,MAAA,EAAQ,aAAA,EAAe,MAAM,CAAA;AAAA,IACpE,CAAA;AAAA,IAEA,MAAM,gBAAgB,QAAA,EAAkB;AACtC,MAAA,OAAO,OAAA,CAAuC,KAAA,EAAO,CAAA,YAAA,EAAe,QAAQ,CAAA,OAAA,CAAS,CAAA;AAAA,IACvF,CAAA;AAAA,IAEA,MAAM,YAAA,GAAe;AACnB,MAAA,OAAO,OAAA,CAA+B,OAAO,gBAAgB,CAAA;AAAA,IAC/D;AAAA,GACF;AACF;AAEA,SAAS,MAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD;AAEA,SAAS,gBAAgB,OAAA,EAAyB;AAChD,EAAA,OAAO,IAAA,CAAK,IAAI,GAAA,GAAO,CAAA,IAAK,UAAU,IAAA,CAAK,MAAA,EAAO,GAAI,GAAA,EAAK,GAAM,CAAA;AACnE;AAEA,SAAS,YAAY,KAAA,EAAyB;AAC5C,EAAA,IAAI,KAAA,YAAiB,YAAA,IAAgB,KAAA,CAAM,IAAA,KAAS,cAAc,OAAO,IAAA;AACzE,EAAA,IAAI,KAAA,YAAiB,WAAW,OAAO,IAAA;AACvC,EAAA,OAAO,KAAA;AACT;;;ACxHO,IAAM,gBAAA,GAAiE;AAAA,EAC5E,EAAA,EAAI,gDAAA;AAAA,EACJ,EAAA,EAAI,gDAAA;AAAA,EACJ,EAAA,EAAI;AACN;AAEA,IAAM,iBAAA,GAAoB,iBAAA;AAC1B,IAAM,oBAAA,GAAuB,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAgB5C,eAAsB,sBAAsB,IAAA,EAMxB;AAClB,EAAA,MAAM,WAAW,IAAA,CAAK,MAAA;AACtB,EAAA,IAAI,QAAA,IAAY,QAAA,KAAa,MAAA,IAAU,gBAAA,CAAiB,QAAQ,CAAA,EAAG;AACjE,IAAA,OAAO,iBAAiB,QAAQ,CAAA;AAAA,EAClC;AAEA,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,IAAW,gBAAA,EAAiB;AACjD,EAAA,MAAM,MAAA,GAAS,SAAA,CAAU,OAAA,EAAS,IAAA,CAAK,SAAS,CAAA;AAChD,EAAA,IAAI,QAAQ,OAAO,MAAA;AAEnB,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,KAAK,OAAA,IAAW,KAAA;AAChC,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAA,CAAK,WAAA,CAAY,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,8BAAA,EAAiC,kBAAA,CAAmB,IAAA,CAAK,SAAS,CAAC,CAAA,CAAA;AACrH,IAAA,MAAM,MAAM,MAAM,OAAA,CAAQ,KAAK,EAAE,MAAA,EAAQ,OAAO,CAAA;AAChD,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,OAAO,IAAA,CAAK,WAAA;AACzB,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,IAAU,CAAC,IAAA,CAAK,QAAA,SAAiB,IAAA,CAAK,WAAA;AAChD,IAAA,UAAA,CAAW,OAAA,EAAS,IAAA,CAAK,SAAA,EAAW,EAAE,QAAQ,IAAA,CAAK,MAAA,EAAQ,QAAA,EAAU,IAAA,CAAK,QAAA,EAAU,EAAA,EAAI,IAAA,CAAK,GAAA,IAAO,CAAA;AACpG,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA,CAAK,WAAA;AAAA,EACd;AACF;AAEA,SAAS,gBAAA,GAAwC;AAC/C,EAAA,IAAI;AACF,IAAA,OAAO,OAAO,UAAA,KAAe,WAAA,IAAe,cAAA,IAAkB,UAAA,GACzD,WAAyC,YAAA,GAC1C,KAAA,CAAA;AAAA,EACN,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAEA,SAAS,SAAA,CAAU,SAA8B,SAAA,EAAkC;AACjF,EAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AACrB,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,OAAA,CAAQ,OAAA,CAAQ,GAAG,iBAAiB,CAAA,CAAA,EAAI,SAAS,CAAA,CAAE,CAAA;AAC/D,IAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AACjB,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,IAAA,IAAI,KAAK,GAAA,EAAI,GAAI,MAAA,CAAO,EAAA,GAAK,sBAAsB,OAAO,IAAA;AAC1D,IAAA,OAAO,MAAA,CAAO,QAAA;AAAA,EAChB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,SAAS,UAAA,CAAW,OAAA,EAA8B,SAAA,EAAmB,KAAA,EAA+B;AAClG,EAAA,IAAI,CAAC,OAAA,EAAS;AACd,EAAA,IAAI;AACF,IAAA,OAAA,CAAQ,OAAA,CAAQ,GAAG,iBAAiB,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,EAAI,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,EAC5E,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;;;AC7FA,IAAM,kBAAA,GAAqB,EAAA;AAC3B,IAAM,kBAAA,GAAqB,GAAA;AAE3B,IAAM,aAAA,GAA0B;AAAA,EAC9B,cAAA;AAAA;AAAA,EACA,kBAAA;AAAA;AAAA,EACA,WAAA;AAAA;AAAA,EACA,sEAAA;AAAA;AAAA,EACA;AAAA;AACF,CAAA;AAEA,IAAM,iBAAA,GAAoB,8BAAA;AAEnB,SAAS,eAAA,CAAgB,MAAA,GAA+B,EAAC,EAAG;AACjE,EAAA,MAAM;AAAA,IACJ,OAAA,GAAU,IAAA;AAAA,IACV,gBAAA,GAAmB,IAAA;AAAA,IACnB,oBAAA,GAAuB,kBAAA;AAAA,IACvB,oBAAA,GAAuB;AAAA,GACzB,GAAI,MAAA;AAEJ,EAAA,SAAS,MAAM,WAAA,EAAsC;AACnD,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,OAAO,EAAE,QAAQ,IAAA,EAAK;AAAA,IACxB;AAEA,IAAA,MAAM,OAAA,GAAU,YAAY,IAAA,EAAK;AAEjC,IAAA,IAAI,OAAA,CAAQ,SAAS,oBAAA,EAAsB;AACzC,MAAA,OAAO,EAAE,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,CAAA,eAAA,EAAkB,oBAAoB,CAAA,YAAA,CAAA,EAAe;AAAA,IACvF;AAEA,IAAA,IAAI,OAAA,CAAQ,SAAS,oBAAA,EAAsB;AACzC,MAAA,OAAO,EAAE,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,CAAA,cAAA,EAAiB,oBAAoB,CAAA,YAAA,CAAA,EAAe;AAAA,IACtF;AAEA,IAAA,IAAI,gBAAA,EAAkB;AACpB,MAAA,KAAA,MAAW,WAAW,aAAA,EAAe;AACnC,QAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA,EAAG;AACzB,UAAA,OAAO,EAAE,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,kBAAA,EAAmB;AAAA,QACrD;AAAA,MACF;AAEA,MAAA,IAAI,iBAAA,CAAkB,IAAA,CAAK,OAAO,CAAA,EAAG;AACnC,QAAA,OAAO,EAAE,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,uBAAA,EAAwB;AAAA,MAC1D;AAEA,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAA,CAAE,OAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,GAAS,CAAC,CAAA;AAC7D,MAAA,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AACpB,QAAA,OAAO,EAAE,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,oCAAA,EAAqC;AAAA,MACvE;AAAA,IACF;AAEA,IAAA,OAAO,EAAE,QAAQ,IAAA,EAAK;AAAA,EACxB;AAEA,EAAA,SAAS,SAAS,WAAA,EAA6B;AAC7C,IAAA,MAAM,OAAA,GAAU,YAAY,IAAA,EAAK;AACjC,IAAA,IAAI,OAAA,CAAQ,MAAA,IAAU,oBAAA,EAAsB,OAAO,OAAA;AACnD,IAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,oBAAoB,CAAA,GAAI,KAAA;AAAA,EAClD;AAEA,EAAA,OAAO,EAAE,OAAO,QAAA,EAAS;AAC3B;;;ACfA,IAAM,WAAA,GAAwC;AAAA,EAC5C,KAAA,EAAO,EAAA;AAAA,EACP,IAAA,EAAM,EAAA;AAAA,EACN,IAAA,EAAM,EAAA;AAAA,EACN,KAAA,EAAO,EAAA;AAAA,EACP,KAAA,EAAO,EAAA;AAAA,EACP,MAAA,EAAQ;AACV,CAAA;AAEA,IAAM,WAAA,GAAsC;AAAA,EAC1C,KAAA,EAAO,KAAA;AAAA,EACP,IAAA,EAAM,KAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,KAAA,EAAO,KAAA;AAAA,EACP,KAAA,EAAO;AACT,CAAA;AAEA,IAAM,IAAA,GAAO;AAAA,EACX,KAAA,EAAO,SAAA;AAAA,EACP,GAAA,EAAK,SAAA;AAAA,EACL,IAAA,EAAM,SAAA;AAAA,EACN,IAAA,EAAM,UAAA;AAAA,EACN,KAAA,EAAO,UAAA;AAAA,EACP,MAAA,EAAQ,UAAA;AAAA,EACR,GAAA,EAAK,UAAA;AAAA,EAEL,KAAA,EAAO,UAAA;AAAA,EACP,KAAA,EAAO;AACT,CAAA;AAEA,IAAM,WAAA,GAAsC;AAAA,EAC1C,OAAO,IAAA,CAAK,GAAA;AAAA,EACZ,MAAM,IAAA,CAAK,KAAA;AAAA,EACX,MAAM,IAAA,CAAK,MAAA;AAAA,EACX,OAAO,IAAA,CAAK,GAAA;AAAA,EACZ,KAAA,EAAO,GAAG,IAAA,CAAK,KAAK,GAAG,IAAA,CAAK,KAAK,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA;AAC/C,CAAA;AAGA,SAAS,YAAA,GAAkC;AACzC,EAAA,IAAI;AACF,IAAA,IAAI,OAAQ,UAAA,CAAmB,IAAA,KAAS,WAAA,EAAa,OAAO,MAAA;AAAA,EAC9D,CAAA,CAAA,MAAQ;AAAA,EAAiB;AAEzB,EAAA,MAAM,OAAO,OAAQ,UAAA,CAAmB,OAAA,KAAY,WAAA,GAC/C,WAAmB,OAAA,GACpB,MAAA;AAEJ,EAAA,IAAI,MAAM,GAAA,EAAK;AACb,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,QAAA,KAAa,YAAA,EAAc,OAAO,MAAA;AAC/C,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,UAAA,KAAe,MAAA,EAAQ,OAAO,MAAA;AAC3C,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,UAAA,KAAe,QAAA,EAAU,OAAO,QAAA;AAC7C,IAAA,IAAI,IAAA,CAAK,MAAA,EAAQ,KAAA,EAAO,OAAO,QAAA;AAAA,EACjC;AAEA,EAAA,IAAI,OAAQ,UAAA,CAAmB,MAAA,KAAW,WAAA,EAAa,OAAO,QAAA;AAE9D,EAAA,OAAO,MAAA;AACT;AAGA,SAAS,YAAY,IAAA,EAAuC;AAC1D,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AACzC,IAAA,IAAI,CAAA,KAAM,MAAA,IAAa,CAAA,KAAM,IAAA,EAAM;AACnC,IAAA,IAAI,OAAO,MAAM,QAAA,EAAU;AACzB,MAAA,KAAA,CAAM,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,EAAI,KAAK,SAAA,CAAU,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,IACxC,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,KAAK,CAAA,EAAG,CAAC,IAAI,MAAA,CAAO,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,IAChC;AAAA,EACF;AACA,EAAA,OAAO,KAAA,CAAM,KAAK,GAAG,CAAA;AACvB;AAEA,SAAS,aAAa,KAAA,EAAyB;AAC7C,EAAA,MAAM,EAAE,EAAA,EAAI,KAAA,EAAO,OAAO,GAAA,EAAK,GAAG,MAAK,GAAI,KAAA;AAC3C,EAAA,MAAM,IAAA,GAAO,EAAA,CAAG,KAAA,CAAM,EAAA,EAAI,EAAE,CAAA;AAC5B,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,KAAK,CAAA,IAAK,EAAA;AACpC,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,KAAK,CAAA,IAAK,MAAM,WAAA,EAAY;AACtD,EAAA,MAAM,UAAU,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,CAAE,SAAS,CAAA,GAAI,CAAA,CAAA,EAAI,IAAA,CAAK,GAAG,GAAG,WAAA,CAAY,IAAI,CAAC,CAAA,EAAG,IAAA,CAAK,KAAK,CAAA,CAAA,GAAK,EAAA;AAEjG,EAAA,OAAO,CAAA,EAAG,IAAA,CAAK,GAAG,CAAA,EAAG,IAAI,CAAA,EAAG,IAAA,CAAK,KAAK,CAAA,CAAA,EAAI,KAAK,CAAA,EAAG,KAAK,CAAA,EAAG,KAAK,KAAK,CAAA,CAAA,EAAI,IAAA,CAAK,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,EAAI,IAAA,CAAK,KAAK,CAAA,CAAA,EAAI,GAAG,CAAA,EAAG,OAAO,CAAA,CAAA;AAC3H;AAEA,SAAS,WAAW,KAAA,EAAyB;AAC3C,EAAA,OAAO,IAAA,CAAK,UAAU,KAAK,CAAA;AAC7B;AAEA,SAAS,IAAA,CAAK,OAAiB,SAAA,EAAyB;AACtD,EAAA,QAAQ,KAAA;AAAO,IACb,KAAK,OAAA;AAAA,IACL,KAAK,OAAA;AACH,MAAA,OAAA,CAAQ,MAAM,SAAS,CAAA;AACvB,MAAA;AAAA,IACF,KAAK,MAAA;AACH,MAAA,OAAA,CAAQ,KAAK,SAAS,CAAA;AACtB,MAAA;AAAA,IACF;AACE,MAAA,OAAA,CAAQ,IAAI,SAAS,CAAA;AAAA;AAE3B;AAEA,SAAS,WAAA,CACP,KAAA,EACA,QAAA,EACA,QAAA,EACA,SAAA,EACQ;AACR,EAAA,IAAI,YAAA,GAAe,QAAA;AAEnB,EAAA,SAAS,GAAA,CAAI,KAAA,EAAiB,GAAA,EAAa,IAAA,EAAsC;AAC/E,IAAA,IAAI,WAAA,CAAY,KAAK,CAAA,GAAI,WAAA,CAAY,YAAY,CAAA,EAAG;AAEpD,IAAA,MAAM,KAAA,GAAkB;AAAA,MACtB,EAAA,EAAA,iBAAI,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MAC3B,KAAA;AAAA,MACA,KAAA;AAAA,MACA,GAAA;AAAA,MACA,GAAG,QAAA;AAAA,MACH,GAAG;AAAA,KACL;AAEA,IAAA,IAAA,CAAK,KAAA,EAAO,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,EAC9B;AAEA,EAAA,OAAO;AAAA,IACL,OAAO,CAAC,GAAA,EAAK,SAAU,GAAA,CAAI,OAAA,EAAS,KAAK,IAAI,CAAA;AAAA,IAC7C,MAAM,CAAC,GAAA,EAAK,SAAU,GAAA,CAAI,MAAA,EAAQ,KAAK,IAAI,CAAA;AAAA,IAC3C,MAAM,CAAC,GAAA,EAAK,SAAU,GAAA,CAAI,MAAA,EAAQ,KAAK,IAAI,CAAA;AAAA,IAC3C,OAAO,CAAC,GAAA,EAAK,SAAU,GAAA,CAAI,OAAA,EAAS,KAAK,IAAI,CAAA;AAAA,IAC7C,OAAO,CAAC,GAAA,EAAK,SAAU,GAAA,CAAI,OAAA,EAAS,KAAK,IAAI,CAAA;AAAA,IAE7C,KAAA,CAAM,YAAoB,SAAA,EAA6C;AACrE,MAAA,OAAO,WAAA;AAAA,QACL,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA;AAAA,QACtB,YAAA;AAAA,QACA,EAAE,GAAG,QAAA,EAAU,GAAG,SAAA,EAAU;AAAA,QAC5B;AAAA,OACF;AAAA,IACF,CAAA;AAAA,IAEA,SAAS,KAAA,EAAiB;AACxB,MAAA,YAAA,GAAe,KAAA;AAAA,IACjB;AAAA,GACF;AACF;AAYO,SAAS,aAAa,OAAA,EAAgC;AAC3D,EAAA,MAAM;AAAA,IACJ,KAAA;AAAA,IACA,KAAA,GAAQ,MAAA;AAAA,IACR,OAAO,EAAC;AAAA,IACR,MAAA,GAAS;AAAA,GACX,GAAI,OAAA;AAEJ,EAAA,MAAM,cAAA,GAAiB,MAAA,KAAW,MAAA,GAAS,YAAA,EAAa,GAAI,MAAA;AAC5D,EAAA,MAAM,SAAA,GAAY,cAAA,KAAmB,MAAA,GAAS,UAAA,GAAa,YAAA;AAE3D,EAAA,OAAO,WAAA,CAAY,KAAA,EAAO,KAAA,EAAO,IAAA,EAAM,SAAS,CAAA;AAClD;AAMO,IAAM,UAAA,GAAqB;AAAA,EAChC,OAAO,MAAM;AAAA,EAAC,CAAA;AAAA,EACd,MAAM,MAAM;AAAA,EAAC,CAAA;AAAA,EACb,MAAM,MAAM;AAAA,EAAC,CAAA;AAAA,EACb,OAAO,MAAM;AAAA,EAAC,CAAA;AAAA,EACd,OAAO,MAAM;AAAA,EAAC,CAAA;AAAA,EACd,OAAO,MAAM,UAAA;AAAA,EACb,UAAU,MAAM;AAAA,EAAC;AACnB;;;ACpNA,IAAM,MAAA,GAAS,qBAAA;AACf,IAAM,SAAA,GAAY,MAAA;AAClB,IAAM,aAAA,GAAgB,kBAAA;AAEtB,IAAI,SAAA,GAA8B,IAAA;AAClC,IAAI,gBAAA,GAA8C,IAAA;AAElD,SAAS,YAAA,GAAwB;AAC/B,EAAA,OACE,OAAO,UAAA,KAAe,WAAA,IACtB,OAAQ,UAAA,CAA8C,MAAA,KAAW,WAAA,IACjE,OAAQ,UAAA,CAA6C,MAAA,CAAO,MAAA,KAAW,WAAA,IACvE,OAAO,SAAA,KAAc,WAAA;AAEzB;AAEA,SAAS,SAAA,GAAkC;AACzC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,GAAA,GAAM,SAAA,CAAU,IAAA,CAAK,MAAA,EAAQ,CAAC,CAAA;AACpC,IAAA,GAAA,CAAI,kBAAkB,MAAM;AAC1B,MAAA,MAAM,KAAK,GAAA,CAAI,MAAA;AACf,MAAA,IAAI,CAAC,EAAA,CAAG,gBAAA,CAAiB,QAAA,CAAS,SAAS,CAAA,EAAG;AAC5C,QAAA,EAAA,CAAG,kBAAkB,SAAS,CAAA;AAAA,MAChC;AAAA,IACF,CAAA;AACA,IAAA,GAAA,CAAI,SAAA,GAAY,MAAM,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA;AACxC,IAAA,GAAA,CAAI,OAAA,GAAU,MAAM,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AAAA,EACtC,CAAC,CAAA;AACH;AAEA,eAAe,OAAA,GAAqC;AAClD,EAAA,MAAM,EAAA,GAAK,MAAM,SAAA,EAAU;AAC3B,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,EAAA,GAAK,EAAA,CAAG,WAAA,CAAY,SAAA,EAAW,UAAU,CAAA;AAC/C,IAAA,MAAM,MAAM,EAAA,CAAG,WAAA,CAAY,SAAS,CAAA,CAAE,IAAI,aAAa,CAAA;AACvD,IAAA,GAAA,CAAI,SAAA,GAAY,MAAM,OAAA,CAAS,GAAA,CAAI,UAAwB,IAAI,CAAA;AAC/D,IAAA,GAAA,CAAI,OAAA,GAAU,MAAM,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AAAA,EACtC,CAAC,CAAA;AACH;AAEA,eAAe,SAAS,GAAA,EAA+B;AACrD,EAAA,MAAM,EAAA,GAAK,MAAM,SAAA,EAAU;AAC3B,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,EAAA,GAAK,EAAA,CAAG,WAAA,CAAY,SAAA,EAAW,WAAW,CAAA;AAChD,IAAA,EAAA,CAAG,WAAA,CAAY,SAAS,CAAA,CAAE,GAAA,CAAI,KAAK,aAAa,CAAA;AAChD,IAAA,EAAA,CAAG,UAAA,GAAa,MAAM,OAAA,EAAQ;AAC9B,IAAA,EAAA,CAAG,OAAA,GAAU,MAAM,MAAA,CAAO,EAAA,CAAG,KAAK,CAAA;AAAA,EACpC,CAAC,CAAA;AACH;AAOA,eAAsB,kBAAA,GAAyC;AAC7D,EAAA,IAAI,WAAW,OAAO,SAAA;AACtB,EAAA,IAAI,kBAAkB,OAAO,gBAAA;AAC7B,EAAA,IAAI,CAAC,cAAa,EAAG;AACnB,IAAA,MAAM,IAAI,MAAM,8DAA8D,CAAA;AAAA,EAChF;AACA,EAAA,gBAAA,GAAA,CAAoB,YAAY;AAC9B,IAAA,MAAM,QAAA,GAAW,MAAM,OAAA,EAAQ;AAC/B,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,SAAA,GAAY,QAAA;AACZ,MAAA,OAAO,QAAA;AAAA,IACT;AACA,IAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,MAAA,CAAO,WAAA;AAAA,MAC9B,EAAE,IAAA,EAAM,SAAA,EAAW,MAAA,EAAQ,GAAA,EAAI;AAAA,MAC/B,KAAA;AAAA,MACA,CAAC,WAAW,SAAS;AAAA,KACvB;AACA,IAAA,MAAM,SAAS,GAAG,CAAA;AAClB,IAAA,SAAA,GAAY,GAAA;AACZ,IAAA,OAAO,GAAA;AAAA,EACT,CAAA,GAAG;AACH,EAAA,OAAO,gBAAA;AACT;AASA,SAAS,WAAW,KAAA,EAA2B;AAC7C,EAAA,IAAI,CAAA,GAAI,EAAA;AACR,EAAA,KAAA,MAAW,CAAA,IAAK,KAAA,EAAO,CAAA,IAAK,MAAA,CAAO,aAAa,CAAC,CAAA;AACjD,EAAA,OAAO,KAAK,CAAC,CAAA;AACf;AAEA,SAAS,WAAW,CAAA,EAAoC;AACtD,EAAA,MAAM,GAAA,GAAM,KAAK,CAAC,CAAA;AAClB,EAAA,MAAM,MAAM,IAAI,UAAA,CAAW,IAAI,WAAA,CAAY,GAAA,CAAI,MAAM,CAAC,CAAA;AACtD,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,MAAA,EAAQ,CAAA,EAAA,EAAK,GAAA,CAAI,CAAC,CAAA,GAAI,GAAA,CAAI,UAAA,CAAW,CAAC,CAAA;AAC9D,EAAA,OAAO,GAAA;AACT;AAEA,eAAsB,YAAY,KAAA,EAA2C;AAC3E,EAAA,MAAM,GAAA,GAAM,MAAM,kBAAA,EAAmB;AACrC,EAAA,MAAM,KAAK,MAAA,CAAO,eAAA,CAAgB,IAAI,UAAA,CAAW,EAAE,CAAC,CAAA;AACpD,EAAA,MAAM,IAAA,GAAO,IAAI,WAAA,EAAY,CAAE,OAAO,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAC3D,EAAA,MAAM,MAAA,GAAS,IAAI,UAAA,CAAW,MAAM,OAAO,MAAA,CAAO,OAAA,CAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,EAAA,EAAG,EAAG,GAAA,EAAK,IAAI,CAAC,CAAA;AAC7F,EAAA,OAAO,EAAE,IAAA,EAAM,CAAA,EAAG,EAAA,EAAI,UAAA,CAAW,EAAE,CAAA,EAAG,EAAA,EAAI,UAAA,CAAW,MAAM,CAAA,EAAE;AAC/D;AAEO,SAAS,mBAAmB,CAAA,EAAmC;AACpE,EAAA,OACE,CAAC,CAAC,CAAA,IACF,OAAO,MAAM,QAAA,IACZ,CAAA,CAAuB,IAAA,KAAS,CAAA,IACjC,OAAQ,CAAA,CAAuB,EAAA,KAAO,QAAA,IACtC,OAAQ,EAAuB,EAAA,KAAO,QAAA;AAE1C;AAEA,eAAsB,YAAyB,OAAA,EAAuC;AACpF,EAAA,MAAM,GAAA,GAAM,MAAM,kBAAA,EAAmB;AACrC,EAAA,MAAM,EAAA,GAAK,UAAA,CAAW,OAAA,CAAQ,EAAE,CAAA;AAChC,EAAA,MAAM,EAAA,GAAK,UAAA,CAAW,OAAA,CAAQ,EAAE,CAAA;AAChC,EAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,EAAA,EAAG,EAAG,GAAA,EAAK,EAAE,CAAA;AAC1E,EAAA,OAAO,KAAK,KAAA,CAAM,IAAI,aAAY,CAAE,MAAA,CAAO,KAAK,CAAC,CAAA;AACnD;;;AC5IA,IAAM,WAAW,YAAA,CAAa,EAAE,OAAO,aAAA,EAAe,KAAA,EAAO,QAAQ,CAAA;AAcrE,IAAM,OAAA,GAAU,aAAA;AAChB,IAAM,UAAA,GAAa,iBAAA;AACnB,IAAM,UAAA,GAAa,CAAA;AACnB,IAAM,MAAA,GAAS,qBAAA;AACf,IAAM,UAAA,GAAa,EAAA;AACnB,IAAM,cAAA,GAAiB,GAAA;AAahB,SAAS,kBAAA,CAAmB,MAAA,GAA6B,EAAC,EAAiB;AAChF,EAAA,MAAM,EAAE,UAAU,IAAA,EAAM,YAAA,GAAe,IAAI,eAAA,GAAkB,IAAA,EAAM,aAAA,GAAgB,IAAA,EAAK,GAAI,MAAA;AAE5F,EAAA,IAAI,WAAA,GAAmC,IAAA;AACvC,EAAA,IAAI,WAAA,GAAqC,IAAA;AAEzC,EAAA,eAAe,eAAe,MAAA,EAAyC;AACrE,IAAA,MAAM,QAAA,GAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AACxC,IAAA,IAAI,CAAC,aAAA,EAAe;AAClB,MAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,QAAA,EAAS;AAAA,IAC/B;AACA,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAM,WAAA,CAAY,MAAM,CAAA;AACxC,MAAA,OAAO,EAAE,EAAA,EAAI,MAAA,CAAO,EAAA,EAAI,UAAU,OAAA,EAAQ;AAAA,IAC5C,SAAS,GAAA,EAAK;AAGZ,MAAA,QAAA,CAAS,KAAK,qDAAA,EAAuD,EAAE,KAAK,MAAA,CAAO,GAAG,GAAG,CAAA;AACzF,MAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,QAAA,EAAS;AAAA,IAC/B;AAAA,EACF;AAEA,EAAA,eAAe,cAAc,GAAA,EAA6C;AACxE,IAAA,IAAI,iBAAA,CAAkB,GAAG,CAAA,EAAG;AAC1B,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,WAAA,CAAyB,GAAA,CAAI,OAAO,CAAA;AAAA,MACnD,SAAS,GAAA,EAAK;AACZ,QAAA,QAAA,CAAS,IAAA,CAAK,6CAAA,EAA+C,EAAE,GAAA,EAAK,MAAA,CAAO,GAAG,CAAA,EAAG,EAAA,EAAI,GAAA,CAAI,EAAA,EAAI,CAAA;AAC7F,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,IACF;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AAEA,EAAA,SAAS,kBAAkB,GAAA,EAAwC;AACjE,IAAA,OAAO,CAAC,CAAE,GAAA,CAAwB,OAAA,IAAW,kBAAA,CAAoB,IAAwB,OAAO,CAAA;AAAA,EAClG;AAEA,EAAA,SAAS,aAAA,GAAgC;AACvC,IAAA,IAAI,aAAa,OAAO,WAAA;AACxB,IAAA,IAAI,OAAO,cAAc,WAAA,EAAa;AACpC,MAAA,WAAA,GAAc,WAAA;AAAA,IAChB,CAAA,MAAA,IAAW,OAAO,YAAA,KAAiB,WAAA,EAAa;AAC9C,MAAA,WAAA,GAAc,cAAA;AAAA,IAChB,CAAA,MAAO;AACL,MAAA,WAAA,GAAc,MAAA;AAAA,IAChB;AACA,IAAA,OAAO,WAAA;AAAA,EACT;AAIA,EAAA,SAAS,MAAA,GAA+B;AACtC,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,MAAM,OAAA,GAAU,SAAA,CAAU,IAAA,CAAK,OAAA,EAAS,UAAU,CAAA;AAClD,MAAA,OAAA,CAAQ,kBAAkB,MAAM;AAC9B,QAAA,MAAM,KAAK,OAAA,CAAQ,MAAA;AACnB,QAAA,IAAI,CAAC,EAAA,CAAG,gBAAA,CAAiB,QAAA,CAAS,UAAU,CAAA,EAAG;AAC7C,UAAA,EAAA,CAAG,iBAAA,CAAkB,UAAA,EAAY,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,QACpD;AAAA,MACF,CAAA;AACA,MAAA,OAAA,CAAQ,SAAA,GAAY,MAAM,OAAA,CAAQ,OAAA,CAAQ,MAAM,CAAA;AAChD,MAAA,OAAA,CAAQ,UAAU,MAAM;AACtB,QAAA,WAAA,GAAc,cAAA;AACd,QAAA,MAAA,CAAO,QAAQ,KAAK,CAAA;AAAA,MACtB,CAAA;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,eAAe,WAAW,MAAA,EAAoC;AAC5D,IAAA,MAAM,EAAA,GAAK,MAAM,MAAA,EAAO;AACxB,IAAA,MAAM,GAAA,GAAM,MAAM,cAAA,CAAe,MAAM,CAAA;AACvC,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,MAAM,EAAA,GAAK,EAAA,CAAG,WAAA,CAAY,UAAA,EAAY,WAAW,CAAA;AACjD,MAAA,EAAA,CAAG,WAAA,CAAY,UAAU,CAAA,CAAE,GAAA,CAAI,GAAG,CAAA;AAClC,MAAA,EAAA,CAAG,UAAA,GAAa,MAAM,OAAA,EAAQ;AAC9B,MAAA,EAAA,CAAG,OAAA,GAAU,MAAM,MAAA,CAAO,EAAA,CAAG,KAAK,CAAA;AAAA,IACpC,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,eAAe,SAAA,GAAkC;AAC/C,IAAA,MAAM,EAAA,GAAK,MAAM,MAAA,EAAO;AACxB,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,MAAM,EAAA,GAAK,EAAA,CAAG,WAAA,CAAY,UAAA,EAAY,UAAU,CAAA;AAChD,MAAA,MAAM,OAAA,GAAU,EAAA,CAAG,WAAA,CAAY,UAAU,EAAE,MAAA,EAAO;AAClD,MAAA,OAAA,CAAQ,SAAA,GAAY,MAAM,OAAA,CAAQ,OAAA,CAAQ,MAAqB,CAAA;AAC/D,MAAA,OAAA,CAAQ,OAAA,GAAU,MAAM,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA;AAAA,IAC9C,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,eAAe,UAAU,EAAA,EAA2B;AAClD,IAAA,MAAM,EAAA,GAAK,MAAM,MAAA,EAAO;AACxB,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,MAAM,EAAA,GAAK,EAAA,CAAG,WAAA,CAAY,UAAA,EAAY,WAAW,CAAA;AACjD,MAAA,EAAA,CAAG,WAAA,CAAY,UAAU,CAAA,CAAE,MAAA,CAAO,EAAE,CAAA;AACpC,MAAA,EAAA,CAAG,UAAA,GAAa,MAAM,OAAA,EAAQ;AAC9B,MAAA,EAAA,CAAG,OAAA,GAAU,MAAM,MAAA,CAAO,EAAA,CAAG,KAAK,CAAA;AAAA,IACpC,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,eAAe,OAAA,GAA2B;AACxC,IAAA,MAAM,EAAA,GAAK,MAAM,MAAA,EAAO;AACxB,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,MAAM,EAAA,GAAK,EAAA,CAAG,WAAA,CAAY,UAAA,EAAY,UAAU,CAAA;AAChD,MAAA,MAAM,OAAA,GAAU,EAAA,CAAG,WAAA,CAAY,UAAU,EAAE,KAAA,EAAM;AACjD,MAAA,OAAA,CAAQ,SAAA,GAAY,MAAM,OAAA,CAAQ,OAAA,CAAQ,MAAM,CAAA;AAChD,MAAA,OAAA,CAAQ,OAAA,GAAU,MAAM,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA;AAAA,IAC9C,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,eAAe,QAAA,GAA0B;AACvC,IAAA,MAAM,EAAA,GAAK,MAAM,MAAA,EAAO;AACxB,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,MAAM,EAAA,GAAK,EAAA,CAAG,WAAA,CAAY,UAAA,EAAY,WAAW,CAAA;AACjD,MAAA,EAAA,CAAG,WAAA,CAAY,UAAU,CAAA,CAAE,KAAA,EAAM;AACjC,MAAA,EAAA,CAAG,UAAA,GAAa,MAAM,OAAA,EAAQ;AAC9B,MAAA,EAAA,CAAG,OAAA,GAAU,MAAM,MAAA,CAAO,EAAA,CAAG,KAAK,CAAA;AAAA,IACpC,CAAC,CAAA;AAAA,EACH;AAIA,EAAA,SAAS,MAAA,GAAsB;AAC7B,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,YAAA,CAAa,OAAA,CAAQ,MAAM,CAAA;AACvC,MAAA,OAAO,GAAA,GAAO,IAAA,CAAK,KAAA,CAAM,GAAG,IAAoB,EAAC;AAAA,IACnD,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,EAAC;AAAA,IACV;AAAA,EACF;AAEA,EAAA,SAAS,QAAQ,IAAA,EAAyB;AACxC,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,OAAA,CAAQ,MAAA,EAAQ,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA;AAAA,IACnD,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAEA,EAAA,eAAe,UAAU,MAAA,EAAoC;AAC3D,IAAA,MAAM,OAAO,MAAA,EAAO;AACpB,IAAA,IAAA,CAAK,IAAA,CAAK,MAAM,cAAA,CAAe,MAAM,CAAC,CAAA;AACtC,IAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,EACd;AAEA,EAAA,SAAS,SAAS,EAAA,EAAkB;AAClC,IAAA,MAAM,IAAA,GAAO,QAAO,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,EAAE,CAAA;AAC/C,IAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,EACd;AAIA,EAAA,eAAe,QAAQ,MAAA,EAAoC;AACzD,IAAA,IAAI,CAAC,OAAA,EAAS;AAEd,IAAA,MAAM,WAAA,GAAc,MAAM,IAAA,EAAK;AAC/B,IAAA,IAAI,eAAe,YAAA,EAAc;AAC/B,MAAA,QAAA,CAAS,IAAA,CAAK,2CAAA,EAAwC,EAAE,YAAA,EAAc,CAAA;AACtE,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,UAAU,aAAA,EAAc;AAC9B,IAAA,IAAI,YAAY,WAAA,EAAa;AAC3B,MAAA,IAAI;AACF,QAAA,MAAM,WAAW,MAAM,CAAA;AACvB,QAAA;AAAA,MACF,CAAA,CAAA,MAAQ;AAEN,QAAA,WAAA,GAAc,cAAA;AAAA,MAChB;AAAA,IACF;AAEA,IAAA,IAAI,OAAA,KAAY,cAAA,IAAkB,WAAA,KAAgB,cAAA,EAAgB;AAChE,MAAA,MAAM,UAAU,MAAM,CAAA;AACtB,MAAA;AAAA,IACF;AAAA,EACF;AAEA,EAAA,SAASA,iBAAgB,OAAA,EAAyB;AAChD,IAAA,OAAO,IAAA,CAAK,IAAI,GAAA,GAAO,CAAA,IAAK,UAAU,IAAA,CAAK,MAAA,EAAO,GAAI,GAAA,EAAK,cAAc,CAAA;AAAA,EAC3E;AAEA,EAAA,SAASC,OAAM,EAAA,EAA2B;AACxC,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AAAA,EACzD;AAEA,EAAA,eAAe,MAAM,MAAA,EAAmE;AACtF,IAAA,IAAI,CAAC,OAAA,EAAS,OAAO,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA,EAAE;AAE1C,IAAA,IAAI,IAAA;AACJ,IAAA,MAAM,UAAU,aAAA,EAAc;AAE9B,IAAA,IAAI,YAAY,WAAA,EAAa;AAC3B,MAAA,IAAI;AACF,QAAA,IAAA,GAAO,MAAM,SAAA,EAAU;AAAA,MACzB,CAAA,CAAA,MAAQ;AACN,QAAA,IAAA,GAAO,MAAA,EAAO;AAAA,MAChB;AAAA,IACF,CAAA,MAAO;AACL,MAAA,IAAA,GAAO,MAAA,EAAO;AAAA,IAChB;AAEA,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA;AACtC,IAAA,IAAI,IAAA,GAAO,CAAA;AACX,IAAA,IAAI,MAAA,GAAS,CAAA;AAEb,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,MAAA,MAAM,GAAA,GAAM,MAAM,CAAC,CAAA;AACnB,MAAA,MAAM,QAAS,GAAA,CAAuB,EAAA;AACtC,MAAA,MAAM,MAAA,GAAS,MAAM,aAAA,CAAc,GAAG,CAAA;AAEtC,MAAA,IAAI,CAAC,MAAA,EAAQ;AAEX,QAAA,IAAI;AACF,UAAA,IAAI,OAAA,KAAY,WAAA,EAAa,MAAM,SAAA,CAAU,KAAK,CAAA;AAAA,wBACpC,KAAK,CAAA;AAAA,QACrB,CAAA,CAAA,MAAQ;AACN,UAAA,QAAA,CAAS,KAAK,CAAA;AAAA,QAChB;AACA,QAAA,MAAA,EAAA;AACA,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,YAAA,CAAa,MAAM,CAAA;AAE/C,MAAA,IAAI,OAAO,EAAA,EAAI;AACb,QAAA,IAAI;AACF,UAAA,IAAI,OAAA,KAAY,WAAA,EAAa,MAAM,SAAA,CAAU,KAAK,CAAA;AAAA,wBACpC,KAAK,CAAA;AAAA,QACrB,CAAA,CAAA,MAAQ;AACN,UAAA,QAAA,CAAS,KAAK,CAAA;AAAA,QAChB;AACA,QAAA,IAAA,EAAA;AAAA,MACF,CAAA,MAAO;AACL,QAAA,MAAA,EAAA;AACA,QAAA,IAAI,CAAA,GAAI,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG;AACxB,UAAA,MAAMA,MAAAA,CAAMD,gBAAAA,CAAgB,CAAC,CAAC,CAAA;AAAA,QAChC;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAO,EAAE,MAAM,MAAA,EAAO;AAAA,EACxB;AAEA,EAAA,eAAe,IAAA,GAAwB;AACrC,IAAA,MAAM,UAAU,aAAA,EAAc;AAC9B,IAAA,IAAI,YAAY,WAAA,EAAa;AAC3B,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,OAAA,EAAQ;AAAA,MACvB,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,QAAO,CAAE,MAAA;AAAA,MAClB;AAAA,IACF;AACA,IAAA,OAAO,QAAO,CAAE,MAAA;AAAA,EAClB;AAEA,EAAA,eAAe,KAAA,GAAuB;AACpC,IAAA,MAAM,UAAU,aAAA,EAAc;AAC9B,IAAA,IAAI,YAAY,WAAA,EAAa;AAC3B,MAAA,IAAI;AACF,QAAA,MAAM,QAAA,EAAS;AAAA,MACjB,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AACA,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,WAAW,MAAM,CAAA;AAAA,IAChC,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAEA,EAAA,SAAS,cAAc,MAAA,EAA8B;AACnD,IAAA,IAAI,CAAC,OAAA,IAAW,CAAC,eAAA,IAAmB,OAAO,WAAW,WAAA,EAAa;AAEnE,IAAA,MAAM,UAAU,MAAM;AACpB,MAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,QAAA,KAAA,CAAM,MAAM,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,QAAC,CAAC,CAAA;AAAA,MAC9B;AAAA,IACF,CAAA;AAEA,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,OAAO,CAAA;AACzC,IAAA,WAAA,GAAc,MAAM,MAAA,CAAO,mBAAA,CAAoB,QAAA,EAAU,OAAO,CAAA;AAAA,EAClE;AAEA,EAAA,SAAS,YAAA,GAAqB;AAC5B,IAAA,WAAA,IAAc;AACd,IAAA,WAAA,GAAc,IAAA;AAAA,EAChB;AAEA,EAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,eAAe,YAAA,EAAa;AACpE;;;AC1UO,SAAS,kBAAA,GAAuC;AACrD,EAAA,MAAM,GAAA,GAAM,OAAO,SAAA,KAAc,WAAA,GAAc,SAAA,GAAY,MAAA;AAC3D,EAAA,MAAM,GAAA,GAAM,OAAO,MAAA,KAAW,WAAA,GAAc,MAAA,GAAS,MAAA;AACrD,EAAA,MAAM,GAAA,GAAM,OAAO,QAAA,KAAa,WAAA,GAAc,QAAA,GAAW,MAAA;AAEzD,EAAA,MAAM,UAAA,GAAa,GAAA,IAAO,YAAA,IAAgB,GAAA,GAAO,IAAgC,UAAA,GAAa,MAAA;AAE9F,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,KAAK,SAAA,IAAa,SAAA;AAAA,IAC7B,QAAA,EAAU,KAAK,QAAA,IAAY,SAAA;AAAA,IAC3B,QAAA,EAAU,KAAK,QAAA,IAAY,IAAA;AAAA,IAC3B,QAAA,EAAU;AAAA,MACR,KAAA,EAAO,KAAK,UAAA,IAAc,CAAA;AAAA,MAC1B,MAAA,EAAQ,KAAK,WAAA,IAAe;AAAA,KAC9B;AAAA,IACA,GAAA,EAAK,GAAA,EAAK,QAAA,EAAU,IAAA,IAAQ,EAAA;AAAA,IAC5B,QAAA,EAAU,KAAK,QAAA,IAAY,EAAA;AAAA,IAC3B,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,IAClC,UAAU,IAAA,EAAM,cAAA,IAAiB,EAAG,eAAA,MAAqB,QAAA,IAAY,KAAA;AAAA,IACrE,YAAY,UAAA,GACR;AAAA,MACE,eAAe,UAAA,CAAW,aAAA;AAAA,MAC1B,UAAU,UAAA,CAAW,QAAA;AAAA,MACrB,KAAK,UAAA,CAAW;AAAA,KAClB,GACA,MAAA;AAAA,IACJ,cAAe,GAAA,EAAmC,YAAA;AAAA,IAClD,qBAAqB,GAAA,EAAK;AAAA,GAC5B;AACF;;;AC/BA,IAAM,WAAA,GAAc,sBAAA;AAEb,SAAS,gBAAA,GAA2B;AACzC,EAAA,IAAI,OAAO,iBAAiB,WAAA,EAAa;AACvC,IAAA,MAAM,QAAA,GAAW,YAAA,CAAa,OAAA,CAAQ,WAAW,CAAA;AACjD,IAAA,IAAI,UAAU,OAAO,QAAA;AAAA,EACvB;AAEA,EAAA,MAAM,QAAQ,aAAA,EAAc;AAE5B,EAAA,IAAI,OAAO,iBAAiB,WAAA,EAAa;AACvC,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,OAAA,CAAQ,aAAa,KAAK,CAAA;AAAA,IACzC,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAEA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,aAAA,GAAwB;AAC/B,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,MAAA,CAAO,UAAA,EAAY;AACtD,IAAA,OAAO,CAAA,MAAA,EAAS,MAAA,CAAO,UAAA,EAAY,CAAA,CAAA;AAAA,EACrC;AAEA,EAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,EAAE,CAAA;AAC/B,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,IAAA,MAAA,CAAO,gBAAgB,KAAK,CAAA;AAAA,EAC9B,CAAA,MAAO;AACL,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,MAAA,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA,CAAK,MAAM,IAAA,CAAK,MAAA,KAAW,GAAG,CAAA;AAAA,IAC3C;AAAA,EACF;AAEA,EAAA,MAAM,MAAM,KAAA,CAAM,IAAA,CAAK,KAAK,CAAA,CACzB,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAC1C,KAAK,EAAE,CAAA;AACV,EAAA,OAAO,SAAS,GAAG,CAAA,CAAA;AACrB;;;ACtBA,IAAM,SAAA,GAAY,wBAAA;AAclB,SAAS,aAAA,GAAmC;AAC1C,EAAA,MAAM,GAAA,GAAM,OAAO,SAAA,KAAc,WAAA,GAAc,SAAA,GAAY,MAAA;AAC3D,EAAA,MAAM,GAAA,GAAM,OAAO,MAAA,KAAW,WAAA,GAAc,MAAA,GAAS,MAAA;AACrD,EAAA,MAAM,GAAA,GAAM,OAAO,MAAA,KAAW,WAAA,GAAc,MAAA,GAAS,MAAA;AACrD,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,KAAK,SAAA,IAAa,SAAA;AAAA,IAC7B,QAAA,EAAU,KAAK,QAAA,IAAY,SAAA;AAAA,IAC3B,QAAA,EAAU,KAAK,QAAA,IAAY,IAAA;AAAA,IAC3B,UAAU,IAAA,EAAM,cAAA,IAAiB,EAAG,eAAA,MAAqB,QAAA,IAAY,KAAA;AAAA,IACrE,WAAA,EAAa,KAAK,KAAA,IAAS,CAAA;AAAA,IAC3B,YAAA,EAAc,KAAK,MAAA,IAAU,CAAA;AAAA,IAC7B,UAAA,EAAY,KAAK,gBAAA,IAAoB,CAAA;AAAA,IACrC,cAAe,GAAA,EAA+C,YAAA;AAAA,IAC9D,qBAAqB,GAAA,EAAK;AAAA,GAC5B;AACF;AAMA,eAAe,UAAU,KAAA,EAAgC;AACvD,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,MAAA,CAAO,MAAA,EAAQ;AAClD,IAAA,MAAM,GAAA,GAAM,IAAI,WAAA,EAAY,CAAE,OAAO,KAAK,CAAA;AAC1C,IAAA,MAAM,SAAS,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,WAAW,GAAG,CAAA;AACxD,IAAA,OAAO,KAAA,CAAM,KAAK,IAAI,UAAA,CAAW,MAAM,CAAC,CAAA,CACrC,IAAI,CAAC,CAAA,KAAM,EAAE,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAC1C,KAAK,EAAE,CAAA;AAAA,EACZ;AAIA,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,IAAA,GAAA,CAAQ,IAAA,IAAQ,CAAA,IAAK,IAAA,GAAO,KAAA,CAAM,WAAW,CAAC,CAAA;AAC9C,IAAA,IAAA,IAAQ,CAAA;AAAA,EACV;AACA,EAAA,OAAO,CAAA,IAAA,EAAA,CAAQ,SAAS,CAAA,EAAG,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AAC1D;AASA,eAAsB,wBAAA,GAAmD;AACvE,EAAA,IAAI,OAAO,iBAAiB,WAAA,EAAa;AACvC,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,OAAA,CAAQ,SAAS,CAAA;AAC7C,IAAA,IAAI,QAAQ,OAAO,MAAA;AAAA,EACrB;AAEA,EAAA,MAAM,SAAS,aAAA,EAAc;AAC7B,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA;AACxC,EAAA,MAAM,IAAA,GAAO,MAAM,SAAA,CAAU,UAAU,CAAA;AAEvC,EAAA,IAAI,OAAO,iBAAiB,WAAA,EAAa;AACvC,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,OAAA,CAAQ,WAAW,IAAI,CAAA;AAAA,IACtC,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;;;AChGA,IAAM,WAAA,GAAc,kBAAA;AAEpB,IAAI,eAAA,GAAiC,IAAA;AAE9B,SAAS,YAAA,GAAuB;AACrC,EAAA,IAAI,iBAAiB,OAAO,eAAA;AAE5B,EAAA,IAAI,OAAO,mBAAmB,WAAA,EAAa;AACzC,IAAA,MAAM,QAAA,GAAW,cAAA,CAAe,OAAA,CAAQ,WAAW,CAAA;AACnD,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,eAAA,GAAkB,QAAA;AAClB,MAAA,OAAO,QAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,MAAM,KAAK,iBAAA,EAAkB;AAC7B,EAAA,eAAA,GAAkB,EAAA;AAElB,EAAA,IAAI,OAAO,mBAAmB,WAAA,EAAa;AACzC,IAAA,IAAI;AACF,MAAA,cAAA,CAAe,OAAA,CAAQ,aAAa,EAAE,CAAA;AAAA,IACxC,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAEA,EAAA,OAAO,EAAA;AACT;AAEA,SAAS,iBAAA,GAA4B;AACnC,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,EAAI,CAAE,SAAS,EAAE,CAAA;AACxC,EAAA,MAAM,MAAA,GAAS,KAAK,MAAA,EAAO,CAAE,SAAS,EAAE,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AACpD,EAAA,OAAO,CAAA,GAAA,EAAM,SAAS,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA;AAClC;;;ACrBA,IAAM,iBAAA,GAAoB,EAAA;AAC1B,IAAM,mBAAA,GAAsB,CAAA;AAC5B,IAAM,0BAAA,GAA6B,GAAA;AAE5B,SAAS,iBAAA,CAAkB,MAAA,GAA4B,EAAC,EAAgB;AAC7E,EAAA,MAAM;AAAA,IACJ,QAAA,GAAW,iBAAA;AAAA,IACX,UAAA,GAAa,mBAAA;AAAA,IACb,gBAAA,GAAmB;AAAA,GACrB,GAAI,MAAA;AAEJ,EAAA,IAAI,MAAA,GAAS,QAAA;AACb,EAAA,IAAI,UAAA,GAAa,KAAK,GAAA,EAAI;AAE1B,EAAA,SAAS,MAAA,GAAS;AAChB,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,UAAU,GAAA,GAAM,UAAA;AACtB,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,gBAAgB,CAAA;AACrD,IAAA,IAAI,UAAU,CAAA,EAAG;AACf,MAAA,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,QAAA,EAAU,MAAA,GAAS,UAAU,UAAU,CAAA;AACzD,MAAA,UAAA,GAAa,GAAA;AAAA,IACf;AAAA,EACF;AAEA,EAAA,SAAS,UAAA,GAAsB;AAC7B,IAAA,MAAA,EAAO;AACP,IAAA,IAAI,SAAS,CAAA,EAAG;AACd,MAAA,MAAA,EAAA;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,SAAS,KAAA,GAAc;AACrB,IAAA,MAAA,GAAS,QAAA;AACT,IAAA,UAAA,GAAa,KAAK,GAAA,EAAI;AAAA,EACxB;AAEA,EAAA,SAAS,eAAA,GAA0B;AACjC,IAAA,MAAA,EAAO;AACP,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,OAAO,EAAE,UAAA,EAAY,KAAA,EAAO,eAAA,EAAgB;AAC9C;;;AC1BA,IAAM,gBAAA,GAAiC;AAAA,EACrC,EAAE,GAAA,EAAK,MAAA,EAAQ,KAAA,EAAO,wBAAA,EAA0B,aAAa,gBAAA,EAAiB;AAAA,EAC9E,EAAE,GAAA,EAAK,aAAA,EAAe,KAAA,EAAO,2BAAA,EAA6B,aAAa,eAAA,EAAgB;AAAA;AAAA,EAGvF,EAAE,GAAA,EAAK,cAAA,EAAgB,KAAA,EAAO,gCAAA,EAAkC,aAAa,oBAAA,EAAqB;AAAA,EAClG,EAAE,GAAA,EAAK,cAAA,EAAgB,KAAA,EAAO,4EAAA,EAA8E,aAAa,6CAAA,EAA8C;AAAA,EACvK,EAAE,GAAA,EAAK,cAAA,EAAgB,KAAA,EAAO,+CAAA,EAAiD,aAAa,uBAAA,EAAwB;AAAA,EACpH,EAAE,GAAA,EAAK,cAAA,EAAgB,KAAA,EAAO,wCAAA,EAA0C,aAAa,sBAAA,EAAuB;AAAA,EAC5G,EAAE,GAAA,EAAK,cAAA,EAAgB,KAAA,EAAO,mCAAA,EAAqC,aAAa,wBAAA,EAAyB;AAAA,EACzG,EAAE,GAAA,EAAK,cAAA,EAAgB,KAAA,EAAO,0BAAA,EAA4B,aAAa,uBAAA,EAAwB;AAAA,EAC/F,EAAE,GAAA,EAAK,cAAA,EAAgB,KAAA,EAAO,mCAAA,EAAqC,aAAa,uBAAA,EAAwB;AAAA,EACxG,EAAE,GAAA,EAAK,cAAA,EAAgB,KAAA,EAAO,sCAAA,EAAwC,aAAa,uBAAA,EAAwB;AAAA,EAC3G,EAAE,GAAA,EAAK,cAAA,EAAgB,KAAA,EAAO,gCAAA,EAAkC,aAAa,0BAAA,EAA2B;AAAA,EACxG,EAAE,GAAA,EAAK,cAAA,EAAgB,KAAA,EAAO,4BAAA,EAA8B,aAAa,uBAAA,EAAwB;AAAA,EACjG,EAAE,GAAA,EAAK,cAAA,EAAgB,KAAA,EAAO,wDAAA,EAA0D,aAAa,gBAAA,EAAiB;AAAA,EAEtH,EAAE,GAAA,EAAK,QAAA,EAAU,KAAA,EAAO,uDAAA,EAAyD,aAAa,kBAAA,EAAmB;AAAA,EACjH,EAAE,GAAA,EAAK,QAAA,EAAU,KAAA,EAAO,gEAAA,EAAkE,aAAa,kBAAA,EAAmB;AAAA,EAC1H,EAAE,GAAA,EAAK,aAAA,EAAe,KAAA,EAAO,8BAAA,EAAgC,aAAa,eAAA,EAAgB;AAAA,EAC1F,EAAE,GAAA,EAAK,MAAA,EAAQ,KAAA,EAAO,iDAAA,EAAmD,aAAa,iBAAA;AACxF,CAAA;AAEA,IAAM,cAAA,GAAoC;AAAA,EACxC,MAAA,EAAQ,IAAA;AAAA,EACR,MAAA,EAAQ,IAAA;AAAA,EACR,WAAA,EAAa,IAAA;AAAA,EACb,IAAA,EAAM,IAAA;AAAA,EACN,WAAA,EAAa,KAAA;AAAA;AAAA;AAAA,EAGb,YAAA,EAAc,IAAA;AAAA,EACd,IAAA,EAAM;AACR,CAAA;AAEO,SAAS,iBAAA,CAAkB,MAAA,GAA4B,EAAC,EAAG;AAChE,EAAA,MAAM,MAAA,GAAS,EAAE,GAAG,cAAA,EAAgB,GAAG,MAAA,EAAO;AAE9C,EAAA,MAAM,cAAA,GAAiB,iBAAiB,MAAA,CAAO,CAAC,MAAM,MAAA,CAAO,CAAA,CAAE,GAAG,CAAC,CAAA;AAEnE,EAAA,SAAS,MAAM,IAAA,EAAsB;AACnC,IAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,IAAA,IAAI,MAAA,GAAS,IAAA;AACb,IAAA,KAAA,MAAW,EAAE,KAAA,EAAO,WAAA,EAAY,IAAK,cAAA,EAAgB;AACnD,MAAA,MAAA,GAAS,MAAA,CAAO,QAAQ,IAAI,MAAA,CAAO,MAAM,MAAA,EAAQ,KAAA,CAAM,KAAK,CAAA,EAAG,WAAW,CAAA;AAAA,IAC5E;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,SAAS,WAAA,CAA+C,KAAQ,IAAA,EAAmB;AACjF,IAAA,MAAM,IAAA,GAAO,EAAE,GAAG,GAAA,EAAI;AACtB,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,IAAI,OAAO,IAAA,CAAK,GAAG,CAAA,KAAM,QAAA,EAAU;AACjC,QAAC,KAAiC,GAAG,CAAA,GAAI,KAAA,CAAM,IAAA,CAAK,GAAG,CAAW,CAAA;AAAA,MACpE;AAAA,IACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAO,EAAE,OAAO,WAAA,EAAY;AAC9B;AAEO,SAAS,QAAA,CAAS,MAAc,MAAA,EAAoC;AACzE,EAAA,OAAO,iBAAA,CAAkB,MAAM,CAAA,CAAE,KAAA,CAAM,IAAI,CAAA;AAC7C","file":"index.js","sourcesContent":["import type { MushiApiClient, MushiApiResponse, MushiReport, MushiReportStatus, MushiRuntimeSdkConfig } from './types';\n\nexport interface ApiClientOptions {\n projectId: string;\n apiKey: string;\n /**\n * Override the API endpoint. Defaults to the canonical Cloud URL\n * (DEFAULT_API_ENDPOINT). Self-hosted users MUST set this.\n */\n apiEndpoint?: string;\n timeout?: number;\n maxRetries?: number;\n}\n\n// V5.3 (M-cross-cutting): canonical Cloud URL — the older `api.mushimushi.dev`\n// hostname was never wired up. Self-hosted users MUST override `apiEndpoint`.\nexport const DEFAULT_API_ENDPOINT = 'https://dxptnwrhwsqckaftyymj.supabase.co/functions/v1/api';\nconst DEFAULT_TIMEOUT = 10_000;\nconst DEFAULT_MAX_RETRIES = 2;\n\nexport function createApiClient(options: ApiClientOptions): MushiApiClient {\n const {\n projectId,\n apiKey,\n apiEndpoint = DEFAULT_API_ENDPOINT,\n timeout = DEFAULT_TIMEOUT,\n maxRetries = DEFAULT_MAX_RETRIES,\n } = options;\n\n let baseUrl = apiEndpoint.replace(/\\/$/, '');\n\n async function request<T>(\n method: string,\n path: string,\n body?: unknown,\n retries = maxRetries,\n ): Promise<MushiApiResponse<T>> {\n const url = `${baseUrl}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'X-Mushi-Api-Key': apiKey,\n 'X-Mushi-Project': projectId,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timer);\n\n // C7: data residency — follow a one-shot redirect when the\n // gateway tells us the project lives in a different region. Cache the\n // new base URL so subsequent calls go straight to the right cluster.\n if (response.status === 307 || response.status === 308) {\n const target = response.headers.get('Location');\n if (target && retries > 0) {\n const targetBase = target.replace(/\\/v1\\/.*$/, '').replace(/\\/$/, '');\n if (targetBase !== baseUrl) {\n baseUrl = targetBase;\n return request<T>(method, path, body, retries - 1);\n }\n }\n }\n\n if (!response.ok) {\n const errorBody = await response.json().catch(() => ({}));\n if (response.status >= 500 && retries > 0) {\n await sleep(getBackoffDelay(maxRetries - retries));\n return request<T>(method, path, body, retries - 1);\n }\n return {\n ok: false,\n error: {\n code: `HTTP_${response.status}`,\n message:\n (errorBody as { message?: string; error?: { message?: string } }).error?.message ||\n (errorBody as { message?: string }).message ||\n `HTTP ${response.status} error`,\n },\n };\n }\n\n const payload = await response.json();\n const data = payload && typeof payload === 'object' && 'ok' in payload && 'data' in payload\n ? (payload as { data: T }).data\n : payload as T;\n return { ok: true, data };\n } catch (error) {\n clearTimeout(timer);\n\n if (retries > 0 && isRetryable(error)) {\n await sleep(getBackoffDelay(maxRetries - retries));\n return request<T>(method, path, body, retries - 1);\n }\n\n return {\n ok: false,\n error: {\n code: 'NETWORK_ERROR',\n message: error instanceof Error ? error.message : 'Unknown network error',\n },\n };\n }\n }\n\n return {\n async submitReport(report: MushiReport) {\n return request<{ reportId: string }>('POST', '/v1/reports', report);\n },\n\n async getReportStatus(reportId: string) {\n return request<{ status: MushiReportStatus }>('GET', `/v1/reports/${reportId}/status`);\n },\n\n async getSdkConfig() {\n return request<MushiRuntimeSdkConfig>('GET', '/v1/sdk/config');\n },\n };\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction getBackoffDelay(attempt: number): number {\n return Math.min(1000 * 2 ** attempt + Math.random() * 500, 10_000);\n}\n\nfunction isRetryable(error: unknown): boolean {\n if (error instanceof DOMException && error.name === 'AbortError') return true;\n if (error instanceof TypeError) return true; // network failures\n return false;\n}\n","/**\n * C7: Data residency region resolution.\n *\n * The SDK supports four regional clouds:\n * - 'us' → United States (default; legacy `dxptnwrhwsqckaftyymj`)\n * - 'eu' → European Union (Frankfurt)\n * - 'jp' → Japan (Tokyo)\n * - 'self' → self-hosted / BYO Supabase\n *\n * Customers choose a region at project creation time, and the gateway will\n * 307-redirect any cross-region calls to the correct host. The SDK caches\n * the resolved hostname in `localStorage` (browser) so that subsequent\n * sessions skip the redirect.\n */\n\nexport type MushiRegion = 'us' | 'eu' | 'jp' | 'self';\n\nexport const REGION_ENDPOINTS: Record<Exclude<MushiRegion, 'self'>, string> = {\n us: 'https://api.us.mushimushi.dev/functions/v1/api',\n eu: 'https://api.eu.mushimushi.dev/functions/v1/api',\n jp: 'https://api.jp.mushimushi.dev/functions/v1/api',\n};\n\nconst ROUTING_CACHE_KEY = 'mushi_region_v1';\nconst ROUTING_CACHE_TTL_MS = 24 * 60 * 60 * 1000;\n\ninterface RegionCacheEntry {\n region: MushiRegion;\n endpoint: string;\n ts: number;\n}\n\n/**\n * Resolve the regional endpoint for a project. Looks up the public\n * `region_routing` table on the legacy US gateway (the catalog of record),\n * then caches the result.\n *\n * Falls back to the explicit `apiEndpoint` if anything goes wrong — failure\n * here must never block report submission.\n */\nexport async function resolveRegionEndpoint(opts: {\n projectId: string;\n apiEndpoint: string;\n region?: MushiRegion;\n storage?: Storage;\n fetcher?: typeof fetch;\n}): Promise<string> {\n const explicit = opts.region;\n if (explicit && explicit !== 'self' && REGION_ENDPOINTS[explicit]) {\n return REGION_ENDPOINTS[explicit];\n }\n\n const storage = opts.storage ?? safeLocalStorage();\n const cached = readCache(storage, opts.projectId);\n if (cached) return cached;\n\n try {\n const fetcher = opts.fetcher ?? fetch;\n const url = `${opts.apiEndpoint.replace(/\\/$/, '')}/v1/region/resolve?project_id=${encodeURIComponent(opts.projectId)}`;\n const res = await fetcher(url, { method: 'GET' });\n if (!res.ok) return opts.apiEndpoint;\n const body = (await res.json()) as { region?: MushiRegion; endpoint?: string };\n if (!body.region || !body.endpoint) return opts.apiEndpoint;\n writeCache(storage, opts.projectId, { region: body.region, endpoint: body.endpoint, ts: Date.now() });\n return body.endpoint;\n } catch {\n return opts.apiEndpoint;\n }\n}\n\nfunction safeLocalStorage(): Storage | undefined {\n try {\n return typeof globalThis !== 'undefined' && 'localStorage' in globalThis\n ? (globalThis as { localStorage: Storage }).localStorage\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction readCache(storage: Storage | undefined, projectId: string): string | null {\n if (!storage) return null;\n try {\n const raw = storage.getItem(`${ROUTING_CACHE_KEY}:${projectId}`);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as RegionCacheEntry;\n if (Date.now() - parsed.ts > ROUTING_CACHE_TTL_MS) return null;\n return parsed.endpoint;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(storage: Storage | undefined, projectId: string, entry: RegionCacheEntry): void {\n if (!storage) return;\n try {\n storage.setItem(`${ROUTING_CACHE_KEY}:${projectId}`, JSON.stringify(entry));\n } catch {\n /* no-op: quota exceeded etc. */\n }\n}\n","import type { MushiPreFilterConfig } from './types';\n\nexport interface PreFilterResult {\n passed: boolean;\n reason?: string;\n}\n\nconst DEFAULT_MIN_LENGTH = 10;\nconst DEFAULT_MAX_LENGTH = 2000;\n\nconst SPAM_PATTERNS: RegExp[] = [\n /^(.)\\1{10,}$/, // repeated single character\n /^[A-Z\\s!?]{20,}$/, // all caps shouting\n /^[\\d\\s]+$/, // numbers only\n /^[^a-zA-Z\\u00C0-\\u024F\\u4E00-\\u9FFF\\u3040-\\u309F\\u30A0-\\u30FF]{10,}$/, // no real letters\n /\\b(test|asdf|qwerty|lorem ipsum)\\b/i, // common test strings\n];\n\nconst GIBBERISH_PATTERN = /^[bcdfghjklmnpqrstvwxz]{6,}/i; // consonant-only strings\n\nexport function createPreFilter(config: MushiPreFilterConfig = {}) {\n const {\n enabled = true,\n blockObviousSpam = true,\n minDescriptionLength = DEFAULT_MIN_LENGTH,\n maxDescriptionLength = DEFAULT_MAX_LENGTH,\n } = config;\n\n function check(description: string): PreFilterResult {\n if (!enabled) {\n return { passed: true };\n }\n\n const trimmed = description.trim();\n\n if (trimmed.length < minDescriptionLength) {\n return { passed: false, reason: `Too short (min ${minDescriptionLength} characters)` };\n }\n\n if (trimmed.length > maxDescriptionLength) {\n return { passed: false, reason: `Too long (max ${maxDescriptionLength} characters)` };\n }\n\n if (blockObviousSpam) {\n for (const pattern of SPAM_PATTERNS) {\n if (pattern.test(trimmed)) {\n return { passed: false, reason: 'Detected as spam' };\n }\n }\n\n if (GIBBERISH_PATTERN.test(trimmed)) {\n return { passed: false, reason: 'Detected as gibberish' };\n }\n\n const words = trimmed.split(/\\s+/).filter((w) => w.length > 1);\n if (words.length < 2) {\n return { passed: false, reason: 'Description needs at least 2 words' };\n }\n }\n\n return { passed: true };\n }\n\n function truncate(description: string): string {\n const trimmed = description.trim();\n if (trimmed.length <= maxDescriptionLength) return trimmed;\n return trimmed.slice(0, maxDescriptionLength) + '...';\n }\n\n return { check, truncate };\n}\n","/**\n * FILE: logger.ts\n * PURPOSE: Zero-dependency structured logger for the mushi-mushi SDK ecosystem.\n *\n * OVERVIEW:\n * - Production-grade logging with levels, scoped namespaces, and child loggers\n * - JSON output for server/production, pretty-formatted output for development\n * - Automatic environment detection (browser vs Node vs Deno)\n * - Structured metadata on every log entry\n * - No external dependencies — safe to ship in any SDK bundle\n *\n * USAGE:\n * import { createLogger } from '@mushi-mushi/core'\n * const log = createLogger({ scope: 'mushi:api' })\n * log.info('Request received', { method: 'POST', path: '/v1/reports' })\n * const child = log.child('ingest', { reportId: 'abc' })\n * child.warn('Slow query', { latencyMs: 420 })\n *\n * TECHNICAL DETAILS:\n * - Log levels: debug(10) < info(20) < warn(30) < error(40) < fatal(50) < silent(99)\n * - Format auto-detected: JSON in production/server, pretty in development\n * - Pretty format uses ANSI colors when supported (Node/Deno TTY)\n * - Child loggers inherit parent scope + metadata, can override level\n * - Timestamps are ISO 8601 with millisecond precision\n */\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'silent'\n\nexport type LogFormat = 'json' | 'pretty' | 'auto'\n\nexport interface LoggerOptions {\n scope: string\n level?: LogLevel\n meta?: Record<string, unknown>\n format?: LogFormat\n}\n\nexport interface Logger {\n debug(msg: string, meta?: Record<string, unknown>): void\n info(msg: string, meta?: Record<string, unknown>): void\n warn(msg: string, meta?: Record<string, unknown>): void\n error(msg: string, meta?: Record<string, unknown>): void\n fatal(msg: string, meta?: Record<string, unknown>): void\n child(scope: string, meta?: Record<string, unknown>): Logger\n setLevel(level: LogLevel): void\n}\n\nexport interface LogEntry {\n ts: string\n level: LogLevel\n scope: string\n msg: string\n [key: string]: unknown\n}\n\nconst LEVEL_VALUE: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n fatal: 50,\n silent: 99,\n}\n\nconst LEVEL_LABEL: Record<string, string> = {\n debug: 'DBG',\n info: 'INF',\n warn: 'WRN',\n error: 'ERR',\n fatal: 'FTL',\n}\n\nconst ANSI = {\n reset: '\\x1b[0m',\n dim: '\\x1b[2m',\n bold: '\\x1b[1m',\n cyan: '\\x1b[36m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n red: '\\x1b[31m',\n magenta: '\\x1b[35m',\n white: '\\x1b[37m',\n bgRed: '\\x1b[41m',\n} as const\n\nconst LEVEL_COLOR: Record<string, string> = {\n debug: ANSI.dim,\n info: ANSI.green,\n warn: ANSI.yellow,\n error: ANSI.red,\n fatal: `${ANSI.bgRed}${ANSI.white}${ANSI.bold}`,\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nfunction detectFormat(): 'json' | 'pretty' {\n try {\n if (typeof (globalThis as any).Deno !== 'undefined') return 'json'\n } catch { /* not Deno */ }\n\n const proc = typeof (globalThis as any).process !== 'undefined'\n ? (globalThis as any).process\n : undefined\n\n if (proc?.env) {\n if (proc.env.NODE_ENV === 'production') return 'json'\n if (proc.env.LOG_FORMAT === 'json') return 'json'\n if (proc.env.LOG_FORMAT === 'pretty') return 'pretty'\n if (proc.stdout?.isTTY) return 'pretty'\n }\n\n if (typeof (globalThis as any).window !== 'undefined') return 'pretty'\n\n return 'json'\n}\n/* eslint-enable @typescript-eslint/no-explicit-any */\n\nfunction flattenMeta(meta: Record<string, unknown>): string {\n const parts: string[] = []\n for (const [k, v] of Object.entries(meta)) {\n if (v === undefined || v === null) continue\n if (typeof v === 'object') {\n parts.push(`${k}=${JSON.stringify(v)}`)\n } else {\n parts.push(`${k}=${String(v)}`)\n }\n }\n return parts.join(' ')\n}\n\nfunction formatPretty(entry: LogEntry): string {\n const { ts, level, scope, msg, ...rest } = entry\n const time = ts.slice(11, 23)\n const color = LEVEL_COLOR[level] ?? ''\n const label = LEVEL_LABEL[level] ?? level.toUpperCase()\n const metaStr = Object.keys(rest).length > 0 ? ` ${ANSI.dim}${flattenMeta(rest)}${ANSI.reset}` : ''\n\n return `${ANSI.dim}${time}${ANSI.reset} ${color}${label}${ANSI.reset} ${ANSI.cyan}[${scope}]${ANSI.reset} ${msg}${metaStr}`\n}\n\nfunction formatJson(entry: LogEntry): string {\n return JSON.stringify(entry)\n}\n\nfunction emit(level: LogLevel, formatted: string): void {\n switch (level) {\n case 'error':\n case 'fatal':\n console.error(formatted)\n break\n case 'warn':\n console.warn(formatted)\n break\n default:\n console.log(formatted)\n }\n}\n\nfunction buildLogger(\n scope: string,\n minLevel: LogLevel,\n baseMeta: Record<string, unknown>,\n formatter: (entry: LogEntry) => string,\n): Logger {\n let currentLevel = minLevel\n\n function log(level: LogLevel, msg: string, meta?: Record<string, unknown>): void {\n if (LEVEL_VALUE[level] < LEVEL_VALUE[currentLevel]) return\n\n const entry: LogEntry = {\n ts: new Date().toISOString(),\n level,\n scope,\n msg,\n ...baseMeta,\n ...meta,\n }\n\n emit(level, formatter(entry))\n }\n\n return {\n debug: (msg, meta?) => log('debug', msg, meta),\n info: (msg, meta?) => log('info', msg, meta),\n warn: (msg, meta?) => log('warn', msg, meta),\n error: (msg, meta?) => log('error', msg, meta),\n fatal: (msg, meta?) => log('fatal', msg, meta),\n\n child(childScope: string, childMeta?: Record<string, unknown>): Logger {\n return buildLogger(\n `${scope}:${childScope}`,\n currentLevel,\n { ...baseMeta, ...childMeta },\n formatter,\n )\n },\n\n setLevel(level: LogLevel) {\n currentLevel = level\n },\n }\n}\n\n/**\n * Create a structured logger instance.\n *\n * @example\n * const log = createLogger({ scope: 'mushi:api', level: 'info' })\n * log.info('Server started', { port: 3000 })\n *\n * const child = log.child('auth', { userId: 'u-123' })\n * child.warn('Token expired')\n */\nexport function createLogger(options: LoggerOptions): Logger {\n const {\n scope,\n level = 'info',\n meta = {},\n format = 'auto',\n } = options\n\n const resolvedFormat = format === 'auto' ? detectFormat() : format\n const formatter = resolvedFormat === 'json' ? formatJson : formatPretty\n\n return buildLogger(scope, level, meta, formatter)\n}\n\n/**\n * Noop logger that discards all output.\n * Useful when logging should be completely disabled.\n */\nexport const noopLogger: Logger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n fatal: () => {},\n child: () => noopLogger,\n setLevel: () => {},\n}\n","/**\n * AES-GCM at-rest encryption for the offline queue (Wave S1 / D-16).\n *\n * Why this exists: on shared devices (kiosks, support-agent laptops) a\n * queued bug report sits in plaintext IndexedDB until the next flush.\n * Browser extensions, other tabs on the same origin, and forensic tools\n * with disk access can all read it. For a QA/bug-reporting SDK that\n * encourages users to paste sensitive data into descriptions, that's\n * unacceptable.\n *\n * Design:\n * - Generate a non-extractable AES-GCM key on first call (256-bit).\n * - Persist the `CryptoKey` object itself (Web Crypto allows IDB round-\n * trip of `CryptoKey` without ever serialising the raw bytes).\n * - Use a 12-byte random IV per payload; prepend it to ciphertext so\n * decrypt() needs no out-of-band state.\n * - Never block the caller — all errors bubble up so the queue can fall\n * back to plaintext storage with a debug log (see queue.ts).\n *\n * The key is tied to the browser origin (same-origin IDB). It does NOT\n * protect against an attacker with admin shell on the device: the browser\n * WILL decrypt on demand for anyone with origin access. That's the same\n * guarantee every origin-bound browser secret has and is the correct\n * threat model for offline bug reports.\n */\n\nconst KEY_DB = 'mushi-mushi-keyring';\nconst KEY_STORE = 'keys';\nconst KEY_RECORD_ID = 'offline-queue/v1';\n\nlet cachedKey: CryptoKey | null = null;\nlet cachedKeyPromise: Promise<CryptoKey> | null = null;\n\nfunction hasWebCrypto(): boolean {\n return (\n typeof globalThis !== 'undefined' &&\n typeof (globalThis as unknown as { crypto?: Crypto }).crypto !== 'undefined' &&\n typeof (globalThis as unknown as { crypto: Crypto }).crypto.subtle !== 'undefined' &&\n typeof indexedDB !== 'undefined'\n );\n}\n\nfunction openKeyDb(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.open(KEY_DB, 1);\n req.onupgradeneeded = () => {\n const db = req.result;\n if (!db.objectStoreNames.contains(KEY_STORE)) {\n db.createObjectStore(KEY_STORE);\n }\n };\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n });\n}\n\nasync function loadKey(): Promise<CryptoKey | null> {\n const db = await openKeyDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(KEY_STORE, 'readonly');\n const req = tx.objectStore(KEY_STORE).get(KEY_RECORD_ID);\n req.onsuccess = () => resolve((req.result as CryptoKey) ?? null);\n req.onerror = () => reject(req.error);\n });\n}\n\nasync function storeKey(key: CryptoKey): Promise<void> {\n const db = await openKeyDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(KEY_STORE, 'readwrite');\n tx.objectStore(KEY_STORE).put(key, KEY_RECORD_ID);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\n/**\n * Lazily get (or generate once + persist) the AES-GCM key for this origin.\n * `extractable: false` — so a script-level attacker can't `exportKey()` and\n * ship the raw bytes to their server, only use it via `encrypt`/`decrypt`.\n */\nexport async function getOfflineQueueKey(): Promise<CryptoKey> {\n if (cachedKey) return cachedKey;\n if (cachedKeyPromise) return cachedKeyPromise;\n if (!hasWebCrypto()) {\n throw new Error('Web Crypto + IndexedDB required for offline queue encryption');\n }\n cachedKeyPromise = (async () => {\n const existing = await loadKey();\n if (existing) {\n cachedKey = existing;\n return existing;\n }\n const key = await crypto.subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt'],\n );\n await storeKey(key);\n cachedKey = key;\n return key;\n })();\n return cachedKeyPromise;\n}\n\nexport interface EncryptedPayload {\n /** Magic marker so decrypt() can tell encrypted vs legacy plaintext rows. */\n readonly _mme: 1;\n readonly iv: string;\n readonly ct: string;\n}\n\nfunction bytesToB64(bytes: Uint8Array): string {\n let s = '';\n for (const b of bytes) s += String.fromCharCode(b);\n return btoa(s);\n}\n\nfunction b64ToBytes(s: string): Uint8Array<ArrayBuffer> {\n const bin = atob(s);\n const out = new Uint8Array(new ArrayBuffer(bin.length));\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nexport async function encryptJson(plain: unknown): Promise<EncryptedPayload> {\n const key = await getOfflineQueueKey();\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const data = new TextEncoder().encode(JSON.stringify(plain));\n const cipher = new Uint8Array(await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, data));\n return { _mme: 1, iv: bytesToB64(iv), ct: bytesToB64(cipher) };\n}\n\nexport function isEncryptedPayload(v: unknown): v is EncryptedPayload {\n return (\n !!v &&\n typeof v === 'object' &&\n (v as EncryptedPayload)._mme === 1 &&\n typeof (v as EncryptedPayload).iv === 'string' &&\n typeof (v as EncryptedPayload).ct === 'string'\n );\n}\n\nexport async function decryptJson<T = unknown>(payload: EncryptedPayload): Promise<T> {\n const key = await getOfflineQueueKey();\n const iv = b64ToBytes(payload.iv);\n const ct = b64ToBytes(payload.ct);\n const plain = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, key, ct);\n return JSON.parse(new TextDecoder().decode(plain)) as T;\n}\n","import type { MushiApiClient, MushiOfflineConfig, MushiReport } from './types';\nimport { createLogger } from './logger';\nimport {\n encryptJson,\n decryptJson,\n isEncryptedPayload,\n type EncryptedPayload,\n} from './queue-crypto';\n\nconst queueLog = createLogger({ scope: 'mushi:queue', level: 'warn' });\n\n// Wave S1 / D-16: opaque at-rest wrapper. Each queue row is either:\n// - a legacy plaintext `MushiReport` (pre-encryption; still readable)\n// - an `EncryptedRecord` with a bare `id` (so count / delete can operate\n// without decrypting every row) plus the encrypted payload blob.\ninterface EncryptedRecord {\n id: string;\n queuedAt: string;\n payload: EncryptedPayload;\n}\n\ntype StoredRow = MushiReport | EncryptedRecord;\n\nconst DB_NAME = 'mushi-mushi';\nconst STORE_NAME = 'offline-reports';\nconst DB_VERSION = 1;\nconst LS_KEY = 'mushi_offline_queue';\nconst BATCH_SIZE = 10;\nconst MAX_BACKOFF_MS = 60_000;\n\nexport interface OfflineQueue {\n enqueue(report: MushiReport): Promise<void>;\n flush(client: MushiApiClient): Promise<{ sent: number; failed: number }>;\n size(): Promise<number>;\n clear(): Promise<void>;\n startAutoSync(client: MushiApiClient): void;\n stopAutoSync(): void;\n}\n\ntype StorageBackend = 'indexeddb' | 'localstorage' | 'none';\n\nexport function createOfflineQueue(config: MushiOfflineConfig = {}): OfflineQueue {\n const { enabled = true, maxQueueSize = 50, syncOnReconnect = true, encryptAtRest = true } = config;\n\n let syncCleanup: (() => void) | null = null;\n let backendType: StorageBackend | null = null;\n\n async function wrapForStorage(report: MushiReport): Promise<StoredRow> {\n const queuedAt = new Date().toISOString();\n if (!encryptAtRest) {\n return { ...report, queuedAt } as MushiReport;\n }\n try {\n const payload = await encryptJson(report);\n return { id: report.id, queuedAt, payload } satisfies EncryptedRecord;\n } catch (err) {\n // Encryption failure is non-fatal — queue integrity matters more than\n // at-rest confidentiality. We fall back to plaintext and warn.\n queueLog.warn('Offline queue: encryption failed, storing plaintext', { err: String(err) });\n return { ...report, queuedAt } as MushiReport;\n }\n }\n\n async function unwrapForSend(row: StoredRow): Promise<MushiReport | null> {\n if (isEncryptedRecord(row)) {\n try {\n return await decryptJson<MushiReport>(row.payload);\n } catch (err) {\n queueLog.warn('Offline queue: decrypt failed, dropping row', { err: String(err), id: row.id });\n return null;\n }\n }\n return row;\n }\n\n function isEncryptedRecord(row: StoredRow): row is EncryptedRecord {\n return !!(row as EncryptedRecord).payload && isEncryptedPayload((row as EncryptedRecord).payload);\n }\n\n function detectBackend(): StorageBackend {\n if (backendType) return backendType;\n if (typeof indexedDB !== 'undefined') {\n backendType = 'indexeddb';\n } else if (typeof localStorage !== 'undefined') {\n backendType = 'localstorage';\n } else {\n backendType = 'none';\n }\n return backendType;\n }\n\n // --- IndexedDB backend ---\n\n function openDb(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME, { keyPath: 'id' });\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => {\n backendType = 'localstorage';\n reject(request.error);\n };\n });\n }\n\n async function idbEnqueue(report: MushiReport): Promise<void> {\n const db = await openDb();\n const row = await wrapForStorage(report);\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite');\n tx.objectStore(STORE_NAME).put(row);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n async function idbGetAll(): Promise<StoredRow[]> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readonly');\n const request = tx.objectStore(STORE_NAME).getAll();\n request.onsuccess = () => resolve(request.result as StoredRow[]);\n request.onerror = () => reject(request.error);\n });\n }\n\n async function idbDelete(id: string): Promise<void> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite');\n tx.objectStore(STORE_NAME).delete(id);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n async function idbSize(): Promise<number> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readonly');\n const request = tx.objectStore(STORE_NAME).count();\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n }\n\n async function idbClear(): Promise<void> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite');\n tx.objectStore(STORE_NAME).clear();\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n // --- localStorage fallback ---\n\n function lsRead(): StoredRow[] {\n try {\n const raw = localStorage.getItem(LS_KEY);\n return raw ? (JSON.parse(raw) as StoredRow[]) : [];\n } catch {\n return [];\n }\n }\n\n function lsWrite(rows: StoredRow[]): void {\n try {\n localStorage.setItem(LS_KEY, JSON.stringify(rows));\n } catch {\n // localStorage full or unavailable\n }\n }\n\n async function lsEnqueue(report: MushiReport): Promise<void> {\n const rows = lsRead();\n rows.push(await wrapForStorage(report));\n lsWrite(rows);\n }\n\n function lsDelete(id: string): void {\n const rows = lsRead().filter((r) => r.id !== id);\n lsWrite(rows);\n }\n\n // --- Unified interface ---\n\n async function enqueue(report: MushiReport): Promise<void> {\n if (!enabled) return;\n\n const currentSize = await size();\n if (currentSize >= maxQueueSize) {\n queueLog.warn('Offline queue full — dropping report', { maxQueueSize });\n return;\n }\n\n const backend = detectBackend();\n if (backend === 'indexeddb') {\n try {\n await idbEnqueue(report);\n return;\n } catch {\n // IndexedDB failed, fall through to localStorage\n backendType = 'localstorage';\n }\n }\n\n if (backend === 'localstorage' || backendType === 'localstorage') {\n await lsEnqueue(report);\n return;\n }\n }\n\n function getBackoffDelay(attempt: number): number {\n return Math.min(1000 * 2 ** attempt + Math.random() * 500, MAX_BACKOFF_MS);\n }\n\n function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n async function flush(client: MushiApiClient): Promise<{ sent: number; failed: number }> {\n if (!enabled) return { sent: 0, failed: 0 };\n\n let rows: StoredRow[];\n const backend = detectBackend();\n\n if (backend === 'indexeddb') {\n try {\n rows = await idbGetAll();\n } catch {\n rows = lsRead();\n }\n } else {\n rows = lsRead();\n }\n\n const batch = rows.slice(0, BATCH_SIZE);\n let sent = 0;\n let failed = 0;\n\n for (let i = 0; i < batch.length; i++) {\n const row = batch[i];\n const rowId = (row as { id: string }).id;\n const report = await unwrapForSend(row);\n\n if (!report) {\n // Undecryptable row — drop so it doesn't re-poison the queue forever.\n try {\n if (backend === 'indexeddb') await idbDelete(rowId);\n else lsDelete(rowId);\n } catch {\n lsDelete(rowId);\n }\n failed++;\n continue;\n }\n\n const result = await client.submitReport(report);\n\n if (result.ok) {\n try {\n if (backend === 'indexeddb') await idbDelete(rowId);\n else lsDelete(rowId);\n } catch {\n lsDelete(rowId);\n }\n sent++;\n } else {\n failed++;\n if (i < batch.length - 1) {\n await sleep(getBackoffDelay(i));\n }\n }\n }\n\n return { sent, failed };\n }\n\n async function size(): Promise<number> {\n const backend = detectBackend();\n if (backend === 'indexeddb') {\n try {\n return await idbSize();\n } catch {\n return lsRead().length;\n }\n }\n return lsRead().length;\n }\n\n async function clear(): Promise<void> {\n const backend = detectBackend();\n if (backend === 'indexeddb') {\n try {\n await idbClear();\n } catch {\n // fall through\n }\n }\n try {\n localStorage.removeItem(LS_KEY);\n } catch {\n // unavailable\n }\n }\n\n function startAutoSync(client: MushiApiClient): void {\n if (!enabled || !syncOnReconnect || typeof window === 'undefined') return;\n\n const handler = () => {\n if (navigator.onLine) {\n flush(client).catch(() => {});\n }\n };\n\n window.addEventListener('online', handler);\n syncCleanup = () => window.removeEventListener('online', handler);\n }\n\n function stopAutoSync(): void {\n syncCleanup?.();\n syncCleanup = null;\n }\n\n return { enqueue, flush, size, clear, startAutoSync, stopAutoSync };\n}\n","import type { MushiEnvironment } from './types';\n\nexport function captureEnvironment(): MushiEnvironment {\n const nav = typeof navigator !== 'undefined' ? navigator : undefined;\n const win = typeof window !== 'undefined' ? window : undefined;\n const doc = typeof document !== 'undefined' ? document : undefined;\n\n const connection = nav && 'connection' in nav ? (nav as NavigatorWithConnection).connection : undefined;\n\n return {\n userAgent: nav?.userAgent ?? 'unknown',\n platform: nav?.platform ?? 'unknown',\n language: nav?.language ?? 'en',\n viewport: {\n width: win?.innerWidth ?? 0,\n height: win?.innerHeight ?? 0,\n },\n url: win?.location?.href ?? '',\n referrer: doc?.referrer ?? '',\n timestamp: new Date().toISOString(),\n timezone: Intl?.DateTimeFormat?.()?.resolvedOptions?.()?.timeZone ?? 'UTC',\n connection: connection\n ? {\n effectiveType: connection.effectiveType,\n downlink: connection.downlink,\n rtt: connection.rtt,\n }\n : undefined,\n deviceMemory: (nav as NavigatorWithDeviceMemory)?.deviceMemory,\n hardwareConcurrency: nav?.hardwareConcurrency,\n };\n}\n\ninterface NetworkInformation {\n effectiveType?: string;\n downlink?: number;\n rtt?: number;\n}\n\ninterface NavigatorWithConnection extends Navigator {\n connection?: NetworkInformation;\n}\n\ninterface NavigatorWithDeviceMemory extends Navigator {\n deviceMemory?: number;\n}\n","const STORAGE_KEY = 'mushi_reporter_token';\n\nexport function getReporterToken(): string {\n if (typeof localStorage !== 'undefined') {\n const existing = localStorage.getItem(STORAGE_KEY);\n if (existing) return existing;\n }\n\n const token = generateToken();\n\n if (typeof localStorage !== 'undefined') {\n try {\n localStorage.setItem(STORAGE_KEY, token);\n } catch {\n // localStorage full or unavailable — token is ephemeral\n }\n }\n\n return token;\n}\n\nfunction generateToken(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return `mushi_${crypto.randomUUID()}`;\n }\n\n const bytes = new Uint8Array(16);\n if (typeof crypto !== 'undefined') {\n crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n\n const hex = Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n return `mushi_${hex}`;\n}\n","/**\n * §3c — stable device fingerprint hash.\n *\n * Hashes a deliberately small set of long-lived device characteristics so\n * the same browser keeps the same hash across sessions, but moving to a\n * new browser/device produces a different one. This lets the server\n * detect cross-account abuse (same hash → many reporter accounts) without\n * needing fingerprint.js or any other entropy-heavy library.\n *\n * Privacy notes:\n * - We never send the raw inputs, only the SHA-256 hex digest.\n * - The set is intentionally low-entropy on purpose; this is \"is this the\n * same device\" not \"who is this user\". For high-stakes anti-fraud you\n * should still combine with server-side IP/geo signals.\n * - Cached in localStorage so subsequent calls are zero-cost.\n */\n\nconst CACHE_KEY = 'mushi_fingerprint_hash';\n\ninterface FingerprintInputs {\n userAgent: string;\n platform: string;\n language: string;\n timezone: string;\n screenWidth: number;\n screenHeight: number;\n pixelRatio: number;\n deviceMemory: number | undefined;\n hardwareConcurrency: number | undefined;\n}\n\nfunction collectInputs(): FingerprintInputs {\n const nav = typeof navigator !== 'undefined' ? navigator : undefined;\n const scr = typeof screen !== 'undefined' ? screen : undefined;\n const win = typeof window !== 'undefined' ? window : undefined;\n return {\n userAgent: nav?.userAgent ?? 'unknown',\n platform: nav?.platform ?? 'unknown',\n language: nav?.language ?? 'en',\n timezone: Intl?.DateTimeFormat?.()?.resolvedOptions?.()?.timeZone ?? 'UTC',\n screenWidth: scr?.width ?? 0,\n screenHeight: scr?.height ?? 0,\n pixelRatio: win?.devicePixelRatio ?? 1,\n deviceMemory: (nav as NavigatorWithDeviceMemory | undefined)?.deviceMemory,\n hardwareConcurrency: nav?.hardwareConcurrency,\n };\n}\n\ninterface NavigatorWithDeviceMemory extends Navigator {\n deviceMemory?: number;\n}\n\nasync function sha256Hex(input: string): Promise<string> {\n if (typeof crypto !== 'undefined' && crypto.subtle) {\n const buf = new TextEncoder().encode(input);\n const digest = await crypto.subtle.digest('SHA-256', buf);\n return Array.from(new Uint8Array(digest))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n }\n // Fallback (Node 18+ test envs, very old browsers): non-cryptographic but\n // good enough for the \"are these two requests from the same device\" use\n // case the server makes of this value.\n let hash = 0;\n for (let i = 0; i < input.length; i++) {\n hash = (hash << 5) - hash + input.charCodeAt(i);\n hash |= 0;\n }\n return `fbk_${(hash >>> 0).toString(16).padStart(8, '0')}`;\n}\n\n/**\n * Returns a stable per-device hash. Cached in localStorage; first call is\n * one SHA-256, subsequent calls are a localStorage read.\n *\n * Returns `null` outside browser-like environments (SSR, web workers\n * without crypto.subtle) so callers can omit the field gracefully.\n */\nexport async function getDeviceFingerprintHash(): Promise<string | null> {\n if (typeof localStorage !== 'undefined') {\n const cached = localStorage.getItem(CACHE_KEY);\n if (cached) return cached;\n }\n\n const inputs = collectInputs();\n const serialised = JSON.stringify(inputs);\n const hash = await sha256Hex(serialised);\n\n if (typeof localStorage !== 'undefined') {\n try {\n localStorage.setItem(CACHE_KEY, hash);\n } catch {\n // localStorage quota / private mode — caller still gets the hash.\n }\n }\n return hash;\n}\n\n/** Test/diagnostic helper — never include in shipped reports. */\nexport function _resetFingerprintCacheForTests(): void {\n if (typeof localStorage !== 'undefined') {\n try {\n localStorage.removeItem(CACHE_KEY);\n } catch {\n // ignore\n }\n }\n}\n","const SESSION_KEY = 'mushi_session_id';\n\nlet cachedSessionId: string | null = null;\n\nexport function getSessionId(): string {\n if (cachedSessionId) return cachedSessionId;\n\n if (typeof sessionStorage !== 'undefined') {\n const existing = sessionStorage.getItem(SESSION_KEY);\n if (existing) {\n cachedSessionId = existing;\n return existing;\n }\n }\n\n const id = generateSessionId();\n cachedSessionId = id;\n\n if (typeof sessionStorage !== 'undefined') {\n try {\n sessionStorage.setItem(SESSION_KEY, id);\n } catch {\n // sessionStorage unavailable\n }\n }\n\n return id;\n}\n\nfunction generateSessionId(): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).slice(2, 8);\n return `ms_${timestamp}_${random}`;\n}\n","export interface RateLimiterConfig {\n maxBurst?: number;\n refillRate?: number;\n refillIntervalMs?: number;\n}\n\nexport interface RateLimiter {\n tryConsume(): boolean;\n reset(): void;\n availableTokens(): number;\n}\n\nconst DEFAULT_MAX_BURST = 10;\nconst DEFAULT_REFILL_RATE = 1;\nconst DEFAULT_REFILL_INTERVAL_MS = 5_000;\n\nexport function createRateLimiter(config: RateLimiterConfig = {}): RateLimiter {\n const {\n maxBurst = DEFAULT_MAX_BURST,\n refillRate = DEFAULT_REFILL_RATE,\n refillIntervalMs = DEFAULT_REFILL_INTERVAL_MS,\n } = config;\n\n let tokens = maxBurst;\n let lastRefill = Date.now();\n\n function refill() {\n const now = Date.now();\n const elapsed = now - lastRefill;\n const refills = Math.floor(elapsed / refillIntervalMs);\n if (refills > 0) {\n tokens = Math.min(maxBurst, tokens + refills * refillRate);\n lastRefill = now;\n }\n }\n\n function tryConsume(): boolean {\n refill();\n if (tokens > 0) {\n tokens--;\n return true;\n }\n return false;\n }\n\n function reset(): void {\n tokens = maxBurst;\n lastRefill = Date.now();\n }\n\n function availableTokens(): number {\n refill();\n return tokens;\n }\n\n return { tryConsume, reset, availableTokens };\n}\n","export interface PiiScrubberConfig {\n emails?: boolean;\n phones?: boolean;\n creditCards?: boolean;\n ssns?: boolean;\n ipAddresses?: boolean;\n /**\n * Scrub vendor-shaped secret tokens (AWS access keys, Stripe keys,\n * Slack/GitHub PATs, OpenAI/Anthropic/Google keys, JWTs).\n *\n * Wave S1 / D-15: SDK parity with the server-side scrubber. The server\n * scrubs these on every LLM invocation; the SDK now scrubs them at\n * capture so they never hit the wire in the first place — important for\n * users who `console.log(stripeKey)` during dev and later ship bug\n * reports with the error text attached.\n */\n secretTokens?: boolean;\n /** IPv6 addresses. Defaults off for the same reason IPv4 does. */\n ipv6?: boolean;\n}\n\ninterface PiiPattern {\n key: keyof PiiScrubberConfig;\n regex: RegExp;\n replacement: string;\n}\n\n// Order matters: SSN → CC → vendor secrets → email → phone → IP. Secret\n// tokens are matched *before* the generic email/phone regex because some JWT\n// payloads contain `.` that could be mis-parsed as `xyz.abc.com`.\nconst ORDERED_PATTERNS: PiiPattern[] = [\n { key: 'ssns', regex: /\\b\\d{3}-\\d{2}-\\d{4}\\b/g, replacement: '[REDACTED_SSN]' },\n { key: 'creditCards', regex: /\\b(?:\\d[ -]*){12,18}\\d\\b/g, replacement: '[REDACTED_CC]' },\n\n // Vendor secret tokens — mirrors packages/server/.../pii-scrubber.ts exactly.\n { key: 'secretTokens', regex: /\\b(?:AKIA|ASIA)[0-9A-Z]{16}\\b/g, replacement: '[REDACTED_AWS_KEY]' },\n { key: 'secretTokens', regex: /(?:aws_secret_access_key|secret_access_key)[\"'\\s:=]+[A-Za-z0-9/+=]{40}\\b/gi, replacement: 'aws_secret_access_key=[REDACTED_AWS_SECRET]' },\n { key: 'secretTokens', regex: /\\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{24,}\\b/g, replacement: '[REDACTED_STRIPE_KEY]' },\n { key: 'secretTokens', regex: /\\bpk_(?:live|test)_[A-Za-z0-9]{24,}\\b/g, replacement: '[REDACTED_STRIPE_PK]' },\n { key: 'secretTokens', regex: /\\bxox[abpor]-[A-Za-z0-9-]{10,}\\b/g, replacement: '[REDACTED_SLACK_TOKEN]' },\n { key: 'secretTokens', regex: /\\bghp_[A-Za-z0-9]{36}\\b/g, replacement: '[REDACTED_GITHUB_PAT]' },\n { key: 'secretTokens', regex: /\\bgithub_pat_[A-Za-z0-9_]{80,}\\b/g, replacement: '[REDACTED_GITHUB_PAT]' },\n { key: 'secretTokens', regex: /\\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\\b/g, replacement: '[REDACTED_OPENAI_KEY]' },\n { key: 'secretTokens', regex: /\\bsk-ant-[A-Za-z0-9_-]{20,}\\b/g, replacement: '[REDACTED_ANTHROPIC_KEY]' },\n { key: 'secretTokens', regex: /\\bAIza[0-9A-Za-z_-]{35}\\b/g, replacement: '[REDACTED_GOOGLE_KEY]' },\n { key: 'secretTokens', regex: /\\beyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\b/g, replacement: '[REDACTED_JWT]' },\n\n { key: 'emails', regex: /\\b[A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z]{2,}\\b/g, replacement: '[REDACTED_EMAIL]' },\n { key: 'phones', regex: /(?:\\+\\d{1,3}[\\s.-])?\\(?\\d{2,4}\\)?[\\s.-]\\d{3,4}[\\s.-]\\d{3,4}\\b/g, replacement: '[REDACTED_PHONE]' },\n { key: 'ipAddresses', regex: /\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b/g, replacement: '[REDACTED_IP]' },\n { key: 'ipv6', regex: /\\b(?:[A-Fa-f0-9]{1,4}:){2,7}[A-Fa-f0-9]{0,4}\\b/g, replacement: '[REDACTED_IPV6]' },\n];\n\nconst DEFAULT_CONFIG: PiiScrubberConfig = {\n emails: true,\n phones: true,\n creditCards: true,\n ssns: true,\n ipAddresses: false,\n // Secret tokens default ON — if they leak into a bug report there's no\n // good reason to ship them to our servers. Cheaper to scrub client-side.\n secretTokens: true,\n ipv6: false,\n};\n\nexport function createPiiScrubber(config: PiiScrubberConfig = {}) {\n const merged = { ...DEFAULT_CONFIG, ...config };\n\n const activePatterns = ORDERED_PATTERNS.filter((p) => merged[p.key]);\n\n function scrub(text: string): string {\n if (!text) return text;\n let result = text;\n for (const { regex, replacement } of activePatterns) {\n result = result.replace(new RegExp(regex.source, regex.flags), replacement);\n }\n return result;\n }\n\n function scrubObject<T extends Record<string, unknown>>(obj: T, keys: string[]): T {\n const copy = { ...obj };\n for (const key of keys) {\n if (typeof copy[key] === 'string') {\n (copy as Record<string, unknown>)[key] = scrub(copy[key] as string);\n }\n }\n return copy;\n }\n\n return { scrub, scrubObject };\n}\n\nexport function scrubPii(text: string, config?: PiiScrubberConfig): string {\n return createPiiScrubber(config).scrub(text);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mushi-mushi/core",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Core types, API client, and pre-filter for Mushi Mushi SDK",
5
5
  "license": "MIT",
6
6
  "type": "module",