Files
kefu/deploy/my-customers-20260918/my-customers-audit.md
T
2026-09-21 10:34:06 +08:00

66 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 医疗助理“我的客户”数据源只读审计
时间:2026-09-18。审计目录 `C:/wechat_rpa` 及 `C:/Users/isard/AppData/Local/ZhenYangTangRPA` 已存在的解密缓存。已通过现有 `active_context → discover → NativeClient(write=False)` 只读核验当前企微账号;未发送消息、未重新解密、未打开原企微数据库、未修改产品文件。报告只含 schema 和聚合计数,不含客户姓名、手机号、客户 ID 或消息正文。
## 明确问题
当前医疗助理选择列表不是“企微通讯录→我的客户”:
- `review_assistant_contacts.py:224` 只从历史 `message_table` 选 `M:%` 会话。
- 第 196 行虽然读取 `external_user_relation_v3`,但只用于补充名字,不据此限定客户归属。
- 第 260 行追加所有 `wechat_contactV1` 微信通讯录条目,与企微客户关系没有必然对应。
- 第 21、305 行只允许 M:;当前缓存的两条企微关系联系人均为 S:,被整个漏掉。
- `review_assistant.py:95` 同样只接受 M: 医疗助理接收人配置。仅修改列表,S: 选择仍无法启用,需同步调整校验与相应用例。此处只报告,未修改。
## 当前账号实测
安装版采用当前账号目录内最新的 `archive_auto_backup/decrypted` user/session/message 缓存,修改时间约 09-18 10:16;源码目录缓存相对更旧,但关键客户关系计数一致。
| 数据 | 安装版最新缓存数量 | 说明 |
|---|---:|---|
| user.db / user_table | 172 | 包括当前企业员工,不能整体当客户 |
| user_table 与当前账号同 corp_id | 168 | 是用户缓存,不是“我的客户”成员表 |
| user.db / external_user_ids | 4 | 外部用户集合,含 2 条没有当前账号关系行 |
| user.db / external_user_relation_v3 | 2 | 两条均在 external_user_ids,且能 join user_table |
| user.db / wechat_contactV1 | 214 | 微信通讯录,不应作为我的客户主列表 |
| user.db / wx_friend | 0 | 当前没有显式 UID↔wx_id 映射,不能将214条微信通讯录直接转发送地址 |
| session.db / conversation_table | 96 | S:17,M:1,其余为其他会话类型 |
| message.db / message_table | 699 | 仅统计数量;未查询正文 |
| 关系联系人→已有S会话 | 2 | 两条都包含当前账号及唯一对端,且都有历史消息 |
| 关系联系人→M会话 | 0 | 旧M列表漏掉全部关系联系人 |
两条关系的 `status` 分别为 2049 和 2057,`stranger_type` 均为 0,`create_time/add_customer_time/remark_time` 均大于 0。两条均有 `user_table.name` 昵称;`real_remarks/remarks/corp_remark/recommend_remark` 均为空。删除关系表 `delete_external_userV1` 和黑名单表 `blacklist_external_userids` 当前均为 0。
## 哪张表应作为主源
应以**当前已核验账号目录里的 `user.db.external_user_relation_v3`**作为归属关系的主源,再以 `user_id = user_table.id` 取名字和身份。该表含 `status`、`stranger_type`、`add_customer_time`、客户来源、客户备注等与本账号关系相关字段;现有归档代码 `archive_auto_backup.py:830` 也用这张关系表限定 `wecom_external_local_uid`,不会把全体同事当外部联系人。
`external_user_ids`、全体 `user_table`、历史单聊集合、微信通讯录均不能独立证明“是当前账号我的客户”。实测 external_user_ids 比关系表多 2 条,正是不能直接并入的证据。
**边界:尚不能仅凭这份缓存证明与企微实时UI完全相同。** 客户关系 status 是组合标志,现有代码没有 2049/2057 的定义,实测样本也不足以推导每个位意义。不能猜测 `status==1`、`status!=0` 或某个位来断言关系当前仍有效。关系表可以提供明确归属候选,但若要求严格排除已删/待确认关系,需要有经过验证的状态定义或只读UI对照,不能用历史消息或姓名推断。
## ID、名称与可发送会话映射
1. 使用关系表的数值型 `user_id` 作为本地外部联系人 UID,作用域包含当前账号。它不等同于官方 API 的字符串 `external_userid`,不能互换。`user_table` 有 unionid 字段,但当前表结构没有明确官方 external_userid 字段;本轮没有解码不透明 protobuf 字段。
2. 展示名字优先读取 `real_remarks → remarks → user_table.name → user_table.real_name`;名称只用于展示和搜索,不作为身份、去重或发送地址。当前两条需要回落到昵称。
3. 从**已经存在**的 session/message 会话里匹配 S::格式 `S:<uid1>_<uid2>`,必须恰有一端等于当前账号、另一端等于关系 UID。当前两条均通过该映射,未发现歧义。保留数据库里的原始会话 ID,不自行猜拼接或依赖名字。
4. M: 只有在对端 UID 与关系 UID 有明确对应时才可候选;当前样本为 0。`wechat_contactV1.gene` 不能猜作 UID;`wx_friend` 当前为空,不具备214条微信通讯录到会话的可靠映射。
5. 客户归属与可发送性应分开:有关系但没有可核验会话的客户仍可展示为暂不可选,不应要求先出现消息才能成为“我的客户”;已映射会话也不能据此保证对端现在接受消息,发送前仍应保留当前账号校验与联系人限制检查。
`session.db` 还存在 `crm_customer_conversation_relation2`、`inner_customer_conversation_relation`、`outer_customer_conversation_relationV2`,当前均为空,不能作为当前列表来源。`user_extend.db` 仅同事备注、休假相关表,没有更完整的我的客户表。
## 联系人限制记录
源码目录 `contactBlocked` 为 0,`unrepliable_sessions` 为 0。安装版 `contactBlocked` 有 1 条,可在内存中按账号+会话哈希匹配到一个 S: 关系联系人,关系 status=2049,但记录已超过现有 6 小时有效期。该记录是曾经不能回复的证据,不能用来定义 status=2049 的含义,也不能作为永久删除关系的依据。
现有 `contact_reply_guard.py` 根据系统验证提示/明确传输拒绝识别限制,`protocol_engine.py:354` 维护短期屏蔽;这些记录是发送保护,不是我的客户名单。医疗助理列表应共享保护结果,不能用屏蔽名单反推出全部客户。
## 交付与限制
- `schema-aggregates.json`:源码缓存各表 schema 与数量。
- `relation-aggregates.json`:源码当前账号关系状态、名称覆盖、S/M映射数量。
- `packaged-aggregates.json`:安装版最新缓存、关系及联系人保护计数。
- 三个 `audit_*.py` 为本次只读审计脚本,只读已解密缓存,输出聚合结果。
当前缓存已经具备“按本账号关系列出候选 + 显示昵称/备注 + 核验既有S会话”的关键数据;不需要为此读取消息正文或强制解密。严格实时UI成员一致性及 status 位定义仍缺证据,本审计未声称解决这些未验证问题。