Files
codex-app-server/docs/chv-muse-p9-gap.md
T
host c06ba50983 feat-chv-muse-p9: 推理与遥测受限通道(Sentinel 预审 + 遥测最小化 + 训练退出开关)
- 受限推理通道:cloud/chv/inference_channel.py(origin 解析、
  allowlist、上限、Sentinel 预审),执行器 _run_with_vm 起 VM 前
  必过 _inference_gate(allow 才继续,deny/ask 审计 + fail-closed,
  任务级 extra_env 合并进预审);host.py 第二道防线(_server_command
  的 origin 结构校验 + Server.request 超时/重试走 env)。
  origin 规则:https 公网网关(只 443);http 只接受本地中继
  (字面环回/私网 IP,如 http://172.17.0.1:28084,端口保留,
  无 DNS、无重绑定,allowlist 与单次能力照常);未知 provider
  标签走默认网关(与 _server_command 一致)。
- sentinel.py:从 P5(25bcd35)取的超集版本 + 推理连接器条目
  (POST /v1/responses、GET /v1/models;scheme/端口只 https/443,
  本地中继不走 evaluate,不把 http 加进表)。
- 遥测最小化:cloud/chv/telemetry.py(字段白名单、确定性采样、
  落盘失败不影响任务、token 未回传记 null)+ 训练退出开关
  (默认开,本项目决定;关后轨迹不再产生;损坏 fail-closed;变更审计)。
- 访问边界:docs/chv-access-boundary.md(运营访问口径 + 审计钩子,
  不冒充技术不可访问;Confidential VM 明确未做)。
- 测试:cloud/tests/test_chv_muse_p9.py 51 组全过;5 个旧文件
  的 make_exec 配假 origin + 假解析器(新 fail-closed 门要求的
  测试配置);全量 cloud 套件 1918 OK(skipped=8)。
  详见 docs/chv-muse-p9-gap.md(含自定清单与真机待验证清单)。
2026-11-06 23:03:06 +00:00

15 KiB
Raw Blame History

对齐 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);采样率可配;落盘 <state_dir>/telemetry.jsonl,发送失败只记日志、不影响任务
3 推理轨迹(对话往返、工具调用、子代理交接)在去除关键个人身份信息后可用于训练新检查点;用户可一键退出训练 无训练上传、无开关 训练退出开关(training_opt,见 §2):状态持久化在 <state_dir>/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)。
  • 遥测目前只落盘 <state_dir>/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. 训练开关在真机上的持久化:开关翻转后重启执行器,状态是否还在。
  8. 超时/重试上限在真机上的表现:长 turn 是否在 CHV_INFERENCE_TIMEOUT 处超时(只记录、不主动造超时)。