Skip to content

Nexo — 2026-09-13 迭代需求文档 ​

范围:承接 2026-08-30 迭代,将用户主数据与认证体系合并收敛为单一应用(nexo-account,统一账号与认证中心)。遵循奥卡姆剃刀与真原子化设计原则,彻底剔除“拆而不分”的分布式单体硬伤、跨库分布式事务与 Outbox 队列、全量数据推送、假权限与管理员判定等过度设计,专注落地统一账号与认证中心、轻量管理员开户(24h 设密链接 / 内部随机初始密码)、管理员用户管理控制台(Web UI)、IM 按需拉取与停用轻量通知断连、三态生命周期(待激活/正常/停用,单表单一事实源)与极简重新启用模型。 验收标准见第 10 节,本文档定义"做什么"与"为什么";"怎么做"以同目录技术方案(design.md)为准。

1. 背景与目标 ​

在既往迭代中:

  • 2026-08-16 单聊跑通:IM 地基建立,但用户账号直接耦合在 nexo-im-api 内部;
  • 2026-08-23 认证中心与桌面壳:成功将令牌签发与会话管理剥离为 nexo-auth,但各业务系统(IM、桌面壳)仍缺乏统一人员档案与维护入口;
  • 2026-08-30 多端能力补齐:完成端侧密码加密与多端会话同步,但 IM 内部仍保留了历史旧注册接口与 5 分钟全量轮询。

Nexo 的形态是统一数字工作台,除 IM 外,后续还将挂载任务平台、发布平台等独立应用。各子系统绝不能各自维护一套用户表,更不能反向依赖 IM 检索人员。

在此前探索中,曾设想将系统物理拆分为独立的 nexo-user(用户主数据)与 nexo-auth(凭据认证)两个微服务。但在单机 Docker Compose 且缺乏分布式事务基础设施(2PC/Saga/Outbox)的现实下,强行拆分暴露出致命的**“伪原子化”硬伤**:

  1. 服务拆而不分:建号、激活、停用在两个服务间强耦合,任何一方网络抖动都会导致系统处于半入库脏数据状态;
  2. 数据事实源分裂:账号状态 status 在两张表双写,缺乏跨库事务,必然导致状态脑裂;
  3. 操作缺乏 ACID 保证:多步跨网络调用无法原子回滚;
  4. 胶水代码冗余:为两个服务编写大量内部 RPC 与双向 HMAC 校验代码,严重增加维护负担。

因此,本迭代核心目标是:遵循第一性原理彻底收敛,将用户主数据与认证体系合并为单一服务 nexo-account,实现单库单事务真原子化,落地轻量开户与管理控制台,完成 IM 登录注册剥离与按需拉取闭环。

本期确立 10 项真原子化架构原则:

  1. 单服务单库真原子收敛:统一为 nexo-account(端口 3001),维护单数据库 nexo_account,消灭所有跨服务分布式事务与双写胶水代码;
  2. 状态单一事实源:status(PENDING/ACTIVE/DISABLED)全局仅在 users 表维护一份,彻底消除脑裂分叉;
  3. 全生命周期单事务原子化:建号、激活、停用、超时处理 100% 在本地单数据库事务内完成;
  4. 取消跨服务全量推送:IM 不再接收全量资料推送,仅在产生数据关联(如开启会话、查看成员、检索人员)时按需拉取并短时缓存;
  5. 账号停用仅推送状态通知:停用时仅向下游 IM 发送 { userId, status: 'DISABLED', disabledAt },0 个人资料传输,IM 收到后毫秒掐断长连接;
  6. 权限平台未上线前不进行鉴权:不写假管理员白名单(无 ADMIN_USERNAMES,无 requireAdmin),只要携带合法 Bearer JWT 即可调用管理接口;
  7. 物理分表实现 Zero-Knowledge:users(档案)与 credentials(密码哈希)物理分表,系统内部随机生成初始密码,员工打开 24h 链接自主改密;
  8. 建号即创建用户,超时未激活单条 SQL 停用:开户落库 PENDING 状态,24 小时未激活单条原子 SQL 自动转为 DISABLED;
  9. 彻底清除 HR 词汇:彻底去除“岗位”、“工号”、“职位”、“在职”、“离职”、“复职”,状态仅保留 PENDING(待激活)、ACTIVE(正常)、DISABLED(停用);
  10. 移除无外部通道支撑的死字段:彻底移除 email(无 SMTP)与 phone(无 SMS),仅保留核心档案。

2. 承接与已知欠账(承接 2026-08-30 验收) ​

欠账项处理排期Owner
IM 依然残留旧有的本地 /register 与旧密码校验端点本期交付(彻底注销路由,历史代码四项归零)2026-09-13待认领
IM 内部 user_profiles 采用 5 分钟轮询与 24h 定时刷新本期交付(移除轮询器,改造为产生关联时按需拉取 + 5分钟短时缓存)2026-09-13待认领
账号停用后在线长连接无法毫秒级掐断本期交付(停用轻量状态通知 + WebSocket 4001 毫秒强制断连)2026-09-13待认领
密码零接触安全规范(Zero-Knowledge 原则)本期交付(物理分表隔离密码;内部随机初始密码 + 24h 激活链接由员工自主设密)2026-09-13待认领

3. 功能需求 ​

3.1 单应用架构与真原子数据模型 ​

FR-1 统一账号与认证中心 nexo-account(单应用单库架构)

  • 将人员主数据与认证逻辑统一收敛在 nexo-account 单一服务中(端口 3001);
  • 采用 Node.js (Hono) + PostgreSQL 16 架构,统一维护 nexo_account 单一数据库;
  • 库内维护 users(用户档案)、credentials(凭据分表)与 account_tickets(单次激活/重置凭据表);
  • 彻底消灭微服务间分布式事务、出件箱(Outbox)表及异步轮询补偿 Worker。

FR-2 极简单一用户模型(单一事实源,7 核心字段)

  • 单表收敛:users 表维护全局唯一的员工档案与生命周期状态:
    • id(UUID,主键)
    • username(登录名,唯一且不可变)
    • real_name(真实姓名,必填)
    • nickname(昵称,选填)
    • avatar_url(头像地址,选填)
    • status(状态:PENDING / ACTIVE / DISABLED,全局唯一状态事实源)
    • created_at、updated_at(时间戳)
  • 字段极简红线:严禁引入 email、phone、version、工号、职位、岗位等冗余字段;
  • 状态三态收敛:
    • PENDING(待激活):建号后的初始状态,等待员工设置新密码;
    • ACTIVE(正常):已完成设密激活,可正常登录与通讯;
    • DISABLED(停用):账号被禁用,长连接被掐断,禁止登录与 API 访问。

FR-3 密码物理分表安全隔离(Zero-Knowledge 原则)

  • 单独维护 credentials 表存储密码哈希(user_id PK FK, password_hash, updated_at);
  • 业务查询用户档案(如姓名、昵称、头像)绝不涉及密码表,从物理表层面隔离敏感凭据;
  • credentials 表不设冗余 status 字段,避免双写与脑裂。

FR-4 账号停用与重新启用

  • 管理员在控制台停用账号时,系统在本地单事务内将 users.status = 'DISABLED',同时吊销其全部活跃 Session;
  • 事务提交后,向 IM 发送轻量通知 { userId, status: 'DISABLED', disabledAt }(disabledAt 为认证中心时钟的停用时刻,ISO 8601 UTC),IM 毫秒强掐客户端长连接;
  • 重新启用时,管理员在控制台点击【重新启用】,单事务将 users.status 重置为 ACTIVE;
  • 全流程无“在职/离职/复职”等 HR 术语,统一使用“待激活”、“正常”、“停用”。

3.2 轻量开户体系 ​

FR-5 原生原子开户建号与 24h 激活设密(Zero-Knowledge 原则)

  • 管理员主动录入:
    • 管理员在 Web 控制台录入新成员基础信息:用户名(username)、真实姓名(real_name),昵称(nickname)选填;
    • 免外部审批流,以控制台录入为主凭据;
  • 原生单事务写入:
    • 系统内部通过 CSPRNG 随机生成 32 位初始密码并计算 scrypt 哈希;
    • 系统生成 32 字节高熵随机激活码并计算 SHA-256 哈希(24h 有效期);
    • 在单个本地 PostgreSQL 事务内同时写入:
      1. users(状态为 PENDING)
      2. credentials(存入随机初始密码哈希)
      3. account_tickets(存入 24h 激活凭据)
    • 任意一步失败全量原子回滚,杜绝半入库脏数据;
    • 控制台返回专属激活链接(https://<auth-domain>/activate?code=xxx),支持一键复制私发员工;
    • 管理员全程不生成、不查看、不输入任何明文密码;
  • 员工自主激活与改密:
    • 员工打开激活链接,系统核验 Ticket 有效后渲染改密页面(展示其用户名);
    • 员工输入新密码并提交,系统在单个本地事务内:
      1. 单次核销 Ticket(记录 used_at 防止重放);
      2. 更新 credentials.password_hash 为新密码哈希;
      3. 更新 users.status = 'ACTIVE'。
    • 设密成功后直接引导至登录页;
  • 超时自动停用:
    • 若自建号起超过 24 小时员工未完成激活,单条 SQL 自动转为 DISABLED;
    • 控制台提供【重新生成激活链接】操作,点击后单事务重置状态为 PENDING 并生成新链接。

3.3 管理控制台 Web UI ​

FR-6 用户管理控制台界面与用户列表

  • 管理控制台提供「用户管理」中心界面:
    • 人员数据表格:展示列包含:【姓名】、【用户名】、【昵称】、【状态】、【创建时间】、【操作】;
    • 统一用户列表视图:直观展示企业全体成员(待激活、正常、停用);
  • 提供关键字模糊搜索(支持姓名、用户名、昵称检索),提供状态下拉筛选(待激活、正常、停用);
  • 操作列动作:资料编辑、重新生成激活链接(或重置密码链接)、停用账号、重新启用。

FR-7 批量导入与 Dry-Run 预检

  • 支持标准 CSV 模板下载与批量导入;模板仅需两列:username、real_name(nickname 选填);
  • 两阶段导入(Dry-Run):
    1. 预检校验:文件上传后先进行格式合规性检查(必填项、用户名唯一性、文件内重复校验),返回校验报告,对错误行红字高亮;
    2. 确认入库:校验通过后一键提交,采用单数据库事务完成全量写入,整批生成初始凭据与激活链接;
    3. 一键导出:批量创建成功后,支持一键下载导出包含全员激活链接的 CSV 文件供分发;
  • 出现未捕获异常整批全量回滚,不产生半入库脏数据。

FR-8 停用账号与防误触安全弹窗

  • 在人员操作列点击「停用账号」时,弹出高风险确认模态框;
  • 防误触安全设计:
    1. 高危警示区:红字提示「停用后将即刻掐断该用户所有客户端长连接,并在全网吊销其 Token 与登录凭证」;
    2. 强制全名二次核验:必须在输入框中完整、准确输入该用户的真实姓名全称,确认按钮方可点亮;
  • 确认提交后,单事务更新状态为 DISABLED 并吊销 Session,向 IM 触发停用通知。

FR-9 凭据重置与激活链接管理

  • 管理员在操作列可对指定员工发起凭证重置:
    • 若账号处于 PENDING(待激活),提供【重新生成激活链接】功能,作废旧链接并生成新 24h 链接;
    • 若账号处于 ACTIVE(正常),提供【发起密码重置】功能,生成 60 分钟短效设密链接;
  • 链接支持一键快速复制至剪贴板,便于管理员私发交付。

3.4 下游业务联动与鉴权放行 ​

FR-10 IM 按需拉取与停用切断

  • nexo-im-api 彻底废弃旧有 5 分钟全量轮询与 24 小时刷新机制;
  • 按需拉取与短时缓存:
    • 当发生数据关联时(如开启会话、查看群成员、通讯录检索),IM 服务在内存中维护轻量 LRU 缓存(TTL 5分钟);
    • 若本地缓存未命中,调用 nexo-account 的内部查询接口 GET /internal/users?ids=...(HMAC 认证)批量获取基础公开资料并写入缓存;
  • 停用状态轻量通知:
    • 账号停用时,nexo-account 仅向 IM 发送轻量通知:POST /internal/users/{userId}/disabled,Payload 为 { userId, status: 'DISABLED', disabledAt }(disabledAt 必填,为认证中心时钟的停用时刻,ISO 8601 UTC,供 IM 做只前进不后退的幂等判定),不传输姓名、头像等冗余资料;
    • IM 收到通知后立即清理本地缓存,并在 150ms 内执行 closeUser(userId, 4001, '账号已停用') 强掐该用户全部在线 WebSocket 连接,客户端收到 4001 码后退回登录页并禁用重连。

FR-11 管理端点免鉴权放行(合法 JWT 放行)

  • 在外部独立权限平台(#58)上线之前,严禁引入任何硬编码管理员名单或伪鉴权逻辑(无 ADMIN_USERNAMES,无 requireAdmin);
  • 管理 REST 接口只要校验请求头携带合法有效 Bearer JWT 即可放行;
  • 鉴权与数据范围判定未来 100% 由外部独立权限平台接管,保持系统架构纯洁。

4. 历史债务清理与缺陷修复 ​

#涉及系统现状与缺陷正确行为
DEBT-1nexo-im-api仍保留本地 /register 与带密码的旧登录路由彻底删除本地注册路由与控制器,移除旧密码表字段
DEBT-2nexo-im-api通讯录依赖 5 分钟全量轮询与 24 小时定时刷新移除定时轮询器,改为发生数据关联时按需拉取并本地短时缓存
BUG-1nexo-im-api账号停用后未被及时踢掉 WebSocket,仍能收发消息收到停用通知后 150ms 内强制关闭全端连接(closeUser(4001))
BUG-2nexo-account跨服务拆分导致开户与改密缺乏原子性,存在半状态收敛为单库单服务,本地 ACID 事务保障天然原子
BUG-3nexo-account既有账号体系缺乏账号停用状态支持扩充 status 字段,三态化表达账号全生命周期

5. 核心技术方案对齐 ​

以下五项在技术方案(design.md)中已完成极简设计与收敛:

  1. 单服务单库真原子架构方案 —— nexo-account 单库本地单事务(ACID)搞定建号、激活、停用,彻底根除分布式伪原子陷阱;
  2. 内部随机初始密码与 24h 激活链接协议 —— 单次 Ticket 核销机制,单事务原子改密与状态激活;
  3. IM 按需拉取与停用切断 —— 本地 5 分钟 LRU 缓存 + POST /internal/users/{id}/disabled 轻量状态通知 + 150ms closeUser(4001) 强掐;
  4. 访问令牌短效收口与 Session 吊销广播 —— Access Token 有效期缩短至 180 秒,Session 吊销广播至资源服务本地内存黑名单;
  5. 免伪鉴权放行原则 —— 权限平台就绪前不写假权限代码,合法 Bearer JWT 即放行。

6. 待评审收口 ​

#待定项倾向不定会怎样
1是否同意收敛为单一服务 nexo-account倾向完全同意彻底消灭伪原子化与跨库事务,实现原生 ACID 强一致
2是否同意取消向 IM 全量推送,改为按需拉取倾向完全同意消除无意义的广播开销,仅停用时通知状态
3是否同意权限平台上线前不进行鉴权倾向完全同意杜绝硬编码假管理员白名单,保持系统架构纯洁
424h 激活链接有效时长倾向设定为 24 小时超时自动停用,后台支持重新生成激活链接
5批量导入单次支持的最大行数倾向限制为 500 行单机单事务控制在毫秒级完成
6访问令牌(Access Token)有效时长倾向设定为 180 秒(3 分钟)构筑无状态吊销兜底上限
7激活链接分发方式倾向控制台复制直达链接私发当前无企业 SMTP 邮件中继,手工分发最务实可靠

7. 候补(登记,本期不做) ​

  • 画像标签系统与规则引擎:本期不建标签表、不打标签,未来根据业务明确诉求再行规划;
  • 外部开放注册审批流:外部审批平台与开放门户就绪后再行规划接入;
  • 细粒度 RBAC 角色授权:等待权限平台(#58)就绪后统一接入。

8. 明确不做(Out of Scope) ​

  • 多服务物理强行拆分与跨库分布式事务 —— 5 人团队坚决不做伪微服务,避免半状态灾难;
  • 重型消息队列中间件与出件箱 —— 单机 Docker 环境坚决不上 Kafka/RocketMQ,采用单事务写入 + 轻量内部调用;
  • 角色定义、组织部门树与管理员白名单 —— 属于权限平台管辖范围,当前不写假代码;
  • 邮箱(SMTP)与短信(SMS)通道 —— 无通道支撑,绝不保留 email / phone 摆设字段;
  • 移动端 Native 界面适配 —— 本期管理控制台聚焦于 PC Web 桌面分辨率。

9. 非功能需求 ​

  • 事务原子性:建号、激活、停用操作 ACID 原子性保证 100%,零半状态;
  • 按需拉取响应时效:IM 批量拉取公开资料响应耗时 P99 ≤ 50ms;
  • 停用阻断时效:管理员办理停用确认后,在线 WebSocket 连接强制掐断延迟 ≤ 150ms;接口级 401 阻断 ≤ 1ms;
  • 批量导入吞吐:500 人批量开户 Dry-Run 校验时间 ≤ 1s,正式入库事务耗时 ≤ 1s;
  • 安全性原则:
    • Zero-Knowledge:密码物理分表隔离,管理员零接触明文密码,初始密码内部随机生成,员工自主设密;
    • Fail-Closed:非法或伪造 Token 严格返回 401,已停用账号禁止签发 Token。

10. 验收标准 ​

验收标准覆盖以下 8 条端到端主路径:

  1. 管理员单人建号与生成激活链接:录入新成员用户名与姓名,系统单事务原子写入档案、随机凭据与 24h 激活链接,复制链接私发;
  2. 员工自助设密激活链路:访问激活链接直达 /activate 页面,输入新密码并提交,单事务原子核销 Ticket、更新密码与置状态为 ACTIVE;
  3. 超时未激活自动停用:超过 24 小时未激活的账号单条 SQL 自动转为 DISABLED;管理员可在后台点击【重新生成激活链接】单事务恢复 PENDING 并生成新链接;
  4. IM 产生关联时按需拉取资料:IM 客户端开启聊天或检索用户时,按需从 nexo-account 查询资料并缓存在本地,不依赖全量推送;
  5. 防误触停用账号:在控制台办理停用,未完全输入真实姓名全称时确认按钮禁用;输入全称确认后,单事务停用并吊销 Session;
  6. 账号停用即时断连:办理停用确认瞬间,该用户的 IM 桌面端收到 4001 码并退回登录页,后续 API 请求被 401 拦截;
  7. 重新启用账号无冲突:为已停用账号点击【重新启用】,状态恢复为 ACTIVE,登录与使用即刻恢复正常;
  8. 批量导入与导出链接:上传包含重复用户名的 CSV 表格,Dry-Run 准确在界面标红报错行;修正后成功单事务批量创建并一键导出全员激活链接 CSV。

11. 风险与降级 ​

风险降级预案
激活链接超过 24h 未使用账号自动变为 DISABLED 状态,管理员可在控制台针对该用户点击「重新生成激活链接」重新复制分发
停用误触风险必须输入员工真实姓名全称,后端全等校验阻断误操作
批量导入遇到未知格式导致解析异常前端限制文件大小(≤ 2MB)并限定 CSV;后端单事务原子回滚,不产生半入库脏数据
Token TTL 缩短带来的续期频率SDK 刷新阈值设为 60s,5 个用户平均每分钟仅产生 2~3 次轻量点查请求,无性能压力

12. 约束与说明 ​

  • 遵循 YYYY-MM-DD 验收会日期命名规范(2026-09-13);
  • 代码修改严禁直接推送到 dev 或 main 分支,统一在特性分支进行并通过 PR 合并;
  • 排期节奏:
    • 09-08(周二):PRD 定稿与技术方案评审;
    • 09-08 ~ 09-09(周二至周三):nexo-account 表结构扩充、单事务建号、24h 激活链接与 /activate 设密页、管理 REST API;
    • 09-09 ~ 09-10(周三至周四):停用通知与 IM closeUser(4001) 掐线、IM 废除轮询接入按需拉取、控制台 Web UI;
    • 09-11(周五):桌面壳 nexo-app 侧边栏挂载、全链路冒烟联调(建号 → 激活 → 登录 → IM 通讯 → 停用断连);
    • 09-12(周六):预跑 TC 验收用例与冒烟测试,产出离线核验证据;
    • 09-13(周日):召开验收会闭环交付。

13. 名词解释 ​

术语含义说明
统一账号与认证中心 (nexo-account)系统的企业人员档案、安全凭据与认证基础设施权威源
真原子化 (True Atomicity)核心生命周期流转(建号、激活、停用、超时)全部基于本地单数据库事务(ACID)完成,零跨网络半状态
单一事实源 (Single Source of Truth)status 仅在 users 表维护全局唯一字段,凭据表不再冗余状态,杜绝脑裂
待激活 (PENDING)账号已创建并生成激活码,员工尚未设置新密码的初始状态;超过 24 小时未激活自动转为停用
正常 (ACTIVE)账号已成功设置密码,可正常登录系统与收发消息
停用 (DISABLED)账号处于禁用状态,长连接被强制切断,禁止登录与 API 访问
按需拉取 (On-Demand Fetch)IM 服务仅在发生数据关联(如开启聊天、检索通讯录)时才向账号中心查询人员公开档案并短时缓存
closeUserIM 连接管理器的方法,接收到停用状态通知后毫秒掐断指定用户全部在线连接并返回 4001 码
Zero-Knowledge 设密管理员零接触明文密码,系统内部随机生成初始密码并通过有时效单次链接由员工自主设密