macos-app.md 4.7 KB

macOS App 与本地服务

App、Web 服务、Vue 界面和 Runner 同仓维护。打开 App 会先核对数据目录及已有监听服务;有可信的已有服务则连接,没有则启动包内服务。默认数据目录为 ~/.hermes-yaoyao,默认 Web 端口为 15300。Hermes 是独立基础运行时,由本地服务检测并按既有托管逻辑启动;隔离电脑另需本机 Docker 或 Podman。

生命周期与权限

  • App 单实例;服务和 Runner 各自对实际数据目录持有 SQLite 独占锁。
  • 使用私有随机凭据核对服务实例、PID、数据目录、协议及版本。App 自己启动的服务必须匹配内置版本。连接旧版本外部服务时使用其界面和能力声明。
  • 老 CLI 服务没有描述文件时,只有确认它同时持有目标 SQLite 文件和监听端口才连接。
  • 关闭窗口保留任务;菜单栏和 Dock 可恢复。明确退出等待自己托管的 Runner 和服务结束,不停止外部服务。停止无法确认时显示实际清理错误。
  • 服务崩溃有界重启,睡眠恢复后重新核对连接;错误页面提供重试和日志。
  • Runner 配置由原生文件选择器导入。新配置用 AES-GCM 加密,密钥按数据目录保存在系统钥匙串中;加密助手仅允许所属、同签名团队的 App 调用,明文通过私有进程管道传递。旧 safeStorage 格式仍可在系统授权后读取。Web 页面没有配置解密或桌面启动权限,外部页面不能调用原生桥。

登录启动

“夭夭 → 登录 macOS 时启动”使用系统登录项,默认不开启。用户可另选“登录启动时仅驻留菜单栏”;这个偏好只影响登录启动,手动打开 App 仍显示窗口。正常安装不会改写系统登录项。

源码开发 App 不提供登录项开关;安装包中的开关由系统管理。实际开机/重新登录验收尚未执行,当前验证的是偏好持久化和手动重新打开行为。

更新与回退

App 内置服务随整个 App 更新,不使用源码部署的 LaunchAgent 更新器。菜单“App 更新与回退”显示当前 App/服务版本、托管归属和数据目录。当前采用手动替换 App 的流程,没有启用自动下载安装:

  1. 停止任务并退出 App。若连接已有外部服务,单独按它的原有方式停止,确认没有进程写入数据目录。
  2. 私有备份整个数据目录和正在使用的 App。电脑工作区可使用 docs/computer-maintenance.md 中的校验备份。
  3. 核对新包架构、签名和校验值,再替换 App;启动后核对服务实际版本、健康状态、会话和任务。
  4. 出现问题时退出新 App,恢复原 App;包含数据迁移的升级须同时恢复升级前的数据。App 不主动删除原镜像和工作区备份。

此流程保护签名后的 App 资源不被 Web 更新器改写。正式数据升级/回退必须在停止写入的条件下操作,不能拿运行中数据库的普通文件复制充当一致备份。

构建与验收

npm run desktop:build
npm run desktop:test
npm run desktop:pack
codesign --verify --deep --strict desktop-release/mac-arm64/夭夭.app
hdiutil verify desktop-release/Yaoyao-0.3.32-arm64.dmg

开发 App 的 6 项测试通过:真实内置服务启动、账号与 Runner 连接、关闭窗口保持运行、服务崩溃恢复、外部客户端不误停服务、退出清理、加密配置再次启动、偏好保存及手动重新打开、版本不符拒绝、钥匙串失败保护。另有更新器 14 项定向测试通过,包含 App 禁用源码更新及回退。

desktop-release 中现有旧包仍是此前阶段快照。最终完整平台尚需重新打包、严格签名验证并对实际 App 重跑生命周期测试;开发签名、公证、安装、发布分别记录,不混为已交付。

原生加密核对

Electron 初始化时设置其钥匙串项目名称(v43.4.0 源码)。首次签名包验收在旧项目的系统授权上等待,未修改其权限。新配置改用 Runner 专属、按数据目录区分的原生项目;旧配置保持兼容读取,不强制迁移。

助手使用 CryptoKit AES-GCM、Security.framework 和私有 stdin/stdout,不把密钥放进环境变量、参数或日志。分发版本验证调用 App 路径、签名和团队,拒绝外部 shell 调用;仅用于源码开发的测试助手不会进入安装包。钥匙串调用有 30 秒上限,失败保留原配置。

原生钥匙串加密往返、密文篡改拒绝、跨数据目录拒绝、外部直接调用拒绝,以及完整 Runner 导入/退出/恢复等 8 项桌面测试通过。