为什么要突然停下来“还债”?

从 2026 年春天到秋天,我们几乎保持着每周都在出新站点、每周都在上大功能的狂飙节奏。但到了 9 月底,我看着越来越庞大的代码库和快要突破百张表的数据库,心里开始发毛:很多早期为了赶进度写出来的接口缺少严格的边界检查,数据库里有些表的索引还是几个月前随手建的,连正式的迁移账本都没有。

我告诉自己:不能再这么闷头往前冲了,必须踩一脚刹车,把地基彻底加固一遍。

10月1日–3日:两轮全仓深度安全审计

十一假期的前三天,我把仓库里所有暴露在公网上的 API 和后台任务挨个过了一遍筛子,一连堵上了好几个藏得很深的隐患:

  • 清除“超时默认放行”与 GC 竞态:早期旧版内容审核接口里有一处逻辑是“如果 AI 审核请求超时就默认先放行”,这明显有被恶意卡超时绕过审核的风险,我直接改成了严格的失败闭环;同时修复了媒体云盘垃圾回收(GC)在极端并发下可能误删刚上传文件的竞态漏洞;
  • 跨子域信任收紧与 Cookie 同源守卫:严格校验所有回调地址的子域白名单,并给全站所有涉及写 Cookie 的接口统一套上了同源守卫(Origin / Referer 强校验),彻底堵死 CSRF 跨站伪造请求的口子;
  • sops + age 密钥加密与迁移账本:把原本裸放在配置里的敏感环境变量统一用 sops + age 非对称加密锁进版本库,并正式建起了 schema_migrations 数据库迁移追踪账本。

10月4日(PR #41):一口气交付数据库 40 项治理(DB-01 ~ DB-40)

紧接着在 10 月 4 日(PR #41),我把数据库里攒下的所有历史遗留问题列了一张从 DB-01 到 DB-40 的 40 项清单,一次性全部清零:

  1. 划分四大清晰数据库域:把核心账户域、社区内容域、Minecraft 游戏业务域与日志统计域的边界、外键约束和级联策略彻底理顺;
  2. MySQL ngram 中文全文检索:替掉了以前搜索帖子和文档时低效的 LIKE '%关键词%' 全表扫描,改用原生 ngram 分词全文索引,搜中文又快又准;
  3. 经验与积分防刷唯一账本:以前发奖励靠代码逻辑判断,遇到网络卡顿连点两下可能发出双倍经验。这次直接把幂等唯一键下沉到数据库账本表里,从物理层面杜绝任何并发刷分;
  4. AES-256-GCM 自动备份与真库恢复演练:不仅写了定时全量备份并用 AES-256-GCM 加密上传的脚本,我还专门拉起了一个空白测试实例,亲手把加密备份包解密导进去跑通了完整校验——因为没演练过的备份,跟没备份没有任何区别。