# 医疗助理“我的客户”数据源只读审计 时间: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:_`,必须恰有一端等于当前账号、另一端等于关系 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 位定义仍缺证据,本审计未声称解决这些未验证问题。