diff --git a/Project/fonrey/ADR.md b/Project/fonrey/ADR.md new file mode 100644 index 00000000..59f8355b --- /dev/null +++ b/Project/fonrey/ADR.md @@ -0,0 +1,206 @@ +# Fonrey ADR 动态决策记录(Architecture & Requirement Decision Records) + +> 目的:沉淀 Vibe Coding 过程中的**技术决策**与**需求决策**,避免跨会话后方案漂移。 +> 适用范围:全项目(TECH_STACK / DATA_MODEL / PRD / TEST_CASES / 开发流程)。 +> 维护原则:新增决策只追加,不覆盖历史;若决策被替代,必须新增 supersede 记录。 + +--- + +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 初始化 ADR 动态决策记录;补录当日关键技术与需求决策 | + +## 一、记录规范(必须遵守) + +### 1.1 决策ID规则 +- 格式:`ADR-YYYYMMDD-XXX` +- 例:`ADR-20260430-001` + +### 1.2 决策类型 +- `TECH`:技术决策(架构、接口、数据、测试、流程规范) +- `REQ`:需求决策(范围、术语、优先级、验收口径) + +### 1.3 状态枚举 +- `accepted`:已生效 +- `superseded`:已被替代(需指向新 ADR) +- `deprecated`:废弃(不再执行) + +### 1.4 最小字段 +每条 ADR 必须包含: +1. 决策ID +2. 日期 +3. 模块 +4. 类型(TECH/REQ) +5. 状态 +6. 背景 +7. 决策内容 +8. 影响范围 +9. 关联文档 +10. 备注(可选) + +--- + +## 二、按日期记录(主索引) + +## 2026-04-30 + +### ADR-20260430-001 +- **类型**:REQ +- **模块**:测试治理(全局) +- **状态**:accepted +- **背景**:测试文档与沟通中存在“业务旅程/测试用例”术语混用,易导致执行偏差。 +- **决策**:全项目统一使用“测试用例”术语,不再以“业务旅程”作为执行口径。 +- **影响范围**:`TECH_STACK/测试规范.md`、`TEST_CASES/*` +- **关联文档**:`TECH_STACK/测试规范.md` + +### ADR-20260430-002 +- **类型**:TECH +- **模块**:测试治理(全局) +- **状态**:accepted +- **背景**:多模块并行时测试编号易重复、不可追溯。 +- **决策**:采用全局唯一测试用例编号:`TC-FON-XXXXXX`,并建立注册表,禁止复用废弃编号。 +- **影响范围**:所有测试用例文档与测试报告系统 +- **关联文档**: + - `TEST_CASES/TEST_CASE_ID_SPEC.md` + - `TEST_CASES/TEST_CASE_REGISTRY.md` + +### ADR-20260430-003 +- **类型**:TECH +- **模块**:测试执行与报告 +- **状态**:accepted +- **背景**:失败定位粒度不足,无法快速定位到具体步骤。 +- **决策**:测试报告必须支持 `test_case_id + step_id` 级追踪,并记录 `expected/actual/error_message` 与证据路径。 +- **影响范围**:CI 报告、自动化测试框架 +- **关联文档**:`TECH_STACK/测试规范.md` + +### ADR-20260430-004 +- **类型**:REQ +- **模块**:登录管理 +- **状态**:accepted +- **背景**:登录 PRD v2.0 与技术方案存在接口命名漂移。 +- **决策**:登录模块接口路径以 PRD v2.0 为唯一权威,技术方案与测试用例全部对齐 PRD 路径。 +- **影响范围**:登录模块 API 设计、自动化测试调用路径 +- **关联文档**: + - `PRD/登录管理/用户登录管理模块PRD.md` + - `TECH_STACK/登录管理技术方案.md` + - `TEST_CASES/TEST_CASES_LOGIN_MODULE.md` + +### ADR-20260430-005 +- **类型**:REQ +- **模块**:登录管理 +- **状态**:accepted +- **背景**:Story 边界存在历史遗留混淆。 +- **决策**:登录模块范围冻结为:短信验证码登录为 MVP 正式能力;“找回用户名”废弃;微信扫码保留为预留。 +- **影响范围**:实现范围、测试覆盖边界 +- **关联文档**: + - `PRD/登录管理/用户登录管理模块PRD.md` + - `TECH_STACK/登录管理技术方案.md` + +### ADR-20260430-006 +- **类型**:TECH +- **模块**:客户端发布管理 +- **状态**:accepted +- **背景**:发布模块缺少可执行技术方案,无法指导实现与测试。 +- **决策**:新增独立技术方案文档,明确 Electron 壳层边界、EV 签名、Heartbeat、自动更新、完整性校验、R2 版本管理、官网分发、便携版策略。 +- **影响范围**:`apps/release` 设计与落地 +- **关联文档**: + - `TECH_STACK/客户端发布管理技术方案.md` + - `PRD/发布管理/客户端发布管理模块PRD.md` + +### ADR-20260430-007 +- **类型**:TECH +- **模块**:客户端发布管理 / 数据模型 +- **状态**:accepted +- **背景**:统计口径需支撑跨租户版本分布与活跃安装数。 +- **决策**:以 `public.client_heartbeats` 作为心跳事实表,使用 `(tenant_id, device_id)` 为 Upsert 锚点,活跃定义为最近 24h。 +- **影响范围**:统计接口、看板与聚合查询 +- **关联文档**:`DATA_MODEL/DATA_MODEL_PUBLIC.md` + +### ADR-20260430-008 +- **类型**:TECH +- **模块**:客户端发布管理 / 安全 +- **状态**:accepted +- **背景**:下载链路存在篡改与损坏风险。 +- **决策**:客户端更新包必须进行 SHA256 完整性校验,校验失败禁止安装并保留当前版本可用。 +- **影响范围**:客户端更新器、发布接口响应字段 +- **关联文档**: + - `TECH_STACK/客户端发布管理技术方案.md` + - `PRD/发布管理/客户端发布管理模块PRD.md` + +### ADR-20260430-009 +- **类型**:TECH +- **模块**:客户端发布管理 / API +- **状态**:accepted +- **背景**:历史文档存在 `/api/client/updates/*` 与 `/api/release/updates/*` 双口径。 +- **决策**:发布模块统一采用 `/api/release/...` 命名空间。 +- **影响范围**:服务端路由、客户端调用、测试用例 +- **关联文档**: + - `PRD/发布管理/客户端发布管理模块PRD.md` + - `TECH_STACK/TECH_STACK.md` + - `TECH_STACK/客户端发布管理技术方案.md` + +### ADR-20260430-010 +- **类型**:TECH +- **模块**:文档治理(全局) +- **状态**:accepted +- **背景**:多目录文档缺少统一变更追溯入口。 +- **决策**:`TECH_STACK / DATA_MODEL / TEST_CASES` 下文档统一添加“变更历史”章节,并规范位置:**头部元信息之后、正文主章节(## 一/## 1)之前**。 +- **影响范围**:全量技术文档与测试文档 +- **关联文档**: + - `TECH_STACK/*.md` + - `DATA_MODEL/*.md` + - `TEST_CASES/*.md` + +--- + +## 三、按模块分类记录(视图索引) + +## 3.1 测试治理(全局) +- `ADR-20260430-001`:术语统一为“测试用例”(REQ) +- `ADR-20260430-002`:全局唯一测试编号机制(TECH) +- `ADR-20260430-003`:报告粒度到 step_id(TECH) + +## 3.2 登录管理 +- `ADR-20260430-004`:接口路径以 PRD 为准(REQ) +- `ADR-20260430-005`:MVP 范围冻结(REQ) + +## 3.3 客户端发布管理 +- `ADR-20260430-006`:新增独立技术方案(TECH) +- `ADR-20260430-008`:SHA256 完整性校验强制(TECH) +- `ADR-20260430-009`:API 命名空间统一 `/api/release/...`(TECH) + +## 3.4 数据模型(public schema) +- `ADR-20260430-007`:`client_heartbeats` Upsert + 24h 活跃口径(TECH) + +## 3.5 文档治理(全局) +- `ADR-20260430-010`:变更历史章节统一规则(TECH) + +--- + +## 四、历史记录(Append-Only Log) + +> 说明:本节为机器可检索的历史流水,不删改旧记录。 + +| ADR ID | 日期 | 模块 | 类型 | 状态 | 摘要 | 关联 | +|---|---|---|---|---|---|---| +| ADR-20260430-001 | 2026-04-30 | 测试治理 | REQ | accepted | 术语统一为“测试用例” | `TECH_STACK/测试规范.md` | +| ADR-20260430-002 | 2026-04-30 | 测试治理 | TECH | accepted | 测试编号全局唯一 `TC-FON-XXXXXX` | `TEST_CASES/TEST_CASE_ID_SPEC.md` | +| ADR-20260430-003 | 2026-04-30 | 测试执行 | TECH | accepted | 报告必须定位到 `test_case_id+step_id` | `TECH_STACK/测试规范.md` | +| ADR-20260430-004 | 2026-04-30 | 登录管理 | REQ | accepted | 登录接口路径全部按 PRD v2.0 | `TECH_STACK/登录管理技术方案.md` | +| ADR-20260430-005 | 2026-04-30 | 登录管理 | REQ | accepted | 登录模块范围冻结(含废弃/预留) | `PRD/登录管理/用户登录管理模块PRD.md` | +| ADR-20260430-006 | 2026-04-30 | 客户端发布 | TECH | accepted | 新建独立技术方案文档 | `TECH_STACK/客户端发布管理技术方案.md` | +| ADR-20260430-007 | 2026-04-30 | 数据模型 | TECH | accepted | `client_heartbeats` Upsert + 24h 活跃 | `DATA_MODEL/DATA_MODEL_PUBLIC.md` | +| ADR-20260430-008 | 2026-04-30 | 客户端发布安全 | TECH | accepted | SHA256 校验失败禁止安装 | `TECH_STACK/客户端发布管理技术方案.md` | +| ADR-20260430-009 | 2026-04-30 | 客户端发布 API | TECH | accepted | 统一 `/api/release/...` 路径 | `TECH_STACK/TECH_STACK.md` | +| ADR-20260430-010 | 2026-04-30 | 文档治理 | TECH | accepted | 变更历史章节位置统一规范 | `TECH_STACK/*.md` `DATA_MODEL/*.md` `TEST_CASES/*.md` | + +--- + +## 五、后续维护约定 + +1. 每当接受新技术或需求决策,**当天必须新增 ADR 条目**。 +2. 若新决策替代旧决策,在新 ADR 中写明 `supersedes: ADR-xxxx`,并将旧条目标记 `superseded`。 +3. PRD / TECH_STACK / DATA_MODEL / TEST_CASES 发生关键口径变化时,必须同步更新本文件。 +4. 本文件是跨 Session 的决策权威输入之一,和 PRD 一起喂给 Agent。 \ No newline at end of file diff --git a/Project/fonrey/AGENTS.md b/Project/fonrey/AGENTS.md index bc8809ff..38652e16 100644 --- a/Project/fonrey/AGENTS.md +++ b/Project/fonrey/AGENTS.md @@ -247,12 +247,13 @@ apps/property/ | 登录认证 | `TECH_STACK/登录管理技术方案.md` | `PRD/登录管理/` | | 权限管理 | `TECH_STACK/权限管理系统技术方案.md` | `PRD/权限管理/` | | 测试规范 | `TECH_STACK/测试规范.md` | — | -| 房源管理 | _待补充_ | `PRD/房源管理/` | -| 客源管理 | _待补充_ | `PRD/客源管理/` | -| 楼盘管理 | _待补充_ | `PRD/房源管理/(含楼盘)` | -| 组织人事 | _待补充_ | `PRD/组织人事管理/` | -| 系统设置 | _待补充_ | `PRD/系统配置/`、`PRD/系统管理/` | -| 客户端发布 | `TECH_STACK/TECH_STACK.md §7` | `PRD/发布管理/客户端发布管理模块PRD.md` | +| 房源管理 | `TECH_STACK/房源管理技术方案.md` | `PRD/房源管理/` | +| 客源管理 | `TECH_STACK/客源管理技术方案.md` | `PRD/客源管理/` | +| 楼盘管理 | `TECH_STACK/楼盘管理技术方案.md` | `PRD/房源管理/(含楼盘)` | +| 组织人事 | `TECH_STACK/组织人事技术方案.md` | `PRD/组织人事管理/` | +| 系统设置 | `TECH_STACK/系统设置技术方案.md` | `PRD/系统配置/`、`PRD/系统管理/` | +| 客户端发布 | `TECH_STACK/客户端发布管理技术方案.md` | `PRD/发布管理/客户端发布管理模块PRD.md` | +| ADR 决策记录 | `ADR.md` | 全局(TECH/REQ) | **设计 Review 记录**(了解当前已知技术债与阻塞项): - `REVIEW/REVIEW_全局_2026-04-26.md`(最新) @@ -260,6 +261,12 @@ apps/property/ --- +### 9.1 ADR 治理联动规则 + +- 任何跨模块规则、口径或范围边界调整,先记录 `ADR.md`,再改对应 TECH_STACK/PRD/DATA_MODEL/TEST_CASES 文档。 +- 若已有结论被替代,必须在 ADR 中新增 superseded 记录并引用新 ADR ID,禁止直接覆盖历史。 +- 涉及上述变更的 PR/提交说明,必须包含 ADR ID(`ADR-YYYYMMDD-XXX`)。 + ## 10. 已知待解决问题(编码前必须确认) 以下问题在开始编码前需先确认当前状态,若未解决应在实现对应模块前暂停并上报: diff --git a/Project/fonrey/DATA_MODEL/DATA_MODEL.md b/Project/fonrey/DATA_MODEL/DATA_MODEL.md index 2d2eaa67..a5fde498 100644 --- a/Project/fonrey/DATA_MODEL/DATA_MODEL.md +++ b/Project/fonrey/DATA_MODEL/DATA_MODEL.md @@ -2,13 +2,20 @@ # Fonrey 房产经纪管理系统 — DATA MODEL 设计文档 > **作者**: Backend Architect -> **版本**: v1.4 -> **日期**: 2026-04-24(v1.1 修复 S1/S2/S4;v1.2 扩展 public schema;v1.3 §三 DDL 迁至 DATA_MODEL_PUBLIC.md,本文改为索引;v1.4 补充 LOGIN/PERMISSION 子文档引用、领域对象、租户 Schema 章节、Redis 缓存策略) +> **版本**: v1.5 +> **日期**: 2026-04-30(v1.1 修复 S1/S2/S4;v1.2 扩展 public schema;v1.3 §三 DDL 迁至 DATA_MODEL_PUBLIC.md,本文改为索引;v1.4 补充 LOGIN/PERMISSION 子文档引用、领域对象、租户 Schema 章节、Redis 缓存策略;v1.5 新增 ADR 导航与治理联动) > **技术栈**: Django 4.x + PostgreSQL + django-tenants + Redis > **设计目标**: 支撑 89,000+ 房源、多租户隔离、sub-100ms 查询、合规审计 --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 新增 ADR 导航与治理联动规则(数据模型变更需 ADR 可追溯) | +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、架构决策总览 (Architecture Decision Records) ### 1.1 多租户策略:Schema-per-Tenant @@ -157,6 +164,7 @@ OrgUnit (组织架构) | [DATA_MODEL_LOGIN.md](./DATA_MODEL_LOGIN.md) | 登录与账号认证(user_accounts, login_attempts, password_reset_tokens, password_histories + Redis 登录缓存) | ✅ 完成 | | [DATA_MODEL_PERMISSION.md](./DATA_MODEL_PERMISSION.md) | 权限管理(permission_defs, roles, role_permissions, staff_roles, staff_permission_overrides, staff_data_scopes, permission_change_logs + Redis 权限缓存) | ✅ 完成 | | [ENUMS.md](./ENUMS.md) | 枚举字典(`public.enum_labels` 表设计 + 所有模块枚举定义 + 种子数据 SQL) | ✅ 完成 | +| [ADR.md](../ADR.md) | 架构与需求决策记录(按日期/按模块/历史流水,append-only) | ✅ 完成 | --- @@ -833,7 +841,14 @@ app.conf.beat_schedule["partition_maintenance_task"] = { | 跟进目的枚举 | 存 lookup_items 表,运营可维护 | 初始化数据需提前收集 | | 手机号加密算法 | AES-256-GCM,密钥存 Django settings(生产用 Vault) | 密钥管理需单独规划 | +## 十、文档治理与 ADR 联动规则 + +- 任何会影响数据模型边界的变更(新增/删除表、关键约束变更、索引策略调整、枚举口径变更)必须先在 `ADR.md` 记录为 `accepted`,再修改本文件与子文档。 +- 若既有数据决策被替代,必须在 `ADR.md` 增加 `superseded` 记录并指向新 ADR,禁止直接覆盖旧结论。 +- 提交 PR 时,凡涉及 `DATA_MODEL/*` 结构性变更,PR 描述必须包含 ADR ID(格式:`ADR-YYYYMMDD-XXX`)。 +- `DATA_MODEL.md` 只维护全局索引与规则;表级 DDL 以各子文档为权威源,避免双写漂移。 + --- -*本文档为 Fonrey 系统 DATA MODEL v1.0,随 PRD 迭代同步更新。* +*本文档为 Fonrey 系统 DATA MODEL v1.5,随 PRD 与 ADR 迭代同步更新。* *下一步建议:API 接口规范(URL 设计 + Request/Response Schema)* diff --git a/Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md b/Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md index 70a020da..b47918ea 100644 --- a/Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md +++ b/Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md @@ -8,6 +8,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、领域概览(Domain Overview) ### 核心概念 diff --git a/Project/fonrey/DATA_MODEL/DATA_MODEL_COMPLEX.md b/Project/fonrey/DATA_MODEL/DATA_MODEL_COMPLEX.md index ee3109a6..7342e89b 100644 --- a/Project/fonrey/DATA_MODEL/DATA_MODEL_COMPLEX.md +++ b/Project/fonrey/DATA_MODEL/DATA_MODEL_COMPLEX.md @@ -8,6 +8,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、领域概览(Domain Overview) ### 核心概念 diff --git a/Project/fonrey/DATA_MODEL/DATA_MODEL_LOGIN.md b/Project/fonrey/DATA_MODEL/DATA_MODEL_LOGIN.md index 9c70171d..866b4555 100644 --- a/Project/fonrey/DATA_MODEL/DATA_MODEL_LOGIN.md +++ b/Project/fonrey/DATA_MODEL/DATA_MODEL_LOGIN.md @@ -9,6 +9,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、领域概览(Domain Overview) ### 核心概念 diff --git a/Project/fonrey/DATA_MODEL/DATA_MODEL_ORG.md b/Project/fonrey/DATA_MODEL/DATA_MODEL_ORG.md index 3d733db2..1340e780 100644 --- a/Project/fonrey/DATA_MODEL/DATA_MODEL_ORG.md +++ b/Project/fonrey/DATA_MODEL/DATA_MODEL_ORG.md @@ -8,6 +8,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、领域概览(Domain Overview) ### 核心概念 diff --git a/Project/fonrey/DATA_MODEL/DATA_MODEL_PERMISSION.md b/Project/fonrey/DATA_MODEL/DATA_MODEL_PERMISSION.md index 61b16395..b065e9f9 100644 --- a/Project/fonrey/DATA_MODEL/DATA_MODEL_PERMISSION.md +++ b/Project/fonrey/DATA_MODEL/DATA_MODEL_PERMISSION.md @@ -10,6 +10,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、领域概览(Domain Overview) ### 1.1 核心概念 diff --git a/Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md b/Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md index 8a4280d8..5430fdfa 100644 --- a/Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md +++ b/Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md @@ -1,45 +1,20 @@ > **For AI assistants**: Read this entire file before writing any code. All decisions here are final. Do not suggest alternatives unless asked. # Fonrey — 房源模块数据模型(DATA_MODEL_PROPERTY) -> **权威定义**:本文件是房源模块所有表结构的唯一权威来源。 +> **所属系统**: Fonrey 房产经纪管理系统 +> **版本**: v1.0 +> **日期**: 2026-04-24 +> **关联模块**: `apps/property/` > **主文档引用**:`DATA_MODEL.md` §3.3–§3.16 为本文件的概览摘要,开发以本文件为准。 > **版本**:v1.0 | **日期**:2026-04-24 --- +## 变更历史 -## 目录 +| 日期 | 变更人 | 变更内容 | +| ---------- | ----- | ---------------- | +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | -1. [模块说明](#1-模块说明) -2. [表清单](#2-表清单) -3. [枚举值总览](#3-枚举值总览) -4. [DDL 定义](#4-ddl-定义) - - 4.1 [properties(房源主表)](#41-properties房源主表) - - 4.2 [property_contacts(联系人)](#42-property_contacts联系人) - - 4.3 [listing_histories(挂牌历史)](#43-listing_histories挂牌历史) - - 4.4 [price_changes(调价记录)](#44-price_changes调价记录) - - 4.5 [follow_logs(跟进日志)](#45-follow_logs跟进日志) - - 4.6 [follow_log_attachments(跟进附件)](#46-follow_log_attachments跟进附件) - - 4.7 [follow_log_recordings(跟进录音)](#47-follow_log_recordings跟进录音) - - 4.8 [property_keys(钥匙管理)](#48-property_keys钥匙管理) - - 4.9 [key_attachments(钥匙附件)](#49-key_attachments钥匙附件) - - 4.10 [commissions(委托管理)](#410-commissions委托管理) - - 4.11 [commission_attachments(委托附件)](#411-commission_attachments委托附件) - - 4.12 [field_surveys(实勘管理)](#412-field_surveys实勘管理) - - 4.13 [survey_photos(实勘照片)](#413-survey_photos实勘照片) - - 4.14 [property_photos(房源图片)](#414-property_photos房源图片) - - 4.15 [property_attachments(房源附件)](#415-property_attachments房源附件) - - 4.16 [property_marketing(营销信息)](#416-property_marketing营销信息) - - 4.17 [property_certificates(产证信息)](#417-property_certificates产证信息) - - 4.18 [property_completeness(维护完成度)](#418-property_completeness维护完成度) - - 4.19 [property_tags / property_tag_relations(标签)](#419-property_tags--property_tag_relations标签) - - 4.20 [property_favorites(收藏)](#420-property_favorites收藏) - - 4.21 [property_protections(保护房)](#421-property_protections保护房) - - 4.22 [number_holder_approvals(号码方审批)](#422-number_holder_approvals号码方审批) -5. [触发器](#5-触发器) -6. [查询模式参考](#6-查询模式参考) -7. [禁止操作](#7-禁止操作) - ---- ## 1 模块说明 diff --git a/Project/fonrey/DATA_MODEL/DATA_MODEL_PUBLIC.md b/Project/fonrey/DATA_MODEL/DATA_MODEL_PUBLIC.md index 8eece44b..7b8b1424 100644 --- a/Project/fonrey/DATA_MODEL/DATA_MODEL_PUBLIC.md +++ b/Project/fonrey/DATA_MODEL/DATA_MODEL_PUBLIC.md @@ -2,7 +2,7 @@ # Fonrey — Public Schema 数据模型 > **作者**: Backend Architect -> **版本**: v1.3 +> **版本**: v1.5 > **日期**: 2026-04-30 > **权威源**: 本文件是 `public` schema 所有表的唯一权威定义 > **设计依据**: 系统管理模块 PRD(`PRD/系统管理/系统管理模块PRD.md`);客户端发布管理模块 PRD(`PRD/发布管理/客户端发布管理模块PRD.md`) @@ -10,6 +10,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、概览 `public` schema 存储**平台运营层**数据,与各租户的业务 schema 完全隔离。 @@ -34,6 +40,7 @@ PostgreSQL Instance │ ├── system_versions 版本历史 │ ├── upgrade_events 升级事件(A/B/C 分级 + B 类分批编排) │ ├── client_releases 客户端版本发布 +│ ├── client_heartbeats 客户端启动心跳(活跃统计 + 版本分布) │ ├── feature_flag_definitions Feature Flag 定义(C 类灰度控制平面) │ └── feature_flag_change_log Feature Flag 变更历史(append-only) │ @@ -59,6 +66,7 @@ PostgreSQL Instance | `public.system_versions` | 平台版本历史,唯一 current 约束 | §2.5 | | `public.upgrade_events` | 升级/回滚事件,A/B/C 升级类型分级,B 类按租户分批编排 + 健康门控 | §2.5 | | `public.client_releases` | Windows 客户端发布版本,含安装包 URL、SHA256、强制更新标记 | §2.6 | +| `public.client_heartbeats` | 客户端启动心跳(活跃统计 + 版本分布支撑) | §2.6 | | `public.feature_flag_definitions` | Feature Flag 全局定义(C 类运行时灰度控制平面) | §2.7 | | `public.tenants.feature_flags` | 租户级 Flag 显式覆盖(`tenants` 表新增 JSONB 列) | §2.7 | | `public.feature_flag_change_log` | Feature Flag 变更历史(append-only) | §2.7 | @@ -538,6 +546,72 @@ CREATE INDEX idx_client_releases_status ON public.client_releases(status, create -- 按版本号快速定位(客户端更新检测时传入 current_version 查询) CREATE INDEX idx_client_releases_version ON public.client_releases(version); + +-- ──────────────────────────────────────────────────────────── +-- 客户端启动心跳表(活跃统计 + 版本分布数据支撑) +-- ──────────────────────────────────────────────────────────── +-- 设计依据: 客户端发布管理模块 PRD §5.5 Story 5(客户端版本分布查询) +-- 上报模型: 客户端 App 每次启动时 Upsert 一条记录(by tenant_id + device_id) +-- 归属说明: 本表属于 shared_apps(public schema)。虽然 tenant_id 字段做了租户归属, +-- 但 device_id 由客户端首次安装时生成(本机 UUID),跨租户全局唯一管理; +-- 将本表放在 public schema 便于平台运营做全量版本分布、活跃数统计, +-- 避免跨所有 tenant schema 做 UNION ALL。 +-- 隐私说明: 不收集任何业务数据,仅用于平台运营版本管理与升级决策。 + +CREATE TABLE public.client_heartbeats ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + + -- 归属 + tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE, + -- 心跳上报时所属租户(由客户端登录态决定,从 Tenant Code 解析得到); + -- 是"按租户统计安装数 / 活跃数 / 版本分布"的核心维度字段, + -- 配合 idx_client_heartbeats_tenant_lastseen 索引支撑租户维度聚合查询; + -- 租户被硬删除时心跳一并清理(CASCADE); + -- 同一物理设备登录不同租户视作多条独立记录(Upsert 锚点为 (tenant_id, device_id)) + device_id UUID NOT NULL, + -- 客户端首次安装时本机生成并持久化的设备 UUID; + -- 卸载重装会变化(视作新设备);同一设备换租户登录视作不同记录 + user_id UUID, + -- 上次启动时登录的用户 ID(指向 tenant schema 的 staff.id); + -- 不加外键约束(跨 schema 无法外键),仅作排查辅助; + -- 未登录或退出后启动允许为 NULL + + -- 版本与环境 + client_version VARCHAR(20) NOT NULL, + -- 上报时客户端 SemVer 版本号,如 '1.2.3' + platform VARCHAR(20) NOT NULL DEFAULT 'win32' + CHECK (platform IN ('win32')), + arch VARCHAR(10) NOT NULL DEFAULT 'x64' + CHECK (arch IN ('x64', 'arm64')), + os_version VARCHAR(80), + -- 操作系统版本字符串,如 'Windows 10 22H2';可选 + + -- 时间戳 + first_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + -- 该 (tenant_id, device_id) 组合首次心跳时间,Upsert 时不更新 + last_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + -- 最近一次启动心跳时间,Upsert 时刷新为 NOW() + launch_count INTEGER NOT NULL DEFAULT 1, + -- 累计启动次数,Upsert 时 +1,用于排查异常高频启动 + + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + + -- 同一租户下同一设备唯一一条记录(Upsert 锚点) + CONSTRAINT uq_client_heartbeats_tenant_device UNIQUE (tenant_id, device_id) +); + +-- 活跃数统计("最近 24h 内有心跳")核心索引 +CREATE INDEX idx_client_heartbeats_last_seen + ON public.client_heartbeats(last_seen_at DESC); + +-- 版本分布统计:按版本聚合活跃设备数 +CREATE INDEX idx_client_heartbeats_version_lastseen + ON public.client_heartbeats(client_version, last_seen_at DESC); + +-- 租户维度排查:某租户下所有活跃设备 +CREATE INDEX idx_client_heartbeats_tenant_lastseen + ON public.client_heartbeats(tenant_id, last_seen_at DESC); ``` ### 2.7 Feature Flag 灰度体系 @@ -644,6 +718,9 @@ CREATE INDEX idx_ff_log_operator ON public.feature_flag_change_log(operator_id, | `client_releases` 唯一 published | `idx_client_releases_published` 部分唯一索引保证同平台+架构下只有一条 `status='published'` | | `client_releases` 不可跨租户隔离 | 本表属于 public schema,所有租户共享;禁止在租户 schema 中创建副本 | | `client_releases.download_count` 原子递增 | 必须使用 `UPDATE ... SET download_count = download_count + 1`,禁止先读后写 | +| `client_heartbeats` Upsert 锚点 | 必须使用 `INSERT ... ON CONFLICT (tenant_id, device_id) DO UPDATE SET last_seen_at=NOW(), launch_count=client_heartbeats.launch_count+1, client_version=EXCLUDED.client_version`;禁止先 SELECT 再 INSERT | +| `client_heartbeats` 仅启动时上报 | 客户端 App 仅在每次启动时上报一次心跳;不做 4h 周期心跳,避免 public schema 写入压力 | +| `client_heartbeats` 不可跨租户隔离 | 本表属于 public schema,所有租户共享;禁止在租户 schema 中创建副本 | | `upgrade_events.gray_tenant_ids` 与 `upgrade_type` 一致性 | A_app 类型必须为空数组(CHECK 约束 `chk_app_upgrade_no_gray` 强制);只有 B_schema 类型才使用灰度名单与批次字段 | | `upgrade_events` 状态流转单向 | 状态机详见 §4.2;`succeeded` / `rolled_back` / `failed` 为终态,禁止再写回中间态 | | `feature_flag_change_log` append-only | 禁止 UPDATE / DELETE;任何 Flag 变更都必须经此表追溯,含 `reason` 强制非空 | @@ -782,11 +859,83 @@ SELECT version, platform, arch, release_type, status, FROM public.client_releases ORDER BY created_at DESC; --- 统计各版本活跃客户端数(需结合客户端上报心跳表,当前仅记录下载量) -SELECT version, download_count -FROM public.client_releases -WHERE status IN ('published', 'archived') -ORDER BY published_at DESC; +-- 客户端启动心跳 Upsert(每次启动调用,原子更新最后活跃时间与启动次数) +INSERT INTO public.client_heartbeats ( + tenant_id, device_id, user_id, + client_version, platform, arch, os_version, + first_seen_at, last_seen_at, launch_count +) +VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW(), 1) +ON CONFLICT (tenant_id, device_id) DO UPDATE + SET last_seen_at = NOW(), + launch_count = public.client_heartbeats.launch_count + 1, + client_version = EXCLUDED.client_version, + user_id = EXCLUDED.user_id, + os_version = EXCLUDED.os_version, + updated_at = NOW(); + +-- 统计各版本活跃客户端数(活跃 = 最近 24h 内有心跳) +SELECT cr.version, + cr.status, + cr.download_count, + COUNT(ch.id) FILTER ( + WHERE ch.last_seen_at >= NOW() - INTERVAL '24 hours' + ) AS active_devices_24h, + COUNT(ch.id) AS total_devices_ever +FROM public.client_releases cr +LEFT JOIN public.client_heartbeats ch ON ch.client_version = cr.version +WHERE cr.status IN ('published', 'archived') +GROUP BY cr.version, cr.status, cr.download_count, cr.published_at +ORDER BY cr.published_at DESC; + +-- 平台总活跃数(最近 24h) +SELECT COUNT(*) AS active_devices_24h +FROM public.client_heartbeats +WHERE last_seen_at >= NOW() - INTERVAL '24 hours'; + +-- 某租户下活跃设备列表(运营排查) +SELECT device_id, client_version, user_id, last_seen_at, launch_count +FROM public.client_heartbeats +WHERE tenant_id = $1 + AND last_seen_at >= NOW() - INTERVAL '24 hours' +ORDER BY last_seen_at DESC; + +-- ============================================================ +-- 租户维度安装/活跃统计(Platform Admin 运营看板) +-- ============================================================ + +-- 某租户当前活跃安装数(最近 24h 内启动过的设备) +SELECT COUNT(*) AS active_installs_24h +FROM public.client_heartbeats +WHERE tenant_id = $1 + AND last_seen_at >= NOW() - INTERVAL '24 hours'; + +-- 某租户历史装机总数(不区分是否活跃,含已离线设备) +SELECT COUNT(*) AS total_installs_ever +FROM public.client_heartbeats +WHERE tenant_id = $1; + +-- 某租户内部各版本分布(识别该租户内升级覆盖率) +SELECT client_version, + COUNT(*) FILTER (WHERE last_seen_at >= NOW() - INTERVAL '24 hours') AS active_devices_24h, + COUNT(*) AS total_devices_ever +FROM public.client_heartbeats +WHERE tenant_id = $1 +GROUP BY client_version +ORDER BY active_devices_24h DESC; + +-- 全平台租户活跃榜(PRD §5.5 Story 5:按租户维度查看版本分布,识别落后租户) +SELECT t.tenant_code, + t.name, + COUNT(h.id) FILTER ( + WHERE h.last_seen_at >= NOW() - INTERVAL '24 hours' + ) AS active_installs_24h, + COUNT(h.id) AS total_installs_ever +FROM public.tenants t +LEFT JOIN public.client_heartbeats h ON h.tenant_id = t.id +WHERE t.status = 'active' +GROUP BY t.id, t.tenant_code, t.name +ORDER BY active_installs_24h DESC; -- ============================================================ -- 升级编排相关查询(B 类 Schema 迁移分批升级) @@ -878,3 +1027,6 @@ ORDER BY created_at DESC; | v1.0 | 2026-04-24 | 从 `DATA_MODEL.md §三` 独立拆分;内容等价于 v1.2 DATA_MODEL.md §三 | | v1.1 | 2026-04-24 | 新增 §2.6 `client_releases` 表(客户端发布管理);同步更新表清单、约束规则、查询模式 | | v1.2 | 2026-04-26 | 配合系统管理技术文档 v1.2 升级分批专节:§2.5 `upgrade_events` 增加 `upgrade_type`、`gray_tenant_ids`、`batch_size`、`batch_concurrency`、`batch_interval_seconds`、`failure_policy`、`current_batch_no`、`total_batch_count`、`health_gate_config`、`pre_backup_record_id`、`halted_reason` 字段,状态机扩展为 10 态;新增 §2.7 Feature Flag 体系(`feature_flag_definitions` / `tenants.feature_flags` JSONB / `feature_flag_change_log`);同步更新表清单、§4.2 升级状态机、§4.3 Flag 流程、§5.1 查询模式、§5.2 禁止操作 | +| v1.3 | 2026-04-30 | 配合登录管理 PRD v2.0 / 系统管理 PRD:§2.1 `tenants` 新增 `tenant_code` (CHAR(12), 全局唯一对外识别码) 与 `contact_phone` (CHAR(11),Tenant Admin 账号创建数据来源),`contact_email` 改为可 NULL;同步更新约束、查询模式 | +| v1.4 | 2026-04-30 | 配合客户端发布管理 PRD v1.1 §5.5 Story 5:§2.6 新增 `client_heartbeats` 表(启动时 Upsert by `tenant_id + device_id`,活跃定义为最近 24h 内心跳);同步更新表清单、§三 约束(Upsert 锚点 / 启动上报 / 不可下沉到租户 schema)、§5.1 查询模式(Upsert 模板 + 版本活跃分布 JOIN + 平台总活跃数 + 租户维度排查);MVP 不做升级趋势图(v2 规划) | +| v1.5 | 2026-04-30 | 配合客户端发布管理 PRD v1.2 §5.5 Story 5 验收标准追加(按租户统计安装数):① §2.6 `client_heartbeats.tenant_id` 注释强化,明确为"按租户统计安装数 / 活跃数 / 版本分布"的核心维度字段;② §5.1 新增"租户维度安装/活跃统计"查询专区(4 个查询:某租户活跃安装数 / 历史装机总数 / 租户内版本分布 / 全平台租户活跃榜) | diff --git a/Project/fonrey/DATA_MODEL/DATA_MODEL_SETTING.md b/Project/fonrey/DATA_MODEL/DATA_MODEL_SETTING.md index cfa63f6e..afaca27a 100644 --- a/Project/fonrey/DATA_MODEL/DATA_MODEL_SETTING.md +++ b/Project/fonrey/DATA_MODEL/DATA_MODEL_SETTING.md @@ -9,6 +9,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、模块定位与架构边界 ### 1.1 系统配置模块职责 diff --git a/Project/fonrey/DATA_MODEL/DATA_MODEL文档要求.md b/Project/fonrey/DATA_MODEL/DATA_MODEL文档要求.md index 45a36522..28b538ff 100644 --- a/Project/fonrey/DATA_MODEL/DATA_MODEL文档要求.md +++ b/Project/fonrey/DATA_MODEL/DATA_MODEL文档要求.md @@ -1,3 +1,4 @@ + `DATA_MODEL.md` 的核心目标是:**让 AI 在触碰任何数据相关代码时,都能理解业务语义,而不只是看到一堆字段名。** --- @@ -11,6 +12,7 @@ md ```md + ## Domain Overview This is a **multi-tenant** project management tool. @@ -259,4 +261,4 @@ md --- -**核心原则**:`DATA_MODEL.md` 写的不是给数据库看的 DDL,而是给 AI 看的**业务契约**。每一个"显而易见"的业务规则,在 AI 眼里都是需要被明确告知的约束。没写的,它都会自己猜。 \ No newline at end of file +**核心原则**:`DATA_MODEL.md` 写的不是给数据库看的 DDL,而是给 AI 看的**业务契约**。每一个"显而易见"的业务规则,在 AI 眼里都是需要被明确告知的约束。没写的,它都会自己猜。 diff --git a/Project/fonrey/DATA_MODEL/ENUMS.md b/Project/fonrey/DATA_MODEL/ENUMS.md index f70e1797..9702e9df 100644 --- a/Project/fonrey/DATA_MODEL/ENUMS.md +++ b/Project/fonrey/DATA_MODEL/ENUMS.md @@ -13,6 +13,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、枚举分层标准(必须遵守) Fonrey 采用两层枚举体系: diff --git a/Project/fonrey/DATA_MODEL/SCHEMA_CHANGES.md b/Project/fonrey/DATA_MODEL/SCHEMA_CHANGES.md deleted file mode 100644 index ef9cd550..00000000 --- a/Project/fonrey/DATA_MODEL/SCHEMA_CHANGES.md +++ /dev/null @@ -1,111 +0,0 @@ -# Schema 变更记录 - -> **用途**:记录在初始 Model 创建之后新增/修改的字段,供架构师逐一更新 Migration 脚本。 -> **格式**:每条变更含目标表、变更类型、字段定义、变更原因、来源 PRD 依据。 -> **状态流转**:`待迁移` → `已迁移`(架构师完成 migration 后更新状态) - ---- - -## 变更清单 - -| # | 状态 | 目标表 | 变更类型 | 字段名 | 提出日期 | -|---|------|--------|----------|--------|----------| -| 1 | 待迁移 | `public.tenants` | 新增字段 | `tenant_code` | 2026-04-30 | -| 2 | 待迁移 | `public.tenants` | 新增字段 | `contact_phone` | 2026-04-30 | -| 3 | 待迁移 | `public.tenants` | 字段修改 | `contact_email`(NOT NULL → 可 NULL) | 2026-04-30 | - ---- - -## 变更详情 - -### #1 — `public.tenants` 新增 `tenant_code` - -**状态**:待迁移 -**提出日期**:2026-04-30 -**目标表**:`public.tenants`(Public Schema,django-tenants 主租户表) - -**字段定义**: -```sql -tenant_code CHAR(12) UNIQUE NOT NULL -``` - -**注释**:对外暴露的 12 位纯数字识别码,如 `202500010001`;用户首次登录客户端时输入;由平台运营在注册租户时生成;创建后不可修改。 - -**推荐加在**:`schema_name` 字段之后,`name` 字段之前。 - -**约束要求**: -- `CHAR(12)`:固定 12 位 -- `UNIQUE`:全局唯一 -- `NOT NULL`:注册时必填 -- 禁止 `UPDATE`(应用层 + DB 层双重约束,与 `schema_name` 同等级别) - -**建议索引**: -```sql -CREATE UNIQUE INDEX idx_tenants_tenant_code ON public.tenants(tenant_code); -``` - -**变更原因**: -登录 PRD §5.1.3 明确用户输入 12 位 Tenant Code 完成租户识别,服务端需通过该码查找对应 `schema_name`,原始 `public.tenants` 表中缺少此字段。 - -**PRD 依据**: -`PRD/登录管理/用户登录管理模块PRD.md` §5.1.3 — Tenant Code 格式规范: -> 格式:固定 12 位纯数字,如 `202500010001` - -**登录查询示例**: -```sql -SELECT schema_name, name -FROM public.tenants -WHERE tenant_code = '202500010001' - AND status = 'active'; -``` - ---- - -### #2 — `public.tenants` 新增 `contact_phone` - -**状态**:待迁移 -**提出日期**:2026-04-30 -**目标表**:`public.tenants`(Public Schema) - -**字段定义**: -```sql -contact_phone CHAR(11) NOT NULL -``` - -**注释**:联系人手机号(11位纯数字);系统开通租户时自动以此手机号创建 Tenant Admin 登录账号;必填字段,平台运营在创建租户时录入。 - -**推荐加在**:`contact_name` 字段之后,`contact_email` 字段之前。 - -**约束要求**: -- `CHAR(11)`:固定 11 位手机号 -- `NOT NULL`:开通租户时必填 - -**变更原因**: -登录 PRD v1.5 决策:Tenant Admin 账号统一以联系人手机号作为用户名,与普通员工账号规则对齐。需在 tenants 表增加手机号字段作为 Tenant Admin 账号创建的数据来源。 - -**PRD 依据**: -`PRD/登录管理/用户登录管理模块PRD.md` §5.3.2 Tenant Admin 账号规格表 - ---- - -### #3 — `public.tenants.contact_email` 改为可 NULL - -**状态**:待迁移 -**提出日期**:2026-04-30 -**目标表**:`public.tenants`(Public Schema) - -**变更 SQL**: -```sql -ALTER TABLE public.tenants - ALTER COLUMN contact_email DROP NOT NULL; -``` - -**变更原因**: -`contact_email` 原为 `NOT NULL`。由于 Tenant Admin 账号创建数据来源改为 `contact_phone`(手机号,必填),邮箱降级为选填,仅用于找回密码功能。为空时 Tenant Admin 无法自助找回密码,需联系平台运营处理。 - -**PRD 依据**: -`PRD/登录管理/用户登录管理模块PRD.md` §5.3.2 - ---- - -*后续如有新增字段,按同样格式追加到本文件。* diff --git a/Project/fonrey/PRD/PRD_MVP.md b/Project/fonrey/PRD/PRD_MVP.md index a1b859ee..94ddfcae 100644 --- a/Project/fonrey/PRD/PRD_MVP.md +++ b/Project/fonrey/PRD/PRD_MVP.md @@ -7,6 +7,13 @@ > **For AI assistants**: 本文件定义 Phase 1(MVP)的边界。在任何功能实现前,先对照本文确认是否在范围内。范围外的功能禁止在 MVP 阶段实现。 +## 变更历史 + +| 版本 | 日期 | 作者 | 变更说明 | +|------|------|------|---------| +| v1.0 | 2026-04-24 | Product Team | 初稿:定义 Phase 1(MVP)边界与范围 | + + --- ## 1. 产品背景与目标 diff --git a/Project/fonrey/PRD/发布管理/客户端发布管理模块PRD.md b/Project/fonrey/PRD/发布管理/客户端发布管理模块PRD.md index 29ba0dbb..ea476602 100644 --- a/Project/fonrey/PRD/发布管理/客户端发布管理模块PRD.md +++ b/Project/fonrey/PRD/发布管理/客户端发布管理模块PRD.md @@ -1,11 +1,20 @@ # PRD: 客户端发布管理模块 **状态**: Draft **作者**: 产品经理 -**最后更新**: 2026-04-24(v1.0 初稿) -**版本**: 1.0 +**最后更新**: 2026-04-30(v1.2) +**版本**: 1.2 **所属系统**: Fonrey 房产经纪管理系统 -**关联模块**: 系统管理、权限管理 -**干系人**: 工程负责人、运维负责人、Tenant Admin(租户管理员) +**关联模块**: 系统管理 +**干系人**: 工程负责人、运维负责人、Platform Admin(平台超级管理员) + +## 变更历史 + +| 版本 | 日期 | 作者 | 变更说明 | +|------|------|------|---------| +| v1.0 | 2026-04-24 | 产品经理 | 初稿 | +| v1.1 | 2026-04-30 | 产品经理 | Persona 与命名修正:① Story 4 / Story 5 责任角色由 Tenant Admin(租户管理员)修正为 Platform Admin(平台超级管理员),客户端版本上传与版本分布监控属于平台运营职责,跨租户统一管理;② §5.3 版本管理后台从"租户系统管理模块"迁移至"平台运营后台",明确 public schema 跨租户、Tenant Admin 与 Agent 无访问权限、不配置 RBAC permission_code;③ 全部 API 路径 `/api/client/updates/...` 重命名为 `/api/release/updates/...`,避免与客源管理模块(apps/client/)命名空间冲突,与 AGENTS.md §3 的 `apps/release/` 目录约定对齐;④ 头部"关联模块"由"系统管理、权限管理"修订为"系统管理"(不再涉及租户 RBAC);⑤ 干系人列表 Tenant Admin → Platform Admin。 | +| v1.2 | 2026-04-30 | 产品经理 | Story 5 验收标准追加"按租户统计安装数"能力:① 新增验收项——可查看任意租户的"当前活跃安装数(最近 24h)"与"历史装机总数";② 新增验收项——全平台租户活跃榜视图,按 `tenant_code` + 租户名称 + 活跃安装数 + 历史装机数列表展示,按活跃安装数降序。底层数据由 `public.client_heartbeats` 表的 `tenant_id` 维度聚合提供(详见 DATA_MODEL_PUBLIC v1.5 §5.1 租户维度安装/活跃统计查询专区)。 | + --- @@ -26,7 +35,7 @@ Fonrey 房产经纪管理系统当前为纯 Web 应用,依赖用户自行通 |------|---------|----------| | Agent(经纪人) | 下载安装客户端、日常登录使用系统、接受自动更新 | 每日 | | 店长/经理 | 同上 | 每日 | -| Tenant Admin(租户管理员) | 发布新版本、管理安装包下载地址、监控客户端版本分布 | 按需 | +| Platform Admin(平台超级管理员) | 发布新版本、管理安装包下载地址、监控客户端版本分布 | 按需 | | IT 运维人员 | 维护更新服务器、签名证书、构建发布流水线 | 按发布周期 | ### 核心痛点 @@ -108,12 +117,12 @@ Fonrey 房产经纪管理系统当前为纯 Web 应用,依赖用户自行通 --- -### Story 4:Tenant Admin(租户管理员)发布新版本 +### Story 4:Platform Admin(平台超级管理员)发布新版本 -**As** Tenant Admin(租户管理员),**I want** 通过管理后台上传新版客户端安装包并配置版本信息,**So that** 客户端能感知到更新并引导用户升级。 +**As** Platform Admin(平台超级管理员),**I want** 通过平台运营后台上传新版客户端安装包并配置版本信息,**So that** 全平台所有租户的客户端能感知到更新并引导用户升级。 **验收标准**: -- [ ] 系统管理后台提供"客户端版本管理"页面(位于系统管理模块下) +- [ ] 平台运营后台提供"客户端版本管理"页面(位于平台运营后台下,不在租户系统管理模块) - [ ] 支持上传 `.exe` 安装包,并填写版本号(遵循 SemVer:`X.Y.Z`)、版本说明(更新日志,支持 Markdown)、发布日期 - [ ] 支持设置版本类型:普通更新 / 强制更新 - [ ] 支持设置版本状态:草稿(不对外生效)/ 已发布 / 已下线 @@ -123,13 +132,15 @@ Fonrey 房产经纪管理系统当前为纯 Web 应用,依赖用户自行通 --- -### Story 5:管理员监控客户端版本分布 +### Story 5:Platform Admin(平台超级管理员)监控客户端版本分布 -**As** Tenant Admin(租户管理员),**I want** 查看当前所有在线客户端的版本分布情况,**So that** 了解升级覆盖率,对仍在使用旧版本的客户端发出提醒或强制升级。 +**As** Platform Admin(平台超级管理员),**I want** 跨租户查看当前所有在线客户端的版本分布情况,**So that** 了解全平台升级覆盖率,对仍在使用旧版本的客户端发出提醒或强制升级。 **验收标准**: - [ ] 客户端版本管理页面展示版本分布统计:各版本在线客户端数量及占比(饼图或条形图) -- [ ] 支持按租户维度查看版本分布(多租户场景下,区分不同经纪公司的版本使用情况) +- [ ] 支持按租户维度查看版本分布(区分不同经纪公司的版本使用情况,便于平台超管识别落后租户) +- [ ] 支持**按租户统计安装数**:可查看任意租户的"当前活跃安装数(最近 24h)"与"历史装机总数(不论是否活跃)",用于评估各租户的客户端覆盖率与渗透率 +- [ ] 支持全平台租户活跃榜视图:以列表形式展示各 active 状态租户的 `tenant_code`、租户名称、活跃安装数、历史装机总数,按活跃安装数降序排列 - [ ] 支持对指定版本范围的用户推送"强制更新"通知(如:将所有低于 v1.5.0 的客户端标记为强制更新) --- @@ -178,7 +189,7 @@ Fonrey 房产经纪管理系统当前为纯 Web 应用,依赖用户自行通 客户端启动 / 定时检测(每4小时) │ ▼ -GET /api/client/updates/latest?platform=win32&arch=x64¤t_version=1.2.0 +GET /api/release/updates/latest?platform=win32&arch=x64¤t_version=1.2.0 │ ▼ 更新服务器(Fonrey 后端 Django API) @@ -201,10 +212,10 @@ GET /api/client/updates/latest?platform=win32&arch=x64¤t_version=1.2.0 | 端点 | 方法 | 说明 | |------|------|------| -| `/api/client/updates/latest/` | GET | 客户端查询最新版本,返回版本信息和下载 URL | -| `/api/client/updates/` | GET | 管理端查询版本列表(需认证) | -| `/api/client/updates/` | POST | 管理端发布新版本(需管理员权限) | -| `/api/client/updates//` | PATCH | 管理端修改版本状态(发布/下线/强制) | +| `/api/release/updates/latest/` | GET | 客户端查询最新版本,返回版本信息和下载 URL | +| `/api/release/updates/` | GET | 管理端查询版本列表(需认证) | +| `/api/release/updates/` | POST | 管理端发布新版本(需管理员权限) | +| `/api/release/updates//` | PATCH | 管理端修改版本状态(发布/下线/强制) | --- @@ -259,9 +270,11 @@ GET /api/client/updates/latest?platform=win32&arch=x64¤t_version=1.2.0 --- -### 5.3 版本管理后台(系统管理模块新增页面) +### 5.3 版本管理后台(平台运营后台新增页面) -**页面路径**:系统管理 → 客户端发布管理 +**页面路径**:平台运营后台 → 客户端发布管理 + +> **归属说明**:本页面归属 Platform Admin(平台超级管理员),位于平台运营后台(public schema 跨租户),不在租户的"系统管理"模块下。Tenant Admin 与 Agent 均无访问权限。 #### 5.3.1 版本列表 @@ -300,7 +313,7 @@ GET /api/client/updates/latest?platform=win32&arch=x64¤t_version=1.2.0 ### 5.4 更新 API 规格 -#### GET `/api/client/updates/latest/` +#### GET `/api/release/updates/latest/` **请求参数(Query String)**: @@ -346,7 +359,7 @@ GET /api/client/updates/latest?platform=win32&arch=x64¤t_version=1.2.0 | EV 代码签名证书 | 需提前申请,EV 证书审核周期 1-2 周 | IT/运维 | 中(需提前排期) | | Cloudflare R2 存储桶 | 存放安装包,利用现有账号新增 bucket | 运维 | 低 | | `electron-updater` | 自动更新库,需配合更新 API 端点实现 | 客户端工程师 | 低 | -| Django 更新 API | 新增 `/api/client/updates/` 相关接口 | 后端工程师 | 低 | +| Django 更新 API | 新增 `/api/release/updates/` 相关接口 | 后端工程师 | 低 | | CI/CD 构建流水线 | 自动构建、签名、上传安装包 | 运维/DevOps | 中 | ### 6.2 已知风险 diff --git a/Project/fonrey/PRD/客源管理/客源管理模块PRD.md b/Project/fonrey/PRD/客源管理/客源管理模块PRD.md index 07d80fdf..c5876e09 100644 --- a/Project/fonrey/PRD/客源管理/客源管理模块PRD.md +++ b/Project/fonrey/PRD/客源管理/客源管理模块PRD.md @@ -6,6 +6,14 @@ **所属系统**: Fonrey 房产经纪管理系统 **关联模块**: 房源管理、组织人事管理、权限管理 +## 变更历史 + +| 版本 | 日期 | 作者 | 变更说明 | +|------|------|------|---------| +| v1.0 | — | 产品经理 | 初稿 | +| v1.4 | 2026-04-23 | 产品经理 | 新增客源信息概览/编辑基础信息/收藏/改等级/改状态/转公客/转成交/转无效/联系人管理/相关员工管理/操作日志章节及 Story 15-24,基于 35 张截图分析完成 | + + --- ## 1. 问题陈述 diff --git a/Project/fonrey/PRD/房源管理/房源管理模块PRD.md b/Project/fonrey/PRD/房源管理/房源管理模块PRD.md index 0be3108e..75c0217d 100644 --- a/Project/fonrey/PRD/房源管理/房源管理模块PRD.md +++ b/Project/fonrey/PRD/房源管理/房源管理模块PRD.md @@ -6,6 +6,14 @@ **所属系统**: Fonrey 房产经纪管理系统 **关联模块**: 客源管理、组织人事管理、权限管理 +## 变更历史 + +| 版本 | 日期 | 作者 | 变更说明 | +|------|------|------|---------| +| v1.0 | — | 产品经理 | 初稿 | +| v2.1 | 2026-04-23 | 产品经理 | 重写 §8.3 相关截图参考:修正所有路径拼写错误(sreenshots→screenshots);补充全部未收录截图(房源详情1-3、房源备注、价格解读、市场报盘、全部商铺、全部写字楼、附件信息、编辑业主联系人、小区/楼盘管理全部截图);按文档章节分组重新整理为表格格式 | + + --- ## 1. 问题陈述 diff --git a/Project/fonrey/PRD/房源管理/楼盘管理模块PRD.md b/Project/fonrey/PRD/房源管理/楼盘管理模块PRD.md index d8981bc2..dbf1b971 100644 --- a/Project/fonrey/PRD/房源管理/楼盘管理模块PRD.md +++ b/Project/fonrey/PRD/房源管理/楼盘管理模块PRD.md @@ -6,6 +6,13 @@ **所属系统**: Fonrey 房产经纪管理系统 **关联模块**: 房源管理、客源管理、组织人事管理、权限管理 +## 变更历史 + +| 版本 | 日期 | 作者 | 变更说明 | +|------|------|------|---------| +| v1.0 | 2026-04-23 | 产品经理 | 初稿,基于楼盘管理列表、楼盘详情(楼盘信息/楼栋管理/结构管理/楼盘照片/楼盘价格走势/周边配套)、区域管理(城区/商圈/关联关系)、学校管理共 14 张截图分析完成 | + + --- ## 1. 问题陈述 diff --git a/Project/fonrey/PRD/权限管理/权限管理模块PRD.md b/Project/fonrey/PRD/权限管理/权限管理模块PRD.md index 8ee24824..2022a8ac 100644 --- a/Project/fonrey/PRD/权限管理/权限管理模块PRD.md +++ b/Project/fonrey/PRD/权限管理/权限管理模块PRD.md @@ -6,6 +6,14 @@ **所属系统**: Fonrey 房产经纪管理系统 **关联模块**: 组织人事管理、房源管理、客源管理、系统设置 +## 变更历史 + +| 版本 | 日期 | 作者 | 变更说明 | +|------|------|------|---------| +| v1.0 | — | 产品经理 | 初稿 | +| v1.1 | 2026-04-24 | 产品经理 | 锁定多角色合并规则 = 并集 / 最宽松 | + + --- ## 1. 问题陈述 diff --git a/Project/fonrey/PRD/登录管理/用户登录管理模块PRD.md b/Project/fonrey/PRD/登录管理/用户登录管理模块PRD.md index 530d3148..15d98b76 100644 --- a/Project/fonrey/PRD/登录管理/用户登录管理模块PRD.md +++ b/Project/fonrey/PRD/登录管理/用户登录管理模块PRD.md @@ -7,6 +7,14 @@ **所属系统**: Fonrey 房产经纪管理系统 **关联模块**: 组织人事管理、权限管理、系统管理 +## 变更历史 + +| 版本 | 日期 | 作者 | 变更说明 | +|------|------|------|---------| +| v1.x | — | 产品经理 | 初稿至 v1.9(详见 git 历史) | +| v2.0 | 2026-04-30 | 产品经理 | 根据 review 后的 §4 用户故事全面同步 §5 功能详细说明:删除找回用户名流程及邮件模板;找回密码改为纯短信流程;新增 §5.5 手机验证码登录详细说明;§6 技术注意事项更新短信依赖/风险/开放问题;§8.2 接口清单同步正式功能状态;全文「Tenant ID」对外概念统一替换为「Tenant Code」 | + + --- ## 1. 问题陈述 diff --git a/Project/fonrey/PRD/系统管理/系统管理模块PRD.md b/Project/fonrey/PRD/系统管理/系统管理模块PRD.md index 29c46fd4..7ab9aea3 100644 --- a/Project/fonrey/PRD/系统管理/系统管理模块PRD.md +++ b/Project/fonrey/PRD/系统管理/系统管理模块PRD.md @@ -6,6 +6,13 @@ **版本**:v1.0 **利益相关方**:工程负责人、运营团队、安全合规、客户成功团队 +## 变更历史 + +| 版本 | 日期 | 作者 | 变更说明 | +|------|------|------|---------| +| v1.0 | 2026-04-24 | 产品经理 | 初稿 | + + --- ## 1. 问题陈述 diff --git a/Project/fonrey/PRD/系统配置/系统配置模块PRD.md b/Project/fonrey/PRD/系统配置/系统配置模块PRD.md index 37b5900d..54859acd 100644 --- a/Project/fonrey/PRD/系统配置/系统配置模块PRD.md +++ b/Project/fonrey/PRD/系统配置/系统配置模块PRD.md @@ -7,6 +7,13 @@ **关联 Task**:US-SETTING-001 **相关文档**:`DATA_MODEL/ENUMS.md`、`PRD/系统配置/系统配置参数数据.md`、`DATA_MODEL/DATA_MODEL.md` +## 变更历史 + +| 版本 | 日期 | 作者 | 变更说明 | +|------|------|------|---------| +| v0.1 | 2026-04-27 | Nova(PM) | 初稿(MVP 范围) | + + --- ## 1. 问题陈述 diff --git a/Project/fonrey/PRD/组织人事管理/组织人事管理模块PRD.md b/Project/fonrey/PRD/组织人事管理/组织人事管理模块PRD.md index c3e475da..ab9972b7 100644 --- a/Project/fonrey/PRD/组织人事管理/组织人事管理模块PRD.md +++ b/Project/fonrey/PRD/组织人事管理/组织人事管理模块PRD.md @@ -6,6 +6,15 @@ **所属系统**: Fonrey 房产经纪管理系统 **关联模块**: 权限管理、房源管理、客源管理、系统设置 +## 变更历史 + +| 版本 | 日期 | 作者 | 变更说明 | +|------|------|------|---------| +| v1.0 | — | 产品经理 | 初稿 | +| v1.1 | — | 产品经理 | (详见 git 历史) | +| v1.2 | 2026-04-24 | 产品经理 | 移除技术实现章节,该部分由独立 DATA_MODEL 文档承载 | + + --- ## 1. 问题陈述 diff --git a/Project/fonrey/TECH_STACK/API_CONTRACT.md b/Project/fonrey/TECH_STACK/API_CONTRACT.md index 77f244f6..3d19c5f5 100644 --- a/Project/fonrey/TECH_STACK/API_CONTRACT.md +++ b/Project/fonrey/TECH_STACK/API_CONTRACT.md @@ -9,6 +9,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 1. 文档定位与原则 本文件定义 Fonrey 全局 API 契约标准,解决跨模块接口风格漂移问题。模块技术方案中的 API 章节必须遵循本文件,不得各自定义冲突规则。 @@ -477,7 +483,7 @@ git diff --exit-code openapi.json || echo "⚠️ openapi.json has changed — # 对本地运行的 dev server 跑契约测试 schemathesis run openapi.json \ --base-url http://localhost:8000 \ - --auth-header "Authorization: Bearer $TEST_TOKEN" \ + --auth-header "Authorization: Bearer *** \ --checks status_code_conformance response_schema_conformance \ --tag property # 可按模块 tag 分批跑 ``` diff --git a/Project/fonrey/TECH_STACK/TECH_STACK 文档要求.md b/Project/fonrey/TECH_STACK/TECH_STACK 文档要求.md index c010f983..cf476f59 100644 --- a/Project/fonrey/TECH_STACK/TECH_STACK 文档要求.md +++ b/Project/fonrey/TECH_STACK/TECH_STACK 文档要求.md @@ -1,3 +1,9 @@ +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + #### 1. 项目概览(Project Overview) 用 2-3 句话说清楚这是什么项目、核心用途、目标用户。AI 需要这个"北极星"来判断所有技术取舍。 @@ -5,6 +11,7 @@ md ```md + ## Project Overview A B2B SaaS invoice management tool. Target users are SMB accountants. Prioritize reliability and data integrity over flashy UI. @@ -158,4 +165,4 @@ md |🟡 重要|关键约定|保持风格一致| |🟢 加分|测试策略 + 代码风格|提升整体质量| -**核心原则**:写给 AI 看的文档要比写给人看的**更具体、更强硬、更少歧义**。任何"视情况而定"的描述,AI 都会做出你不想要的选择。 \ No newline at end of file +**核心原则**:写给 AI 看的文档要比写给人看的**更具体、更强硬、更少歧义**。任何"视情况而定"的描述,AI 都会做出你不想要的选择。 diff --git a/Project/fonrey/TECH_STACK/TECH_STACK.md b/Project/fonrey/TECH_STACK/TECH_STACK.md index 55e5ce12..41c3d117 100644 --- a/Project/fonrey/TECH_STACK/TECH_STACK.md +++ b/Project/fonrey/TECH_STACK/TECH_STACK.md @@ -2,11 +2,18 @@ > **For AI assistants**: Read this entire file before writing any code. All decisions here are final. Do not suggest alternatives unless asked. -**版本**: 2.3 | **最后更新**: 2026-04-29 +**版本**: 2.5 | **最后更新**: 2026-04-30 **定位**: 本文档是 Fonrey 项目技术栈的**总索引**。所有跨模块的技术决策、版本约束、目录规范、禁止项在此定稿;**单一模块的具体技术方案**(数据模型、服务层、HTMX 交互、Celery 任务等)见各自子文档(见 §9 索引)。 --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 新增 ADR 导航入口与变更治理规则(README 缺失场景下接入 TECH_STACK / DATA_MODEL / AGENTS) | +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 1. 项目概览 **Fonrey(房睿)房产经纪管理系统** —— 面向房地产经纪公司的 B2B SaaS 平台,解决房源/客源信息散乱、跟进缺失、重复录入等痛点,支撑单租户 89,000+ 房源数据量级下的高效匹配。 @@ -115,11 +122,11 @@ apps/property/ ## 7. 客户端发布技术栈(Desktop Client) -> **完整方案**见 PRD:`PRD/发布管理/客户端发布管理模块PRD.md`。本节仅列最终结论。 +> **完整方案**见:`TECH_STACK/客户端发布管理技术方案.md`(实现口径)与 `PRD/发布管理/客户端发布管理模块PRD.md`(需求口径)。本节仅列最终结论。 - **框架**:Electron(稳定版) + Chromium 内核(随版本固定,不依赖系统浏览器) - **渲染层**:直接加载 Fonrey Web URL,**100% 复用 HTMX + Alpine + Tailwind**,渲染层零新增框架 -- **自动更新**:`electron-updater`;更新包存 R2 / 经 CDN 分发;后端检测端点 `GET /api/client/updates/latest/`(公开);启动时 + 每 4h 轮询;后台静默下载,下载完成提示重启;服务端可标记强制更新 +- **自动更新**:`electron-updater`;更新包存 R2 / 经 CDN 分发;后端检测端点 `GET /api/release/updates/latest/`(公开);启动时 + 每 4h 轮询;后台静默下载,下载完成提示重启;服务端可标记强制更新 - **构建**:`electron-builder` 输出 NSIS `.exe` + 便携版 `.zip`;目标 Windows x64(优先),ARM64 按需 - **代码签名**:EV 证书,CI/CD 自动签名,消除 SmartScreen 警告 - **完整性校验**:下载后必须校验 SHA256 与服务端返回一致才能安装 @@ -140,11 +147,12 @@ apps/property/ | 楼盘管理 | [`楼盘管理技术方案.md`](./楼盘管理技术方案.md) | `PRD/房源管理/`(含楼盘) | `DATA_MODEL/DATA_MODEL_COMPLEX.md` | `tests/integration/complex/test_us_complex.py` | `v1.0` | | 组织人事 | [`组织人事技术方案.md`](./组织人事技术方案.md) | `PRD/组织人事管理/` | `DATA_MODEL/DATA_MODEL_ORG.md` | `tests/integration/org/test_us_org.py` | `v1.0` | | 系统设置 | [`系统设置技术方案.md`](./系统设置技术方案.md) | `PRD/系统配置/`、`PRD/系统管理/` | `DATA_MODEL/DATA_MODEL_SETTING.md` | `tests/integration/setting/test_us_setting.py` | `v1.2` | -| 客户端发布 | 见本文档 §7 | `PRD/发布管理/客户端发布管理模块PRD.md` | — | — | `§7(本文)` | +| 客户端发布 | [`客户端发布管理技术方案.md`](./客户端发布管理技术方案.md) | `PRD/发布管理/客户端发布管理模块PRD.md` | `DATA_MODEL/DATA_MODEL_PUBLIC.md`(`client_releases` / `client_heartbeats`) | `tests/integration/release/test_us_release.py` | `v1.0` | **总览数据模型**:[`DATA_MODEL/DATA_MODEL.md`](../DATA_MODEL/DATA_MODEL.md) **全局 API 契约**:[`API_CONTRACT.md`](./API_CONTRACT.md) **MVP 范围与产品总览**:[`PRD/PRD_MVP.md`](../PRD/PRD_MVP.md) +**ADR 动态决策记录**:[`ADR.md`](../ADR.md) --- @@ -172,7 +180,7 @@ apps/property/ | 14 | 落地顺序建议 | | 15 | 文档同步规则 | -### 9.2 模块覆盖情况(2026-04-27) +### 9.2 模块覆盖情况(2026-04-30) | 模块 | 技术方案文档 | 15 章节覆盖 | 备注 | |---|---|---:|---| @@ -183,6 +191,7 @@ apps/property/ | 楼盘管理 | `楼盘管理技术方案.md` | 15/15 | 完全覆盖 | | 组织人事 | `组织人事技术方案.md` | 15/15 | 完全覆盖 | | 系统设置 | `系统设置技术方案.md` | 15/15 | 完全覆盖 | +| 客户端发布 | `客户端发布管理技术方案.md` | 15/15 | 新增,已覆盖 Electron/EV/Heartbeat/自动升级/R2/官网下载/便携版 | ### 9.3 使用规则(对 AI Agent 生效) @@ -238,6 +247,9 @@ Fonrey 采用 AI vibe coding 模式开发,测试是保证每日迭代质量的 - API 契约总则在 `API_CONTRACT.md` 维护;模块文档只做模块特化,不得覆盖全局契约 - 任何技术栈变更(替换组件、升级主版本、新增外部服务)须同步更新本文档 §2、§5、§6 - 新增模块时,先在 §4 目录结构补位,再在 §8 索引登记子文档 +- 涉及跨模块规则、接口口径、测试治理、范围边界的决策,必须先写入 `ADR.md`(新增 accepted 记录)再改 TECH_STACK/PRD/DATA_MODEL/TEST_CASES +- 若已有决策被替代,必须在 `ADR.md` 新增 superseded 记录并显式关联新 ADR;禁止静默改文档覆盖历史 +- 提交 PR 时,若变更命中上述决策域,必须在描述中附 ADR ID(如 `ADR-20260430-011`) - 测试规范变更须同步更新 §10 关键结论,完整细节在 [`测试规范.md`](./测试规范.md) 中维护 - 15 章节统一模板发生变更时,须先更新 §9 标准章节骨架,再同步各模块文档 @@ -448,5 +460,3 @@ class ScopedModel(models.Model): | own | 员工查自己负责的数据 | 返回数据 ✅ | | department | 店长查本部门数据 | 按角色返回 ✅ | | cross_department_denied | 普通员工跨部门查询 | 空集或 403 ✅ | - - diff --git a/Project/fonrey/TECH_STACK/客户端发布管理技术方案.md b/Project/fonrey/TECH_STACK/客户端发布管理技术方案.md new file mode 100644 index 00000000..6e3e3568 --- /dev/null +++ b/Project/fonrey/TECH_STACK/客户端发布管理技术方案.md @@ -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": "", + "portable_checksum_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": "", + "portable_checksum_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,首次运行写入用户目录配置,不修改系统级安装。 diff --git a/Project/fonrey/TECH_STACK/客源管理技术方案.md b/Project/fonrey/TECH_STACK/客源管理技术方案.md index 4a756e92..8ac1a4a9 100644 --- a/Project/fonrey/TECH_STACK/客源管理技术方案.md +++ b/Project/fonrey/TECH_STACK/客源管理技术方案.md @@ -13,6 +13,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、文档定位与边界 本文件聚焦客源模块的: diff --git a/Project/fonrey/TECH_STACK/房源管理技术方案.md b/Project/fonrey/TECH_STACK/房源管理技术方案.md index bbe61570..9abd3275 100644 --- a/Project/fonrey/TECH_STACK/房源管理技术方案.md +++ b/Project/fonrey/TECH_STACK/房源管理技术方案.md @@ -13,6 +13,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、文档定位与边界 本文件只定义房源模块的: diff --git a/Project/fonrey/TECH_STACK/权限管理系统技术方案.md b/Project/fonrey/TECH_STACK/权限管理系统技术方案.md index 1da63ccc..449ca6ea 100644 --- a/Project/fonrey/TECH_STACK/权限管理系统技术方案.md +++ b/Project/fonrey/TECH_STACK/权限管理系统技术方案.md @@ -12,6 +12,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、文档定位与边界 本文件仅定义权限模块的: diff --git a/Project/fonrey/TECH_STACK/楼盘管理技术方案.md b/Project/fonrey/TECH_STACK/楼盘管理技术方案.md index df76a63e..8e29d128 100644 --- a/Project/fonrey/TECH_STACK/楼盘管理技术方案.md +++ b/Project/fonrey/TECH_STACK/楼盘管理技术方案.md @@ -13,6 +13,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、文档定位与边界 本文件只定义楼盘模块的: diff --git a/Project/fonrey/TECH_STACK/测试规范.md b/Project/fonrey/TECH_STACK/测试规范.md index 8cf46455..78954a28 100644 --- a/Project/fonrey/TECH_STACK/测试规范.md +++ b/Project/fonrey/TECH_STACK/测试规范.md @@ -10,6 +10,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、文档定位与边界 本文件定义项目统一测试标准: diff --git a/Project/fonrey/TECH_STACK/登录管理技术方案.md b/Project/fonrey/TECH_STACK/登录管理技术方案.md index 1f14f342..ba49ee3c 100644 --- a/Project/fonrey/TECH_STACK/登录管理技术方案.md +++ b/Project/fonrey/TECH_STACK/登录管理技术方案.md @@ -13,6 +13,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、文档定位与边界 本文件定义登录模块的实现口径: diff --git a/Project/fonrey/TECH_STACK/系统管理技术文档.md b/Project/fonrey/TECH_STACK/系统管理技术文档.md index 972de8a2..e1a94994 100644 --- a/Project/fonrey/TECH_STACK/系统管理技术文档.md +++ b/Project/fonrey/TECH_STACK/系统管理技术文档.md @@ -13,6 +13,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 1. 模块边界与定位 | 维度 | 说明 | diff --git a/Project/fonrey/TECH_STACK/系统设置技术方案.md b/Project/fonrey/TECH_STACK/系统设置技术方案.md index 3a8ef9d8..ea7e04ac 100644 --- a/Project/fonrey/TECH_STACK/系统设置技术方案.md +++ b/Project/fonrey/TECH_STACK/系统设置技术方案.md @@ -13,6 +13,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、文档定位与边界 本文件仅定义系统设置模块的: diff --git a/Project/fonrey/TECH_STACK/组织人事技术方案.md b/Project/fonrey/TECH_STACK/组织人事技术方案.md index 2e4e38ae..11309cb0 100644 --- a/Project/fonrey/TECH_STACK/组织人事技术方案.md +++ b/Project/fonrey/TECH_STACK/组织人事技术方案.md @@ -13,6 +13,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 一、文档定位与边界 本文件只定义组织人事模块的: diff --git a/Project/fonrey/TEST_CASES/TEST_CASES_LOGIN_MODULE.md b/Project/fonrey/TEST_CASES/TEST_CASES_LOGIN_MODULE.md index 228eccd7..888cde37 100644 --- a/Project/fonrey/TEST_CASES/TEST_CASES_LOGIN_MODULE.md +++ b/Project/fonrey/TEST_CASES/TEST_CASES_LOGIN_MODULE.md @@ -7,6 +7,12 @@ --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 1. 目标与原则 1. 本文档用于让工程师直接生成自动化测试代码(API 集成测试 + Web E2E)。 diff --git a/Project/fonrey/TEST_CASES/TEST_CASES_RELEASE_MODULE.md b/Project/fonrey/TEST_CASES/TEST_CASES_RELEASE_MODULE.md new file mode 100644 index 00000000..2125c419 --- /dev/null +++ b/Project/fonrey/TEST_CASES/TEST_CASES_RELEASE_MODULE.md @@ -0,0 +1,221 @@ +# Fonrey 客户端发布模块测试用例文档(可自动化) + +> 文档版本:v1.0 +> 适用范围:`PRD/发布管理/客户端发布管理模块PRD.md` v1.2 +> 用例编号范围:`TC-FON-000049` ~ `TC-FON-000072`(全局唯一) +> 编号规范:`TEST_CASES/TEST_CASE_ID_SPEC.md` + +--- + +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + +## 1. 目标与原则 + +1. 覆盖客户端发布模块 P0:下载安装、自动升级、版本发布、版本分布统计。 +2. 每个用例必须可追溯到 `test_case_id + step_id`。 +3. 优先 API 集成自动化,客户端壳层 UI 能力以 E2E/手工补充。 +4. 失败报告必须定位到具体步骤,并保留请求响应或截图证据。 + +--- + +## 2. 自动化执行与报告要求(强制) + +- 执行层: + - API 集成:`pytest + pytest-django`(public schema) + - 客户端 E2E:后续 `playwright + Electron`(当前先预留) +- 每步输出:`run_id / test_case_id / step_id / status / expected_result / actual_result / error_message` +- 失败附件: + - API:请求体、响应体、关键日志路径 + - E2E:截图与视频路径 + +--- + +## 3. 客户端发布模块 API 端点口径(以 PRD/TECH_STACK 为准) + +- `GET /api/release/updates/latest/` +- `GET /api/release/updates/` +- `POST /api/release/updates/` +- `PATCH /api/release/updates/{id}/` +- `POST /api/release/updates/{id}/rollback/` +- `POST /api/release/heartbeats/` +- `GET /api/release/metrics/version-distribution/` +- `GET /api/release/metrics/tenant-installs/` +- `GET /api/release/metrics/tenant-leaderboard/` + +--- + +## 4. 全量测试用例清单(24条) + +## A. 下载与完整性(Story 1) + +### TC-FON-000049 官网下载页可访问且展示最新版本 +- 级别:E2E +- 步骤: + - `TC-FON-000049-S01` 访问官网客户端下载页 + - `TC-FON-000049-S02` 校验展示版本号/发布日期/下载按钮 + - `TC-FON-000049-S03` 校验下载按钮链接可用 +- 预期:页面可访问,元信息完整 + +### TC-FON-000050 latest 接口返回下载地址与校验值 +- 级别:API +- 步骤: + - `TC-FON-000050-S01` 调用 `GET /api/release/updates/latest/?platform=win32&arch=x64¤t_version=1.2.0` + - `TC-FON-000050-S02` 校验返回 `download_url`、`checksum_sha256`、`release_notes` + - `TC-FON-000050-S03` 校验 `checksum_sha256` 长度为 64 +- 预期:响应字段完整且格式正确 + +### TC-FON-000051 安装包 SHA256 校验通过 +- 级别:API+脚本 +- 步骤: + - `TC-FON-000051-S01` 获取 `download_url` 和 `checksum_sha256` + - `TC-FON-000051-S02` 下载文件并计算本地 SHA256 + - `TC-FON-000051-S03` 比对本地值与接口返回值 +- 预期:一致,允许进入安装流程 + +### TC-FON-000052 安装包 SHA256 不一致时拒绝安装 +- 级别:客户端集成 +- 步骤: + - `TC-FON-000052-S01` 构造篡改包或错误 checksum + - `TC-FON-000052-S02` 触发更新下载完成后的校验 + - `TC-FON-000052-S03` 校验客户端拒绝安装并保留当前版本 +- 预期:提示完整性校验失败,不覆盖现版本 + +--- + +## B. 自动升级(Story 3) + +### TC-FON-000053 无新版本时返回 has_update=false +- 级别:API +- 步骤:`S01` 用当前最新版本调用 latest;`S02` 校验 `has_update=false`;`S03` 校验 `latest_version` 存在 +- 预期:不触发更新 + +### TC-FON-000054 有新版本时返回升级信息 +- 级别:API +- 步骤:`S01` 用旧版本调用 latest;`S02` 校验 `has_update=true`;`S03` 校验 `latest_version` 高于 `current_version` +- 预期:触发可升级状态 + +### TC-FON-000055 普通更新允许“稍后提醒” +- 级别:客户端 E2E +- 步骤:`S01` 服务端发布 `release_type=normal`;`S02` 客户端检测更新;`S03` 校验出现“立即更新/稍后提醒” +- 预期:普通更新可延期 + +### TC-FON-000056 强制更新不允许“稍后提醒” +- 级别:客户端 E2E +- 步骤:`S01` 服务端发布 `release_type=force`;`S02` 客户端检测更新;`S03` 校验仅可“立即更新” +- 预期:必须升级后继续使用 + +### TC-FON-000057 更新下载失败时保持当前版本可用 +- 级别:客户端 E2E +- 步骤:`S01` 模拟下载中断/磁盘不足;`S02` 校验错误提示;`S03` 校验当前版本仍可正常操作 +- 预期:失败可恢复,不影响业务使用 + +### TC-FON-000058 更新成功后重启生效并保留登录态 +- 级别:客户端 E2E +- 步骤:`S01` 执行更新并下载完成;`S02` 重启客户端;`S03` 校验标题版本号更新且会话恢复 +- 预期:升级成功且无需重新登录 + +--- + +## C. 平台发布管理(Story 4) + +### TC-FON-000059 平台管理员可创建草稿版本 +- 级别:API +- 步骤:`S01` 调用 `POST /api/release/updates/` 创建草稿;`S02` 校验 `status=draft`;`S03` 校验版本记录可在列表查询到 +- 预期:草稿创建成功 + +### TC-FON-000060 版本号必须符合 SemVer +- 级别:API +- 步骤:`S01` 提交非法版本号(如 `1.2`);`S02` 校验 400;`S03` 校验错误码 `RELEASE_VERSION_INVALID` +- 预期:非法版本号被拒绝 + +### TC-FON-000061 发布后 latest 接口即时可见 +- 级别:API +- 步骤:`S01` 将草稿改为 `published`(PATCH);`S02` 调用 latest;`S03` 校验返回该版本 +- 预期:发布即时生效 + +### TC-FON-000062 同平台架构仅允许一个 published +- 级别:API +- 步骤:`S01` 已有一个 published;`S02` 尝试并发发布第二个;`S03` 校验冲突(409) +- 预期:唯一生效版本约束成立 + +### TC-FON-000063 版本下线后 latest 不再返回该版本 +- 级别:API +- 步骤:`S01` 将已发布版本改 `archived`;`S02` 调用 latest;`S03` 校验不返回已下线版本 +- 预期:下线立即生效 + +### TC-FON-000064 回滚接口将历史版本恢复为 published +- 级别:API +- 步骤:`S01` 调用 `POST /api/release/updates/{id}/rollback/`;`S02` 校验目标版本为 `published`;`S03` 校验原版本自动下线 +- 预期:回滚原子完成 + +--- + +## D. Heartbeat 与版本分布(Story 5) + +### TC-FON-000065 启动心跳首次上报创建记录 +- 级别:API +- 步骤:`S01` 调用 `POST /api/release/heartbeats/`;`S02` 校验写入 `(tenant_id, device_id)`;`S03` 校验 `launch_count=1` +- 预期:首次上报成功 + +### TC-FON-000066 启动心跳重复上报走 Upsert +- 级别:API +- 步骤:`S01` 对同 `(tenant_id,device_id)` 再次上报;`S02` 校验未新增新行;`S03` 校验 `launch_count+1` 且 `last_seen_at` 刷新 +- 预期:符合 Upsert 语义 + +### TC-FON-000067 版本分布统计按 24h 活跃口径 +- 级别:API +- 步骤:`S01` 构造多版本心跳数据(含超 24h);`S02` 调用 `GET /api/release/metrics/version-distribution/`;`S03` 校验仅统计最近 24h 活跃 +- 预期:统计口径正确 + +### TC-FON-000068 指定租户安装统计返回活跃+历史总数 +- 级别:API +- 步骤:`S01` 调用 `GET /api/release/metrics/tenant-installs/?tenant_id=...`;`S02` 校验返回 `active_install_count_24h`;`S03` 校验返回 `historical_install_count` +- 预期:两个指标均返回且数值正确 + +### TC-FON-000069 租户活跃榜按活跃安装数降序 +- 级别:API +- 步骤:`S01` 调用 `GET /api/release/metrics/tenant-leaderboard/`;`S02` 校验字段包含 `tenant_code/tenant_name/active/historical`;`S03` 校验按活跃安装数降序 +- 预期:排序与字段正确 + +### TC-FON-000070 心跳接口拒绝未鉴权请求 +- 级别:API +- 步骤:`S01` 未带会话访问 heartbeats;`S02` 校验 401/403;`S03` 校验无数据写入 +- 预期:防伪造上报有效 + +### TC-FON-000071 发布管理接口拒绝非平台管理员 +- 级别:API +- 步骤:`S01` 租户管理员调用 `POST /api/release/updates/`;`S02` 校验 403;`S03` 校验无新版本记录 +- 预期:权限边界正确 + +### TC-FON-000072 下载检测接口限流生效 +- 级别:API +- 步骤:`S01` 同 IP 高频访问 latest;`S02` 校验前 N 次成功;`S03` 校验超阈值 429 +- 预期:触发限流,保护服务 + +--- + +## 5. 工程实现指引(给测试开发工程师) + +1. **目录建议** + - `tests/integration/release/test_us_release.py` + - `tests/e2e/release/test_tc_fon_000049_000072.spec.ts`(预留) +2. **命名规范** + - 函数名必须带用例ID,例如:`def test_tc_fon_000062_single_published_constraint():` +3. **步骤日志** + - 每步打印 step_id,断言失败消息包含 step_id +4. **报告产物** + - `reports/release_run_.json` +5. **CI 门禁(阶段性)** + - P0 API 用例(000050, 000053~000054, 000059~000069, 000070~000072)必须全过 + +--- + +## 6. 变更规则 + +- 本模块新增用例从 `TC-FON-000073` 继续递增 +- 全项目继续使用单一序列,不得重号 +- 历史 ID 仅可 `deprecated`,不得复用 diff --git a/Project/fonrey/TEST_CASES/TEST_CASE_ID_SPEC.md b/Project/fonrey/TEST_CASES/TEST_CASE_ID_SPEC.md index bf2f33db..d0226a20 100644 --- a/Project/fonrey/TEST_CASES/TEST_CASE_ID_SPEC.md +++ b/Project/fonrey/TEST_CASES/TEST_CASE_ID_SPEC.md @@ -1,5 +1,11 @@ # 测试用例全局编号规范(Fonrey) +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 1. 目标 确保所有模块(登录、房源、客源等)测试用例编号**全局唯一**,便于自动化执行、失败定位、统计报表。 diff --git a/Project/fonrey/TEST_CASES/TEST_CASE_REGISTRY.md b/Project/fonrey/TEST_CASES/TEST_CASE_REGISTRY.md index 8639f1c2..207d046b 100644 --- a/Project/fonrey/TEST_CASES/TEST_CASE_REGISTRY.md +++ b/Project/fonrey/TEST_CASES/TEST_CASE_REGISTRY.md @@ -1,11 +1,17 @@ # Fonrey 测试用例编号注册表(全局唯一) > 用途:统一管理全项目测试用例编号,避免撞号,支持自动化报告追踪。 -> 适用范围:登录、房源、客源、组织人事、权限、系统设置等全部模块。 +> 适用范围:登录、房源、客源、组织人事、权限、系统设置、客户端发布等全部模块。 > 编号规范:见 `TEST_CASES/TEST_CASE_ID_SPEC.md` --- +## 变更历史 + +| 日期 | 变更人 | 变更内容 | +|---|---|---| +| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) | + ## 1) 全局规则(强制) 1. 全项目共用一个递增序列:`TC-FON-XXXXXX`。 @@ -18,12 +24,12 @@ ## 2) 当前编号水位 -- **已分配到**:`TC-FON-000048` -- **下一个可用编号**:`TC-FON-000049` +- **已分配到**:`TC-FON-000072` +- **下一个可用编号**:`TC-FON-000073` - **最后更新人**:Atlas - **最后更新时间**:2026-04-30 -> 说明:下一个新增用例(不论哪个模块)都应从 `TC-FON-000049` 开始。 +> 说明:下一个新增用例(不论哪个模块)都应从 `TC-FON-000073` 开始。 --- @@ -32,6 +38,7 @@ | 批次ID | 模块 | 编号范围 | 数量 | 状态 | 文档 | |---|---|---:|---:|---|---| | BATCH-LOGIN-001 | 登录模块 | TC-FON-000001 ~ TC-FON-000048 | 48 | active | `TEST_CASES/TEST_CASES_LOGIN_MODULE.md` | +| BATCH-RELEASE-001 | 客户端发布模块 | TC-FON-000049 ~ TC-FON-000072 | 24 | active | `TEST_CASES/TEST_CASES_RELEASE_MODULE.md` | **状态枚举**: - `active`:有效且执行中 @@ -48,6 +55,8 @@ |---|---|---|---|---|---| | TC-FON-000001 | 登录 | Tenant Code 页面首启展示 | active | v1.0 | 见登录用例文档 | | TC-FON-000048 | 登录 | 验证码登录成功/失败/锁定限制 | active | v1.0 | 见登录用例文档 | +| TC-FON-000049 | 客户端发布 | 官网下载页可访问且展示最新版本 | active | v1.0 | 见发布模块用例文档 | +| TC-FON-000072 | 客户端发布 | 下载检测接口限流生效 | active | v1.0 | 见发布模块用例文档 | --- @@ -75,3 +84,4 @@ | 日期 | 变更人 | 变更内容 | |---|---|---| | 2026-04-30 | Atlas | 初始化注册表;登记登录模块 000001~000048;下一号设为 000049 | +| 2026-04-30 | Atlas | 新增客户端发布模块测试用例文档;登记 000049~000072;下一号设为 000073 |