Files
ctms/docs/guides/client-release.md
T
chengchengzhou7 de3dc87920
Client Quality Gates / Shared client and Web (push) Has been cancelled
Client Quality Gates / macOS Desktop (push) Has been cancelled
Storage Persistence Guard / storage-persistence-audit (push) Has been cancelled
Client Quality Gates / Shared client and Web (pull_request) Has been cancelled
Client Quality Gates / macOS Desktop (pull_request) Has been cancelled
Storage Persistence Guard / storage-persistence-audit (pull_request) Has been cancelled
release(main): 准备 v0.1.0 候选版本 (#5)
* docs: add desktop project plan

* feat(desktop): implement phase 1 tauri client

* refactor(client): unify web and desktop release workflow

* feat(desktop): implement phase 2 native capabilities

* 完善桌面端交互体验与发布检查

* 完善桌面端界面、发布检查与邮箱域名同步

* fix(deploy): 修复数据库初始化复用旧镜像

* fix(deploy): 增加部署更新实时进度

* fix(auth): 支持无邮箱后缀时手动输入

* feat(desktop): 稳定桌面端界面与文件操作反馈

- 重构 DesktopPreferences 为分栏式设置面板,整合连接、外观、通知、更新与诊断信息分区,并补充过渡动效与暗色主题样式
- DesktopLayout 侧边栏导航分组支持展开折叠,调整管理/项目区块顺序并统一图标与标题
- 新增 fileTaskFeedback 工具,统一 pickFiles/saveFile/openFile 的成功/取消提示,替换审计导出、权限日志、附件、文档、线程、项目配置等处的直接调用
- desktopUpdateManager 暴露更新状态快照与状态变更监听,区分检查中、安装中、已推迟、失败等状态
- DesktopServerSettings 增加连接诊断信息(检查时间、健康地址、耗时、HTTP 状态)
- unified-page.css 与 ProjectMilestones 引入 CSS 变量以适配暗色主题
- WebLayout 将服务器设置入口改为打开系统偏好面板,管理菜单中邮件服务归入系统设置分组
- ProfileSettings 移除已迁入偏好面板的桌面端专属区块
- 补充 Layout.desktop 布局与偏好面板契约测试

* feat(desktop): 支持桌面端三十天免登录

* 完善桌面端发布稳定化门禁

* 完善桌面端端到端回归收口

* 补齐桌面端附件文件流回归

* 完善桌面端回归与安全边界复审

* 完善桌面体验与系统通知收口

* feat(desktop): 收口桌面工作台视觉与活动反馈

* 优化桌面端界面布局

* style: 优化个人中心和偏好设置弹窗样式,重构工作入口为精致分屏布局并移除首字徽标

* 功能(桌面端):增加在线辅助本地缓存

* 优化桌面端标签导航与后台交互

* ci: 新增 Windows 桌面端内测构建

* fix: 修复桌面检查脚本的 Windows 路径判断

* test: 兼容 Windows 换行的桌面布局断言

* test: 兼容 Windows 换行的路由断言

* ci: 修复 Windows 内测构建配置传参

* ci: 避免 Windows 安装器构建交互等待

* 修复桌面端界面显示与稳定性问题

* feat(网页端): 完善登录后工作台与项目管理体验

* docs(desktop): 精简桌面端约束入口

* feat(admin): 完善审计访问上下文与后台布局

* fix(git): 跟踪原生图标资源

* fix(web): 修正工作台端侧标识

* feat(监控): 完善系统监控、登录状态与访问审计能力

* 修复(权限管理):统一 PM 系统导航与权限校验

* feat(工作台): 优化入口布局与连接安全状态

* feat(桌面与监控): 完善工作台导航和登录活动定位

- 优化桌面标签、上下文标题、前进后退、导航栏隐藏和原生菜单体验

- 补充登录会话 IP 采集、地理位置回退、管理端展示及数据库迁移

- 更新桌面发布检查、运维文档和前后端测试覆盖

* 功能(文档与桌面):完善文件预览下载与客户端构建基线

- 保存文档版本原始文件名,规范下载响应并持久化上传目录\n- 增加 PDF.js 预览、桌面保存打开流程及统一错误反馈\n- 统一 Node.js 22.13 构建基线并收紧临时文件权限门禁\n- 补充迁移、单元测试、发布检查与运维文档

* 功能(文档预览):集成 ONLYOFFICE 安全只读预览与工作台体验

新增 ONLYOFFICE 配置签名、内部内容接口、容器编排与反向代理。

打通网页端和桌面端独立预览工作区,完善文档入口、布局及帮助体验。

补充桌面安全发布门禁、开发脚本、使用文档和前后端测试。

* feat(collaboration): 完善在线文档协作与通知闭环

- 新增协作文件夹、文件、不可变修订、成员、会话、回调回执、编辑申请与分享链接数据模型。

- 补齐新建、导入、复制、下载、回收站、恢复、成员授权、所有权转让及文件级权限接口。

- 接入 ONLYOFFICE 共同编辑、历史版本预览与恢复、修订另存副本、导出下载审计和幂等回调保存。

- 增加编辑权限申请、审批通知、项目提醒聚合、通知 Feed、已读处理及历史待办数据回填。

- 支持公开分享的查看或编辑模式、有效期、密码哈希、失败锁定、短时访问凭证与固定分享地址。

- 增加协作者导出、申请编辑、工作表结构保护和所有权管理策略,并纳入项目接口权限矩阵。

- 新增协作文件库、编辑工作区、公开分享页、下载与另存为对话框,以及导航、路由和权限入口。

- 统一网页端与桌面端通知布局,增加沉浸式工作区和浏览器、Tauri 双端全屏能力。

- 扩展运行时文件下载适配、Tauri 环境识别和原生全屏命令,继续保持业务代码运行时边界。

- 加固 ONLYOFFICE 消息桥的同源下载、签名地址隔离和保存为能力校验,并更新桌面发布检查。

- 增加连续数据库迁移、50MB 上传限制、OnlyOffice 中文文案与开发启动路由校验。

- 补充协作、通知、权限、路由、运行时、布局和 OnlyOffice 相关测试及模块说明文档。

* refactor(frontend): 按需加载页面并清理未使用代码

- 将业务页面路由统一改为动态导入,拆分首屏入口与各功能模块构建产物。

- 将网页端和桌面端布局改为异步组件,避免两套平台布局同时进入初始包。

- 新增 Element Plus 按需安装入口,并通过全局配置组件统一注入中文语言包。

- 提取 API 运行时钩子,在应用启动时注入项目清理、令牌续期和认证失效退出能力。

- 将权限监控面板及地图资源改为延迟加载,补充地图加载状态、失败提示和切换竞态保护。

- 删除已被现有工作流替代的项目成员、接口权限、中心绑定、培训表单及旧项目首页等页面。

- 清理废弃的快捷操作、项目选择、用户选择、FAQ 表单、风险占位组件和旧地图辅助模块。

- 移除未使用的 API 方法、类型、字典、状态机、展示工具、样式和项目详情编辑逻辑。

- 开启 TypeScript 未使用变量与参数检查,并同步收紧相关测试和组件暴露类型。

- 移除未使用的 updater、date-fns 和 Sass 前端依赖,更新锁文件并删除旧 CSS 清洗插件。

- 更新路由、Axios、ETMF、通知、权限监控和桌面布局测试以覆盖重构后的边界。

* fix(审计): 移除共享库审计与预览噪声

* 功能(提醒):统一项目提醒中心与桌面通知链路

增加通用提醒状态、数据库迁移和定时同步,覆盖风险时效、文件回执、项目里程碑、访视窗口与协作申请。

新增网页端和桌面端提醒中心、真实投递诊断与固定隐私通知正文,并补齐登录来源聚合、测试和说明文档。

* feat(deploy): 默认安装 ONLYOFFICE 标准组件

* build(release): 加固 v0.1.0 桌面发布链路 (#3)
2026-07-17 09:47:40 +08:00

9.6 KiB

CTMS Web and Desktop Release Guide

Release Unit

CTMS uses one repository, one promotion path, and one product version. Web and Desktop are build targets from the same source commit, not separately versioned products.

The release identity consists of:

  • semantic version, for example 1.8.0
  • Git tag, for example v1.8.0
  • full Git commit SHA
  • build channel: dev, main, or release
  • client type: web or desktop

Runtime Boundary

Shared Vue business code lives under frontend/src/. Platform decisions are exposed through frontend/src/runtime/index.ts.

The runtime contract currently provides:

  • API base URL resolution
  • Web, macOS, Windows, and Linux runtime identification
  • app version, source commit, build channel, and client type metadata
  • explicit capability flags
  • Desktop server address configuration
  • secure session storage
  • file picker/save/open adapters
  • desktop system notification adapters
  • desktop updater adapters
  • native desktop application menu and shortcut synchronization
  • desktop window lifecycle and system appearance synchronization

Business modules must use this public runtime entry point. They must not inspect Tauri globals or import Tauri packages directly. Native files, notifications, secure session storage, and automatic updates must remain behind frontend/src/runtime/ and explicit capability flags.

Desktop menu accelerators and window appearance are synchronized through narrow Tauri commands owned by frontend/src/runtime/. macOS close/reopen behavior is handled by the Tauri event loop so a genuinely closed main window can be rebuilt from the Dock; these concerns must not move into Vue business modules.

Version Change

Update every client manifest with one command:

cd frontend
npm run version:set -- 1.8.0
npm run version:check

This synchronizes:

  • frontend/package.json
  • frontend/package-lock.json
  • frontend/src-tauri/tauri.conf.json
  • frontend/src-tauri/Cargo.toml
  • frontend/src-tauri/Cargo.lock

Manual edits that leave these files inconsistent fail CI.

Stabilization Gates

Client builds require Node.js 22.13.0 or newer. The development frontend container, Web CI, macOS and Windows release candidates, Windows internal validation, and the production Web image use the same Node 22.13 baseline.

Client release candidates must pass the shared Web checks and the Desktop release/security gate before promotion:

cd frontend
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

release:env:check verifies build channel and commit metadata, and becomes platform-strict with REQUIRE_DESKTOP_SIGNING=true on macOS or REQUIRE_WINDOWS_SIGNING=true on Windows. desktop:release:check statically verifies the Tauri bundle, updater public key, CSP, capability scopes, command allowlist, query-token ban, generic system notification boundary, CI gate coverage, and secure session token boundary. The full manual release, security, regression, and Desktop UX checklist lives in docs/audits/desktop-release-stabilization-checklist.md.

Promotion

  1. Merge feature branches into dev.
  2. Require the shared client/Web and macOS/Windows Desktop CI jobs to pass.
  3. Promote the accepted scope from dev to main.
  4. Set the release version and complete regression testing on main.
  5. Promote main to release.
  6. Create the matching vX.Y.Z tag on the accepted release commit.
  7. Build both Web and Desktop artifacts from that exact tag.

Build metadata is injected by CI:

VITE_BUILD_CHANNEL=release
VITE_BUILD_COMMIT="$(git rev-parse HEAD)"

These values support diagnostics but do not replace the semantic version.

Desktop Updater

Formal Desktop release builds must use Tauri updater signatures. The application embeds the updater public key in frontend/src-tauri/tauri.conf.json; the private key must live only in the organization key vault or CI secret store.

Runtime update checks derive the feed from the currently configured CTMS origin:

/desktop-updates/stable/latest.json

Production update feeds must use HTTPS. Local update testing may use HTTP only for localhost, 127.0.0.1, or ::1.

The release pipeline must:

  1. build from the accepted release tag and commit;
  2. build the Universal macOS app/DMG and Windows x64 NSIS installer from that tag;
  3. sign and notarize macOS, and Authenticode-sign Windows with an RFC 3161 timestamp;
  4. produce macOS .app.tar.gz and Windows .nsis.zip updater artifacts plus their .sig files with the shared updater private key;
  5. generate one combined latest.json and checksum manifest with npm run desktop:update-feed:create;
  6. verify all macOS and Windows entries with npm run desktop:update-feed:check -- --feed <release-dir>/latest.json --artifacts-dir <release-dir> --require-platform windows-x86_64;
  7. upload immutable artifacts first;
  8. atomically replace latest.json last.

For Universal macOS artifacts, latest.json must provide both darwin-aarch64 and darwin-x86_64 entries pointing at the same Universal update package.

The same feed must also contain windows-x86_64, pointing to the signed NSIS .nsis.zip updater package. The Windows .exe installer is distributed next to the updater package but is not used as the updater URL.

The signed release candidate workflow lives at .github/workflows/desktop-release-candidate.yml. It must be run from a matching vX.Y.Z tag and produces a verified release directory as a GitHub artifact. That artifact is still only a release candidate; the release owner must upload immutable files to the production download origin and replace latest.json atomically after validation.

Windows Release and Internal Validation

Windows x64 NSIS is an approved formal Desktop target. Formal Windows builds run in .github/workflows/desktop-release-candidate.yml from the same exact vX.Y.Z tag and SHA as Web and macOS. They must:

  • import a Base64-encoded PFX from WINDOWS_CERTIFICATE using WINDOWS_CERTIFICATE_PASSWORD;
  • configure the imported certificate thumbprint, SHA-256 digest, WINDOWS_TIMESTAMP_URL, and RFC 3161 timestamp mode dynamically in CI;
  • set REQUIRE_WINDOWS_SIGNING=true and use the updater signing secrets;
  • verify the application and installer with Get-AuthenticodeSignature, including signer and timestamp certificates;
  • publish the signed NSIS .exe, .nsis.zip, and .nsis.zip.sig into the combined verified Desktop release directory.

Windows release validation also covers:

  • WebView2 runtime prerequisite behavior;
  • user-level installer assumptions;
  • Windows Credential Manager session storage;
  • path handling and temporary file cleanup;
  • notification and updater compilation;
  • code-signing trust, timestamp validity, and updater signature verification.

The manual internal Windows validation workflow lives at .github/workflows/desktop-windows-internal.yml. It is workflow_dispatch only, runs on windows-latest, injects VITE_BUILD_CHANNEL and VITE_BUILD_COMMIT from the selected branch context, executes the shared client and Desktop safety gates, builds an unsigned NSIS installer with updater artifacts disabled, and uploads the .exe plus SHA256SUMS.txt as a GitHub Actions artifact. This workflow is for internal compatibility verification only; it must not generate latest.json, update feeds, signed release directories, or formal Windows release artifacts. A successful internal build does not substitute for the signed tag-only release workflow.

The formal workflow requires these organization settings:

  • secrets: TAURI_SIGNING_PRIVATE_KEY, TAURI_SIGNING_PRIVATE_KEY_PASSWORD, WINDOWS_CERTIFICATE, and WINDOWS_CERTIFICATE_PASSWORD;
  • variable: WINDOWS_TIMESTAMP_URL;
  • shared versioned HTTPS artifact prefix: DESKTOP_UPDATE_BASE_URL or the manual workflow input.

The checked-in workflow implements the exportable PFX path. Confirm that the organization's certificate policy permits an exportable CI certificate before provisioning it. If the selected CA provides only hardware- or cloud-backed keys, replace the PFX import with a reviewed Tauri signCommand integration (for example, the organization's Azure signing provider) while retaining the same Authenticode and timestamp verification gates.

Required Checks

cd frontend
npm ci
npm run version:check
export VITE_BUILD_CHANNEL=release
export VITE_BUILD_COMMIT="$(git rev-parse HEAD)"
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
export TAURI_SIGNING_PRIVATE_KEY="$UPDATER_PRIVATE_KEY"
export TAURI_SIGNING_PRIVATE_KEY_PASSWORD="$UPDATER_PRIVATE_KEY_PASSWORD"
export REQUIRE_DESKTOP_SIGNING=true
npm run release:env:check
npm run desktop:release-readiness:check
npm run desktop:build:macos-release -- --ci
npm run desktop:update-feed:create -- --artifact <CTMS.app.tar.gz> --platform-artifact windows-x86_64=<CTMS.nsis.zip> --include <CTMS.dmg> --include <CTMS-installer.exe> --base-url <versioned-https-artifact-prefix> --output-dir <release-dir>
npm run desktop:update-feed:check -- --feed <release-dir>/latest.json --artifacts-dir <release-dir> --require-platform windows-x86_64

The macOS and Windows signed builds run in their native CI jobs. macOS requires the Apple signing/notarization credentials defined by the release owner; Windows requires the PFX certificate/password and timestamp URL above. Both use the same updater signing key and are aggregated only after both native jobs pass. Unsigned internal builds are not formal distributions.