🔴 Analyzer 严重问题

以下问题可能导致数据泄露、安全风险或资金损失,需优先修复。

🔴 P01 ✅ 已修复 transactions · CSV导入

CSV 覆盖式导入,数据不可恢复

API:POST /api/transactions/:billId/upload
问题描述:CSV 导入时,后端执行 DELETE FROM transactions WHERE bill_id = ? 全量删除旧数据,再 INSERT 新数据。旧数据被永久清除,无法恢复。
修复内容:
  1. DELETE 改为 UPDATE ... SET deleted_at = now()(软删除),旧数据保留在数据库中
  2. ✅ GET /transactions 和 Admin 后台均过滤 deleted_at IS NOT NULL 的记录
  3. ✅ 数据库已支持软删除(deleted_at 列,迁移添加)
  4. ⚠️ 若需彻底清理,建议通过 Admin 审计日志清理接口定期删除超过 90 天的软删除记录
影响:
  • 旧数据全部被不可恢复地删除
  • 用户误上传、空文件上传、列错位上传都会导致历史数据全部丢失
  • CSV 上传没有"追加"模式
改进建议:
  1. ✅ 已修复:软删除机制替代全量 DELETE
  2. 可进一步增加"追加模式"与"覆盖模式"选项
✅ 已修复 🔴 P02 ✅ 已修复 bills · 邀请成员

邀请成员无通知机制,功能不可用

API:POST /api/bills/:id/invite
修复内容:
  1. POST /api/bills/:id/invite 在事务中同时插入 bill_invitationsnotifications 记录
  2. ✅ 被邀请人可在通知列表中看到"新账单邀请"通知
  3. ❌ 无短信/邮件实时推送(仅站内通知,可接受)
  4. ❌ 被邀请人登录后无弹窗/横幅主动提示(可选改进项)
🔴 P03 ✅ 已修复 auth · 图形验证码

图形验证码存内存 Map,重启后失效

API:GET /api/auth/login-captcha · GET /api/auth/register-captcha
问题描述:验证码 ID 和答案存在内存 Map 中(global.captchaStore),服务器重启后全部清空。用户拿到的 captchaId 在重启前一直有效,但重启后 map.get(captchaId) 永远返回 undefined。
修复内容:
  1. ✅ 验证码存储迁移至数据库 captchas 表(id, answer, type, expire_at, ip_address, created_at
  2. ✅ 服务启动时自动调用 ensureCaptchasTable() 创建表(如不存在)
  3. verifyRegisterCaptcha() / verifyLoginCaptcha() 均从数据库读取并验证
  4. register-captcha / login-captcha 生成时写入数据库并设置 expire_at
  5. ✅ 验证后自动删除已使用的验证码记录
影响:
  • 服务器重启后,所有已发出的图形验证码 ID 全部失效
  • 用户输入正确的图形验证码答案,但后端 map 中已无此 ID
  • 登录/注册页面显示验证码但提交永远失败,需刷新页面重新获取
改进建议:
  1. ✅ 已实现:验证码存储到数据库 captchas
  2. 图形验证码与 IP 绑定(防刷)