# 生产上线前风险修复计划与实施记录

## 背景

项目准备正式部署前，对用户端、管理后台、后端服务和容器编排进行上线审查。审查发现并发排队、每日额度、安全配置、登录防护、生产部署、自动化验证及代码维护性仍存在风险。本次按“先修复阻断上线的问题，再补齐验证与维护性”的顺序一次性收口。

## 修复范围

1. 修复聊天请求进入排队后引用未定义变量、流式响应中断的问题，并覆盖排队、超时、拒绝和释放场景。
2. 为每日问答额度增加按自然日自动重置机制，避免额度累计后永久不可用，并保证并发扣减一致性。
3. 为短信发送、短信验证码校验、图形验证码校验和管理员登录增加 Redis 限流与失败锁定；Redis 不可用时采用进程内降级保护。
4. 对模型 API Key、飞书 AppSecret、阿里云 AccessKey Secret 等敏感配置进行应用层加密存储；读取接口只返回掩码，更新时留空不覆盖已有密钥。
5. 将用户和管理员退出后的 Token 撤销状态迁移到 Redis，并按 Token 剩余有效期保存；Redis 不可用时保留进程内降级机制。
6. 新增生产镜像与生产编排：前端使用 Nginx 静态服务，后端关闭 debug 和 mock，数据库与 Redis 不暴露公网端口，生产密钥必须显式配置。
7. 修复自动验证脚本，补充后端关键单元测试、前端构建、数据库迁移和 Docker Compose 配置检查，并锁定依赖版本。
8. 拆分管理后台超大单文件和后端高复杂度模块的职责边界；优先提取系统设置定义、登录视图和共享安全组件，保持现有行为不变。

## 上线验收条件

- 排队状态能够正常返回位置提示，排队完成、超时、取消和异常均释放占用。
- 用户跨自然日首次提问时自动清零昨日用量，同日并发请求不能绕过额度。
- 短信和登录接口具备可配置限流，错误次数达到阈值后临时锁定。
- 管理后台和接口响应中不出现任何完整密钥；数据库中的新保存密钥不是明文。
- 多 worker 下退出登录立即生效，Token 撤销状态在服务重启后仍可由 Redis 保留。
- `docker-compose.prod.yml` 不包含开发弱口令、mock、debug、Vite 开发服务器和数据库公网端口。
- 后端测试、迁移检查、用户端构建、管理后台构建和 Compose 检查全部通过。
- 拆分后页面功能和 API 行为保持一致，核心文件职责更清晰。

## 实施记录

### 已完成批次

1. `5aca872`：修复排队分支未定义变量；新增每日额度日期、数据库迁移和按上海自然日自动重置。
2. `aedecb3`：新增短信手机号/IP 限流、短信验证码错误锁定、管理员登录限流与锁定，并将退出 Token 撤销状态迁移到 Redis。
3. `9fb3dad`：新增敏感配置加密服务；模型 API Key、飞书 AppSecret、阿里云 AccessKey Secret 加密保存，后台接口仅返回掩码。
4. `fb39c9c`：新增生产前端静态镜像、生产网关和 `docker-compose.prod.yml`，关闭 debug/mock，内部服务不暴露宿主机端口。
5. `7f835ec`：锁定后端直接依赖版本，修复 SQLite 验证，新增六项关键测试并扩展自动验证脚本。
6. `076fcb9`：将后台登录页面从总控页面提取为独立组件；安全状态与敏感配置已分别由独立后端服务承载。

### 验证结果

- `./scripts/phase6_verify.sh` 全部通过：44 个 OpenAPI 路径、6 项关键测试、4 个数据库迁移、用户端构建、管理端构建、开发与生产 Compose 配置检查。
- 三个生产镜像均构建成功：后端、用户端 Nginx 静态镜像、管理后台 Nginx 静态镜像。
- 隔离生产环境以 4 个后端 worker 启动成功，MySQL 和 Redis 健康检查通过。
- `/api/health`、`/`、`/login/` 和 `/login/assets/...` 均返回 200。
- 实际接口验证：管理员登录成功；飞书 Secret 接口返回 `******`；数据库保存值以 `enc:v1:` 开头且不包含明文；管理员退出后原 Token 返回 401。
- 验证完成后已删除隔离容器、网络和测试数据卷，不影响开发环境及正式数据。

### 实施决策

- 自然日统一按 `Asia/Shanghai` 计算，符合国内用户业务口径。
- Redis 是生产环境安全状态和并发队列的共享存储；短暂故障时使用进程内降级，保证接口仍有基础保护。
- 历史明文密钥允许兼容读取，下一次后台保存时转为密文，避免升级直接破坏现有配置。
- 生产环境缺少 `CONFIG_ENCRYPTION_KEY` 时后端拒绝启动，防止误以为已经加密而实际使用弱兜底密钥。
- 本轮只拆分行为边界清晰的登录页、安全状态和密钥服务，不重写已经稳定运行的飞书检索算法；后续页面继续按业务模块渐进拆分。
