From 7e94a879ce7822fa99e5a09af9803429df96f487 Mon Sep 17 00:00:00 2001 From: Julian Christian Sanders Date: Sat, 18 Jul 2026 07:53:07 -0700 Subject: [PATCH] Keep cold authority boot on the verified path --- .../e2e/world-cell-cold-boot.spec.ts | 25 +++++++++++++++++++ .../e2e/world-cell-webkit-smoke.spec.ts | 4 +++ .../scripts/verify-live-release.mjs | 2 ++ .../src/world-cell-authority-entry.ts | 9 ++++--- .../tests/live-scan-release-gate.test.mjs | 1 + .../tests/world-cell-mobile-boot.test.mjs | 13 +++++----- apps/viewer-web/world-cell-theater.html | 5 +++- 7 files changed, 48 insertions(+), 11 deletions(-) create mode 100644 apps/viewer-web/e2e/world-cell-cold-boot.spec.ts diff --git a/apps/viewer-web/e2e/world-cell-cold-boot.spec.ts b/apps/viewer-web/e2e/world-cell-cold-boot.spec.ts new file mode 100644 index 0000000..f54f2d3 --- /dev/null +++ b/apps/viewer-web/e2e/world-cell-cold-boot.spec.ts @@ -0,0 +1,25 @@ +import { expect, test } from "@playwright/test"; + +test.use({ serviceWorkers: "block" }); + +test("cold authority fetch cannot be preempted by the recovery watchdog", async ({ page }) => { + test.setTimeout(45_000); + let delayedAuthority = false; + await page.route("**/keyxym-v26/keyxym-v26.wasm**", async (route) => { + delayedAuthority = true; + await new Promise((resolve) => setTimeout(resolve, 9_000)); + await route.continue(); + }); + + const response = await page.goto("/world-cell-theater/", { waitUntil: "domcontentloaded" }); + expect(response?.ok()).toBe(true); + await page.waitForTimeout(8_500); + expect(delayedAuthority).toBe(true); + await expect(page.locator("html")).not.toHaveAttribute("data-world-cell-mode", "visual-preview"); + await expect(page.locator("html")).not.toHaveAttribute("data-world-cell-mode", "boot-recovery"); + await expect(page.locator("html")).toHaveAttribute("data-world-cell-mode", "authoritative", { + timeout: 25_000, + }); + await expect(page.locator("html")).toHaveAttribute("data-keyxym-authority", "verified"); + await expect(page.locator("#start-button")).toBeEnabled(); +}); diff --git a/apps/viewer-web/e2e/world-cell-webkit-smoke.spec.ts b/apps/viewer-web/e2e/world-cell-webkit-smoke.spec.ts index e44b9f0..50cabf2 100644 --- a/apps/viewer-web/e2e/world-cell-webkit-smoke.spec.ts +++ b/apps/viewer-web/e2e/world-cell-webkit-smoke.spec.ts @@ -36,6 +36,10 @@ test("iPhone WebKit exposes a basic camera fallback when the release module fail const response = await page.goto("/world-cell-theater.html", { waitUntil: "domcontentloaded" }); expect(response?.ok()).toBe(true); + await page.evaluate(() => { + (window as typeof window & { tessarynWorldCellBootFailure?: (reason: string) => void }) + .tessarynWorldCellBootFailure?.("The World Cell release module could not load."); + }); await expect(page.locator("html")).toHaveAttribute("data-world-cell-mode", "boot-recovery", { timeout: 15_000, diff --git a/apps/viewer-web/scripts/verify-live-release.mjs b/apps/viewer-web/scripts/verify-live-release.mjs index f5aa883..69b1a33 100644 --- a/apps/viewer-web/scripts/verify-live-release.mjs +++ b/apps/viewer-web/scripts/verify-live-release.mjs @@ -98,6 +98,7 @@ if (keyxymManifest.schema !== "keyxym.browser-runtime-provenance/v11" || const legacyTheater = (await fetchBytes("world-cell-theater.html")).bytes.toString("utf8"); if (!/type="module"[^>]+src="\.\/assets\//u.test(legacyTheater) || !legacyTheater.includes('id="retained-source-frame"') || + !legacyTheater.includes("const timeoutMs = 45000") || legacyTheater.includes("/src/world-cell-authority-entry.ts")) { throw new Error("live legacy World Cell Theater route is not the built application entry"); } @@ -113,6 +114,7 @@ if (!canonicalInventory || canonicalRoute.bytes.byteLength !== canonicalInventor if (!//u.test(canonicalTheater) || !/type="module"[^>]+src="\.\.\/assets\//u.test(canonicalTheater) || !canonicalTheater.includes('id="retained-source-frame"') || + !canonicalTheater.includes("const timeoutMs = 45000") || canonicalTheater.includes("/src/world-cell-authority-entry.ts")) { throw new Error("live extensionless World Cell Theater route lacks its root asset contract"); } diff --git a/apps/viewer-web/src/world-cell-authority-entry.ts b/apps/viewer-web/src/world-cell-authority-entry.ts index 0a90e42..084756a 100644 --- a/apps/viewer-web/src/world-cell-authority-entry.ts +++ b/apps/viewer-web/src/world-cell-authority-entry.ts @@ -2,8 +2,8 @@ const root = document.documentElement; root.dataset.worldCellBoot = "module-started"; root.dataset.worldCellMode = "initializing"; -const BOOT_PHASE_TIMEOUT_MS = 8_000; -const PREVIEW_LOAD_TIMEOUT_MS = 12_000; +const BOOT_PHASE_TIMEOUT_MS = 20_000; +const PREVIEW_LOAD_TIMEOUT_MS = 20_000; function setText(id: string, value: string): void { const node = document.getElementById(id); @@ -133,13 +133,14 @@ async function enterPreview(error: unknown): Promise { } async function boot(): Promise { - const serviceWorkerRefresh = refreshServiceWorker(); + // Theater and authority artifacts are network-only in the service worker. + // Refresh it concurrently, never on the provenance/WASM critical path. + void refreshServiceWorker(); try { // Keyxym v0.26 owns monocular RGBA feature tracking, relative pose recovery, // forming output, geometry, quality, and receipts. A verified spatial sensor // is optional evidence that promotes scale from relative to metric; it is not // a prerequisite for loading or executing the reconstruction authority. - await serviceWorkerRefresh; const { verifyKeyxymV26Bundle } = await withTimeout( import("./keyxym-v26-provenance"), BOOT_PHASE_TIMEOUT_MS, diff --git a/apps/viewer-web/tests/live-scan-release-gate.test.mjs b/apps/viewer-web/tests/live-scan-release-gate.test.mjs index b972ec5..bfa53b1 100644 --- a/apps/viewer-web/tests/live-scan-release-gate.test.mjs +++ b/apps/viewer-web/tests/live-scan-release-gate.test.mjs @@ -15,6 +15,7 @@ test("live release verification requires the calibrated spatial continuum and re assert.match(source, /relative-native-triangles/); assert.match(source, /RELATIVE RECONSTRUCTION READY/); assert.match(source, /retained-source-frame/); + assert.match(source, /const timeoutMs = 45000/); assert.match(source, /tessaryn\/spatial-calibration\/v1/); assert.match(source, /Metric capture requires an exact browser media-frame identity/); assert.match(source, /Host-verified synchronized RGB-D/); diff --git a/apps/viewer-web/tests/world-cell-mobile-boot.test.mjs b/apps/viewer-web/tests/world-cell-mobile-boot.test.mjs index 60fa617..a759a94 100644 --- a/apps/viewer-web/tests/world-cell-mobile-boot.test.mjs +++ b/apps/viewer-web/tests/world-cell-mobile-boot.test.mjs @@ -14,7 +14,7 @@ test("mobile boot always leaves VERIFYING through authority, preview, or visible assert.match(theater, /dataset\.worldCellMode = "booting"/); assert.match(theater, /dataset\.worldCellBoot = "html-ready"/); assert.match(theater, /new Set\(\["booting", "initializing", "boot-error"\]\)/); - assert.match(theater, /const timeoutMs = 8000/); + assert.match(theater, /const timeoutMs = 45000/); assert.match(theater, /window\.tessarynWorldCellBootFailure = recover/); assert.match(theater, /WORLD CELL MODULE UNAVAILABLE/); assert.match(theater, /START BASIC CAMERA/); @@ -31,16 +31,17 @@ test("mobile boot always leaves VERIFYING through authority, preview, or visible assert.match(entry, /dataset\.worldCellBoot = "module-started"/); assert.match(entry, /dataset\.worldCellMode = "initializing"/); - assert.match(entry, /const BOOT_PHASE_TIMEOUT_MS = 8_000/); - assert.match(entry, /const PREVIEW_LOAD_TIMEOUT_MS = 12_000/); - assert.match(entry, /const serviceWorkerRefresh = refreshServiceWorker\(\)/); + assert.match(entry, /const BOOT_PHASE_TIMEOUT_MS = 20_000/); + assert.match(entry, /const PREVIEW_LOAD_TIMEOUT_MS = 20_000/); + assert.match(entry, /void refreshServiceWorker\(\)/); assert.match(entry, /"World Cell preview module load"/); assert.match(entry, /installEmergencyShell\(previewError\)/); assert.doesNotMatch(entry, /hasVerifiedSpatialAdapter/); - const authoritativeServiceWorkerWait = entry.indexOf("await serviceWorkerRefresh"); + assert.doesNotMatch(entry, /await serviceWorkerRefresh/); + const concurrentServiceWorkerRefresh = entry.indexOf("void refreshServiceWorker()"); const provenanceVerification = entry.indexOf("verifyKeyxymV26Bundle"); - assert.ok(authoritativeServiceWorkerWait >= 0 && provenanceVerification > authoritativeServiceWorkerWait); + assert.ok(concurrentServiceWorkerRefresh >= 0 && provenanceVerification > concurrentServiceWorkerRefresh); assert.ok( entry.indexOf('dataset.worldCellMode = "initializing"') < entry.indexOf("async function boot"), "module startup state must be visible before asynchronous work", diff --git a/apps/viewer-web/world-cell-theater.html b/apps/viewer-web/world-cell-theater.html index 7ba2354..470aa8f 100644 --- a/apps/viewer-web/world-cell-theater.html +++ b/apps/viewer-web/world-cell-theater.html @@ -103,7 +103,10 @@ root.dataset.worldCellMode = "booting"; root.dataset.worldCellBoot = "html-ready"; const startupModes = new Set(["booting", "initializing", "boot-error"]); - const timeoutMs = 8000; + // A cold mobile edge may need to fetch, hash, compile, and instantiate both + // authority WASM modules. Keep an eventual recovery bound without racing a + // valid first boot into the non-authoritative preview. + const timeoutMs = 45000; let basicStream = null; const setText = (id, text) => {