From 1efc20b2b25041d67959992f9b100b7b043be69f Mon Sep 17 00:00:00 2001 From: baiqing Date: Thu, 30 Apr 2026 17:41:50 +0800 Subject: [PATCH] =?UTF-8?q?chore(release):=20bump=201.2.2=20->=201.2.3=20+?= =?UTF-8?q?=20=E8=87=AA=E6=9C=89=20updater=20pubkey=20+=20=E9=87=8D?= =?UTF-8?q?=E5=90=AF=E5=89=8D=20strip=20xattr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复 Codex audit 对 main HEAD a9c81e6 的 2 条 HIGH + 把 macOS auto-update 的 "重启后 Gatekeeper 拦截"问题封死。 ## HIGH #2: 版本号不一致 PR #84 没顺手 bump 版本,main 仍自报 1.2.2,下次直接打 v1.2.3-tauri 会让 updater manifest 自报 1.2.2,已安装的 1.2.2 客户端永远拿不到 "有新版本"。 修:package.json + tauri.conf.json + Cargo.toml 全部改 1.2.3。 ## HIGH #1: updater pubkey 所有权 PR #84 使用的 pubkey 是外部贡献者本地生成的,appergb 不掌握对应 private key。 任何持有那把私钥的人都能签发更新 -> 客户端 OTA 装上恶意版本。 修: - 用 npx @tauri-apps/cli signer generate --ci 生成 appergb 自己的 keypair - 新 pubkey: F0FCDE68E08E6D4E (写入 tauri.conf.json plugins.updater.pubkey) - 私钥已通过 gh secret set TAURI_SIGNING_PRIVATE_KEY 配到 GitHub repo secret - 私钥本地副本只在 /tmp,不进 git,commit 后会清除 ## macOS auto-update 后 strip xattr restart_app 在 app.restart() 前对 .app bundle 跑 /usr/bin/xattr -cr。这是 Tauri auto-updater + 未公证应用的组合下唯一让"自动更新对用户零摩擦"的解法 — 否则 Gatekeeper 在重启时会拦说"OpenLess 已损坏",用户必须开终端 xattr 才能 继续用,违反 auto-update 的本意。 未来发版逻辑必须保留这一步。release-tauri.yml 上一次 PR (#83) 已经在 CI 侧 strip 过一次,本次在 client 侧重启时再 strip 一次,双保险覆盖 "下载 -> 解压 -> 安装 -> 重启"全链路。 --- openless-all/app/package.json | 2 +- openless-all/app/src-tauri/Cargo.lock | 2 +- openless-all/app/src-tauri/Cargo.toml | 2 +- openless-all/app/src-tauri/src/lib.rs | 20 ++++++++++++++++++++ openless-all/app/src-tauri/tauri.conf.json | 4 ++-- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/openless-all/app/package.json b/openless-all/app/package.json index 6bdf51ec..843703bf 100644 --- a/openless-all/app/package.json +++ b/openless-all/app/package.json @@ -1,7 +1,7 @@ { "name": "openless-app", "private": true, - "version": "1.2.2", + "version": "1.2.3", "type": "module", "scripts": { "dev": "vite", diff --git a/openless-all/app/src-tauri/Cargo.lock b/openless-all/app/src-tauri/Cargo.lock index 321e00d9..0311fd9f 100644 --- a/openless-all/app/src-tauri/Cargo.lock +++ b/openless-all/app/src-tauri/Cargo.lock @@ -3250,7 +3250,7 @@ dependencies = [ [[package]] name = "openless" -version = "1.2.2" +version = "1.2.3" dependencies = [ "anyhow", "arboard", diff --git a/openless-all/app/src-tauri/Cargo.toml b/openless-all/app/src-tauri/Cargo.toml index 4ac05434..68dce5bd 100644 --- a/openless-all/app/src-tauri/Cargo.toml +++ b/openless-all/app/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "openless" -version = "1.2.2" +version = "1.2.3" description = "OpenLess — local voice input that types where your cursor is" authors = ["OpenLess"] edition = "2021" diff --git a/openless-all/app/src-tauri/src/lib.rs b/openless-all/app/src-tauri/src/lib.rs index 1121287f..01b33e2b 100644 --- a/openless-all/app/src-tauri/src/lib.rs +++ b/openless-all/app/src-tauri/src/lib.rs @@ -191,6 +191,26 @@ pub fn run() { #[tauri::command] fn restart_app(app: AppHandle) { + // macOS:自动更新会让新装的 .app 带 com.apple.quarantine(无论 Tauri updater + // 怎么解包,下载流由 LaunchServices 接管,输出物可能仍带 xattr)。如果不 + // strip,重启后 Gatekeeper 会拦着说"OpenLess 已损坏 / 来自未识别开发者", + // 用户必须自己开终端跑 xattr -cr 才能继续用 — 违反了"自动更新对用户应该零摩擦"。 + // + // 在 restart 前阻塞地清一次 xattr。失败容忍(PATH 异常、xattr 不存在、磁盘 + // 只读等边角情况),不让它阻塞重启本身。 + #[cfg(target_os = "macos")] + if let Ok(exe) = std::env::current_exe() { + if let Some(bundle) = exe + .ancestors() + .find(|p| p.extension().map(|e| e == "app").unwrap_or(false)) + { + let _ = std::process::Command::new("/usr/bin/xattr") + .arg("-cr") + .arg(bundle) + .status(); + log::info!("[updater] stripped xattr on {:?} before restart", bundle); + } + } app.restart(); } diff --git a/openless-all/app/src-tauri/tauri.conf.json b/openless-all/app/src-tauri/tauri.conf.json index af421d31..19260e0f 100644 --- a/openless-all/app/src-tauri/tauri.conf.json +++ b/openless-all/app/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "OpenLess", - "version": "1.2.2", + "version": "1.2.3", "identifier": "com.openless.app", "build": { "beforeDevCommand": "npm run dev", @@ -68,7 +68,7 @@ }, "plugins": { "updater": { - "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDFERUFBODAzNTY0QzMyM0YKUldRL01reFdBNmpxSGE1K0JadlpONXNWTzhJcGZCRGxjUVdIWExNNFJpeUNsSGZwazdlQThhemkK", + "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEYwRkNERTY4RTA4RTZENEUKUldST2JZN2dhTjc4OE92OWpSR3dlYzAzVm13cG9jd1p6cytUZnVwc3IycnJwTHNDU0xMOThxdmEK", "endpoints": [ "https://github.com/appergb/openless/releases/latest/download/latest-{{target}}-{{arch}}.json" ]