fix(desktop): keep packaged frontendDist relative so Windows embeds assets - #7177
Conversation
…ssets Regression introduced by 5673c33 (block#6902, "feat(desktop): add protected-build Bestie experiment"). The protected-build boundary itself is sound; the packaging wrapper that PR added hands Tauri a path shape that Windows parses differently. ## Root cause `tauri-command.mjs` points `frontendDist` at a `mkdtemp` directory so concurrent OSS/internal packages cannot overwrite each other's assets. On Windows that is an absolute path with a drive letter. `FrontendDist` is an untagged serde enum whose **first** variant is `Url(Url)`, and `C:\Users\...` is a valid WHATWG URL with scheme `c:`, so serde selects `Url`. `tauri-codegen` then does: FrontendDist::Url(_url) => Default::default(), // embed nothing A missing *directory* panics with a clear message; a URL is silent. The build exits 0 and produces an installable app with no frontend assets, which boots to `ERR_FILE_NOT_FOUND` in the WebView. Linux and macOS are unaffected — `/tmp/...` has no scheme, so it falls through to `Directory`. This affects every Windows build that goes through `pnpm tauri build`, including `release.yml`'s NSIS job and `windows-canary.yml`. ## Fix Pass the path relative to the config's own directory. `tauri-codegen` resolves `frontendDist` with `config_parent.join(path)`, so a relative path reaches the same directory and cannot parse as a URL. When the temp directory is on another drive there is no relative form, so the scratch root is created beside the config instead. `BUZZ_PROTECTED_BUILD_OUTPUT` still receives the absolute path, and cleanup is unchanged. ## Testing `tauriCommand.test.mjs` asserted against the value it had just been handed, so it could not observe this. Its fake CLI also resolved `frontendDist` against the process cwd, which is not what Tauri does. - Fake CLI now resolves against the config directory, matching `config_parent.join(path)`. - New case asserts the packaged `frontendDist` is not absolute and does not parse as a URL. The absolute check is what fails on Linux/macOS, so the regression stays covered on every platform. - Verified the new case fails on the unpatched wrapper and passes with the fix; the two existing cases pass either way. - Desktop suite: 5844 passed. `useDocumentVisible` has a pre-existing load-dependent flake that also reproduces on an unmodified checkout. - Biome check clean on both files. Verified end to end by rebuilding the Windows NSIS installer: embedded asset keys in `buzz-desktop.exe` went from 0 to 490, and the app launches. Signed-off-by: Jeff Hedlund <jhedlund@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
🔐 Codex Security Review
|
1fcb919 to
1f80098
Compare
| mkdirSync(output, { recursive: true }); | ||
| writeFileSync(path.join(output, "variant.txt"), process.env.VITE_BUZZ_BESTIE); |
There was a problem hiding this comment.
Review by Brain on behalf of Wes (wesbillman).
Please have the fake build write through the producer environment path, while keeping the read below on the config-resolved consumer path. Currently, changing the wrapper's production frontendDist to dist/wrong-subdir still passes all three tests: this fake writes and reads the same wrong location.
I verified the suggestion below in an isolated checkout at 1f80098bb9: valid production code passes 3/3; the wrong-directory mutation fails. The existing relative/non-URL assertions also fail when the absolute-path regression is restored.
| mkdirSync(output, { recursive: true }); | |
| writeFileSync(path.join(output, "variant.txt"), process.env.VITE_BUZZ_BESTIE); | |
| const producer = process.env.BUZZ_PROTECTED_BUILD_OUTPUT; | |
| mkdirSync(producer, { recursive: true }); | |
| writeFileSync(path.join(producer, "variant.txt"), process.env.VITE_BUZZ_BESTIE); |
There was a problem hiding this comment.
Applied in 363d925, with one deviation from the suggestion: I added a
three-line comment above it explaining why the write and the read use
different paths, so it doesn't read as pointless indirection and get
collapsed back later.
Confirmed the finding reproduces here before changing anything. With the
old fixture, repointing the wrapper's override at
path.join(relativeTo(invocationRoot), "wrong-subdir") still passed 3/3.
With the change it's 0/3. The absolute-path regression this PR exists for
is still caught by the relative/non-URL case, on its own assertion.
One caveat worth your opinion: the wrong-directory mutation now fails as
Error: wrapper exited 1 — the fake's readFileSync throwing ENOENT —
rather than a named assertion. It's a genuine failure, but not a
self-explaining one. Happy to give it a clearer shape if you'd prefer.
The fake CLI resolved frontendDist against the config directory and then both wrote and read variant.txt there, so it agreed with itself no matter where the wrapper pointed frontendDist. Repointing the production override at <relative>/wrong-subdir still passed all three cases. Write through BUZZ_PROTECTED_BUILD_OUTPUT -- the absolute path the wrapper publishes for build-protected-feature-artifacts.mjs -- and keep the read on the config-resolved consumer path. The two only agree when the wrapper's relative frontendDist actually reaches the directory the build wrote to. Verified on this branch: - Unmodified wrapper: 3/3 pass. - frontendDist -> <relative>/wrong-subdir: 0/3 with this change, 3/3 without it. - Absolute-path regression restored: the relative/non-URL case still fails on the value it is meant to catch. - Desktop suite: 5843/5844. useDocumentVisible "focused polling pauses on blur" fails about 1 run in 3 in isolation; both of its files are byte-identical to the pre-PR commit, so it is unrelated. - biome check clean. Reported by Brain on behalf of wesbillman in review of block#7177. Signed-off-by: Jeff Hedlund <jhedlund@gmail.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Thanks for this! |
|
@wesbillman thanks for the review! |
|
@wesbillman Thanks again for looking at this PR so quickly. I don't have write access so I can't merge, is that something you do or it gets picked up automatically or what? |
|
@wesbillman I think the new 0.5.22 release is probably broken on Windows without this merged. I haven't confirmed it yet because I have some agents mid-thought right now on my local Buzz, but looking at the size of the file (~42MB) it's near the exact one that broke on my dev that made me push this PR. Normal was ~53MB, with ~42MB the windows assets are missing. As soon as I can I'll confirm on my Windows desktop |
|
No need for me to confirm it locally, #7334 opened with people seeing the issue |
…n (1 commit: block#7177 desktop frontendDist relative path for Windows asset embedding)
* origin/main: fix(desktop): keep packaged frontendDist relative so Windows embeds assets (#7177) fix(sidebar): simplify unread indicators and emphasize priority activity (#7134) Add generic information-flow control core (#7293) feat(buzz-acp): update base prompt; add buzz context and skills to Pi agents (#7335) fix(desktop): restore mention chip identity icons (#7338) Persist video playback speed preference (#7336) Verify ACP relay events before prompt routing (#7010) fix(buzz-acp): bound busy-owner hold to prevent cross-channel starvation (#7337) feat(desktop): invite owned agents from standalone forums (#7125) fix(desktop): authorize remote mentions at publication (#7124) fix(acp): rename system tag to agent-instructions (#7332) fix(desktop): bind duplicate mention selections to exact recipients (#7133) refactor(relay): extract NIP-29 membership authorization (#7285) chore(release): release Buzz Desktop version 0.5.22 (#7308) feat(desktop): preserve mentions across copy and paste (#7228) test(desktop): await Bestie drag and profile hover endpoints (#7294) Signed-off-by: Fizz <400e8babadcee6a7f420103f10a2849d84c4a9c71d5bd04f3948c814216648a3@buzz.block.builderlab.xyz>
* origin/main: chore(release): release Buzz Desktop version 0.5.23 (#7381) fix(desktop): keep packaged frontendDist relative so Windows embeds assets (#7177) fix(sidebar): simplify unread indicators and emphasize priority activity (#7134) Add generic information-flow control core (#7293) feat(buzz-acp): update base prompt; add buzz context and skills to Pi agents (#7335) fix(desktop): restore mention chip identity icons (#7338) Persist video playback speed preference (#7336) Verify ACP relay events before prompt routing (#7010) fix(buzz-acp): bound busy-owner hold to prevent cross-channel starvation (#7337) feat(desktop): invite owned agents from standalone forums (#7125) fix(desktop): authorize remote mentions at publication (#7124) fix(acp): rename system tag to agent-instructions (#7332) fix(desktop): bind duplicate mention selections to exact recipients (#7133) refactor(relay): extract NIP-29 membership authorization (#7285) chore(release): release Buzz Desktop version 0.5.22 (#7308) feat(desktop): preserve mentions across copy and paste (#7228) test(desktop): await Bestie drag and profile hover endpoints (#7294) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
…n-surface * origin/main: (23 commits) chore(release): release Buzz Desktop version 0.5.23 (#7381) fix(desktop): keep packaged frontendDist relative so Windows embeds assets (#7177) fix(sidebar): simplify unread indicators and emphasize priority activity (#7134) Add generic information-flow control core (#7293) feat(buzz-acp): update base prompt; add buzz context and skills to Pi agents (#7335) fix(desktop): restore mention chip identity icons (#7338) Persist video playback speed preference (#7336) Verify ACP relay events before prompt routing (#7010) fix(buzz-acp): bound busy-owner hold to prevent cross-channel starvation (#7337) feat(desktop): invite owned agents from standalone forums (#7125) fix(desktop): authorize remote mentions at publication (#7124) fix(acp): rename system tag to agent-instructions (#7332) fix(desktop): bind duplicate mention selections to exact recipients (#7133) refactor(relay): extract NIP-29 membership authorization (#7285) chore(release): release Buzz Desktop version 0.5.22 (#7308) feat(desktop): preserve mentions across copy and paste (#7228) test(desktop): await Bestie drag and profile hover endpoints (#7294) Collapse contiguous join messages (#7262) chore(release): release Buzz Desktop version 0.5.21 (#7301) fix(scripts): copy global-agent-config.json in buzz-adopt-prod-agents (#7303) ... Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…-enforcement * origin/main: feat(mesh): upgrade to mesh-llm 0.76.0-rc8 and recommend Qwen3.8 27B (#6189) fix(agent): route GPT-5+ model-service FQNs to Responses (#7358) fix(buzz-acp): wake held ACP threads and fence forked sessions (#7340) fix(mobile): style inline code with the app mono face (#6631) chore(release): release Buzz Desktop version 0.5.23 (#7381) fix(desktop): keep packaged frontendDist relative so Windows embeds assets (#7177) fix(sidebar): simplify unread indicators and emphasize priority activity (#7134) Signed-off-by: Hayt <9e1c23a3fd83f61da34420e4e88ff1b16e45cafcc0cd9019eb07d4ecfa8ca9b0@buzz.block.builderlab.xyz>
* origin/main: feat(mesh): upgrade to mesh-llm 0.76.0-rc8 and recommend Qwen3.8 27B (#6189) fix(agent): route GPT-5+ model-service FQNs to Responses (#7358) fix(buzz-acp): wake held ACP threads and fence forked sessions (#7340) fix(mobile): style inline code with the app mono face (#6631) chore(release): release Buzz Desktop version 0.5.23 (#7381) fix(desktop): keep packaged frontendDist relative so Windows embeds assets (#7177) fix(sidebar): simplify unread indicators and emphasize priority activity (#7134) Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
* origin/main: (29 commits) fix(acp): pace targeted overflow recovery on consumer capacity (#7325) fix(link-preview): keep composer fetches user-paced (#7211) feat(mesh): upgrade to mesh-llm 0.76.0-rc8 and recommend Qwen3.8 27B (#6189) fix(agent): route GPT-5+ model-service FQNs to Responses (#7358) fix(buzz-acp): wake held ACP threads and fence forked sessions (#7340) fix(mobile): style inline code with the app mono face (#6631) chore(release): release Buzz Desktop version 0.5.23 (#7381) fix(desktop): keep packaged frontendDist relative so Windows embeds assets (#7177) fix(sidebar): simplify unread indicators and emphasize priority activity (#7134) Add generic information-flow control core (#7293) feat(buzz-acp): update base prompt; add buzz context and skills to Pi agents (#7335) fix(desktop): restore mention chip identity icons (#7338) Persist video playback speed preference (#7336) Verify ACP relay events before prompt routing (#7010) fix(buzz-acp): bound busy-owner hold to prevent cross-channel starvation (#7337) feat(desktop): invite owned agents from standalone forums (#7125) fix(desktop): authorize remote mentions at publication (#7124) fix(acp): rename system tag to agent-instructions (#7332) fix(desktop): bind duplicate mention selections to exact recipients (#7133) refactor(relay): extract NIP-29 membership authorization (#7285) ... Signed-off-by: Tom Brow <tomb@block.xyz>
* origin/main: (77 commits) fix(acp): pace targeted overflow recovery on consumer capacity (#7325) fix(link-preview): keep composer fetches user-paced (#7211) feat(mesh): upgrade to mesh-llm 0.76.0-rc8 and recommend Qwen3.8 27B (#6189) fix(agent): route GPT-5+ model-service FQNs to Responses (#7358) fix(buzz-acp): wake held ACP threads and fence forked sessions (#7340) fix(mobile): style inline code with the app mono face (#6631) chore(release): release Buzz Desktop version 0.5.23 (#7381) fix(desktop): keep packaged frontendDist relative so Windows embeds assets (#7177) fix(sidebar): simplify unread indicators and emphasize priority activity (#7134) Add generic information-flow control core (#7293) feat(buzz-acp): update base prompt; add buzz context and skills to Pi agents (#7335) fix(desktop): restore mention chip identity icons (#7338) Persist video playback speed preference (#7336) Verify ACP relay events before prompt routing (#7010) fix(buzz-acp): bound busy-owner hold to prevent cross-channel starvation (#7337) feat(desktop): invite owned agents from standalone forums (#7125) fix(desktop): authorize remote mentions at publication (#7124) fix(acp): rename system tag to agent-instructions (#7332) fix(desktop): bind duplicate mention selections to exact recipients (#7133) refactor(relay): extract NIP-29 membership authorization (#7285) ... Signed-off-by: Sol <478bb5a31222ea2b28a3d1afb8b1d598940628f19c2a87efc3c4b822299eeec6@buzz.block.builderlab.xyz> # Conflicts: # desktop/src-tauri/src/commands/media_download.rs # desktop/src-tauri/src/lib.rs
…ssets (block#7177) ## Root cause `tauri-command.mjs` points `frontendDist` at a `mkdtemp` directory so concurrent OSS/internal packages cannot overwrite each other's assets. On Windows that is an absolute path with a drive letter. `FrontendDist` is an untagged serde enum whose **first** variant is `Url(Url)`, and `C:\Users\...` is a valid WHATWG URL with scheme `c:`, so serde selects `Url`. `tauri-codegen` then does: FrontendDist::Url(_url) => Default::default(), // embed nothing A missing *directory* panics with a clear message; a URL is silent. The build exits 0 and produces an installable app with no frontend assets, which boots to `ERR_FILE_NOT_FOUND` in the WebView. Linux and macOS are unaffected — `/tmp/...` has no scheme, so it falls through to `Directory`. This affects every Windows build that goes through `pnpm tauri build`, including `release.yml`'s NSIS job and `windows-canary.yml`. ## Fix Pass the path relative to the config's own directory. `tauri-codegen` resolves `frontendDist` with `config_parent.join(path)`, so a relative path reaches the same directory and cannot parse as a URL. When the temp directory is on another drive there is no relative form, so the scratch root is created beside the config instead. `BUZZ_PROTECTED_BUILD_OUTPUT` still receives the absolute path, and cleanup is unchanged. ## Testing `tauriCommand.test.mjs` asserted against the value it had just been handed, so it could not observe this. Its fake CLI also resolved `frontendDist` against the process cwd, which is not what Tauri does. - Fake CLI now resolves against the config directory, matching `config_parent.join(path)`. - New case asserts the packaged `frontendDist` is not absolute and does not parse as a URL. The absolute check is what fails on Linux/macOS, so the regression stays covered on every platform. - Verified the new case fails on the unpatched wrapper and passes with the fix; the two existing cases pass either way. - Desktop suite: 5844 passed. `useDocumentVisible` has a pre-existing load-dependent flake that also reproduces on an unmodified checkout. - Biome check clean on both files. Verified end to end by rebuilding the Windows NSIS installer: embedded asset keys in `buzz-desktop.exe` went from 0 to 490, and the app launches. --------- Signed-off-by: Jeff Hedlund <jhedlund@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Christian Schröder <christian.w.schroeder@gmail.com>
Merge desktop-v0.5.23 into the 0.5.22-2 base; 12 conflicts resolved. Adopt upstream's official frontendDist fix (block#7177), retiring the fork workaround. Keep fork features: @channel/@here scope in useMentions, MessageTimeline providers + pinned intro, MessageRow onUnpin. Adopt upstream mention overhaul (block#7133, block#7228, block#7338), sidebar unread simplification (block#7134), and join-message collapse. Version 0.5.23-1. Signed-off-by: ashish <ashishkaran@gmail.com>
…ssets (block#7177) ## Root cause `tauri-command.mjs` points `frontendDist` at a `mkdtemp` directory so concurrent OSS/internal packages cannot overwrite each other's assets. On Windows that is an absolute path with a drive letter. `FrontendDist` is an untagged serde enum whose **first** variant is `Url(Url)`, and `C:\Users\...` is a valid WHATWG URL with scheme `c:`, so serde selects `Url`. `tauri-codegen` then does: FrontendDist::Url(_url) => Default::default(), // embed nothing A missing *directory* panics with a clear message; a URL is silent. The build exits 0 and produces an installable app with no frontend assets, which boots to `ERR_FILE_NOT_FOUND` in the WebView. Linux and macOS are unaffected — `/tmp/...` has no scheme, so it falls through to `Directory`. This affects every Windows build that goes through `pnpm tauri build`, including `release.yml`'s NSIS job and `windows-canary.yml`. ## Fix Pass the path relative to the config's own directory. `tauri-codegen` resolves `frontendDist` with `config_parent.join(path)`, so a relative path reaches the same directory and cannot parse as a URL. When the temp directory is on another drive there is no relative form, so the scratch root is created beside the config instead. `BUZZ_PROTECTED_BUILD_OUTPUT` still receives the absolute path, and cleanup is unchanged. ## Testing `tauriCommand.test.mjs` asserted against the value it had just been handed, so it could not observe this. Its fake CLI also resolved `frontendDist` against the process cwd, which is not what Tauri does. - Fake CLI now resolves against the config directory, matching `config_parent.join(path)`. - New case asserts the packaged `frontendDist` is not absolute and does not parse as a URL. The absolute check is what fails on Linux/macOS, so the regression stays covered on every platform. - Verified the new case fails on the unpatched wrapper and passes with the fix; the two existing cases pass either way. - Desktop suite: 5844 passed. `useDocumentVisible` has a pre-existing load-dependent flake that also reproduces on an unmodified checkout. - Biome check clean on both files. Verified end to end by rebuilding the Windows NSIS installer: embedded asset keys in `buzz-desktop.exe` went from 0 to 490, and the app launches. --------- Signed-off-by: Jeff Hedlund <jhedlund@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Root cause
tauri-command.mjspointsfrontendDistat amkdtempdirectory so concurrent OSS/internal packages cannot overwrite each other's assets. On Windows that is an absolute path with a drive letter.FrontendDistis an untagged serde enum whose first variant isUrl(Url), andC:\Users\...is a valid WHATWG URL with schemec:, so serde selectsUrl.tauri-codegenthen does:A missing directory panics with a clear message; a URL is silent. The build exits 0 and produces an installable app with no frontend assets, which boots to
ERR_FILE_NOT_FOUNDin the WebView.Linux and macOS are unaffected —
/tmp/...has no scheme, so it falls through toDirectory.This affects every Windows build that goes through
pnpm tauri build, includingrelease.yml's NSIS job andwindows-canary.yml.Fix
Pass the path relative to the config's own directory.
tauri-codegenresolvesfrontendDistwithconfig_parent.join(path), so a relative path reaches the same directory and cannot parse as a URL. When the temp directory is on another drive there is no relative form, so the scratch root is created beside the config instead.BUZZ_PROTECTED_BUILD_OUTPUTstill receives the absolute path, and cleanup is unchanged.Testing
tauriCommand.test.mjsasserted against the value it had just been handed, so it could not observe this. Its fake CLI also resolvedfrontendDistagainst the process cwd, which is not what Tauri does.config_parent.join(path).frontendDistis not absolute and does not parse as a URL. The absolute check is what fails on Linux/macOS, so the regression stays covered on every platform.useDocumentVisiblehas a pre-existing load-dependent flake that also reproduces on an unmodified checkout.Verified end to end by rebuilding the Windows NSIS installer: embedded asset keys in
buzz-desktop.exewent from 0 to 490, and the app launches.