# 开发质量与前后端架构规范设计 - 功能编号:GOV-010 - 设计版本:0.1 - 状态:approved - 日期:2026-08-13 ## 1. 决策摘要 采用“规范文档 + 功能模板 + 自动门禁”的可执行治理方案。安全、性能、GitNexus 影响和同步修改进入设计、测试与 Review;实际完成事实进入独立 `development-summary.md`。前端将现有 `openapi-fetch` 请求实现迁移为统一 Axios 封装,继续使用 OpenAPI 生成类型。后端采用业务模块垂直组织、模块内部按需分层,不强制空目录或透传层。 ## 2. 方案比较 ### 方案 A:文档、模板与关键门禁结合(采用) 优点是关键证据可以自动阻断,架构职责仍保留工程判断空间;既不会让规范沦为建议,也不会因为一个固定目录生成器迫使小模块过度设计。成本是治理脚本和边界校验需要测试,并且后端分层仍需认真 Review。 ### 方案 B:只更新规范文档 实施成本最低,但无法防止缺少开发总结、空安全评估和页面直连 HTTP。随着功能增加,违反约定往往只能在人工 Review 后期发现,不符合项目要求的可追溯和可执行治理目标。 ### 方案 C:固定目录生成器与全面架构 lint 自动化最强,但会要求每个模块凑齐 Controller、Service、DTO、Repository 和 Adapter,容易制造无意义转发、文件碎片和错误抽象。当前业务模块尚未充分展开,固定全部结构为时过早。 ## 3. 治理证据链 ```text Schema 发布基线 ↓ governance:start + GitNexus 开发前分析 ↓ PRD / requirements / design / test-plan ↓ 测试先行 → 实现 → 完整验证 ↓ GitNexus detect_changes + 前后对比 ↓ development-summary ↓ 代码 Review + 规范 Review ↓ governance:finish ``` 开发前影响计划必须显式列出 HTTP/OpenAPI、Web API、消息、数据库、缓存、三个服务进程、部署、测试和文档的同步修改结论。开发后变更检测将实际符号和执行流与计划对照,避免只分析主要模块而漏掉消费者。 安全和性能采用贯穿式记录,不额外拆成孤立文件: - `design.md` 记录威胁、缓解、残余风险、性能目标和取舍。 - `test-plan.md` 记录验证方法和风险相称的测试强度。 - `review/*.md` 记录实现证据、问题、处置和遗留风险。 - `development-summary.md` 记录实际需求完成、缺陷和验证结果。 ## 4. 独立开发总结 新增 `docs/templates/development-summary-template.md`,并把 `development-summary.md` 加入所有后续功能档案的完成清单。固定章节为: 1. 原始开发需求。 2. 需求与范围变化。 3. 实际完成需求。 4. 修复缺陷。 5. 未完成与延期项。 6. 关键提交。 7. 验证证据。 自动校验验证标题存在且正文有实质说明。对于没有缺陷或延期项的功能,仍需说明“没有”的依据,不允许删除章节或只填写无解释的占位词。历史已发布档案不因新规则被批量改写;门禁以 GOV-010 生效范围和新建档案为边界,GOV-010 自身也提供该文件。 ## 5. 后端架构 ```text server/apps/api/src/modules/ └── market-overview/ ├── market-overview.module.ts ├── controllers/ ├── services/ ├── dto/ ├── domain/ ├── repositories/ ├── adapters/ ├── types/ └── utils/ ``` 业务模块是第一组织边界,目录只在有对应职责时创建。依赖方向为: ```text Controller → Service / use case → Domain + Repository port ↑ Infrastructure Adapter ``` - Controller 处理协议、校验后的输入和响应映射,不包含市场计算或数据访问。 - Service 编排用例、事务边界和降级,不成为所有逻辑的集中地。 - Domain 保持纯 TypeScript 规则、口径和模型,不依赖 NestJS 或基础设施 SDK。 - Repository 是业务所需的持久化端口;Adapter 实现 MySQL、Redis、RocketMQ、免费数据源或 AI Provider。 - DTO、领域模型和数据库实体分别服务传输、业务和持久化,不互相冒充。 - 模块间共享只有在重复已经出现、语义稳定且所有者明确后才上移到 `server/libs`。 现有健康检查是脚手架基础能力,本功能不为展示目录形式而迁移其后端文件。新的业务模块从本规范开始执行;后续触及健康检查模块时再基于影响分析判断是否垂直归档。 ## 6. 前端架构与 Axios 数据流 ```text web/src/ ├── utils/ │ └── request.ts ├── api/ │ ├── generated/ │ │ └── schema.ts │ ├── health/ │ │ └── index.ts │ ├── market-overview/ │ │ └── index.ts │ ├── sectors/ │ │ └── index.ts │ └── stocks/ │ └── index.ts └── features/ └── / ├── adapters/ ├── components/ ├── composables/ ├── stores/ └── views/ ``` 实际数据流为: ```text NestJS DTO 与 Swagger 元数据 ↓ server/openapi/openapi.json ↓ openapi-typescript web/src/api/generated/schema.ts ↓ 类型约束 api/<业务域>/index.ts ↓ 调用 utils/request.ts(Axios) ↓ 业务 adapter → ViewModel → 页面/组件 ``` `request.ts` 创建唯一 Axios 实例,负责 base URL 规范化、超时、通用请求头、取消信号、错误归一化和后续认证扩展。响应拦截器只返回响应数据,API 函数不向功能层泄漏 `AxiosResponse`。错误类型保留稳定的用户安全消息,并可携带不敏感的错误分类和 HTTP 状态供界面决定重试或降级;原始配置、请求头、内网地址和上游正文不进入展示消息。 业务 API 文件从生成 Schema 中提取请求与响应类型,并使用封装后的 request。Vue 页面、组件、Store 和 Composable 不得直接导入 Axios、调用浏览器 `fetch` 或拼接业务 URL。DTO 到 ViewModel 的转换保留在功能适配层,使后端传输字段不会扩散到展示组件。 ## 7. Axios 迁移 迁移现有健康请求客户端脚手架,并建立业务 API 样例。当前页面尚未消费健康接口,现有 `client.ts` 只有直接单元测试,Playwright 则从测试进程直接请求后端;因此本次不虚构页面调用方: - 删除 `openapi-fetch` 依赖,新增锁定版本的 `axios`。 - 以测试先行创建 `web/src/utils/request.ts`,覆盖根地址、超时、数据解包、取消和脱敏错误。 - 创建 `web/src/api/health/index.ts`,使用生成的 `HealthResponseDto` 类型调用 `/api/v1/health`。 - 更新旧客户端测试,并为健康业务 API 增加测试;保留 DTO 到 `HealthViewModel` 的适配器,暂不为了展示调用链而把健康状态接入页面。 - 删除不再使用的 `web/src/api/client.ts` 及对应旧测试。 - 扩展项目边界校验,拒绝 API 目录外直接使用 Axios/fetch,并拒绝 API 模块绕过统一 request。 OpenAPI 文档与 OpenAI 兼容 API 是不同概念:前者是 NestJS 对本项目 HTTP 契约的机器可读描述;后者是未来后端 AI Provider 需要兼容的外部调用协议。本功能只改变浏览器到本项目 API 的 Axios 实现。 ## 8. 安全设计 ### 资产与信任边界 - 浏览器输入和网络响应均不可信;Axios 封装是浏览器 HTTP 错误边界,业务 API 是传输契约边界。 - OpenAPI 生成文件是可提交的公开契约,不得包含内部消息、实体或密钥。 - 治理工具读取仓库文档和 Git 状态,不读取生产环境;Schema 门禁仍只允许既定开发库边界。 ### 主要风险与控制 - 错误泄漏:统一转换网络和 HTTP 错误,用户消息不包含 URL、凭据、响应正文或底层异常。 - 绕过请求策略:边界校验限制 Axios 实例和直接 fetch,减少遗漏超时、认证、错误处理和日志脱敏。 - 供应链:Axios 使用固定版本并提交锁文件;安装前核对官方包、许可证、维护状态和依赖变化。 - 注入与浏览器攻击:本功能不渲染远程 HTML、不添加认证 Cookie、不生成动态 SQL;后续涉及这些边界时仍必须分别评估 XSS、CSRF、SSRF 和注入。 - 伪造治理证据:完成门禁检查必备章节及理由,Review 仍核对内容与 Git diff、测试输出是否一致。 残余风险是自动校验无法判断文字结论是否真实,因此保留结构化人工 Review;Axios 响应数据的运行时 Schema 校验不在本次引入,现有健康适配器继续拒绝未知枚举,后续高风险接口按具体功能决定是否引入运行时校验。 ## 9. 性能设计 - Axios 替代 `openapi-fetch` 会增加有限前端依赖体积,但换取项目已确认的统一请求范式、成熟拦截器和取消能力;构建产物记录迁移前后体积并在 Review 中评估变化。 - 统一请求层不得默认无限重试,避免行情刷新时形成放大流量;本次不加入自动重试。 - 超时采用有限默认值,业务域可在设计批准后缩短,但不得无上限等待。 - API 函数返回解包后的 DTO,避免重复转换与组件订阅 Axios 对象;该差异不是性能热点,主要价值是边界稳定。 - 治理扫描只在开发与发布验证执行,不进入线上请求路径;文件扫描保持线性遍历,当前仓库规模不要求负载测试。 - 本功能不查询 MySQL、Redis 或行情数据,不改变 Scheduler/Worker 吞吐;这些项不适用于运行时性能验证,边界是后续业务功能必须重新评估。 ## 10. 自动校验边界 适合自动化的规则:必备文件、必填章节、Review 固定结论、前端非法依赖、直接 HTTP 调用和生成契约泄漏。后端目录是否需要某一层、重复是否足以抽取、注释是否真正解释原因等需要语义判断,进入规范 Review,不用脆弱的固定目录规则代替。 内容校验以结构为主:确认标题、标题下非空正文、明确的不适用理由格式;不通过搜索“安全”“性能”等零散词语来推定证据完整。校验函数保持纯函数并由 fixture 测试覆盖,`finish.mjs` 只负责编排。 ## 11. 错误与回退 - 门禁失败必须列出具体文件和缺失章节,不能只返回布尔值。 - Axios 遇到取消请求时保留可识别取消语义,不错误展示为服务故障。 - 非取消错误转换为项目错误类型;调试细节只允许进入受控开发日志且必须脱敏,本次默认不记录原始错误。 - 若迁移回归,可用中文回退提交恢复 `openapi-fetch` 客户端、依赖和调用方;规范、模板和校验必须作为一致变更回退,避免规范与基础代码不一致。 ## 12. 验证与完成标准 - 治理单元测试覆盖开发总结和章节校验的通过、缺失和伪占位失败场景。 - 边界测试覆盖 Axios/fetch 的非法与合法路径、Vue 脚本和路径别名。 - Web 单元测试覆盖请求 URL、响应解包、网络错误、HTTP 错误和取消。 - OpenAPI 生成、格式、lint、类型检查、全量测试、构建、Playwright 和源码发布门禁通过。 - 现有页面在桌面与移动视口完成视觉回归,证明请求基础设施迁移没有造成布局或交互旁路变化。 - GitNexus 开发后变更检测与前置计划一致,两类 Review 最终结论均为 `passed`。