From edbff1768054afa80efda721cd1011b29c7fe355 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Fri, 11 Sep 2026 17:47:42 +0200 Subject: feat(packaging): an MSIX target for Microsoft Store submission Store certification of the NSIS "MSI/EXE" submission failed on three checks (silent-install verification, Add/Remove Programs entry, bundleware check) -- traced and reproduced live to one cause: SmartScreen blocks an unsigned, internet-downloaded installer at the shell layer before Microsoft's own unattended validation bot ever gets to run it. MSIX sidesteps this class of failure entirely: submitted through the Store's native pipeline, there is no browser-download-then-launch step for SmartScreen to intercept, and Microsoft signs the package itself at publish time -- free, and specific to this submission type (Trusted Signing remains a paid service for the MSI/EXE path). Full plan and findings: C:\Users\admin\devel\msix-installer.md (out of repo). electron-builder.msix.yml carries the same bundle as Full (node runtime, ffmpeg, both service scripts) -- an AppX/MSIX install never elevates, by design, but that changes only *when* the two elevated operations can run, not whether the daemon ships. No main.js changes were needed: the on-demand elevation path for service-mode (winElevateServiceMode(), driven from the Node page) already existed for a different reason and depends only on service-mode.ps1 being present as an extraResource, true for any packaged Windows target. identityName/publisher/publisherDisplayName are the real values from Partner Center's app-identity reservation, not placeholders. build-win-msix.ps1 points electron-builder at the system Windows 10 SDK (auto-detected) instead of letting it download its own bundled copy -- that download's 7z extraction creates symlinks this target never uses and fails without SeCreateSymbolicLinkPrivilege, reproduced on this machine. build/appx/ carries the four tile images the AppX target requires regardless of showNameOnTiles, generated once from the existing app icon (see that directory's README) since the system-SDK redirect has no vendor samples to fall back to. build/appx-extensions.xml declares windows.startupTask by hand rather than via electron-builder's addAutoLaunchExtension, which always targets the Electron shell -- this points at the bundled node binary instead, matching what "starts at sign in" already means for Full. Verified live via a signed sideload install (self-signed test cert, cleaned up after): the package installs and the app runs correctly. One finding worth carrying forward -- the declared network capabilities (internetClientServer, privateNetworkClientServer) do not create any firewall exemption for this app, most likely because automatic capability-based exemption is an AppContainer-sandbox property and this app deliberately runs full-trust, outside any sandbox. Not a regression: no install-time elevation was possible either way, so the cost is the same one-time OS firewall prompt firewall.ps1's own header already documents as its fallback today. Co-Authored-By: Claude Sonnet 5 --- packages/meshbay-client/build/appx/README.md | 44 +++++++++++++++++++++ .../build/appx/Square150x150Logo.png | Bin 0 -> 38507 bytes .../meshbay-client/build/appx/Square44x44Logo.png | Bin 0 -> 4258 bytes packages/meshbay-client/build/appx/StoreLogo.png | Bin 0 -> 5388 bytes .../meshbay-client/build/appx/Wide310x150Logo.png | Bin 0 -> 32069 bytes 5 files changed, 44 insertions(+) create mode 100644 packages/meshbay-client/build/appx/README.md create mode 100644 packages/meshbay-client/build/appx/Square150x150Logo.png create mode 100644 packages/meshbay-client/build/appx/Square44x44Logo.png create mode 100644 packages/meshbay-client/build/appx/StoreLogo.png create mode 100644 packages/meshbay-client/build/appx/Wide310x150Logo.png (limited to 'packages/meshbay-client/build/appx') diff --git a/packages/meshbay-client/build/appx/README.md b/packages/meshbay-client/build/appx/README.md new file mode 100644 index 0000000..ef47411 --- /dev/null +++ b/packages/meshbay-client/build/appx/README.md @@ -0,0 +1,44 @@ +# AppX/MSIX tile images + +Generated once from `../icon-square.png` (1024×1024), not by any build script +— electron-builder's AppX target (`app-builder-lib/out/targets/AppxTarget.js`) +requires these four regardless of `showNameOnTiles`, and looks for them here +(`packager.getResource(undefined, "appx")` resolves to `build/appx/`) before +falling back to its own vendor-bundled samples. Falling back was not an +option here: this repo points `ELECTRON_BUILDER_WINDOWS_KITS_PATH` at the +system Windows SDK instead of letting electron-builder download its own +copy (see `packaging/win/build-win-msix.ps1`'s comment for why), and the +system SDK has no `appxAssets` samples to fall back to at all. + +| File | Size | Source | +|---|---|---| +| `StoreLogo.png` | 50×50 | resized | +| `Square44x44Logo.png` | 44×44 | resized | +| `Square150x150Logo.png` | 150×150 | resized | +| `Wide310x150Logo.png` | 310×150 | icon centered on a `#464646` canvas (the appx target's own default `backgroundColor`) | + +Regenerate with System.Drawing if the source icon changes: + +```powershell +Add-Type -AssemblyName System.Drawing +$img = [System.Drawing.Image]::FromFile("build\icon-square.png") +function Resize-Square($image, $size, $outPath) { + $bmp = New-Object System.Drawing.Bitmap $size, $size + $g = [System.Drawing.Graphics]::FromImage($bmp) + $g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic + $g.DrawImage($image, 0, 0, $size, $size) + $bmp.Save($outPath, [System.Drawing.Imaging.ImageFormat]::Png) + $g.Dispose(); $bmp.Dispose() +} +Resize-Square $img 50 "build\appx\StoreLogo.png" +Resize-Square $img 44 "build\appx\Square44x44Logo.png" +Resize-Square $img 150 "build\appx\Square150x150Logo.png" + +$bmp = New-Object System.Drawing.Bitmap 310, 150 +$g = [System.Drawing.Graphics]::FromImage($bmp) +$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic +$g.Clear([System.Drawing.Color]::FromArgb(255, 0x46, 0x46, 0x46)) +$g.DrawImage($img, 90, 10, 130, 130) +$bmp.Save("build\appx\Wide310x150Logo.png", [System.Drawing.Imaging.ImageFormat]::Png) +$g.Dispose(); $bmp.Dispose(); $img.Dispose() +``` diff --git a/packages/meshbay-client/build/appx/Square150x150Logo.png b/packages/meshbay-client/build/appx/Square150x150Logo.png new file mode 100644 index 0000000..cd64829 Binary files /dev/null and b/packages/meshbay-client/build/appx/Square150x150Logo.png differ diff --git a/packages/meshbay-client/build/appx/Square44x44Logo.png b/packages/meshbay-client/build/appx/Square44x44Logo.png new file mode 100644 index 0000000..d714c94 Binary files /dev/null and b/packages/meshbay-client/build/appx/Square44x44Logo.png differ diff --git a/packages/meshbay-client/build/appx/StoreLogo.png b/packages/meshbay-client/build/appx/StoreLogo.png new file mode 100644 index 0000000..2062b36 Binary files /dev/null and b/packages/meshbay-client/build/appx/StoreLogo.png differ diff --git a/packages/meshbay-client/build/appx/Wide310x150Logo.png b/packages/meshbay-client/build/appx/Wide310x150Logo.png new file mode 100644 index 0000000..0ca324d Binary files /dev/null and b/packages/meshbay-client/build/appx/Wide310x150Logo.png differ -- cgit v1.2.3