Repository navigation
fix(desktop): serve done() and preview harness from memory for sandboxed Chrome - #461
Conversation
The done() verifier and the preview tool wrote their harness HTML under os.tmpdir() and navigated system Chrome to that file:// URL. Chrome builds with a private /tmp (Snap Chromium, Flatpak) cannot see that file, so every verification failed with net::ERR_FILE_NOT_FOUND and generation ended in GENERATION_INCOMPLETE. Fulfil the harness document request through the existing request interception instead, keeping the same file:// URL so relative workspace assets and the file-URL allowlist behave exactly as before. Nothing is written to the temp directory any more. Refs OpenCoworkAI#455
There was a problem hiding this comment.
Findings
No blockers, majors, or minors found. The change is correct and narrowly scoped: both harness loaders serve the document from memory at the same file:// URL through the request interceptors they already install, so <base href>, relative workspace assets, the file-URL allowlist, and error formatting are all unchanged. This matches the stated root cause (sandboxed Chrome with a private /tmp cannot read a file written under os.tmpdir()).
Verification notes from the diff:
apps/desktop/src/main/done-verify.ts:277—verify.htmlis no longer written;srcdocis passed intoverifyWithSystemChrome(...)and served viarespondWithHarnessDocument. Parameter order at both call sites (verifyWithSystemChrome(verifyUrl, verifyPath, srcdoc, workspaceRoot, context?.signal)andhandleVerifierRequest(req, verifyPath, html, workspaceRoot)) lines up with the new signatures.apps/desktop/src/main/preview-runtime.ts:420isHarnessDocumentRequestand:434respondWithHarnessDocumentare checked before the allowlist in both handlers and sit inside the existingtryblocks, so arespond()rejection still degrades toabort().- Cleanup is correct: the
finally { await rm(tempDir, ...) }is removed and no orphan temp directory is created, whilemkdtemp/rmremain live for the disposableuserDataDir(no unused imports). .changeset/done-verify-sandboxed-chrome.mdis present with apatchbump for@open-codesign/desktop.apps/desktop/src/main/harness-document.test.tstargets the exact regression mechanism: the navigation URL is asserted absent on disk and fulfilled viarespond()with the generated body, andcontinue()is asserted never called.isHarnessDocumentRequestedge cases (…verify.html.bak,https:, non-URL) are covered.
Questions
- I could not fetch issue #455 from the public context provided in this run, so I could not independently confirm its acceptance criteria. The PR body says
Closes #455; can a maintainer confirm the issue is limited to thedoneverifier /previewharness document-load failure (no additional runtime paths such as title generation or export in scope)?
Summary
Review mode: initial
Directionally sound and ready to merge; no material issues found. The design explicitly trades an on-disk harness file (which was the failure source) for in-memory interception, and the tests plus the author's real-Chrome/bwrap checks are proportional to the risk.
Residual observations (non-blocking):
- The harness now depends entirely on request interception, so a rare
req.respond()failure on the navigation surfaces asERR_FAILED/aborted rather than falling back to disk. This is an intentional consequence of removing the temp write and is covered by the same interception the allowlist already required — no action needed unless you want a clearer error message on that path. isHarnessDocumentRequestcomparesfileURLToPath(new URL(rawUrl)) === documentPathas an exact string. This round-trips on the producing side, but if Windows CI exists it is worth confirming that drive-letter case normalization in Chrome'sreq.url()does not diverge frompathToFileURL(tmpdir()).- I could not verify #455's acceptance criteria in this run; the diff does touch the expected paths, so the closure claim is plausible.
Testing
Not run (automation). The added harness-document.test.ts is the right unit-level guard. If a Windows runner is available, add one assertion that isHarnessDocumentRequest returns true for a pathToFileURL(join(tmpdir(), ...)) round-trip to lock in cross-platform URL equality.
Open-CoDesign Bot
|
Thanks for the review. I checked #455 and the other Chrome entry points. No code change. Scope of #455. The report is
Windows drive-letter equality. PR CI is |
Summary
The
done()runtime verifier wrote its harness HTML toos.tmpdir()(/tmp/codesign-done-verify-*/verify.html) and pointed system Chrome at thatfile://URL. Chrome builds that run with a private/tmp, such as Snap Chromium (Ubuntu'schromium-browser/chromiumare Snap wrappers) and Flatpak browsers, can't see that file. Every verification then fails withnet::ERR_FILE_NOT_FOUNDand the run ends inGENERATION_INCOMPLETE, even whenApp.jsxis fine. The agentpreviewtool has the same problem because it writespreview.htmlinto its temp profile dir.This PR serves both harness documents from memory through the request interception that is already in place (
req.respond(...)for the exact document URL). Thefile://URL stays the same, so relative workspace assets (<base href>), the file-URL allowlist, and error messages work as before. Nothing gets written to the temp directory anymore, so the verifier no longer needs a filesystem it shares with the browser. The disposableuserDataDirstays intmpdir(). Chrome creates it inside its own namespace, and puppeteer reads the DevTools endpoint from stderr.Root cause reproduction (Linux): I used
bwrap --dev-bind / / --tmpfs /tmp google-chrome, which gives Chrome a private/tmpthe way Snap's per-snap/tmpdoes, asCODESIGN_CHROME_PATH:makeRuntimeVerifier()/ workspace verifierresource failed: net::ERR_FILE_NOT_FOUND [file:///tmp/codesign-done-verify-…/verify.html]+runtime verifier load failed: net::ERR_FILE_NOT_FOUND …(the same two errors as in the issue)[]for a valid artifact, and a realReferenceErroris still reported for a broken onerunPreviewok: false,net::ERR_FILE_NOT_FOUND at file:///tmp/codesign-preview-…/preview.htmlok: true, workspace-relative SVG loadsWith the normal (non-sandboxed) Chrome, the results are the same before and after.
Type of change
Linked issue
Closes #455
Checklist
pnpm lint && pnpm typecheck && pnpm testpasses locallypnpm changeset) if user-visibleTests
apps/desktop/src/main/harness-document.test.ts(mocked puppeteer, runs in CI without Chrome):respond()with the generated document, and it is nevercontinue()dpreview.htmlisHarnessDocumentRequestmatches only the exact document URLmainand pass with this change.done-verify.workspace.test.ts,preview-runtime.test.ts) still pass, including relative workspace assets and blocking files outside the workspace.PRINCIPLES §5b
isHarnessDocumentRequest+respondWithHarnessDocument) covers both without changing the sandbox or allowlist.