docs: add full codebase optimization checklist for ephron.ren

This commit is contained in:
Ubuntu
2026-05-16 15:22:42 +08:00
parent babb2d9e3e
commit d6c8d17ce7

View File

@@ -0,0 +1,730 @@
# PRD — ephron.ren 全项目代码阅读后的完整优化清单
## 说明
本清单基于对 `ephron.ren` **远端 `origin/main`** 的系统性源码阅读整理,不以当前本地工作树为准。
之所以强调这一点,是因为本地仓库当前状态与远端并不一致:
- 本地 `HEAD``origin/main` 存在 ahead/behind 分叉
- 本地还存在不在 `origin/main` 中的文件(例如 `prompt/tests/test_settings_validation_regression.py`
因此,本 PRD 的结论全部以 **`origin/main` 可验证代码** 为依据,避免把本地漂移状态误判为正式项目现状。
本次阅读重点覆盖:
- 顶层入口与项目运行骨架
- `shared/` 全部核心 Python 模块
- 五个服务的 `src/` 关键入口、routes、services
- 全局 tests 与各服务代表性 tests
- 必要的 scripts 层职责分布
阅读方式不是逐个文档回顾,而是**以 Python 代码为主、以测试和脚本为辅助**,用于形成项目层面的结构优化结论。
---
## 一、执行摘要
当前 `ephron.ren` 项目已经从早期多服务 MVP 演进到一个拥有:
- 五个 FastAPI 服务home/auth/blog/canvas/prompt
- 一层共享模块shared
- 一批管理脚本scripts
- 混合测试体系(全局 + 各服务)
的中型单仓项目。
它已经具备一定工程化基础:
- 统一启动器
- shared 安全头 / cookie / CSRF / 审计 / ports / rate limit 等公共模块
- app factory / config base 共享化的第一轮落地
- service token / audit event / RBAC 等基础治理能力
但通读代码后可以明确判断:
> 这个项目当前的主要矛盾已经不是“功能缺失”,而是**结构进入半统一状态后,边界没有完全收紧**。
也就是说:
- shared 已经出现,但没有真正成为单一权威层
- 服务之间已经开始收敛,但仍保留大量复制变体
- 测试已经很多,但测试结构并不稳定
- 运维脚本已经存在,但项目契约在代码、文档、脚本三层之间有漂移
因此,本清单的核心不是列零散 bug而是给出 **整站层面需要收口的工程性优化项**
---
## 二、代码规模与结构概览
基于 `origin/main` 的粗略统计:
- `shared/`17 个 Python 文件,约 1492 行
- `auth/src/`17 个 Python 文件,约 4369 行
- `auth/tests/`9 个 Python 文件,约 1851 行
- `auth/scripts/`7 个 Python 文件,约 1384 行
- `blog/src/`21 个 Python 文件,约 5734 行
- `blog/tests/`8 个 Python 文件,约 913 行
- `blog/scripts/`8 个 Python 文件,约 973 行
- `canvas/src/`10 个 Python 文件,约 2208 行
- `canvas/tests/`3 个 Python 文件,约 702 行
- `home/src/`9 个 Python 文件,约 1007 行
- `home/tests/`2 个 Python 文件,约 400 行
- `home/scripts/`2 个 Python 文件,约 362 行
- `prompt/src/`18 个 Python 文件,约 4293 行
这说明项目已经明显超出“小型 MVP”范畴进入了
- 多服务
- 多存储模型
- 多种认证形态
- 多种测试风格
- 多种运维入口
并存的复杂系统阶段。
此时最重要的不是继续叠功能,而是**统一边界、清理漂移、建立工程约束**。
---
## 三、总体问题地图
通读代码后,当前整站问题可以归纳为六大类:
1. **架构边界问题**shared 化进行到一半,责任分层尚不稳定
2. **数据与模式归属问题**:数据库 schema ownership 漂移,跨服务边界模糊
3. **认证与权限问题**:跨服务 auth/helper 重复实现guard 逻辑分散
4. **测试体系问题**:测试风格混杂,很多测试在替结构问题兜底
5. **运维与部署契约问题**代码、README、scripts、依赖链之间存在漂移
6. **性能与运行时语义问题**:部分启动逻辑、缓存、健康检查和 IO 设计仍偏“功能优先”而非“系统优先”
下面按优先级展开。
---
## 四、P0必须优先处理的系统性问题
## P0-1. Shared 层已经成为基础设施核心,但还没有真正成为单一权威层
### 现象
项目已经有大量 shared 模块:
- `shared/security_headers.py`
- `shared/limiter.py`
- `shared/health.py`
- `shared/csrf.py`
- `shared/cookie_utils.py`
- `shared/request_ip.py`
- `shared/service_tokens.py`
- `shared/auth_users.py`
- `shared/redirect_codec.py`
- `shared/audit_log.py`
- `shared/audit_events.py`
- `shared/config_base.py`
- `shared/error_handlers.py`
- `shared/app_factory.py`
这已经说明 shared 不是辅助目录,而是事实上的基础设施层。
但代码同时又显示出明显的“半统一态”:
- 各服务仍自己写 path hack
- 各服务仍各自保留 auth helper 变体
- 各服务仍自行拼装部分 guard / token / DB 逻辑
- 测试大量依赖服务内 patch / import 注入来运行
### 问题本质
项目已经决定走 shared 化,但还没有把这个决定贯彻为**稳定架构边界**。
现在的 shared 更像:
- “可复用模块集合”
而不是:
- “明确的公共协议层和基础设施层”
### 优化建议
1. 把 shared 的职责重新定义清楚,至少分三层:
- **shared/core**ports、config、health、sqlite、templating 等基础设施
- **shared/security**cookie、csrf、redirect、request_ip、network_safety、service_tokens
- **shared/governance**audit_log、audit_events、auth_users
2. 明确服务层只允许:
- 组合 shared
- 实现服务自己的业务逻辑
3. 禁止服务层重复实现 shared 已经承担的协议逻辑
4. 为 shared 层补一个“模块边界文档 + import 约束清单”
### 价值
这一步不是美化目录,而是让项目从“共享了一些代码”变成“建立了共享层权威”。
---
## P0-2. 数据库 schema ownership 已经漂移Prompt 服务承担了不属于自己的数据库中枢职责
### 现象
`prompt/src/services/db.py` 不仅初始化 prompt 自己的表:
- `prompts`
- `prompt_versions`
- `collections`
- `collection_items`
- `settings`
- `test_audit_log`
还在同一个模块里初始化:
- `blog_collections`
- `blog_collection_items`
### 这为什么严重
这不是简单的“顺手建表”,而是**服务边界被数据库初始化逻辑穿透了**。
直接后果:
1. Prompt 服务在事实层面成了跨域 schema bootstrap owner
2. Blog 的集合表不再由 Blog 自己的模块负责
3. 后续如果 blog collections 结构要演进,维护者必须去 prompt/db 里改
4. 新人很难从目录结构直觉判断“哪个服务拥有哪张表”
5. 迁移/部署/排障都会误导
### 优化建议
1. 重新定义数据库模式归属:
- `auth` 拥有用户/角色/权限/邀请/service account 相关表
- `prompt` 拥有 prompts / prompt_versions / prompt collections / settings / prompt audit
- `blog` 拥有 blog_collections 等 blog 相关表
- 全局共享表必须明确标注为 shared schema
2. 不允许某个服务的 `db.py` 去创建另一个服务的业务表
3. 建立统一的 migration / schema registration 机制:
- 可以是根级 `scripts/migrate_database.py` 调度各服务注册器
- 或 shared schema registry
4. 把“建表逻辑”和“运行时 connection helper”拆开
- `db.py` 负责连接和轻量 helper
- schema 初始化由独立 migration 层负责
### 价值
这是整站层面最需要收口的一条,不然项目继续增长后,数据库会先于代码架构失控。
---
## P0-3. 认证/权限协议在跨服务间被重复实现,风险在于未来持续漂移
### 现象
多个服务都存在自己的 auth service
- `auth/src/services/auth.py`
- `blog/src/services/auth.py`
- `canvas/src/services/auth.py`
- `home/src/services/auth.py`
- `prompt/src/services/auth.py`
虽然它们都围绕同一 cookie/token 协议,但实现并不完全统一。
常见重复内容包括:
- token verify
- get_auth_user
- require_admin_role
- require_permission
- service actor 识别
- admin guard / redirect 逻辑
### 问题
这不是“代码重复”这么简单,而是**认证协议重复实现**。
一旦协议升级,比如:
- token 字段变化
- current DB role 解释变化
- service token 行为变化
- handoff_to_human 规则变化
多个服务必须同步修改,否则就会出现行为漂移。
### 优化建议
1. 抽出一层 shared auth protocol helper
- token verify
- current user resolve
- current role/permission resolve
2. 抽 shared admin guard skeleton
- 登录跳转
- redirect 编解码
- service token 能否访问 admin 的统一策略
3. 服务层只保留:
- 各自业务资源上的权限要求
- 各自页面跳转的 UI 差异
4. 统一 `service actor` 的语义,不要每个 service_api 都自己再包一层近似实现
### 价值
认证和权限如果不先统一协议层,将来每个服务都能“看起来能用,但行为不完全一致”。这是最难排查的线上问题类型之一。
---
## P0-4. 当前测试体系已经在为结构债务兜底,必须先治理测试边界
### 现象
测试中出现多种明显信号:
1. 大量 `sys.path.insert(...)`
2. 大量 `sys.modules['src.config'] = mock_config`
3. 既有真实入口测试,也有内存 SQLite 模拟测试
4. 一些 tests 更像脚本式 smoke file而不是稳定单测
5. 有些测试在 patch import path 后才跑得起来
### 问题本质
这说明测试体系并不只是“多样”,而是:
> 结构不稳定,测试在替结构问题兜底。
当测试必须大量:
- 改路径
- 改模块缓存
- patch 配置模块
- patch 连接层
才能运行时,往往意味着:
- 模块边界不清晰
- 初始化副作用太强
- 配置/数据库/依赖注入方式不够健康
### 优化建议
1. 重新分层测试:
- **unit**:纯函数/纯 service helper
- **contract**shared 协议、entrypoint 装配、cookie/redirect/security headers 合同
- **integration**:服务路由 + 临时 DB / 文件系统
- **script smoke**:脚本独立,不混在核心单测里
2. 把脚本式测试文件从核心 pytest 回归层剥离
3. 减少 `sys.modules['src.config']` 风格 patch改为显式配置注入或 fixture
4. 建立统一测试 helper
- temp DB
- temp content dir
- service runtime bootstrap
5. 明确哪些 tests 允许 mock哪些必须走真实入口
### 价值
如果不先治理测试边界,后续任何重构都会因为“测试全在 patch 系统内部结构”而变得高风险。
---
## 五、P1高优先级结构优化
## P1-1. `sys.path.insert(...)` 仍然是整站普遍现象,说明模块边界和运行契约都不稳定
### 现象
根入口、五个服务 main/config、routes、services、tests、scripts 中广泛存在 `sys.path.insert(...)`
这意味着项目当前默认运行模型仍然是:
- 依赖 cwd
- 依赖相对路径
- 依赖手动往 `sys.path` 注入仓库根或服务根
### 问题
这会导致:
- 测试和运行环境对 cwd 高度敏感
- 一旦目录结构调整,影响面极大
- 局部脚本行为难预测
- 本地与 CI、服务与脚本之间的 import 语义不稳定
### 优化建议
1. 先收敛核心入口(根 `main.py` + 5 个服务 `main.py/config.py`
2. 再收敛服务内 routes/services 的 path 注入
3. 最后收敛 tests/scripts
4. 推荐建立统一 bootstrap helper 或显式包运行约定
5. 长期建议迁移到更稳定的 package/import 结构
### 价值
这是整站工程可维护性的基础设施问题,不解决的话 shared 化永远会停在“看起来统一”。
---
## P1-2. Root `main.py` 已承担启动器职责,但与服务/文档/环境管理之间的契约仍旧脆弱
### 现象
`main.py`
- 负责 5 个服务统一拉起
- 自己处理 Windows / conda / venv / Python 路径探测
- 自己检查 `.env`
- 通过 subprocess + uvicorn 启动每个服务
这是一个“越来越重的启动器”。
### 问题
1. 环境选择逻辑混在业务启动器里
2. 文档、服务真实依赖、启动脚本之间的契约分散
3. 统一启动器既是开发工具,又试图兼容生产模式
4. 一旦某个服务需要特殊启动参数,根 `main.py` 会继续膨胀
### 优化建议
1. 明确 root `main.py` 的角色:
- 仅作为开发/本地一键启动器
- 不承担生产部署入口的抽象责任
2. 把环境探测逻辑拆出去
- 例如单独的 runtime/bootstrap helper
3. 用配置声明服务列表,而不是在代码里硬编码越来越多的服务元数据
4. README 明确区分:
- 开发启动
- 测试启动
- 生产部署
### 价值
避免根 `main.py` 继续演变成“全能脚本”。
---
## P1-3. `shared/health.py` 当前统一检查 sqlite但没有表达“每个服务的真实健康语义”
### 现象
`shared/health.py` 当前统一返回:
- service
- uptime
- database status
而所有服务都走这一套。
### 问题
这在格式统一上是好的,但语义上过度简化:
- `canvas` 主要是文件存储,但 health 只看 DB
- `blog` 的 search index / content dir 状态不在 health 中
- `prompt` 对外部 LLM provider 的依赖也不在 health 中
- `home` 的 content state 也不在 health 中
也就是说health 现在更像:
- “进程 + sqlite 基本可用”
而不是:
- “服务核心依赖健康”
### 优化建议
1. 保留 shared health response 骨架
2. 允许每个服务注册自己的 health probes
3. 将 health 结构设计为:
- shared baseline
- service-specific checks
4. 区分:
- `ok`
- `degraded`
- `error`
### 价值
这能显著提升运维判断质量避免“health 绿了但服务关键功能其实坏了”。
---
## P1-4. Service API 在 blog/canvas/prompt 三个服务中存在明显的重复模式,应该抽共享骨架
### 现象
三个 service API 都有相似结构:
- bearer token 识别
- actor 权限检查
- own draft / manageable state 判断
- 审计记录
- create / edit / delete / publish / unpublish
其中大量逻辑只是资源字段不同,本质模式一致。
### 问题
这类“高度相似但不完全相同”的复制是最危险的:
- 现在看还能维护
- 再迭代 2~3 次就会出现细节漂移
- 测试也会不断复制
### 优化建议
1. 抽 service API shared skeleton
- require_service_actor
- permission check helpers
- audit emit helper
- draft/manageable state helper interface
2. 资源特有逻辑通过回调/策略注入
3. 保持每个服务自己的 resource serializer
### 价值
这不是为了“抽象好看”,而是为了避免 blog/canvas/prompt 在未来演化出三套近似但不兼容的 draft workflow。
---
## P1-5. README / docs / 代码现状之间存在持续漂移,需要把“文档同步”从手工习惯变成约束
### 现象
顶层 README 仍然保留部分旧叙述,例如:
- `home/.env` 使用 `ENVIRONMENT`,其他服务使用 `ENV`
而代码实际上已经进入:
- shared config base
- `home` 兼容 `ENVIRONMENT`,但系统已有 `ENV` 主路径
类似漂移在多服务项目中会越来越常见。
### 优化建议
1. 把运行契约文档集中到一份单一权威说明
2. README 只保留高层入口,不重复易漂移细节
3. 与代码强耦合的配置/依赖契约,尽量让测试检查而不是只写文档
4. 把“更新 README”纳入涉及运行契约改动的 PR checklist
### 价值
减少“文档看起来对,但代码其实已经变了”的维护成本。
---
## 六、P2中优先级改进项
## P2-1. 启动时副作用偏多,部分初始化逻辑应继续外移
### 现象
示例:
- blog 启动时会检查并构建 search index
- prompt 启动时初始化 DB
- auth 启动时初始化 DB
### 问题
这种模式在开发期方便,但会导致:
- 启动时间与副作用不可预测
- 失败原因混在应用启动里
- 多进程/并发启动场景下更脆弱
### 优化建议
1. 区分“必须阻塞启动的初始化”和“可外移的预热任务”
2. search index 这类工作更适合显式脚本 / 后台任务 / 管理命令
3. DB migration 与 table bootstrap 应从服务启动逻辑继续拆离
---
## P2-2. 审计体系方向正确,但日志职责还可进一步统一
### 现象
项目已经有:
- `shared/audit_log.py`
- `shared/audit_events.py`
- service API 中的记录逻辑
- prompt service test audit log
### 问题
目前审计能力分成:
- 传统文本审计日志
- 结构化 event 记录
- 各服务局部 audit 表
这三类并存,但归属和用途界限还不够清楚。
### 优化建议
1. 明确区分:
- 运维审计日志
- 结构化安全事件
- 业务行为记录
2. 不同用途采用不同存储模型,但命名/入口统一
3. 避免某服务自己再长出第四套审计语义
---
## P2-3. Script 层数量已经不小,但还缺少明确分类
### 现象
根 scripts + 各服务 scripts 中,已经有相当多的管理脚本。
### 问题
这些脚本有的负责:
- DB init
- 迁移
- backup
- health
- audit rotate
- cache clear
- 校验工具
但当前更多是“文件集合”,不是“清晰操作面”。
### 优化建议
1. 给脚本分层:
- init
- migrate
- maintenance
- diagnose
- admin
2. 为每类脚本建立统一 CLI 约定
3. 减少“功能可用,但脚本发现与使用成本高”的问题
---
## P2-4. 多服务配置约定仍有历史兼容包袱,建议逐步统一为显式配置模型
### 现象
- `home` 仍兼容 `ENVIRONMENT`
- 其他服务走 `ENV`
- 各服务 config summary 字段不完全一致
- 部分服务仍自己决定目录存在性和默认值策略
### 建议
1. 保留兼容,但把兼容行为写进测试
2. 明确哪些配置是全局契约,哪些是服务局部契约
3. 配置模块尽量只做“读取 + 校验”,不做过多隐式推导
---
## 七、按维度汇总的完整优化清单
下面给出可以直接交给开发的总清单版本。
## A. 架构与边界
1. 重构 shared 目录为更清晰的核心/安全/治理分层
2. 定义 shared 为公共权威层,而不是可选工具箱
3. 清理服务内重复的 auth/token/helper 骨架
4. 统一 service API shared skeleton
5. 建立更清晰的 schema ownership 归属关系
6. 把 DB migration/bootstrap 从单个服务 `db.py` 中抽离
7. 收敛根 `main.py` 的职责,只保留开发启动器定位
## B. 数据与存储
8. 让各服务只初始化自己拥有的业务表
9. 建立统一 migration 入口和注册机制
10. 区分 shared 表、auth 表、blog 表、prompt 表等 ownership
11. 明确文件存储服务canvas/blog content与 sqlite 的边界
## C. 认证与权限
12. 抽 shared token verify / current user resolve helper
13. 抽 shared admin guard skeleton
14. 统一 service token 行为解释
15. 统一 redirect / login jump / unauthorized response 约定
16. 让服务只实现资源级权限,不重复协议级权限逻辑
## D. 测试
17. 将测试划分为 unit / contract / integration / script smoke
18. 把脚本式测试从核心 pytest 回归集合中分离
19. 减少 `sys.modules['src.config']` 类测试补丁
20. 建立统一 fixture / runtime helper
21. 新增服务入口装配合同测试
22. 新增配置兼容合同测试
23. 新增 shared/service API 行为合同测试
## E. 运维与部署
24. 统一依赖声明,确保 shared factory 新增依赖覆盖开发/测试/部署链路
25. 统一 README 与真实代码契约
26. 明确开发启动、测试启动、生产启动三种模式
27. 给 scripts 建立分类和统一调用方式
28. 让 health 支持服务特有探针
## F. 可维护性
29. 分阶段清理 `sys.path.insert(...)`
30. 统一 config summary 骨架,但不强行统一业务字段含义
31. 降低 import-time 副作用
32. 将启动阶段的重任务外移
33. 统一 shared 与服务层的异常处理约定
## G. 性能与运行时语义
34. review blog 的 search index 启动构建策略,考虑外移
35. review health response 语义,避免“数据库好=服务好”的误判
36. review缓存/内容读取路径,减少重复 IO 和重复解析热点
37. 评估 comments/likes/views/search 的存储与索引策略是否继续扩张会失控
---
## 八、建议实施顺序
整站层面不建议一次性全做,建议按风险和价值排序:
### 第一组:先收边界
1. schema ownership / migration 归属梳理
2. shared auth/service API/admin guard 协议层抽象
3. 收敛核心入口 path hack
### 第二组:再稳测试
4. 入口合同测试
5. 测试分类与 fixture 统一
6. 减少 patch 配置/patch module 风格测试
### 第三组:再治运行契约
7. 依赖链统一
8. README / scripts / 启动器 对齐
9. health probe 模型升级
### 第四组:最后处理性能与脚本治理
10. 启动重任务外移
11. 脚本层分类
12. 次级 IO/缓存/索引优化
---
## 九、完成定义
当以下条件同时成立时,才能说 `ephron.ren` 从“多服务功能可用”进入“整站工程结构稳定”:
1. shared 成为清晰的公共权威层
2. 数据库 schema ownership 明确,单服务不再越界建表
3. 认证/权限协议不再跨服务重复实现
4. 测试体系不再依赖大量结构性 patch 才能跑起来
5. 启动、依赖、文档、脚本的运行契约一致
6. health / migration / scripts / shared app factory 都有明确职责边界
---
## 十、最终结论
如果只看功能,这个项目已经能跑很多东西;但如果看长期维护,它最需要的不是再堆功能,而是:
> 把已经出现的“shared、RBAC、service API、统一启动、统一测试”这些好方向真正收敛成稳定边界。
现在最大的风险不是“缺模块”,而是:
- 模块已经有了,但边界还不够硬
- shared 已经有了,但权威性还不够强
- 测试已经很多了,但结构还不够稳
这也是为什么本清单的重点会落在:
- 架构边界
- schema ownership
- auth 协议统一
- 测试分层
- 运维契约对齐
而不是零散功能修补。
从整站视角看,只要先把这几条收住,后续新功能开发成本会明显下降,回归风险也会显著降低。