> ## Documentation Index
> Fetch the complete documentation index at: https://invariant-cad.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Browser and worker deployment

> Bundle both WebAssembly kernels with Vite, control asset URLs, and isolate long-running evaluation.

InvariantCAD's release gate builds a production Vite application and exercises
both public kernel entry points in Chromium. The test evaluates a `2 × 3 × 4`
box, checks Manifold mesh/STL results, checks exact OCCT topology counts, and
exports STEP. It also exercises exact manifest/JavaScript/WASM verification
through the browser-specific OCCT attested loader and exercises the
repository-private OCCT artifact candidate inside disposable stock-runtime
module workers. Those workers also run real evaluator-invoked OCCT operations
through repository-private deadline and abort gates. Neither test advertises a
public codec or isolated-evaluation API.

## Vite application

```ts theme={"system"}
import { createEvaluator, design, mm, vec3 } from "invariantcad";

const cad = design("browser-part");
const body = cad.box("body", {
  size: vec3(mm(20), mm(10), mm(4)),
});
cad.output("body", body);

const evaluator = await createEvaluator();
const result = await evaluator.evaluate(cad.build());
```

The bundled Manifold runtime uses `import.meta.url` to locate its sibling WASM.
Set Vite's `assetsInlineLimit: 0` if you need a physical emitted asset rather
than an inline representation.

## Explicit asset URL

CDN rewriting or a strict asset pipeline may require an explicit URL:

```ts theme={"system"}
const evaluator = await createEvaluator({
  manifold: {
    wasmUrl: new URL("/wasm/manifold.wasm", window.location.origin).href,
  },
});
```

For OCCT:

```ts theme={"system"}
import { createOcctKernel } from "invariantcad/kernels/occt";

const kernel = await createOcctKernel({
  wasm: new URL("/wasm/occt-wasm.wasm", window.location.origin),
});
```

`createOcctKernel` snapshots all caller-owned initialization options before its
first asynchronous import. WASM `ArrayBuffer` and `Uint8Array` inputs are
copied, including an exact typed-array view; a URL's href is captured with a
cross-realm-safe brand check; and the factory, tolerance, tessellation options,
callbacks, and normalized limits retain their call-time values. Mutating the
options or a URL after calling the function therefore cannot change the later
execution source or make an explicitly supplied source acquire a false stock
runtime identity.

Serve WASM with `Content-Type: application/wasm`. Same-origin hosting avoids
cross-origin credential and policy surprises; otherwise configure CORS
explicitly.

## Attested owned OCCT runtime

The browser-specific entry verifies an already acquired owned runtime pair
before importing its JavaScript:

```ts theme={"system"}
import { createOcctKernel } from "invariantcad/kernels/occt";
import {
  INVARIANTCAD_OCCT_FACADE_0_9_0_RELEASE_MANIFEST_SHA256,
  loadAttestedOcctRuntime,
} from "invariantcad/kernels/occt/browser";

const attestedRuntime = await loadAttestedOcctRuntime({
  releaseManifest,
  expectedReleaseManifestSha256:
    INVARIANTCAD_OCCT_FACADE_0_9_0_RELEASE_MANIFEST_SHA256,
  javascript,
  webassembly,
});
const kernel = await createOcctKernel({ attestedRuntime });
```

`releaseManifest`, `javascript`, and `webassembly` are `ArrayBuffer` or
`Uint8Array` values fetched under application-controlled size and network
limits. The loader snapshots their exact views, verifies the canonical manifest
against the independent pin, and checks both runtime files against that trusted
manifest before creating a Blob module URL. It revokes the URL after import;
the evaluated module remains cached for the lifetime of that realm.

The visible attestation report can be structured-cloned, but that clone carries
no executable authority. The private `attestedRuntime` authority cannot be
transferred into another Worker or reproduced outside the evaluated
InvariantCAD internal module instance that created it. Load and verify a new pair
inside each worker/module instance that needs one, and terminate the worker when
hard code/runtime reclamation is required. The pair identity is bound only to
the repository-private artifact fingerprint, while the declared-build identity
and explicit evidence flags do not authenticate build execution, a publisher,
or the host. See
[OCCT runtime attestation](/evaluation/occt-runtime-attestation).

## Worker pattern

Geometry can block the main thread. Put document parsing and evaluation in a
dedicated module worker:

```ts theme={"system"}
// geometry.worker.ts
import { createEvaluator, parseDocumentValue } from "invariantcad";

const evaluatorPromise = createEvaluator();

self.onmessage = async (event) => {
  const parsed = parseDocumentValue(event.data.document);
  if (!parsed.ok) {
    self.postMessage({ ok: false, diagnostics: parsed.diagnostics });
    return;
  }

  const evaluator = await evaluatorPromise;
  const result = await evaluator.evaluate(parsed.value, event.data.options);
  if (!result.ok) {
    self.postMessage({ ok: false, diagnostics: result.diagnostics });
    return;
  }

  try {
    const stl = result.value.output(event.data.output).export("stl");
    self.postMessage({ ok: true, stl }, { transfer: [stl.buffer] });
  } finally {
    result.value.dispose();
  }
};
```

Create it with
`new Worker(new URL("./geometry.worker.ts", import.meta.url), { type: "module" })`
in bundlers that support module-worker URLs.

## Cancellation strategy

Use `AbortSignal` for cooperative cancellation. If the host must enforce a hard
deadline during a synchronous native call, terminate the worker and create a
new one. Do not reuse objects transferred from a terminated realm.

An internal one-shot coordinator used by the release gate rejects pre-abort
without creating a worker, starts the deadline before worker startup, settles
result/abort/timeout/startup races once, terminates every created worker exactly
once, and waits for its termination adapter before returning. Browser
`Worker.terminate()` itself returns `void`; the browser adapter can therefore
confirm the termination request but cannot await or claim worker exit. It is not
exported as a library API; applications should implement an appropriate
ownership and acknowledgement rule in their host framework.

## Release-gated isolation evidence

The production Chromium test loads the committed `13,735`-byte OCCT candidate
v3 asymmetric-box fixture in the main realm, retains those source bytes, and
transfers a distinct copied `ArrayBuffer` into a fresh module worker. It
requires the transfer copy to detach and the retained source to remain
byte-identical.

V3 retains bounded semantic sidecar v2 and adds native identity v1. Its 64-byte
header carries canonical first-`IsSame` direct-child paths plus a complete
rooted pre-order occurrence manifest. Every fixed 12-byte occurrence record
contains shape type, composed orientation, direct-child count, and the
canonical `IsSame` class for solid/shell/wire/face/edge/vertex; compound,
compsolid, and generic-shape nodes are structurally recorded but unindexed.
This removes producer/consumer raw enumeration order and detects occurrence
multiplicity, order, orientation, and `IsSame`-class membership substitution. A
separate critical duplicate-occurrence regression substitutes two uses of one
located TShape for a single occurrence and requires transactional rejection.
The worker exercises decode and scalar observation of the current fixture.

The worker protocol has exact closed message shapes and phase ordering.
Artifact decode admits one matching `started` event, then one `success` or
`failure`. In that success path, the worker creates stock OCCT, confirms that
`shapeArtifacts` and both public codec methods remain absent, decodes through
the repository-private candidate, and captures only scalar volume, topology
counts, candidate version, compatibility fingerprint, and input-immutability
evidence. It disposes the live shape and kernel before posting that evidence; no
native handle crosses the worker boundary.

Separate fresh workers run the actual `Evaluator.evaluate(...)` path over a
fixed `2 × 3 × 7` stock-OCCT box. A successful worker binds the unexported
trusted-store experiment, evaluates cold and warm, and requires `miss,write`
with one native box call followed by `hit` with zero additional box calls.
Volume, face, edge, vertex, output, and diagnostic evidence must match exactly;
public artifact support remains absent, and the worker responds only after
disposing its `EvaluatedDesign` and evaluator. Deadline and post-start abort
runs use an unbound evaluator, emit `started`, enter the wrapped box operation,
complete the real native box, emit `kernel-operation-started`, and then stall
without yielding before the wrapper can return to the evaluator. The host
requests `Worker.terminate()` in both cases. A subsequent fresh worker must
reproduce the successful evaluator's detached scalar evidence exactly.

This proves production-bundle termination requests and deterministic recovery
for the tested stock runtime, not observed exit of the terminated worker.
Neither normal cleanup nor a message from the killed realm is expected after
termination: a killed realm cannot execute language-level `finally` blocks, so
destroying that complete realm is the containment mechanism. The worker cases
are not themselves runtime attestation, live/peak-memory measurement, a real
OCCT-trap injection, trusted-host isolation, cross-edit/persistent assembly
identity, distinct-location `IsPartner`/shared-TShape proof, a cross-platform
golden matrix, a public/production evaluator cache, compatibility certification,
or operational-cancellation certification. The v3 paths remain coordinates in
the exact serialized child hierarchy.

The separate Node owned-runtime gate is repository tooling rather than browser
deployment support. `pnpm test:occt-artifact-process` runs fresh ABI 0.9
producer and consumer child processes, verifies packaged
`metadata/release.json` against the independently maintained reviewed pin,
imports the exact verified JavaScript through the runtime-selected Node module
hook path, passes a fresh verified WASM copy, covers `SIGKILL` deadline/abort
and injected-trap recovery, and explicitly reports
`certifiesCompatibility: false`. Additional children evaluate a deterministic
two-box Boolean union through the real evaluator. Their exact
`operation-started` then `kernel-operation-started` protocol proves entry into
the evaluator-invoked native Boolean path. After the real Boolean returns, the
wrapper emits `non-yielding-stall-started` immediately before entering its
non-yielding stall. Timeout requires that third marker, and abort waits for it
before sending `SIGKILL`; both await child close before fresh-process recovery.
Incomplete nonempty event prefixes are rejected, while a pre-start attestation
failure legitimately emits no marker. Only detached measurements, topology,
document, and runtime evidence can succeed, and only after cleanup; an injected
cleanup failure must fail the operation. The verified facade-bundle gate invokes
this matrix automatically. No temporary executable JavaScript file is created.

Process protocol v3 additionally passes one private evaluator-cache record
through the parent between fresh verified owned-runtime children. Independent
producers must emit identical records after `miss,write`, one native direct-box
construction, and encode; a compatible read-only consumer must `hit`, decode,
perform zero native box calls, and reproduce complete detached geometry
evidence. A different solver fingerprint derives another key and must miss
without invoking either codec direction. The parent validates a bounded,
versioned binary frame, canonical header, exact payload, and SHA-256; tamper,
forged metadata, shared/hostile input, and post-start abort precede a fresh
recovery run. This is explicitly a trusted parent-mediated record, not record
authentication or a public cache API.

## Content Security Policy

WebAssembly compilation may require `wasm-unsafe-eval` in `script-src`,
depending on browser and deployment mode. Test the exact production policy;
avoid broadly enabling `unsafe-eval`. Asset fetching also needs the relevant
`connect-src` or `default-src` allowance. The attested browser loader also
requires `blob:` for module scripts, for example:

```http theme={"system"}
Content-Security-Policy: script-src 'self' blob: 'wasm-unsafe-eval'
```

Use only the directives required by the tested application and browser.

## Tested boundary

The release suite currently guarantees Chromium production-bundle behavior for
the public kernels, a synthetic matched-pair/tamper corpus through the browser
attested loader, and the stock-runtime module-worker scenario described above.
The owned ABI 0.9 pair is exercised through the separate Node process gate, not
as a real owned-browser bundle in this Chromium test. Other evergreen browsers
are plausible but are not claimed as release-gated until executable coverage is
added. The private candidate remains unexported, `shapeArtifacts` remains
absent, and these tests confer no production compatibility or operational
cancellation certification. Ordinary public `Evaluator.evaluate(...)` remains
same-thread and cooperatively cancellable; no public isolated evaluator API,
public cache configuration, compatibility certification, public
compound/compsolid identity class, or cross-platform matrix has been added.
These workers also do not turn repository-private process/realm termination
into hard cancellation in the public evaluator API or make
serialization-local paths persistent across model edits or assemblies.
