# Clover 客户交付前完整审核报告 审核日期:2026-06-26 审核对象:`/Users/qiyu/Documents/企业培训项目/万牛会L1准备/北哥小红书产品/Clover` 审核口径:以当前工作区为准,包含未提交修改和未跟踪新增文件。本文档只记录审核结论与整改方案,不包含真实密钥值。 ## 一、总审核结论 当前项目**不建议直接交付客户生产使用**。 原因不是单点 bug,而是交付前仍存在安全、部署、测试、业务链路一致性、文件路径、版本冻结和文档可信度等多类风险。前端生产构建可以通过,后端代码可编译,但这只能说明项目有基本可构建性,不能证明已经达到客户可稳定使用的交付标准。 交付前必须先处理 P0 问题,再处理 P1 问题。P2 问题可以排期,但至少要在交付说明中明确边界和已知风险。 ## 二、已执行的只读检查与结果 | 检查项 | 命令/方式 | 结果 | |---|---|---| | 前端生产构建 | `npm run build` | 通过 | | 前端 lint | `npm run lint` | 失败,进入 ESLint 初始化交互,不能作为一键质量检查 | | 后端测试 | `python3 -m pytest -q` | 失败:缺 `celery` 依赖,且临时测试文件导入阶段尝试写 `/app` | | 后端语法编译 | `python3 -m compileall -q app` | 通过 | | 前端依赖安全审计 | `npm audit --audit-level=high --omit=dev` | 失败:Next.js critical,PostCSS moderate | | Git 工作区 | `git status --short` / `git diff --stat` | 43 个已修改文件,另有多批未跟踪文件、截图、验证输出 | | 项目体积 | `du -sh` | 项目约 439M,`frontend/node_modules` 约 328M,`.next` 约 74M | | 代码入口核对 | FastAPI 路由、Next 页面、Celery worker、OpenAPI、Docker 配置 | 发现多处实现/文档/类型不一致 | ## 三、P0 必须修复问题 ### P0-1 明文环境文件和密钥泄露风险 **问题** 项目目录内存在多份 `.env`、备份环境文件、测试环境文件,包含第三方 API Key、JWT/FERNET、数据库密码等敏感配置。虽然这些文件未被 Git 跟踪,但如果按目录整体打包交付给客户,会直接泄露。 涉及文件类型包括: - `.env` - `.env.bak` - `backend/.env` - `backend/.env.bak.*` - `frontend/.env.local` - `test/.env` **风险** - 第三方模型账号被滥用,产生费用。 - 客户或外部人员可伪造 JWT 或解密历史 API Key 密文。 - 数据库、Redis、MongoDB 凭据泄露。 - 客户交付包中出现开发方内部密钥,属于严重交付事故。 **修改方案** 1. 交付包只保留 `.env.example`,删除所有真实 `.env*`、备份 env、测试 env。 2. 立即轮换已经出现在本地文件里的第三方 API Key、JWT_SECRET、FERNET_KEY、数据库密码。 3. 增加交付打包脚本,默认排除 `.env*`、`*.bak*`、`test/.env`。 4. 在 README 中写清楚客户需要自行填写哪些环境变量。 ### P0-2 Next.js 生产依赖存在 critical 漏洞 **问题** `npm audit --audit-level=high --omit=dev` 报告 `next@14.2.0` 存在 critical 级漏洞,PostCSS 存在 moderate 漏洞。 **风险** 客户部署的是 Web 应用,Next.js 相关漏洞可能涉及缓存污染、授权绕过、DoS、SSRF、XSS 等风险。即使某些漏洞只在特定配置下触发,也不应带 critical 依赖交付。 **修改方案** 1. 升级 `next` 到审计建议的修复版本,例如 `14.2.35` 或更高兼容版本。 2. 同步升级 `eslint-config-next`,避免版本错配。 3. 重新执行 `npm install` 更新 `package-lock.json`。 4. 重新验证 `npm run build`、`npm run lint`、`npm audit --audit-level=high --omit=dev`。 ### P0-3 Docker 部署仍是开发形态 **问题** `backend/docker-compose.yml` 中 API 使用: - 源码目录挂载:`.:/app` - `uvicorn --reload` - MySQL/Redis/MongoDB 端口直接映射到宿主机 这更像本地开发配置,不是客户生产部署配置。 **风险** - `--reload` 增加生产不稳定性和资源开销。 - 源码挂载导致容器内容和宿主机状态耦合。 - 数据库、Redis、MongoDB 暴露到宿主机端口,若服务器安全组配置不当,可能被外部访问。 **修改方案** 1. 拆分 `docker-compose.prod.yml`。 2. 生产 API 命令改为不带 `--reload` 的固定进程。 3. 生产环境不挂载源码目录,只挂载上传目录和持久化数据卷。 4. MySQL/Redis/MongoDB 不暴露公网端口,只在 Docker 内部网络访问。 5. 增加生产部署文档,明确开发 compose 与生产 compose 的区别。 ### P0-4 CORS 生产未收口 **问题** `backend/main.py` 中 CORS 仍为 `allow_origins=["*"]`。 **风险** 任意来源页面都可以向后端发起跨域请求。即使接口需要 JWT,这仍会扩大攻击面,不符合客户生产交付标准。 **修改方案** 1. 增加 `CORS_ORIGINS` 环境变量。 2. 生产环境只允许客户前端域名。 3. 开发环境可保留 localhost 白名单。 4. `APP_ENV=production` 时禁止 `*`。 ### P0-5 测试不可一键运行 **问题** 后端 `python3 -m pytest -q` 失败: - 当前环境缺 `celery`。 - `backend/test_color_compare.py` 在导入阶段创建 `/app/...`,触发权限错误。 - 顶层临时验证脚本会被 pytest 自动收集。 前端 `npm run lint` 失败: - 进入 Next.js ESLint 初始化交互,不是非交互式检查。 **风险** 交付前无法用自动化测试证明项目状态稳定。客户或接手工程师也无法复现质量检查。 **修改方案** 1. 后端测试固定用 Docker test profile 或 `.venv`,并写入 README。 2. 临时验证脚本移出 pytest 自动收集范围,或改名不以 `test_` 开头。 3. 所有测试不得在 import 阶段写文件。 4. 前端补 `.eslintrc` 或 `eslint.config.*`,让 `npm run lint` 非交互式执行。 5. 增加统一验收命令,例如 `make verify` 或 `scripts/verify.sh`。 ### P0-6 默认账号和默认密码风险 **问题** `backend/scripts/seed_data.py` 内置 admin/supervisor/operator 三类账号,并使用同一默认密码。 **风险** 如果客户生产环境直接使用 seed 数据且未改密,任何知道交付包的人都可能登录系统。 **修改方案** 1. seed 仅用于初始化,不得作为生产长期账号配置。 2. 首次登录强制改密。 3. 生产交付说明中明确默认账号仅用于首次进入。 4. 客户验收后删除或禁用默认密码账号。 ## 四、P1 交付前应修复问题 ### P1-1 当前工作区不是干净交付版本 **问题** 当前 Git 工作区存在 43 个已修改文件,并有大量未跟踪文件,包括新增组件、截图、验证输出、计划文档等。 **风险** 无法判断客户拿到的是稳定版本、实验版本还是半成品版本。后续问题排查也没有明确基线。 **修改方案** 1. 先确定交付基准 commit。 2. 将要交付的代码整理成干净分支。 3. 删除或排除截图、验证输出、缓存文件、临时计划文档。 4. 打交付 tag,例如 `delivery-beige-xhs-v1.0.0`。 ### P1-2 文案/图片多选语义与真实处理不一致 **问题** 前端文案页允许多选,图片页也允许多选;后端选择接口只是把当前候选置为 `is_selected=True`,不会取消同任务下旧选择。生成图片时实际只取第一条文案作为语境;审核队列也只展示第一条选中文案和第一张选中图。 **风险** 客户会以为自己选择了多条文案/多组图片,但生成、审核、打包结果不一定按选择生效。最终交付内容可能文图不匹配。 **修改方案** 1. 明确产品语义:每套 A/B/C 选择一条文案和一组图片,或明确只允许单选。 2. 如果保留三套,后端选择接口应按 `task_id + strategy` 清理旧选择。 3. 生图、审核、打包全部按 strategy 配对。 4. 前端按钮文案和 UI 状态同步改为“每套选择”。 ### P1-3 文件路径存储和读取不稳定 **问题** 项目里同时存在: - 产品图存容器绝对路径。 - 生成图用 `UPLOAD_BASE_PATH` 相对路径。 - 静态服务挂载 `/uploads`。 - 打包任务用 URL 反推本地路径读取图片。 **风险** 本地运行、Docker 运行、客户服务器部署时路径根目录不同,可能出现图片前端能看但 worker 读不到、worker 写了但前端访问不到、打包 zip 里缺图。 **修改方案** 1. 数据库只保存相对对象路径,例如 `products/{workspace_id}/{product_id}/{file}`。 2. 后端统一用 `UPLOAD_ABS_ROOT` 拼本地绝对路径。 3. 前端 URL 统一由后端转换成 `/uploads/...`。 4. 打包任务不得从 URL 反推路径,应使用统一路径解析函数。 ### P1-4 交付包状态查询接口有副作用 **问题** `GET /delivery-packages/{package_id}/download` 查询状态时,如果状态是 `ready`,会改成 `downloaded`。 **风险** 前端轮询或用户刷新页面就会改变业务状态。客户看到的状态可能不是实际下载行为。 **修改方案** 1. 状态查询接口只读,不修改状态。 2. 文件真正开始下载或下载成功后再标记 `downloaded`。 3. 如果无法检测下载成功,至少单独提供“确认已下载”接口。 ### P1-5 任务创建产品校验不完整 **问题** 当 `need_product_image=True` 时会校验产品存在和产品图;但如果关闭产品入镜,可以创建指向不存在产品的任务。 **风险** 后续 worker 构建产品信息时可能失败,或生成质量不可控。 **修改方案** 1. 无论是否产品入镜,都校验 `product_id` 存在、属于当前 workspace、处于 active。 2. `need_product_image` 只额外控制是否要求产品参考图。 ### P1-6 裂变源文案可能直接使用 JSON 字符串 **问题** `TextCandidate.content` 存储的是 JSON 字符串;裂变服务读取源文案时直接返回该字段,没有稳定解析出纯正文。 **风险** 裂变 prompt 可能拿到 JSON 原文,影响生成质量和输出格式。 **修改方案** 1. 裂变读取源文案时先解析 JSON。 2. 拼接 `title/content/tags` 为纯发布文案。 3. 解析失败才回退原始文本。 ### P1-7 OpenAPI、前端 DTO、后端实现不一致 **问题** 存在多处契约分叉,例如: - `SwitchWorkspaceResponse` 前端声明有 `role`,后端实际不返回。 - 导出接口直接返回数组或 CSV,不走统一 `{ code, data }` 包络。 - README 和 OpenAPI 对已有功能描述滞后。 **风险** 后续开发者按文档接入会出错;前端类型不能真实约束后端行为。 **修改方案** 1. 以实际 FastAPI 路由重新梳理 OpenAPI。 2. 前端 DTO 与后端响应逐项对齐。 3. 导出类接口如果故意不走包络,应在文档里明确标注。 4. 增加契约测试,至少覆盖前端已调用接口。 ### P1-8 前端 SSE 和 API 基础地址部署边界不清 **问题** 前端 API 默认相对路径,Next rewrite 默认指向 `http://localhost:8000`;SSE 另有 `NEXT_PUBLIC_SSE_BASE_URL`,注释说明必须绕过 Next rewrite。 **风险** 客户部署时如果只配置 API 地址而没配置 SSE 地址,实时进度可能失效。跨域时还会叠加 CORS 和网络配置问题。 **修改方案** 1. 生产 `.env.example` 明确列出 `NEXT_PUBLIC_API_BASE_URL` 和 `NEXT_PUBLIC_SSE_BASE_URL`。 2. 部署文档给出同域反代和跨域直连两种配置。 3. 增加 SSE 连通性验收步骤。 ## 五、P2 建议修复问题 ### P2-1 README 和真实项目状态错位 **问题** 后端 README 仍写 migration 到 004,但实际已有 021;前端 README 写“五屏骨架”,实际已有 dashboard、board、history、fission、settings 等页面。 **风险** 客户或接手人员按 README 操作会误判项目状态。 **修改方案** 1. 重写根 README、前端 README、后端 README。 2. 以“客户如何启动、如何配置、如何验收”为中心,而不是开发历史。 3. 加入故障排查章节。 ### P2-2 交付目录过重且包含临时产物 **问题** 项目约 439M,其中 `frontend/node_modules` 约 328M,`.next` 约 74M;目录中还有大量截图、缓存、验证输出。 **风险** 交付包臃肿,且容易夹带开发过程文件、客户素材或内部验证信息。 **修改方案** 1. 交付源码包排除 `node_modules`、`.next`、`__pycache__`、`.pytest_cache`、截图、verify_output。 2. 提供 `package-lock.json` 和 `requirements.txt`,由客户环境安装依赖。 3. 单独准备必要的样例素材,不混入开发截图。 ### P2-3 fallback 结果可能掩盖真实失败 **问题** 视觉分析、标杆分析、裂变等模块有 fallback 逻辑。fallback 能避免空结果,但客户可能无法分辨结果是模型真实分析还是兜底模板。 **风险** 客户把兜底结果当真实 AI 结果使用,影响内容质量。 **修改方案** 1. 所有 fallback 结果在 UI 明确标注“兜底生成,需要人工复核”。 2. 交付包中保留来源字段。 3. 日志和任务详情中保存失败原因。 ### P2-4 Python 依赖缺少安全审计 **问题** 本地没有 `pip_audit`,因此没有完成 Python 依赖漏洞审计。 **风险** 后端依赖可能存在已知漏洞但未被发现。 **修改方案** 1. 在 CI 或 Docker test profile 中安装并执行 `pip-audit -r requirements.txt`。 2. 将结果纳入交付前验收。 ## 六、建议整改顺序 1. 先冻结交付分支,清理工作区,明确客户要拿到哪个版本。 2. 删除真实环境文件并轮换密钥。 3. 升级 Next.js 并通过 `npm audit`。 4. 拆生产部署配置,收口 CORS 和端口暴露。 5. 修测试体系,让前后端检查可一键运行。 6. 修文案/图片选择、审核、打包之间的语义一致性。 7. 修统一文件路径策略。 8. 重写客户交付 README 和验收清单。 9. 跑完整端到端验收。 ## 七、最终交付前 Checklist 交付前必须逐项确认: - [ ] 交付包不包含任何真实 `.env*`、备份 env、测试 env。 - [ ] 所有已泄露风险的 Key 和密码已轮换。 - [ ] `npm run build` 通过。 - [ ] `npm run lint` 非交互式通过。 - [ ] `npm audit --audit-level=high --omit=dev` 无 high/critical。 - [ ] `python3 -m pytest -q` 在标准环境通过。 - [ ] 后端依赖完成漏洞审计。 - [ ] 生产 Docker 配置不使用 `--reload`。 - [ ] 数据库、Redis、MongoDB 不对公网暴露。 - [ ] CORS 仅允许客户前端域名。 - [ ] 默认账号首次登录必须改密。 - [ ] 产品图上传、生成图展示、打包下载在生产部署环境跑通。 - [ ] SSE 实时进度在生产域名下跑通。 - [ ] 文案选择、图片选择、审核、打包结果一致。 - [ ] 客户 README 与实际启动方式一致。 - [ ] Git 工作区干净,并打交付 tag。 ## 八、最终判断 本轮整改后,代码层 P0/P1 阻断项已完成核销,可以进入客户交付前最终验收阶段。 正式交付仍必须满足: 1. 不直接整目录拷贝,必须使用干净交付包并排除真实 `.env*`、`node_modules`、`.next`、验证产物和截图。 2. 已暴露风险的 Key、默认密码、数据库密码全部轮换。 3. 用客户部署方式完成一次真实端到端验收。 ## 九、本轮修复核销记录(2026-06-26) 本轮已按“B 类功能 bug → A 类交付卫生 → C 类安全收口”的顺序完成整改,并做了交叉验证。 ### 已核销 - `apiports` 图片编辑备份已改为 `/chat/completions` 多模态参考图路径;`codeproxy` 保持 `/images/edits`。 - A/B/C 三套内容已按 `strategy` 绑定文案和图片,生图不再复用第一条文案。 - 提交审核前强制校验 A/B/C 每套都有已选文案,并且每套选满 `task.image_count` 张图片。 - 审核队列新增 `selected_sets`,前端可按 A/B/C 展示,同时保留旧字段兼容。 - 下载状态 GET 和文件下载 GET 均已改为只读;前端下载成功后显式调用 POST 标记 `downloaded`。 - 创建任务无论是否产品入镜,都会校验产品存在且属于当前 workspace。 - 裂变源文案会解析 JSON 候选并提取标题/正文/卖点,不再把整段 JSON 字符串当源文案。 - 工作区切换响应补齐 `role` 字段。 - 标杆 fallback 结果已在 API 和前端显式标注,任务创建不再选用 fallback 标杆。 - `/uploads` 静态挂载统一使用 `UPLOAD_ABS_ROOT`,避免写盘目录和访问目录不一致。 - 新增 `.env.example`、`backend/.env.example`、`frontend/.env.example`。 - 新增 `.dockerignore`、`backend/.dockerignore`、`frontend/.dockerignore`,并扩展 `.gitignore` 排除验证产物和截图。 - 新增 `docker-compose.prod.yml`,生产启动不挂载源码、不使用 `--reload`,数据库/Redis/Mongo 不暴露宿主端口。 - 新增根目录 `README.md`,更新前后端 README,使迁移版本、页面数量、SSE/API 配置说明与当前代码一致。 - 新增 `backend/pytest.ini`,后端 pytest 只收集 `backend/tests`,避免临时验证脚本被误收集。 - 前端 lint 已从交互式 `next lint` 改为 ESLint 9 flat config,可一键运行。 - Next 已升级到 `16.2.9`,并用 `overrides` 将依赖树中的 `postcss` 收到安全版本。 - 生产 CORS 已从硬编码 `*` 改为 `CORS_ALLOW_ORIGINS`,生产环境会过滤通配符。 - 默认种子密码 `Clover2026!` 在生产登录中被拒绝;生产执行 seed 必须显式设置非默认 `CLOVER_SEED_PASSWORD`。 ### 最终验证命令 - `cd backend && python3 -m compileall -q app tests`:通过。 - `cd backend && python3 -m pytest`:通过,`113 passed`。 - `cd frontend && npm run lint`:通过,0 error,仍有 12 个 warning。 - `cd frontend && npm run build`:通过,Next `16.2.9`,webpack 构建。 - `cd frontend && npm audit --omit=dev`:通过,`found 0 vulnerabilities`。 - `docker compose -f docker-compose.prod.yml --env-file .env.example config`:通过。 ### 仍需交付前人工确认 - 真实 `.env` 和历史 `.env.bak` 文件仍在本地工作区,未做破坏性删除;交付包必须排除,且已暴露风险的 Key/密码必须轮换。 - 当前 git 工作区仍有大量既有改动和未跟踪文件;正式交付前需要冻结版本、确认 diff、打交付 tag。 - Python 依赖尚未执行 `pip-audit`,因为本地未安装该工具;建议在 CI 或交付镜像中补跑。 - 尚未在真实客户域名、真实数据库、真实 Redis/Mongo、真实 AI provider 恢复后跑完整端到端验收。