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
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:wasmUrl on the first Manifold initialization in each page or worker. The
first successful initialization fixes the location for that realm, and a later
call with a different explicit URL fails, including one after a default
createEvaluator(). A failed load, such as a 404, is not cached, so a later
call can retry with the same or a corrected URL.
For OCCT:
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: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.
Worker pattern
Geometry can block the main thread. Put document parsing and evaluation in a dedicated module worker:new Worker(new URL("./geometry.worker.ts", import.meta.url), { type: "module" })
in bundlers that support module-worker URLs.
evaluatorPromise holds a single initialization attempt. If that attempt can
fail in your deployment, for example because the WASM asset is missing, clear
the cached promise when it rejects and call createEvaluator() again;
InvariantCAD does not cache a failed Manifold initialization.
Cancellation strategy
Evaluator.evaluate(...) runs on the worker’s thread. When it receives a
signal, it yields to the event loop before geometry work starts, between
selected outputs, and after the last output, so a cancel message can abort it
at those points:
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 committed13,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
Ascript-src (or default-src) policy must allow both kinds of dynamic code
that the bundled runtimes use while they initialize:
'wasm-unsafe-eval'permits WebAssembly compilation.'unsafe-eval'is also required. The bundled Manifold 3.5.1 runtime and the stockocct-wasm3.8.0 glue are Emscripten Embind builds that generate their binding invokers withnew Function. Under a policy without'unsafe-eval', Chromium throwsEvalErrorduring runtime initialization, so neithercreateEvaluator()norcreateOcctKernel()can succeed.'wasm-unsafe-eval'does not cover this.
blob:. The Chromium release gate serves its production
bundle, including its module workers, with exactly this policy:
blob: if the application never uses the attested loader. Asset fetching
also needs the relevant connect-src or default-src allowance for the WASM
URLs. The allowances are needed in every realm that initializes a runtime,
including module workers; the release gate sends the same policy with the page
and with every worker script.
Removing the 'unsafe-eval' requirement would need runtimes rebuilt with
Emscripten’s -sDYNAMIC_EXECUTION=0; InvariantCAD does not ship such builds.
The owned OCCT facade is built from the same Embind glue without that setting,
so expect it to need the same allowance, although the owned pair is not
executed in the Chromium gate. Test the exact production policy in every
browser you support.
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, all served under the Content Security Policy shown in the previous section. 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 observes its signal only at the boundaries described in
cancellation strategy; 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.