# 对齐 Muse P9 差距表:推理与遥测受限通道 > 先写表再动手。依据:`~/workspace/research_notes/meta-muse-ai-architecture-20261101-0755/report.md` > (Meta 官方 security.muse.ai 与设计文 2026-09-08 为准;第三方拆解只作参考,不得把逆向细节写成官方架构)。 > 基线:`06c3e17`。分支:`feat-chv-muse-p9`。本地做,不推、不合、不部署。 ## 1. 现状 vs Muse 官方要求 | # | Muse 官方要求(security.muse.ai / 设计文) | 现状(基线 06c3e17) | 本轨做法 | |---|---|---|---| | 1 | 推理与遥测代理是通向外部基础设施的**受限通道** | 模型调用无收敛点:`host.py` 起 `codex app-server`,provider=`sub2api` 时 `-c` 覆盖 base_url(取 `SUB2API_BASE_URL`);provider 为空时 codex 用自身 config.toml 默认网关(xcmapi 路径),执行器侧没有任何出口校验 | 新模块 `cloud/chv/inference_channel.py`:单一出口点 + 执行器 `_run_with_vm` 起 VM 前预审(Sentinel 评估);`host.py` 的 `_server_command` 做结构校验(https、无 userinfo、主机在 allowlist 内)当第二道防线 | | 2 | VM 发送**有限数据**用于推理与遥测(安全文**未给字段级清单**) | 无任何遥测:任务元数据只进宿主日志与审计 spill,无字段清单、无采样、无发送路径 | 新模块 `cloud/chv/telemetry.py`:字段级白名单(只含任务级元数据,见 §2);采样率可配;落盘 `/telemetry.jsonl`,发送失败只记日志、不影响任务 | | 3 | 推理轨迹(对话往返、工具调用、子代理交接)在**去除关键个人身份信息后**可用于训练新检查点;用户可**一键退出训练** | 无训练上传、无开关 | 训练退出开关(`training_opt`,见 §2):状态持久化在 `/training-opt.json`,关后轨迹类事件不再产生;开关变更进审计。**默认值开是本项目决定,非 Meta 官方值**(报告注明帮助中心原文未逐字确认默认开启) | | 4 | 当前 VM 的 Meta 访问边界(官方明确,非营销口径):运营政策限制 Meta 人员访问用户数据,但**并不阻止** Meta 在必要时为支持、保障或运营而访问;“连 Meta 也看不到”是未来 Confidential VM 的目标 | 无边界说明 | `docs/chv-access-boundary.md`:只写文档 + 审计钩子,不冒充技术上不可访问;Confidential VM 明确列为未做 | | 5 | 广告隔离:不把用户对话或 VM 数据分享给广告系统;但浏览互联网时表现为用户活动、可能间接影响广告 | 无口径 | 只记为口径(见 §4),不用写代码 | | 6 | Sentinel 是连接器动作与全部网络出口的唯一权限机构 | P3 已做 Sentinel 最小审批、P5 已做纵深(本基线**都没有**;P3 在 `feat-chv-muse-p3` 分支 a90cf78,P5 在 `feat-chv-muse-p5` 分支 25bcd35) | 推理通道走 Sentinel 审批,不重复造审批:`cloud/chv/sentinel.py` 从 **P5 的 25bcd35 拷入**(P5 版已是 P3 的超集,顶层仍只用标准库),再加 P9 的 inference 条目(三张表里加 `inference`:scheme https、端口 443、路径 `POST /v1/responses` + `GET /v1/models`);合入时以本文件为准(它是 P3+P5+P9 的并集) | ## 2. 本项目自定清单(非 Meta 官方值,逐项注明) ### 2.1 遥测字段白名单(`telemetry.py`) 只含任务级元数据,**绝不含**对话原文、文件内容、密钥、个人身份信息: | 字段 | 含义 | 来源 | |---|---|---| | `task_id` | 任务 id | 任务 dict | | `vm_id` | VM 名 | 执行器 | | `provider` | 模型 provider(`sub2api` / `xcmapi`) | 通道决策 | | `model` | 模型名 | 任务 dict | | `status` | `completed` / `failed` / `interrupted` / `timeout` | 运行结果 | | `started_at` / `ended_at` | 起止时间戳(秒) | 执行器 | | `duration_ms` | 耗时毫秒 | 执行器 | | `tokens_in` / `tokens_out` / `tokens_total` | token 数 | host.py 回传的 usage(未回传时记 `null`,**不编造**) | | `turns` | 回合数 | 运行结果 | | `tool_calls` | 工具调用次数 | 运行结果 | | `sampled` | 是否被采样命中 | 采样器 | 不在白名单里的键一律丢弃;键名含 `key` / `token` / `secret` / `password` / `prompt` / `content` / `text` / `message` / `email` / `name` 的一律丢弃(防误带)。采样率 `CHV_TELEMETRY_SAMPLE_RATE`:0.0–1.0,默认 `1.0`(全量,任务级元数据量小);按 `task_id` 确定性采样(同一任务每次判定一致,可测试)。 ### 2.2 轨迹事件(训练用) 轨迹类事件只含回合级元数据(回合数、工具名、耗时),**不含任何文本**;去标识化 = 只出元数据、不出内容。退出开关关后,轨迹类事件**不再产生**(不是产生后丢弃)。 ### 2.3 推理通道上限(自定) | 项 | 环境变量 | 默认 | 范围 | 说明 | |---|---|---|---|---| | 单次请求超时(秒) | `CHV_INFERENCE_TIMEOUT` | `120` | 10–600 | 与 `host.py` 的 `Server.request` 默认超时一致;非法值即 ValueError | | 重试上限(次) | `CHV_INFERENCE_MAX_RETRIES` | `1` | 0–5 | `Server.request` 的 BrokenPipe 重连次数上限;默认 `1` 即**保持现有行为不变**(现为 `range(2)`);模型回合级重试仍是 worker 的 `max_retries` 语义,本轨不动 | ### 2.4 训练退出开关默认值 默认**开**(轨迹可用于训练)。这是**本项目决定,非 Meta 官方值**:报告注明帮助中心原文未逐字确认 默认开启。开关状态持久化、变更进审计;关后立即生效(后续轨迹不再产生)。 ### 2.5 推理出口 allowlist 与 origin 规则 - provider=`sub2api`:origin 取 `SUB2API_BASE_URL`(去尾斜杠);未知 provider 标签与 provider 为空一样走默认网关(与 host.py `_server_command` 一致——标签本身不决定 origin,origin 永远只取 operator 配置的 env)。 - provider 为空或未知标签(xcmapi 路径,codex 用自身 config.toml 默认网关):执行器 **看不到** origin,改取 `CHV_INFERENCE_ORIGIN`(operator 显式配置,如 `https://xgapi.lol`); 未配即 `ask`——审计 + 任务停止(fail-closed),**不静默放行**。部署迁移:现网 xcmapi 部署 须补设 `CHV_INFERENCE_ORIGIN`,否则任务会在预审处停下(这是有意行为,见 §3)。 - scheme 规则(2026-11-07 全量套件复核时修正——初版只认 https 是错的): - https:公网网关(如 xgapi.lol),端口只接受 443(或缺省); - http:**只接受本地中继**——字面环回/私网 IP 主机(如 cloud/README.md 的 sub2api 网关 文档形状 `http://172.17.0.1:28084`,Docker 桥接 IP),端口保留;http + 公网主机名/IP、 http + 主机名一律拒绝。主机名一律不算本地中继(DNS 结果不可信)。 - 本地中继分支:字面 IP 无 DNS、无重绑定,跳过 Sentinel 的 DNS/SSRF 步;allowlist 与 单次能力(P3 默认档)照常执行;解析器不被调用(测试用必错解析器钉住)。Sentinel 表里的 inference scheme/端口仍只写 https/443——本地中继不走 `evaluate`,不要“顺手”把 http 加进表(那会放宽公网路径)。 - 路径规则(`inference` 连接器):只放 `POST /v1/responses` 与 `GET /v1/models`; `/v1/models` 是否必需**待真机核实**(codex 启动时是否拉模型列表),若非必需则收紧为只放 `/v1/responses`。公网路径:解析到私网 IP 即 deny(SSRF,复用 Sentinel);解析失败即 deny。 - 任务级 env 合并:门的 origin 取任务级 `extra_env`(网关配置随任务来,如 worker 的 `_gateway_env`)覆盖执行器进程 env;origin 非法(http 公网、带 userinfo、https 非 443 端口)记 deny,不抛裸 ValueError。报错/审计原因不带 origin 原值(http URL 里可能含 userinfo,见 `resolve_inference_origin`)。 ## 3. 改什么(文件清单) | 文件 | 动作 | |---|---| | `cloud/chv/sentinel.py` | **新增**:从 P5 分支 `25bcd35` 拷入(P5 版已是 P3 的超集,顶层仍只用标准库),再加 P9 的 inference 条目(三张表:路径、scheme、端口);合入时以本文件为准(P3+P5+P9 的并集) | | `cloud/chv/inference_channel.py` | **新增**:受限推理通道(origin 解析、allowlist、上限校验、Sentinel 预审、`InferenceChannelDenied` 之外的 Decision 返回) | | `cloud/chv/telemetry.py` | **新增**:遥测事件(字段白名单、采样、落盘、永不抛错)+ 训练退出开关(持久化、审计) | | `cloud/chv/executor.py` | **改动**:`_run_with_vm` 起 VM 前调推理预审(`_inference_gate`);allow 通过、deny/ask 审计 + `ChvFailure` 停止,不起 VM。`execute()`(只读 status,不跑模型回合)不设门 | | `host.py` | **改动**:`_server_command` 的 sub2api origin 结构校验(https、无 userinfo、主机在 allowlist 内);`Server.request` 默认超时与重连上限改走 `CHV_INFERENCE_TIMEOUT` / `CHV_INFERENCE_MAX_RETRIES`(默认 120 秒 / 1 次,即现有行为) | | `cloud/tests/test_chv_muse_p9.py` | **新增**:全部覆盖(见 §5) | | `docs/chv-muse-p9-gap.md` | **新增**:本文件 | | `docs/chv-access-boundary.md` | **新增**:运营访问边界说明 | **不碰的**:`cloud/chv/config.py`(通道读 `env` 字典,不进 VM 配置片段;架构测试无“env 必须进片段”的规矩)、 P3 的 authd、P5 的 eBPF 污点(P5 已结论:本 VM 的 bpf() 被 seccomp 挡,不可行;本轨不重复探)、 P6 的确定性检查层(审计复用执行器已有的 `_emit`,不另造审计接口)、worker 的 `max_retries`、 guest 镜像(`host.py` 是标准库单文件,`/app/host.py` 拷入方式不变——本轨对 `host.py` 的改动只用标准库)。 ## 4. 诚实边界 - 本轨是**决策层 + 预审**,不是网络层强制:客内 codex 直连的强制仍靠 Tinyproxy 白名单 + 宿主防火墙 (第三棒落地中)。不要把本轨写成“出口已全部经 Sentinel”——P3 的模块 docstring 同款声明。 - provider 为空时执行器看不到 codex config.toml 里的 origin:本轨用 `CHV_INFERENCE_ORIGIN` 显式配置 + 未配即 ask 兜底;这不是“读到了 config”,部署时须补 env(见 §2.5)。 - 遥测目前只落盘 `/telemetry.jsonl`,**没有**向外部遥测端点发送的路径;“发送失败不影响任务” 指落盘失败也不影响任务。向外部发遥测是后续工作,需另批。 - 训练轨迹目前**没有**上传路径:开关管的是“轨迹类事件是否产生”;上传通道本身不存在,开关是为 上传通道预留的门禁,不是已接通的上传。 - token 数只取 host.py 回传的 usage;codex 未回传时记 `null`,不估算、不编造。 - `GET /v1/models` 是否必需未验证(见 §2.5),真机核实前不收紧、也不放宽。 - `sentinel.py` 是从 P5 分支(25bcd35)原样拿来的超集版本:其中 `capability_for` 的非 one-shot 分支在运行时 import `cloud.chv.capabilities`——该模块是 P5 的文件,本轨基线 06c3e17 里没有。 本轨只走 one-shot 默认档,运行时不触及该分支(新测试 51/51 证明);mypy 会报 1 处 `import-not-found`,待 P3/P5/P9 集成轨把 capabilities.py 带进来后消除,不在本轨另造一份。 其余 mypy 报错与基线一致:`executor.py:1396/1401`(`out` 未注解)与 `marker_tools.py:142` 是 P3 已记录的基线问题,本轨未碰。 ## 5. 测试清单(`test_chv_muse_p9.py`,全部用标准库与 mock,不联网、不启动真实 VM) - origin 解析:合法 origin 通过;缺 `SUB2API_BASE_URL` 即错;http 公网主机名/IP 被拒; http 本地中继(字面环回/私网 IP,如 `http://172.17.0.1:28084`)通过且端口保留; URL 带 userinfo 被拒;尾斜杠被剥掉;未知 provider 标签走默认网关(不 deny)。 - allowlist:`CHV_INFERENCE_ALLOW_HOSTS` 显式覆盖生效;默认即 origin host。 - 上限校验:超时/重试非法值(非整数、越界)即 ValueError;默认值 120/1。 - 预审决策(假解析器,不联网):allow(公网 IP + 白名单 + 路径内);deny(解析到私网 IP、 origin 非法);ask(主机不在白名单、provider 为空且未配 `CHV_INFERENCE_ORIGIN`); 路径越界(`GET /v1/admin`)即 deny;能力绑定(单次、300 秒);本地中继 allow(不查 DNS, 用必错解析器钉住)与本地中继 ask(allowlist 不含该主机)。 - 旁路:直连(非通道)调模型无入口——执行器 `_run_with_vm` 前必过预审(mock 执行器验调用顺序: 预审 deny 时 `wake_vm` 未被调用);任务级 `extra_env` 的 origin 被合并进预审(worker 网关 路径),非法 origin 转 deny 而不是裸 ValueError。 - 遥测:白名单外键丢弃;`prompt`/`content`/`api_key` 类键丢弃;采样确定性(同一 task_id 多次判定一致; 采样率 0 全丢、1 全留);落盘失败(state_dir 不可写)不抛错、不影响任务;token 未回传记 `null`。 - 训练开关:默认开;关后轨迹事件不再产生、任务级遥测不受影响;开关变更持久化 + 审计有记录; 状态文件损坏时 fail-closed(当作关处理,记日志)。 - host.py:`_server_command` 的 origin 结构校验(http 公网被拒、本地中继通过、allowlist 不匹配 被拒、合法通过);`Server.request` 默认超时与重试上限走 env(mock 验默认值 120/1 与 env 覆盖)。 - 旧测试 harness:5 个文件的 `make_exec` 配了假 origin(`SUB2API_BASE_URL` 与 `CHV_INFERENCE_ORIGIN` 均为 `https://xgapi.lol`)+ 假公网解析器——这是新 fail-closed 门 要求的测试配置,不是放宽门;门的 deny/ask 行为由本轨新测试钉住。 ## 6. 真机待验证清单(排队,测试机空闲后;第三棒 → round-11 → P4/P5/P6 → 本轨) 1. `GET /v1/models` 是否必需:真机跑一轮 turn,确认 codex 是否调它;必需则保留,不必需则收紧为只放 `POST /v1/responses`。 2. 预审对真实 xgapi 主机的判定:`https://xgapi.lol` 解析后 IP 是否干净(不在 SSRF 挡截网段内);若解析到被挡网段,记录真实判定、不绕过。 3. `CHV_INFERENCE_ORIGIN` 未配时 xcmapi 任务是否如实停在预审(ask + 审计),配上后是否放行。 4. 本地中继真机:`SUB2API_BASE_URL=http://172.17.0.1:28084` 的任务预审是否放行(本地中继分支)、 真实 turn 是否走通该中继;同时确认 http 公网 origin 在真机仍被拒。 5. 真实 turn 的 usage 是否回传:遥测里的 token 字段是否从 `null` 变成实数。 6. 遥测落盘文件在真实任务后是否存在、内容是否只有白名单字段。 7. 训练开关在真机上的持久化:开关翻转后重启执行器,状态是否还在。 7. 超时/重试上限在真机上的表现:长 turn 是否在 `CHV_INFERENCE_TIMEOUT` 处超时(只记录、不主动造超时)。