Files
sub2api-cn-relay-manager/docs/EXECUTION_BOARD.md

194 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# sub2api-cn-relay-manager 执行板
日期2026-05-21
当前 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` 已共同证明:`subscription``self_service` 主链路都能在真实 fresh host 上闭环到 readyhost `/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 流量能力。
- 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 accountIDs `14,15,16,17,19,20,23,25,26,28`chat 请求会在这些重复 account 之间 failover全部记为 `account_upstream_error 500/502` 后才落成 gateway `502`
- MiniMax group `6` 当前挂了 6 个 active accountIDs `18,21,22,24,27,29``temp_unschedulable_reason` 都明确记录为 `insufficient_user_quota`;说明它的 completion 阻断已不是 CRM/host 路由问题,而是验证 key 配额不足。
- 汇总证据:`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/completions` smoke未通过 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`
- 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`
- 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`
- 2026-05-21 latest-head `self_service` fresh-host 复验也已收口:
- 最新完整标准 artifact`artifacts/real-host-acceptance/20260521_210403`
- `05-import.json` 已显示:`batch_status=succeeded``access_status=self_service_ready``provider_status=active`
- `06-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 里的历史残留资源仍存在,不影响本次访问闭环结论
- 结论更新:旧的 code-side false positive、MiniMax account probe 假失败、DeepSeek completion 阻断、以及 latest-head `self_service` gateway 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%`
## 本轮已完成
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_id`batch detail 仅返回本批次 reconcile 记录
4. capability probe 收敛为无副作用探测
- 不再对真实创建接口发送空 `POST`
5. rollback-provider 风险收敛
- 改为优先按已记录批次资源 `RollbackStoredResources()` 回滚
- 缺少已记录资源时拒绝危险删除
6. 文档真相同步
- 新增 `docs/2026-05-18-PRODUCTION_REMEDIATION_TASK_BOARD.md`
- 下调 `DEPLOYMENT.md` 中未实现的 `/metrics` / 限流 / 监控承诺
7. 真实宿主重新验收已执行
- `self_service` 新 artifact`artifacts/real-host-acceptance/20260518_self_service_reaccept_v6`
- `subscription` 新 artifact`artifacts/real-host-acceptance/20260518_subscription_reaccept_v6`
- 两轮都完成了 `preview-import / import / access-preview / status / reconcile / rollback` 全链路落盘
8. reconcile host-scope 证据已补强
- `self_service``artifacts/real-host-acceptance/20260518_reconcile_hostscope_self_service`
- `subscription``artifacts/real-host-acceptance/20260518_reconcile_hostscope_subscription`
- 已补齐 `status / resources / reconcile / batch detail / rollback` 的 host-scoped artifact验证 batch detail 的 reconcile 视图按 batch 收口
9. 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已补齐实现与测试
10. 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/access``internal/provision``internal/host/sub2api`
11. 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`
12. current-code remote43 验收脚本已补 upstream API 证据层
- `scripts/import_remote43_provider.sh` 会直探 provider `base_url` 对应的 upstream `/models``/chat/completions`
- 新增 `21-summary.json`,用于把 completion 失败自动分流成 `host_compatibility_gap``upstream_key_quota_issue`
13. 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` 已同时证明当前 `subscription` provider 链路可真实闭环
- `20260521_210403` 已证明 latest-head `self_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`
## 本轮真实宿主复验结果
0. `ca1d448` latest-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_import`
- `artifacts/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_mapping`
- `GET /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”的阻断已消失
1. `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 绑定 / 余额要求,而不是代码级阻塞。
2. `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 验收补充结论
1. 验收入口
- 证据目录:`/home/long/artifacts/real-host-acceptance/20260519_195827_remote43_deepseek_key_import`
- 本地 CRM 通过隧道访问 remote host`CRM_HOST_BASE` 指向 CRM 侧可达的 host 地址
2. 导入链路结论
- `import` 成功返回 `batch_id=19`
- `managed_resources` 已包含 `group/channel/plan/account`
- `provider_status=partially_succeeded`,说明已进入真实业务路径,不再是 host 注册/pack path/隧道前置问题
3. access gate 失败结论
- `latest_access_status=broken`
- `access preview available=false`
- `reconcile status=drifted`,其中 `probe_failures=1`
4. 当前修正
- 旧 artifact 中 `09-models.headers.txt` / `10-models.body.json` 暴露 GPT 系模型根因已重新归类为CRM 写了 channel model_mapping但 account `credentials.model_mapping` 未同步,导致宿主 `/v1/models` 从 account 视图回退到默认模型集
- 同时,旧脚本/调用路径把外部 `subscription_users` / `access_api_key` 直接当宿主用户和宿主 key 使用,无法形成“宿主普通用户创建/查找 + key + 订阅分配”的真正闭环;该问题现已改为宿主托管闭环
- 代码侧阻断点已修复;下一步只剩 DeepSeek / MiniMax 真实 key 复验
## 剩余项(含当前外部门禁)
1. current-code code-side false positive 已关闭fresh-host 外网复验证据已补齐
- `artifacts/real-host-acceptance/20260520_222713_crm18100_live_model_mapping_validation` 已证明 account `credentials.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`
2. 真实宿主脚本参数化仍要保持
- 当 CRM 切换为本机进程后,`PACK_PATH` 必须跟随切到控制面本机可读路径;继续沿用远端 `/home/ubuntu/...` 会触发 `stat pack path ... no such file or directory`
- 但当前脚本已经额外具备 upstream 直探与 `21-summary.json` 分类能力,可直接作为 fresh rerun 的主入口,而不必再先修新的工具链
3. 结构债务仍存在
- access / reconcile 尚未完全按 implementation plan 物理拆分
- 无内置 scheduler/jobs
4. 运营前置动作需要 runbook 化执行
- 真实宿主初始化不会自动创建普通用户;当前 CRM subscription 闭环已证明 managed key 语义正确,但 fresh restart 后仍需重新做整条 live 验收,才能把“宿主托管普通用户/key”从代码能力提升为已验收事实
- `self_service` 需要普通用户 key 绑定目标标准 group且通常还需要可用余额
- `subscription` 需要 subscription 类型 group + 普通用户订阅分配 + key/group 绑定
5. 标准多阶段 Dockerfile 在受限网络环境下仍不稳
- 当前推荐 `scripts/build_local_image.sh` + `Dockerfile.local`
6. 真实宿主验收工具需补 host 级参数化
- `scripts/real_host_acceptance.sh``AFTER_IMPORT_HOOK_COMMAND` 仍有价值,但 remote43/fresh-host 变体还缺“目标 Postgres/Redis 容器名、目标 host env 文件、目标 forward 端口”的显式参数化
- 否则 artifact 会混入旧宿主状态,误导 gate 判断
## 当前最短上线路径
1. 替换 DeepSeek / MiniMax 的验证 key要求具备真实 completion quota
2. 用当前脚本重新跑 remote43/fresh-host 验收,检查新的 `21-summary.json`
3. 若换 key 后 upstream `/chat/completions` 变成 `200`,再看 host `/chat/completions` 是否仍有兼容性问题
4. 当前代码状态可维持 “代码侧 `CONDITIONAL_APPROVED`、外部门禁 `BLOCKED`
## 禁止错误结论
- ❌ 历史失败 artifact ≠ 当前 fresh redeploy 仍失败
- ❌ capability probe 无副作用 ≠ 所有宿主版本都已真实兼容
- ❌ rollback-provider 已改安全路径 ≠ 历史脏资源自动消失
-`HTTP 200` ≠ 宿主初始化会自动准备普通用户/订阅/余额;这些仍是显式运营前置