From 3f120417d1b944b144c284726328658e5d2c7d27 Mon Sep 17 00:00:00 2001 From: chenjw28 <792430652@qq.com> Date: Tue, 15 Sep 2026 18:07:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ROADMAP.md | 17 ++++++ docs/STATUS.md | 2 + docs/TECH_DEBT.md | 140 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+) diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 558fbd5..8894f92 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -98,6 +98,23 @@ geMoldInsight 已从历史单体逐步演进为“双业务模块 + 共享平台 --- +### 3.1 后端设计治理批次(2026-09 设计审查产出) + +> 2026-09-15 完成 moldinsight 后端设计审查,产出的具体治理批次是当前下一阶段最具体的执行计划。 +> 债务明细与逐项现状见 [TECH_DEBT.md](TECH_DEBT.md) §3(D5–D14);本小节只描述批次、顺序与每批归属。 + +| 批次 | 主题 | 内容 | 对应债务 | +|------|------|------|---------| +| 批次 0 | 安全与诚实(0.5–1 天) | `/api/status/{task_id}` 补鉴权 + 任务归属校验;`pythonocc_available` 真实检测;bcrypt 超长密码拒绝;SECRET_KEY / RUSTFS_* 惰性校验补齐 | D5 | +| 批次 1 | 部署正确性(1–2 天) | 主链路改走 RustFS(分派入参 `file_path` → `stp_file_id`,worker 按 object_key 下载解析);compose 共享卷兜底(过渡);alembic 移出 startup(`AUTO_MIGRATE` 开关);OCC 镜像引入方式修正 + 依赖锁文件 | D6、D12、D13 | +| 批次 2 | 任务一致性模型(2–4 天) | PG 为单一事实源、Redis 仅热缓存;去掉多进程内存回退;批量元数据入库;型腔失败标 failed;持久化事务边界收口 | D7、D8、D9、D11 | +| 批次 3 | API 与代码结构(3–5 天) | `_safe_include` 失败显式化(/health 暴露缺失路由);advanced_router 拆分 + Pydantic 请求模型;async 重计算统一 executor;StorageIntegrationService 拆分;配置治理 | D1、D14 | +| 批次 4 | 架构演进(5 天+) | 共享 ORM 按模块拆分;OCC 吞吐方案设计先行;文档 / 契约同步 | D3、D10 | + +**执行顺序建议**:批次 0 与批次 1 的 D6(RustFS 主链路)先行——前者是确认的安全漏洞,后者是部署根本性缺陷,两者互不依赖、改动可控。其余按批次顺序推进,每批完成同步 STATUS / TECH_DEBT / API_CONTRACT。 + +--- + ## 4. 中长期方向 ### 4.1 平台层语义收敛 diff --git a/docs/STATUS.md b/docs/STATUS.md index 61ca50e..4132f82 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -3,6 +3,8 @@ > 文档定位:**唯一的「现在到哪了」**。README / AGENTS / 各主文档只链接到这里,不复制状态内容。 > 维护规则:每完整完成一个需求,**倒序在本文顶部加一条**(日期 + 主题 + 关键事实);其余主文档(架构 / 规划 / 技术债 / 部署)维护各自的"当前有效说法",本文只记录"什么时候做到了哪一步"。维护规则出处见根目录 [AGENTS.md](../AGENTS.md)。 +> 2026-09-15(**后端设计审查完成 → 治理计划入文档**:完成 moldinsight 后端设计审查(部署 / 任务一致性 / API / 代码结构),产出治理批次计划入 [ROADMAP.md](ROADMAP.md) §3.1(批次 0–4:安全→部署→一致性→结构→架构);新识别技术债 D5–D14 入 [TECH_DEBT.md](TECH_DEBT.md) §3——含确认安全缺口 `/api/status/{task_id}` 无鉴权、主处理链路依赖节点本地文件路径(API 与 Celery worker 容器无共享卷)等。**下一步**:按批次 0 + 批次 1 的 D6(RustFS 主链路)启动实施。) + > 最后更新:2026-09-15(**项目规范体系对齐 ipc-chat-cortex**——参考 `ipc-chat-cortex` 的 AGENTS.md + docs 规范重整本文档体系:① [AGENTS.md](../AGENTS.md) 重写——硬约束速览(新增:接口变更三件套 Pydantic→openapi.json→gen:api、配置只走 .env 且关键项不兜底、单数据库刻意设计)+ 代码地图逐文件化 + 开发约定映射表(改什么→同步什么文档);② 新增 [OPERATIONS.md](OPERATIONS.md)(配置来源与优先级 / 本地启动 / Compose / 运维硬性要求)与 [API_CONTRACT.md](API_CONTRACT.md)(端点总览 / 统一约定 / OpenAPI 类型生成流程);③ 本文件改为日志体,原静态内容分流到各归属文档(推荐部署模式→DEPLOYMENT §1,未完成项→ROADMAP/TECH_DEBT)。**验证**:openapi 导出命令实测可用(conda gemold 环境,unified app 76 paths);**待办**:checked-in `openapi.json`(2026-07-27,70 paths)已落后当前代码,下次接口变更时按 [API_CONTRACT.md](API_CONTRACT.md) §4 重导出并 `npm run gen:api`。) > 上一条:2026-09-02(**模块化收口 + 文档主骨架建立(基线条目)**:代码侧完成 moldinsight 技术债治理——安全收口(debug/history 权限补齐、任务访问控制收紧)、静默失败修复(`detect-undercuts` 基于真实 shape 重建)、OCC 超时后 executor 重建防毒化全队列、后台任务统一分派、Redis 任务状态改 Hash 原子更新、完成态任务视图缓存、导出缓存与持久化收口、旧入口与死代码删除、Generator 公共接口提取 + 契约测试;详见 [TECH_DEBT.md](TECH_DEBT.md) §2。结构侧完成 `src/entrypoints/` 三入口拆分(moldinsight / inventory / unified)、`shared` 平台能力集中、前端独立 `frontend/` 工程。文档侧建立 `STATUS / ARCHITECTURE / ROADMAP / TECH_DEBT / DEPLOYMENT` 主骨架,README 收敛为唯一导航入口,历史材料迁入 [archive/](archive/README.md)。**测试基线**:本地 pip 环境 **47 passed, 1 skipped**(pythonocc 缺失自动 skip);moldinsight conda + OCC 环境 **88 passed**。inventory 侧少量既有 deprecation warnings 不影响通过。) diff --git a/docs/TECH_DEBT.md b/docs/TECH_DEBT.md index 1d99c45..c578574 100644 --- a/docs/TECH_DEBT.md +++ b/docs/TECH_DEBT.md @@ -111,10 +111,150 @@ 优先级:**P1** +### D5. `/api/status/{task_id}` 未鉴权(安全缺口) + +现状: +- [src/moldinsight/api/task_router.py](../src/moldinsight/api/task_router.py) 的 `/api/status/{task_id}` 未挂 `get_current_active_user`,也无任务归属校验 +- 匿名可枚举任务号拉取完整分析视图(几何 / 型腔方案 / LLM 报告 / 服务器本地路径) + +影响: +- 与"任务访问控制已收紧"的既有结论矛盾;任务号可经批量/历史接口关联到真实用户 +- 属确认的安全漏洞,应最先修复 + +建议: +- 补 `Depends(get_current_active_user)` 并复用 `_ensure_task_access` 归属校验 + +优先级:**P0** + +### D6. 主处理链路依赖节点本地文件路径 + +现状: +- 上传保存到本地目录,任务处理直接 `load_step_file(Path(file_path))`([processing_service.py](../src/moldinsight/services/processing_service.py)) +- docker-compose 中 backend 与 moldinsight-celery 为独立容器且无共享 volume,worker 读不到 API 节点写入的本地文件 + +影响: +- 双容器部署下主流程必然 `FileNotFoundError`;代码已有从 RustFS 重建几何的 [shape_loader.py](../src/moldinsight/services/shape_loader.py),主链路却未复用 + +建议: +- 分派入参由 `file_path` 改为 `stp_file_id`,worker 端按 `object_key` 从 RustFS 下载后解析 + +优先级:**P0** + +### D7. Redis 降级为进程内 dict,多副本状态不一致 + +现状: +- Redis 不可用时任务状态 / 批量元数据 / 任务视图缓存静默降级到各进程内存([redis_task_manager.py](../src/shared/services/redis_task_manager.py) / [batch_router.py](../src/moldinsight/api/batch_router.py) / [task_query_service.py](../src/moldinsight/services/task_query_service.py)) + +影响: +- 多 worker + 多 API 副本下各进程内存互相不可见:同一任务在不同副本读到不同状态 + +建议: +- PG 作为单一事实源、Redis 仅热缓存;内存回退仅限单进程 DEBUG 模式 + +优先级:**P1** + +### D8. 型腔生成失败被静默标记为 completed + +现状: +- `_step_generate_cavity` 异常时置 `plan_result=None` 继续主流程,最终任务标记 completed([processing_service.py](../src/moldinsight/services/processing_service.py)) + +影响: +- 核心能力失败却对外呈现"成功","完成"状态可信度低 + +建议: +- 型腔失败 → 任务 failed,或显式 `completed_with_fallback` 并前端标注 + +优先级:**P1** + +### D9. 持久化事务边界破碎 + +现状: +- [storage_integration_rustfs.py](../src/moldinsight/services/storage_integration_rustfs.py) 各方法内部自行 `session.commit()`,编排层上下文又 commit +- 型腔保存失败时几何/网格等前期数据已提交落库 + +影响: +- 失败后留下已提交的半成品数据,无对账补偿 + +建议: +- 各方法不再自提交,由编排层统一提交;明确 RustFS 与 PG 写入顺序 + +优先级:**P1** + +### D10. OCC 全局单线程串行 + 超时重建泄漏线程 + +现状: +- 所有 OCC 操作经 `max_workers=1` executor 串行([processing_service.py](../src/moldinsight/services/processing_service.py)),celery 并发无法扩展 OCC 吞吐 +- 超时重建 executor 每次泄漏 1 个线程,长期运行只涨不降 + +影响: +- 一个长耗时型腔生成阻塞全部几何处理;线程随故障累积 + +建议: +- 记录吞吐上限为已知约束;线程泄漏治理方案设计先行(见 [ROADMAP.md](ROADMAP.md) §3.1 批次 4) + +优先级:**P2** + +### D11. HTML 报告本地磁盘与 RustFS 双写双读 + +现状: +- 可视化 HTML/摘要同时写本地 `html_output/`(/html 静态挂载)与 RustFS + +影响: +- 多副本下 /html 命中结果取决于负载均衡,跨副本文件不共享;同一份报告两套来源 + +建议: +- 统一 RustFS 为唯一来源,本地仅作按需缓存 + +优先级:**P2** + +### D12. 应用启动时自动执行 alembic 迁移 + +现状: +- [init_db.py](../src/shared/database/init_db.py) 在 web 进程 startup 中执行 `alembic upgrade head` + +影响: +- 多副本并发迁移有竞态,且迁移阻塞服务就绪 + +建议: +- 迁移移出 web 进程,作为独立部署步骤(`AUTO_MIGRATE` 开关) + +优先级:**P1** + +### D13. PythonOCC 镜像引入方式脆弱 + 依赖无版本锁 + +现状: +- [Dockerfile.moldinsight](../deploy/Dockerfile.moldinsight) 从 conda env 拷贝 site-packages 进 python:3.12-slim +- [requirements.txt](../requirements.txt) 全部为 `>=` 下限,无锁文件 + +影响: +- slim 缺 libstdc++/libgomp 等运行时库,跨发行版拷二进制纯靠运气;构建不可复现 + +建议: +- 基础镜像改用完整 conda 环境;依赖以 pip-compile 锁文件固化 + +优先级:**P2** + +### D14. 配置漂移:弱默认 / 死配置 / 重复解析 + +现状: +- RUSTFS_* 带 `localhost:8080` / `your-secret-key` 弱默认;compose 给 SECRET_KEY / ADMIN_PASSWORD 弱默认 +- MAX_FILE_SIZE 配置项未被使用([file_handler.py](../src/shared/utils/file_handler.py) 硬编码 50MB) +- [celery_app.py](../src/celery_app.py) 重新 load_dotenv 并手拼 REDIS URL,与 settings 两份实现 + +影响: +- 违背"关键项不兜底"硬约束;配置行为与文档不一致 + +建议: +- 去掉弱默认、对齐或删除死配置、celery_app 复用 settings + +优先级:**P2** + --- ## 4. 当前推荐治理顺序 +> 注:2026-09-15 后端设计审查后,治理**执行顺序**以 [ROADMAP.md](ROADMAP.md) §3.1 批次计划为准(批次 0–4);D5–D14 的批次归属见该表。本节保留原有优先项作为补充说明。 + ### 第一优先级 1. `advanced_router` 拆分 2. 高优先级接口补 Pydantic 请求模型