diff --git a/apps/desktop/README.md b/apps/desktop/README.md index c0c6a5c..e4875cd 100644 --- a/apps/desktop/README.md +++ b/apps/desktop/README.md @@ -39,9 +39,17 @@ cargo test --manifest-path src-tauri/Cargo.toml The Tauri process invokes one fixed executable, without a shell. During local development it resolves `simplicio` from `PATH`; an explicit `SIMPLICIO_RUNTIME_BIN` may be provided by a controlled test or packaging -harness. The production bundle will stage a signed Runtime as a Tauri sidecar -only after the release pipeline validates its manifest, checksum, signature, -SBOM and component lock. +harness. The production bundle stages the exact signed Runtime release asset as a Tauri +sidecar after the release pipeline validates its manifest, checksum, Ed25519 +signature, SBOM and provenance. The bridge prefers that bundled binary, then a +managed per-user installation, and finally the executable on `PATH`. + +For a manual build, stage the verified target-specific Runtime at +`src-tauri/binaries/simplicio-`; for example, +`simplicio-aarch64-apple-darwin` on Apple Silicon. These executable bytes remain +ignored by Git and are never committed to the public source tree. The explicit +`Reparar integrações` action runs the Runtime's governed global installer so +MCP registrations, hooks and detected-host adapters converge together. See [`../../docs/desktop/ADR-0001-public-tauri-shell.md`](../../docs/desktop/ADR-0001-public-tauri-shell.md) for the ownership and security decision. diff --git a/apps/desktop/package-lock.json b/apps/desktop/package-lock.json index be9a59c..eb634cf 100644 --- a/apps/desktop/package-lock.json +++ b/apps/desktop/package-lock.json @@ -1,12 +1,12 @@ { "name": "@simplicio/desktop", - "version": "0.1.0", + "version": "3.8.38", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@simplicio/desktop", - "version": "0.1.0", + "version": "3.8.38", "dependencies": { "@tauri-apps/api": "2.11.1", "react": "19.2.8", diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 0ffb2f9..3ae43d4 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@simplicio/desktop", - "version": "0.1.0", + "version": "3.8.38", "private": true, "type": "module", "scripts": { diff --git a/apps/desktop/src-tauri/Cargo.lock b/apps/desktop/src-tauri/Cargo.lock index e3dbe96..4d8cc1c 100644 --- a/apps/desktop/src-tauri/Cargo.lock +++ b/apps/desktop/src-tauri/Cargo.lock @@ -2807,7 +2807,7 @@ checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" [[package]] name = "simplicio-desktop" -version = "0.1.0" +version = "3.8.38" dependencies = [ "serde_json", "sha2", diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index b8e3705..1d230a9 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "simplicio-desktop" -version = "0.1.0" +version = "3.8.38" description = "Public desktop shell for the Simplicio Runtime" authors = ["SimpleTI"] edition = "2021" diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index ef25a19..a55b379 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -1,10 +1,10 @@ use serde_json::Value; use std::ffi::OsString; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::{Command, Output}; -mod supervisor; mod legacy_snapshot; +mod supervisor; const SNAPSHOT_SCHEMA: &str = "simplicio.desktop-snapshot/v1"; const MAX_SNAPSHOT_BYTES: usize = 65_536; @@ -17,13 +17,14 @@ const LEGACY_AUTH_ARGS: &[&str] = &["auth", "status", "--json"]; const LEGACY_STATUS_ARGS: &[&str] = &["status", "--json"]; const LEGACY_SAVINGS_ARGS: &[&str] = &["savings", "report", "--json"]; const LEGACY_INSTALL_ARGS: &[&str] = &["install", "--global", "--dry-run", "--json"]; -const REGISTER_ARGS_PREFIX: &[&str] = &["mcp", "register", "--binary"]; +const INSTALL_ARGS: &[&str] = &["install", "--global", "--json"]; const SUBSCRIPTION_URL: &str = "https://simpleti.com.br/simplicio"; fn runtime_candidates_with( override_binary: Option, simplicio_home: Option, user_home: Option, + current_executable: Option, ) -> Vec { if let Some(binary) = override_binary { return vec![binary]; @@ -38,7 +39,13 @@ fn runtime_candidates_with( "simplicio" }; - let mut candidates = Vec::with_capacity(2); + let mut candidates = Vec::with_capacity(3); + if let Some(parent) = current_executable + .map(PathBuf::from) + .and_then(|path| path.parent().map(Path::to_path_buf)) + { + candidates.push(parent.join(executable).into_os_string()); + } if let Some(root) = install_root { candidates.push(root.join("bin").join(executable).into_os_string()); } @@ -51,6 +58,7 @@ fn runtime_candidates() -> Vec { std::env::var_os("SIMPLICIO_RUNTIME_BIN"), std::env::var_os("SIMPLICIO_HOME"), std::env::var_os("HOME").or_else(|| std::env::var_os("USERPROFILE")), + std::env::current_exe().ok().map(PathBuf::into_os_string), ) } @@ -93,20 +101,8 @@ fn run_runtime_action(args: &[&str]) -> Result<(), String> { } fn repair_provider_integrations() -> Result<(), String> { - for binary in runtime_candidates() { - let result = Command::new(&binary) - .args(REGISTER_ARGS_PREFIX) - .arg(&binary) - .arg("--json") - .env("SIMPLICIO_DESKTOP_BRIDGE", "1") - .output(); - match result { - Ok(output) if output.status.success() => return Ok(()), - Ok(_) => return Err("O Runtime não conseguiu reparar as integrações".to_string()), - Err(_) => continue, - } - } - Err("Simplicio Runtime não encontrado".to_string()) + run_runtime_action(INSTALL_ARGS) + .map_err(|_| "O Runtime não conseguiu reparar as integrações".to_string()) } fn open_subscription_url() -> Result<(), String> { @@ -141,7 +137,6 @@ fn open_subscription_url() -> Result<(), String> { }) } - fn validate_snapshot(value: Value) -> Result { let encoded = serde_json::to_vec(&value) .map_err(|_| "Contrato de snapshot do Runtime incompatível".to_string())?; @@ -373,20 +368,28 @@ mod tests { LEGACY_INSTALL_ARGS, ["install", "--global", "--dry-run", "--json"] ); - assert_eq!(REGISTER_ARGS_PREFIX, ["mcp", "register", "--binary"]); + assert_eq!(INSTALL_ARGS, ["install", "--global", "--json"]); assert_eq!(SUBSCRIPTION_URL, "https://simpleti.com.br/simplicio"); } #[test] - fn bridge_prefers_the_managed_runtime_and_honors_an_explicit_override() { + fn bridge_prefers_the_bundled_runtime_then_managed_install_and_honors_an_explicit_override() { let managed = runtime_candidates_with( None, Some(OsString::from("/managed/simplicio")), Some(OsString::from("/ignored/home")), + Some(OsString::from("/bundle/simplicio-desktop")), ); assert_eq!( managed, [ + PathBuf::from("/bundle") + .join(if cfg!(windows) { + "simplicio.exe" + } else { + "simplicio" + }) + .into_os_string(), PathBuf::from("/managed/simplicio") .join("bin") .join(if cfg!(windows) { @@ -408,6 +411,7 @@ mod tests { Some(OsString::from("/explicit/runtime")), Some(OsString::from("/managed/simplicio")), None, + Some(OsString::from("/bundle/simplicio-desktop")), ), [OsString::from("/explicit/runtime")] ); diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 208cc3e..2743b59 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "Simplicio", - "version": "0.1.0", + "version": "3.8.38", "identifier": "br.com.simpleti.simplicio", "build": { "beforeDevCommand": "npm run dev", @@ -30,6 +30,7 @@ "active": true, "targets": "all", "icon": ["icons/icon.icns", "icons/icon.ico", "icons/icon.png"], + "externalBin": ["binaries/simplicio"], "category": "DeveloperTool", "shortDescription": "Controle local do Simplicio Runtime", "longDescription": "Login, acesso, economia, memória, diagnósticos e providers do Simplicio Runtime em uma interface nativa." diff --git a/docs/desktop/RELEASE.md b/docs/desktop/RELEASE.md index 2d8dcea..2d2ffd9 100644 --- a/docs/desktop/RELEASE.md +++ b/docs/desktop/RELEASE.md @@ -17,3 +17,10 @@ The updater follows a stage-before-swap transaction: The release acceptance suite must exercise both a successful fresh start and a failed-start rollback. The Desktop UI never presents an update as complete until the Runtime returns a healthy receipt. + +The Tauri bundle must include the exact verified Runtime release binary through +`bundle.externalBin`. Before a native build, stage it at +`apps/desktop/src-tauri/binaries/simplicio-` and verify that its +SHA-256 matches the public Runtime asset. The Desktop bridge resolves this +bundled sidecar before any managed per-user or `PATH` fallback. Target-specific +binary files are release staging material and remain outside Git.