From f486ff4cbc755337a74d0588ed95774827d89bda Mon Sep 17 00:00:00 2001 From: Jake Date: Wed, 22 Apr 2026 00:26:15 +0100 Subject: [PATCH] feat(A.1 #2): build-time CSP regression guard for localhost LLM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pins the connect-src CSP entries for http://127.0.0.1:* and ws://127.0.0.1:* at build time. If a future edit to tauri.conf.json strips the local-LLM permit, the kon crate fails to build rather than shipping a binary whose webview fetch() silently 404s with an opaque scope error (Vibe #438 / #487). Closes item #2 of docs/whisper-ecosystem/brief.md — CSP widening itself landed in an earlier commit; this is the regression-proofing the plan calls for. --- src-tauri/build.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) 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." + ); + } +}