Files
im_server/docs/IM-需求实现情况审核报告.md
T

24 KiB
Raw Blame History

IM 产品需求实现情况审核报告

审核日期:2026-08-17 审核对象:当前仓库代码、数据库脚本及运行配置 主要依据:IM-产品原型需求文档.md、IM-前后端对接文档.md 多租户依据:IM-独立库多租户改造方案.md 明确排除:已废弃的 IM-服务端多租户改造方案.md

1. 审核说明

本报告以代码和数据库脚本的实际状态为准,不直接沿用前后端对接文档中的“现状/目标”状态。对接文档中的状态是设计阶段快照,部分“新增”接口目前已经实现,部分已注册接口仍缺少业务闭环。

判定口径:

状态 含义
已实现 主流程、存储和必要权限校验已落地,可进入联调
部分实现 已有接口或数据模型,但缺少关键策略、通知、推送、事务或异常闭环
阻断缺陷 代码已存在,但当前实现会导致主流程失败、权限绕过或数据不一致
未实现 未找到对应路由、业务逻辑或持久化实现

本次为代码审核并辅以 Go 单元测试和真实 MySQL 适配器集成测试,不包含多节点 WebSocket、移动端、短信通道和真实 FCM 凭据的端到端联调。

2. 总体结论

当前版本已经不是初始 Tinode 的简单 topic 模型。好友关系、群业务扩展表、认证安全、收藏搜索、工作台、会议、日报月报、反馈举报等模块均已出现较完整的 HTTP 路由和存储接口,产品功能骨架已经形成。

首轮审核发现的 P0 和本报告第 4 节的 6 项 P1 已于 2026-08-17 完成代码修复。项目仍不应按“全部完成”交付,以下部署和 P2 闭环仍需处理:

  1. FCM 已接通产品 Token 表,但真实环境凭据和移动端联调仍待部署完成。
  2. 真实短信、多节点 WebSocket、通话竞态和后台处置工作流仍未闭环。
  3. 青少年模式、文件安全、群文件和会话设备管理等 P2 能力仍待开发。

2.1 分章完成度

章节 模块 当前判断 摘要
0 公共协议与基础约定 已实现主流程 统一响应、公共头、消息协议、Bearer 认证和全局幂等已落地
1 租户、认证与安全 部分实现 租户解析、验证码、密码重置、实名提交、安全挑战已实现;真实短信、会话管理等缺失
2 首页、会话与消息基础 部分实现 会话、回执、撤回、编辑、能力开关、实时事件和系统通知已落地;稳定游标等仍待增强
3 单聊与好友关系 部分实现 好友、黑名单、隐私策略、关系事件和通知已落地;历史文件/通话组合规则仍待验收
4 消息能力 部分实现 @、媒体、转发、收藏及协议类型兼容已有;@通知和贴纸等缺失
5 联系人与关系管理 部分实现 基础功能、全局幂等和实时事件已落地;审计和二维码风控仍需增强
6 群聊 P0 已修复,仍部分实现 初始化、邀请、申请、禁言、事务和 Outbox 已修复;群文件、解散等仍缺失
7 收藏、搜索与文件 部分实现 收藏、上下文、媒体搜索、文件 ACL/Range/ETag 已有;群文件、安全扫描等缺失
8 音视频通话 部分实现 Tinode 通话事件和记录已存在;离线呼叫、跨设备竞态、群通话等未闭环
9 工作台与办公协同 部分实现 工作台、公开租户编码、组织查询、会议通知与报表已实现;权限仍需增强
10 设置与设备 部分实现 资料、隐私及主要策略执行、青少年模式、版本、Push Token 已有;设备会话与青少年统一策略仍待增强
11 安全、举报与反馈 部分实现 URL 检查、挑战、举报和反馈提交已有;风险令牌消费、处置工作流和安全通知缺失

3. 发布阻断问题

修复状态更新(2026-08-17):本节列出的 7 项 P0 代码问题均已处理。FCM 代码链路已经接通,部署环境仍必须提供真实 Firebase 服务账号凭据。

P0-01 消息头协议与对接文档不一致(已修复)

对接文档约定消息头使用:

{
  "x-im-schema": 1,
  "x-im-type": "text"
}

修复前的校验在 server/store/store.go 中存在两处不兼容:

  • x-im-schema 被要求为字符串,文档示例中的数字 1 会被判为 malformed。
  • 消息类型主要校验 head["type"],而不是协议约定的 head["x-im-type"]。
  • 服务端允许的 type 值与文档的 voice、contact_card、forward_bundle、system_event 等枚举不一致。
  • server/topic.go:1050 仅通过 head["type"] == "system" 防止客户端伪造系统消息,无法覆盖 x-im-type=system_event。

修复结果:现已接受数字或字符串形式的 schema 1,以 x-im-type 为产品协议字段并兼容旧 type;增加类型别名兼容、双字段冲突校验和 system_event 防伪测试。

P0-02 群业务表未按租户业务库自动初始化(已修复)

修复前群表脚本存在以下问题:

  • SQL 在第 7 行硬编码 CREATE DATABASE tinode,所有表也写死在 tinode.im_group_*。
  • scripts/check_group_business_tables.go:44 写死 TABLE_SCHEMA='tinode'。
  • server/db/mysql/adapter.go 的业务库创建流程没有创建这些群业务表。

修复结果:12 张群表已进入 MySQL 统一初始化;服务启动和首次打开独立租户库时会执行幂等建表;SQL 与检查脚本改为使用 DSN 当前选中的租户库,不再硬编码 tinode。

P0-03 群邀请会把非成员误判为已入群(已修复)

原逻辑只判断 store.Subs.Get(...) 的 err == nil,因此会把 (nil, nil) 的非成员判为已入群。

修复结果:邀请改为 MySQL 原子操作,在事务内判断有效 Subscription、恢复删除订阅、写邀请和成员记录、更新人数并写 Outbox;已补充非成员邀请回归测试。

P0-04 入群申请主流程和状态一致性有问题(已修复)

原入群申请入口复用了 requireIMGroupMember,群外用户无法提交申请;审批状态和成员写入也不在同一事务。

修复结果:POST 入群申请只校验登录用户、群状态及当前非成员状态;审批在一个事务内锁定申请,先完成 Subscription/成员写入,再更新申请状态和 Outbox,任何一步失败都会回滚。

P0-05 群禁言未接入消息发布权限(已修复)

原 WebSocket 发布路径没有查询成员禁言和全员禁言状态。

修复结果:消息持久化前调用群发言策略,覆盖成员禁言、全员禁言、禁言过期、管理员豁免和 Root 系统消息;已补充被禁言成员发布返回 403 的测试。

P0-06 产品 Push Token 与 FCM 数据源断开(代码已修复)

  • 产品 Push Token 接口写入 im_device_push_tokens,原 FCM 只读取旧 im_devices。
  • 仓库默认配置没有内置 Firebase 凭据。

修复结果:FCM 现优先读取产品 Token 表,并保留旧设备表回退;支持通过 IM_FCM_CREDENTIALS_FILE 或 IM_FCM_CREDENTIALS_JSON 注入凭据并自动启用。真实 Android/iOS 推送仍需部署方提供有效凭据完成联调。

P0-07 群写操作缺少事务和可靠事件机制(已修复)

原建群、成员变更、审批、退群、角色变更和群主转让分别修改 Topic、Subscription 与群扩展表,并存在忽略错误的情况。

修复结果:上述关键写操作已收口到租户 MySQL 事务,角色 ACL 与业务角色同步更新;同一事务写入 im_group_events_outbox,提交后通过 Hub 向在线 Topic 派发,派发失败保留 pending 状态并在后续群请求重试。其余双写路径不再忽略错误,并提供回滚补偿。

4. 跨模块公共问题

修复状态更新(2026-08-17):本节 6 项 P1 代码问题均已处理。

P1-01 HTTP 公共请求头未统一执行(已修复)

对接文档要求产品 HTTP 请求携带 X-Tinode-APIKey、X-IM-Schema 和 X-Request-ID。修复前各 Handler 主要在 authenticateIMHTTPBearer 中校验 Bearer Token:

  • /v1/im 认证接口未统一校验 API Key。
  • 未找到统一的 HTTP X-IM-Schema 版本校验。
  • X-Request-ID 仅回显,缺失时不会拒绝或生成服务端 Request ID。

修复结果:/v1/im/ 已统一经过协议中间件,强制校验 Header 中的 X-Tinode-APIKey 和 X-IM-Schema: 1;X-Request-ID 缺失时服务端生成并在响应中回传。

P1-02 幂等只检查 Key 是否存在,没有实现幂等语义(已修复)

修复前 requireIMIdempotencyKey 主要检查请求头非空,没有统一持久化以下信息:

  • tenant + uid + method + route + idempotency_key
  • 请求体哈希
  • 首次响应状态码和响应体

修复结果:新增租户库 im_http_idempotency 表和统一中间件,按用户、方法、路由和 Key 建立唯一作用域,持久化 Query/Body 哈希及首次状态码/响应体;支持完整响应重放、同 Key 不同请求冲突和处理中冲突。

P1-03 HTTP 写操作缺少在线事件与 Outbox(已修复)

修复前,消息编辑/撤回、好友申请/通过/删除/拉黑、群资料与成员变更等 HTTP 操作大多只修改数据库并返回 HTTP 响应,没有统一广播到在线会话,也没有可靠 Outbox 供重试。

修复结果:新增 im_business_events_outbox,通过 Hub 向 Topic 或用户其他设备发布 im 事件,队列满或 Hub 不可用时保留 pending 以便重试。已覆盖消息编辑/撤回、好友关系、群业务、会议和安全事件;消息、好友申请/审批、群与会议的关键写路径在业务事务内写 Outbox,其他可重复关系写由全局幂等机制保证失败后可补写。

P1-04 系统通知只有查询能力,缺少业务生产者(已修复)

修复前,系统通知表、列表和已读接口已经存在,但好友、安全、群聊、会议等模块没有完整生产链路。

修复结果:好友申请/处理/删除、群成员与群设置、会议变更/提醒/回应和安全确认均已生产用户系统通知,通知 event_id 可重复执行且不会重复入箱。

P1-05 隐私配置已存储但未全面执行(已修复)

修复前,资料可见性、加好友方式、最后在线时间、已读回执等配置已经有表和接口,但主要读写路径没有执行这些策略。

修复结果:搜索与好友申请已执行 add_me_methods,用户资料执行 profile_visibility,HTTP 回执列表执行 read_receipts,Tinode P2P get.desc/get.sub 输出执行 last_seen_visibility;非法隐私枚举也会在存储入口被拒绝。

P1-06 返回了内部租户 ID(已修复)

修复前工作台数据把数字 TenantID 格式化后放入 tenant_code 返回。对接约定要求客户端只使用公开租户编码,不感知内部 tenant_id。

修复结果:工作台会根据当前 TenantID 查询租户注册表,tenant_code 仅返回公开 code,不再暴露内部数字 ID。

5. 按需求章节审核

第 1 章:租户、认证与安全

已实现

  • 租户解析、状态检查和 WebSocket hi 阶段租户绑定。
  • Basic/Token 登录和 Token 中的租户、auth_version 校验。
  • 注册验证码创建/校验、注册前验证消费、密码重置。
  • 独立密码设置与验证、安全挑战、实名提交与状态查询。
  • 用户安全状态变化后的在线 Session 驱逐能力。

问题与缺失

  • 验证码目前主要完成生成、哈希和记录,未接入可验证的真实短信发送通道。
  • 限流以租户、场景、手机号和重发窗口为主,缺少 IP、设备、账号等组合风控。
  • 未找到完整的登录失败次数、账号临时锁定和解锁闭环。
  • 实名认证只有用户提交和状态查询,缺少审核/第三方认证结果回写流程。
  • 缺少 Refresh Token、登录设备列表、单设备下线、全部设备下线等会话管理 API。
  • 缺少 API Key 轮换、吊销和灰度兼容机制。

第 2 章:首页、会话与消息基础

已实现

  • Tinode me/sub/pres 会话基础能力。
  • Bootstrap、会话搜索、未读/已读回执、消息撤回和编辑接口。
  • 系统通知列表、未读数和已读接口。
  • 撤回/编辑能力开关、事务内 Outbox 和在线事件已开启。
  • 好友、群、会议和安全模块可向系统通知箱生产通知。

问题与缺失

  • 回执游标依赖当前成员集合和整数偏移,成员变化后不属于稳定游标。

第 3 章:单聊与好友关系

已实现

  • 好友申请、申请列表、同意、拒绝、好友列表和删除。
  • 好友备注、黑名单、关系上下文和用户资料查询。
  • WebSocket P2P 发消息前调用 CanSendP2P,可阻止非好友或拉黑关系发送。
  • 单聊消息、回执、文件上传和历史消息基础能力。
  • 好友申请、处理、删除、拉黑和备注会生成可重试关系事件,需要提醒对端的操作同时生成系统通知。
  • 搜索、好友申请、资料、已读回执和最后在线时间已执行隐私设置。

问题与缺失

  • 删除好友或拉黑后的历史消息、文件下载、通话权限缺少统一规则和验收测试。

第 4 章:消息能力

已实现

  • @成员和 @all 解析,@all 有管理员权限限制。
  • 文本、媒体、文件等基础消息与附件上传。
  • 消息转发、收藏和历史上下文查询。
  • 通话消息会写入 x-im-type=call。

问题与缺失

  • @消息没有形成专门通知、Push 优先级和频控策略。
  • 未找到贴纸包/表情商店相关数据模型与接口。
  • 媒体上传进度、失败恢复主要依赖客户端,服务端缺少分片/断点上传状态机。
  • 消息 client_mid 的幂等写入和 topic seq 增长不是完整事务,并发重复请求可能产生序号空洞或冲突错误。

第 5 章:联系人和关系管理

已实现

  • 用户搜索、好友、申请、黑名单、关系上下文等核心接口已经注册。
  • 关系表和 P2P 发送权限已纳入 MySQL 租户业务存储。
  • 关系写操作已纳入全局幂等、系统通知和实时事件链路。

问题与缺失

  • 手机号/通讯录匹配的授权、脱敏和隐私规则未形成完整闭环。
  • 关系独立审计记录仍需补充。
  • 二维码关系入口主要依赖签名令牌,缺少服务端可吊销记录、使用次数和风险控制。

第 6 章:群聊

已实现

  • 群创建、资料、成员、成员资料、邀请、入群申请、公告、角色、转让群主、退群、禁言、二维码等路由已增加。
  • 已持久化群设置、群成员、邀请、入群申请、公告、公告已读和禁言数据。
  • docs/IM-群聊业务表设计.sql 设计了 12 张群业务扩展表。

已修复的阻断项与剩余缺失

  • 群业务表自动初始化已修复,见 P0-02。
  • 群邀请误判非成员已修复,见 P0-03。
  • 群外申请和审批一致性已修复,见 P0-04。
  • WebSocket 禁言校验已修复,见 P0-05。
  • 建群、成员、角色和群主变更事务及 Outbox 已落地,见 P0-07。
  • im_group_qrcodes、im_group_files、im_group_admin_logs 目前仍主要是表设计;im_group_idempotency 和 im_group_events_outbox 已有生产代码。
  • 未找到群解散接口和完整状态清理流程。
  • 未找到群文件列表、分类、搜索和文件消息自动索引能力。
  • 群二维码主要使用 HMAC Token,没有持久化,无法单码吊销、限制使用次数或查看使用记录。
  • 群公告、成员、角色、禁言等变更已接入 Outbox 与系统通知,真实多端与离线 Push 仍需联调验收。

第 7 章:收藏、搜索与文件

已实现

  • 收藏新增、列表、详情、删除和转发。
  • 消息搜索、上下文定位和媒体消息筛选。
  • 文件资源访问会校验用户权限,响应支持 ETag;本地存储通过 ServeContent 支持 Range,S3 支持预签名 URL。

问题与缺失

  • 未接入病毒扫描、恶意文件识别、图片/视频内容安全和隔离状态。
  • 群文件索引表没有写入及查询实现。
  • 搜索和列表游标的稳定性、权限快照和数据删除后的结果一致性需要专项测试。
  • 文件下载审计、敏感文件水印和生命周期清理未实现。

第 8 章:音视频通话

已实现

  • Tinode 通话邀请、接听、挂断等实时事件基础能力。
  • 通话记录创建、接听、结束和列表接口。
  • P2P 消息入口的好友关系校验可覆盖在线通话邀请的基础关系限制。

问题与缺失

  • FCM 代码已使用产品 Token 数据源,但离线来电仍需真实凭据和移动端联调验收。
  • 多设备同时接听缺少服务端唯一接听者仲裁和状态序列控制。
  • 通话状态写入、实时事件和 Push 之间没有幂等/Outbox 保证。
  • 未实现通话质量指标、失败原因标准化和质量上报。
  • 未找到群语音/群视频通话的完整参与者状态模型。
  • 好友、黑名单、青少年模式等策略没有通过统一服务覆盖所有通话入口。

第 9 章:工作台与办公协同

已实现

  • 工作台聚合接口、组织树和成员搜索。
  • 会议创建、修改、取消、提醒、参会响应和查询。
  • 会议变更与参会响应在同一事务内写入 Outbox 和系统通知。
  • 工作台 tenant_code 返回注册表的公开租户编码。
  • 日报/月报草稿、提交、列表、统计和提醒。
  • 邮箱配置查询和问题提交。

问题与缺失

  • 工作台功能项与权限没有完全由服务端动态下发和裁剪。
  • 组织、会议和报表的数据范围/角色权限需要更严格的统一校验和跨租户测试。
  • 会议提醒已有实时事件和系统通知;报表审批/提交结果、角标和真实 Push 仍需闭环。
  • 邮箱提交更接近收件记录,缺少分派、处理、回复、关闭等工作流。

第 10 章:设置、隐私与设备

已实现

  • 个人资料读写、隐私设置读写。
  • 加好友方式、资料可见性、最后在线时间和已读回执已在主要业务入口执行。
  • 青少年模式启用、关闭和查询。
  • 最新版本查询和设备 Push Token 注册接口。

问题与缺失

  • GET /me 的实名状态和青少年模式字段存在硬编码默认值,与独立查询接口的数据可能不一致。
  • 缺少登录设备/会话列表、设备改名、单设备退出、全端退出等完整设备管理。
  • 青少年模式目前以设置存储为主,夜间限制、内容过滤、通话/加好友限制没有统一策略执行层。
  • Push Token 注册与 FCM 发送数据源已统一,真实 Firebase 凭据和移动端仍待联调。
  • 版本接口缺少灰度发布、渠道、强更分组及回滚策略。

第 11 章:安全、举报与反馈

已实现

  • URL 安全检查和基础规则判定。
  • 风险挑战继续/取消流程及风险动作令牌签发。
  • 举报原因列表、举报提交、反馈配置和反馈提交。

问题与缺失

  • risk_action_token 签发后,未找到原始高风险业务操作对该令牌进行统一消费和一次性校验的链路。
  • URL 检查主要是基础规则,缺少信誉库、重定向链分析和异步复检。
  • 举报和反馈以接收为主,缺少审核、分派、处置、申诉、回复和 SLA 状态流转。
  • 风险确认已写入用户可见的系统安全通知,其他安全操作仍需按场景补齐。
  • 举报证据文件没有明确接入专门 ACL、安全扫描和保留/删除策略。

6. 数据库与迁移审核

已具备

  • 核心 Tinode 表已统一使用 im_ 前缀。
  • 好友关系、认证安全、隐私、收藏、通知、会议、报表等业务表已在 MySQL 适配器中出现对应存储实现。
  • 群业务从 Topic/Subscription 扩展为独立业务表,方向符合复杂群管理需求。
  • im_http_idempotency 和 im_business_events_outbox 已纳入应用自动建表与数据库变更汇总脚本。

需要修正

  1. 建立唯一 schema 版本和迁移入口,禁止“应用启动建部分表 + 手工 SQL 建另一部分表”长期并存。
  2. 群业务 SQL 必须参数化目标租户库,禁止硬编码 tinode。
  3. 新租户建库和存量租户升级必须执行同一套 migration。
  4. 为 Topic、Subscription、群业务表之间的复合写操作提供事务边界。
  5. 对已设计但未使用的群表明确去留,避免表结构被误认为功能已经完成。
  6. 补充索引、唯一键和外键/逻辑引用的一致性检查,尤其是邀请、申请、成员和幂等键。

7. 测试与验证结果

本次执行

go test -tags mysql ./server/db/mysql ./server/store ./server/push/fcm ./server -count=1

结果:全部通过。覆盖 HTTP 协议头、幂等响应重放/冲突、消息协议、隐私策略、群业务、FCM Token 数据源和 MySQL 建表语句。

go test -tags mysql ./server/db/mysql/tests -count=1

结果:使用 root/root@127.0.0.1:3306 和临时数据库完整通过;包含租户库创建、群表、P1 基础设施表、无 tenant_id 约束和多租户隔离测试。测试后已恢复 test.conf 并删除临时数据库。

测试缺口

  • 缺少 HTTP 写入后 WebSocket 多端同步的集成测试。
  • 缺少真实 FCM 凭据和移动端设备的离线推送测试。
  • 隐私策略的基础分支已有测试,但黑名单、青少年模式、文件和通话的组合权限仍缺专项矩阵。
  • 幂等重放和同 Key 不同 Body 已有单测,多进程高并发压测仍未执行。

8. 文档一致性问题

  1. IM-服务端多租户改造方案.md 已明确废弃,本报告未把它作为实现依据。
  2. IM-系统设计文档.md 中仍有共享业务库加 tenant_id 的描述,与当前独立租户业务库方向不一致,需要更新或标记历史版本。
  3. IM-前后端对接文档.md 的接口状态是设计阶段快照,已有多项“新增”路由落地,应按本报告和实际联调结果刷新。
  4. IM-未实现后续增强项.md 已于 2026-08-17 按最新 P0/P1 修复状态同步:已完成项已移入各章基线,待办表仅保留未实现或待环境联调的增强项。
  5. 群表设计文档与独立库多租户方案冲突,脚本中的 tinode 库名必须移除。

9. 建议开发顺序

第一阶段:解除主流程阻断(已完成)

  1. 统一消息协议字段、类型枚举和兼容策略。
  2. 把群表纳入租户库 migration,并完成存量租户升级。
  3. 修复群邀请、群外申请、审批一致性和禁言绕过。
  4. 为建群、成员变更、群主转让建立事务和明确错误处理。
  5. 统一 Push Token 数据源并启用 FCM 测试环境。

第二阶段:完成生产闭环(P1 代码已完成)

  1. 建立统一 HTTP Middleware:API Key、Schema、Request ID、Bearer、限流。
  2. 建立统一幂等存储和响应重放机制。
  3. 落地 Outbox,补齐关系、群、消息编辑/撤回、会议等实时事件。
  4. 建立系统通知生产服务,并与 Push、角标联动。
  5. 建立统一隐私/关系/青少年模式 Policy Service。

第三阶段:补齐增强能力

  1. 群文件、群解散、二维码管理、管理员日志。
  2. 多设备会话管理、Refresh Token、API Key 生命周期。
  3. 通话多设备仲裁、质量指标及群通话。
  4. 举报、反馈、实名和邮箱的后台处置工作流。
  5. 文件安全扫描、版本灰度和运营配置能力。

10. 建议验收门槛

在声明产品需求“已完成”前,至少满足:

  • 新建租户无需手工 SQL 即可完成全部模块初始化。
  • 文档示例消息可直接发送、存储、搜索、转发并被旧客户端兼容处理。
  • 所有写接口具备可验证的幂等语义。
  • HTTP 状态变更能可靠同步到 WebSocket 在线端,并能通过 Outbox 重试。
  • FCM 使用产品注册的 Token 完成真实离线推送。
  • 群邀请、申请、禁言、退群、转让和解散通过真实 MySQL 集成测试。
  • 好友、黑名单、隐私、青少年模式在消息、文件、资料、通话入口保持一致。
  • go test ./... 能完整编译并通过;关键链路另有端到端测试。