feat: organize scripts and add portal validation assets

This commit is contained in:
phamnazage-jpg
2026-05-27 09:39:05 +08:00
parent c1172d7714
commit 02580cda0b
180 changed files with 3392 additions and 76 deletions

View File

@@ -46,6 +46,24 @@ SUB2API_CRM_ADMIN_TOKEN=change-me-before-production SUB2API_CRM_LISTEN_ADDR=127.
| `SUB2API_CRM_LISTEN_ADDR` | 监听地址 | `:18081` |
| `SUB2API_CRM_SQLITE_DSN` | SQLite DSN | `file:/tmp/sub2api-cn-relay-manager.db?_foreign_keys=on&_busy_timeout=5000` |
## 公网 Portal 资产
如果你还需要同时维护 `sub.tksea.top` 上的用户态 portal不要再把静态页或 Nginx 规则只放在 `/tmp`
- 静态页源码:`deploy/tksea-portal/index.html`
- Nginx 示例:`deploy/tksea-portal/nginx.sub.tksea.top.conf.example`
- 部署脚本:`scripts/deploy/deploy_tksea_portal.sh`
- 资产回归:`scripts/test/test_tksea_portal_assets.sh`
当前正式入口:
- `https://sub.tksea.top/portal/`
兼容入口:
- `https://sub.tksea.top/kimi-portal/`
- 当前应保持跳转到 `/portal/`
## 上线前验证
```bash

View File

@@ -15,6 +15,18 @@
- `self_service` 主链路已通过 latest-head 标准 fresh-host 复验:
- `artifacts/real-host-acceptance/20260521_210403/05-import.json`
- `artifacts/real-host-acceptance/20260521_210403/07-access-status.json`
- 2026-05-27 已把公网用户入口从 `kimi-portal` 收口为通用多模型 portal
- 新正式地址:`https://sub.tksea.top/portal/`
- 旧地址 `https://sub.tksea.top/kimi-portal/` 当前保留为 `302` 跳转,避免历史分享链接失效
- 站点资产与 Nginx 路由不再只存在 `/tmp` 临时文件,已收口进仓库:
- `deploy/tksea-portal/index.html`
- `deploy/tksea-portal/nginx.sub.tksea.top.conf.example`
- `scripts/deploy/deploy_tksea_portal.sh`
- 新页面已补齐登录态、用户信息、可绑定分组、活跃订阅、历史 key 列表,以及“新创建 key 对应分组/模型”的即时展示
- 线上无副作用验收已确认:
- `GET /portal/` 返回 `200`
- `GET /kimi-portal/` 返回 `302 -> /portal/`
- `GET /portal-proxy/api/v1/keys` 在无效 token 下已命中宿主真实 `INVALID_TOKEN`,说明新的同域代理已生效
- 2026-05-26 已把“最终用户 -> 公网域名 -> OpenClaw”这一跳补进正式验证口径
- 公网根地址当前统一为 `https://sub.tksea.top`
- OpenClaw 本地 `MiniMax` 运行时故障已定位为 `pi-ai/openai-node` 未继承系统 `HTTP(S)_PROXY`,不是 allowlist 或模型名大小写问题
@@ -38,12 +50,12 @@
- 旧 artifact `artifacts/real-host-acceptance/20260526_155810_remote43_deepseek_chat_official_multi_model_rootprep/21-summary.json` 停在 `partially_succeeded/degraded`
- 2026-05-27 rerun `artifacts/real-host-acceptance/20260527_051655_remote43_deepseek-chat-official_key_import/21-summary.json` 已确认本机经 remote43 patched host 的真实数据面恢复:`direct_models_http200=true``direct_models=["deepseek-chat"]``direct_chat_status=200``latest_access_status=subscription_ready``upstream_chat_status=200`
- 剩余 `partially_succeeded/degraded` 的唯一原因已定位为宿主 account probe 返回裸 `API returned 404:`,而后续 gateway `/v1/models` + `/v1/chat/completions` 实际都已通过HEAD 现已把该 404 视为 advisory不再阻塞最终状态收敛
- 同轮还补上 remote43 scripted stack 的真实脚本缺陷:`.env.crm` 里的 SQLite DSN 含 `&_busy_timeout=5000` 时,旧版未做 shell escape`source .env.crm` 会吞掉 `SUB2API_CRM_SQLITE_DSN`,导致 remote CRM 实际退回默认 DB 路径;`scripts/remote43_patched_stack_lib.sh` 已修复并有回归测试覆盖
- 同轮还补上 remote43 scripted stack 的真实脚本缺陷:`.env.crm` 里的 SQLite DSN 含 `&_busy_timeout=5000` 时,旧版未做 shell escape`source .env.crm` 会吞掉 `SUB2API_CRM_SQLITE_DSN`,导致 remote CRM 实际退回默认 DB 路径;`scripts/deploy/remote43_patched_stack_lib.sh` 已修复并有回归测试覆盖
- latest-head relay-manager 已新增宿主 capability 自愈:
- 当第三方 OpenAI-compatible upstream 因宿主把 `openai_responses_supported` 误判成 `true` 而导致 host `/v1/chat/completions` 返回 `502 upstream_error`access closure 与后台 reconcile 会自动把相关 account 修正到 raw `/chat/completions` 路径后再重试
- 但这条控制面自愈当前仍不足以单独收敛本地 stock `weishaw/sub2api:0.1.129` + `kimi-a7m` 场景;`artifacts/real-host-acceptance/20260525_local_v0129_kimi_a7m_scheme_c_stockhost_rerun/21-summary.json` 已再次证明在不改宿主源码的前提下managed `/v1/models` 虽然命中 `kimi-k2.6``/v1/chat/completions` 仍会落到 `502 upstream_error`,所以该 case 仍需宿主运行时兼容补丁或 shim
- 2026-05-23 remote43 线上验收脚本已继续收口:
- `scripts/import_remote43_provider.sh` 现已明确拆分 `CRM_HOST_BASE``REMOTE_HOST_BASE`
- `scripts/acceptance/import_remote43_provider.sh` 现已明确拆分 `CRM_HOST_BASE``REMOTE_HOST_BASE`
- 远端 Postgres / Redis 容器已改成按目标宿主端口自动解析,不再硬编码落到 `sub2api-relaymgr-pg/redis`
- 远端 managed probe `/v1/models``/v1/chat/completions` 已改成只走 `REMOTE_HOST_BASE`
- provider status / access status / access preview 末尾查询已补 `host_id`,避免本地 CRM 有多宿主历史时被 `provider exists on multiple hosts` 截断
@@ -65,14 +77,14 @@
- `artifacts/real-host-acceptance/20260525_remote43_kimi_a7m_patched_overlay_freshhost_remotecrm/21-summary.json` 已确认:`batch_status=succeeded``access_status_from_import=subscription_ready``provider_status_from_import=active``direct_models_http200=true``direct_chat_http200=true``upstream_chat_status=200`
- 同目录 `14-access-status.json` 已确认 `effective_probe_key_source=managed_subscription``completion_status=200`
- remote43 宿主日志也已落到真实 `GET /v1/models = 200``POST /v1/chat/completions = 200`,说明这条 patched overlay 路线不只在本地 fresh-host 成功,也已在远端真实环境收敛到 ready
- 这轮还顺手修掉了 `scripts/import_remote43_provider.sh` 的一个真实脚本缺陷:查找未分配 `relay-sub-*` 用户时,`NOT EXISTS` 子查询错误引用了无 alias 的 `users.id`,在 PostgreSQL 上会报 `invalid reference to FROM-clause entry for table "users"`
- 这轮还顺手修掉了 `scripts/acceptance/import_remote43_provider.sh` 的一个真实脚本缺陷:查找未分配 `relay-sub-*` 用户时,`NOT EXISTS` 子查询错误引用了无 alias 的 `users.id`,在 PostgreSQL 上会报 `invalid reference to FROM-clause entry for table "users"`
- 2026-05-25 继续把这套 remote43 patched-host / remote CRM 的启动流程脚本化:
- 新增 `scripts/setup_remote43_patched_stack.sh`,把 pack 镜像、二进制上传、remote43 上的 PG/Redis/patched host/临时 CRM 拉起、以及本地 operator env / SSH 隧道提示收口为一个固定入口
- 新增 `scripts/remote43_patched_stack_lib.sh`,把远端 host env / CRM env / bootstrap script 渲染逻辑抽成可测试 helper
- `scripts/test_real_host_scripts.sh` 已新增对应回归,避免以后再回退到手工 `/tmp/*.sh` 拼装
- 新增 `scripts/deploy/setup_remote43_patched_stack.sh`,把 pack 镜像、二进制上传、remote43 上的 PG/Redis/patched host/临时 CRM 拉起、以及本地 operator env / SSH 隧道提示收口为一个固定入口
- 新增 `scripts/deploy/remote43_patched_stack_lib.sh`,把远端 host env / CRM env / bootstrap script 渲染逻辑抽成可测试 helper
- `scripts/test/test_real_host_scripts.sh` 已新增对应回归,避免以后再回退到手工 `/tmp/*.sh` 拼装
- 脚本首轮真实演练暴露出一个运行态细节patched `sub2api` 二进制实际监听 `8080`,不能沿用旧临时脚本里的 `127.0.0.1:$HOST_PORT:3000` 端口映射;当前 `setup_remote43_patched_stack.sh` 已新增 `HOST_CONTAINER_PORT=8080` 默认值并完成 remote43 二次实跑验证
- 用修复后的固定脚本在 remote43 新起的 `sub2api-kimi-patched-auto2-20260525` 栈上,`kimi-a7m` 再次完成真实导入主链路:`artifacts/real-host-acceptance/20260525_remote43_kimi_a7m_patched_overlay_scripted_stack/03-import.body.json` 已确认 `batch_status=succeeded``access_status=subscription_ready``provider_status=active`,同目录 `10-models.body.json` / `12-chat.body.json` / `18-upstream-models.body.json` / `20-upstream-chat.body.txt` 也已再次证明 managed 与 upstream 双侧都回到 `HTTP 200`
- 2026-05-26 继续把 scripted stack 的末尾状态查询收口为稳定契约:`scripts/import_remote43_provider.sh` 末尾不再只传 `host_id`,而是显式拼上 `pack_id=openai-cn-pack&host_id=<create-host 返回值>`;修复原因是 remote43 上同一个 provider 可能存在多个 pack 版本,缺 `pack_id``/api/providers/{providerID}/status` 会返回 `400 provider exists in multiple packs; pack_id is required`
- 2026-05-26 继续把 scripted stack 的末尾状态查询收口为稳定契约:`scripts/acceptance/import_remote43_provider.sh` 末尾不再只传 `host_id`,而是显式拼上 `pack_id=openai-cn-pack&host_id=<create-host 返回值>`;修复原因是 remote43 上同一个 provider 可能存在多个 pack 版本,缺 `pack_id``/api/providers/{providerID}/status` 会返回 `400 provider exists in multiple packs; pack_id is required`
- 修复后,`artifacts/real-host-acceptance/20260526_remote43_kimi_a7m_patched_overlay_scripted_stack_rerun2/13-provider-status.json``14-access-status.json``21-summary.json` 已全部自动补齐;其中 `21-summary.json` 已再次确认 `batch_status=succeeded``provider_status_from_import=active``latest_access_status=subscription_ready``direct_chat_status=200``upstream_chat_status=200`
- `artifacts/real-host-acceptance/20260525_local_v0129_kimi_a7m_from_hermes/21-summary.json` 已证明:
- Hermes 本机 `A7M_KIMI_API_KEY` 直探 upstream `/v1/models``/v1/chat/completions` 均为 `200`
@@ -133,7 +145,7 @@
- 新增 `docs/2026-05-18-PRODUCTION_REMEDIATION_TASK_BOARD.md`
- 下调 `DEPLOYMENT.md` 中未实现的 `/metrics` / 限流 / 监控承诺
7. current-code remote43 导入链路已补齐 tunnel-aware 验证能力
- `scripts/import_remote43_provider.sh` 新增 `CRM_HOST_BASE`允许把“operator 访问 host 地址”和“CRM 进程访问 host 地址”分离
- `scripts/acceptance/import_remote43_provider.sh` 新增 `CRM_HOST_BASE`允许把“operator 访问 host 地址”和“CRM 进程访问 host 地址”分离
- 历史 live model-mapping 关键证据保留在:`artifacts/real-host-acceptance/20260520_222713_crm18100_live_model_mapping_validation`
8. current-code remote43 access gate 根因修正已落地
- subscription access 改为宿主侧闭环CRM 不再依赖外部预先给定的宿主普通用户 key而是按 `subscription_users` selector 在宿主创建/查找托管普通用户、登录创建托管 key、回写 allowed_groups / balance、再执行订阅分配
@@ -145,7 +157,7 @@
- access closure / import runtime artifact / reconcile rerun payload 都会持久化 `completion_ok/completion_status/completion_type/completion_preview`
10. current-code remote43 验收脚本已补 upstream API 证据层
- `scripts/import_remote43_provider.sh` 会直探 provider `base_url` 对应的 upstream `/models``/chat/completions`
- `scripts/acceptance/import_remote43_provider.sh` 会直探 provider `base_url` 对应的 upstream `/models``/chat/completions`
- 新增 `21-summary.json`,用于把 completion 失败自动分流成 `host_compatibility_gap``upstream_key_quota_issue`
11. patched CRM external validation 已完成
@@ -191,7 +203,7 @@
- `internal/provision`: `79.4%`
- `internal/store/sqlite`: `77.9%`
- `go test ./tests/integration/... -count=1`
- `bash ./scripts/test_real_host_scripts.sh`
- `bash ./scripts/test/test_real_host_scripts.sh`
## 当前保留的最终证据
@@ -244,7 +256,7 @@
2. 部署与环境限制
- 标准多阶段 Dockerfile 在受限网络环境下仍不稳
- 当前推荐 `scripts/build_local_image.sh` + `Dockerfile.local`
- 当前推荐 `scripts/deploy/build_local_image.sh` + `Dockerfile.local`
3. official provider 验证矩阵
- official MiniMax 当前 live 样本已证明模板链路可用,但验证 key 命中 upstream `429`

View File

@@ -19,7 +19,7 @@ This document covers known limitations that operators should be aware of before
### 3. Standard Multi-stage Docker Build Still Depends on Outbound Module Download
- `Dockerfile.local` has been validated as the recommended proxy-safe build path.
- `scripts/build_local_image.sh` now prebuilds the Linux binary on the host and produces `sub2api-cn-relay-manager:local` reliably in this environment.
- `scripts/deploy/build_local_image.sh` now prebuilds the Linux binary on the host and produces `sub2api-cn-relay-manager:local` reliably in this environment.
- The standard multi-stage `Dockerfile` still requires outbound Go module download from inside the container build context; in restricted networks, prefer the local-image path.
## Accepted Design Trade-offs

View File

@@ -0,0 +1,358 @@
# OpenClaw 外部真实验证
日期2026-05-26
## 目的
这份文档补齐两类长期缺口:
1. `sub2api-cn-relay-manager` 之外的最终使用面验证
- 即真实用户拿到宿主 key 后,在本机 `OpenClaw` 上是否真的可用
2. OpenClaw 本地运行时补丁的可复用操作流程
- 包括 `MiniMax` 的代理兼容补丁
- 以及升级后如何自动提醒重新打补丁
它不替代:
- `docs/REAL_HOST_ACCEPTANCE_RUNBOOK.md`
- 负责 `relay-manager -> host -> upstream` 三段验收
- 本文
- 负责 `user key -> OpenClaw -> public endpoint` 最后一段真实使用验证
## 当前结论
截至 2026-05-27公网根端点已经切到 patched host可统一按 OpenAI 兼容根地址使用:
- `base_url=https://sub.tksea.top`
- 若客户端强制要求显式 `/v1`,则使用 `https://sub.tksea.top/v1`
OpenClaw 当前外部真实验证结论如下:
| OpenClaw provider | model | base_url | 结果 | 说明 |
| ----------------- | ------------------------ | ---------------------------- | ---- | ------------------------------------------------------- |
| `tksea` | `kimi-k2.6` | `https://sub.tksea.top/kimi` | PASS | 已在 OpenClaw `agent` 路径验证通过 |
| `tksea-gpt` | `gpt-5.4` | `https://sub.tksea.top/v1` | PASS | `openclaw infer model run --local` 返回 `pong` |
| `tksea-gpt` | `gpt-5.4-mini` | `https://sub.tksea.top/v1` | PASS | `openclaw infer model run --local` 返回 `pong` |
| `tksea-gpt` | `gpt-5.5` | `https://sub.tksea.top/v1` | FAIL | upstream 当前返回 `503 Service temporarily unavailable` |
| `tksea-minimax` | `MiniMax-M2.5-highspeed` | `https://sub.tksea.top/v1` | PASS | 对应 remote43 导入 `minimax-53hk` 后的公网消费口径 |
| `tksea-minimax` | `MiniMax-M2.7-highspeed` | `https://sub.tksea.top/v1` | PASS | 对应 remote43 导入 `minimax-53hk` 后的公网消费口径 |
| `minimax53hk` | `MiniMax-M2.5-highspeed` | `https://api.53hk.cn/v1` | PASS | 本地补丁后恢复的 53hk 直连口径 |
| `minimax53hk` | `MiniMax-M2.7-highspeed` | `https://api.53hk.cn/v1` | PASS | 本地补丁后恢复的 53hk 直连口径 |
与 relay-manager pack 内 `provider_id` 的映射关系当前明确为:
- `openai-zhongzhuan``tksea-gpt`
- `minimax-53hk``tksea-minimax`
- `deepseek-chat-official``deepseek-official`2026-05-27 已补齐 `auth-profiles.json``openclaw infer model run --model \"deepseek-official/deepseek-chat\" --prompt 'Reply with exactly OK' --json` 返回 `OK`
## 前置条件
### 远端入口
- 用户注册页:`https://sub.tksea.top/portal/`
- 旧地址:`https://sub.tksea.top/kimi-portal/`
- 当前应作为兼容跳转入口保留,而不是继续作为正式主地址
- 宿主 OpenAI 兼容入口:`https://sub.tksea.top`
### OpenClaw 本地要求
- 已安装 `OpenClaw`
- 本机代理环境可用:
- `HTTP_PROXY`
- `HTTPS_PROXY`
- 已写入至少一种测试 key
- `tksea`
- `tksea-gpt`
- `tksea-minimax`
- `minimax53hk`
### 已存在的本地补丁脚本
下列脚本当前位于操作者本机,不在本仓库内版本化;本仓库只记录它们的使用方法与验收口径:
- `~/.openclaw/bin/apply-openclaw-minimax-proxy-fix.sh`
- `~/.openclaw/bin/openclaw-minimax-post-upgrade-check.sh`
- `~/.openclaw/bin/openclaw-minimax-proxy-reminder.sh`
- `~/.openclaw/bin/install-openclaw-minimax-reminder-cron.sh`
## 根因与补丁范围
本轮 `MiniMax` 的 OpenClaw 故障,不是模型名大小写,也不是 allowlist 漏配导致。
真实根因是:
- `curl` 可以通过系统 `HTTP(S)_PROXY` 正常访问 `53hk``tksea``MiniMax`
-`OpenClaw -> pi-ai -> openai-node` 默认没有继承同样的代理行为
- 因此在本地 one-shot 路径里被吞成:
- `No text output returned`
- `Connection error`
当前补丁做法是:
- 对本机安装的 `pi-ai` 运行时文件注入 `EnvHttpProxyAgent`
- 让 OpenAI SDK 使用带系统代理的 `fetch`
补丁目标文件:
- `~/.local/lib/node_modules/openclaw/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js`
注意:
- 这不是本仓库源码补丁
- `OpenClaw` 升级后,这个补丁可能会被覆盖
## 用例设计
### 用例 1提醒任务已安装
目的:
- 确保 OpenClaw 升级后,系统会自动提醒是否需要重新打补丁
执行:
```bash
crontab -l
```
预期:
- 输出中包含:
- `# BEGIN openclaw-minimax-proxy-reminder`
- `@reboot sleep 180 && "~/.openclaw/bin/openclaw-minimax-proxy-reminder.sh" ...`
- `*/30 * * * * "~/.openclaw/bin/openclaw-minimax-proxy-reminder.sh" ...`
### 用例 2补丁状态诊断
目的:
- 在升级后先判定当前是否还带着代理补丁
执行:
```bash
~/.openclaw/bin/apply-openclaw-minimax-proxy-fix.sh doctor
```
预期:
- 输出 `OpenClaw` 版本
- 输出目标 `pi-ai` 文件路径
- 输出当前 `patched/not_patched`
- 输出 `HTTP_PROXY/HTTPS_PROXY/NO_PROXY`
- 输出备份列表
### 用例 3升级后一键恢复
目的:
- 在 OpenClaw 升级后,自动完成 `doctor -> apply -> verify`
执行:
```bash
~/.openclaw/bin/openclaw-minimax-post-upgrade-check.sh
```
预期:
- `doctor` 正常输出
- `apply` 在已打补丁时表现为幂等
- `verify` 最终四条 `MiniMax` smoke 全部通过
### 用例 453hk MiniMax 直连恢复
目的:
- 验证官方宿主之外,老的 `53hk` 线路在 OpenClaw 本地也已恢复
执行:
```bash
openclaw infer model run --local \
--model "minimax53hk/MiniMax-M2.5-highspeed" \
--prompt "reply with pong only" \
--json
openclaw infer model run --local \
--model "minimax53hk/MiniMax-M2.7-highspeed" \
--prompt "reply with pong only" \
--json
```
预期:
- `ok=true`
- 输出文本为 `pong`
### 用例 5tksea MiniMax 真实调用
目的:
- 验证 patched host 暴露的 `MiniMax` 公网入口,已经可被 OpenClaw 正常消费
执行:
```bash
openclaw infer model run --local \
--model "tksea-minimax/MiniMax-M2.5-highspeed" \
--prompt "reply with pong only" \
--json
openclaw infer model run --local \
--model "tksea-minimax/MiniMax-M2.7-highspeed" \
--prompt "reply with pong only" \
--json
```
预期:
- `ok=true`
- 输出文本为 `pong`
### 用例 6tksea GPT 可用模型验证
目的:
- 区分“GPT 配置是否正确”与“某个具体模型当前 upstream 是否可用”
执行:
```bash
openclaw infer model run --local \
--model "tksea-gpt/gpt-5.4" \
--prompt "reply with pong only" \
--json
openclaw infer model run --local \
--model "tksea-gpt/gpt-5.4-mini" \
--prompt "reply with pong only" \
--json
```
预期:
- `gpt-5.4` 返回 `pong`
- `gpt-5.4-mini` 返回 `pong`
### 用例 7tksea GPT 不稳定模型验证
目的:
- 把“不稳定模型”显式记录为当前运行态限制,而不是笼统地宣称 GPT 全量可用
执行:
```bash
openclaw infer model run --local \
--model "tksea-gpt/gpt-5.5" \
--prompt "reply with pong only" \
--json
```
预期:
- 当前基线结果是失败
- 错误为:
- `503 Service temporarily unavailable`
### 用例 8DeepSeek 官方 OpenClaw 配置缺口探测
目的:
- 区分“remote43 上 `deepseek-chat-official` 已导入并能 completion”与“本机 OpenClaw 已经可直接消费”这两个结论
执行:
```bash
openclaw infer model run --local \
--model "deepseek-official/deepseek-chat" \
--prompt "reply with pong only" \
--json
```
预期:
- 当前基线结果是失败
- 失败点不是模型推理,而是本机 auth/profile 尚未就绪
- 典型错误:
- `No API key found for provider "deepseek-official"`
## 推荐执行顺序
每次 OpenClaw 升级后,按下面顺序执行:
1. 检查提醒任务
```bash
crontab -l
```
2. 先诊断当前状态
```bash
~/.openclaw/bin/apply-openclaw-minimax-proxy-fix.sh doctor
```
3. 再执行升级后一键恢复
```bash
~/.openclaw/bin/openclaw-minimax-post-upgrade-check.sh
```
4. 验证 `tksea-gpt` 当前可用模型
```bash
openclaw infer model run --local --model "tksea-gpt/gpt-5.4" --prompt "reply with pong only" --json
openclaw infer model run --local --model "tksea-gpt/gpt-5.4-mini" --prompt "reply with pong only" --json
```
5. 验证 `tksea-minimax`
```bash
openclaw infer model run --local --model "tksea-minimax/MiniMax-M2.5-highspeed" --prompt "reply with pong only" --json
openclaw infer model run --local --model "tksea-minimax/MiniMax-M2.7-highspeed" --prompt "reply with pong only" --json
```
## 诊断分流
### `/v1/models` 能出模型,但 OpenClaw 本地仍报 `Connection error`
优先排查:
1. `doctor` 是否显示 `patched`
2. 当前 shell 是否存在 `HTTP_PROXY` / `HTTPS_PROXY`
3. OpenClaw 是否刚升级,导致 `pi-ai` patch 丢失
### GPT 某个模型失败,但同组其他模型正常
优先判断为:
- 特定模型 upstream 不稳定
- 不要误判成整个 `tksea-gpt` provider 失效
当前基线就是:
- `gpt-5.4`PASS
- `gpt-5.4-mini`PASS
- `gpt-5.5`FAIL503
### MiniMax API 直连可用,但 OpenClaw 本地失败
优先判断为:
- OpenClaw 本地运行时代理兼容问题
- 不是宿主 key、也不是 relay-manager 导入问题
## 结论口径
截至 2026-05-26当前可以对外采用下面这套简化口径
1. patched host 公网根入口已可直接给 OpenAI 兼容客户端使用:
- `https://sub.tksea.top`
2. OpenClaw 的 `MiniMax` 本地运行时兼容问题已经通过代理补丁恢复
3. `tksea-minimax` 当前可用
4. `tksea-gpt` 当前不是“全模型可用”,而是:
- `gpt-5.4` 可用
- `gpt-5.4-mini` 可用
- `gpt-5.5` 当前仍需视 upstream 状态单独观察

View File

@@ -19,13 +19,13 @@
- 汇总证据:`artifacts/real-host-acceptance/20260521_064910_completion_smoke_calibration.md`
- 调通细节与经验沉淀:`docs/REAL_HOST_ACCEPTANCE_LEARNINGS.md`
- 2026-05-21 当前代码已关闭“models-only 假 ready”问题access closure / import / reconcile rerun 现在都会在 `/v1/models` 成功后追加一次最小 `POST /v1/chat/completions` smokecompletion 失败的链路不会再被记成 ready。
- `scripts/import_remote43_provider.sh` 已新增 upstream `/models``/chat/completions` 直探,额外产出 `17-upstream-*``19-upstream-*``21-summary.json`,用于把失败分流为 `host_compatibility_gap``upstream_key_quota_issue`
- `scripts/acceptance/import_remote43_provider.sh` 已新增 upstream `/models``/chat/completions` 直探,额外产出 `17-upstream-*``19-upstream-*``21-summary.json`,用于把失败分流为 `host_compatibility_gap``upstream_key_quota_issue`
- patched CRM live rerun 已验证:
- MiniMax 最新 `artifacts/real-host-acceptance/20260521_191418_remote43_minimax_key_import` 已提升到 `batch_status=succeeded``provider_status=active`
- DeepSeek 最新 `artifacts/real-host-acceptance/20260521_201509_remote43_deepseek_key_import` 也已提升到 `batch_status=succeeded``provider_status=active`
- latest-head `self_service` 标准 fresh-host 验收 `artifacts/real-host-acceptance/20260521_210403` 已落成 `batch_status=succeeded``access_status=self_service_ready``provider_status=active`,且 `latest_access_status=fully_ready`
- 本轮真正收口的根因修复是:账号 probe SSE 错误消息已保留CRM 会显式向 `/api/v1/admin/accounts/:id/test``provider.SmokeTestModel`,瞬时 `429` probe 现在会按 advisory 处理,不再把已通过 gateway closure 的账号批次错误降级,同时 self-service 的 gateway probe 已从错误的 `x-api-key` 切到真实宿主要求的 `Authorization: Bearer`
- 代码/本地运行态门禁已于 2026-05-21 在这轮补丁后再次独立复跑:`gofmt -l .``go vet ./...``go test ./... -count=1``go test -race ./... -count=1``go test -cover ./internal/... -count=1``go test ./tests/integration/... -count=1``bash ./scripts/test_real_host_scripts.sh` 全通过。
- 代码/本地运行态门禁已于 2026-05-21 在这轮补丁后再次独立复跑:`gofmt -l .``go vet ./...``go test ./... -count=1``go test -race ./... -count=1``go test -cover ./internal/... -count=1``go test ./tests/integration/... -count=1``bash ./scripts/test/test_real_host_scripts.sh` 全通过。
## 当前门控结论
@@ -43,8 +43,8 @@
| OpenAPI | ✅ SYNCED | `docs/openapi.yaml` 已补当前控制面端点 |
| Local runtime smoke | ✅ PASS | `go build ./cmd/{server,cli}``GET /healthz``GET /api/hosts` |
| Local OCI image | ✅ PASS | `docker build -f Dockerfile.local -t sub2api-cn-relay-manager:local .` |
| Real-host acceptance tooling | ✅ READY | `docs/REAL_HOST_ACCEPTANCE_RUNBOOK.md` + `scripts/real_host_acceptance.sh` |
| Harness regression self-check | ✅ PASS | `bash ./scripts/test_real_host_scripts.sh` |
| Real-host acceptance tooling | ✅ READY | `docs/REAL_HOST_ACCEPTANCE_RUNBOOK.md` + `scripts/acceptance/real_host_acceptance.sh` |
| Harness regression self-check | ✅ PASS | `bash ./scripts/test/test_real_host_scripts.sh` |
| `self_service` 真实宿主 latest-head fresh host 复验 | ✅ PASS | `artifacts/real-host-acceptance/20260521_210403``05-import.json` = `succeeded/self_service_ready/active``07-access-status.json` = `latest_access_status=fully_ready` |
| `subscription` 真实宿主 patched fresh host 复验 | ✅ PASS | MiniMax`artifacts/real-host-acceptance/20260521_191418_remote43_minimax_key_import`DeepSeek`artifacts/real-host-acceptance/20260521_201509_remote43_deepseek_key_import`;两条 provider 都已证明 current-code 在真实 fresh-host 上可闭环到 `batch_status=succeeded``provider_status=active` |
| stale CRM / channel pricing 缺口 | ✅ CLOSED | 宿主 `GET /api/v1/admin/channels/5``/channels/4` 已返回非空 `model_pricing` + `model_mapping` |
@@ -69,9 +69,9 @@
- 本地 HTTP smoke 与 `Dockerfile.local` 容器构建已验证通过
4. 补齐上线前执行工具
- 新增 `scripts/build_local_image.sh`,固化本地/代理环境的镜像构建路径
- 新增 `scripts/deploy/build_local_image.sh`,固化本地/代理环境的镜像构建路径
- 新增 `docs/REAL_HOST_ACCEPTANCE_RUNBOOK.md`
- 新增 `scripts/real_host_acceptance.sh`,把真实宿主验收固化为可落盘 artifact 的流程
- 新增 `scripts/acceptance/real_host_acceptance.sh`,把真实宿主验收固化为可落盘 artifact 的流程
5. 当前代码后的最新事实
- 宿主 admin 侧直接复核仍证明 channel `billing_model_source=channel_mapped``restrict_models=true``model_pricing/model_mapping` 已能被正确写入
@@ -93,7 +93,7 @@
### P2 已接受技术债务
- `internal/worker` 已抽出通用 polling runner当前 batch-import runtime 与后台 reconcile 都已接入;调度模型仍是固定间隔 polling而不是完整 jobs/reconcile 平台
- CLI `run*` 真实链路函数未做系统性 mock 单测
- 标准多阶段 `Dockerfile` 在受限网络下仍依赖容器内联网拉取 Go modules本地部署默认走 `scripts/build_local_image.sh`
- 标准多阶段 `Dockerfile` 在受限网络下仍依赖容器内联网拉取 Go modules本地部署默认走 `scripts/deploy/build_local_image.sh`
- `subscription` 这条 provider matrix 已通过;剩余待补的是 latest-head `self_service` fresh-host 复验,而不是继续替换 provider key
## 最短上线闭环

166
docs/PROJECT_STRUCTURE.md Normal file
View File

@@ -0,0 +1,166 @@
# 项目目录说明
日期2026-05-27
## 目的
这份文档用于回答两个问题:
1. 当前仓库各一级目录分别负责什么
2. 新增文件应该放到哪里,避免继续把运行时脚本、部署资产、验收证据混在一起
它不替代 `README.md`,而是补充更细的目录职责说明。
## 一级目录
### `cmd/`
程序入口:
- `cmd/server`
- 控制面 HTTP 服务入口
- `cmd/cli`
- 导入、overlay、验证等命令行入口
### `internal/`
控制面核心实现,按职责拆分:
- `internal/access`
- access closure、自愈、gateway 验证
- `internal/app`
- HTTP API、bootstrap、后台任务
- `internal/batch`
- batch import 请求与状态投影
- `internal/config`
- 配置装载
- `internal/host/sub2api`
- 宿主适配器
- `internal/overlay`
- host overlay 执行器
- `internal/pack`
- pack 装载、校验、overlay 解析
- `internal/probe`
- upstream / host smoke probes
- `internal/provision`
- import / preview / rollback / reconcile 编排
- `internal/reconcile`
- 后台对账
- `internal/store`
- SQLite repo 与 migrations
- `internal/testutil`
- 测试辅助
- `internal/worker`
- 后台 runner
### `packs/`
版本化模型包资产:
- `packs/openai-cn-pack`
- provider manifests
- checksums
- overlay metadata
这层只放 pack 资产,不放远端站点静态页。
### `deploy/`
面向部署目标的静态资产或配置模板。
当前已经纳入:
- `deploy/tksea-portal/index.html`
- `sub.tksea.top/portal/` 静态页
- `deploy/tksea-portal/nginx.sub.tksea.top.conf.example`
- 对应 Nginx 路由示例
这层的规则是:
- 放“部署产物模板”
- 不放需要编译的 Go 代码
- 不放临时 `/tmp` 产物
### `scripts/`
运维、验收、部署脚本,当前已经按用途拆成三层目录:
- `scripts/deploy/`
- 部署与环境拉起脚本
- 例如 `build_local_image.sh``setup_remote43_patched_stack.sh``deploy_tksea_portal.sh`
- `scripts/acceptance/`
- 真实宿主验收与证据处理脚本
- 例如 `real_host_acceptance.sh``import_remote43_provider.sh``check_deepseek_completion_split.sh`
- `scripts/test/`
- 脚本资产回归
- 例如 `test_real_host_scripts.sh``test_tksea_portal_assets.sh`
规则:
- 只放可执行运维脚本
- 新脚本必须先判断属于 `deploy/``acceptance/` 还是 `test/`
- 脚本依赖的静态模板应尽量放到 `deploy/``docs/`
### `docs/`
所有长期保留文档:
- 真相入口
- 执行板
- 验收 runbook
- provider 矩阵
- 外部 OpenClaw 验证
- 目录与部署说明
### `tests/`
集成测试套件:
- `tests/integration`
### `artifacts/`
真实验收产物与归档证据。
规则:
- `artifacts/real-host-acceptance/`
- 当前最终证据
- `artifacts/real-host-acceptance-archive/`
- 历史调试样本与归档
不要把部署模板、静态页、脚本说明放到这里。
### `web/`
保留给未来管理端前端实现。
当前公网 portal 已经独立作为 `deploy/tksea-portal/` 静态资产纳管,不应误放进 `web/`,因为它不是控制面管理后台。
## 当前推荐放置规则
新增文件时,优先按下面规则归类:
- 新的 provider / pack 元数据
-`packs/`
- 新的 Go 业务逻辑
-`internal/`
- 新的 CLI 或 server 入口
-`cmd/`
- 新的线上静态部署页 / 反向代理模板
-`deploy/`
- 新的运维或验收命令脚本
-`scripts/deploy``scripts/acceptance``scripts/test`
- 新的长期说明文档
-`docs/`
- 新的验收证据
-`artifacts/`
## 当前整理结果
截至 2026-05-27最近一轮目录整理主要做了三件事
1. 把原来只存在 `/tmp``sub.tksea.top` portal 静态页与 Nginx 规则正式纳入仓库
2. 把 portal 部署动作收口到 `scripts/deploy/deploy_tksea_portal.sh`
3.`scripts/` 从全平铺整理为 `deploy/``acceptance/``test/` 三层,减少脚本入口混杂
4. 把“公网 portal / OpenClaw / remote43 验收”相关说明分别挂回 `deploy/``scripts/``docs/`

View File

@@ -37,33 +37,46 @@
- 高频误判点
- 推荐诊断顺序
7. [OPENCLAW_EXTERNAL_VALIDATION.md](./OPENCLAW_EXTERNAL_VALIDATION.md)
- OpenClaw 最后一跳真实使用验证
- 升级后补丁自检与 cron 提醒
- `tksea` / `53hk` 多模型运行态口径
8. [PROJECT_STRUCTURE.md](./PROJECT_STRUCTURE.md)
- 当前仓库目录职责说明
- 新增文件该放在哪一层
9. [../scripts/README.md](../scripts/README.md)
- `scripts/deploy``scripts/acceptance``scripts/test` 的入口说明
- 继续整理脚本或追脚本回归时先看这里
## 背景/设计文档
6. [PRD.md](./PRD.md)
10. [PRD.md](./PRD.md)
- PRD 首版范围
7. [TDD_PLAN.md](./TDD_PLAN.md)
11. [TDD_PLAN.md](./TDD_PLAN.md)
- 测试设计与实现计划
8. [2026-05-12-sub2api-cn-relay-manager-solution.md](./2026-05-12-sub2api-cn-relay-manager-solution.md)
12. [2026-05-12-sub2api-cn-relay-manager-solution.md](./2026-05-12-sub2api-cn-relay-manager-solution.md)
- 早期方案设计与宿主接口理解
9. [DEPLOYMENT.md](./DEPLOYMENT.md)
13. [DEPLOYMENT.md](./DEPLOYMENT.md)
- 部署说明
10. [KNOWN_LIMITATIONS.md](./KNOWN_LIMITATIONS.md)
14. [KNOWN_LIMITATIONS.md](./KNOWN_LIMITATIONS.md)
- 当前限制项
11. [plans/2026-05-12-sub2api-cn-relay-manager-implementation-plan.md](./plans/2026-05-12-sub2api-cn-relay-manager-implementation-plan.md)
15. [plans/2026-05-12-sub2api-cn-relay-manager-implementation-plan.md](./plans/2026-05-12-sub2api-cn-relay-manager-implementation-plan.md)
- 初始实现计划
## 历史快照文档(只可参考,不可直接当当前真相)
12. [2026-05-18-PRODUCTION_READINESS_REVIEW.md](./2026-05-18-PRODUCTION_READINESS_REVIEW.md)
16. [2026-05-18-PRODUCTION_READINESS_REVIEW.md](./2026-05-18-PRODUCTION_READINESS_REVIEW.md)
- 历史审查快照
- 用来看当时发现了哪些系统性问题
13. [2026-05-18-PRODUCTION_REMEDIATION_TASK_BOARD.md](./2026-05-18-PRODUCTION_REMEDIATION_TASK_BOARD.md)
17. [2026-05-18-PRODUCTION_REMEDIATION_TASK_BOARD.md](./2026-05-18-PRODUCTION_REMEDIATION_TASK_BOARD.md)
- 历史整改任务板
- 用来看 2026-05-18 那一轮是如何收口的

View File

@@ -16,6 +16,9 @@
- 适合快速确认红线、三层证据和最短诊断顺序。
5. `docs/REAL_HOST_ACCEPTANCE_LEARNINGS.md`
- 看已经调通的细节、典型误判点、推荐诊断顺序。
6. `docs/OPENCLAW_EXTERNAL_VALIDATION.md`
- 当真实宿主、公网域名与最终用户 key 已经打通后,继续看这份。
- 它定义的是 OpenClaw 最后一跳真实使用验证与升级后自检,不再局限于 relay-manager/host 导入层。
## 目标
@@ -49,7 +52,7 @@
```bash
cd /path/to/sub2api-cn-relay-manager
bash ./scripts/test_real_host_scripts.sh
bash ./scripts/test/test_real_host_scripts.sh
```
说明:
@@ -60,7 +63,7 @@ bash ./scripts/test_real_host_scripts.sh
```bash
cd /path/to/sub2api-cn-relay-manager
scripts/build_local_image.sh
scripts/deploy/build_local_image.sh
```
默认输出:
@@ -76,7 +79,7 @@ cd /path/to/sub2api-cn-relay-manager
HOST_BINARY=/path/to/sub2api-patched \
CRM_BINARY=./server \
bash ./scripts/setup_remote43_patched_stack.sh
bash ./scripts/deploy/setup_remote43_patched_stack.sh
```
脚本会:
@@ -98,7 +101,7 @@ bash /tmp/remote43-patched-stack-18139.tunnel.sh
然后再跑:
```bash
bash ./scripts/import_remote43_provider.sh kimi-a7m kimi-k2.6 A7M_KIMI_API_KEY /path/to/keyfile
bash ./scripts/acceptance/import_remote43_provider.sh kimi-a7m kimi-k2.6 A7M_KIMI_API_KEY /path/to/keyfile
```
### 3. 先 dry-run 检查真实验收参数
@@ -115,7 +118,7 @@ KEYS=sk-live-1,sk-live-2 \
ACCESS_MODE=self_service \
ACCESS_API_KEY=user-gateway-key \
DRY_RUN=1 \
bash ./scripts/real_host_acceptance.sh
bash ./scripts/acceptance/real_host_acceptance.sh
```
### 4. 执行真实验收
@@ -131,7 +134,7 @@ PROVIDER_ID=deepseek \
KEYS=sk-live-1,sk-live-2 \
ACCESS_MODE=self_service \
ACCESS_API_KEY=user-gateway-key \
bash ./scripts/real_host_acceptance.sh
bash ./scripts/acceptance/real_host_acceptance.sh
```
### 5. 订阅模式示例
@@ -148,7 +151,7 @@ KEYS=sk-live-1 \
ACCESS_MODE=subscription \
SUBSCRIPTION_USERS=user-a,user-b \
SUBSCRIPTION_DAYS=30 \
bash ./scripts/real_host_acceptance.sh
bash ./scripts/acceptance/real_host_acceptance.sh
```
### 6. 导入后自动补 access 前置(可选)
@@ -158,7 +161,7 @@ bash ./scripts/real_host_acceptance.sh
```bash
AFTER_IMPORT_HOOK_COMMAND='bash /path/to/host-access-hook.sh' \
... \
scripts/real_host_acceptance.sh
scripts/acceptance/real_host_acceptance.sh
```
hook 执行时会额外导出:
@@ -176,6 +179,31 @@ hook 执行时会额外导出:
- `05b-after-import-hook.stdout.txt`
- `05b-after-import-hook.stderr.txt`
### 7. OpenClaw 最后一跳外部验证
当你已经确认:
- remote43 或本地 patched host 验收通过
- 公网根地址已暴露
- 真实用户可以自助注册并创建 key
不要在 `21-summary.json` 停止,继续追加一轮 OpenClaw 外部真实验证:
```bash
~/.openclaw/bin/apply-openclaw-minimax-proxy-fix.sh doctor
~/.openclaw/bin/openclaw-minimax-post-upgrade-check.sh
openclaw infer model run --local --model "tksea-gpt/gpt-5.4" --prompt "reply with pong only" --json
openclaw infer model run --local --model "tksea-gpt/gpt-5.4-mini" --prompt "reply with pong only" --json
openclaw infer model run --local --model "tksea-minimax/MiniMax-M2.5-highspeed" --prompt "reply with pong only" --json
openclaw infer model run --local --model "tksea-minimax/MiniMax-M2.7-highspeed" --prompt "reply with pong only" --json
```
当前推荐把这一步的口径记录到:
- `docs/OPENCLAW_EXTERNAL_VALIDATION.md`
- 或对应批次 artifact 的补充说明中
## 产物
脚本会把每一步 JSON 响应落到:
@@ -229,7 +257,7 @@ remote43 / 本地缩圈脚本若需要额外证据,会在同目录追加:
- `21-summary.json` / `99-semantic-summary.json`(推荐长期保留的摘要证据)
- 若你是在清理旧目录,而不是生成新验收产物,优先运行:
```bash
python3 scripts/migrate_historical_artifacts.py artifacts/real-host-acceptance
python3 scripts/acceptance/migrate_historical_artifacts.py artifacts/real-host-acceptance
```
它会把主目录中的历史敏感材料迁到 `artifacts/real-host-acceptance-sensitive/`,并在原目录生成安全摘要版。
- 历史目录迁移脚本当前已覆盖两层:
@@ -281,7 +309,7 @@ remote43 / 本地缩圈脚本若需要额外证据,会在同目录追加:
1. 默认会执行 rollback smoke若当前环境不允许回滚设置
```bash
SKIP_ROLLBACK=1 scripts/real_host_acceptance.sh
SKIP_ROLLBACK=1 scripts/acceptance/real_host_acceptance.sh
```
2. `PACK_PATH` 必须是控制面进程可读路径,不是用户本地概念路径。
@@ -292,13 +320,13 @@ SKIP_ROLLBACK=1 scripts/real_host_acceptance.sh
7. `self_service` 验证除普通用户 key 外,还需要该 key 绑定目标 group若目标 group 是标准计费组,还需要用户侧具备可用余额,否则 `/v1/models` 可能从“未授权”转为 `INSUFFICIENT_BALANCE`。
8. `subscription` 验证需要目标 group 本身是 `subscription` 类型,并且完成“普通用户订阅分配 + 普通用户 key 绑定该 group”仅有管理员主体或未绑定 key 不足以通过 `/v1/models`。
9. 若需要验证 `reconcile` 收敛,优先在干净宿主场景或隔离 group 下执行,避免历史残留资源把结果污染成 `status=drifted` / `extra_count>0`。
10. `scripts/import_remote43_provider.sh` 现已内置 remote43 的 subscription 验收补全动作:会根据 import batch 自动解析目标 group执行“普通用户最低余额补齐 + key/group 绑定 + user_subscriptions upsert + 定向 Redis 缓存失效auth / balance / subscription并把 SQL / host state 证据写入 artifact 目录。
10. `scripts/acceptance/import_remote43_provider.sh` 现已内置 remote43 的 subscription 验收补全动作:会根据 import batch 自动解析目标 group执行“普通用户最低余额补齐 + key/group 绑定 + user_subscriptions upsert + 定向 Redis 缓存失效auth / balance / subscription并把 SQL / host state 证据写入 artifact 目录。
11. 当 CRM 进程与 operator 到 host 的访问地址不一致时,优先显式设置 `CRM_HOST_BASE`,避免把 CRM 侧探测地址和本地运维隧道地址混用。
12. 对 `Upstream service temporarily unavailable` 一类 502不要先认定是上游聊天链路故障先看脚本落盘的 `09-models.headers.txt` / `10-models.body.json`。若 `/v1/models` 已返回了别的 provider 模型集(例如 GPT 系列而不是预期的 DeepSeek/Minimax 模型),先检查普通用户 key/group 绑定,也要检查 CRM 导入时是否把 provider 的 `channel_template.model_mapping`、`restrict_models`、`billing_model_source` 一并下发到宿主 channel。
13. subscription 场景里closure 最终用于 gateway probe 的 key 是宿主侧 managed key不一定是请求体里外部传入的 `ACCESS_API_KEY`。如果你拿原始 key 直打 `/v1/models` 收到 `403 not assigned to any group`,先不要判定 CRM 主链路失败。
14. 对“既有 channel 没自动补 `model_pricing`”这类 live 现象,先核对在线 CRM 进程的启动时间与 git 提交时间;之前 MiniMax 的该现象最终被确认是 stale CRM 进程导致,而不是源码缺逻辑。
15. 当 CRM 切换到本机运行时,`PACK_PATH` 也必须切换到控制面本机可读路径;继续沿用远端 `/home/ubuntu/...` 会触发 `stat pack path ... no such file or directory`,这是验收 harness 参数问题,不是导入业务逻辑问题。
16. 若要把 DeepSeek 的“host `/v1/models`=200 但 host `/v1/chat/completions`=502而 upstream 直探 `/chat/completions`=200”做成可提 issue 的最小复现,直接运行 `scripts/check_deepseek_completion_split.sh`。它会同时落盘 host `/v1/models`、host `/v1/chat/completions`、upstream `/chat/completions` 三层证据,并在 `summary.json` 里给出 `host_compatibility_gap|upstream_key_quota_issue|unknown` 分类。
16. 若要把 DeepSeek 的“host `/v1/models`=200 但 host `/v1/chat/completions`=502而 upstream 直探 `/chat/completions`=200”做成可提 issue 的最小复现,直接运行 `scripts/acceptance/check_deepseek_completion_split.sh`。它会同时落盘 host `/v1/models`、host `/v1/chat/completions`、upstream `/chat/completions` 三层证据,并在 `summary.json` 里给出 `host_compatibility_gap|upstream_key_quota_issue|unknown` 分类。
17. 若 reconcile 面对的是“非 latest batch 的同前缀旧账号”,最新代码会把它们记为 `stale_noise_count` / `stale_noise_accounts` 并保留 `raw_extra_count`,而不是继续把它们算进 `extra_count` 造成 drift 误报;因此应优先看 `extra_count` 是否归零,再看 `probe_failures`/`access_status` 是否仍有真实异常。
18. self_service 场景里,普通用户 gateway key 访问宿主 `/v1/models` / `/v1/chat/completions` 时,真实语义是 `Authorization: Bearer <gateway-key>`;若 CRM 的 self_service closure 仍显示 `401/403 broken`,优先排查 gateway probe 是否错误复用了 `x-api-key`。
19. fresh-host 管理员 bearer token 过期时,最前面的 `POST /api/hosts` / `probe-host` 可能直接表现成 CRM 侧 `502`。遇到这类现象,先刷新 host bearer token再继续验收不要先把它归因为最新代码故障。

View File

@@ -44,7 +44,7 @@
当历史 `artifacts/real-host-acceptance/` 目录里仍残留旧版敏感材料时,使用:
```bash
python3 scripts/migrate_historical_artifacts.py artifacts/real-host-acceptance
python3 scripts/acceptance/migrate_historical_artifacts.py artifacts/real-host-acceptance
```
默认行为:

View File

@@ -9,7 +9,7 @@
当前 gate 升到 `APPROVED` 的原因是:
1. 代码侧已关闭“只靠 `/v1/models` 就把 access 标成 ready”的假阳性当前 ready 必须同时通过 `/v1/models``/v1/chat/completions` smoke
2. `scripts/import_remote43_provider.sh` 已补上 upstream `/models``/chat/completions` 直探,并落盘 `21-summary.json` 做根因分类
2. `scripts/acceptance/import_remote43_provider.sh` 已补上 upstream `/models``/chat/completions` 直探,并落盘 `21-summary.json` 做根因分类
3. account `credentials.model_mapping`、channel `model_mapping/model_pricing`、managed key 视角 `/v1/models` 都已有 live 证据
4. completion-gated 补丁已经在 fresh-host 上重跑验证通过control plane 会把 completion 失败正确落成 `broken`
5. MiniMax account probe 假失败也已被最新补丁关闭: