- Add BATCH_AUTO_IMPORT_SPEC.md: 3-stage pipeline (probe/provision/validate), provider_id=host+hash, smoke_model=find-first-usable, pricing=defaults - Add BATCH_AUTO_IMPORT_TDD_PLAN.md: 5-stage implementation plan, 10 tasks - Update EXECUTION_BOARD.md: add v2 section with resolved open questions
22 KiB
sub2api-cn-relay-manager 执行板
日期:2026-05-21
当前 Gate:APPROVED(代码门禁已通过,并且 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 已共同证明:subscription 与 self_service 主链路都能在真实 fresh host 上闭环到 ready,host /v1/models 与 /v1/chat/completions 也都真实返回 HTTP 200。当前仍存在的 reconcile=drifted 只反映共享 fresh-host 环境里的历史残留资源,不阻塞 PRD 首版放行)
目标:实现独立控制面、零侵入宿主、可导入国产模型并具备可运维的导入/回滚/访问闭环。
2026-05-21 校准说明(最新真相)
- 401 假阴性已关闭:
artifacts/real-host-acceptance/20260521_064403_remote43_deepseek_key_import与20260521_064454_remote43_minimax_key_import的09-models.headers.txt都是HTTP 200,说明 managed probe key / 本机PACK_PATH修复生效。 - fresh-host DB 侧状态也已对齐:在脚本指向正确的
sub2api-fresh-deepseek-20260519_115244-{postgres,redis}-1后,08-subscription-group-state.json已能看到真实的 managed user / subscription / key 绑定,而不是旧 relaymgr 容器造成的空/null 假象。 - 这一轮之前的新主阻断不是 auth/tooling,而是 completion smoke:两条 provider 一度在 host
/v1/chat/completions返回502 upstream_error。 - 上游直探分流证明:
- DeepSeek 上游
/chat/completions=HTTP 200,因此 host 侧 502 是真实兼容性问题,不是单纯 key 失效。 - MiniMax 上游
/chat/completions=HTTP 403 insufficient_user_quota,因此当前验证 key 本身不具备真实 completion 流量能力。
- DeepSeek 上游
- 2026-05-21 进一步缩圈结果:
- DeepSeek managed key 直打 fresh host
http://127.0.0.1:18097/v1/chat/completions仍稳定返回502;但同一台 remote43 主机直接curl https://aitoken.quanfuli.cn/v1/chat/completions(同一 upstream key、同一 payload)返回HTTP 200,且Content-Type: text/event-stream。 - fresh-host app 日志显示 DeepSeek group
5当前挂了 10 个 active account(IDs14,15,16,17,19,20,23,25,26,28),chat 请求会在这些重复 account 之间 failover,全部记为account_upstream_error 500/502后才落成 gateway502。 - MiniMax group
6当前挂了 6 个 active account(IDs18,21,22,24,27,29),temp_unschedulable_reason都明确记录为insufficient_user_quota;说明它的 completion 阻断已不是 CRM/host 路由问题,而是验证 key 配额不足。
- DeepSeek managed key 直打 fresh host
- 汇总证据:
artifacts/real-host-acceptance/20260521_064910_completion_smoke_calibration.md - 2026-05-21 当前代码已补一层稳定性收口:
internal/provision/import_service.go在 replacement account 全部通过 smoke 校验后,会先清理同 provider 前缀的旧 account 再做 gateway closure,避免重复导入把同 group 污染成多活重复 account;若 replacement 校验失败则保留旧 account,不做破坏性清理。 - 2026-05-21 同时新增
scripts/check_deepseek_completion_split.sh,可把 DeepSeek “host models=200 / host chat=502 / upstream chat=200” 压缩成可复现的最小 issue 证据包。 - 2026-05-21 本机 CRM(18100) 已补上 reconcile stale-noise 分类:对
remote43-fresh18097-deepseek-1779280533执行POST /api/providers/deepseek/reconcile后,batch_id=13返回extra_count=0、raw_extra_count=15、stale_noise_count=15、status=degraded;说明旧同前缀账号已不再被记成 drift,只剩真实probe_failures=1继续暴露。 - 2026-05-21 当前代码又补了一层 readiness 收口:
internal/access/closure.go、internal/provision/import_service.go、internal/provision/batch_detail_and_reconcile_service.go、internal/app/http_api.go现在都会在/v1/models通过后继续执行一次最小POST /v1/chat/completionssmoke;未通过 completion 的链路不再被记成subscription_ready/self_service_ready。 - 2026-05-21
scripts/import_remote43_provider.sh已新增 upstream/models与/chat/completions直探,额外落盘17-upstream-models.*、19-upstream-chat.*、21-summary.json,用于把“宿主兼容层问题”和“上游 key/quota 问题”分流。 - 2026-05-21 patched CRM fresh-host 复验结果:
- DeepSeek:
artifacts/real-host-acceptance/20260521_172709_remote43_deepseek_key_import/03-import.body.json已返回access_status=broken,并在gateway中明确写入completion_ok=false、completion_status=502;21-summary.json显示upstream_chat_status=403、completion_classification=upstream_key_quota_issue - MiniMax:
artifacts/real-host-acceptance/20260521_172646_remote43_minimax_key_import/03-import.body.json已返回access_status=broken,并在gateway中明确写入completion_ok=false、completion_status=502;21-summary.json同样显示upstream_chat_status=403、completion_classification=upstream_key_quota_issue
- DeepSeek:
- 2026-05-21 account probe 最后一层剩余问题已确认并关闭:
- 新 artifact:
artifacts/real-host-acceptance/20260521_191418_remote43_minimax_key_import - 结论:MiniMax 53hk 当前已从
partially_succeeded/degraded收口到succeeded/active - 根因 1:
internal/host/sub2api/accounts.go之前只取 SSE 最后一个 payload 的status/message/ok/success,会把type=error的真实错误原因吃掉,落成“failed + 空 message” - 根因 2:
internal/provision/import_service.go与 reconcile rerun 之前没有给POST /api/v1/admin/accounts/:id/test传provider.SmokeTestModel,宿主默认用gpt-5.4做账号测试,因 channel pricing restriction 误把 MiniMax 账号记成 failed - 修复后最新 batch detail
04-batch-detail-initial.json已显示:account_status=passed、probe_ok=true、validation_status=passed
- 新 artifact:
- 2026-05-21 DeepSeek 2166 路由的项目级 fresh-host 复验也已收口:
- 新 artifact:
artifacts/real-host-acceptance/20260521_201509_remote43_deepseek_key_import - 结论:DeepSeek 当前已从
partially_succeeded/degraded收口到succeeded/active - 关键证据:
21-summary.json显示batch_status=succeeded、provider_status_from_import=active、host/v1/chat/completions=200、upstream/chat/completions=200 16-batch-detail-final.json已显示:account_status=passed、probe_ok=true、validation_status=passed
- 新 artifact:
- 2026-05-21 latest-head
self_servicefresh-host 复验也已收口:- 最新完整标准 artifact:
artifacts/real-host-acceptance/20260521_210403 05-import.json已显示:batch_status=succeeded、access_status=self_service_ready、provider_status=active06-access-preview.json/07-access-status.json已显示:available=true、latest_access_status=fully_ready- 期间暴露并修复的最后一个代码级根因是:
internal/host/sub2api/gateway_probe.go之前把普通用户 gateway key 错误地放进x-api-key,而真实宿主要求Authorization: Bearer <gateway-key> 09-reconcile.json仍是status=drifted,但summary.access_status=self_service_ready,说明当前 shared fresh-host 里的历史残留资源仍存在,不影响本次访问闭环结论
- 最新完整标准 artifact:
- 结论更新:旧的 code-side false positive、MiniMax account probe 假失败、DeepSeek completion 阻断、以及 latest-head
self_servicegateway probe 认证偏差都已真实关闭;当前 Gate 可以按 PRD 首版范围提升为APPROVED。 - 调通细节与经验沉淀:
docs/REAL_HOST_ACCEPTANCE_LEARNINGS.md - 代码门禁与本地运行态已于 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全通过;覆盖率当前为internal/access 80.5%、internal/host/sub2api 78.1%、internal/pack 73.9%、internal/provision 76.3%。
本轮已完成
- 宿主身份模型统一
- host 注册时持久化
auth_type/auth_token - import / reconcile / rollback-provider / access 运行时链路切换为
host_id主键 - provider status / resources / access status / import-batches 支持
host_id查询维度
- host 注册时持久化
- managed_resources 宿主维度收口
- 新增迁移
0004_host_identity_and_managed_resources.sql managed_resources唯一键提升为(host_id, resource_type, host_resource_id)- 仓储与服务查询切换为 host-scoped 语义
- 新增迁移
- reconcile run 结果按批次收口
- 新增迁移
0006_reconcile_runs_batch_scope.sql reconcile_runs补充batch_id,batch detail 仅返回本批次 reconcile 记录
- 新增迁移
- capability probe 收敛为无副作用探测
- 不再对真实创建接口发送空
POST
- 不再对真实创建接口发送空
- rollback-provider 风险收敛
- 改为优先按已记录批次资源
RollbackStoredResources()回滚 - 缺少已记录资源时拒绝危险删除
- 改为优先按已记录批次资源
- 文档真相同步
- 新增
docs/2026-05-18-PRODUCTION_REMEDIATION_TASK_BOARD.md - 下调
DEPLOYMENT.md中未实现的/metrics/ 限流 / 监控承诺
- 新增
- 真实宿主重新验收已执行
self_service新 artifact:artifacts/real-host-acceptance/20260518_self_service_reaccept_v6subscription新 artifact:artifacts/real-host-acceptance/20260518_subscription_reaccept_v6- 两轮都完成了
preview-import / import / access-preview / status / reconcile / rollback全链路落盘
- reconcile host-scope 证据已补强
self_service:artifacts/real-host-acceptance/20260518_reconcile_hostscope_self_servicesubscription:artifacts/real-host-acceptance/20260518_reconcile_hostscope_subscription- 已补齐
status / resources / reconcile / batch detail / rollback的 host-scoped artifact,验证 batch detail 的 reconcile 视图按 batch 收口
- current-code remote43 导入链路已补齐 tunnel-aware 验证能力
scripts/import_remote43_provider.sh新增CRM_HOST_BASE,允许把“operator 访问 host 地址”和“CRM 进程访问 host 地址”分离- latest artifact:
/home/long/artifacts/real-host-acceptance/20260519_195827_remote43_deepseek_key_import - 结论:import / batch detail / managed resources 已真实落库;前一轮定位到 channel 创建缺少 model_mapping / restrict_models / billing_model_source,已补齐实现与测试
- current-code remote43 access gate 根因修正已落地
- subscription access 改为宿主侧闭环:CRM 不再依赖外部预先给定的宿主普通用户 key,而是按
subscription_usersselector 在宿主创建/查找托管普通用户、登录创建托管 key、回写 allowed_groups / balance、再执行订阅分配 - account 创建请求现在同步写入
credentials.model_mapping,修正/v1/models读取 account model whitelist 时回退到 GPT 默认集合的问题 - 新增/更新测试覆盖:
internal/access、internal/provision、internal/host/sub2api
- current-code access ready 语义已提升到 completion 层
/v1/models不再单独决定subscription_ready/self_service_ready- 只有
/v1/models命中smoke_test_model且/v1/chat/completionssmoke 成功,控制面才会把 access 状态记成 ready - access closure / import runtime artifact / reconcile rerun payload 都会持久化
completion_ok/completion_status/completion_type/completion_preview
- current-code remote43 验收脚本已补 upstream API 证据层
scripts/import_remote43_provider.sh会直探 providerbase_url对应的 upstream/models与/chat/completions- 新增
21-summary.json,用于把 completion 失败自动分流成host_compatibility_gap或upstream_key_quota_issue
- patched CRM external validation 已完成
- patched CRM 实例下,DeepSeek 与 MiniMax 都已验证“completion smoke 通过时能落成 succeeded/active,失败时不会误记成 ready”
20260521_191418_remote43_minimax_key_import与20260521_201509_remote43_deepseek_key_import已同时证明当前subscriptionprovider 链路可真实闭环20260521_210403已证明 latest-headself_service标准 fresh-host 验收也可闭环到self_service_ready/fully_ready
已验证门禁
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:76.3%internal/store/sqlite:61.4%
go test ./tests/integration/... -count=1✅bash ./scripts/test_real_host_scripts.sh✅
本轮真实宿主复验结果
-
ca1d448latest-head stale-process 阻断已关闭(2026-05-21)- 本地 CRM(18100) 新进程启动时间:
2026-05-21 01:08 - 当前 18100 使用的真实 DB:
/tmp/sub2api-relay-manager-realhost-18100.db - fresh remote43 证据目录:
artifacts/real-host-acceptance/20260521_011544_remote43_minimax_key_importartifacts/real-host-acceptance/20260521_011717_remote43_deepseek_key_import
- MiniMax:
03-import.body.json显示batch_id=7、access_status=subscription_ready、gateway.status_code=200 - DeepSeek:
03-import.body.json显示batch_id=8、access_status=subscription_ready、gateway.status_code=200 - 宿主 admin 侧直接复核:
GET /api/v1/admin/channels/5(MiniMax)已含非空model_pricing与model_mappingGET /api/v1/admin/channels/4(DeepSeek)已含非空model_pricing与model_mapping
- 旧现象的根因时间线已确认:
artifacts/real-host-acceptance/20260520_222713_crm18100_live_model_mapping_validation/summary.json中 MiniMax channel 5 仍是model_pricing=[],且created_at=updated_at=2026-05-20T20:39:23Z,说明它是旧 CRM 进程创建出的半成品 channel,而不是 current-code rerun 后依然未纠偏 - 当前 live host 上同一 channel 5 的
updated_at=2026-05-21T06:45:00Z,且model_pricing已非空,证明新进程已真正执行UpdateChannel纠偏 - 结论:
ca1d448对 channel pricing / hosted access 的修正已在真实宿主 fresh rerun 上落地,之前“旧 CRM 进程导致 MiniMax channel 仍空 pricing”的阻断已消失
- 本地 CRM(18100) 新进程启动时间:
-
self_service(最新 fresh redeploy 复验)- 证据目录:
artifacts/real-host-acceptance/20260518_redeploy_matrix - 初始状态:普通用户 key 未绑定 group、用户余额为 0 时,
/v1/models返回403 - 修正后:对普通用户执行“key 绑定标准 group + 用户余额=10”后,
04-self-after-balance.headers.txt显示HTTP/1.1 200 OK - 结论:
self_service主链路已在 fresh host 上真实打通;当前关键前置条件已收敛为 runbook 中明确记录的普通用户创建 / key-group 绑定 / 余额要求,而不是代码级阻塞。
- 证据目录:
-
subscription(最新 fresh redeploy 复验)- 证据目录:
artifacts/real-host-acceptance/20260518_redeploy_matrix - 修正后:创建 subscription 类型 group、完成普通用户订阅分配、并把普通用户 key 绑定到该 group 后,
06-subscription-after-assign.headers.txt显示HTTP/1.1 200 OK - 结论:
subscription主链路也已在 fresh host 上真实打通;其可用前提不是“宿主自动初始化一切”,而是显式完成 subscription group / user subscription / key binding 这一套运营动作。
- 证据目录:
2026-05-19 current-code remote43 验收补充结论
- 验收入口
- 证据目录:
/home/long/artifacts/real-host-acceptance/20260519_195827_remote43_deepseek_key_import - 本地 CRM 通过隧道访问 remote host,
CRM_HOST_BASE指向 CRM 侧可达的 host 地址
- 证据目录:
- 导入链路结论
import成功返回batch_id=19managed_resources已包含group/channel/plan/accountprovider_status=partially_succeeded,说明已进入真实业务路径,不再是 host 注册/pack path/隧道前置问题
- access gate 失败结论
latest_access_status=brokenaccess preview available=falsereconcile status=drifted,其中probe_failures=1
- 当前修正
- 旧 artifact 中
09-models.headers.txt/10-models.body.json暴露 GPT 系模型,根因已重新归类为:CRM 写了 channel model_mapping,但 accountcredentials.model_mapping未同步,导致宿主/v1/models从 account 视图回退到默认模型集 - 同时,旧脚本/调用路径把外部
subscription_users/access_api_key直接当宿主用户和宿主 key 使用,无法形成“宿主普通用户创建/查找 + key + 订阅分配”的真正闭环;该问题现已改为宿主托管闭环 - 代码侧阻断点已修复;下一步只剩 DeepSeek / MiniMax 真实 key 复验
- 旧 artifact 中
剩余项(含当前外部门禁)
- current-code code-side false positive 已关闭,fresh-host 外网复验证据已补齐
artifacts/real-host-acceptance/20260520_222713_crm18100_live_model_mapping_validation已证明 accountcredentials.model_mapping与 managed key 视角模型暴露正确20260521_172646_remote43_minimax_key_import/20260521_172709_remote43_deepseek_key_import已证明 patched CRM 下 control plane 会把 completion 失败正确落成broken- 旧阻断“CRM(18100) 进程过旧导致 MiniMax channel
model_pricing=[]”已被 host admin 现场证据推翻:GET /api/v1/admin/channels/5现已返回非空model_pricing - 当前 remaining gap 已不再是“控制面把 models-only 场景误报成 ready”,而是两把验证 key 的 upstream completion 都已明确返回
403 insufficient_user_quota
- 真实宿主脚本参数化仍要保持
- 当 CRM 切换为本机进程后,
PACK_PATH必须跟随切到控制面本机可读路径;继续沿用远端/home/ubuntu/...会触发stat pack path ... no such file or directory - 但当前脚本已经额外具备 upstream 直探与
21-summary.json分类能力,可直接作为 fresh rerun 的主入口,而不必再先修新的工具链
- 当 CRM 切换为本机进程后,
- 结构债务仍存在
- access / reconcile 尚未完全按 implementation plan 物理拆分
- 无内置 scheduler/jobs
- 运营前置动作需要 runbook 化执行
- 真实宿主初始化不会自动创建普通用户;当前 CRM subscription 闭环已证明 managed key 语义正确,但 fresh restart 后仍需重新做整条 live 验收,才能把“宿主托管普通用户/key”从代码能力提升为已验收事实
self_service需要普通用户 key 绑定目标标准 group,且通常还需要可用余额subscription需要 subscription 类型 group + 普通用户订阅分配 + key/group 绑定
- 标准多阶段 Dockerfile 在受限网络环境下仍不稳
- 当前推荐
scripts/build_local_image.sh+Dockerfile.local
- 当前推荐
- 真实宿主验收工具需补 host 级参数化
scripts/real_host_acceptance.sh的AFTER_IMPORT_HOOK_COMMAND仍有价值,但 remote43/fresh-host 变体还缺“目标 Postgres/Redis 容器名、目标 host env 文件、目标 forward 端口”的显式参数化- 否则 artifact 会混入旧宿主状态,误导 gate 判断
当前最短上线路径
- 替换 DeepSeek / MiniMax 的验证 key,要求具备真实 completion quota
- 用当前脚本重新跑 remote43/fresh-host 验收,检查新的
21-summary.json - 若换 key 后 upstream
/chat/completions变成200,再看 host/chat/completions是否仍有兼容性问题 - 当前代码状态可维持 “代码侧
CONDITIONAL_APPROVED、外部门禁BLOCKED”
v2 规划:Batch Auto-Import(URL + Key)
文档:docs/2026-05-21-BATCH_AUTO_IMPORT_SPEC.md(需求规格)
TDD 计划:docs/2026-05-21-BATCH_AUTO_IMPORT_TDD_PLAN.md(实现路径)
核心目标:管理员只需提供 (base_url, api_key) 列表,系统自动完成上游模型探测 → 宿主 channel 扩展 → provider 注册 → 中转闭环验证,全程无需预置 provider manifest。
三阶段管道:
Stage 1 (Probe) → GET /v1/models 获取模型列表,smoke test completion
Stage 2 (Provision) → channel 自动扩展 model_mapping,创建/更新 account
Stage 3 (Validate) → host relay completion 测试,写 access_status
新增模块:
internal/probe/— 上游探测(models 解析 / completion smoke / 错误分类)internal/batch/— 批量编排(URL→provider_id / model_mapping 扩展 / 管道服务)cmd/cli/batch_import.go— CLI 入口internal/host/sub2api/channel.go— PatchChannel 扩展
成功标准:
- 单条和文件批量输入均可
- 重复导入同一 URL+key 幂等(不重复创建 channel/account)
- strict/partial 两种模式
- Stage 3 completion 通过时
access_status=active,失败时正确降级 - 全流程不修改宿主源码,不写宿主数据库
任务清单(共 10 项,详见 TDD_PLAN):
- probe/models + test
- probe/classifier + test
- probe/completion + test
- batch/provider_id + test
- batch/channel_evolution + test
- host/channel.go PatchChannel + test
- batch/service + test
- cmd/cli/batch_import
- integration test
- 全量门禁
开放问题(已决策):
smoke test model 选择策略→ 选 C:遍历找第一个可用的model_pricing 为空时 restrict_models 行为→ 选 B:自动补空 pricingprovider_id 冲突策略→ 选 B:host + hash({normalized_host}-{url_hash_last8})
禁止错误结论
|- ❌ 历史失败 artifact ≠ 当前 fresh redeploy 仍失败 |- ❌ capability probe 无副作用 ≠ 所有宿主版本都已真实兼容 |- ❌ rollback-provider 已改安全路径 ≠ 历史脏资源自动消失
- ❌
HTTP 200≠ 宿主初始化会自动准备普通用户/订阅/余额;这些仍是显式运营前置