添加变更历史 添加ARD文档
This commit is contained in:
330
Project/fonrey/TECH_STACK/客户端发布管理技术方案.md
Normal file
330
Project/fonrey/TECH_STACK/客户端发布管理技术方案.md
Normal file
@@ -0,0 +1,330 @@
|
||||
> **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 16(public 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¤t_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,首次运行写入用户目录配置,不修改系统级安装。
|
||||
Reference in New Issue
Block a user