{"version":3,"sources":["../../src/host/declarative/evaluator.ts","../../src/host/declarative/interpreter.ts","../../src/host/worker/component-registry.ts","../../src/host/worker/offscreen.ts","../../src/bridge/mcp-error.ts","../../src/host/version-skew.ts","../../src/host/worker/bridge-envelopes.ts","../../src/host/worker/transport.ts","../../src/host/iframe/transport.ts"],"names":["KNOWN_OPERATORS","createElement","z"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Pure JsonLogic evaluator for the curated 14-operator subset declared in\n * `@ethisyscore/protocol`'s {@link KNOWN_OPERATORS}.\n *\n * The evaluator implements **only** the closed vocabulary:\n *\n * - Comparison: `==`, `!=`, `>`, `<`, `>=`, `<=`\n * - Boolean:    `and`, `or`, `not`\n * - Arithmetic: `+`, `-`, `*`, `/`, `%`\n * - Reference:  `var` (dot-path resolution against the supplied context)\n *\n * Design constraints:\n *\n * - **Pure function.** No I/O, no async, no `eval`, no `Function` construction.\n * - **Closed vocabulary.** Operators outside {@link KNOWN_OPERATORS} cause an\n *   immediate throw — there is no extension mechanism for plugin authors.\n * - **No function values.** Function-typed inputs are rejected at every depth.\n *   This keeps expression trees serialisable and free of host-side side effects.\n * - **Fail-loud.** Malformed expressions (e.g. an operator object with more or\n *   fewer than one key) throw rather than silently returning `undefined`.\n */\nimport { KNOWN_OPERATORS } from \"@ethisyscore/protocol\";\n\n/**\n * Resolution context for `var` references. Keys are looked up via dot-path\n * traversal; missing paths resolve to `undefined`.\n */\nexport type EvaluatorContext = Record<string, unknown>;\n\nconst KNOWN_OPERATOR_SET = new Set<string>(KNOWN_OPERATORS);\n\n/**\n * Evaluate a JsonLogic expression in the closed operator subset against the\n * supplied context.\n *\n * @param expr    The expression tree. Scalars (`string | number | boolean | null`)\n *                evaluate to themselves; arrays map element-wise; operator\n *                objects must contain exactly one key from\n *                {@link KNOWN_OPERATORS}.\n * @param context The context bag for `var` resolution. Dot-paths traverse\n *                nested objects.\n *\n * @throws Error if `expr` contains an unknown operator, a function-typed value,\n *         an operator object with a number of keys other than one, or any\n *         other unsupported shape (e.g. `undefined`, `Symbol`, `bigint`).\n */\nexport function evaluate(expr: unknown, context: EvaluatorContext): unknown\n{\n    // Literal scalars — return as-is.\n    if (expr === null)\n    {\n        return null;\n    }\n\n    const t = typeof expr;\n    if (t === \"string\" || t === \"number\" || t === \"boolean\")\n    {\n        return expr;\n    }\n\n    if (t === \"function\")\n    {\n        throw new Error(\"Function-typed values are not allowed in expressions.\");\n    }\n\n    if (Array.isArray(expr))\n    {\n        return expr.map((e) => evaluate(e, context));\n    }\n\n    if (t !== \"object\")\n    {\n        throw new Error(`Unsupported expression type: ${t}.`);\n    }\n\n    // Operator object — must have exactly one key from the closed vocabulary.\n    const obj = expr as Record<string, unknown>;\n    const keys = Object.keys(obj);\n    if (keys.length !== 1)\n    {\n        throw new Error(\n            `Expression object must have exactly one operator key (got ${keys.length}).`,\n        );\n    }\n\n    const op = keys[0];\n    if (!KNOWN_OPERATOR_SET.has(op))\n    {\n        throw new Error(`Unknown operator: ${op}.`);\n    }\n\n    const rawArgs = obj[op];\n\n    // `var` takes a single dot-path argument and does not recurse over its operand.\n    if (op === \"var\")\n    {\n        const path = typeof rawArgs === \"string\"\n            ? rawArgs\n            : Array.isArray(rawArgs) && typeof rawArgs[0] === \"string\"\n                ? rawArgs[0]\n                : \"\";\n        return resolveVar(path, context);\n    }\n\n    const evaluatedArgs: unknown[] = Array.isArray(rawArgs)\n        ? rawArgs.map((a) => evaluate(a, context))\n        : [evaluate(rawArgs, context)];\n\n    switch (op)\n    {\n        case \"==\": return evaluatedArgs[0] === evaluatedArgs[1];\n        case \"!=\": return evaluatedArgs[0] !== evaluatedArgs[1];\n        case \">\":  return (evaluatedArgs[0] as number) >  (evaluatedArgs[1] as number);\n        case \"<\":  return (evaluatedArgs[0] as number) <  (evaluatedArgs[1] as number);\n        case \">=\": return (evaluatedArgs[0] as number) >= (evaluatedArgs[1] as number);\n        case \"<=\": return (evaluatedArgs[0] as number) <= (evaluatedArgs[1] as number);\n        case \"and\": return evaluatedArgs.every(Boolean);\n        case \"or\":  return evaluatedArgs.some(Boolean);\n        case \"not\": return !evaluatedArgs[0];\n        case \"+\":   return evaluatedArgs.reduce((acc: number, n) => acc + (n as number), 0);\n        case \"-\":   return (evaluatedArgs[0] as number) - (evaluatedArgs[1] as number);\n        case \"*\":   return evaluatedArgs.reduce((acc: number, n) => acc * (n as number), 1);\n        case \"/\":   return safeDivide(evaluatedArgs[0] as number, evaluatedArgs[1] as number);\n        case \"%\":   return safeModulo(evaluatedArgs[0] as number, evaluatedArgs[1] as number);\n        default:\n            // Unreachable: gated by KNOWN_OPERATOR_SET above. Kept for exhaustiveness.\n            throw new Error(`Unknown operator: ${op}.`);\n    }\n}\n\n/**\n * Throw on zero or non-finite denominators in `/`. JavaScript silently coerces\n * `1 / 0` to `Infinity`; that value then leaks into host-rendered props and\n * surfaces as weird UI (or React `<input value={Infinity} />` warnings). The\n * closed evaluator's fail-loud contract demands a real error so the host\n * surface mount can fall back to an `ErrorState`.\n */\nfunction safeDivide(a: number, b: number): number\n{\n    if (b === 0 || !Number.isFinite(b))\n    {\n        throw new Error(\n            `Division by ${b === 0 ? \"zero\" : String(b)} is not allowed in the closed evaluator.`,\n        );\n    }\n    return a / b;\n}\n\n/**\n * Throw on zero or non-finite denominators in `%`. JavaScript silently coerces\n * `1 % 0` to `NaN`; that value would compare unequal to itself and corrupt\n * downstream comparisons in reactive rules.\n */\nfunction safeModulo(a: number, b: number): number\n{\n    if (b === 0 || !Number.isFinite(b))\n    {\n        throw new Error(\n            `Modulo by ${b === 0 ? \"zero\" : String(b)} is not allowed in the closed evaluator.`,\n        );\n    }\n    return a % b;\n}\n\n/**\n * Resolve a dot-separated path against the supplied context, returning the\n * leaf value or `undefined` if any segment is missing or non-traversable.\n *\n * Empty paths resolve to `undefined`.\n */\nfunction resolveVar(path: string, context: EvaluatorContext): unknown\n{\n    if (path === \"\")\n    {\n        return undefined;\n    }\n\n    const parts = path.split(\".\");\n    let curr: unknown = context;\n    for (const part of parts)\n    {\n        if (curr === null || typeof curr !== \"object\")\n        {\n            return undefined;\n        }\n        curr = (curr as Record<string, unknown>)[part];\n    }\n    return curr;\n}\n","import { createElement, type ReactElement, type ReactNode } from \"react\";\nimport type { ComponentRegistry } from \"./registry\";\nimport type { SduiNode } from \"./types\";\n\n/**\n * Walk a parsed SDUI tree and render it as a React element by looking up each\n * node's `type` in the supplied {@link ComponentRegistry}.\n *\n * The interpreter is purely structural:\n *\n * - It owns no UI styling, layout, or data fetching.\n * - It never reads `node.props` — props are forwarded opaquely to the host\n *   component, which owns interpretation per primitive.\n * - It does not evaluate `node.bindings` — reactive rules are handled in a\n *   separate task (E2.S2). For v1 the interpreter passes through the static\n *   tree only.\n *\n * Each child is given a stable React `key` derived from its position so that\n * React's reconciler can identify list items across renders. The key is a\n * sibling-local index; the registry consumer is responsible for opting into a\n * stable identity if it has a domain-meaningful `props.key`.\n *\n * @throws Error when `node.type` is not present in the registry. This is the\n * fail-loud behaviour required by the closed v1 vocabulary — unknown\n * primitives must not silently degrade.\n */\nexport function interpret(node: SduiNode, registry: ComponentRegistry): ReactElement\n{\n    const Component = registry[node.type];\n    if (!Component)\n    {\n        throw new Error(`Unknown SDUI primitive: ${String(node.type)}`);\n    }\n\n    const children: ReactNode[] | undefined = node.children?.map(\n        (child, index) => interpretChild(child, registry, index),\n    );\n\n    return createElement(Component, { props: node.props }, children);\n}\n\nfunction interpretChild(node: SduiNode, registry: ComponentRegistry, index: number): ReactElement\n{\n    const Component = registry[node.type];\n    if (!Component)\n    {\n        throw new Error(`Unknown SDUI primitive: ${String(node.type)}`);\n    }\n\n    const children: ReactNode[] | undefined = node.children?.map(\n        (child, childIndex) => interpretChild(child, registry, childIndex),\n    );\n\n    return createElement(Component, { props: node.props, key: index }, children);\n}\n","/**\n * Semantic component registry for Contract B (worker remote-runtime)\n * extensions.\n *\n * Worker-side plugin code references UI primitives by name — e.g.\n * `<DataTable />`, `<Drawer />`, `<CanvasSurface />`. The host owns rendering:\n * a {@link SemanticComponentRegistry} maps each name to a concrete component\n * type, and the Remote DOM host receiver consults the registry on every\n * worker-emitted mutation. The closed primitive vocabulary {@link CONTRACT_B_PRIMITIVES}\n * is intentionally narrow — adding a primitive is a coordinated host change so\n * plugins cannot extend the contract ad hoc.\n *\n * **Alignment with SDUI:** Where the Contract B name overlaps with the\n * `@ethisyscore/protocol` SDUI primitive vocabulary (`DataTable`, `Form`), the\n * names are identical to avoid synonym drift. SDUI's `Action` is intentionally\n * NOT reused — Contract B's interactive primitive is named `Button` so the\n * worker authoring API stays close to React DOM idioms. The two vocabularies\n * may converge as they evolve, but the host registries (Contract A SDUI vs\n * Contract B Semantic) remain distinct surfaces today.\n *\n * The registry is renderer-agnostic — the generic `TComponent` parameter is\n * whatever component type the host supplies (React `ComponentType` in\n * production; plain objects in tests). This keeps the registry free of a\n * React peer-dep requirement and lets tests assert behaviour without rendering.\n */\n\n// ─── Closed v1 vocabulary ─────────────────────────────────────────────────────\n\n/**\n * The mandatory Contract B (worker remote-runtime) semantic primitive vocabulary.\n *\n * Adding a primitive requires a coordinated host change + protocol bump —\n * plugins cannot extend this set. Each name has a host-supplied concrete\n * component (gogo-ui in production); the registry enforces 1:1 substitution.\n */\nexport const CONTRACT_B_PRIMITIVES = [\n    \"Button\",\n    \"DataTable\",\n    \"Form\",\n    \"EntityPicker\",\n    \"CommandBar\",\n    \"Drawer\",\n    \"Modal\",\n    \"CanvasSurface\",\n    \"WebGLSurface\",\n    // Phase 1 additions — mirror the vite-plugin's CONTRACT_B_SEMANTIC_PRIMITIVES\n    // list verbatim; drift between the two is caught by the\n    // contract-b.test.ts \"import-map-allowlist matches extension-runtime\n    // CONTRACT_B_PRIMITIVES\" test.\n    \"Card\",\n    \"Tabs\",\n    \"Select\",\n    \"Alert\",\n] as const;\n\n/**\n * Union type of the Contract B semantic primitive names — exported so callers\n * (tests, hosts) get full IntelliSense and compile-time exhaustiveness checks.\n */\nexport type SemanticPrimitiveName = typeof CONTRACT_B_PRIMITIVES[number];\n\nconst KNOWN_PRIMITIVE_SET: ReadonlySet<string> = new Set(CONTRACT_B_PRIMITIVES);\n\n// ─── Registry ─────────────────────────────────────────────────────────────────\n\n/**\n * Map of semantic primitive name → concrete component for Contract B\n * extensions.\n *\n * Construction is open-ended (callers register primitives one at a time) or\n * eager via {@link SemanticComponentRegistry.fromMap} which forces a complete\n * map up front and aborts if any primitive is missing.\n *\n * @typeParam TComponent - The host's concrete component shape. React hosts pass\n *                         `ComponentType<P>`; tests pass any tagged object.\n */\nexport class SemanticComponentRegistry<TComponent>\n{\n    private readonly entries = new Map<SemanticPrimitiveName, TComponent>();\n\n    /**\n     * Register a primitive → component binding.\n     *\n     * Throws if `name` is not in {@link CONTRACT_B_PRIMITIVES} (drift prevention)\n     * or if `name` is already registered (silent-override prevention).\n     */\n    public register(name: SemanticPrimitiveName, component: TComponent): void\n    {\n        if (!KNOWN_PRIMITIVE_SET.has(name))\n        {\n            throw new Error(\n                `[component-registry] unknown semantic primitive '${name}'. ` +\n                `Allowed: ${CONTRACT_B_PRIMITIVES.join(\", \")}.`,\n            );\n        }\n        if (this.entries.has(name))\n        {\n            throw new Error(\n                `[component-registry] primitive '${name}' is already registered. ` +\n                `Construct a new registry instead of overriding a binding.`,\n            );\n        }\n        this.entries.set(name, component);\n    }\n\n    /**\n     * Resolve a primitive name to its concrete component. Throws if the name is\n     * outside the Contract B vocabulary OR if the registry has no binding —\n     * silent fallthrough would let typos render blank components, which is\n     * worse than a fast failure for plugin authors.\n     */\n    public resolve(name: SemanticPrimitiveName): TComponent\n    {\n        if (!KNOWN_PRIMITIVE_SET.has(name))\n        {\n            throw new Error(\n                `[component-registry] unknown semantic primitive '${name}'. ` +\n                `Allowed: ${CONTRACT_B_PRIMITIVES.join(\", \")}.`,\n            );\n        }\n        const found = this.entries.get(name);\n        if (found === undefined)\n        {\n            const registered = this.listRegistered().join(\", \") || \"<none>\";\n            throw new Error(\n                `[component-registry] primitive '${name}' is not registered. ` +\n                `Registered primitives: ${registered}.`,\n            );\n        }\n        return found;\n    }\n\n    /**\n     * Cheap presence probe — never throws. Use this when callers want to\n     * fall back to a default component instead of erroring.\n     */\n    public has(name: SemanticPrimitiveName): boolean\n    {\n        return this.entries.has(name);\n    }\n\n    /**\n     * Sorted list of registered primitive names. Stable output makes registry\n     * diagnostics and snapshot tests deterministic.\n     */\n    public listRegistered(): SemanticPrimitiveName[]\n    {\n        return [...this.entries.keys()].sort() as SemanticPrimitiveName[];\n    }\n\n    /**\n     * Build a registry from a complete `Record<SemanticPrimitiveName, T>` map.\n     *\n     * The `Record` type forces TypeScript to refuse incomplete literals at\n     * compile time, AND we re-check at runtime so callers who type-erase the\n     * record (e.g., via `as any`) still get a fast failure.\n     */\n    public static fromMap<T>(map: Record<SemanticPrimitiveName, T>): SemanticComponentRegistry<T>\n    {\n        const registry = new SemanticComponentRegistry<T>();\n        const missing: SemanticPrimitiveName[] = [];\n        for (const name of CONTRACT_B_PRIMITIVES)\n        {\n            const component = (map as Partial<Record<SemanticPrimitiveName, T>>)[name];\n            if (component === undefined)\n            {\n                missing.push(name);\n                continue;\n            }\n            registry.register(name, component);\n        }\n        if (missing.length > 0)\n        {\n            throw new Error(\n                `[component-registry] fromMap is missing semantic primitive(s): ${missing.join(\", \")}.`,\n            );\n        }\n        return registry;\n    }\n}\n","/**\n * OffscreenCanvas transfer helpers + pointer/keyboard coalescing for\n * Contract B (worker remote-runtime) extensions.\n *\n * **Architecture.** Hosts that expose a {@link import(\"./component-registry\").SemanticComponentRegistry}'s\n * `CanvasSurface` / `WebGLSurface` primitive create a host-side `<canvas>`,\n * transfer control to the worker via {@link createOffscreenCanvasTransfer}, and\n * the plugin (running inside the worker realm) calls `offscreen.getContext()`\n * to render. The `<canvas>` is owned by the host DOM tree (so layout, theming,\n * and accessibility properties stay on the host side) but every pixel is\n * produced inside the worker — no per-frame `postMessage` cost, no main-thread\n * blocking.\n *\n * **Pointer / keyboard delivery.** Input events still originate on the host\n * `<canvas>`. To avoid spraying the worker port with per-event traffic the\n * host should wrap pointer-move / wheel / scroll callbacks in\n * {@link createInputEventCoalescer}, matching the trailing-edge coalescer\n * already documented in {@link import(\"./transport\").WorkerRemoteDomTransport}\n * (default 16ms ≈ one rAF). Keyboard events MUST use `discrete: true` —\n * coalescing them would drop characters.\n *\n * **Security.** No capability token, no MCP traffic, and no host-only globals\n * cross via the offscreen transfer. The transfer envelope is plain JSON with a\n * single `OffscreenCanvas` handle in the transfer list — the worker side\n * receives an opaque drawing surface and nothing else.\n */\n\n// ─── Public constants ────────────────────────────────────────────────────────\n\n/**\n * Default trailing-edge coalesce window for pointer / wheel / scroll events,\n * in milliseconds. 16ms ≈ one animation frame at 60Hz. Matches the default\n * documented in {@link import(\"./transport\").WorkerRemoteDomTransport}.\n */\nexport const DEFAULT_OFFSCREEN_COALESCE_MS = 16;\n\n// ─── Transfer envelope ───────────────────────────────────────────────────────\n\n/**\n * Host → worker envelope shape for an `OffscreenCanvas` transfer. Stable wire\n * contract — the worker side decodes by `type` and uses `surfaceId` to bind\n * the offscreen to the right host slot when a plugin renders multiple\n * canvases concurrently.\n */\nexport interface OffscreenTransferMessage\n{\n    type: \"ethisys:offscreen:transfer\";\n    surfaceId: string;\n    width: number;\n    height: number;\n    offscreen: OffscreenCanvas;\n}\n\n/**\n * Construction options for {@link createOffscreenCanvasTransfer}.\n */\nexport interface OffscreenCanvasTransferOptions\n{\n    /**\n     * The host-owned `<canvas>` element. Its `width` / `height` are captured\n     * before transfer so the worker sees the intended pixel dimensions even if\n     * the host element resizes later (host should send a separate resize\n     * message in that case).\n     */\n    canvas: HTMLCanvasElement;\n\n    /**\n     * Stable identifier the worker uses to route the offscreen to the matching\n     * surface slot. Typically the SDUI node id of the `CanvasSurface` /\n     * `WebGLSurface` primitive that the worker will draw into.\n     */\n    surfaceId: string;\n\n    /**\n     * Host-side postMessage function — typically the\n     * {@link import(\"./transport\").WorkerRemoteDomTransport}'s port-side\n     * `postMessage`. Tests inject a spy.\n     */\n    postMessage(message: OffscreenTransferMessage, transfer: Transferable[]): void;\n}\n\n/**\n * Successful transfer result. The caller retains a reference to the\n * `OffscreenCanvas` only for observability (e.g., to wire to the worker's\n * reply handshake) — direct rendering from the host side is forbidden because\n * control has already been transferred and any host-side draw call would\n * throw.\n */\nexport interface OffscreenCanvasTransferResult\n{\n    offscreen: OffscreenCanvas;\n}\n\n/**\n * Module-scoped WeakSet tracking canvases this SDK has already transferred.\n *\n * Stored OUTSIDE the DOM node deliberately:\n *\n * - Writing an SDK expando (e.g. `__ethisysOffscreenTransferred`) onto a host-\n *   owned `<canvas>` mutates state the host doesn't own. A WeakSet keeps the\n *   bookkeeping on the SDK side and lets the canvas object stay pristine.\n * - WeakSet entries are collected when the canvas is GC'd, so the guard does\n *   not leak memory for plugins that mount and unmount many surfaces.\n * - WeakSet membership is identity-based, so React/concurrent remount paths\n *   that re-use the SAME node still see \"already transferred\"; a fresh DOM\n *   node (always allocated by React when the key changes) is a fresh entry.\n */\nconst transferredCanvases: WeakSet<HTMLCanvasElement> = new WeakSet<HTMLCanvasElement>();\n\n/**\n * Transfer control of a host-owned `<canvas>` to the worker.\n *\n * Throws if:\n * - the environment lacks `HTMLCanvasElement.prototype.transferControlToOffscreen`\n *   (the helper does NOT silently fall back — Contract B clients must require\n *   the API and surface a clear error in unsupported browsers);\n * - the same canvas has already had control transferred (idempotency is the\n *   caller's responsibility — re-transferring would throw in the browser\n *   anyway, but we raise a clearer, diagnosable message ahead of that).\n */\nexport function createOffscreenCanvasTransfer(\n    options: OffscreenCanvasTransferOptions,\n): OffscreenCanvasTransferResult\n{\n    const { canvas, surfaceId, postMessage } = options;\n    const proto = HTMLCanvasElement.prototype as unknown as {\n        transferControlToOffscreen?: () => OffscreenCanvas;\n    };\n    if (typeof proto.transferControlToOffscreen !== \"function\")\n    {\n        throw new Error(\n            \"[offscreen-canvas] OffscreenCanvas is not supported in this environment. \" +\n            \"Contract B canvas surfaces require a browser with HTMLCanvasElement.transferControlToOffscreen.\",\n        );\n    }\n    if (transferredCanvases.has(canvas))\n    {\n        throw new Error(\n            `[offscreen-canvas] canvas already transferred (surfaceId='${surfaceId}'). ` +\n            \"Create a fresh <canvas> for each surface instead of re-transferring.\",\n        );\n    }\n\n    const offscreen = canvas.transferControlToOffscreen();\n    transferredCanvases.add(canvas);\n\n    const envelope: OffscreenTransferMessage = {\n        type: \"ethisys:offscreen:transfer\",\n        surfaceId,\n        width: canvas.width,\n        height: canvas.height,\n        offscreen,\n    };\n    postMessage(envelope, [offscreen]);\n\n    return { offscreen };\n}\n\n// ─── Coalescing ──────────────────────────────────────────────────────────────\n\n/**\n * Construction options for {@link createInputEventCoalescer}.\n */\nexport interface InputEventCoalescerOptions\n{\n    /**\n     * Coalesce window in milliseconds. Ignored when {@link discrete} is true.\n     * Defaults to {@link DEFAULT_OFFSCREEN_COALESCE_MS} (16ms — one rAF).\n     */\n    coalesceMs?: number;\n\n    /**\n     * When `true`, forward every payload synchronously without coalescing.\n     * Use this for keyboard events — coalescing would drop characters by\n     * collapsing multiple key strokes into one trailing delivery.\n     */\n    discrete?: boolean;\n}\n\n/**\n * Build a trailing-edge input-event coalescer. The pattern matches\n * {@link import(\"./transport\").WorkerRemoteDomTransport.createCoalescer} —\n * factored out here so OffscreenCanvas callers don't need to construct a full\n * transport just to coalesce pointer-move events.\n *\n * Trailing-edge semantics: every burst within a coalesce window collapses to\n * a single delivery carrying the **last** payload seen in the window. A new\n * payload arriving after a window has flushed starts a fresh window.\n */\nexport function createInputEventCoalescer<T>(\n    sink: (payload: T) => void,\n    options: InputEventCoalescerOptions = {},\n): (payload: T) => void\n{\n    if (options.discrete === true)\n    {\n        // Discrete mode: pass through unchanged. Keyboard input belongs here.\n        return (payload: T) =>\n        {\n            sink(payload);\n        };\n    }\n    const coalesceMs = options.coalesceMs ?? DEFAULT_OFFSCREEN_COALESCE_MS;\n    let pending: T | undefined;\n    let pendingSet = false;\n    let timer: ReturnType<typeof setTimeout> | undefined;\n\n    const flush = (): void =>\n    {\n        timer = undefined;\n        if (!pendingSet)\n        {\n            return;\n        }\n        const value = pending as T;\n        pending = undefined;\n        pendingSet = false;\n        sink(value);\n    };\n\n    return (payload: T) =>\n    {\n        pending = payload;\n        pendingSet = true;\n        if (timer === undefined)\n        {\n            timer = setTimeout(flush, coalesceMs);\n        }\n    };\n}\n","/**\n * A machine-readable classification for an MCP call that failed, carried across the host/plugin\n * bridge alongside the human-readable message.\n *\n * ## Why this exists\n *\n * The bridge used to reduce every failure to `err.message`, a bare string. A plugin therefore could\n * not tell \"you lack permission for this tool\" from \"the host is unreachable\" without matching on\n * host error prose, and the practical consequence was that plugins swallowed *all* failures into a\n * successful empty result to keep a permission denial from looking like a crash. That turns a\n * transient outage into \"you have no connectors\" - a false statement about the user's data, and one\n * that also suppresses the query layer's retry.\n *\n * A closed vocabulary lets the plugin branch on the one case it wants to tolerate and rethrow the\n * rest.\n *\n * ## Deliberately small, and deliberately not HTTP\n *\n * These are the distinctions a *caller* acts on differently, not a mirror of any status enum. Codes\n * that would prompt the same handling are folded together, because a vocabulary nobody can apply is\n * just a wider surface to get wrong. `unavailable` and `timeout` stay separate only because retry\n * policy differs between them.\n */\nexport type McpErrorCode =\n    /** The caller is not authenticated, or its token expired. Re-authentication may fix it. */\n    | \"unauthorized\"\n    /** Authenticated, but not permitted this tool or resource. Retrying will not help. */\n    | \"forbidden\"\n    /** The tool, resource, or addressed entity does not exist. */\n    | \"not_found\"\n    /** The arguments were rejected. A caller bug, or stale client-side validation. */\n    | \"invalid_request\"\n    /** A concurrency or state conflict - a row version, or a duplicate. */\n    | \"conflict\"\n    /** Throttled. Retry later, with backoff. */\n    | \"rate_limited\"\n    /** The call did not complete in time. Safe to retry only if the operation is idempotent. */\n    | \"timeout\"\n    /** The host or an upstream dependency is down. Retryable. */\n    | \"unavailable\"\n    /** Anything else, including an unclassifiable failure. The default - never a claim. */\n    | \"internal\";\n\n/**\n * Every valid {@link McpErrorCode}. Used to validate a code arriving over the wire: an unknown\n * string is downgraded rather than trusted, so a newer host cannot make an older plugin branch on a\n * code it has never heard of.\n */\nexport const MCP_ERROR_CODES: readonly McpErrorCode[] = [\n    \"unauthorized\",\n    \"forbidden\",\n    \"not_found\",\n    \"invalid_request\",\n    \"conflict\",\n    \"rate_limited\",\n    \"timeout\",\n    \"unavailable\",\n    \"internal\",\n];\n\n/** True when `value` is a code this build understands. */\nexport function isMcpErrorCode(value: unknown): value is McpErrorCode\n{\n    return typeof value === \"string\"\n        && (MCP_ERROR_CODES as readonly string[]).includes(value);\n}\n\n/**\n * Codes a caller can retry without changing anything about the request. Exposed so retry policy is\n * decided once here rather than re-derived, subtly differently, at each call site.\n *\n * `unauthorized` is absent on purpose: a retry only helps once something else has refreshed the\n * token, which is a different action from retrying.\n */\nconst RETRYABLE: readonly McpErrorCode[] = [\"rate_limited\", \"timeout\", \"unavailable\"];\n\n/** True when the failure is worth retrying as-is. */\nexport function isRetryableMcpErrorCode(code: McpErrorCode): boolean\n{\n    return RETRYABLE.includes(code);\n}\n\n/**\n * An MCP call rejected by the host, carrying its {@link McpErrorCode}.\n *\n * `name` stays `\"McpHostError\"` - the string the bridge has always set - so code that matches on the\n * name keeps working. Prefer {@link isMcpToolError}, which survives a name change and works across\n * realm boundaries where `instanceof` does not.\n */\nexport class McpToolError extends Error\n{\n    /** Machine-readable classification. `internal` when the host sent none. */\n    public readonly code: McpErrorCode;\n\n    /**\n     * Marks the instance for {@link isMcpToolError}. A structural marker rather than a prototype\n     * check because the error can be constructed in one bundle and inspected in another, where\n     * `instanceof` compares two different class objects and answers false.\n     */\n    public readonly isMcpToolError = true as const;\n\n    public constructor(message: string, code: McpErrorCode = \"internal\")\n    {\n        super(message);\n        this.name = \"McpHostError\";\n        this.code = code;\n    }\n\n    /** True when this failure is worth retrying unchanged. */\n    public get retryable(): boolean\n    {\n        return isRetryableMcpErrorCode(this.code);\n    }\n}\n\n/** True when `value` is an {@link McpToolError}, including one from another bundle. */\nexport function isMcpToolError(value: unknown): value is McpToolError\n{\n    return value instanceof McpToolError\n        || (value !== null\n            && typeof value === \"object\"\n            && (value as { isMcpToolError?: unknown }).isMcpToolError === true\n            && isMcpErrorCode((value as { code?: unknown }).code));\n}\n\n/**\n * Maps an HTTP status onto a code. Split out because host MCP clients are commonly HTTP clients, so\n * a status is the classification most of them already have.\n *\n * Unrecognised statuses (including every 2xx and 3xx, which should not be reaching an error path)\n * yield `internal` rather than a guess.\n */\nexport function mcpErrorCodeFromHttpStatus(status: number): McpErrorCode\n{\n    switch (status)\n    {\n        case 401:\n            return \"unauthorized\";\n        case 403:\n            return \"forbidden\";\n        case 404:\n            return \"not_found\";\n        case 400:\n        case 422:\n            return \"invalid_request\";\n        case 409:\n        case 412:\n            return \"conflict\";\n        case 429:\n            return \"rate_limited\";\n        case 408:\n        case 504:\n            return \"timeout\";\n        case 502:\n        case 503:\n            return \"unavailable\";\n        default:\n            // Everything unmapped, 500 included. `internal` is the honest answer for a status this\n            // vocabulary has no distinct handling for - inventing a closer-looking code would tell\n            // the caller something the status does not actually say.\n            return \"internal\";\n    }\n}\n\n/**\n * Derives a code from a host MCP client's RETURNED failure, as opposed to a thrown one.\n *\n * Both paths exist and both have to be covered. A client that throws is handled by\n * {@link classifyHostError}; a client that reports failure as `{ ok: false, error, status }` - the\n * common shape for anything wrapping HTTP - comes through here. Covering only the throw path leaves\n * the majority of real failures arriving as `internal`, which is the same blindness the code was\n * added to remove.\n *\n * Returns `undefined` for a successful response, so a caller can spread it without putting a\n * meaningless code on the happy path.\n */\nexport function classifyHostResponse(response: {\n    readonly ok: boolean;\n    readonly status?: number;\n    readonly mcpErrorCode?: unknown;\n}): McpErrorCode | undefined\n{\n    if (response.ok)\n    {\n        return undefined;\n    }\n\n    // Same precedence as the thrown path: an explicit code from the client beats the transport's\n    // status, and neither is ever inferred from the message.\n    if (isMcpErrorCode(response.mcpErrorCode))\n    {\n        return response.mcpErrorCode;\n    }\n\n    return typeof response.status === \"number\"\n        ? mcpErrorCodeFromHttpStatus(response.status)\n        : \"internal\";\n}\n\n/**\n * Derives a code from an arbitrary thrown value, for the host side of the bridge.\n *\n * Precedence, most explicit first:\n *\n * 1. An `mcpErrorCode` property holding a known code. The intended contract: a host MCP client that\n *    knows why a call failed says so directly.\n * 2. A numeric `status` / `statusCode`, mapped by {@link mcpErrorCodeFromHttpStatus}. Covers the\n *    HTTP clients that already carry one without asking every host to adopt the field above.\n * 3. `name === \"AbortError\"` / `\"TimeoutError\"`, which is how the platform's own aborts surface.\n * 4. `internal`.\n *\n * **Never infers from the message.** Matching prose would make the classification depend on wording\n * nobody treats as a contract, and it would silently reclassify itself the day someone improves an\n * error string. An unclassifiable failure is `internal`, which is honest.\n */\nexport function classifyHostError(err: unknown): McpErrorCode\n{\n    if (err === null || typeof err !== \"object\")\n    {\n        return \"internal\";\n    }\n\n    const candidate = err as {\n        mcpErrorCode?: unknown;\n        status?: unknown;\n        statusCode?: unknown;\n        name?: unknown;\n    };\n\n    if (isMcpErrorCode(candidate.mcpErrorCode))\n    {\n        return candidate.mcpErrorCode;\n    }\n\n    const status = typeof candidate.status === \"number\"\n        ? candidate.status\n        : typeof candidate.statusCode === \"number\" ? candidate.statusCode : undefined;\n\n    if (status !== undefined)\n    {\n        return mcpErrorCodeFromHttpStatus(status);\n    }\n\n    if (candidate.name === \"AbortError\" || candidate.name === \"TimeoutError\")\n    {\n        return \"timeout\";\n    }\n\n    return \"internal\";\n}\n","/**\n * Version-skew detection for host-side MCP calls.\n *\n * A mounted plugin surface holds a capability token minted against the extension version that\n * was active when the page loaded. When the install is upgraded underneath it, the kernel stops\n * honouring that token: it rejects with `401` and\n * `X-Capability-Token-Rejection-Reason: ExtensionVersionMismatch`. Every other rejection reason is\n * terminal for the surface, but this one is recoverable — remounting against the new version fixes\n * it — which is why it is worth telling apart from an ordinary auth failure.\n *\n * Two signals are handled here, and the difference matters:\n *\n * - **Reactive**, from a rejection: the call already failed. Recovery costs the user a round trip\n *   and whatever in-page state the remount discards.\n * - **Proactive**, from the version stamped on a *successful* response: the surface learns the\n *   install moved while it is still working, and can remount at a moment of its choosing. Reads\n *   keep succeeding until the token's own version check catches up, so this is the path that\n *   avoids a visible failure altogether.\n *\n * The interpretation lives here rather than in each host application so that \"which reason means\n * remount\" is decided once, in code that can be tested, instead of being re-derived by every\n * embedder from HTTP trivia.\n */\n\n/** Response header naming the extension version a request was served as. */\nexport const EXTENSION_VERSION_HEADER = \"x-extension-version\";\n\n/** Response header naming the version a rejected surface must remount at. */\nexport const EXTENSION_ACTIVE_VERSION_HEADER = \"x-extension-active-version\";\n\n/** Response header carrying the kernel's structured capability-token rejection reason. */\nexport const CAPABILITY_REJECTION_REASON_HEADER = \"x-capability-token-rejection-reason\";\n\n/** The one rejection reason a surface can resolve by remounting. */\nexport const VERSION_MISMATCH_REASON = \"extensionversionmismatch\";\n\n/**\n * What the host observed about an MCP response, beyond its payload. Both fields are optional\n * because the {@link McpHttpClient} contract predates them: an implementation that does not supply\n * them simply never reports skew, which is the previous behaviour rather than a new failure.\n */\nexport interface McpResponseMetadata\n{\n    /** HTTP status code, when the implementation surfaces it. */\n    readonly status?: number;\n\n    /** Response headers. Looked up case-insensitively, so any casing is fine. */\n    readonly headers?: Readonly<Record<string, string>>;\n}\n\n/**\n * How skew came to light.\n *\n * - `\"rejection\"` — a call was refused because the surface's token is stale. Recovery costs a round\n *   trip and whatever in-page state the remount discards.\n * - `\"response-stamp\"` — a call succeeded, but the install has moved on. The surface can remount\n *   before anything fails, so this is the path worth preferring.\n */\nexport type VersionSkewSource = \"rejection\" | \"response-stamp\";\n\n/**\n * The result of one host-side MCP call: the payload the plugin asked for, plus whatever the host\n * observed about the response itself.\n *\n * Named rather than inlined at the {@link McpHttpClient} declaration so hosts have a type to\n * implement against, and so the skew detector and the transports agree on one shape instead of\n * three structurally-compatible copies drifting apart.\n */\nexport interface McpHttpResponse extends McpResponseMetadata\n{\n    /** Whether the call succeeded. */\n    readonly ok: boolean;\n\n    /** The response payload, shaped by the request kind. */\n    readonly data?: unknown;\n\n    /** Failure message when {@link ok} is false. */\n    readonly error?: string;\n\n    /**\n     * Optional machine-readable classification for a failure, mirroring the `mcpErrorCode` a client\n     * can attach to a thrown error. Set it when the client knows why the call failed more precisely\n     * than the status says - it takes precedence over {@link status} when the bridge classifies the\n     * reply. Values outside the published vocabulary are ignored rather than forwarded.\n     */\n    readonly mcpErrorCode?: string;\n}\n\n/** A detected mismatch between the version a surface is running and the version now installed. */\nexport interface VersionSkew\n{\n    /**\n     * The version to remount at, when the kernel named it. Undefined means skew is certain but the\n     * target is not — the surface should re-read the extension descriptor rather than guess.\n     */\n    readonly activeVersion?: string;\n\n    /** Which signal detected the skew. */\n    readonly detectedFrom: VersionSkewSource;\n}\n\n/**\n * Case-insensitive header read. Hosts pass headers through from whatever HTTP client they use, and\n * casing varies by implementation (`fetch` lower-cases, some proxies and Node clients do not), so\n * matching exactly would make detection depend on the embedder's plumbing.\n */\nfunction readHeader(headers: Readonly<Record<string, string>> | undefined, name: string): string | undefined\n{\n    if (!headers)\n    {\n        return undefined;\n    }\n    const direct = headers[name];\n    if (direct !== undefined)\n    {\n        return direct;\n    }\n    const lowered = name.toLowerCase();\n    for (const key of Object.keys(headers))\n    {\n        if (key.toLowerCase() === lowered)\n        {\n            return headers[key];\n        }\n    }\n    return undefined;\n}\n\nfunction trimmedOrUndefined(value: string | undefined): string | undefined\n{\n    const trimmed = value?.trim();\n    return trimmed !== undefined && trimmed.length > 0 ? trimmed : undefined;\n}\n\n/**\n * Decides whether an MCP response means the surface is running against a version that is no longer\n * installed.\n *\n * @param response What the host observed: whether the call succeeded, plus any status and headers.\n * @param mountedExtensionVersion The version this surface mounted at. Required for proactive\n * detection — without it a response stamp cannot be compared to anything, and only rejections are\n * detectable.\n * @returns The skew, or `null` when the response says nothing about versions.\n */\nexport function detectVersionSkew(\n    response: McpHttpResponse,\n    mountedExtensionVersion?: string): VersionSkew | null\n{\n    const reason = trimmedOrUndefined(readHeader(response.headers, CAPABILITY_REJECTION_REASON_HEADER));\n    if (reason !== undefined && reason.toLowerCase() === VERSION_MISMATCH_REASON)\n    {\n        return {\n            activeVersion: trimmedOrUndefined(readHeader(response.headers, EXTENSION_ACTIVE_VERSION_HEADER)),\n            detectedFrom: \"rejection\",\n        };\n    }\n\n    // Proactive: only meaningful on a call that worked. A failed response's stamp says nothing\n    // about the install having moved — the failure has its own cause, and treating it as skew\n    // would remount the surface on every unrelated error.\n    if (!response.ok)\n    {\n        return null;\n    }\n\n    const mounted = trimmedOrUndefined(mountedExtensionVersion);\n    const served = trimmedOrUndefined(readHeader(response.headers, EXTENSION_VERSION_HEADER));\n    if (mounted === undefined || served === undefined || served === mounted)\n    {\n        return null;\n    }\n\n    return { activeVersion: served, detectedFrom: \"response-stamp\" };\n}\n","/**\n * Wire-shape constants and type guards for host→plugin bridge push messages\n * (WI 4858 sub-plan 2). These types ride the existing MessagePort channel\n * alongside the `ethisys:mcp:*` and `ethisys:remotedom` envelopes — the\n * `type` discriminant keeps them fully separate at the dispatch site.\n *\n * The host posts bridge pushes through `WorkerRemoteDomTransport.hostPort`;\n * the plugin side reads them in `createPortBridgeClient` (plugin-ui package).\n * In-realm (Tier T) plugins use `InMemoryBridgeTransport` which calls the\n * subscriber callbacks directly — no serialisation needed.\n */\n\n// ── Type constants ───────────────────────────────────────────────────────────\n\nexport const BRIDGE_PUSH_THEME       = \"ethisys:bridge:theme\"          as const;\nexport const BRIDGE_PUSH_LOCALE      = \"ethisys:bridge:locale\"         as const;\nexport const BRIDGE_PUSH_DENSITY     = \"ethisys:bridge:density\"        as const;\nexport const BRIDGE_PUSH_A11Y        = \"ethisys:bridge:a11y\"           as const;\nexport const BRIDGE_NAV_PUSH         = \"ethisys:bridge:nav\"            as const;\nexport const BRIDGE_CHROME_REQUEST   = \"ethisys:bridge:chrome:request\" as const;\nexport const BRIDGE_CHROME_RESPONSE  = \"ethisys:bridge:chrome:response\" as const;\nexport const BRIDGE_SESSION_TOKEN_PUSH = \"ethisys:bridge:token\"        as const;\nexport const BRIDGE_LIFECYCLE_EVENT  = \"ethisys:bridge:lifecycle\"      as const;\nexport const BRIDGE_A11Y_ANNOUNCE    = \"ethisys:bridge:a11y:announce\"  as const;\n\n// ── Envelope shapes ──────────────────────────────────────────────────────────\n\n/** Theme push: host → plugin whenever the host theme changes. */\nexport interface BridgePushThemeEnvelope {\n  readonly type: typeof BRIDGE_PUSH_THEME;\n  /** \"light\" | \"dark\" | \"high-contrast\" */\n  readonly mode: string;\n  /** Flat design-token map (CSS-variable-name → value). May be empty. */\n  readonly tokens: Readonly<Record<string, string>>;\n}\n\n/** Locale push: host → plugin whenever the active locale changes. */\nexport interface BridgePushLocaleEnvelope {\n  readonly type: typeof BRIDGE_PUSH_LOCALE;\n  /** BCP 47 tag, e.g. \"en-GB\". */\n  readonly locale: string;\n  /** \"ltr\" | \"rtl\" */\n  readonly dir: \"ltr\" | \"rtl\";\n}\n\n/** Density push: host → plugin when the UI density preference changes. */\nexport interface BridgePushDensityEnvelope {\n  readonly type: typeof BRIDGE_PUSH_DENSITY;\n  /** \"comfortable\" | \"compact\" */\n  readonly density: string;\n}\n\n/** A11y push: host → plugin when accessibility prefs change. */\nexport interface BridgePushA11yEnvelope {\n  readonly type: typeof BRIDGE_PUSH_A11Y;\n  readonly reducedMotion: boolean;\n  readonly highContrast: boolean;\n}\n\n/** Nav push: host → plugin when the SPA location changes. */\nexport interface BridgeNavPushEnvelope {\n  readonly type: typeof BRIDGE_NAV_PUSH;\n  /** Current SPA path (pathname + search). */\n  readonly path: string;\n  /** `window.history.length` at the time of push. */\n  readonly historyLength: number;\n}\n\n/** Plugin → host: request a chrome action (e.g. toast, modal). */\nexport interface BridgeChromeRequestEnvelope {\n  readonly type: typeof BRIDGE_CHROME_REQUEST;\n  /** Correlation id — matched against the response. */\n  readonly id: string;\n  /** \"toast\" | \"confirm\" | \"openUrl\" */\n  readonly action: string;\n  readonly payload: Readonly<Record<string, unknown>>;\n}\n\n/** Host → plugin: response to a chrome request. */\nexport interface BridgeChromeResponseEnvelope {\n  readonly type: typeof BRIDGE_CHROME_RESPONSE;\n  readonly id: string;\n  readonly ok: boolean;\n  readonly result?: unknown;\n  readonly error?: string;\n}\n\n/** Host → plugin: push a short-lived frontend-session token. */\nexport interface BridgeSessionTokenPushEnvelope {\n  readonly type: typeof BRIDGE_SESSION_TOKEN_PUSH;\n  /** Opaque JWT string — audience-restricted to the plugin's own backend. */\n  readonly token: string;\n  /** Absolute epoch-ms at which the token expires. Refresh fires 30 s before. */\n  readonly expiresAtMs: number;\n}\n\n/** Host ↔ plugin lifecycle event. */\nexport type BridgeLifecyclePhase = \"load\" | \"ready\" | \"error\" | \"unload\";\n\nexport interface BridgeLifecycleEventEnvelope {\n  readonly type: typeof BRIDGE_LIFECYCLE_EVENT;\n  readonly phase: BridgeLifecyclePhase;\n  /** Present when phase === \"error\". */\n  readonly message?: string;\n}\n\n/** Plugin → host: a11y live-region announcement request. */\nexport interface BridgeA11yAnnounceEnvelope {\n  readonly type: typeof BRIDGE_A11Y_ANNOUNCE;\n  readonly message: string;\n  /** \"polite\" | \"assertive\" */\n  readonly politeness: \"polite\" | \"assertive\";\n}\n\n// ── Type guards ──────────────────────────────────────────────────────────────\n\nfunction isObj(v: unknown): v is Record<string, unknown> {\n  return v !== null && typeof v === \"object\";\n}\n\nexport function isBridgePushTheme(v: unknown): v is BridgePushThemeEnvelope {\n  return isObj(v) && v[\"type\"] === BRIDGE_PUSH_THEME && typeof v[\"mode\"] === \"string\";\n}\n\nexport function isBridgePushLocale(v: unknown): v is BridgePushLocaleEnvelope {\n  return isObj(v) && v[\"type\"] === BRIDGE_PUSH_LOCALE && typeof v[\"locale\"] === \"string\";\n}\n\nexport function isBridgePushDensity(v: unknown): v is BridgePushDensityEnvelope {\n  return isObj(v) && v[\"type\"] === BRIDGE_PUSH_DENSITY && typeof v[\"density\"] === \"string\";\n}\n\nexport function isBridgePushA11y(v: unknown): v is BridgePushA11yEnvelope {\n  return isObj(v) && v[\"type\"] === BRIDGE_PUSH_A11Y\n    && typeof v[\"reducedMotion\"] === \"boolean\"\n    && typeof v[\"highContrast\"] === \"boolean\";\n}\n\nexport function isBridgeNavPush(v: unknown): v is BridgeNavPushEnvelope {\n  return isObj(v) && v[\"type\"] === BRIDGE_NAV_PUSH && typeof v[\"path\"] === \"string\";\n}\n\nexport function isBridgeChromeRequest(v: unknown): v is BridgeChromeRequestEnvelope {\n  return isObj(v) && v[\"type\"] === BRIDGE_CHROME_REQUEST && typeof v[\"id\"] === \"string\";\n}\n\nexport function isBridgeChromeResponse(v: unknown): v is BridgeChromeResponseEnvelope {\n  return isObj(v) && v[\"type\"] === BRIDGE_CHROME_RESPONSE && typeof v[\"id\"] === \"string\";\n}\n\nexport function isBridgeSessionTokenPush(v: unknown): v is BridgeSessionTokenPushEnvelope {\n  return isObj(v) && v[\"type\"] === BRIDGE_SESSION_TOKEN_PUSH\n    && typeof v[\"token\"] === \"string\"\n    && typeof v[\"expiresAtMs\"] === \"number\";\n}\n\nexport function isBridgeLifecycleEvent(v: unknown): v is BridgeLifecycleEventEnvelope {\n  return isObj(v) && v[\"type\"] === BRIDGE_LIFECYCLE_EVENT && typeof v[\"phase\"] === \"string\";\n}\n\nexport function isBridgeA11yAnnounce(v: unknown): v is BridgeA11yAnnounceEnvelope {\n  return isObj(v) && v[\"type\"] === BRIDGE_A11Y_ANNOUNCE && typeof v[\"message\"] === \"string\";\n}\n","/**\n * Worker-side host transport for `renderMode: remote-runtime` extensions\n * (Contract B). Owns the lifecycle of:\n *\n *   1. A path-pinned module `Worker` spawned from a host-issued bootstrap URL.\n *   2. A `MessagePort`-based RPC channel (handed to the worker on spawn).\n *   3. A Shopify Remote DOM root receiver — wired here so the worker's UI\n *      tree mounts into a host React tree.\n *   4. Event coalescing (default ≤16ms, one rAF) for high-frequency input\n *      events before they cross the port.\n *   5. MCP tool/resource calls forwarded through the port — but **the\n *      capability token never crosses the boundary**. The token is bound\n *      to the worker scope on the HOST side: the host transport intercepts\n *      the plugin's MCP request, attaches the token to the outbound HTTP\n *      call, and forwards ONLY the response payload back through the port.\n *\n * This module is intentionally framework-thin: callers wire `mount(root)`\n * onto a React tree (typically inside a `<WorkerSurfaceMount>`), and the\n * Remote DOM receiver is responsible for translating worker-side\n * RemoteRoot mutations into host-side component renders.\n */\n\nimport { createOffscreenCanvasTransfer } from \"./offscreen\";\nimport { classifyHostError, classifyHostResponse } from \"../../bridge/mcp-error\";\nimport type { UploadDocumentMeta } from \"../../plugin/transport\";\nimport {\n  detectVersionSkew,\n  type McpHttpResponse,\n  type VersionSkew,\n} from \"../version-skew\";\nimport {\n  BRIDGE_PUSH_THEME,\n  BRIDGE_PUSH_LOCALE,\n  BRIDGE_PUSH_DENSITY,\n  BRIDGE_PUSH_A11Y,\n  BRIDGE_NAV_PUSH,\n  BRIDGE_CHROME_REQUEST,\n  BRIDGE_A11Y_ANNOUNCE,\n  BRIDGE_LIFECYCLE_EVENT,\n  type BridgePushThemeEnvelope,\n  type BridgePushLocaleEnvelope,\n  type BridgePushDensityEnvelope,\n  type BridgePushA11yEnvelope,\n  type BridgeNavPushEnvelope,\n} from \"./bridge-envelopes\";\n\n// ─── Public types ─────────────────────────────────────────────────────────────\n\n/**\n * Structural subset of the DOM `Worker` interface that the transport needs.\n * Tests inject a fake; production callers pass the global `Worker`.\n */\nexport interface WorkerLike\n{\n    onmessage: ((ev: MessageEvent) => void) | null;\n    onerror: ((ev: ErrorEvent) => void) | null;\n    onmessageerror: ((ev: MessageEvent) => void) | null;\n    postMessage(message: unknown, transfer?: Transferable[]): void;\n    terminate(): void;\n}\n\n/**\n * Constructor signature compatible with the DOM `Worker` constructor. The\n * `workerCtor` option exists exclusively so tests can swap in a fake — in\n * production the caller passes the global `Worker`.\n */\nexport type WorkerCtor = new (url: string | URL, options?: WorkerOptions) => WorkerLike;\n\n/**\n * Discriminated union of MCP fetch shapes the host transport issues. The\n * `capabilityToken` is attached on the host side ONLY — it is never present\n * in any message that crosses the worker port.\n */\nexport type McpHttpRequest =\n    | {\n        kind: \"invokeTool\";\n        name: string;\n        args: unknown;\n        capabilityToken: string;\n        signal?: AbortSignal;\n    }\n    | {\n        kind: \"getResource\";\n        uri: string;\n        capabilityToken: string;\n        signal?: AbortSignal;\n    }\n    | McpUploadRequest;\n\n/**\n * Host-side document-upload request (a `kind` of {@link McpHttpRequest}).\n * Carries the transferred bytes + advisory metadata plus the host-minted\n * capability token. As with the other request kinds, the token is attached on\n * the HOST side only and never crosses the worker port. Implementations POST\n * the bytes as `application/octet-stream` (metadata in `x-cc-*` headers) to the\n * kernel's capability-token-authed document-upload route; `data` on success is\n * an {@link UploadDocumentResult}.\n */\nexport interface McpUploadRequest\n{\n    kind: \"uploadDocument\";\n    meta: UploadDocumentMeta;\n    buffer: ArrayBuffer;\n    capabilityToken: string;\n    signal?: AbortSignal;\n}\n\n/**\n * Host-side HTTP client for MCP calls. Implementations are responsible for\n * carrying the supplied `capabilityToken` on the outbound request (typically\n * via `Authorization: Bearer` / `PluginCap`). The `uploadDocument` kind is\n * additive — implementations that predate it fall through to their unknown-kind\n * branch until updated (the FE upload hook is inert until the host handles it).\n */\nexport interface McpHttpClient\n{\n    /**\n     * Performs the call. The response's `status` and `headers` are optional and additive: supplying\n     * them is what enables version-skew detection (see {@link detectVersionSkew}), and an\n     * implementation that omits them behaves exactly as before rather than failing.\n     */\n    fetch(request: McpHttpRequest): Promise<McpHttpResponse>;\n}\n\n/**\n * Construction options for {@link WorkerRemoteDomTransport}.\n */\nexport interface WorkerRemoteDomTransportOptions\n{\n    /**\n     * Canonical host-origin URL for the worker bootstrap script. This MUST\n     * be supplied by the host — never built from user input or extension\n     * manifest values — so the worker spawn is path-pinned.\n     */\n    bootstrapUrl: string;\n\n    /**\n     * Mints (or fetches a cached) capability token. The host transport\n     * resolves this for each outbound MCP HTTP call. The token NEVER leaves\n     * host scope — plugin code (the worker side) cannot read it.\n     */\n    capabilityToken: () => Promise<string>;\n\n    /**\n     * Host-side MCP HTTP client. The transport bridges port-side plugin\n     * MCP requests to this client and returns only the response payload\n     * back through the port.\n     */\n    mcpClient: McpHttpClient;\n\n    /**\n     * The extension version this surface mounted at. Supplying it enables *proactive* skew\n     * detection: a successful response stamped with a different version means the install moved\n     * while the surface is still working, so it can remount before anything fails. Without it only\n     * outright rejections are detectable, which is a worse experience but not a broken one.\n     */\n    mountedExtensionVersion?: string;\n\n    /**\n     * Called at most once, when this surface is found to be running against a version that is no\n     * longer installed. The host is expected to remount the surface (which re-mints a capability\n     * token against the new version); the transport itself does not retry, because the pending call\n     * belongs to a page that is about to be replaced.\n     */\n    onVersionSkew?: (skew: VersionSkew) => void;\n\n    /**\n     * Injectable Worker constructor (tests use a fake). Defaults to the\n     * global `Worker`.\n     */\n    workerCtor?: WorkerCtor;\n\n    /**\n     * Coalescing window in milliseconds for high-frequency events. Defaults\n     * to 16ms (~one animation frame). Trailing-edge: the most recent payload\n     * within the window is delivered after the window elapses.\n     */\n    coalesceMs?: number;\n\n    /**\n     * Maximum number of MCP requests (combined `invokeTool` + `getResource`)\n     * the transport will forward to {@link mcpClient} concurrently. Defaults\n     * to 8. Requests above the cap are rejected with a deterministic error\n     * reply over the port — the worker MUST handle that response shape.\n     *\n     * Bounded concurrency is a back-pressure boundary, not a quota: it stops\n     * a compromised or buggy worker from saturating the host's HTTP / token\n     * pool. Production hosts may want to lower this in multi-tenant pools\n     * where many extensions share one host process.\n     */\n    maxConcurrentMcpRequests?: number;\n}\n\n/**\n * Wire shape of a host-sourced input event forwarded to the worker over the\n * port. Pointer / wheel / keyboard payloads share a single envelope type so\n * the worker has one inbound dispatch site. The transport is structurally\n * agnostic to the payload — it forwards verbatim.\n *\n * `kind` discriminates the event family. Coordinates are CSS pixels relative\n * to the host canvas; coalescing happens host-side before the call to\n * {@link WorkerRemoteDomTransport.postInputEvent}.\n */\nexport type InputEventPayload =\n    | {\n        kind: \"pointermove\" | \"pointerdown\" | \"pointerup\" | \"pointercancel\";\n        surfaceId: string;\n        x: number;\n        y: number;\n        buttons: number;\n        pointerType: string;\n    }\n    | {\n        kind: \"wheel\";\n        surfaceId: string;\n        deltaX: number;\n        deltaY: number;\n        deltaMode: number;\n    }\n    | {\n        kind: \"keydown\" | \"keyup\";\n        surfaceId: string;\n        key: string;\n        code: string;\n        ctrlKey: boolean;\n        shiftKey: boolean;\n        altKey: boolean;\n        metaKey: boolean;\n    };\n\n/**\n * Documented wire protocol identifier embedded in handshake / message\n * envelopes. Bumped when the worker ↔ host message shape changes in a\n * backward-incompatible way.\n */\nexport const WORKER_TRANSPORT_PROTOCOL = \"ethisys.worker.remotedom.v1\";\n\n/**\n * Wire shape of the handshake message the host posts to the worker on\n * {@link WorkerRemoteDomTransport.connect}. Locked here so the SDK side and the\n * API-hosted bootstrap script (`WorkerBootstrapScriptProvider`) read from the\n * same field names — see the API tests pinning `event.data.moduleUrl` and\n * `event.data.importMap`.\n *\n * The handshake is the SOLE message that ever carries `moduleUrl` or\n * `importMap`; subsequent port traffic uses the discriminated message types\n * declared below. The capability token NEVER appears in this payload (or any\n * other postMessage payload) — it is bound on the host side via\n * {@link WorkerRemoteDomTransportOptions.capabilityToken}.\n */\nexport interface WorkerHandshakePayload\n{\n    readonly type: \"ethisys:worker:handshake\";\n    readonly protocol: string;\n    /** Host-origin URL of the plugin's worker bundle entry. */\n    readonly moduleUrl: string;\n    /**\n     * Frozen bare-specifier → host-origin URL map that the bootstrap installs\n     * before importing {@link moduleUrl}. Pulled from the plugin's\n     * `worker-bundle.import-map.json` at runtime by the host mount.\n     */\n    readonly importMap: Readonly<Record<string, string>>;\n}\n\n// ─── Implementation ───────────────────────────────────────────────────────────\n\ninterface InvokeToolMessage\n{\n    id: string;\n    type: \"ethisys:mcp:invokeTool\";\n    name: string;\n    args: unknown;\n}\n\ninterface GetResourceMessage\n{\n    id: string;\n    type: \"ethisys:mcp:getResource\";\n    uri: string;\n}\n\ninterface UploadDocumentMessage\n{\n    id: string;\n    type: \"ethisys:mcp:uploadDocument\";\n    meta: UploadDocumentMeta;\n    buffer: ArrayBuffer;\n}\n\ninterface RemoteDomMessage\n{\n    type: \"ethisys:remotedom\";\n    payload: unknown;\n}\n\ntype InboundMessage = InvokeToolMessage | GetResourceMessage | UploadDocumentMessage | RemoteDomMessage | { type: string; [k: string]: unknown };\n\n/**\n * Worker-side host transport for Contract B extensions.\n *\n * Construction immediately spawns the worker and transfers one end of a\n * fresh `MessageChannel`; the host retains `port1`, the worker receives\n * `port2`. Both sides exchange messages via their port and the worker port\n * is the *only* channel for plugin ↔ host traffic after handshake.\n */\n/**\n * Default cap for in-flight MCP requests forwarded by the transport. Chosen to\n * cover typical interactive UI traffic (dashboards, list views, detail panels)\n * without letting a runaway worker saturate the host's HTTP / token pool.\n */\nexport const DEFAULT_MAX_CONCURRENT_MCP_REQUESTS = 8;\n\nexport class WorkerRemoteDomTransport\n{\n    private readonly worker: WorkerLike;\n    private readonly hostPort: MessagePort;\n    private readonly workerPort: MessagePort;\n    private readonly mcpClient: McpHttpClient;\n    private readonly capabilityTokenProvider: () => Promise<string>;\n    private readonly mountedExtensionVersion?: string;\n    private readonly onVersionSkew?: (skew: VersionSkew) => void;\n    private versionSkewReported = false;\n    private readonly coalesceMs: number;\n    private readonly maxConcurrentMcpRequests: number;\n    private readonly abortController: AbortController;\n    // Per-request AbortControllers keyed by request id. An inbound\n    // `ethisys:mcp:abort` envelope (the worker posts one when a hook's\n    // AbortSignal fires on unmount / arg change) aborts just that request;\n    // dispose() fans out to every registered controller. Without this a\n    // cancelled call — most costly for uploadDocument — keeps streaming to the\n    // kernel even though the plugin promise already rejected.\n    private readonly inFlightAborts = new Map<string, AbortController>();\n    private inFlightMcpRequests = 0;\n    private remoteDomConsumer: ((payload: unknown) => void) | undefined;\n    private bridgeMessageConsumer: ((msg: unknown) => void) | undefined;\n    private disposed = false;\n    private connected = false;\n\n    public constructor(options: WorkerRemoteDomTransportOptions)\n    {\n        const WorkerCtor = options.workerCtor ?? (globalThis as unknown as { Worker: WorkerCtor }).Worker;\n        if (!WorkerCtor)\n        {\n            throw new Error(\"WorkerRemoteDomTransport: no Worker constructor available\");\n        }\n\n        this.mcpClient = options.mcpClient;\n        this.capabilityTokenProvider = options.capabilityToken;\n        this.mountedExtensionVersion = options.mountedExtensionVersion;\n        this.onVersionSkew = options.onVersionSkew;\n        this.coalesceMs = options.coalesceMs ?? 16;\n        this.maxConcurrentMcpRequests = Math.max(\n            1,\n            options.maxConcurrentMcpRequests ?? DEFAULT_MAX_CONCURRENT_MCP_REQUESTS,\n        );\n        // Aborted from dispose() — propagates into the mcpClient.fetch path so\n        // already-in-flight HTTP calls can short-circuit instead of resolving\n        // into a closed port.\n        this.abortController = new AbortController();\n\n        // Spawn the worker FIRST so the constructor's spawn shape is\n        // observable to tests even if MessageChannel construction throws.\n        this.worker = new WorkerCtor(options.bootstrapUrl, { type: \"module\" });\n\n        const channel = new MessageChannel();\n        this.hostPort = channel.port1;\n        this.workerPort = channel.port2;\n\n        // Wire host-side port handling before {@link connect} posts the\n        // handshake — this closes a race where the worker could reply faster\n        // than we wire up.\n        this.hostPort.onmessage = (ev) => this.handlePortMessage(ev.data as InboundMessage);\n        this.hostPort.start();\n\n        this.worker.onerror = (ev) =>\n        {\n            // Defensive: do NOT echo worker errors back to the worker — they\n            // may carry plugin-side details. Host-side observability is the\n            // platform's responsibility.\n            void ev;\n        };\n    }\n\n    /**\n     * Post the handshake to the worker. Idempotent — only the FIRST call\n     * transfers the {@link MessagePort} and posts the handshake payload;\n     * subsequent calls are silent no-ops. Splitting this off from the\n     * constructor lets the host mount fetch the per-plugin\n     * `worker-bundle.import-map.json` (and resolve the bundle's module URL)\n     * before the bootstrap script consumes them.\n     *\n     * Wire shape: {@link WorkerHandshakePayload}. The capability token NEVER\n     * appears in the payload — it's bound on the host side via the\n     * {@link WorkerRemoteDomTransportOptions.capabilityToken} provider.\n     *\n     * The `moduleUrl` and `importMap` are forwarded to the worker so the\n     * bootstrap script (served from the host-pinned\n     * `/extensions/runtime/worker-bootstrap.js`) can:\n     *   1. Compose the frozen, same-origin-validated `IMPORT_MAP` from the\n     *      handshake payload (rejecting any cross-origin entries).\n     *   2. `safeImport(moduleUrl)` the plugin's entry module.\n     *\n     * Same-origin enforcement is the bootstrap's job — this transport is\n     * structurally agnostic to the host origin and only forwards what it's\n     * handed.\n     */\n    public connect(moduleUrl: string, importMap: Record<string, string>): void\n    {\n        if (this.connected)\n        {\n            return;\n        }\n        this.connected = true;\n\n        // Snapshot the import map into a fresh object so the worker handshake\n        // is decoupled from caller-side mutation. `Object.freeze` here is\n        // defence-in-depth — the worker rebuilds with `Object.create(null)`\n        // anyway, but freezing the host-side payload makes mutation a typed\n        // error for any host code that hangs onto the reference.\n        const handshake: WorkerHandshakePayload = Object.freeze({\n            type: \"ethisys:worker:handshake\",\n            protocol: WORKER_TRANSPORT_PROTOCOL,\n            moduleUrl,\n            importMap: Object.freeze({ ...importMap }),\n        });\n        this.worker.postMessage(handshake, [this.workerPort]);\n    }\n\n    /**\n     * Bind a consumer for Remote DOM mutation payloads emitted by the worker.\n     * The Remote DOM receiver wiring is owned by the caller (typically a host\n     * React component); this method exposes the raw stream so the receiver\n     * can integrate cleanly without a circular package import.\n     */\n    public onRemoteDom(consumer: (payload: unknown) => void): void\n    {\n        this.remoteDomConsumer = consumer;\n    }\n\n    /**\n     * Transfer control of a host-owned `<canvas>` to the worker so plugin code\n     * can render via `OffscreenCanvas`. The host retains the `<canvas>` for\n     * layout / accessibility purposes only — every pixel is produced inside the\n     * worker, so the main thread is never blocked per frame.\n     *\n     * The transfer rides the established MessagePort (not the worker global\n     * `postMessage`) so it is multiplexed with the rest of the host ↔ worker\n     * traffic on the same channel. The `OffscreenCanvas` handle is the sole\n     * `Transferable` in the envelope; no capability token, MCP context, or\n     * other host-only data crosses the boundary.\n     *\n     * Throws if the environment lacks `transferControlToOffscreen()` or if the\n     * canvas has already been transferred — see {@link createOffscreenCanvasTransfer}\n     * for the exact diagnostics.\n     */\n    public transferCanvas(\n        canvas: HTMLCanvasElement,\n        options: { surfaceId: string },\n    ): { offscreen: OffscreenCanvas }\n    {\n        return createOffscreenCanvasTransfer({\n            canvas,\n            surfaceId: options.surfaceId,\n            postMessage: (message, transfer) =>\n            {\n                this.hostPort.postMessage(message, transfer);\n            },\n        });\n    }\n\n    /**\n     * Forward a host-sourced input event to the worker over the port. The\n     * payload shape is opaque to the transport — pointer / wheel / keyboard\n     * envelopes share the same wire type. Callers are expected to wrap\n     * high-frequency (pointer-move, wheel, scroll) events in\n     * {@link createCoalescer} or {@link createInputEventCoalescer} BEFORE\n     * calling this method so the port never sees the un-coalesced flood.\n     *\n     * Keyboard / pointer-down / pointer-up events are discrete and should be\n     * delivered without coalescing — pass them straight through.\n     */\n    public postInputEvent(payload: InputEventPayload): void\n    {\n        this.hostPort.postMessage({\n            type: \"ethisys:input:event\",\n            payload,\n        });\n    }\n\n    /**\n     * Build a trailing-edge coalescer keyed to {@link WorkerRemoteDomTransportOptions.coalesceMs}.\n     *\n     * Use it to wrap pointer-move / scroll / resize callbacks **before**\n     * they cross the port. The last payload in any coalescing window is the\n     * one that wins.\n     */\n    public createCoalescer<T>(consumer: (payload: T) => void): (payload: T) => void\n    {\n        let pending: T | undefined;\n        let timer: ReturnType<typeof setTimeout> | undefined;\n        const flush = () =>\n        {\n            timer = undefined;\n            const value = pending;\n            pending = undefined;\n            if (value !== undefined)\n            {\n                consumer(value);\n            }\n        };\n        return (payload: T) =>\n        {\n            pending = payload;\n            if (timer === undefined)\n            {\n                timer = setTimeout(flush, this.coalesceMs);\n            }\n        };\n    }\n\n    // ─── Bridge push methods (WI 4858 sub-plan 2) ─────────────────────────────\n\n    /**\n     * Register a consumer for inbound plugin→host bridge messages\n     * (chrome requests, a11y announce, lifecycle events). Only the most recently\n     * registered consumer is kept — the host mount wires exactly one.\n     */\n    public onBridgeMessage(consumer: (msg: unknown) => void): void\n    {\n        this.bridgeMessageConsumer = consumer;\n    }\n\n    /**\n     * Push the current host theme to the plugin worker. Safe to call on every\n     * host theme-context change — the transport coalesces nothing here; rate\n     * limiting at the call site is the host's responsibility.\n     */\n    public pushTheme(payload: Omit<BridgePushThemeEnvelope, \"type\">): void\n    {\n        this.safePostMessage({ type: BRIDGE_PUSH_THEME, ...payload });\n    }\n\n    /** Push the current host locale and text direction to the plugin worker. */\n    public pushLocale(payload: Omit<BridgePushLocaleEnvelope, \"type\">): void\n    {\n        this.safePostMessage({ type: BRIDGE_PUSH_LOCALE, ...payload });\n    }\n\n    /** Push the current UI density preference to the plugin worker. */\n    public pushDensity(payload: Omit<BridgePushDensityEnvelope, \"type\">): void\n    {\n        this.safePostMessage({ type: BRIDGE_PUSH_DENSITY, ...payload });\n    }\n\n    /** Push updated accessibility preferences to the plugin worker. */\n    public pushA11y(payload: Omit<BridgePushA11yEnvelope, \"type\">): void\n    {\n        this.safePostMessage({ type: BRIDGE_PUSH_A11Y, ...payload });\n    }\n\n    /** Push the current SPA navigation state to the plugin worker. */\n    public pushNav(payload: Omit<BridgeNavPushEnvelope, \"type\">): void\n    {\n        this.safePostMessage({ type: BRIDGE_NAV_PUSH, ...payload });\n    }\n\n    /**\n     * Tear down the worker and port. Idempotent.\n     *\n     * Order matters: we abort BEFORE closing the port so any in-flight\n     * `mcpClient.fetch` that observes the signal short-circuits and the\n     * subsequent attempt to post a reply lands in the disposed-guard branch\n     * (which silently drops the post) instead of throwing on a closed port.\n     */\n    public dispose(): void\n    {\n        if (this.disposed)\n        {\n            return;\n        }\n        this.disposed = true;\n        try\n        {\n            this.abortController.abort();\n            // Fan out to every in-flight per-request controller so their\n            // `mcpClient.fetch` calls short-circuit too — the dispose-level\n            // controller is not the signal those requests were handed.\n            for (const controller of this.inFlightAborts.values())\n            {\n                controller.abort();\n            }\n            this.inFlightAborts.clear();\n        }\n        catch\n        {\n            // AbortController.abort() shouldn't throw, but never let dispose\n            // crash the caller — teardown must be best-effort across all\n            // resources.\n        }\n        try\n        {\n            this.hostPort.close();\n        }\n        catch\n        {\n            // ignore — port may already be closed\n        }\n        try\n        {\n            this.worker.terminate();\n        }\n        catch\n        {\n            // ignore\n        }\n    }\n\n    /**\n     * Best-effort wrapper around `hostPort.postMessage` that tolerates posts\n     * arriving after {@link dispose}. The browser throws on a closed port and\n     * the async handlers below can race dispose, so any post initiated by an\n     * awaited continuation must be guarded.\n     */\n    private safePostMessage(message: unknown): void\n    {\n        if (this.disposed)\n        {\n            return;\n        }\n        try\n        {\n            this.hostPort.postMessage(message);\n        }\n        catch\n        {\n            // Port may have been closed between the disposed check and the\n            // post call (browser closes ports asynchronously). Swallowing the\n            // throw here is safe because we are already on a teardown path.\n        }\n    }\n\n    // ─── Port message handling ──────────────────────────────────────────────\n\n    private handlePortMessage(message: InboundMessage): void\n    {\n        // Post-dispose port traffic is dropped silently. The browser closes\n        // MessagePorts asynchronously; any handler invocation after dispose\n        // is a race we observe-and-skip rather than try to service.\n        if (this.disposed)\n        {\n            return;\n        }\n        switch (message.type)\n        {\n        case \"ethisys:mcp:invokeTool\":\n            this.dispatchMcp(message as InvokeToolMessage, \"ethisys:mcp:invokeTool:result\", (m) => this.handleInvokeTool(m));\n            return;\n\n        case \"ethisys:mcp:getResource\":\n            this.dispatchMcp(message as GetResourceMessage, \"ethisys:mcp:getResource:result\", (m) => this.handleGetResource(m));\n            return;\n\n        case \"ethisys:mcp:uploadDocument\":\n            this.dispatchMcp(message as UploadDocumentMessage, \"ethisys:mcp:uploadDocument:result\", (m) => this.handleUploadDocument(m));\n            return;\n\n        case \"ethisys:mcp:abort\":\n            // Client-side cancel (hook unmount / arg change). Abort just the\n            // matching in-flight request so its `mcpClient.fetch` short-circuits\n            // instead of streaming to completion. The worker has already dropped\n            // its pending resolver, so any late `:result` reply is ignored.\n            this.inFlightAborts.get((message as { id?: string }).id ?? \"\")?.abort();\n            return;\n\n        case \"ethisys:remotedom\":\n            this.remoteDomConsumer?.((message as RemoteDomMessage).payload);\n            return;\n\n        case BRIDGE_CHROME_REQUEST:\n        case BRIDGE_A11Y_ANNOUNCE:\n        case BRIDGE_LIFECYCLE_EVENT:\n            this.bridgeMessageConsumer?.(message);\n            return;\n\n        default:\n            // Unknown messages are ignored. The host MUST NOT echo unknown\n            // shapes back to the worker — that would create an attacker-\n            // controlled reflection surface.\n            return;\n        }\n    }\n\n    /**\n     * Gate inbound MCP requests through the bounded concurrency window,\n     * reject with a deterministic error reply when the cap is exceeded, and\n     * decrement the counter unconditionally when the underlying handler\n     * settles (regardless of resolution/rejection shape).\n     */\n    private dispatchMcp<T extends { id: string }>(\n        message: T,\n        resultType: string,\n        handler: (m: T) => Promise<void>,\n    ): void\n    {\n        if (this.inFlightMcpRequests >= this.maxConcurrentMcpRequests)\n        {\n            // Back-pressure boundary. The worker MUST surface this to plugin\n            // code so it can retry / degrade gracefully rather than silently\n            // hang on a never-resolving promise.\n            this.safePostMessage({\n                id: message.id,\n                type: resultType,\n                ok: false,\n                error: `MCP back-pressure: in-flight cap of ${this.maxConcurrentMcpRequests} reached.`,\n            });\n            return;\n        }\n        this.inFlightMcpRequests++;\n        this.registerRequestAbort(message.id);\n        handler(message).finally(() =>\n        {\n            this.releaseRequestAbort(message.id);\n            this.inFlightMcpRequests = Math.max(0, this.inFlightMcpRequests - 1);\n        });\n    }\n\n    /**\n     * Create a per-request AbortController and register it under the request id\n     * so an inbound `ethisys:mcp:abort` can cancel just this call. If the\n     * transport is already disposed the controller starts aborted so the\n     * handler's `mcpClient.fetch` short-circuits immediately.\n     */\n    private registerRequestAbort(id: string): void\n    {\n        const controller = new AbortController();\n        if (this.abortController.signal.aborted)\n        {\n            controller.abort();\n        }\n        this.inFlightAborts.set(id, controller);\n    }\n\n    /** Drop a settled request's AbortController. */\n    private releaseRequestAbort(id: string): void\n    {\n        this.inFlightAborts.delete(id);\n    }\n\n    /**\n     * The signal to hand to `mcpClient.fetch` for a given request: the\n     * per-request controller when registered (client cancel path), falling back\n     * to the dispose-level controller.\n     */\n    private requestSignal(id: string): AbortSignal\n    {\n        return this.inFlightAborts.get(id)?.signal ?? this.abortController.signal;\n    }\n\n    /**\n     * Raises the skew callback the first time this surface is seen to be running against a version\n     * that is no longer installed.\n     *\n     * Latched deliberately. A page typically has several MCP calls in flight, and after an upgrade\n     * every one of them reports the same skew — firing per response would ask the host to remount\n     * the same surface repeatedly, and the second remount would tear down the first. One signal per\n     * transport is all a remount needs, and the transport is discarded along with the surface.\n     *\n     * The callback is host code, so it is assumed to be able to throw. Two consequences are guarded\n     * here: the throw must not escape into the MCP handler's catch (which would reply `ok: false`\n     * for a call that actually succeeded), and it must not consume the latch (which would leave the\n     * surface with no response AND no further chance of being told to remount).\n     */\n    private reportVersionSkew(response: McpHttpResponse): void\n    {\n        if (this.versionSkewReported || this.onVersionSkew === undefined)\n        {\n            return;\n        }\n        const skew = detectVersionSkew(response, this.mountedExtensionVersion);\n        if (skew === null)\n        {\n            return;\n        }\n        try\n        {\n            this.onVersionSkew(skew);\n            this.versionSkewReported = true;\n        }\n        catch\n        {\n            // Swallowed on purpose: a failed remount attempt is the host's problem, and turning it\n            // into an MCP failure would corrupt a response the plugin is entitled to. The latch\n            // stays open so the next response gets another chance to raise it.\n        }\n    }\n\n    private async handleInvokeTool(message: InvokeToolMessage): Promise<void>\n    {\n        let token: string;\n        try\n        {\n            token = await this.capabilityTokenProvider();\n        }\n        catch (err)\n        {\n            this.replyError(message.id, \"ethisys:mcp:invokeTool:result\", err);\n            return;\n        }\n        // Disposed-before-token: short-circuit. The token mint may have\n        // resolved seconds after dispose; posting the reply now would race\n        // a closed port.\n        if (this.disposed)\n        {\n            return;\n        }\n        try\n        {\n            const result = await this.mcpClient.fetch({\n                kind: \"invokeTool\",\n                name: message.name,\n                args: message.args,\n                capabilityToken: token,\n                signal: this.requestSignal(message.id),\n            });\n            this.reportVersionSkew(result);\n            // CRITICAL: response payload must never include the token. We\n            // forward ONLY the public-facing fields the plugin needs.\n            this.safePostMessage({\n                id: message.id,\n                type: \"ethisys:mcp:invokeTool:result\",\n                ok: result.ok,\n                data: result.data,\n                error: result.error,\n                // A client that REPORTS failure rather than throwing lands here, which is the common\n                // shape for anything wrapping HTTP. Classifying only the thrown path left these\n                // arriving as `internal`.\n                code: classifyHostResponse(result),\n            });\n        }\n        catch (err)\n        {\n            this.replyError(message.id, \"ethisys:mcp:invokeTool:result\", err);\n        }\n    }\n\n    private async handleGetResource(message: GetResourceMessage): Promise<void>\n    {\n        let token: string;\n        try\n        {\n            token = await this.capabilityTokenProvider();\n        }\n        catch (err)\n        {\n            this.replyError(message.id, \"ethisys:mcp:getResource:result\", err);\n            return;\n        }\n        if (this.disposed)\n        {\n            return;\n        }\n        try\n        {\n            const result = await this.mcpClient.fetch({\n                kind: \"getResource\",\n                uri: message.uri,\n                capabilityToken: token,\n                signal: this.requestSignal(message.id),\n            });\n            this.reportVersionSkew(result);\n            this.safePostMessage({\n                id: message.id,\n                type: \"ethisys:mcp:getResource:result\",\n                ok: result.ok,\n                data: result.data,\n                error: result.error,\n                // A client that REPORTS failure rather than throwing lands here, which is the common\n                // shape for anything wrapping HTTP. Classifying only the thrown path left these\n                // arriving as `internal`.\n                code: classifyHostResponse(result),\n            });\n        }\n        catch (err)\n        {\n            this.replyError(message.id, \"ethisys:mcp:getResource:result\", err);\n        }\n    }\n\n    private async handleUploadDocument(message: UploadDocumentMessage): Promise<void>\n    {\n        let token: string;\n        try\n        {\n            token = await this.capabilityTokenProvider();\n        }\n        catch (err)\n        {\n            this.replyError(message.id, \"ethisys:mcp:uploadDocument:result\", err);\n            return;\n        }\n        // Disposed-before-token: short-circuit. The token mint may have resolved\n        // after dispose; posting the reply now would race a closed port.\n        if (this.disposed)\n        {\n            return;\n        }\n        try\n        {\n            // CRITICAL security invariant: the worker transferred ONLY bytes +\n            // metadata. The capability token is minted + attached here (host\n            // side) and never crosses the port. The abort signal propagates so\n            // a client cancel / host dispose aborts the octet-stream upload.\n            const result = await this.mcpClient.fetch({\n                kind: \"uploadDocument\",\n                meta: message.meta,\n                buffer: message.buffer,\n                capabilityToken: token,\n                signal: this.requestSignal(message.id),\n            });\n            this.reportVersionSkew(result);\n            // Response payload must never include the token — forward only the\n            // public-facing UploadDocumentResult fields.\n            this.safePostMessage({\n                id: message.id,\n                type: \"ethisys:mcp:uploadDocument:result\",\n                ok: result.ok,\n                data: result.data,\n                error: result.error,\n                // A client that REPORTS failure rather than throwing lands here, which is the common\n                // shape for anything wrapping HTTP. Classifying only the thrown path left these\n                // arriving as `internal`.\n                code: classifyHostResponse(result),\n            });\n        }\n        catch (err)\n        {\n            this.replyError(message.id, \"ethisys:mcp:uploadDocument:result\", err);\n        }\n    }\n\n    private replyError(id: string, type: string, err: unknown): void\n    {\n        // Surface a sanitised error string — never the raw error object\n        // (which may carry stack traces or token fragments from a misbehaving\n        // mcpClient implementation). Routed through safePostMessage so a\n        // post-dispose reply does not crash on a closed port.\n        const message = err instanceof Error ? err.message : \"MCP request failed\";\n        // `code` is derived from the error's own explicit classification (or an HTTP status), never\n        // from its message — see classifyHostError. It is safe to expose where the message may not\n        // be: a closed vocabulary carries no host internals.\n        this.safePostMessage({ id, type, ok: false, error: message, code: classifyHostError(err) });\n    }\n}\n","/**\n * Cross-origin iframe bridge transport (WI 4858 sub-plan 5, Tier U).\n *\n * The host-side counterpart to a `TENANT_APP` plugin rendered in a cross-origin\n * `<iframe sandbox>`. It brokers the SAME `ethisys:mcp:*` request/reply shapes\n * and host-side capability-token brokering as {@link WorkerRemoteDomTransport}\n * (the capability JWT NEVER crosses the boundary), but the transport is a\n * cross-origin iframe rather than a Worker, so it adds:\n *   - a per-mount handshake **nonce** delivered with the transferred MessagePort,\n *   - strict `targetOrigin` on every `postMessage` (never `\"*\"`),\n *   - Zod schema validation of every inbound envelope (unknown shapes dropped),\n *   - nonce validation on every inbound port message (defence-in-depth on top of\n *     the private MessageChannel + per-plugin origin boundary),\n *   - a rolling per-second inbound rate limit.\n *\n * MCP request handling (bounded concurrency, token brokering, reply shape) is\n * structurally identical to the worker transport.\n */\nimport { z } from \"zod\";\nimport { classifyHostError, classifyHostResponse } from \"../../bridge/mcp-error\";\nimport {\n  type McpHttpClient,\n  DEFAULT_MAX_CONCURRENT_MCP_REQUESTS,\n} from \"../worker/transport\";\nimport {\n  detectVersionSkew,\n  type McpHttpResponse,\n  type VersionSkew,\n} from \"../version-skew\";\n\nexport const IFRAME_BRIDGE_PROTOCOL = \"ethisys.iframe.bridge.v1\";\n\n/** Construction options for {@link IframeBridgeTransport}. */\nexport interface IframeBridgeTransportOptions {\n  /** The cross-origin iframe's `contentWindow` (host never touches its document). */\n  frameWindow: Window;\n  /** EXACT plugin origin; every postMessage uses this as `targetOrigin`, never `\"*\"`. */\n  targetOrigin: string;\n  /**\n   * Mints (or returns a cached) capability token. Resolved per outbound MCP HTTP\n   * call on the HOST side only — the token NEVER crosses to the plugin frame.\n   */\n  capabilityToken: () => Promise<string>;\n  /** Host-side MCP HTTP client; carries the capability token on the outbound call. */\n  mcpClient: McpHttpClient;\n  /**\n   * The extension version this surface mounted at. Enables proactive skew detection — a successful\n   * response stamped with a different version means the install moved while the surface is still\n   * working, so it can remount before anything fails.\n   */\n  mountedExtensionVersion?: string;\n  /**\n   * Called at most once, when this surface is found to be running against a version that is no\n   * longer installed. The host remounts the surface; the transport does not retry, because the\n   * pending call belongs to a page about to be replaced.\n   */\n  onVersionSkew?: (skew: VersionSkew) => void;\n  /** Bounded in-flight MCP requests before back-pressure. Default 8. */\n  maxConcurrentMcpRequests?: number;\n  /** Max inbound port messages per rolling second before drop. Default 64. */\n  maxMessagesPerSecond?: number;\n  /** Optional sink for dropped-message security telemetry (bad schema / nonce / rate). */\n  onSecurityEvent?: (event: IframeBridgeSecurityEvent) => void;\n}\n\n/** Reason an inbound message was dropped. */\nexport type IframeBridgeSecurityEvent =\n  | { reason: \"schema-invalid\" }\n  | { reason: \"nonce-mismatch\" }\n  | { reason: \"rate-limit-exceeded\"; type: string };\n\n/** Handshake payload posted to the frame (carries the nonce + transferred port). */\nexport interface IframeHandshakePayload {\n  readonly type: \"ethisys:iframe:handshake\";\n  readonly protocol: string;\n  readonly nonce: string;\n}\n\n// Inbound envelope schema — validated BEFORE any handling. Unknown shapes dropped.\nconst InboundEnvelope = z.discriminatedUnion(\"type\", [\n  z.object({ type: z.literal(\"ethisys:mcp:invokeTool\"), id: z.string().min(1), name: z.string().min(1), args: z.unknown(), nonce: z.string() }),\n  z.object({ type: z.literal(\"ethisys:mcp:getResource\"), id: z.string().min(1), uri: z.string().min(1), nonce: z.string() }),\n  z.object({ type: z.literal(\"ethisys:event\"), name: z.string().min(1), payload: z.unknown(), nonce: z.string() }),\n]);\n\ntype InboundMessage = z.infer<typeof InboundEnvelope>;\n\n/** base64url-encode raw bytes (no padding). 32 bytes → 43 chars. */\nfunction base64url(bytes: Uint8Array): string {\n  let binary = \"\";\n  for (const b of bytes) {\n    binary += String.fromCharCode(b);\n  }\n  return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nfunction mintNonce(): string {\n  const bytes = new Uint8Array(32);\n  crypto.getRandomValues(bytes);\n  return base64url(bytes);\n}\n\n/**\n * Host-side cross-origin iframe bridge. Construct, then call {@link connect} to\n * post the handshake (transferring one end of a fresh `MessageChannel`). The\n * plugin frame must echo the handshake `nonce` on every port message.\n */\nexport class IframeBridgeTransport {\n  private readonly frameWindowRef: { current: Window | null };\n  private readonly targetOrigin: string;\n  private readonly capabilityTokenProvider: () => Promise<string>;\n  private readonly mcpClient: McpHttpClient;\n  private readonly maxConcurrentMcpRequests: number;\n  private readonly maxMessagesPerSecond: number;\n  private readonly onSecurityEvent: ((event: IframeBridgeSecurityEvent) => void) | undefined;\n  private readonly mountedExtensionVersion: string | undefined;\n  private readonly onVersionSkew: ((skew: VersionSkew) => void) | undefined;\n  private versionSkewReported = false;\n  private readonly abortController = new AbortController();\n\n  private hostPort: MessagePort | undefined;\n  private framePort: MessagePort | undefined;\n  private nonce: string | undefined;\n  private eventConsumer: ((name: string, payload: unknown) => void) | undefined;\n  private inFlightMcpRequests = 0;\n  private windowTimestamps: number[] = [];\n  private connected = false;\n  private disposed = false;\n\n  public constructor(options: IframeBridgeTransportOptions) {\n    this.frameWindowRef = { current: options.frameWindow };\n    this.targetOrigin = options.targetOrigin;\n    this.capabilityTokenProvider = options.capabilityToken;\n    this.mcpClient = options.mcpClient;\n    this.mountedExtensionVersion = options.mountedExtensionVersion;\n    this.onVersionSkew = options.onVersionSkew;\n    this.maxConcurrentMcpRequests = Math.max(1, options.maxConcurrentMcpRequests ?? DEFAULT_MAX_CONCURRENT_MCP_REQUESTS);\n    this.maxMessagesPerSecond = Math.max(1, options.maxMessagesPerSecond ?? 64);\n    this.onSecurityEvent = options.onSecurityEvent;\n  }\n\n  /**\n   * Post the handshake to the frame. Idempotent — only the FIRST call mints the\n   * nonce, creates the channel, wires the host port, and transfers the frame\n   * port. The handshake uses the exact `targetOrigin` (never `\"*\"`).\n   */\n  public connect(): void {\n    if (this.connected || this.disposed) {\n      return;\n    }\n    this.connected = true;\n\n    this.nonce = mintNonce();\n    const channel = new MessageChannel();\n    this.hostPort = channel.port1;\n    this.framePort = channel.port2;\n    this.hostPort.onmessage = (ev) => this.handlePortMessage(ev.data);\n    this.hostPort.start();\n\n    const handshake: IframeHandshakePayload = {\n      type: \"ethisys:iframe:handshake\",\n      protocol: IFRAME_BRIDGE_PROTOCOL,\n      nonce: this.nonce,\n    };\n    const frameWindow = this.frameWindowRef.current;\n    frameWindow?.postMessage(handshake, this.targetOrigin, [this.framePort]);\n  }\n\n  /**\n   * The per-mount handshake nonce (set after {@link connect}, `undefined` before\n   * connect / after dispose). The host mount reads this to validate inbound\n   * cross-origin `window`-level messages (which carry no MessagePort identity).\n   */\n  public get connectedNonce(): string | undefined {\n    return this.nonce;\n  }\n\n  /** Register a consumer for inbound plugin→host `ethisys:event` envelopes. */\n  public onEvent(consumer: (name: string, payload: unknown) => void): void {\n    this.eventConsumer = consumer;\n  }\n\n  /**\n   * Push a host→plugin envelope (theme/nav/chrome). Always uses the exact\n   * `targetOrigin` (never `\"*\"`) and stamps the handshake nonce.\n   */\n  public postOutbound(envelope: Record<string, unknown>): void {\n    if (this.disposed || this.nonce === undefined) {\n      return;\n    }\n    const frameWindow = this.frameWindowRef.current;\n    frameWindow?.postMessage({ ...envelope, nonce: this.nonce }, this.targetOrigin);\n  }\n\n  /** Tear down. Idempotent. Does NOT remove the iframe (the host mount owns it). */\n  public dispose(): void {\n    if (this.disposed) {\n      return;\n    }\n    this.disposed = true;\n    try {\n      this.abortController.abort();\n    } catch {\n      // best-effort\n    }\n    try {\n      this.hostPort?.close();\n    } catch {\n      // ignore — may already be closed\n    }\n    this.nonce = undefined;\n    this.frameWindowRef.current = null;\n  }\n\n  // ─── Inbound port message handling ────────────────────────────────────────\n\n  private handlePortMessage(data: unknown): void {\n    if (this.disposed) {\n      return;\n    }\n\n    // 1. Schema validation — unknown shapes are dropped.\n    const parsed = InboundEnvelope.safeParse(data);\n    if (!parsed.success) {\n      this.onSecurityEvent?.({ reason: \"schema-invalid\" });\n      return;\n    }\n    const message = parsed.data;\n\n    // 2. Nonce validation — defence-in-depth over the private MessageChannel.\n    if (message.nonce !== this.nonce) {\n      this.onSecurityEvent?.({ reason: \"nonce-mismatch\" });\n      return;\n    }\n\n    // 3. Rolling per-second rate limit.\n    if (this.isRateLimited()) {\n      this.onSecurityEvent?.({ reason: \"rate-limit-exceeded\", type: message.type });\n      if (message.type === \"ethisys:mcp:invokeTool\" || message.type === \"ethisys:mcp:getResource\") {\n        this.safePostMessage({\n          id: message.id,\n          type: `${message.type}:result`,\n          ok: false,\n          error: \"iframe-bridge rate limit exceeded\",\n        });\n      }\n      return;\n    }\n\n    // 4. Route.\n    switch (message.type) {\n    case \"ethisys:mcp:invokeTool\":\n      this.dispatchMcp(message, \"ethisys:mcp:invokeTool:result\", (m) => this.handleInvokeTool(m));\n      return;\n    case \"ethisys:mcp:getResource\":\n      this.dispatchMcp(message, \"ethisys:mcp:getResource:result\", (m) => this.handleGetResource(m));\n      return;\n    case \"ethisys:event\":\n      this.eventConsumer?.(message.name, message.payload);\n      return;\n    }\n  }\n\n  private isRateLimited(): boolean {\n    const now = Date.now();\n    const cutoff = now - 1000;\n    this.windowTimestamps = this.windowTimestamps.filter((t) => t > cutoff);\n    if (this.windowTimestamps.length >= this.maxMessagesPerSecond) {\n      return true;\n    }\n    this.windowTimestamps.push(now);\n    return false;\n  }\n\n  // ─── MCP brokering (structurally identical to the worker transport) ───────\n\n  private dispatchMcp<T extends { id: string }>(\n    message: T,\n    resultType: string,\n    handler: (m: T) => Promise<void>,\n  ): void {\n    if (this.inFlightMcpRequests >= this.maxConcurrentMcpRequests) {\n      this.safePostMessage({\n        id: message.id,\n        type: resultType,\n        ok: false,\n        error: `MCP back-pressure: in-flight cap of ${this.maxConcurrentMcpRequests} reached.`,\n      });\n      return;\n    }\n    this.inFlightMcpRequests++;\n    handler(message).finally(() => {\n      this.inFlightMcpRequests = Math.max(0, this.inFlightMcpRequests - 1);\n    });\n  }\n\n  private async handleInvokeTool(message: Extract<InboundMessage, { type: \"ethisys:mcp:invokeTool\" }>): Promise<void> {\n    let token: string;\n    try {\n      token = await this.capabilityTokenProvider();\n    } catch (err) {\n      this.replyError(message.id, \"ethisys:mcp:invokeTool:result\", err);\n      return;\n    }\n    if (this.disposed) {\n      return;\n    }\n    try {\n      const result = await this.mcpClient.fetch({\n        kind: \"invokeTool\",\n        name: message.name,\n        args: message.args,\n        capabilityToken: token,\n        signal: this.abortController.signal,\n      });\n      this.reportVersionSkew(result);\n      // CRITICAL: the response payload must never include the token.\n      this.safePostMessage({\n        id: message.id,\n        type: \"ethisys:mcp:invokeTool:result\",\n        ok: result.ok,\n        data: result.data,\n        error: result.error,\n        // A client that REPORTS failure rather than throwing lands here, which is the common shape\n        // for anything wrapping HTTP. Classifying only the thrown path left these arriving as\n        // `internal`.\n        code: classifyHostResponse(result),\n      });\n    } catch (err) {\n      this.replyError(message.id, \"ethisys:mcp:invokeTool:result\", err);\n    }\n  }\n\n  /**\n   * Raises the skew callback the first time this surface is seen to be running against a version\n   * that is no longer installed. Latched: a page usually has several MCP calls in flight and after\n   * an upgrade every one of them reports the same skew, so firing per response would ask the host\n   * to remount the same surface repeatedly and each remount would tear down the last.\n   *\n   * The callback is host code and may throw. That must neither escape into the MCP handler's catch\n   * (replying `ok: false` for a call that succeeded) nor consume the latch (leaving the surface with\n   * no response and no further chance of being told to remount).\n   */\n  private reportVersionSkew(response: McpHttpResponse): void {\n    if (this.versionSkewReported || this.onVersionSkew === undefined) {\n      return;\n    }\n    const skew = detectVersionSkew(response, this.mountedExtensionVersion);\n    if (skew === null) {\n      return;\n    }\n    try {\n      this.onVersionSkew(skew);\n      this.versionSkewReported = true;\n    } catch {\n      // Swallowed on purpose: a failed remount attempt is the host's problem, and turning it into\n      // an MCP failure would corrupt a response the plugin is entitled to. The latch stays open so\n      // the next response gets another chance to raise it.\n    }\n  }\n\n  private async handleGetResource(message: Extract<InboundMessage, { type: \"ethisys:mcp:getResource\" }>): Promise<void> {\n    let token: string;\n    try {\n      token = await this.capabilityTokenProvider();\n    } catch (err) {\n      this.replyError(message.id, \"ethisys:mcp:getResource:result\", err);\n      return;\n    }\n    if (this.disposed) {\n      return;\n    }\n    try {\n      const result = await this.mcpClient.fetch({\n        kind: \"getResource\",\n        uri: message.uri,\n        capabilityToken: token,\n        signal: this.abortController.signal,\n      });\n      this.reportVersionSkew(result);\n      this.safePostMessage({\n        id: message.id,\n        type: \"ethisys:mcp:getResource:result\",\n        ok: result.ok,\n        data: result.data,\n        error: result.error,\n        // A client that REPORTS failure rather than throwing lands here, which is the common shape\n        // for anything wrapping HTTP. Classifying only the thrown path left these arriving as\n        // `internal`.\n        code: classifyHostResponse(result),\n      });\n    } catch (err) {\n      this.replyError(message.id, \"ethisys:mcp:getResource:result\", err);\n    }\n  }\n\n  private replyError(id: string, type: string, err: unknown): void {\n    const message = err instanceof Error ? err.message : \"MCP request failed\";\n    // `code` accompanies the message so the plugin can branch on WHY the call failed. Without it a\n    // plugin's only options were to match on host error prose or to swallow every failure\n    // indiscriminately, and the latter is what shipped: permission denials and outages both became\n    // \"no results\", which is a false statement about the user's data.\n    this.safePostMessage({ id, type, ok: false, error: message, code: classifyHostError(err) });\n  }\n\n  /** Best-effort reply over the host port; tolerates post-dispose races. */\n  private safePostMessage(message: unknown): void {\n    if (this.disposed || this.hostPort === undefined) {\n      return;\n    }\n    try {\n      this.hostPort.postMessage(message);\n    } catch {\n      // Port may have closed between the disposed check and the post.\n    }\n  }\n}\n"]}