Files
sub2api-cn-relay-manager/docs/EXECUTION_BOARD.md
2026-05-28 20:25:46 +08:00

48 KiB
Raw Blame History

sub2api-cn-relay-manager 执行板

日期2026-05-22 当前 GateAPPROVED代码门禁已通过并且 2026-05-21 已继续收掉 account probe、gateway probe 认证语义和 latest-head self_service fresh-host 复验的剩余问题。最新 MiniMax 53hk fresh-host 验收 artifacts/real-host-acceptance/20260521_191418_remote43_minimax_key_import/21-summary.json、DeepSeek 2166 subscription fresh-host 验收 artifacts/real-host-acceptance/20260521_201509_remote43_deepseek_key_import/21-summary.json、以及 latest-head self_service 标准 fresh-host 验收 artifacts/real-host-acceptance/20260521_210403/05-import.json / 07-access-status.json 已共同证明:subscriptionself_service 主链路都能在真实 fresh host 上闭环到 readyhost /v1/models/v1/chat/completions 也都真实返回 HTTP 200。当前仍存在的 reconcile=drifted 只反映共享 fresh-host 环境里的历史残留资源,不阻塞 PRD 首版放行) 目标:实现独立控制面、零侵入宿主、可导入国产模型并具备可运维的导入/回滚/访问闭环。

2026-05-22 当前真相

  • 当前主目录 artifacts/real-host-acceptance/ 已只保留最终证据;历史调试样本已迁到 artifacts/real-host-acceptance-archive/
  • access ready 语义已经收口为:/v1/models 命中 smoke_test_model,且最小 POST /v1/chat/completions smoke 成功;不会再出现 models-only 假 ready
  • subscription 主链路已通过 latest fresh-host 复验:
    • MiniMax 53hkartifacts/real-host-acceptance/20260521_191418_remote43_minimax_key_import/21-summary.json
    • DeepSeek 2166artifacts/real-host-acceptance/20260521_201509_remote43_deepseek_key_import/21-summary.json
    • Kimi A7Mlocal host v0.1.129artifacts/real-host-acceptance/20260522_122706_local_v0129_kimi_a7m_subscription_freshhost/21-summary.json
  • 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/admin-batch-import.html
      • deploy/tksea-portal/nginx.sub.tksea.top.conf.example
      • scripts/deploy/deploy_tksea_portal.sh
    • 新页面已补齐登录态、用户信息、可绑定分组、活跃订阅、历史 key 列表,以及“新创建 key 对应分组/模型”的即时展示
    • 同轮已补最小 batch-import 管理页:
      • 地址:/portal/admin-batch-import.html
      • 直接消费 POST /api/batch-import/runs
      • 直接消费 GET /api/batch-import/runs/{run_id}
      • 直接消费 GET /api/batch-import/runs/{run_id}/items
      • 用于验证 matched_account_state / account_resolution / provision_reused
    • 2026-05-27 已继续把管理入口收成统一 /portal/admin/ 体系:
      • https://sub.tksea.top/portal/admin/:管理首页
      • https://sub.tksea.top/portal/admin/providers.htmlprovider 目录 / preview-import / import / manifest 草稿页
      • https://sub.tksea.top/portal/admin/batch-import.html:结构化 batch-import 入口,当前跳转到 legacy admin-batch-import.html
      • Nginx 示例与 deploy 脚本已补同域 CRM 反代 https://sub.tksea.top/portal-admin-api/
      • 目的不是绕过鉴权,而是让浏览器可直接操作 remote43 CRM当前已继续补成“管理员用户名 / 密码登录 + HttpOnly session cookie”同时保留 Bearer admin token 兼容脚本与紧急兜底
    • 2026-05-27 已继续把 provider manifest 草稿从“只存在浏览器”补成真正的服务端能力:
      • 新增 POST /api/provider-drafts
      • 新增 GET /api/provider-drafts
      • 新增 GET /api/provider-drafts/{draft_id}
      • 新增 PUT /api/provider-drafts/{draft_id}
      • 新增 DELETE /api/provider-drafts/{draft_id}
      • 数据当前落到 CRM SQLite provider_drafts
      • providers.html 已可直接“保存到服务端”、回看历史草稿、以及更新 / 删除已保存草稿
    • 2026-05-28 已把“草稿一键生成 pack/provider 文件并提交到仓库”的发布链路补齐:
      • 新增 POST /api/provider-drafts/{draft_id}/publish
      • 发布动作会把草稿 canonicalize 成完整 pack.ProviderManifest
      • 服务端会原子执行:写 providers/<provider_id>.json、bump pack.json patch 版本、更新 checksums.txt、重跑整包校验、git add + git commit
      • 运行前提新增:SUB2API_CRM_REPO_ROOT 必须指向真实 Git 仓库
      • remote43 原本的 /home/ubuntu/sub2api-cn-relay-manager 只是普通目录,不带 .git
      • 2026-05-28 已继续把这条路径收成正式部署约定:
        • CRM 现在应统一指向 /home/ubuntu/sub2api-cn-relay-manager-git-current
        • scripts/deploy/setup_remote43_patched_stack.sh 会自动生成并刷新该固定 checkout
        • 这样 provider 草稿发布链不再依赖任何一次性的时间戳 repo 目录
      • 公网 providers.html 已新增“发布到仓库”按钮与 commit message 输入框
      • remote43 公网真验已通过:
        • draft_id=draft_remote43_publish_smoke_1779924243
        • provider_id=smoke-publish-1779924243
        • provider_path=packs/openai-cn-pack/providers/smoke-publish-1779924243.json
        • pack_version=1.1.5 -> 1.1.6
        • publish_mode=created
        • commit_sha=d8d647e
        • 远端 repo HEAD 与 API 返回 commit_sha 一致,说明 create -> publish -> git commit 已完整闭环
    • 线上无副作用验收已确认:
      • GET /portal/ 返回 200
      • GET /kimi-portal/ 返回 302 -> /portal/
      • GET /portal-proxy/api/v1/keys 在无效 token 下已命中宿主真实 INVALID_TOKEN,说明新的同域代理已生效
    • 2026-05-28 已继续把管理态“每次手贴 Bearer token”收口为正式登录流
      • 新增 GET /api/admin/session
      • 新增 POST /api/admin/session/login
      • 新增 POST /api/admin/session/logout
      • 管理态受保护接口现已同时接受:
        • Authorization: Bearer <SUB2API_CRM_ADMIN_TOKEN>
        • 或同域管理员 session cookie
      • providers.htmladmin-batch-import.html 现已优先走 sessiontoken 输入框仅保留为兜底
      • 当前部署环境可通过以下变量显式配置管理员账号:
        • SUB2API_CRM_ADMIN_USERNAME
        • SUB2API_CRM_ADMIN_PASSWORD
        • SUB2API_CRM_ADMIN_SESSION_TTL
    • 2026-05-28 已继续把 providers.html 的 manifest 草稿表单收口成“按最近成功模板起步”的录入流:
      • 草稿区首次打开且字段为空时,会优先回填最近一次成功发布的模板;没有历史时,回退到当前 pack/provider 目录里的现有 provider最后才使用静态样例
      • Provider ID 现已按 display_name / base_url / supported_models 自动生成,并在与现有 provider / draft 冲突时自动补后缀避重
      • 当新填的 supported_models 已在现有 provider 或草稿里出现时,页面会直接提示“同模型已存在”,并优先建议复用已有 provider_id,避免因为“官方 / 中转”重复新增同一模型定义
      • GET /api/packs/{pack_id}/providers 现已补充返回 base_url / smoke_test_model / supported_models,用于前端做模板参考和模型冲突提示
      • 2026-05-28 继续把这条规则下沉到服务端:POST /api/provider-draftsPUT /api/provider-drafts/{draft_id}POST /api/provider-drafts/{draft_id}/publish 现在都会做 pack 级模型冲突校验;同模型若已被其他 provider / draft 占用,会直接返回 409 provider_model_conflict
    • 2026-05-28 已新增独立实验 pack packs/openai-cn-pack-route-lab/,用于验证 “同一个 group 下挂多条 GPT 路线” 的方案 B 骨架:
      • 当前实验 provider 为 gpt-asxs-route-labgpt-codex2api-route-lab
      • 两者共用 group_template.name=GPT Shared 路由实验plan_template.name=GPT Shared 路由实验套餐
      • 两者使用不同 channel_template.name,并先以不同公开 alias 对外:
        • gpt-5.4-asxs / gpt-5.4-mini-asxs
        • gpt-5.4-codex2api / gpt-5.4-mini-codex2api
      • 这轮只解决 “同组多线路” 的第一阶段验证,不代表当前系统已经支持 “同公开模型名双线路 + 显式 route policy”
      • codex2api 当前先按 https://www.codex2api.com/v1 作为 API 根地址假设,若 preview/import 失败,需先校正真实 API base URL
      • 2026-05-28 remote43 真验结论已落地:
        • gpt-asxs-route-lab 可成功导入artifactartifacts/real-host-acceptance/20260528_142205_remote43_gpt-asxs-route-lab_key_import/21-summary.json
        • 导入时创建资源:group_id=8channel_id=7plan_id=7account_id=9
        • upstream asxs/models/chat/completions200;但该轮 managed chat 仍返回 503,原因是脚本首轮使用了 canonical model gpt-5.4 探测,而当前 route-lab 对外 alias 实际是 gpt-5.4-asxs
        • gpt-codex2api-route-lab 在尝试复用同一 group 时被宿主直接拒绝artifactartifacts/real-host-acceptance/20260528_142320_remote43_gpt-codex2api-route-lab_key_import/03-import.body.json
        • 宿主返回 409 GROUP_ALREADY_IN_CHANNEL,错误为:one or more groups already belong to another channel
        • 因此当前真实结论不是“同组多 channel 可继续验证路由策略”,而是 stock / patched sub2api 当前结构上不允许同一个 group 绑定到第二个 channel
        • 2026-05-28 已进一步把宿主侧最小改造方案固化到 docs/HOST_MULTI_CHANNEL_MINIMAL_RETROFIT.md
          • 真实最小改造不只是移除 channel_groups(group_id) 唯一索引
          • 还必须给宿主 account_groups 引入 channel_id,并让 gateway / scheduler / sticky session / account stats pricing 全部从 group -> single channel 升级到 group + channel 维度
          • 否则就算数据库允许同一 group 绑定多个 channel运行时账号池仍会被按 group 混跑,结构上仍不成立
        • 2026-05-28 已明确 fallback 方案:不修改宿主源码,改由 relay-manager 插件层维护 logical_group -> route -> shadow_group 三层抽象,详见 docs/PLUGIN_ROUTE_STICKY_DESIGN.md
          • 前端只看到一个逻辑分组
          • 插件层先做 route 级 sticky再把请求稳定转发到某个宿主 shadow group
          • 宿主继续只做单线路 group 内的 account sticky / 调度
        • 2026-05-28 已新增插件整体需求盘点 docs/PLUGIN_REQUIREMENTS_OVERVIEW_2026-05-28.md
          • 已把“增加模型、维护逻辑分组、智能路由、供应商帐号导入与停启用、普通用户前端”五大功能域统一收口
          • 并明确区分 已完成 / 待优化 / 待完成 / 未来规划
        • 2026-05-28 已继续细化闭环实施规划 docs/PLUGIN_CLOSED_LOOP_IMPLEMENTATION_PLAN_2026-05-28.md
          • 明确当前插件数据库仍为 SQLiteSUB2API_CRM_SQLITE_DSN
          • 明确后续继续以 SQLite 作为主状态库Redis 作为智能路由运行态缓存
          • 明确智能路由日志必须结构化落入插件 SQLite而不是只放 Redis 或 stdout
        • 2026-05-28 已新增 Phase 1 可开工任务单 docs/plans/2026-05-28-phase1-logical-routing-foundation-plan.md
          • 已把 SQLite migration / logical_group-route repo+API / 路由日志写入器 / Redis sticky 抽象 拆成可执行任务
          • 已继续细化到任务级 入场条件 / 产出清单 / 远端验证步骤 / 证据要求 / 回滚原则
          • 并明确要求:每个闭环功能完成后,都必须提交、推送、部署到 remote43 再验证,不能只停留在本地测试
          • 当前 Phase 1 的统一真相是:
            • 主状态库继续使用 SQLite
            • 路由运行态使用 Redis 或 memory backend 抽象
            • 智能路由日志必须最终结构化写回插件 SQLite
        • 2026-05-28 已完成 Phase 1 / P1-T1 SQLite schema foundation
          • 提交:7f75d8a6 feat(routing): add logical group schema foundation
          • 新 migrationinternal/store/migrations/0010_logical_groups_and_routes.sql
          • 本地门禁已通过:
            • gofmt -l .
            • go vet ./...
            • go test -cover ./internal/...
            • go test ./tests/integration/... -count=1
          • remote43 已原位升级到 repo HEAD = 7f75d8a
          • http://127.0.0.1:18173/healthz 返回 ok
          • remote43 实例 SQLite /home/ubuntu/sub2api-kimi-patched-auto2-20260525_18169/sub2api-cn-relay-manager.db 已确认包含:
            • logical_groups
            • logical_group_models
            • logical_group_routes
            • logical_group_route_models
          • 这轮远端验证还顺手暴露并修正了一个部署细节:
            • 若只在 /home/ubuntu 下直接拉起 CRM新进程会回退到默认相对 SQLite 路径 /home/ubuntu/sub2api-cn-relay-manager.db
            • 当前已改为显式 cd 到实例目录并 source .env.crm 后再启动,确保 migration 生效在实例库而不是错误的默认库
        • 2026-05-28 已完成 Phase 1 / P1-T2 logical_group / route repo + admin API
          • 提交:28188922 feat(routing): add logical group admin api
          • 新增 SQLite repo
            • logical_groups
            • logical_group_models
            • logical_group_routes
            • logical_group_route_models
          • 新增管理 API
            • POST /api/logical-groups
            • GET /api/logical-groups
            • GET /api/logical-groups/{group_id}
            • PUT /api/logical-groups/{group_id}
            • DELETE /api/logical-groups/{group_id}
            • POST /api/logical-groups/{group_id}/models
            • GET /api/logical-groups/{group_id}/models
            • DELETE /api/logical-groups/{group_id}/models/{model}
            • POST /api/logical-groups/{group_id}/routes
            • GET /api/logical-groups/{group_id}/routes
            • PUT /api/logical-groups/{group_id}/routes/{route_id}
            • DELETE /api/logical-groups/{group_id}/routes/{route_id}
            • POST /api/logical-groups/{group_id}/routes/{route_id}/models
            • GET /api/logical-groups/{group_id}/routes/{route_id}/models
          • 本地门禁已通过:
            • gofmt -l .
            • go vet ./...
            • go test -cover ./internal/...
            • go test ./tests/integration/... -count=1
          • remote43 已原位升级到 repo HEAD = 2818892
          • http://127.0.0.1:18173/healthz 返回 ok
          • remote43 真实 API 验证已通过:
            • POST /api/logical-groups 创建 logical_group_id=p1t2-gpt-shared-1779971040
            • GET /api/logical-groups 返回列表,当前计数 2
            • GET /api/logical-groups/p1t2-gpt-shared-1779971040 返回 display_name=P1T2 GPT Shared,建 route 前 routes_count=0
            • POST /api/logical-groups/p1t2-gpt-shared-1779971040/routes 创建 route_id=asxs-1779971040shadow_group_id=p1t2-gpt-shared-1779971040__asxs
  • 2026-05-26 已把“最终用户 -> 公网域名 -> OpenClaw”这一跳补进正式验证口径
    • 公网根地址当前统一为 https://sub.tksea.top
    • OpenClaw 本地 MiniMax 运行时故障已定位为 pi-ai/openai-node 未继承系统 HTTP(S)_PROXY,不是 allowlist 或模型名大小写问题
    • 操作者本机已新增升级后自检与提醒链路:
      • ~/.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
    • 当前 OpenClaw 真实验证基线已收口为:
      • tksea-gpt/gpt-5.4PASS
      • tksea-gpt/gpt-5.4-miniPASS
      • tksea-gpt/gpt-5.5:当前 upstream 503
      • tksea-minimax/MiniMax-M2.5-highspeedPASS
      • tksea-minimax/MiniMax-M2.7-highspeedPASS
      • deepseek-official/deepseek-chatPASS2026-05-27 已补齐本机 auth profileone-shot 返回 OK
    • 这部分测试用例与执行过程已沉淀到 docs/OPENCLAW_EXTERNAL_VALIDATION.md
  • 2026-05-26 remote43 patched host 最新 provider 扩展验收:
    • openai-zhongzhuanartifacts/real-host-acceptance/20260526_155548_remote43_openai_zhongzhuan_multi_model_rootprep/21-summary.json 已确认 batch_status=succeededprovider_status_from_import=activedirect_chat_status=200
    • minimax-53hkartifacts/real-host-acceptance/20260526_155705_remote43_minimax53hk_multi_model_rootprep/21-summary.json 已确认 batch_status=succeededprovider_status_from_import=activedirect_chat_status=200upstream_chat_status=200
    • deepseek-chat-official
      • 旧 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=truedirect_models=["deepseek-chat"]direct_chat_status=200latest_access_status=subscription_readyupstream_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 escapesource .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_erroraccess 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/acceptance/import_remote43_provider.sh 现已明确拆分 CRM_HOST_BASEREMOTE_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 截断
  • 2026-05-25 已把 Hermes 里可复用的 a7m-kimi 正式并入主 pack
    • 新增 packs/openai-cn-pack/providers/kimi-a7m.json
    • openai-cn-pack 版本现为 1.1.3
    • 当前主仓不再需要依赖历史临时 pack openai-cn-pack-kimi-a7m
    • kimi-a7m provider manifest 现在也开始承载 host_overlays 元数据;本地已把 sub2api v0.1.129 的 Kimi A7M runtime overlay 说明与 .patch 资产纳入 packs/openai-cn-pack/overlays/
    • 新增 go run ./cmd/cli apply-host-overlay 最小执行器;当前 pack 内命中的 overlay 已可直接生成 patched 宿主构建目录,不再只是 preview/import 阶段的提示信息
  • 2026-05-25 已继续把路线 A 推进到运行态层面:
    • /tmp/sub2api-clean 的 clean worktree HEAD 导出 stock 源码,再用 go run ./cmd/cli apply-host-overlay --provider-id kimi-a7m --host-version 0.1.129 生成全新 patched 源码树
    • 基于该 patched 源码树重建 localhost/sub2api:patched-overlay-20260525-clean,并在独立 Podman 网络里启动新的 Postgres / Redis / App fresh-host
    • artifacts/real-host-acceptance/20260525_local_v0129_kimi_a7m_patched_overlay_image_freshhost_clean/21-summary.json 已确认:import_batch_status=succeededprovider_status=activelatest_access_status=subscription_readycompletion_ok=truecompletion_status=200
    • 同目录 07-access-status.json 与 patched host 运行日志已共同证明 managed subscription key 真实打通 /v1/modelsPOST /v1/chat/completions
    • 注意:该 fresh-host 使用的镜像基底仍是 weishaw/sub2api:0.1.129,但宿主管理 API 当前自报 host_version=0.1.126;后续读 artifact 时应以日期和证据链为准,不要只依赖版本字段
    • 2026-05-25 已把同一条 patched overlay 路线放到 remote43 做线上验收:
      • remote43 侧单独拉起了 sub2api-kimi-patched-20260525-{app,pg,redis}patched host 暴露 127.0.0.1:18139
      • 临时 CRM 也切到 remote43 本机运行,再通过 SSH 隧道映射回本地 127.0.0.1:18143,避免“本地 CRM 透过隧道探远端 host”导致的 get host version 超时噪音
      • artifacts/real-host-acceptance/20260525_remote43_kimi_a7m_patched_overlay_freshhost_remotecrm/21-summary.json 已确认:batch_status=succeededaccess_status_from_import=subscription_readyprovider_status_from_import=activedirect_models_http200=truedirect_chat_http200=trueupstream_chat_status=200
      • 同目录 14-access-status.json 已确认 effective_probe_key_source=managed_subscriptioncompletion_status=200
      • remote43 宿主日志也已落到真实 GET /v1/models = 200POST /v1/chat/completions = 200,说明这条 patched overlay 路线不只在本地 fresh-host 成功,也已在远端真实环境收敛到 ready
      • 这轮还顺手修掉了 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/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=succeededaccess_status=subscription_readyprovider_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/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.json14-access-status.json21-summary.json 已全部自动补齐;其中 21-summary.json 已再次确认 batch_status=succeededprovider_status_from_import=activelatest_access_status=subscription_readydirect_chat_status=200upstream_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
    • latest-head relay-manager + 本地 weishaw/sub2api:0.1.129 fresh-host 下import-time gateway /v1/models 命中 kimi-k2.6
    • 但 completion 仍落到 502 upstream_error,手工 managed key 再探 /v1/chat/completions 也返回 503
    • 管理员 account 视角 /api/v1/admin/accounts/1/models 正确,但手工 managed key /v1/models 仍会回到 GPT 默认集合,当前应继续归类为宿主运行时 gap / drift而不是 Hermes key 失效
  • artifacts/real-host-acceptance/20260525_local_v0129_kimi_a7m_from_hermes/22-patched-host-validation.json 已证明:
    • 问题根因是宿主把 Kimi A7M 这类 custom upstream 误走到 Responses 路径,而不是 Hermes key 或 relay-manager pack 失效
    • /tmp/sub2api-clean 的宿主补丁下,旁路容器 sub2api-patched 已恢复 managed key /v1/models=200managed key /v1/chat/completions=200admin accounts/:id/test=true
    • fallback 日志与账号 extra.openai_responses_supported=false 持久化已同时出现,说明这条链路已经从 stock host 的 partially_succeeded / broken 收敛到 patched host 的 ready
  • artifacts/real-host-acceptance/20260525_local_v0129_kimi_a7m_scheme_c_stockhost_rerun/21-summary.json 已证明:
    • 仅启用 relay-manager 侧方案 C预先 force_disable_openai_responses_api + import/access/reconcile capability repair但保持宿主仍是未打补丁的 stock weishaw/sub2api:0.1.129
    • import-time gateway /v1/models 仍能命中 kimi-k2.6
    • 但 import-time gateway /v1/chat/completions 依旧返回 502 upstream_erroraccess_status 仍是 brokenprovider_status_latest 仍是 partially_succeeded
    • 因此当前最新真相不是“方案 C 已替代宿主补丁”,而是“方案 C 缩小了控制面误判范围,但这条 Kimi A7M / stock v0.1.129 链路仍需要宿主运行时兼容修复”
  • 2026-05-25 已继续补齐方案 C控制面侧 capability repair
    • internal/host/sub2api 新增 ClearTempUnschedulable
    • access / reconcile 的 capability repair 现在会同时写 extra.openai_responses_supported=false 并清理账号 temp_unschedulable
    • packs/openai-cn-pack/providers/kimi-a7m.json 新增 force_disable_openai_responses_api=true,导入后会在 gateway closure 前预先把该账号切到 raw /v1/chat/completions
  • artifacts/real-host-acceptance/20260523_144937_remote43_kimi-a7m_key_import 已证明:
    • 这轮线上 kimi-a7m 不再复现“错库取 key 导致统一 401”或“模型列表串成 GPT 默认集合”
    • import 已返回 gateway.status_code=200models=["kimi-k2.6"]has_expected_model=true
    • upstream /models/chat/completions 都是 200
    • 未改宿主的真实阻塞已收缩为 host /v1/chat/completions 仍返回 503/502,不再是插件脚本的数据面问题
  • artifacts/real-host-acceptance/20260523_145531_remote43_kimi-a7m_key_import 说明另一类运行时噪音:
    • 当本地 SSH 隧道端口存活但链路已失活时,POST /api/hosts 阶段会在 get host version 处超时
    • 这类现象应优先解释为 tunnel/runtime 故障,而不是 provider 导入逻辑回退
  • 官方 provider 验证矩阵当前仍保留一条非阻塞事实:
    • artifacts/real-host-acceptance/20260521_222212_remote43_minimax-m2-7-official_key_import/21-summary.json 已证明 official MiniMax 模板链路是通的,但该验证 key 当前命中 upstream 429
  • reconcile=drifted 仍可能在 shared fresh-host 上出现,但当前解释是“历史残留资源噪音”,不阻塞 PRD 首版放行
  • 调通细节与诊断经验已沉淀到:
    • docs/REAL_HOST_ACCEPTANCE_LEARNINGS.md
    • docs/REAL_HOST_ARTIFACT_RETENTION.md
  • 2026-05-24 本地代码门禁修复已继续收口三类非回归点:
    • go test -race ./... -count=1 现已再次真实通过;根因不是业务逻辑,而是多个测试包并行 sqlite.Open() 时与 modernc.org/sqlite 初始化路径的 race 噪音。当前已把 internal/appinternal/provisioninternal/reconcile 的测试 SQLite 打开路径收口到串行 helper关闭这类假红灯同时保持 sqlite 包内测试不引入导入环。
    • DELETE /api/hosts/{hostID} 不再默认放行危险级联删除;hosts repo 现在会先统计 import_batches / managed_resources / reconcile_runs 三类运行态依赖,有残留时返回 409 host_in_use,避免误删状态库里的回滚/对账真相。
    • 控制面 JSON 请求体现在统一受 MaxBytesReader 限制;超限请求会明确返回 413 request_too_large,不再允许无界 body 直接进入解码路径。

本轮已完成

  1. 宿主身份模型统一
    • host 注册时持久化 auth_type/auth_token
    • import / reconcile / rollback-provider / access 运行时链路切换为 host_id 主键
    • provider status / resources / access status / import-batches 支持 host_id 查询维度
  2. managed_resources 宿主维度收口
    • 新增迁移 0004_host_identity_and_managed_resources.sql
    • managed_resources 唯一键提升为 (host_id, resource_type, host_resource_id)
    • 仓储与服务查询切换为 host-scoped 语义
  3. reconcile run 结果按批次收口
    • 新增迁移 0006_reconcile_runs_batch_scope.sql
    • reconcile_runs 补充 batch_idbatch detail 仅返回本批次 reconcile 记录
  4. capability probe 收敛为无副作用探测
    • 不再对真实创建接口发送空 POST
  5. rollback-provider 风险收敛
    • 改为优先按已记录批次资源 RollbackStoredResources() 回滚
    • 缺少已记录资源时拒绝危险删除
  6. 文档真相同步
    • 新增 docs/2026-05-18-PRODUCTION_REMEDIATION_TASK_BOARD.md
    • 下调 DEPLOYMENT.md 中未实现的 /metrics / 限流 / 监控承诺
  7. current-code remote43 导入链路已补齐 tunnel-aware 验证能力
    • 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、再执行订阅分配
    • account 创建请求现在同步写入 credentials.model_mapping,修正 /v1/models 读取 account model whitelist 时回退到 GPT 默认集合的问题
    • 新增/更新测试覆盖:internal/accessinternal/provisioninternal/host/sub2api
  9. current-code access ready 语义已提升到 completion 层
    • /v1/models 不再单独决定 subscription_ready/self_service_ready
    • 只有 /v1/models 命中 smoke_test_model/v1/chat/completions smoke 成功,控制面才会把 access 状态记成 ready
    • access closure / import runtime artifact / reconcile rerun payload 都会持久化 completion_ok/completion_status/completion_type/completion_preview
  10. current-code remote43 验收脚本已补 upstream API 证据层
  • scripts/acceptance/import_remote43_provider.sh 会直探 provider base_url 对应的 upstream /models/chat/completions
  • 新增 21-summary.json,用于把 completion 失败自动分流成 host_compatibility_gapupstream_key_quota_issue
  • 2026-05-27 已把 V2 batch-import reuse runtime 真正接到 live action
    • internal/app/batch_runtime.go 现已接入 InspectReuse
    • runtime reuse 查询优先命中既有 import_run_items,再回退到 legacy import_batches / import_batch_items / managed_resources / providers
    • 兼容 V2 短指纹与 legacy 完整 sha256 指纹
    • live run 现在可真实产出 matched_account_state / account_resolution / provision_reused
  • 2026-05-27 继续用 /portal/admin-batch-import.html 做真实页面操作验证,抓到了一个 live reuse 兼容缺口并已在本地修正:
    • real remote43 样本 https://api.53hk.cn/v1 + sk-4175...d776 + host=remote43-kimi-patched-auto2-18169 首轮返回 TOKEN_EXPIRED,根因是 CRM 中持久化的宿主 bearer 已过期;刷新 host auth 后item 已能恢复到 access_status=active
    • 旧版 runtime 仍把同一条历史账号判成 matched_account_state=none / account_resolution=created,根因是 live runtime 的 normalized provider_id(如 api-53hk-42797c06)与 legacy pack provider idminimax-53hk不一致时legacy reuse fallback 只按 provider_id 精确匹配
    • 当前已补 base_url fallback + ProviderMatched 策略信号legacy lookup 会补查相同 base_url 的 provider且“同 base_url + 同 key + family covered”现在可以真实收敛到 reused/reactivated
    • 定向回归已通过:go test ./internal/app -run 'TestBatchImportHTTP/(create run action reuses matched legacy account|create run action reuses legacy account when pack provider id differs from normalized runtime id)$' -count=1go test ./internal/batch -run TestDecideReuse -count=1go test ./internal/store/sqlite -run 'TestProvidersRepoListBy(BaseURL|BaseURLEmpty)$' -count=1
    • remote43 二次复验现已补证:更新后的 CRM 二进制已替换到 18173 控制面,真实 rerun run_1779882868037300268 已确认 item 从 account_resolution=created 收敛为 account_resolution=reused,并且 provision_reused=trueaccess_status=active
    • 当前剩余的细节是:该 rerun item 的 matched_account_state 仍为 none说明“reuse 命中后是否补出 active/disabled/deprecated state badge”仍可继续优化但这不影响本轮要验证的 created -> reused 结果成立
  1. patched CRM external validation 已完成
  • patched CRM 实例下DeepSeek 与 MiniMax 都已验证“completion smoke 通过时能落成 succeeded/active失败时不会误记成 ready”
  • 20260521_191418_remote43_minimax_key_import20260521_201509_remote43_deepseek_key_import 已同时证明当前 subscription provider 链路可真实闭环
  • 20260521_210403 已证明 latest-head self_service 标准 fresh-host 验收也可闭环到 self_service_ready / fully_ready
  1. artifact 保留策略已收口
  • 主目录 artifacts/real-host-acceptance/ 当前只保留最终证据
  • 历史失败/半成功/试错样本已迁到 artifacts/real-host-acceptance-archive/
  • 分类规则见:docs/REAL_HOST_ARTIFACT_RETENTION.md
  1. relay-manager latest-head 已收口 Kimi A7M 两段竞态
  • account test 首次 403 Forbidden 已降级为 advisory warning只要 /models 已命中 smoke_test_model,不会再把 batch 误判为 blocking failure
  • access closure 对导入后瞬时 503 / no available accounts 增加短暂 completion retry避免宿主异步 probe / account warm-up 窗口把真实可用链路误记成 broken
  • 20260522_122706_local_v0129_kimi_a7m_subscription_freshhost 已证明:在修复后的 relay-manager + patched host 组合下,kimi-a7m / kimi-k2.6 可落到 batch_status=succeededprovider_status=activelatest_access_status=subscription_ready
  1. relay-manager latest-head 已补宿主升级后的 capability 自愈
  • API returned 403: Forbidden 这类 /responses 误判 advisory控制面现在会在 access closure 与 reconcile rerun 中把目标 account 的 openai_responses_supported 修正为 false,随后重试 gateway /v1/chat/completions
  • 这样即使宿主升级或异步 probe 把 capability 标记覆写错,控制面也能在“安装后确认”与“后台持续对账”两个环节重新拉回可用状态
  1. 2026-05-24 本地质量门禁补丁已完成
  • 新增 repo 级删除保护:internal/store/sqlite/hosts_repo.go 引入 RuntimeDependencyCountsByHostIDHostDeleteBlocker
  • 新增回归测试:TestHostsRepoDeleteByHostIDBlocksWhenRuntimeStateExistsTestBatchImportRejectsOversizedJSONBodyTestDecodeJSON/rejects oversized request body
  • internal/app/http_api.go 现已统一限制 JSON request body 大小,并把 host 删除占用态映射为 host_in_use
  • internal/app / internal/provision / internal/reconcile 测试 SQLite 打开路径已改为串行 helper当前 go test -race ./... -count=1 重新恢复为绿

已验证门禁

  • gofmt -l . 空输出
  • go vet ./...
  • go test ./...
  • go test -race ./...
  • go test -cover ./internal/...
    • internal/access: 80.5%
    • internal/host/sub2api: 78.1%
    • internal/pack: 73.9%
    • internal/provision: 79.4%
    • internal/store/sqlite: 77.9%
  • go test ./tests/integration/... -count=1
  • bash ./scripts/test/test_real_host_scripts.sh

当前保留的最终证据

  1. artifacts/real-host-acceptance/20260520_222713_crm18100_live_model_mapping_validation

    • 证明 account credentials.model_mapping 与 live runtime 对齐
  2. artifacts/real-host-acceptance/20260521_142211_crm18100_deepseek_completion_split

    • 证明 host completion 失败与 upstream completion 成功可以分离
    • 是 completion 分流逻辑的关键根因证据
  3. artifacts/real-host-acceptance/20260521_191418_remote43_minimax_key_import

    • MiniMax 53hk subscription 最终成功样本
    • 21-summary.json 已到 batch_status=succeededprovider_status=active
  4. artifacts/real-host-acceptance/20260521_201509_remote43_deepseek_key_import

    • DeepSeek 2166 subscription 最终成功样本
    • 21-summary.json 已到 batch_status=succeededprovider_status=active
  5. artifacts/real-host-acceptance/20260521_210403

    • latest-head self_service 标准 fresh-host 验收最终成功样本
    • 05-import.json = succeeded/self_service_ready/active
    • 07-access-status.json = latest_access_status=fully_ready
  6. artifacts/real-host-acceptance/20260521_222212_remote43_minimax-m2-7-official_key_import

    • official MiniMax 模板 live 样本
    • 模板链路打通,但当前验证 key 命中 upstream 429
  7. artifacts/real-host-acceptance/20260522_122706_local_v0129_kimi_a7m_subscription_freshhost

    • latest-head relay-manager 对 patched host v0.1.129 的 Kimi A7M subscription 最终成功样本
    • 21-summary.json 已到 batch_status=succeededprovider_status=active
    • account_probe_summary 明确记录 probe_advisory=truevalidation_status=warning,证明 403 probe race 已被 relay-manager 正确降级
  8. artifacts/real-host-acceptance/20260523_144937_remote43_kimi-a7m_key_import

    • remote43 未改宿主 + 修正后的 latest-head 验收脚本样本
    • 已证明脚本层的“错库取 key / 错地址 / 多 host 历史查询”问题被收掉
    • 仍保留的真实阻塞是宿主 completion 路径 502/503
  9. artifacts/real-host-acceptance/20260525_local_v0129_kimi_a7m_from_hermes

    • 当前主 pack 1.1.1 正式纳入 kimi-a7m 后的本地 fresh-host 验收样本
    • 21-summary.json 保留了 stock host v0.1.129 的原始失败快照,证明 Hermes A7M upstream key 当前在线可用,阻塞不在 key 本身
    • 22-patched-host-validation.json23-sub2api-host-patch-notes.md 已补齐 patched host 的真实收敛证据:问题是宿主 runtime 的 Responses -> raw chat 兼容缺口,补丁后链路已回到 ready

剩余项P2 / 运营前置,不阻塞按 PRD 首版范围上线)

  1. 运营前置

    • 真实宿主初始化不会自动创建普通用户;上线前必须显式创建普通用户并留存可复用凭据
    • self_service 需要普通用户 key 绑定目标标准 group且通常还需要可用余额
    • subscription 需要 subscription 类型 group + 普通用户订阅分配 + key/group 绑定
    • 若启用持续后台 reconcileSQLite 状态库将持久化最新 access probe 元数据,部署时必须按 secret 级别保护数据库文件
  2. 部署与环境限制

    • 标准多阶段 Dockerfile 在受限网络环境下仍不稳
    • 当前推荐 scripts/deploy/build_local_image.sh + Dockerfile.local
  3. official provider 验证矩阵

    • official MiniMax 当前 live 样本已证明模板链路可用,但验证 key 命中 upstream 429
    • Qwen / GLM / Kimi / Step 等官方 provider 是否通过 live 验收,仍取决于后续官方 key 与 quota

当前最短后续路径

  1. 若继续扩大 provider 覆盖面,优先按 docs/PROVIDER_VALIDATION_MATRIX.md 补官方 key再做 official live 验收
  2. 若继续优化 shared fresh-host 信噪比,对历史残留资源做一次环境清理,降低 reconcile=drifted 噪音
  3. 若继续产品化,优先扩大 official provider live 验收覆盖面,并基于新 create-run 入口补充真实宿主 acceptance artifact

v2 规划Batch Auto-ImportURL + Key

当前阶段 已按基线计划恢复实现T1~T13 已落地create-run entry wiring 已补齐,最新全量验证通过)

文档docs/2026-05-21-BATCH_AUTO_IMPORT_SPEC.md(需求规格) TDD 计划docs/2026-05-21-BATCH_AUTO_IMPORT_TDD_PLAN.md(实现路径,已确认开放问题) 技术架构docs/2026-05-22-BATCH_AUTO_IMPORT_V2_ARCHITECTURE.md运行态状态库、结果页、API、页面字段布局 Migration 草案docs/2026-05-22-BATCH_AUTO_IMPORT_V2_MIGRATION_DRAFT.mdSQLite 新表、索引、lease/retry 字段、legacy link API Schema 细稿docs/2026-05-22-BATCH_AUTO_IMPORT_V2_API_SCHEMAS.mdrun/item 响应结构、筛选参数、badge 文案、错误语义)

本轮设计收敛

  • 已把真实验收中的三类高频问题写入 v2 方案:
    • 添加模型时的模型名归一化与纠错
    • 第三方国产模型的兼容能力画像(/responses/chat/completions、Anthropic compatible、stream/tools
    • 添加账号后的异步确认窗口(首次 403 probe race、首次 503 no available accounts warm-up
  • 已补充两类产品化能力到 v2
    • run / item 状态持久化、retry 轨迹、控制面重启后的历史结果查看
    • 批次列表页 / 批次详情页用于查看模型纠错结果、账号状态、provider warning 与最终 access 状态
  • 当前 v2 的目标已从“同步导入成功”升级为“导入 + 异步确认 + 最终闭环验真”
  • 已按 review 收口最关键的 4 个冲突:
    • 统一 canonical contractrun_id/item_id/provider_id/run.state/confirmation_status/access_status
    • 补齐 subscription / self_service 的输入契约
    • 明确 V2 唯一状态源为 import_runs/import_run_items/import_run_item_events
    • 明确 ConfirmationWorker + lease + next_retry_at 的异步确认执行机制
  • 其余 review 问题也已同步收口:
    • capability 从 upstream 总画像升级为 transport + model profiles
    • 结果页字段、状态库存储字段、retry/event trail 已统一
    • run 级请求上下文已持久化到 import_runs,控制面重启后 validate 能继续使用 host_id / subscription_users / subscription_days / probe_api_key
    • OpenAPI 已补齐 /api/batch-import/runs*legacy /api/import-batches/* 降级为 v1/legacy
    • run/item 列表 API 已补齐 cursor/next_cursorrun 列表 q 可命中 run_id / provider_id / base_url
    • 已补充重复导入自动复用策略:按 provider_id + api_key_fingerprint + canonical_model_family 判断 reused / patch_only / replace
    • 已补充同模型别名归一化契约:例如 kimi 2.6 / kimi-2.6 / kimi-k2.6 可归并到同一模型家族并快速复用
    • 已补充多账号重复导入与弃用账号再启用策略active 账号提示“重复已启用”disabled/deprecated 账号显示原状态并走 reactivated 快速启用路径
    • 已修正 access closure artifact 的 probe key 语义漂移:subscription 现在持久化 requested_probe_api_keyeffective_probe_key_sourceeffective_probe_key_fingerprint,不再把外部 raw key 伪装成 probe_api_keyprobe_api_key 仅继续用于 self_service 向后兼容
    • 最新干净本地 fresh-host 验收 artifacts/real-host-acceptance/20260523_local_clean_minimax_subscription_probe_semantics 已验证:
      • subscription closure 会正确区分 requested_probe_api_keymanaged_subscription 实际 probe 来源
      • 同一轮 raw key 直打宿主仍返回 403 not assigned to any group
      • provider completion 仍受 MiniMax 官方 upstream 429 rate_limit_error 影响,但这已不再会被 artifact 误读成 raw key 可用
    • 同一 fresh-host 上继续补的 MiniMax M2.5 缩圈验证已证明:
      • artifacts/real-host-acceptance/20260523_local_clean_minimax_m25_only_probe:单独只打 M2.5 时,宿主会选中真实账号并命中 upstream 429
      • artifacts/real-host-acceptance/20260523_local_clean_minimax_m25_repeated_probe:连续第 1 次 M2.5429,后续第 2/3 次退化成 503 Service temporarily unavailable
      • 对应宿主日志中,第一次有 account_id=1upstream_status=429,后续只有 account_select_failed error=\"no available accounts\"
      • 当前 MiniMax live 阻断要按两层解释:第一次是 upstream quota/rate-limit后续 503 是唯一账号进入临时不可调度窗口后的宿主侧结果

本轮实现状态T1 ~ T13

  • internal/batch canonical types / reuse policy / service / confirmation / validation / projection 已落地
  • internal/probe models / alias / capability / smoke completion 已落地
  • internal/store/sqlite run/item/event runtime state repo 与 migration 已落地
  • /api/batch-import/runs* 路由、projection 读取、CLI batch-import 命令、集成测试与设计还原审计已落地
  • go test ./... -count=1
  • go test ./tests/integration/... -count=1
  • go test -cover ./internal/... -count=1
  • go vet ./...
  • gofmt -l .

T13 审计结论

  • docs/2026-05-22-BATCH_AUTO_IMPORT_V2_RESTORATION_CHECKLIST.md 已完成
  • latest-head 已补齐 internal/app/http_batch_import.go -> internal/app/batch_runtime.go 的 create-run 入口 wiring
  • API 与 CLI create-run 现在都会真实驱动 BatchImportService + ConfirmationWorker + ValidationService
  • 控制面 server 启动后会自动运行 batch-import background schedulerrunning run 在重启后可继续推进
  • 最新一轮验证结果保持全绿:go test ./... -count=1go test ./tests/integration/... -count=1go test -cover ./internal/... -count=1go vet ./...gofmt -l .

真实 Gate 文档、状态机、投影、测试、审计与 create-run 入口已经对齐,V2 设计已按基线计划交付


禁止错误结论

  • 历史失败 artifact ≠ 当前 latest-head 仍失败
  • capability probe 无副作用 ≠ 所有宿主版本都已真实兼容
  • rollback-provider 已改安全路径 ≠ 历史脏资源自动消失
  • HTTP 200 ≠ 宿主初始化会自动准备普通用户/订阅/余额;这些仍是显式运营前置