Files
secrets/plans/code-review-fixes-2026-04-11.md
2026-04-11 17:04:18 +08:00

202 lines
6.6 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.
# Code Review 修复计划
**日期**: 2026-04-11
**来源**: 三份 code review 报告提炼合并
**范围**: 7 项修复 + 1 项风险提示(不纳入本次修复)
---
## 1. `secrets-core` 导入/导出链路
**目标**: 修复"导入丢失 secret type"。
**涉及文件**:
- `crates/secrets-core/src/models.rs`
- `crates/secrets-core/src/service/export.rs`
- `crates/secrets-core/src/service/import.rs`
**实施项**:
1.`ExportEntry` 增加可选字段 `secret_types: Option<BTreeMap<String, String>>`,键为 secret 名,值为 type。
2. 修改导出逻辑,除了导出 `secrets` 的值,也把每个 secret 的 `type` 一并导出。
3. 修改导入逻辑,把 `entry.secret_types` 传给 `AddParams.secret_types`,不再用 `&Default::default()`
4. 明确兼容旧导出文件:`secret_types` 缺失时继续默认 `"text"`
**验证**:
1. 新增 round-trip 测试:带 `password` / `key` / `text` 三种类型的导出再导入,类型保持不变。
2. 新增向后兼容测试:旧格式导入时仍成功,默认回落到 `"text"`
---
## 2. `secrets-core` env map
**目标**: 修复环境变量名碰撞。
**涉及文件**:
- `crates/secrets-core/src/service/env_map.rs`
**实施项**:
1. 统一分隔符策略:把字段名里的 `.` 替换成 `__`(双下划线),保留原始 `_` 为单下划线,避免 `db.password``db_password` 碰撞。
2. 如仍发生碰撞,显式返回错误,而不是 `HashMap::insert` 静默覆盖。
**验证**:
1. 添加测试覆盖:
- `db.password` vs `db_password`
-`prefix` 的情况
- 多 entry 合并时碰撞
2. 确认输出变量名文档与实现一致。
---
## 3. `secrets-core` rollback
**目标**: 修复回滚路径中的 TOCTOU 和"使用旧 live 值"问题。
**涉及文件**:
- `crates/secrets-core/src/service/rollback.rs`
**实施项**:
1. 把首次读取 live entry 的逻辑移入事务内,并与 `FOR UPDATE` 合并,避免在加锁前基于过期数据做决策。
2. 在拿到加锁后的 live row 后,再决定错误消息、审计字段和更新语句输入。
3. 明确回滚语义:
- 若产品希望"完全回到快照",则 `name/notes` 也从快照恢复。
- 若希望保留当前标识,则代码和文档都要显式说明此设计决策。
4. 避免混用事务前的 `live_entry` 与事务内的 `lr`
**验证**:
1. 新增测试覆盖:
- 回滚时恢复字段是否符合预期
- 并发更新 + 回滚场景不再依赖过期值
---
## 4. `secrets-core` API key
**目标**: 修复 `regenerate_api_key` 返回未持久化 key。
**涉及文件**:
- `crates/secrets-core/src/service/api_key.rs`
**实施项**:
1. 检查 `UPDATE``rows_affected()`
2. 若为 `0`,返回 `NotFoundUser` 或等价业务错误。
3. 可选:改成 `UPDATE ... RETURNING api_key`,减少"先生成后判断"的分支。
**验证**:
1. 新增测试:
- 正常用户可返回新 key
- 不存在用户时返回错误,而不是返回伪成功 key
---
## 5. `secrets-mcp` tools
**目标**: 修复 MCP 层三个问题:
- `secrets_add` 提交后再回查 entry 的竞态
- `secrets_find` 计数失败被吞成 0
- `secrets_rollback` 冗余要求 encryption key
**涉及文件**:
- `crates/secrets-mcp/src/tools.rs`
- 可能连带 `crates/secrets-core/src/service/add.rs` 的返回结构
**实施项**:
1.`svc_add` 直接返回 `entry_id`MCP 不再在提交后用 `name+folder+user_id` 二次 `resolve_entry`
2. `secrets_find` 中移除 `.unwrap_or(0)`
- 要么把计数错误向上传播
- 要么返回 `total_count: null` / `count_unavailable: true`
3. `secrets_rollback` 改为只要求用户身份,不要求 encryption key。
4. 同步修正工具描述文案,避免 schema 与实际行为不一致。
**验证**:
1. `secrets_add`:父子关系新增时直接使用返回的 `entry_id`
2. `secrets_find`:模拟 count 失败时,结果不再伪装成 `0`
3. `secrets_rollback`:无 key 时可执行,工具描述与行为一致。
---
## 6. `secrets-mcp` Web 会话校验
**目标**: 让 JSON API 与页面路由的 `key_version` 校验对齐。
**涉及文件**:
- `crates/secrets-mcp/src/web/mod.rs`
- `crates/secrets-mcp/src/web/entries.rs`
- `crates/secrets-mcp/src/web/account.rs`
- 其他仅使用 `current_user_id()` 的 JSON handler
**实施项**:
1. 抽一个适用于 JSON API 的用户校验辅助函数。
2. 该函数应同时完成:
- session 取 `user_id`
- 加载用户
- 比对 `SESSION_KEY_VERSION` 与 DB `key_version`
3. 页面路由继续保留 `require_valid_user`JSON 路由统一改用等价校验。
4. 统一失败语义:
- HTML 路由:重定向 `/login`
- JSON 路由:返回 `401`
**验证**:
1. 新增测试覆盖:
- `key_version` 一致时 JSON API 正常
- `key_version` 不一致时 JSON API 返回 `401`
- 用户删除/会话损坏时返回正确错误
---
## 7. Web API 输入校验
**目标**: 补齐 Web JSON API 的长度校验,避免 DB 约束错误落成 500。
**涉及文件**:
- `crates/secrets-mcp/src/web/entries.rs`
- 如有需要,抽公共 helper 到 `web/mod.rs` 或单独模块
**实施项**:
1.`api_entry_patch` 对齐 MCP 的长度规则:
- `folder <= 128`
- `type <= 64`
- `name <= 256`
- `notes <= 10000`
2. 视情况复用 `validation` 常量,避免 Web/MCP 两套上限漂移。
3. 保持错误返回为 `400`,而不是依赖数据库报错。
**验证**:
1. 为超长 `folder/type/name/notes` 分别补测试。
2. 确认错误文案和现有本地化风格一致。
---
## 8. 暂不纳入本次修复(风险提示)
- 调试日志记录加密密钥片段(`extract_enc_key_or_arg` 在 debug 级别记录 key 前后缀)
- `encryption_key` 作为工具参数带来的日志/对话暴露面
**处理方式**: 记录为"接口安全风险提示",待后续单独决定是否收紧 debug 日志、调整工具描述或限制参数传 key 的路径。
---
## 实施顺序
1. `secrets-core` 导入/导出链路
2. `secrets-core` env map
3. `secrets-core` rollback
4. `secrets-core` API key
5. `secrets-mcp` tools
6. `secrets-mcp` Web 会话校验
7. `secrets-mcp` Web 输入校验
**原因**: 先修 core 语义和返回结构,再修上层接入。`svc_add` 返回结构、rollback 语义、export/import 格式都属于底层契约,适合先稳定。
---
## 验证与收尾
1. 先跑相关单元/集成测试。
2. 再跑全量:
```bash
cargo fmt -- --check
cargo clippy --locked -- -D warnings
cargo test --locked
```
3. 若涉及 `crates/**` 的实际改动,按 `AGENTS.md` 约定检查版本/tag并执行 `./scripts/release-check.sh`。