Files
nexus/Project/fonrey/TECH_STACK/客户端发布管理技术方案.md
2026-04-30 20:33:51 +08:00

331 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
> **For AI assistants**: Read this entire file before writing any code. All decisions here are final. Do not suggest alternatives unless asked.
# Fonrey 客户端发布管理技术方案
**版本**: 1.0
**项目**: Fonrey 房产经纪管理系统
**技术栈**: Django 4.x + HTMX + PostgreSQL 16public schema+ Redis + Celery + Electron + electron-updater + Cloudflare R2/CDN
**关联 PRD**: `PRD/发布管理/客户端发布管理模块PRD.md`v1.2
**关联数据模型**: `DATA_MODEL/DATA_MODEL_PUBLIC.md``client_releases` / `client_heartbeats`
**关联枚举字典**: `DATA_MODEL/ENUMS.md`(含中文显示标签)
**关联契约规范**: `TECH_STACK/API_CONTRACT.md`
**最后更新**: 2026-04-30
---
## 变更历史
| 日期 | 变更人 | 变更内容 |
|---|---|---|
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
## 一、文档定位与边界
本文件定义客户端发布管理模块(`apps/release`)的实现口径:
1. Electron 客户端壳应用与运行时安全边界
2. EV 代码签名与构建发布链路
3. Heartbeat 上报与版本分布统计方案
4. 自动升级、强制升级与失败回退策略
5. 客户端下载完整性校验SHA256
6. R2 版本资产管理(对象键、状态流转、回滚)
7. 公司下载站点(官网)分发方案
8. 便携版Portable ZIP落地方案
> 本文件不重复 DDL。表结构与索引以 `DATA_MODEL_PUBLIC.md` 为唯一权威。
---
## 二、范围定义(以 PRD v1.2 为准)
### 2.1 P0 必须覆盖
- Windows 客户端win32下载安装与登录使用
- 平台运营后台版本管理(草稿/发布/下线、普通/强制)
- 自动更新(启动 + 每 4 小时检测)
- SHA256 完整性校验EXE/ZIP
- Heartbeat启动时上报与版本分布/租户活跃统计
- 官方下载页(公司站点)
- 便携版 ZIP可选上传、受控分发
### 2.2 非目标(本期不做)
- macOS / Linux 客户端
- 移动端 App
- 客户端离线模式
- 客户端反逆向加固v2
---
## 三、模块架构边界
### 3.1 模块职责(`apps/release`
- 管理端:客户端版本元数据管理、发布状态流转、回滚
- 公共接口客户端更新检测、下载引导、Heartbeat 上报
- 统计接口:版本分布、租户活跃数、历史装机总数
- 资产管理R2 对象键规范、发布包引用与审计
### 3.2 分层与鉴权
| 子能力 | Schema | 鉴权 | 说明 |
|---|---|---|---|
| 版本管理后台 API | public | Platform Admin 必须认证 | 跨租户统一运营能力 |
| 更新检测 API | public | 公开(客户端调用) | 仅返回当前发布版本,不暴露草稿/下线版本 |
| Heartbeat API | public | 已登录客户端会话或签名设备票据 | 防伪造上报、防刷统计 |
| 统计 API | public | Platform Admin 必须认证 | 提供 Story 5 所需聚合指标 |
### 3.3 外部依赖
| 依赖 | 用途 |
|---|---|
| Electron + electron-updater | 客户端壳应用、更新下载与安装 |
| electron-builder | 打包 NSIS EXE + Portable ZIP |
| EV 代码签名证书 | Windows SmartScreen 信任 |
| Cloudflare R2 + CDN | 发布包存储与分发 |
| Celery | 异步计算 checksum / 文件扫描 / 可选预热 |
---
## 四、API 设计原则
1. **路径以 PRD 为准**:统一使用 `/api/release/...` 命名空间。
2. **只允许单一生效版本**:同 `platform + arch` 仅 1 条 `published`
3. **公开接口最小暴露**:客户端仅获取更新必要字段,不返回后台内部字段。
4. **统计可信优先**Heartbeat 仅“启动上报”,按 `(tenant_id, device_id)` Upsert。
5. **完整性优先于安装**:校验失败禁止安装,保留当前版本可用。
6. **强制更新可控**`release_type=force` + `min_required_version` 双保险。
---
## 五、端点清单(核心)
### 5.1 页面路由(平台运营后台)
| 路径 | 方法 | 鉴权 | 说明 |
|---|---|---|---|
| `/platform/release/updates/` | GET | Platform Admin | 版本列表页 |
| `/platform/release/updates/new/` | GET | Platform Admin | 新建版本页 |
| `/platform/release/updates/{id}/edit/` | GET | Platform Admin | 编辑版本页 |
| `/platform/release/metrics/` | GET | Platform Admin | 版本分布与租户活跃榜 |
### 5.2 JSON API对齐 PRD + 数据模型)
| 端点 | 方法 | 说明 |
|---|---|---|
| `/api/release/updates/latest/` | GET | 客户端检查最新版本(公开) |
| `/api/release/updates/` | GET | 管理端查询版本列表 |
| `/api/release/updates/` | POST | 管理端创建版本(草稿/发布) |
| `/api/release/updates/{id}/` | PATCH | 修改状态、版本类型、日志 |
| `/api/release/updates/{id}/rollback/` | POST | 回滚至历史版本(原子切换 published |
| `/api/release/heartbeats/` | POST | 客户端启动上报Upsert |
| `/api/release/metrics/version-distribution/` | GET | 版本活跃分布 |
| `/api/release/metrics/tenant-installs/` | GET | 指定租户活跃安装数 + 历史装机数 |
| `/api/release/metrics/tenant-leaderboard/` | GET | 全平台租户活跃榜 |
> 说明:`heartbeats/metrics` 为实现 Story 5 与 `DATA_MODEL_PUBLIC` 聚合查询所需端点,归属同一模块。
---
## 六、关键 API 规范(请求/响应)
### 6.1 更新检测
`GET /api/release/updates/latest/?platform=win32&arch=x64&current_version=1.2.0`
响应(有更新):
```json
{
"has_update": true,
"latest_version": "1.3.0",
"force_update": false,
"min_required_version": "1.0.0",
"download_url": "https://download.fonrey.com/releases/system/v1.3.0/fonrey-setup-1.3.0-win.exe",
"portable_url": "https://download.fonrey.com/releases/system/v1.3.0/fonrey-portable-1.3.0-win.zip",
"checksum_sha256": "<exe_sha256>",
"portable_checksum_sha256": "<zip_sha256>",
"file_size_bytes": 157286400,
"release_notes": "## v1.3.0\n- ...",
"release_date": "2026-05-01"
}
```
### 6.2 Heartbeat 上报
`POST /api/release/heartbeats/`
```json
{
"device_id": "9e6de37b-8c49-4f9b-af47-52f4e5b8b7f2",
"client_version": "1.3.0",
"platform": "win32",
"arch": "x64",
"os_version": "Windows 11 23H2"
}
```
处理要求:
- 服务端从登录上下文解析 `tenant_id``user_id`
- 使用 `INSERT ... ON CONFLICT (tenant_id, device_id) DO UPDATE`
- 更新 `last_seen_at``launch_count = launch_count + 1`
### 6.3 版本发布(管理端)
`POST /api/release/updates/`
```json
{
"version": "1.3.0",
"platform": "win32",
"arch": "x64",
"release_type": "normal",
"min_required_version": "1.0.0",
"download_url": "https://download.fonrey.com/releases/system/v1.3.0/fonrey-setup-1.3.0-win.exe",
"portable_url": "https://download.fonrey.com/releases/system/v1.3.0/fonrey-portable-1.3.0-win.zip",
"checksum_sha256": "<exe_sha256>",
"portable_checksum_sha256": "<zip_sha256>",
"release_notes": "## v1.3.0\n- ...",
"status": "published"
}
```
---
## 七、HTMX 交互约定(平台运营后台)
- 列表筛选(状态/版本号)使用 HTMX 局刷表格区域
- 发布/下线/回滚操作使用确认弹窗 + 局部刷新
- 成功:`HX-Trigger: toast-success`
- 失败:`HX-Trigger: toast-error`(同时返回标准错误码)
模板建议:
- `templates/release/updates_list.html`
- `templates/release/fragments/updates_table.html`
- `templates/release/fragments/version_distribution_chart.html`
- `templates/release/fragments/tenant_leaderboard_table.html`
---
## 八、权限与数据范围
### 8.1 最小权限矩阵
| 能力 | permission_code |
|---|---|
| 客户端版本列表查看 | `platform.release.view.allow` |
| 创建/编辑发布版本 | `platform.release.edit.allow` |
| 发布/下线/回滚 | `platform.release.publish.allow` |
| 版本分布与租户统计查看 | `platform.release.metrics.view.allow` |
### 8.2 范围规则
- 所有管理能力仅 Platform Admin 可访问
- Tenant Admin / Agent 不可访问平台发布后台
- 数据物理存储在 public schema逻辑上属于平台级共享数据
---
## 九、异步任务与缓存策略
### 9.1 异步任务
| 任务 | 触发时机 | 说明 |
|---|---|---|
| `release_compute_checksum_task` | 文件上传后 | 计算 EXE/ZIP SHA256 并回填 |
| `release_publish_cdn_warmup_task` | 版本发布后 | 可选,预热热点下载节点 |
| `release_scan_artifact_task` | 文件上传后 | 可选,执行恶意文件扫描与审计 |
### 9.2 Redis Key 建议
| Key | TTL | 说明 |
|---|---|---|
| `release:latest:{platform}:{arch}` | 60s | 最新发布版本缓存 |
| `release:metrics:version_distribution` | 60s | 版本分布聚合缓存 |
| `release:metrics:tenant:{tenant_id}` | 60s | 单租户安装/活跃统计缓存 |
| `release:download:ratelimit:{ip}` | 60s | 下载链接接口限流 |
---
## 十、性能与可靠性约束
- 更新检测接口:`p95 < 120ms`(缓存命中)
- Heartbeat 写入:`p95 < 80ms`
- 版本列表页:`p95 < 200ms`
- 发布状态切换使用事务,保证“下线旧版 + 发布新版”原子完成
- 任意更新失败不影响当前版本继续运行(可恢复原则)
---
## 十一、安全与合规
1. Electron 必须启用:`contextIsolation=true``nodeIntegration=false``sandbox=true`
2. 更新包仅允许 HTTPS 下载;域名白名单固定为 `download.fonrey.com`
3. EV 证书私钥仅在 CI 密钥库中可用,禁止落盘到开发机。
4. 校验值由服务端生成并签名传输(至少 TLS + 服务端可信源)。
5. Heartbeat 接口必须防重放/防刷(鉴权 + 频控 + 审计)。
6. 管理端操作(发布、回滚、下线)全部记录审计日志。
---
## 十二、错误码建议
| code | HTTP | 中文含义 |
|---|---|---|
| `RELEASE_VERSION_INVALID` | 400 | 版本号不符合 SemVer |
| `RELEASE_PUBLISHED_CONFLICT` | 409 | 当前平台架构已存在发布版本 |
| `RELEASE_ARTIFACT_NOT_FOUND` | 404 | 发布包不存在或不可访问 |
| `RELEASE_CHECKSUM_MISMATCH` | 400 | 安装包完整性校验失败 |
| `RELEASE_HEARTBEAT_INVALID` | 400 | 心跳参数非法 |
| `RELEASE_PERMISSION_DENIED` | 403 | 权限不足 |
| `RELEASE_RATE_LIMITED` | 429 | 请求过于频繁 |
---
## 十三、测试映射P0
| Story | 测试关注点 |
|---|---|
| Story 1 下载安装 | 官网下载链接可用、签名有效、安装步骤 ≤3、首次启动直达登录 |
| Story 2 客户端使用 | Chromium 内核能力、HTMX/Alpine/Tailwind 渲染一致性、文件上传下载 |
| Story 3 自动升级 | 启动 + 4h 检测、普通更新/强制更新分支、失败可恢复 |
| Story 4 发布管理 | 版本创建/发布/下线/回滚、唯一 published 约束 |
| Story 5 版本分布 | Heartbeat Upsert、活跃统计24h、租户活跃榜排序 |
测试文件建议:`tests/integration/release/test_us_release.py`
---
## 十四、落地顺序建议
1. `apps/release` 模型/服务/API 基础骨架(先打通 `/api/release/updates/latest/`
2. 平台运营后台版本管理页(列表 + 新建 + 发布/下线)
3. Electron 壳应用最小可运行版本(加载 Web + 标题版本)
4. 自动更新链路electron-updater + 后端 latest API
5. Heartbeat 上报 + 统计 API + 后台图表
6. 官网下载页上线(公司域名)
7. 便携版 ZIP 与企业无安装权限场景验收
---
## 十五、文档同步规则
- PRD 发布管理模块变更:同步本文件
- `client_releases/client_heartbeats` 字段变更:同步 `DATA_MODEL_PUBLIC.md`
- 枚举值变更:同步 `DATA_MODEL/ENUMS.md`(含中文标签)
- API 包络/错误契约变更:同步 `TECH_STACK/API_CONTRACT.md`
- 若将来新增独立测试用例文档:同步 `TECH_STACK/测试规范.md` 与测试用例注册表
---
## 附:你关注的 8 个专题落地结论
1. **Electron 方案**:采用 Electron + electron-updater客户端坚持“壳应用”原则。
2. **EV 证书方案**CI 自动签名,证书私钥仅在密钥管理系统。
3. **Heartbeat 方案**:仅启动上报,`(tenant_id, device_id)` Upsert支撑活跃与版本分布。
4. **自动升级方案**:启动 + 每 4h 轮询,普通/强制双模式,失败可恢复。
5. **完整性验证**:下载后先 SHA256 校验,再安装;失败禁止覆盖当前版本。
6. **R2 版本管理**`releases/system/v{version}/...` 路径规范,发布状态驱动可见性。
7. **公司网站下载**`download.fonrey.com` 静态下载页 + 版本信息 + 更新日志。
8. **便携版实现**electron-builder 输出 ZIP首次运行写入用户目录配置不修改系统级安装。