# CTMS Desktop Release Stabilization Checklist 状态: `active` 适用范围: Web 与 macOS Desktop 统一客户端发布 最后更新: `2026-07-01` 本清单用于第一、二阶段桌面端能力完成后的准发布稳定化。它不引入离线登录、本地业务数据存储、内嵌后端服务或离线同步。 ## 1. 发布链路门禁 发布候选提交必须从同一 Git 提交构建 Web 与 Desktop 制品,并完成以下检查: ```bash cd frontend npm ci npm run version:check npm run release:env:check npm run runtime:check npm run desktop:release:check npm run ui:contract npm run type-check npm run test:unit npm run build npm run desktop:build:app ``` 正式发布还必须确认: - [ ] `frontend/package.json`、`package-lock.json`、Tauri 配置、Cargo manifest/lock 版本一致。 - [ ] `VITE_BUILD_CHANNEL=release` 和 `VITE_BUILD_COMMIT=` 由 CI 注入,且 `npm run release:env:check` 通过。 - [ ] 在正式 release tag 和签名环境中执行 `npm run desktop:release-readiness:check`,确认 tag、构建元数据、签名/公证变量、updater 私钥和生产 artifact HTTPS 基址齐备。 - [ ] macOS app 已签名和公证。 - [ ] updater `.sig` 使用组织 CI secret 或密钥库中的私钥生成,私钥未进入仓库。 - [ ] 设置 `TAURI_SIGNING_PRIVATE_KEY`、`TAURI_SIGNING_PRIVATE_KEY_PASSWORD` 和 Apple 签名/公证变量后,以 `REQUIRE_DESKTOP_SIGNING=true` 再次执行 `npm run release:env:check`,随后执行 `npm run desktop:build:macos-release -- --ci`。 - [ ] 正式 updater feed 先执行 `npm run desktop:update-feed:create -- --artifact --base-url --output-dir ` 生成 `latest.json` 与 `SHA256SUMS.txt`。 - [ ] 正式 updater feed 执行 `npm run desktop:update-feed:check -- --feed /latest.json --artifacts-dir `,并确认 checksum manifest、updater artifact、`.sig` 和 `latest.json` 均通过校验。 - [ ] 不可变制品先上传,`latest.json` 最后原子替换;若 feed 校验未通过,不替换线上 `latest.json`。 - [ ] Web 与 Desktop 制品记录同一产品版本、Git 标签和完整提交 SHA。 ## 2. 安全边界复审 自动门禁 `npm run desktop:release:check` 覆盖以下静态约束: - [ ] Tauri bundle 启用 `app`、`dmg` 和 updater artifacts。 - [ ] updater public key 已配置。 - [ ] CSP 禁止 wildcard source、`unsafe-eval`、宽泛 HTTP API 访问和 `object-src`。 - [ ] Tauri capability 不包含 shell 权限、持久文件系统 scope 或宽泛目录读写。 - [ ] 文件系统与 opener scope 只允许 `$TEMP/ctms-desktop/**`。 - [ ] 单实例插件先于其他桌面插件注册。 - [ ] Tauri command 白名单仅包含凭据和更新命令。 - [ ] 前端源码不通过 query string 传递 token。 - [ ] `ctms_token` 只允许由 `secureSessionStorage` 处理。 - [ ] 系统通知只能通过 `frontend/src/runtime/notifications.ts` 发送,标题和正文保持通用。 - [ ] CI release 候选 workflow 包含 version/runtime/desktop/ui/type/unit/build/desktop app smoke 门禁。 - [ ] signed macOS release candidate workflow 只允许从 `vX.Y.Z` tag 运行,并包含签名环境检查、Universal macOS 构建、update feed 生成、checksum 校验和 verified release directory 上传。 人工复审还必须确认: - [ ] token 不出现在 URL、日志、系统通知正文、下载链接或持久化业务缓存中。 - [ ] 桌面端通知正文只显示通用内容,不包含项目、文件或版本详情。 - [ ] 服务端权限、审计和业务数据持久化仍由 FastAPI 后端裁决。 - [ ] Web 运行时不直接导入 Tauri API。 ## 3. 端到端回归矩阵 | 场景 | Web | macOS Desktop | 预期 | | --- | --- | --- | --- | | 登录与项目恢复 | 必测 | 必测 | 登录成功后恢复可访问项目;401 后重新登录 | | 30 天免登录 | 不适用 | 必测 | 关闭并重启 App 后复用系统凭据库中的后端在线会话;超过 30 天或 `/me` 校验失败后重新登录 | | 服务器地址未配置 | 不适用 | 必测 | 自动进入服务器设置,不进入业务页 | | 服务器地址切换 | 不适用 | 必测 | 清除当前会话和项目上下文,要求重新登录 | | 服务端不可达 | 必测 | 必测 | 显示可恢复错误,不进入离线模式 | | 附件上传 | 必测 | 必测 | Web 使用浏览器文件选择,Desktop 使用原生选择 | | 附件下载/保存/打开 | 必测 | 必测 | 使用 Authorization header;无 `?token=` | | 临时文件清理 | 不适用 | 必测 | 启动时清理 `$TEMP/ctms-desktop/**` | | 系统通知开启 | 不适用 | 必测 | 用户主动开启后请求 OS 权限并创建订阅 | | 系统通知拒绝 | 不适用 | 必测 | 开关回退,提示系统权限未开启 | | 通知领取与 ack | 不适用 | 必测 | 显示成功后 ack;失败等待租约重试 | | 单实例重复启动 | 不适用 | 必测 | 恢复、显示并聚焦主窗口 | | 自动更新检查 | 不适用 | 必测 | release 通道按当前 CTMS origin 派生清单 | | 更新稍后提醒 | 不适用 | 必测 | 同版本 24 小时内不重复提示 | | 更新安装失败 | 不适用 | 必测 | 不打断业务录入,显示可排障错误 | ## 4. 桌面体验验收 - [ ] 登录页显示当前桌面服务器地址,长 URL 不撑破登录面板。 - [ ] 30 天免登录仍只保存系统凭据库会话记录,不保存密码,不把 token 写入 URL、日志、通知正文或业务缓存。 - [ ] 服务器设置页显示当前服务器、连接检查状态、HTTP 错误、超时和网络失败原因。 - [ ] 个人中心显示客户端类型、版本、平台、构建通道、提交、服务器和能力状态。 - [ ] 个人中心可复制诊断信息,内容不包含 token 或业务敏感数据。 - [ ] 通知开关显示 OS 权限状态。 - [ ] 手动检查更新能反馈“已是最新版本”、未启用更新或检查失败。 - [ ] 关键弹窗、表单、按钮在最小窗口尺寸 `1180x760` 下不重叠、不溢出。 - [ ] 更新弹窗只显示版本、发布日期和通用 release notes,不展示 token、下载链接或业务详情。 ## 5. 不允许项 - [ ] 不实现离线登录、离线浏览、离线队列或离线同步。 - [ ] 不在桌面端保存 CTMS 业务数据副本。 - [ ] 不内嵌 FastAPI、PostgreSQL、SQLite 或本地业务 API 镜像。 - [ ] 不绕过后端做本地权限裁决或本地审计回放。 ## 6. 2026-07-01 收尾验证记录 本轮收尾验证在 `/Users/zcc/MyCTMS/ctms-dev/worktrees/ctms-desktop` 的 detached HEAD `c923f887` 上执行,包含当前工作区文档与 CI 门禁调整。 已通过的自动门禁: - `cd frontend && npm run version:check` - `cd frontend && npm run release:env:check` - `cd frontend && npm run runtime:check` - `cd frontend && npm run desktop:release:check` - `cd frontend && npm run ui:contract` - `cd frontend && npm run type-check` - `cd frontend && npm run test:unit` - `cd frontend && npm run build` - `cd frontend && npm run desktop:build:app` - `cd frontend && node --check scripts/verify-desktop-update-feed.mjs` 验证结论: - Tauri 运行时边界、release 静态安全门禁、构建元数据预检、版本一致性和 UI 合约均通过。 - Web 生产构建和未签名 macOS `.app` smoke 构建均可重复执行。 - 当前 CI 已补齐 `npm run release:env:check` 和 `npm run ui:contract`,tag 构建会将 `VITE_BUILD_CHANNEL` 规范为 `release` 并校验 tag 与版本号一致。 - updater feed 校验脚本已完成语法检查;正式 `latest.json` 需要在签名 updater artifacts 生成后执行实物校验。 仍需正式发布前人工确认: - macOS 签名、公证、Apple Developer 凭据和组织 updater 私钥。 - 签名后的 updater artifacts、`.sig`、checksum manifest 和 `latest.json` 在真实发布目录内通过 `npm run desktop:update-feed:check`。 - 不可变制品上传完成后,再原子替换线上 `latest.json`。 - Desktop 端到端人工回归矩阵、最小窗口体验验收和系统通知/自动更新真实环境验证。 ## 7. 2026-07-02 发布稳定化推进记录 本次推进补齐了发布链路自动化,不改变桌面端产品边界: - 新增 `npm run desktop:build:macos-release`,封装 Universal macOS `app`/`dmg` release candidate 构建命令。 - 新增 `npm run desktop:update-feed:create`,从签名 updater artifact 和 `.sig` 生成 `latest.json`、复制发布目录文件并生成 `SHA256SUMS.txt`。 - `npm run desktop:update-feed:check` 在传入 `--artifacts-dir` 时要求并校验 `SHA256SUMS.txt`。 - 新增 `npm run desktop:release-readiness:check`,在正式签名候选构建前检查 release tag、构建元数据、签名/公证变量、updater 私钥和生产 artifact HTTPS 基址。 - 新增 `.github/workflows/desktop-release-candidate.yml`,在 release tag 上执行签名候选构建、feed 生成、feed 校验并上传 verified release directory。 - `npm run desktop:release:check` 已检查上述脚本和 workflow,避免发布链路回退。 仍未自动完成、正式发布前必须人工确认: - Apple Developer 凭据、证书、签名身份、公证结果和组织 updater 私钥。 - 生产下载源的不可变制品上传和线上 `latest.json` 原子替换。 - 真实环境下的自动更新安装、系统通知、单实例和完整人工回归。 ## 8. 2026-07-02 端到端回归优化记录 本轮端到端优化仍保持在线桌面客户端边界,不引入离线、本地业务存储或本地权限裁决。 已完成的自动化收口: - 服务器地址切换时,桌面设置页调用 `auth.logout({ rememberCurrentStudy: false })`,避免退出时把旧服务器项目记入当前用户的最近项目;随后继续清除当前项目上下文。 - 系统通知轮询在部分通知显示失败时,先 ack 已成功显示的通知,再让失败项通过租约重试,贴合“显示成功后 ack;失败等待重试”的回归预期。 - 自动更新管理器新增稍后提醒 24 小时抑制、安装失败可重试、检查失败不打断业务和未启用更新状态的单元覆盖。 - 附件 API 新增 blob 下载、multipart 上传和删除端点单元覆盖,确保下载凭据继续由 axios Authorization header 承载而不是进入 URL。 - 文件任务反馈 helper 新增选择、保存、取消保存和打开的单元覆盖,约束桌面保存/打开继续走 `frontend/src/runtime/` 适配层。 - 新增相关单元测试覆盖服务器切换不记忆旧项目、通知权限未授权不领取、部分通知失败时只 ack 成功项、自动更新失败恢复路径,以及附件文件流契约。 仍需人工或真实环境验证: - Keychain/凭据库 30 天在线会话恢复。 - 原生附件上传、下载、保存和打开。 - 系统通知授权/拒绝的 OS 级交互。 - 单实例重复启动聚焦主窗口。 - 签名 release 构建下的自动更新 feed、验签、安装和重启实物流。