Files
sub2api-cn-relay-manager/docs/2026-05-18-PRODUCTION_READINESS_REVIEW.md

19 KiB
Raw Blame History

Sub2API CN Relay Manager 上线审查报告

日期2026-05-18 审查范围:/home/long/project/sub2api-cn-relay-manager 审查目标:评估当前实现是否与规划设计对齐,是否达到生产上线要求,并明确阻塞项、非阻塞项和建议整改路径。

状态更新2026-05-18 晚些时候):本报告识别出的 4 个系统性阻塞项已进入代码修复并已落地到当前分支;对应执行任务见 docs/2026-05-18-PRODUCTION_REMEDIATION_TASK_BOARD.md。本报告保留为“发现问题时的审查快照”,最新门禁结论以整改板与执行板为准。

再次状态更新2026-05-18 最新真实宿主复验后):已在最新代码上重新生成两套真实宿主 artifact

  • artifacts/real-host-acceptance/20260518_self_service_reaccept_v6
  • artifacts/real-host-acceptance/20260518_subscription_reaccept_v6

结果:两条链路都未形成最终通过 artifact因此当前仍不能把项目从 CONDITIONAL_APPROVED 推进到最终放行。

最终状态更新2026-05-18 fresh redeploy 复验后):artifacts/real-host-acceptance/20260518_redeploy_matrix 已在全新 redeploy 宿主上确认两条真实普通用户访问链路都可打通:

  • self_service:普通用户 key 绑定标准 group 且用户具备可用余额后,/v1/models -> 200
  • subscriptionsubscription 类型 group + 普通用户订阅分配 + key/group 绑定后,/v1/models -> 200

进一步状态更新2026-05-18 reconcile host-scope 复验后):已在最新代码上补充两套 host-scoped acceptance artifact

  • artifacts/real-host-acceptance/20260518_reconcile_hostscope_self_service
  • artifacts/real-host-acceptance/20260518_reconcile_hostscope_subscription

这两套新 artifact 补齐了 status / resources / reconcile / batch detail / rollback 的 host-scoped 证据链,进一步证明 reconcile_runs 带上 host_id + batch_idbatch detail 的 reconcile 视图已不再按 provider 粗暴聚合。

因此本报告中的 REJECT / CONDITIONAL_APPROVED 结论已成为历史快照;当前最新真相以 docs/EXECUTION_BOARD.mddocs/PRODUCTION_CLOSURE_BOARD.md20260518_redeploy_matrix20260518_reconcile_hostscope_* artifact 为准。

一、审查结论

本节为“首次审查时的历史结论快照”,不再代表当前最新 gate

  • 当时判断:代码层质量门禁整体通过,但真实宿主最终放行证据不足。
  • 因此当时结论为“代码层 CONDITIONAL_APPROVED,真实宿主最终放行未完成”。

当前最新上线判定请以:

  • docs/EXECUTION_BOARD.md
  • docs/PRODUCTION_CLOSURE_BOARD.md
  • artifacts/real-host-acceptance/20260518_redeploy_matrix
  • artifacts/real-host-acceptance/20260518_reconcile_hostscope_self_service
  • artifacts/real-host-acceptance/20260518_reconcile_hostscope_subscription

为准。

二、审查方法与证据

本次审查结合以下证据来源:

  1. 设计与规划文档对齐

  2. 代码审查重点

  3. 本地质量门禁复核

    • gofmt -l .:空输出
    • go vet ./...:通过
    • go test ./...:通过
    • go test -race ./...:通过
    • go test -cover ./internal/...:通过
      • internal/access77.3%
      • internal/pack72.7%
      • internal/provision76.9%
      • internal/store/sqlite68.2%
  4. 真实宿主 artifact 复核

三、设计对齐判断

已对齐部分

  • 满足“零宿主代码改动”的核心约束。
    • 当前所有宿主交互都通过 internal/host/sub2api 适配层完成,未发现直接写宿主数据库或注入宿主目录的实现。
  • 满足 MVP 的主链路目标。
    • pack 装载、provider 解析、导入编排、账号探测、网关 GET /v1/models 检查、状态库存证据链都已具备。
  • 控制面 API 基本覆盖当前计划要求。
    • 对照 implementation plan 中列出的当前 API仓库已实现主要端点。
  • 测试覆盖与门禁实现基本符合仓库自述。

未完全对齐部分

  • implementation plan 中的“宿主管理对象”与运行时导入路径没有形成统一身份模型。
  • implementation plan 默认呈现为“可管理宿主对象 + 持久化资源状态”的控制面,但当前状态模型仍偏向“单次导入任务持久化”,不足以支撑稳定的多次运维动作。
  • PRD 把多宿主管理列为首版非目标,但仓库已经暴露 hosts 管理 API这意味着系统外观上已像多宿主管理器但状态语义并未真正收口。

四、阻塞项

以下问题阻塞“整体生产无条件上线”。

阻塞项 1宿主身份模型不统一/api/hosts 与导入/对账/回滚没有形成同一条资产链

严重级别:High

证据:

  • POST /api/hosts 保存的是用户提供的 name -> host_idhttp_api.go http_api.go
  • POST /api/providers/{providerID}/import 请求体没有 host_id 字段,只有 host_base_url 和临时认证信息,http_api.go
  • RuntimeImportService.Import()HostID 为空时直接退回到 HostBaseURL 作为宿主身份,runtime_import_service.go

影响:

  • 先注册的宿主记录和后续真实导入批次可能落在两条不同的 hosts 记录上。
  • GET /api/hosts/{hostID}、批次查询、provider 状态、回滚定位不会共享同一条宿主身份链。
  • 这会直接削弱控制面的可运维性和可审计性。

结论:

  • 当前宿主对象模型只具备“登记能力”,不具备稳定的“生命周期主键能力”。

阻塞项 2managed_resources 没有宿主维度,状态库存在跨宿主资源串扰风险

严重级别:High

证据:

影响:

  • 两个不同宿主只要资源 ID 恰好相同,就会被控制面当成同一条资源。
  • rollback/reconcile 的依据会被污染。
  • 该风险和宿主 ID 通常为自增整数的现实形态高度相容,不能假设不会发生。

结论:

  • 这不是边界体验问题,而是状态建模缺陷。

阻塞项 3宿主能力探测存在副作用风险违背“零侵入宿主”目标的工程保守性

严重级别:High

证据:

  • ProbeCapabilities() 直接对真实创建接口发空 POST
    • /api/v1/admin/groups
    • /api/v1/admin/channels
    • /api/v1/admin/payment/plans
    • /api/v1/admin/accounts
    • /api/v1/admin/subscriptions/assign
    • capability_probe.go

影响:

  • 该实现假设宿主会把空请求稳定地当作“无副作用校验失败”处理。
  • 一旦宿主版本行为变化、参数默认值变化或某接口宽松接受空载荷,探测可能制造脏资源。
  • 这和 PRD 的“零侵入”承诺不冲突于字面,但明显冲突于生产工程保守性。

结论:

  • 在真实生产宿主上,这类探测方式不可视为安全。

阻塞项 4rollback-provider 仍按同名资源扫描删除,不是按批次记录的真实资源集删除

严重级别:High

证据:

  • rollback-provider 入口虽然先找到了 pack/provider/latest batchhttp_api.go
  • 但实际执行仍走 Rollback(ctx, RollbackRequest{Provider: providerManifest})http_api.go
  • Rollback() 的实现会按名字重新枚举宿主资源再删除,rollback_service.go
  • 更安全的 RollbackStoredResources() 已存在,但未被该路径采用,rollback_service.go

影响:

  • 在脏现场、残留现场、同名 provider 现场,会有误删风险。
  • 当前真实 artifact 已经反复体现 reconcile 仍可能看到 extra_count,此时按名字删尤其不稳。

结论:

  • 当前回滚策略还不满足“生产可放心执行”的标准。

五、非阻塞项

以下问题不一定阻塞受限范围上线,但会显著影响运维成熟度与文档可信度。

非阻塞项 1部署文档承诺高于实际实现

证据:

  • DEPLOYMENT.md/metrics、限流、监控接入写进了生产清单,DEPLOYMENT.md
  • 实际路由只看到 /healthz 和控制面 APIhttp_api.go

影响:

  • 运维人员容易误以为仓库已内置观测与生产保护机制。
  • 文档可信度低于代码可信度。

结论:

  • 应补功能,或先下调文档承诺。

非阻塞项 2计划结构与物理目录仍有明显漂移

证据:

  • 该评审形成时implementation plan 里期望的 internal/reconcile/*access/planner.goworker/scheduler.go 等结构仍未落地,implementation-plan.md
  • 截至 2026-05-22这些结构项已分别落到 internal/reconcile/*internal/access/{planner,subscription,self_service,validation}.gointernal/worker/*

影响:

  • 目前更像可运行 MVP而不是已经完成结构收敛的生产后端。
  • 长期维护和职责边界清晰度会受影响。

结论:

  • 属于已知结构债务,不阻塞受限范围上线,但不应被忽略。

非阻塞项 3subscription 模式缺少现成通过的真实闭环 artifact

证据:

  • 当前看到的 subscription 真实宿主样例仍是:
    • batch_status=partially_succeeded
    • provider_status=degraded
    • access_status=broken
    • 05-import.json
  • 访问预检也仍显示不可用,06-access-preview.json

影响:

  • subscription 不能被纳入当前上线放行范围。

结论:

  • 该项虽已在执行板中被承认为剩余风险,但从上线审查角度仍需明确隔离。

非阻塞项 4reconcile 结果在真实宿主上仍有漂移

证据:

  • self_service 成功样例中,09-reconcile.json 仍是 status=driftedextra_count=1109-reconcile.json

影响:

  • 说明系统主链路成功并不等于现场状态完全收敛。
  • 当前更适合“可上线但需现场治理”,不适合“上线即稳定自治”。

结论:

  • 该问题单独不阻塞 self_service 条件性放行,但阻塞“成熟运维能力”结论。

六、建议整改 PR 列表

以下 PR 列表按优先级排序。

PR-1统一宿主身份模型导入/对账/回滚全面切换到 host_id

目标:

  • 把宿主从“可登记对象”升级为“真实生命周期主对象”。

建议内容:

  • 为导入、reconcile、rollback、assign-subscriptions 等请求增加显式 host_id 输入。
  • 通过 host_id 查宿主记录并派生 base_url、认证策略。
  • 禁止运行时再用 HostBaseURL 作为默认宿主主键。
  • 梳理 hostsimport_batches、provider 状态接口的主键一致性。

预期收益:

  • 彻底消除宿主对象分裂。
  • 为后续多宿主治理和审计打基础。

PR-2managed_resources 增加宿主维度并修复唯一约束

目标:

  • 把资源身份从“宿主外的资源 ID”升级成“宿主内资源身份”。

建议内容:

  • managed_resources 中增加 host_id 或等价外键。
  • 唯一约束改为 host_id + resource_type + host_resource_id
  • GetByResourceIdentity()ListByProviderID()、持久化逻辑同步改造。
  • 增加迁移和回归测试,覆盖“两个宿主同 ID 资源不串扰”场景。

预期收益:

  • 消除跨宿主资源串写与误跳过问题。

PR-3重写 ProbeCapabilities,改成无副作用探测

目标:

  • 让能力探测满足生产保守性要求。

建议内容:

  • 优先使用只读接口、标准版本接口或显式 capability endpoint。
  • 无只读接口时,退化为“版本白名单 + 已知能力矩阵”。
  • 至少不要再通过真实创建接口发空 POST
  • 给真实宿主兼容矩阵补测试与文档。

预期收益:

  • 避免宿主现场因 probe 被污染。

PR-4rollback-provider 走批次资源集回滚,不再按名字重新扫描

目标:

  • 让回滚动作真正基于控制面状态库,而不是宿主现场猜测。

建议内容:

  • rollback-provider 先定位 latest batch再读取该 batch 的 managed resources。
  • 统一调用 RollbackStoredResources()
  • 名字扫描保留为显式“人工应急模式”,不要做默认路径。
  • 增加“存在同名残留资源时不误删”的测试。

预期收益:

  • 明显降低误删风险。

PR-5补齐最小生产运维能力或下调部署文档口径

目标:

  • 让文档承诺和代码现实一致。

建议内容:

  • 二选一:
    • 实装 /metrics、基础限流、最小审计日志
    • 或把 DEPLOYMENT.md 中的生产清单改成“建议外挂能力”,不暗示已内建

预期收益:

  • 避免上线预期与实际能力错配。

PR-6补 subscription 真实闭环验收,并固化 artifact

目标:

  • subscription 模式从“理论支持”转为“真实可放行”。

建议内容:

  • 使用有效凭据复跑真实宿主验证。
  • 固化 import / access-preview / access-status / reconcile / rollback artifact。
  • 失败时把原因收敛到代码问题还是宿主现场问题。

预期收益:

  • 决定 subscription 是否可以进入下一个放行窗口。

七、上线建议

可以上线的范围

  • 单宿主
  • OpenAI-compatible provider
  • self_service 主链路
  • 接受以下前提:
    • reconcile 仍需现场治理
    • 回滚不作为默认高频自动运维动作
    • 不把 /api/hosts 视为稳定宿主管理源

不建议上线的范围

  • subscription 模式对外承诺
  • 多宿主统一治理
  • 高信任自动回滚
  • 把控制面当成已具备完整生产运维能力的平台使用

八、最终判定

综合设计对齐度、代码门禁、真实 artifact 和运维语义,本次审查给出如下正式判定:

  1. 代码质量:PASS
  2. MVP 主链路完整性:PASS
  3. 生产运维闭环完整性:FAIL
  4. 全量生产放行:REJECT
  5. 单宿主 self-service 条件性放行:CONDITIONAL_APPROVED

九、附注

以下事项需要避免被错误解读:

  • go testracevet 全通过,不等于已经具备完整生产运维语义。
  • self_service 成功,不等于 subscription 已成功。
  • 当前存在 hosts API不等于宿主对象模型已经真正完成。
  • 当前有 rollback 能力,不等于 rollback 已达到低误删风险的生产标准。