diff --git a/src-tauri/build.rs b/src-tauri/build.rs index b31d0a2..f6b5dbe 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -9,5 +9,35 @@ fn main() { println!("cargo:rustc-link-arg=-Wl,--allow-multiple-definition"); } + assert_localhost_llm_csp(); + tauri_build::build() } + +/// Regression guard for brief item #2 (pre-emptive localhost LLM scope). +/// +/// Kon's bundled llama.cpp server and any BYO Ollama install speak HTTP +/// on `127.0.0.1:*`. If the `connect-src` CSP ever drops those entries, +/// `fetch()` from the webview to the local LLM silently 404s with an +/// opaque scope error (Vibe #438 / #487). We keep the current permit +/// pinned at build time so a stray edit can't regress it unnoticed. +fn assert_localhost_llm_csp() { + let conf_path = std::path::Path::new("tauri.conf.json"); + println!("cargo:rerun-if-changed=tauri.conf.json"); + + let raw = std::fs::read_to_string(conf_path) + .expect("build.rs: failed to read tauri.conf.json for CSP regression guard"); + let csp_start = raw + .find("\"csp\"") + .expect("build.rs: tauri.conf.json missing \"csp\" field"); + // Read the rest of the CSP string — we only need to substring-search. + let csp_slice = &raw[csp_start..]; + for required in ["http://127.0.0.1:*", "ws://127.0.0.1:*"] { + assert!( + csp_slice.contains(required), + "build.rs: tauri.conf.json CSP must permit {required} for local LLM \ + connectivity (brief item #2). Restore the connect-src entry before \ + building." + ); + } +}