# 200 Admin:增加管理员 AI 服务商与模型配置 - 类型:需求 - 父级大工单:#14 - 所属 MVP / 版本:#199 / AI规格批量匹配 - 状态:已完成 - 日期:2026-08-14 - Gitea 工单:http://ilaer.eicp.net:8418/chengma/cmautobuy/issues/200 ## 背景与目标 AI 规格匹配需要在不重新发布 Admin 的情况下切换 OpenAI 兼容服务商和模型,同时确保 API Key 不进入数据库、`data/`、日志、页面响应、工单或文档。配置入口及全部写操作仅 允许管理员使用。 ## 最终方案 - 使用 MySQL v20 保存服务商普通配置和非敏感操作审计;生成列唯一索引保证最多一个 服务商处于启用状态。 - 增加 `AISecretStore`,把 API Key 写入部署指定的绝对路径。写入使用同目录临时文件、 `fsync`、原子替换和 `600` 权限;页面只展示是否配置及尾四位掩码。 - 增加仅管理员可访问的服务端渲染配置页,支持新增、编辑、替换/清除密钥、连接测试和 启停。普通配置或密钥变化后会停用并要求重新测试。 - 外部端点只允许 HTTPS;拒绝 URL 凭据、环回、链路本地、元数据和未允许的私网地址, 并在 DNS 解析、实际拨号和重定向阶段重复校验。私有端点只能通过部署静态允许列表开放。 - 连接测试发送不含订单、店铺、用户和 Client 信息的最小请求,不保存完整响应。 ## 改了哪些 - `admin/config.example.yaml`、`admin/config/config.go`:增加密钥路径和私有端点允许列表。 - `admin/model/model.go`、`admin/repository/ai_config.go`、`admin/repository/mysql_db.go`: 增加 AI 配置、审计模型和 MySQL v20 迁移、自检。 - `admin/service/ai_secret.go`、`admin/service/ai_config.go`:实现密钥隔离、配置业务规则、 连接测试和 SSRF 防护。 - `admin/handler/web/ai_config.go`、`admin/handler/web/web.go`、`admin/templates/ai/list.html`: 增加管理员配置页面及全部操作。 - `admin/*_test.go`、`admin/service/*_test.go`、`admin/repository/mysql_db_integration_test.go`: 增加权限、模板、密钥、端点安全和迁移测试。 - `docs/admin/`:同步需求、架构、数据模型、界面和安全基线。 ## 验收结果 | 验收标准 | 结果 | |---|---| | 管理员可管理、测试和启停服务商,且最多一个启用项 | 通过(代码和自动化测试) | | 采购员页面和全部写接口被服务端拒绝 | 通过 | | API Key 不回显,只显示掩码尾号 | 通过 | | 密钥不进入数据库、`data/`、日志和页面 | 通过(代码及假密钥测试) | | 密钥原子写入且失败不破坏旧值 | 通过(单元测试);生产 Linux 路径待部署验证 | | 测试失败不切换当前配置,成功后可热启用 | 通过 | | 不安全 URL 和未允许私网地址被拒绝 | 通过 | | 审计仅记录操作者、时间和非敏感内容 | 通过 | | MySQL 8.4 `_test` 迁移和自检 | 未验证:本机未启用隔离测试库 | | 固定 Go 1.23.0 build、test、vet | 通过 | ## 测试 - 执行的命令: - `go test ./config ./service ./repository` - `go test . -run "Test(AI|MainPages)" -count=1` - `$env:GOTOOLCHAIN="go1.23.0"; go build ./...; go test ./... -count=1; go vet ./...` - 结果:固定 Go 1.23.0 的构建、全量测试和静态检查全部通过。 - **没验证到的部分**:未连接 MySQL 8.4 `_test` 实库;未在生产 Linux 上验证 `/etc/cmautobuy/ai-secrets.yaml` 的最终属主、权限和服务进程读写权限;未调用真实模型。 ## 相关提交 - `018da3f` feat: 增加管理员 AI 模型配置 (#200)