# 真实宿主验收速查清单 日期:2026-05-21 用途: - 给后续每次 real-host 验收直接复用 - 只保留最短闭环,不展开历史背景 - 如果你当前是在“新增 provider”或“宿主版本升级后重新适配”,先看:`PROVIDER_ONBOARDING_PLAYBOOK.md` - 详细解释仍看:`REAL_HOST_ACCEPTANCE_RUNBOOK.md` 与 `REAL_HOST_ACCEPTANCE_LEARNINGS.md` ## 0. 先确认你看的是真相文档 按顺序先读: 1. `docs/SOURCE_OF_TRUTH.md` 2. `docs/EXECUTION_BOARD.md` 3. `docs/PRODUCTION_CLOSURE_BOARD.md` 禁止: - 直接拿历史 review/task board 顶部 gate 当当前状态 - 直接拿历史 PASS artifact 当 latest-head 当前真相 ## 1. 环境前置检查 每次验收前先确认 5 件事: 1. 在线 CRM 进程是不是最新提交对应进程 2. `PACK_PATH` 是不是 CRM 进程本机可读路径 3. `CRM_HOST_BASE` 是不是 CRM 到宿主真实可达地址 4. 验收脚本命中的 Postgres/Redis/host 是不是目标 fresh host,而不是旧环境 5. **入口一致性检查** — 对本机 SSH 隧道、宿主容器端口、CRM 注册的 host 版本三者做三层核对,确保验收不因端口漂移/旧进程残留/宿主串台产生误报 若这 5 项没先确认,后续结论一律不可信。 ## 2. channel 宿主契约检查 对每个导入 provider,必须确认 channel 最终同时具备: - `model_mapping` - `model_pricing` - `restrict_models=true` - `billing_model_source=channel_mapped` 补充规则: - `model_mapping` 真实宿主接口是按 platform 嵌套结构 - `model_pricing[].platform` 不能留空 - existing channel 不能只复用名字,必须执行纠偏更新 一句话: - 新建即完整 - 已存在可纠偏 ## 3. access / key 语义检查 ### self_service 必须同时满足: 1. 普通用户已创建 2. 普通用户 key 已创建 3. key 已绑定目标 standard group 4. 用户有可用余额 ### subscription 必须同时满足: 1. 普通用户已创建 2. 普通用户 key 已创建 3. 目标 group 是 `subscription` 类型 4. 用户有 active subscription 5. key 已绑定该 subscription group 关键规则: - subscription 场景最终 probe key 是宿主 managed key - 不是外部传入原始 `ACCESS_API_KEY` ## 4. 每次都要落的三层证据 不能只看一层,必须分开留证据: 1. account 视角 - `GET /api/v1/admin/accounts/:id` - `GET /api/v1/admin/accounts/:id/models` 2. 普通用户 / managed key 视角 - `GET /v1/models` 3. completion 视角 - `POST /v1/chat/completions` 禁止混用: - `accounts/:id/models` 正确 ≠ `/v1/models` 正确 - `/v1/models` 正确 ≠ `/v1/chat/completions` 正确 - admin API 成功 ≠ 普通用户链路成功 ## 5. 最短诊断顺序 如果验收失败,按这个顺序查: 1. 先查环境 - CRM 进程版本/启动时间 - `PACK_PATH` - `CRM_HOST_BASE` - fresh host 目标是否打对 2. 再查宿主落库 - account `credentials.model_mapping` - `GET /api/v1/admin/accounts/:id/models` - channel `model_mapping/model_pricing/restrict_models/billing_model_source` 3. 最后查普通用户流量 - `/v1/models` - `/v1/chat/completions` ## 6. 常见现象 → 优先判断 ### 现象 A:`/accounts/:id/models` 对,但 `/v1/models` 403 优先判断: - key 没绑 group - subscription 没分配 - 用错了原始 probe key,没用 managed key - self_service 缺余额 ### 现象 B:模型列表返回成 GPT 系,而不是目标 provider 模型 优先判断: - account `credentials.model_mapping` 没落对 - channel 缺 `model_pricing` - channel 缺 `restrict_models=true` - channel 缺 `billing_model_source=channel_mapped` - 在线 CRM 还是旧进程 ### 现象 C:`/v1/models` 已 200,但 `/v1/chat/completions` 失败 优先判断: - host provider 兼容性 - 上游 key/quota - 不要先回退归因为 CRM 导入失败 ## 7. 一次验收的最小通过标准 至少同时满足: 1. import 成功,且 batch/provider 不为 `failed` 2. account `/models` 返回目标模型 3. channel 回读包含完整 routing/pricing 字段 4. `/v1/models` 返回目标模型 若要宣称“真实可用通过”,还必须再加:5. `/v1/chat/completions` 成功 ## 8. 一句话红线 - 不要把 `/v1/models` 当 completion 成功 - 不要把 account 成功当普通用户成功 - 不要把原始 `ACCESS_API_KEY` 当 subscription 最终 probe key - 不要看到旧 artifact 就直接判定 current-code 失效 - 不要在没核对在线 CRM 进程版本前下 live 结论 - **不要跳过入口一致性检查 — SSH 隧道端口、宿主容器端口、CRM 注册的 host 版本必须三层核对一致** ## 9. 2026-06-04 新增的坑(已验证修复) ### 坑 1:验收脚本里 gateway 直探和 managed key 又混了 `import_remote43_provider.sh` 第 690/695 行用来直探 gateway `/v1/models` 和 `/v1/chat/completions` 的 key,**必须用 `$sub_key`(普通用户的真实 gateway key)**,不能复用 `$managed_probe_key`(托管用户的 hash key,仅用于 subscription 绑定关系验证)。 用错 key 时直探返回 401,但这不代表 CRM 产品链路有问题——只代表验收脚本用错了 probe key。 当前脚本已加 `# REDLINE` 注释标注此约束。 ### 坑 2:从 session 中获取的 key 不可靠——必须从 PG 直取原始 key Hermes 脱敏工具会在 session 中截断所有 API key 环境变量。如果要直探 stock host gateway,必须从 stock host PG 的 `api_keys` 表直取原始 key 值。 正确的获取方式: ```bash ssh remote43 "sudo -n docker exec pg psql -U sub2api -d sub2api -Atc \"SELECT key FROM api_keys WHERE user_id = N\"" ``` 然后用这个原始值做 `Authorization: Bearer *** ` 直探。 ### 坑 3:更新 account upstream key 的正确方法 通过 stock host admin API 更新 account 的 upstream key 时: - ✅ **正确**:`PUT /api/v1/admin/accounts/{id}` with body `{"type": "apikey", "key": "sk-..."}` → `credentials_status.has_api_key = true` - ❌ **错误**:`PUT /api/v1/admin/accounts/{id}` with body `{"credentials": {"api_key": "sk-...", ...}}` → api_key 不会保存 ### 坑 4:Heremes 脱敏会破坏脚本变量 在 Hermes 会话中,如果用 `write_file` 或 `patch` 工具修改 `.sh` 文件,文件中 `$sub_key`、`$managed_probe_key`、`$upstream_key` 这类 shell 变量名可能被脱敏工具替换为 `***`。修复时必须用 Python bytes 操作或 base64 绕开。