实现密钥批量管理(P0-5)。后端 .env 读写 + API + 前端页面。 ## 后端: Key Manager 服务 创建 backend/app/services/key_manager.py: 核心功能: - 读取 Profile 的 .env 文件中指定密钥字段 - 脱敏显示: 前3字符 + "**...**" + 后4字符 (如 "sk-**...**b12c") - 白名单字段: DEEPSEEK_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY, FEISHU_APP_ID, FEISHU_APP_SECRET - 批量覆盖: 写入新值到 .env 文件 (操作前自动备份 .env → .env.bak) - 批量检查: 扫描全部 Profile 的 .env, 返回缺失字段列表 - 差异视图: 对比各 Profile 同一字段的值 (只显示有无和长度, 不显示原文) - 不写入审计日志原文(只记录 action + profile 名 + 字段名) ## 后端: Keys API 创建 backend/app/api/keys.py, 全部 require_role("owner","operator") ### GET /api/v1/keys 返回密钥字段列表: ```json [{"profile": "hebo", "fields": {"DEEPSEEK_API_KEY": "sk-**...**b12c", ...}, "missing": 0}] ``` ### POST /api/v1/keys/batch-overwrite 批量覆盖密钥: - body: {profile_names: [...], key_name: "DEEPSEEK_API_KEY", new_value: "sk-xxx", confirmation: "我确认覆盖 N 个 Profile"} - 验证 confirmation 短语精确匹配 - 逐 Profile 写入 + 返回成功/失败列表 ### POST /api/v1/keys/batch-scan 批量检查缺失: - body: {profile_names: [...]} 或全部 Profile - 返回缺失统计 + 详情 ### GET /api/v1/keys/diff 差异视图: - query: ?profiles=hebo,ops-engineer - 返回对比表: 横向 Profile, 纵向字段, 值状态(有/无/长度) ### GET /api/v1/keys/export CSV 导出批量检查结果 ## 前端: Keys 页面 修改 frontend/src/pages/KeysPage.tsx: ### 操作栏 - [批量覆盖] 按钮 → Modal - [批量检查] 按钮 → 扫描结果展示 - Profile 筛选下拉 - 搜索密钥字段 ### 密钥列表 - Table 组件 - 列: ☐复选框, Profile名, 各密钥字段(脱敏显示), 缺失计数 - 缺失字段标红 ❌ - 差异视图切换 ### 批量覆盖 Modal - 下拉选择密钥字段 - 输入新值(密码框, 可切换明文) - 预览: "将覆盖 N 个 Profile 的 {KEY_NAME}" - 当前值脱敏预览 - 输入确认短语: "我确认覆盖 N 个 Profile" - 确认后执行 → 进度提示 → 成功/失败列表 ### 批量检查结果 - 显示扫描结果表: Profile, 缺失字段列表, 缺失数 - 支持导出 CSV (下载按钮) - 缺失行标红 ### 差异视图 - 勾选 2+ Profile → "查看差异" - 对比表: 横向 Profile, 纵向字段, ✅有/❌无 - 差异行黄色高亮 - "只看差异" 切换 ### 四态覆盖 + 审计日志 注册路由, 完成后提交。