Skip to content

feat(macos): add verified update download handoff - #355

Draft
cixiangtao wants to merge 3 commits into
Fei-Away:mainfrom
cixiangtao:codex/verified-auto-update
Draft

feat(macos): add verified update download handoff#355
cixiangtao wants to merge 3 commits into
Fei-Away:mainfrom
cixiangtao:codex/verified-auto-update

Conversation

@cixiangtao

@cixiangtao cixiangtao commented Aug 11, 2026

Copy link
Copy Markdown

Summary

  • upgrade the existing macOS update notification from a Release-page link to an explicit, user-confirmed DMG download
  • bind downloads to the exact stable tag and unique canonical DMG/checksum assets, with bounded metadata and payload sizes plus approved HTTPS redirects
  • verify the GitHub asset digests, SHA256SUMS.txt, DMG integrity, mounted app bundle identity/version, embedded engine version, and code-signature integrity before opening the DMG
  • keep replacement manual: the client never overwrites /Applications, removes quarantine, or silently installs an unsigned package
  • integrate the guided handoff with the bilingual macOS UI introduced upstream, including stable localized failure messages while keeping raw verifier diagnostics out of alerts

Context and scope

This builds on #348, which added the background update check and notification but only opened GitHub Releases. The background check remains metadata-only; downloading starts only after the user confirms.

The branch is synced with main at public v1.5.14 through a regular merge commit; no published branch history was rewritten.

Windows is deliberately out of scope. This PR does not close #276 or #237; the PowerShell 5.1 parsing and Setup handoff need a separate review surface.

The current public macOS artifacts are ad-hoc signed. The API digest and checksum asset protect integrity and wrong-package handling, but they share the GitHub Release trust domain and are not an independent publisher signature. For that reason this is a verified guided handoff, not a silent self-updater.

Validation

  • live GitHub latest-release metadata check (v1.5.14)
  • shell syntax and git diff --check
  • Swift frontend parse and direct typecheck
  • shared runtime asset sync and both platform payload checks
  • all six release-version sources agree on 1.5.14
  • 104 portable Node tests and 6/6 localization contract tests
  • complete macOS wrapper with guided-update success plus checksum mismatch, wrong bundle identity, wrong URL, duplicate asset, draft release, symlink cache, oversized version component, and conflicting-mode rejection

Remaining CI / smoke evidence

This Mac has Command Line Tools but not a full matching Xcode platform, so SwiftPM/XCTest and the packaged DMG build remain CI requirements. Signed-runtime integration and Doctor were also intentionally skipped locally. There is no newer public release than the branch version, so the real menu-to-newer-release download/open path must be smoke-tested when such a release exists. Automated tests intentionally never launch an installer.

@Fei-Away

Copy link
Copy Markdown
Owner

复核意见:方向正确,应该推进,但需要先 rebase。

现状确认:菜单里的更新入口最终就是 NSWorkspace.shared.open(url),跳到 GitHub Releases 页,用户自己下载、自己拖进 Applications。这个 PR 把它升级成「验证过的下载交接」——绑定精确 tag、校验 GitHub asset digest 与 SHA256SUMS.txt、校验 DMG 完整性、挂载后校验 app bundle 身份/版本/内嵌引擎版本与代码签名,然后打开 DMG,替换仍由用户手动完成。

你在描述里给的理由是:当前 macOS 产物是 ad-hoc 签名的,digest 和 checksum 与 Release 共享同一个信任域,不构成独立的发布者签名,所以只做引导式交接而不是静默自更新。这个判断是对的,我同意保留手动替换那一步。

需要调整三点:

1. 基线过时,而且会带回一个刚修掉的 bug。 本 PR 基于 v1.5.14,main 已经是 v1.5.16,并且 #387 修了更新检查的一处真问题:客户端此前优先执行已部署引擎里的 check-update-macos.sh,而该脚本靠读自身同级的 VERSION 判断「当前版本」。引擎是启动后异步安装的,且只要 Codex 在运行安装就会被直接拒绝(Close Codex before installation so config.toml cannot be rewritten while the app is saving it)。这个拒绝一持续,App 已是新版、引擎还停在旧版,客户端就会对着自己正在运行的版本弹更新通知。#387 改成更新检查一律优先用 App 包内副本。本 PR 必须 rebase 到那之后,否则会把旧的解析顺序带回来。

2. 和 #279 绑定看。 有了 Developer ID 签名 + 公证之后,「静默自更新」的安全前提才成立;在那之前引导式交接就是正确的上限。其中 GitHub 的 actions/attest-build-provenance免费的,现在就能加,能证明 DMG 由本仓库哪个 workflow、从哪个 commit 构建——建议在本 PR 或 #279 里先落这一条,它能给这里的校验链加一个独立环节。

3. Windows 记一笔。 你标了 out of scope,同意,但 Windows 的更新入口同样���是打开 Releases 页,而且 check-update.ps1 用的是无界的 Invoke-RestMethod#276)。Windows 的等价工作应在 #276 之后单独做。

顺带一个刚落地的东西对你有用:CI 现在会把 Setup.exe 和 DMG 一起作为 artifact 上传(此前只有 DMG)。你的验收里提到「没有比分支版本更新的公开 release,所以真实的菜单→下载路径无法冒烟」——artifact 至少能让你拿到可安装产物做半程验证。

请 rebase 到 #387 之后,我再做完整复核。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature][Windows]: Bound update-check response before JSON deserialization

2 participants