Supersedes the demo-gate shell call: frontendDist points at the generated (gitignored) portal-dist/, but the payload was only assembled by Tauri's beforeBuildCommand — which runs solely under the Tauri CLI and shells out to bash. Plain cargo builds (cargo test/check, rust-analyzer) still panicked in tauri::generate_context! on a missing frontendDist, and the bash hook would not run on a Windows client build. Move the allowlist assembly into the portal crate's build.rs in pure Rust so every compile path stages the payload before generate_context! resolves it, with no external shell step and no bash dependency. The build script copies the fixed entry points plus every top-level *.mjs except *.test.mjs, prunes anything stale, and reruns when portal/ changes. Drop the beforeDev/beforeBuild hooks, the now-redundant demo gate call, and scripts/build-portal-dist.sh.
- commit
- e388c67f80453c7d29b64f582411f9f04e1eab4d
- parent
- 0ff59ad1b5d834a6a0b11f3cdc8464e61eb82b46
- author
- Dami <dami.etoile@gmail.com>
| D | scripts/ | 45 | ----------------- |
| M | scripts/ | 7 | --- |
| M | src-tauri/ | 78 | ++++++++++++++++++++++++++++++ |
| M | src-tauri/ | 4 | +- |
@@ -1,45 +0,0 @@
1-2-# Assemble the Portal webview payload from an explicit runtime allowlist.3-#4-# Tauri's frontendDist previously pointed at the raw portal/ source tree, so5-# every file dropped into that directory — test suites included — shipped6-# verbatim inside the signed, notarized app. This script makes the release7-# payload enforceable by construction: only the file classes named below can8-# reach the bundle, and *.test.mjs files are rejected even if a glob would9-# have matched them.10-set -euo pipefail11-12-repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"13-source_dir="${repo_root}/portal"14-dist_dir="${repo_root}/portal-dist"15-16-rm -rf "${dist_dir}"17-mkdir -p "${dist_dir}"18-19-# Runtime payload allowlist. Anything not matched here does not ship.20-allowlist=(21- "index.html"22- "style.css"23- "main.js"24- "codecs.js"25- "audio-worklet.js"26-)27-while IFS= read -r module; do28- allowlist+=("$(basename "${module}")")29-done < <(find "${source_dir}" -maxdepth 1 -name '*.mjs' ! -name '*.test.mjs' | sort)30-31-for file in "${allowlist[@]}"; do32- case "${file}" in33- *.test.mjs)34- echo "refusing to bundle test module: ${file}" >&235- exit 136- ;;37- esac38- if [[ ! -f "${source_dir}/${file}" ]]; then39- echo "allowlisted portal payload file is missing: ${file}" >&240- exit 141- fi42- cp "${source_dir}/${file}" "${dist_dir}/${file}"43-done44-45-echo "portal payload: $(find "${dist_dir}" -type f | wc -l | tr -d ' ') files in ${dist_dir}"@@ -76,13 +76,6 @@ printf 'revision=%s\n' "$(git rev-parse HEAD)"
7676 rustc --version7777 cargo --version7878 79-# Assemble the Portal webview payload before any plain-cargo compile of the80-# portal crate. tauri::generate_context! resolves frontendDist at compile time,81-# and portal-dist/ is generated (gitignored), not committed. Tauri's82-# beforeBuildCommand only runs under the Tauri CLI, so the plain cargo builds83-# below would otherwise panic on a missing frontendDist.84-"$script_dir/build-portal-dist.sh"85-8679 require_rust_test 'resolves_pinned_upstream_gamescope_pipewire_contract' \8780 -p sigil-host --bin sigil8881 cargo fmt --all -- --check@@ -1,3 +1,81 @@
1+use std::collections::BTreeSet;2+use std::env;3+use std::fs;4+use std::path::Path;5+16 fn main() {7+ assemble_portal_dist();28 tauri_build::build()39 }10+11+/// Assemble the Portal webview payload (`../portal-dist`) from an explicit12+/// runtime allowlist before the crate compiles.13+///14+/// `tauri::generate_context!` resolves `frontendDist` at compile time and15+/// `portal-dist/` is generated, not committed, so every build path — plain16+/// `cargo`, `cargo tauri`, and rust-analyzer — needs the directory to exist17+/// without an external shell step (the previous `beforeBuildCommand` hook only18+/// ran under the Tauri CLI and depended on `bash`). Only the file classes named19+/// here can reach the signed bundle; `*.test.mjs` is excluded by construction.20+fn assemble_portal_dist() {21+ let manifest_dir =22+ env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR is set for build scripts");23+ let source_dir = Path::new(&manifest_dir).join("../portal");24+ let dist_dir = Path::new(&manifest_dir).join("../portal-dist");25+26+ // Fixed, non-module runtime entry points. Anything not matched here or by27+ // the module sweep below does not ship.28+ let mut wanted: BTreeSet<String> = [29+ "index.html",30+ "style.css",31+ "main.js",32+ "codecs.js",33+ "audio-worklet.js",34+ ]35+ .iter()36+ .map(|name| (*name).to_string())37+ .collect();38+ for name in &wanted {39+ if !source_dir.join(name).is_file() {40+ panic!("allowlisted portal payload file is missing: {name}");41+ }42+ }43+44+ // Every top-level ES module except test suites.45+ for entry in fs::read_dir(&source_dir).expect("portal source directory must exist") {46+ let entry = entry.expect("readable portal source entry");47+ let is_file = entry48+ .file_type()49+ .map(|kind| kind.is_file())50+ .unwrap_or(false);51+ if !is_file {52+ continue;53+ }54+ let name = entry.file_name().to_string_lossy().into_owned();55+ if name.ends_with(".mjs") && !name.ends_with(".test.mjs") {56+ wanted.insert(name);57+ }58+ }59+60+ fs::create_dir_all(&dist_dir).expect("portal-dist directory is creatable");61+62+ // Copy the allowlist, overwriting stale content, and rebuild whenever any63+ // staged source changes.64+ for name in &wanted {65+ fs::copy(source_dir.join(name), dist_dir.join(name))66+ .unwrap_or_else(|error| panic!("failed to stage portal payload {name}: {error}"));67+ println!("cargo:rerun-if-changed=../portal/{name}");68+ }69+70+ // Prune anything previously staged that is no longer allowlisted.71+ for entry in fs::read_dir(&dist_dir).expect("portal-dist directory is readable") {72+ let entry = entry.expect("readable portal-dist entry");73+ let name = entry.file_name().to_string_lossy().into_owned();74+ if !wanted.contains(&name) {75+ let _ = fs::remove_file(entry.path());76+ }77+ }78+79+ // Watch the directory itself so added or removed source files re-run this.80+ println!("cargo:rerun-if-changed=../portal");81+}@@ -4,9 +4,7 @@
44 "version": "0.1.0",55 "identifier": "sh.goq.portal",66 "build": {7- "frontendDist": "../portal-dist",8- "beforeDevCommand": "bash ../scripts/build-portal-dist.sh",9- "beforeBuildCommand": "bash ../scripts/build-portal-dist.sh"7+ "frontendDist": "../portal-dist"108 },119 "app": {1210 "windows": [