Phase 9 of the rebrand cascade. Sweep covers everything the Phase 8
frontend pass deliberately skipped: docs/, root markdown, scripts,
Cargo.toml descriptions, code comments that survived earlier
word-boundary sed, plus a handful of identifiers caught on the final
verify pass.
transcription-app changes:
- README.md, HANDOVER.md, KNOWN-ISSUES.md, run.sh — magnotia/Magnotia
-> lumotia/Lumotia.
- docs/ — sweep across all subdirs except docs/handovers/ (preserved
as immutable audit trail). Includes architecture-map references
to magnotia_core::*, magnotia_storage::*, etc. now pointing at
lumotia_*; dev-setup.md tracing output examples (lumotia_startup
target); brief/ + superpowers/ + issues/ + whisper-ecosystem/ +
audit/.
- Cargo.toml descriptions on 9 crates (core, audio, cloud-providers,
hotkey, llm, mcp, plus referenced others).
- crates/core/src/{error,hardware,recommendation,paths}.rs +
crates/audio/src/wav.rs + crates/llm/src/model_manager.rs +
crates/cloud-providers/src/keystore.rs + crates/mcp/src/lib.rs —
doc comments and a model-manager user-agent string.
- Caught on final pass: BroadcastChannel("magnotia_task_sync") -> ...
("lumotia_task_sync"); magnotia_locale i18n localStorage key
renamed + migration shim added; CSS keyframe names
magnotiaPulse / magnotiaBar / magnotiaFade renamed in the design-
system kit; magnotia_viewer_item / magnotia_viewer_mode handoff
keys renamed in HistoryPage + viewer/+page.svelte; src/assets/
wordmark.svg text.
- src-tauri/src/lib.rs comment cleanup ("magnotia era" was sed'd
to "lumotia era" earlier — restored).
Preserved (intentional):
- crates/core/src/paths.rs — keeps "magnotia" / "Magnotia" / ".magnotia"
legacy detection strings in legacy_and_target_paths() so the
migration shim can still find user data from the magnotia era.
- src/lib/stores/{page,focusTimer}.svelte.ts + src/lib/i18n/index.ts
— migration call sites reference the legacy magnotia keys
deliberately.
- docs/handovers/ — historical audit trail.
cargo build --workspace passes. npm run check: 0 errors / 0 warnings
(3958 files). cargo test --workspace: 339 pass / 0 fail.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
82 lines
3.4 KiB
Rust
82 lines
3.4 KiB
Rust
fn main() {
|
|
// INTERIM: both llama-cpp-sys-2 and whisper-rs-sys statically link
|
|
// their own copy of ggml, so GNU ld / lld see duplicate symbols when
|
|
// linking the lumotia binary and its lib-tests. --allow-multiple-definition
|
|
// makes the linker pick the first definition; safe while both crates
|
|
// pin compatible ggml revisions. Replace with a system-ggml shared-lib
|
|
// setup as a follow-up.
|
|
if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("linux") {
|
|
println!("cargo:rustc-link-arg=-Wl,--allow-multiple-definition");
|
|
}
|
|
|
|
assert_loopback_llm_csp();
|
|
|
|
tauri_build::build()
|
|
}
|
|
|
|
/// Regression guard for brief item #2 (pre-emptive loopback LLM scope).
|
|
///
|
|
/// Lumotia'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.
|
|
///
|
|
/// Parses `tauri.conf.json` properly and inspects the `connect-src`
|
|
/// directive of the CSP, rather than substring-searching the whole
|
|
/// file — the latter would both false-pass on unrelated values
|
|
/// containing a loopback URL and false-fail on JSON-escaped forward
|
|
/// slashes.
|
|
fn assert_loopback_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 conf: serde_json::Value =
|
|
serde_json::from_str(&raw).expect("build.rs: tauri.conf.json is not valid JSON");
|
|
|
|
let csp = conf
|
|
.pointer("/app/security/csp")
|
|
.and_then(|v| v.as_str())
|
|
.expect("build.rs: tauri.conf.json missing app.security.csp string");
|
|
|
|
// Split the CSP into directives (`default-src 'self'; script-src ...`)
|
|
// and find the one whose directive NAME is exactly "connect-src".
|
|
// A prefix match would also accept hypothetical future directives
|
|
// like "connect-src-elem" (2026-04-22 review MINOR).
|
|
let connect_src = csp
|
|
.split(';')
|
|
.map(str::trim)
|
|
.find_map(|directive| {
|
|
let (name, rest) = directive.split_once(char::is_whitespace)?;
|
|
if name == "connect-src" {
|
|
Some(rest.trim())
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.expect(
|
|
"build.rs: tauri.conf.json CSP missing connect-src directive — \
|
|
local LLM fetches will be blocked (brief item #2)",
|
|
);
|
|
|
|
let tokens: Vec<&str> = connect_src.split_whitespace().collect();
|
|
for required in ["http://127.0.0.1:*", "ws://127.0.0.1:*"] {
|
|
assert!(
|
|
tokens.contains(&required),
|
|
"build.rs: tauri.conf.json CSP connect-src must permit {required} \
|
|
for local LLM connectivity (brief item #2). Current connect-src: \
|
|
{connect_src:?}"
|
|
);
|
|
}
|
|
for forbidden in ["http://localhost:*", "ws://localhost:*"] {
|
|
assert!(
|
|
!tokens.contains(&forbidden),
|
|
"build.rs: tauri.conf.json CSP connect-src must not permit {forbidden}; \
|
|
normalize local LLM endpoints to 127.0.0.1 instead. Current connect-src: \
|
|
{connect_src:?}"
|
|
);
|
|
}
|
|
}
|