Files
danyang-match/docs/superpowers/specs/2026-10-14-global-public-id-design.md
T
WorkBuddy 3c2b967274
CI/CD Pipeline / UI Contracts (source-structure gates) (push) Canceled after 0s
CI/CD Pipeline / E2E (live stack) (push) Canceled after 0s
CI/CD Pipeline / Backend Build & Test (push) Canceled after 0s
CI/CD Pipeline / Admin Web Build (push) Canceled after 0s
CI/CD Pipeline / Mini Program Compile Check (push) Canceled after 0s
CI/CD Pipeline / Migration Validation (push) Canceled after 0s
CI/CD Pipeline / Test Shell Guard (Phase 23 Gate) (push) Canceled after 0s
release: freeze 2026-10-15 validated release baseline
2026-10-15 09:47:31 +08:00

6.9 KiB
Raw Blame History

全平台业务展示编号统一设计

背景与目标

用户在联系授权审批页看到红娘与用户 UUID,且管理端、小程序部分页面继续显示底层 UUID。统一全平台用户可见编号,使人员、业务记录和活动在 Web、小程序及运营接口中均可读、稳定、唯一,并保持既有数据关联与权限边界。

已确认编号格式

全平台公开展示编号统一为 13 位 ASCII 字母数字:2 位类型前缀 + Asia/Shanghai 日期 YYYYMMDD + 3 位当日序号。例:HN20261013001、YH20261014002、RW20261014001、HD20261014001。

用户编号采用 YH 前缀,注册日后按性别分别排名;男性序号为奇数、女性序号为偶数,序号宽度 3 位(男性 001/003/...,女性 002/004/...)。红娘使用 HN,其他工作人员使用 GL。任务使用 RW,活动使用 HD。推荐对象和被举报人是用户,因此显示其 YH 编号,不另造人员编号。

其他需要在页面展示的业务记录使用独立前缀,首批建议为:红娘服务 FW、红娘推荐记录 TJ、联系授权 LX、服务分配 FP、跟进记录 GJ、举报记录 JB、转介 ZF、审核任务 RW。实施盘点若发现其他实体已向用户展示其主键,必须列入覆盖矩阵并在编码前确认前缀;不得临时回退显示 UUID。

序号达到 999 时拒绝分配并记录明确错误,不截断、不复用旧编号。编号创建后不可变;用户性别资料更正不重算既有编号。

设计决策

内部主键与公开编号

  • PostgreSQL UUID 主键、外键、JWT subject、数据范围查询、幂等键和内部服务间调用保持不变。
  • 每个需要公开展示的实体增加持久化公开编号字段(已存在的 users.display_number、operators.display_id 保留并扩展格式);所有业务编号设置唯一约束。
  • API 面向展示的数据提供明确命名的 displayId / displayNumber 字段。现有 id、userId 等 UUID 仅保留为内部资源寻址和向后兼容字段;页面表格、详情、弹窗和导出文案不得渲染这些 UUID。
  • 写请求仍使用既有 UUID 路由参数或受保护的内部 ID 字段,避免更改所有外键和既有 API 路由;用户可见的人员选择、搜索和表单输入改用搜索接口解析公开编号到内部用户。

编号生成与历史数据

  • PostgreSQL 提供按 prefix + date + sequence_group 原子递增的编号分配器,以事务级 INSERT ... ON CONFLICT ... DO UPDATE ... RETURNING(或等价数据库原子操作)处理并发;普通实体的 sequence_group 为空,用户按性别分别计数并以步长 2 产生奇偶序号。应用层不得用 COUNT(*) + 1 生成序号。
  • 日期统一按 Asia/Shanghai 取值。调用方在创建实体的同一事务内取得编号并写入实体;失败整体回滚,唯一约束作为最终并发保护。
  • 迁移为所有既有记录回填公开编号。用户按注册日、实名性别和注册时间排名;红娘及工作人员按创建日与稳定主键顺序排名;其他实体按创建时间与 UUID 稳定排序排名。按实体、日期分别编号。
  • 用户旧 YH...、工作人员旧 HN.../GL... 编号更新为新格式;应检查外部可见引用,必要时保留旧编号别名仅供检索,不再用于展示。不得更换 UUID 主键或破坏既有关系。
  • 回填前执行冲突和数量预检;迁移必须可在空库和包含现有演示数据的 PostgreSQL 上重复验证。历史回填不可逆展示变化须提供旧号到新号映射证据。

展示范围

  • 红娘联系授权:红娘列显示 HN...,用户列显示 YH...。
  • 红娘工作台、服务详情、推荐列表、跟进和转介:服务/推荐/跟进/转介记录显示其公开业务编号;申请服务用户、推荐对象、被推荐人始终显示 YH...,操作者显示 HN.../GL...。
  • 活动管理、报名、互选、签到:活动显示 HD...;参与者显示 YH...。
  • 举报、安全与审核:举报记录显示 JB...,被举报人、举报人显示 YH...;审核工作项显示 RW...,工作人员显示 GL.../HN...。
  • 审计日志若展示实体引用,应显示已解析的业务编号;对无公开编号或权限不足的引用显示中文类型标签和脱敏占位,不暴露 UUID。
  • 用户小程序对外展示个人编号、活动编号、红娘服务进度编号时使用对应业务编号;交互调用使用内部 ID,不向用户暴露 UUID。

数据流

创建业务对象
  -> 数据库原子分配器生成公开编号
  -> 与 UUID 主键在同一事务写入
  -> API DTO 同时提供内部寻址字段与公开展示字段
  -> Web / 小程序只渲染公开字段
  -> 用户选择或搜索用公开编号查询,再由后端做权限校验

安全与兼容

  • 公开编号不可作为授权凭证;所有权限校验仍基于认证主体、UUID 关联和现有 DataScope/Capability 规则。
  • 不返回敏感资料,不通过编号查询绕过字段脱敏或组织范围。
  • 保留旧 API UUID 参数以兼容现有页面和客户端;新增展示字段不改变原 JSON 字段语义。
  • 对用户输入的编号严格校验前缀、长度和字符集;未找到、已删除或越权对象使用既有统一错误语义,避免枚举信息泄露。

验收标准

  1. 公开编号全部满足 ^[A-Z]{2}[0-9]{11}$,唯一、非空、持久化;新建和历史记录均覆盖。
  2. 男性用户当日序号为奇数、女性为偶数;其余编号符合各自前缀和创建日。
  3. 并发创建同日同类型记录不会重复编号;达到 999 时明确拒绝。
  4. 联系授权截图、管理端业务列表、审核/举报/活动/推荐页面、小程序业务详情无 UUID 展示。
  5. 用户编号在推荐对象、被举报人、活动参与者等跨模块场景一致。
  6. 既有 UUID 主外键、登录、权限、数据范围、操作请求与旧 API 路由继续工作。
  7. 后端测试、迁移验证、管理端类型检查/构建、小程序结构与行为检查通过;演示 Docker 环境完成迁移和 HTTP 抽查。

明确不在本次范围

  • 不迁移数据库主键类型,不改 JWT subject,不把 UUID 外键改成业务编号。
  • 不改变红娘服务、推荐、联系授权、举报、活动和审核的业务状态机或权限规则。
  • 不因编号暴露而开放用户搜索、手机号、身份证或任何其他敏感字段。
  • 不生成未展示且无业务价值的随机内部记录编号;只对用户可见或跨角色操作中可见的业务实体分配公开编号。

实施前置检查

实现前建立“公开 ID 展示清单”:逐项检查后端 DTO/API、管理端模板/表格/导出、小程序模板/文案,以及数据库实体和迁移。清单中的每个公开 ID 必须映射到本设计的编号类型;任何新增前缀或需要改变 API 路由参数的情况应先更新本设计并取得确认。