# Cross-Origin Isolation URL: /runtime/guides/cross-origin-isolation `@taucad/runtime` needs `crossOriginIsolated === true` for its `SharedArrayBuffer`-backed features. Two layers own SABs — the active transport allocates the geometry pool and cooperative-abort channel internally, and the multi-threaded OpenCASCADE WASM heap belongs to the kernel — but they share one isolation requirement: the top-level document must be served with the right COOP, COEP, and CORP headers. Without isolation the runtime still works, degraded: the geometry pool falls back to copy delivery, render abort to wire notification, and auto-selected OCCT kernels to single-threaded WASM. The worker logs a structured warning naming the degradation, so the failure is observable in telemetry rather than silent. The runtime ships an adapter for each layer that produces responses. Use them; do not duplicate header strings in your app. ## The required headers [#the-required-headers] `SharedArrayBuffer` is blocked by default to mitigate Spectre-class attacks. To opt in, the document must declare: | Header | Value | Purpose | | ------------------------------ | -------------- | -------------------------------------------------------------------- | | `Cross-Origin-Opener-Policy` | `same-origin` | Isolates the top-level browsing context. | | `Cross-Origin-Embedder-Policy` | `require-corp` | Forces every embedded resource to declare CORP. | | `Cross-Origin-Resource-Policy` | `same-origin` | Allows the document and same-origin subresources to load under COEP. | Safari is strictly conformant: under `require-corp`, every subresource — including same-origin worker scripts and WASM binaries — must carry an explicit CORP header. Chromium and Firefox are more permissive, which is why a missing CORP header on a worker often appears as a Safari-only eternal-loading bug. Set the headers at every layer that produces a response; missing any one of HTML, worker-script, or WASM responses breaks Safari. | Layer | Adapter | | ------------------------------------ | ---------------------------------------------------- | | Vite dev/preview server | `@taucad/runtime/vite#tauRuntime` | | Next.js | `@taucad/runtime/nextjs/config#withTauRuntime` | | React Router SSR (the HTML document) | `@taucad/runtime/react-router` | | Express/Connect production server | `@taucad/runtime/cross-origin-isolation/express` | | Electron renderer session | `@taucad/runtime/electron/main` | | Static host with declarative headers | Your host's config (e.g. `netlify.toml`, `_headers`) | ## Vite dev/preview [#vite-devpreview] ```typescript import { tauRuntime } from '@taucad/runtime/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [tauRuntime()], }); ``` `tauRuntime()` includes the isolation adapter plus the runtime's asset and worker invariants. Reach for the lower-level `crossOriginIsolation()` export only when another integration already supplies those build invariants. ## Next.js [#nextjs] ```typescript import { withTauRuntime } from '@taucad/runtime/nextjs/config'; export default withTauRuntime(); ``` `withTauRuntime()` composes existing application headers with the canonical runtime rules. Use `nextRuntimeHeaders()` only when another config composer owns the bundler configuration. ## React Router SSR [#react-router-ssr] ```tsx import { applyHandleRequestHeaders } from '@taucad/runtime/react-router'; export default function handleRequest( request: Request, responseStatusCode: number, responseHeaders: Headers, routerContext: EntryContext, ) { applyHandleRequestHeaders(responseHeaders); // …existing renderToPipeableStream logic } ``` ## Express production server [#express-production-server] Mount `coiMiddleware()` **before** `express.static` so worker scripts and WASM responses carry CORP. The middleware also suppresses downstream `res.append()` of COI headers, so a downstream `Response` writer (e.g. `@react-router/express`) cannot duplicate the triple: ```typescript import express, { type Express } from 'express'; import { createRequestHandler } from '@react-router/express'; import { coiMiddleware } from '@taucad/runtime/cross-origin-isolation/express'; type ServerBuild = Parameters[0]['build']; export function createApp(build: ServerBuild): Express { const app = express(); app.disable('x-powered-by'); app.use(coiMiddleware()); app.use('/assets', express.static('build/client/assets', { immutable: true, maxAge: '1y' })); app.use(express.static('build/client', { maxAge: '1h' })); app.all('*splat', createRequestHandler({ build })); return app; } ``` ## Electron [#electron] Install the renderer-session headers after `app.whenReady()` and before creating runtime windows: ```typescript import { app } from 'electron'; import { installElectronRuntimeHeaders } from '@taucad/runtime/electron/main'; await app.whenReady(); installElectronRuntimeHeaders(); ``` ## Static hosts [#static-hosts] Behind a CDN, configure the headers declaratively. For Netlify: ```toml [[headers]] for = "/*" [headers.values] Cross-Origin-Opener-Policy = "same-origin" Cross-Origin-Embedder-Policy = "require-corp" Cross-Origin-Resource-Policy = "same-origin" ``` ## Verify [#verify] Check each response class — HTML document, worker script, WASM binary — for exactly one copy of all three headers: ```bash curl -sI http://localhost:3000/ | grep -i cross-origin curl -sI http://localhost:3000/assets/file-manager.worker-XXXXX.js | grep -i cross-origin find apps/ui/build/client/assets -name '*.wasm' -print curl -sI http://localhost:3000/assets/EMITTED-ASSET.wasm | grep -Ei 'content-type|cross-origin' ``` Then confirm `crossOriginIsolated === true` in the browser DevTools console. ## Cross-origin APIs [#cross-origin-apis] When the isolated document fetches a different origin (an analytics or asset CDN), that origin must opt in with `Cross-Origin-Resource-Policy: cross-origin`. Use the `apiHeaders` constant or `applyApiHeaders()` from `@taucad/runtime/cross-origin-isolation` on your API responses. ## References [#references] * [web.dev: Why you need cross-origin isolated for powerful features](https://web.dev/articles/coop-coep)