846 lines
37 KiB
Markdown
846 lines
37 KiB
Markdown
# 开发质量与前后端架构规范实施计划
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**Goal:** 建立可自动执行的安全、性能、GitNexus 影响和开发总结门禁,并把前端请求脚手架迁移为使用 OpenAPI 类型的统一 Axios 分域 API 架构。
|
||
|
||
**Architecture:** 治理规则由纯函数负责档案结构和章节证据校验,`finish.mjs` 只负责编排;前端由 `utils/request.ts` 独占 Axios 实例,`api/<业务域>/index.ts` 暴露类型化 DTO,功能层不依赖 Axios 类型。后端只更新正式架构规范,不为尚未出现的业务职责创建空目录或透传层。
|
||
|
||
**Tech Stack:** Node.js 22.x、pnpm 10.25.0、TypeScript 5.9、Vue 3、Vite 6、Vitest、Axios 1.19.0、OpenAPI、NestJS、GitNexus、Node Test Runner。
|
||
|
||
## Global Constraints
|
||
|
||
- 开始实现前,开发前 Schema 基线和 `governance:start` 已完成;基线提交为 `1c1b15e7093e0e8b4acdc48ba59d92e57ac888f0`。
|
||
- 修改任何现有函数、类或方法前,必须对该符号执行 GitNexus upstream impact;HIGH 或 CRITICAL 必须先报告用户。
|
||
- 每项行为变化先写失败测试、确认按预期失败,再写最小实现并重构。
|
||
- Git 提交必须使用中文 Conventional Commit,并带 `GOV-010`;每次验证通过的提交立即精确推送 `origin/main`,禁止强推。
|
||
- 不触碰生产数据库、生产配置或生产数据;本功能不修改 MySQL、Redis 或 RocketMQ 运行状态。
|
||
- MySQL 继续固定 5.7.42、`utf8mb4`、`utf8mb4_general_ci` 和 `+08:00`;生产继续仅支持 Ubuntu 源码部署。
|
||
- 前端 HTTP 请求统一使用 Axios;OpenAPI 仅生成 TypeScript 契约;AI 兼容 OpenAI API 是独立的后端 Provider 协议。
|
||
- 禁止 `any` 代替已有 OpenAPI 类型;外部错误不得泄漏内部 URL、凭据、请求头或响应正文。
|
||
- 只在真实重复和稳定边界出现后抽取复用代码,不为满足目录外观创建空层。
|
||
- 当前 Vue 页面尚未消费健康 API;本次只迁移请求客户端脚手架并新增健康 API 分域样例,不把健康状态强行接入页面。
|
||
|
||
---
|
||
|
||
## File Structure
|
||
|
||
### 新建文件
|
||
|
||
- `docs/templates/development-summary-template.md`:独立开发总结模板。
|
||
- `web/src/utils/request.ts`:唯一 Axios 实例、类型化请求和错误归一化入口。
|
||
- `web/src/utils/request.test.ts`:Axios 封装的 URL、DTO 解包、超时、错误与取消测试。
|
||
- `web/src/api/health/index.ts`:健康业务域 API。
|
||
- `web/src/api/health/index.test.ts`:健康 API 的请求配置与生成类型测试。
|
||
- `docs/features/GOV-010-development-quality-architecture/development-summary.md`:实际完成事实。
|
||
- `docs/features/GOV-010-development-quality-architecture/gitnexus/detected-changes.md`:开发后影响检测。
|
||
- `docs/features/GOV-010-development-quality-architecture/gitnexus/after.md`:开发后图谱基线,由完成门禁生成后补充。
|
||
- `docs/features/GOV-010-development-quality-architecture/gitnexus/comparison.md`:计划与实际影响比较。
|
||
- `docs/features/GOV-010-development-quality-architecture/qa/test-results.md`:测试、安全、性能和构建体积证据。
|
||
- `docs/features/GOV-010-development-quality-architecture/qa/visual-qa.md`:桌面和移动视觉回归证据。
|
||
- `docs/features/GOV-010-development-quality-architecture/review/code-review.md`:代码 Review。
|
||
- `docs/features/GOV-010-development-quality-architecture/review/standards-review.md`:规范符合性 Review。
|
||
- `docs/features/GOV-010-development-quality-architecture/release-notes.md`:未发布变更说明。
|
||
|
||
### 修改文件
|
||
|
||
- `tools/governance/feature-record.mjs`:必备开发总结和结构化证据校验。
|
||
- `tools/governance/feature-record.test.mjs`:治理规则的正反例测试。
|
||
- `tools/governance/finish.mjs`:读取档案并执行证据门禁。
|
||
- `tools/governance/start.mjs`:为后续功能生成 GitNexus 影响计划骨架。
|
||
- `tools/boundaries/verify-project-boundaries.mjs`:前端 HTTP 请求边界校验。
|
||
- `tools/boundaries/verify-project-boundaries.test.mjs`:Axios、fetch、业务 URL 和合法分层测试。
|
||
- `web/package.json`、`pnpm-lock.yaml`:用 Axios 1.19.0 替换 `openapi-fetch`。
|
||
- `web/tsconfig.json`、`web/vite.config.ts`、`web/vitest.config.ts`:统一 `@/* -> web/src/*` 别名。
|
||
- `web/src/vite-config.test.ts`:别名和现有同源代理测试。
|
||
- `docs/governance/code-development-standards.md`:安全、性能、复用、前后端架构规范。
|
||
- `docs/governance/development-workflow.md`:GitNexus 同步修改分析、总结和 Review 流程。
|
||
- `docs/governance/documentation-traceability.md`:独立开发总结的档案位置和职责。
|
||
- `docs/governance/prd-standard.md`:安全、性能、关联模块和依赖评估输入。
|
||
- `docs/governance/review-standard.md`:两类 Review 的新增必查证据。
|
||
- `docs/templates/prd-template.md`、`docs/templates/code-review-template.md`、`docs/templates/standards-review-template.md`:新增必填章节和检查项。
|
||
- `docs/architecture/system-architecture.md`:模块内分层和 Axios/OpenAPI 数据流事实。
|
||
- `AGENTS.md`:开发代理入口强制要求。
|
||
- `CHANGELOG.md`:GOV-010 未发布变更。
|
||
- `docs/features/GOV-010-development-quality-architecture/manifest.yaml`:实施状态和总结入口。
|
||
|
||
### 删除文件
|
||
|
||
- `web/src/api/client.ts`:由 `utils/request.ts` 和业务域 API 取代。
|
||
- `web/src/api/client.test.ts`:由新请求封装和健康 API 测试取代。
|
||
|
||
---
|
||
|
||
### Task 1: 治理档案与证据校验
|
||
|
||
**实施状态:已完成。** 对应提交 `e12c572`,治理测试 9 项通过并已推送 Gitea。
|
||
|
||
**Files:**
|
||
|
||
- Modify: `tools/governance/feature-record.test.mjs`
|
||
- Modify: `tools/governance/feature-record.mjs`
|
||
- Modify: `tools/governance/finish.mjs`
|
||
- Modify: `tools/governance/start.mjs`
|
||
|
||
**Interfaces:**
|
||
|
||
- Consumes: `Map<string, string>`,键为功能目录内相对路径,值为完整 Markdown 内容。
|
||
- Produces: `getRequiredFeatureFiles(): string[]`,清单新增 `development-summary.md`。
|
||
- Produces: `getInvalidFeatureEvidence(featureReports: Map<string, string>): string[]`,返回 `文件:章节` 形式的问题,不抛出首个错误后停止。
|
||
- Produces: `buildImpactPlanTemplate(featureId: string): string`,生成包含影响范围、风险和同步修改清单的 Markdown 骨架。
|
||
- Completion behavior: `finish.mjs` 在文件存在校验后调用证据校验,并一次列出全部无效章节。
|
||
|
||
- [x] **Step 1: 先对现有治理符号执行 GitNexus 影响分析**
|
||
|
||
Run:
|
||
|
||
```text
|
||
gitnexus_impact(target="getRequiredFeatureFiles", direction="upstream", includeTests=true)
|
||
gitnexus_impact(target="getUnpassedReviewFiles", direction="upstream", includeTests=true)
|
||
```
|
||
|
||
Expected: LOW 或 MEDIUM;直接同步范围至少包含 `feature-record.test.mjs` 和 `finish.mjs`。若结果为 `partial`,记录限制并继续使用静态引用交叉核对。
|
||
|
||
- [x] **Step 2: 写治理规则失败测试**
|
||
|
||
在 `feature-record.test.mjs` 中加入以下结构化样例。完整有效档案必须包含:
|
||
|
||
```js
|
||
const validReports = new Map([
|
||
[
|
||
'development-summary.md',
|
||
`# 开发总结
|
||
|
||
## 原始开发需求
|
||
建立可自动执行的质量门禁。
|
||
|
||
## 需求与范围变化
|
||
范围未变化,仍只处理治理与请求脚手架。
|
||
|
||
## 实际完成需求
|
||
完成独立总结和证据校验。
|
||
|
||
## 修复缺陷
|
||
本次没有修复既有业务缺陷;只补足治理能力。
|
||
|
||
## 未完成与延期项
|
||
AI Provider 延期到独立功能,不属于本次范围。
|
||
|
||
## 关键提交
|
||
记录中文提交 SHA 与摘要。
|
||
|
||
## 验证证据
|
||
记录测试、构建和 Review 结果。
|
||
`,
|
||
],
|
||
['design.md', '# 设计\n\n## 安全策略与评估\n说明信任边界和残余风险。\n\n## 性能目标与评估\n说明预算和验证强度。\n'],
|
||
['test-plan.md', '# 测试\n\n## 安全验证\n验证脱敏错误。\n\n## 性能验证\n比较构建体积。\n'],
|
||
['gitnexus/impact-plan.md', '# 影响\n\n## 直接与间接影响\n列出消费者。\n\n## 跨模块同步修改\n逐项判断契约、缓存和进程。\n'],
|
||
['review/code-review.md', '# Review\n\n## 安全与残余风险\n证据充分。\n\n## 性能与资源影响\n增量可接受。\n\n## GitNexus 与同步修改\n实际影响符合计划。\n\n最终结论:passed\n'],
|
||
['review/standards-review.md', '# 规范 Review\n\n## 安全、性能与架构检查\n逐项符合。\n\n## GitNexus 与开发总结检查\n证据齐全。\n\n最终结论:passed\n'],
|
||
]);
|
||
```
|
||
|
||
断言:
|
||
|
||
```js
|
||
assert.ok(getRequiredFeatureFiles().includes('development-summary.md'));
|
||
assert.deepEqual(getInvalidFeatureEvidence(validReports), []);
|
||
```
|
||
|
||
再逐一删除章节、提供空正文、提供裸 `无`、裸 `不适用`、`N/A`,断言返回对应的 `文件:章节`。提供 `不适用:本功能不进入生产请求路径,边界仅为开发门禁。`,断言可以通过。
|
||
|
||
- [x] **Step 3: 运行测试确认按预期失败**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
npm run test:governance
|
||
```
|
||
|
||
Expected: FAIL,原因是 `development-summary.md` 尚未在清单中,且 `getInvalidFeatureEvidence`、`buildImpactPlanTemplate` 尚未导出。
|
||
|
||
- [x] **Step 4: 实现最小 Markdown 章节校验**
|
||
|
||
在 `feature-record.mjs` 中保持单文件职责,加入固定规则:
|
||
|
||
```js
|
||
const REQUIRED_EVIDENCE_SECTIONS = Object.freeze({
|
||
'development-summary.md': [
|
||
'原始开发需求',
|
||
'需求与范围变化',
|
||
'实际完成需求',
|
||
'修复缺陷',
|
||
'未完成与延期项',
|
||
'关键提交',
|
||
'验证证据',
|
||
],
|
||
'design.md': ['安全策略与评估', '性能目标与评估'],
|
||
'test-plan.md': ['安全验证', '性能验证'],
|
||
'gitnexus/impact-plan.md': ['直接与间接影响', '跨模块同步修改'],
|
||
'review/code-review.md': ['安全与残余风险', '性能与资源影响', 'GitNexus 与同步修改'],
|
||
'review/standards-review.md': [
|
||
'安全、性能与架构检查',
|
||
'GitNexus 与开发总结检查',
|
||
],
|
||
});
|
||
```
|
||
|
||
章节解析允许标题前带数字序号,例如 `## 8. 安全策略与评估` 与 `## 安全策略与评估` 视为同一标题;正文截止下一个二级标题。有效正文至少包含一个非标题、非注释、非空白的说明行;若规范化后仅为 `无`、`不适用`、`N/A` 或 `none` 则无效。不要解析业务结论真伪,也不要依赖包含“安全”或“性能”的任意散文。
|
||
|
||
- [x] **Step 5: 让开始门禁生成影响计划骨架**
|
||
|
||
导出并测试:
|
||
|
||
```js
|
||
export function buildImpactPlanTemplate(featureId) {
|
||
return `# GitNexus 开发前影响计划
|
||
|
||
- 功能编号:${featureId}
|
||
- 总体风险:待分析
|
||
|
||
## 直接与间接影响
|
||
|
||
请记录 query、context、upstream impact、消费者和执行流。
|
||
|
||
## 跨模块同步修改
|
||
|
||
请逐项判断 HTTP/OpenAPI、Web API、消息契约、数据库、Redis、API、Scheduler、Worker、配置部署、测试和文档。
|
||
`;
|
||
}
|
||
```
|
||
|
||
`start.mjs` 在创建 `before.md` 的同一目录创建 `impact-plan.md`;若任一目标文件已存在则在写入前失败,禁止覆盖历史。GOV-010 已有人工影响计划,因此只影响后续功能。
|
||
|
||
- [x] **Step 6: 接入完成门禁**
|
||
|
||
`finish.mjs` 读取全部必备文件形成 `Map`,先报告缺失文件,再调用:
|
||
|
||
```js
|
||
const invalidEvidence = getInvalidFeatureEvidence(featureReports);
|
||
if (invalidEvidence.length > 0) {
|
||
throw new Error(`完成门禁未通过,证据章节缺失或说明无效:\n- ${invalidEvidence.join('\n- ')}`);
|
||
}
|
||
```
|
||
|
||
已发布 GOV-001 至 GOV-008 不批量修改;它们是不可变历史,也不再重新执行新的完成门禁。仍为 `unreleased` 的 GOV-009、FEAT-MO-001 以及后续档案,在将来完成时必须满足新规则。
|
||
|
||
- [x] **Step 7: 运行治理测试**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
npm run test:governance
|
||
```
|
||
|
||
Expected: PASS,覆盖必备清单、有效章节、空章节、裸占位词、带理由不适用和影响计划骨架。
|
||
|
||
- [x] **Step 8: 检测变化并提交推送**
|
||
|
||
Run GitNexus `detect_changes(scope="all")`,确认只影响治理完成路径。然后:
|
||
|
||
```bash
|
||
git add tools/governance/feature-record.mjs tools/governance/feature-record.test.mjs tools/governance/finish.mjs tools/governance/start.mjs
|
||
git commit -m "feat(GOV-010): 强制校验开发质量证据"
|
||
git push origin main
|
||
```
|
||
|
||
Expected: 本地 HEAD 与 `refs/heads/main` 远程 SHA 一致。
|
||
|
||
---
|
||
|
||
### Task 2: 规范、模板与架构事实
|
||
|
||
**实施状态:已完成。** 对应提交 `3a22fde`,格式、治理和环境相关验证通过并已推送 Gitea。
|
||
|
||
**Files:**
|
||
|
||
- Create: `docs/templates/development-summary-template.md`
|
||
- Modify: `docs/governance/code-development-standards.md`
|
||
- Modify: `docs/governance/development-workflow.md`
|
||
- Modify: `docs/governance/documentation-traceability.md`
|
||
- Modify: `docs/governance/prd-standard.md`
|
||
- Modify: `docs/governance/review-standard.md`
|
||
- Modify: `docs/templates/prd-template.md`
|
||
- Modify: `docs/templates/code-review-template.md`
|
||
- Modify: `docs/templates/standards-review-template.md`
|
||
- Modify: `docs/architecture/system-architecture.md`
|
||
- Modify: `AGENTS.md`
|
||
- Modify: `CHANGELOG.md`
|
||
|
||
**Interfaces:**
|
||
|
||
- Consumes: Task 1 的固定章节名,模板标题必须逐字一致。
|
||
- Produces: 后续功能可直接复制的开发总结、安全、性能、GitNexus 和 Review 模板。
|
||
- Produces: 前端 Axios/OpenAPI 分工与后端业务模块内按需分层的正式架构事实。
|
||
|
||
- [x] **Step 1: 对入口规范和架构文档执行影响检查**
|
||
|
||
Run GitNexus 对 `AGENTS.md`、`code-development-standards.md`、`development-workflow.md` 和 `system-architecture.md` 文件执行 upstream impact。Expected: 文档变化不影响生产执行流;若工具只能返回文件级 LOW/partial,记录限制。
|
||
|
||
- [x] **Step 2: 建立与门禁完全一致的模板**
|
||
|
||
`development-summary-template.md` 必须包含 Task 1 的七个二级标题,并在每节说明应记录的事实。PRD 模板新增:
|
||
|
||
```markdown
|
||
## 安全需求与信任边界
|
||
|
||
## 性能目标与容量假设
|
||
|
||
## 关联模块与同步修改
|
||
|
||
## 新增依赖评估
|
||
```
|
||
|
||
代码 Review 模板新增 `安全与残余风险`、`性能与资源影响`、`GitNexus 与同步修改`;规范 Review 模板新增 `安全、性能与架构检查`、`GitNexus 与开发总结检查`。标题必须与 Task 1 校验规则一致。
|
||
|
||
- [x] **Step 3: 更新代码开发规范**
|
||
|
||
明确写入:
|
||
|
||
- 安全评估的资产、信任边界、认证授权、校验与注入、XSS/CSRF/CORS/SSRF、凭据、供应链、日志、保留、滥用和残余风险。
|
||
- 性能评估的延迟/吞吐/新鲜度、复杂度、MySQL 索引/N+1、Redis TTL/一致性/击穿、API 载荷、前端包体/渲染/图表、Worker 并发/幂等/背压、上游与 AI 超时/重试/批处理/成本。
|
||
- 出现真实重复并形成稳定职责后再抽取工具、Composable、组件或共享库;禁止凭感觉预抽象。
|
||
- 后端以业务模块为一级目录,模块内部按需建立 `controllers/services/dto/domain/repositories/adapters/types/utils`,禁止全局堆放和空透传层。
|
||
- 前端 `utils/request.ts` 独占 Axios;业务接口位于 `api/<业务域>/index.ts`;页面、组件、Store、Composable 禁止直接 HTTP;生成 OpenAPI 类型继续作为契约来源。
|
||
- 新依赖安装前记录用途、替代、安全、许可证、体积/成本、维护和退出方案。
|
||
|
||
- [x] **Step 4: 更新流程与追溯规范**
|
||
|
||
开发前流程要求 GitNexus 同时回答影响其他功能/模块和是否需要同步修改;缺陷修复不例外。开发后流程要求先填写开发总结,再做两类 Review。追溯树加入:
|
||
|
||
```text
|
||
├── development-summary.md
|
||
```
|
||
|
||
并明确 PRD、开发总结、release notes 三者分别记录目标、实际完成和面向版本使用者的变化。
|
||
|
||
- [x] **Step 5: 更新系统架构与代理入口**
|
||
|
||
`system-architecture.md` 增加 Axios/OpenAPI 数据流和业务模块内分层;修正当前仓库结构中不存在的顶层 `contracts/` 表述,使用实际的 `server/openapi`、`server/libs/http-contracts` 和 `server/libs/message-contracts`。`AGENTS.md` 增加强制安全/性能、GitNexus 同步修改、独立开发总结、前后端架构边界。`CHANGELOG.md` 的 Unreleased 增加 GOV-010 条目。
|
||
|
||
- [x] **Step 6: 校验标题与格式**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
rg -n "^## (原始开发需求|需求与范围变化|实际完成需求|修复缺陷|未完成与延期项|关键提交|验证证据|安全策略与评估|性能目标与评估|安全验证|性能验证|直接与间接影响|跨模块同步修改|安全与残余风险|性能与资源影响|GitNexus 与同步修改|安全、性能与架构检查|GitNexus 与开发总结检查)$" docs AGENTS.md
|
||
pnpm exec prettier --check AGENTS.md CHANGELOG.md docs/governance docs/templates docs/architecture/system-architecture.md
|
||
npm run test:governance
|
||
```
|
||
|
||
Expected: 所有门禁标题均出现在对应模板或 GOV-010 档案中,格式与治理测试通过。
|
||
|
||
- [x] **Step 7: 检测变化并提交推送**
|
||
|
||
Run GitNexus `detect_changes(scope="all")`,然后:
|
||
|
||
```bash
|
||
git add AGENTS.md CHANGELOG.md docs/governance docs/templates docs/architecture/system-architecture.md
|
||
git commit -m "docs(GOV-010): 完善安全性能与架构规范"
|
||
git push origin main
|
||
```
|
||
|
||
---
|
||
|
||
### Task 3: Axios 请求封装与路径别名
|
||
|
||
**实施状态:已完成。** 对应提交 `4105336`,请求、配置、类型、lint 和格式验证通过并已推送 Gitea。
|
||
|
||
**Files:**
|
||
|
||
- Create: `web/src/utils/request.test.ts`
|
||
- Create: `web/src/utils/request.ts`
|
||
- Modify: `web/package.json`
|
||
- Modify: `pnpm-lock.yaml`
|
||
- Modify: `web/tsconfig.json`
|
||
- Modify: `web/vite.config.ts`
|
||
- Modify: `web/vitest.config.ts`
|
||
- Modify: `web/src/vite-config.test.ts`
|
||
- Delete: `web/src/api/client.ts`
|
||
- Delete: `web/src/api/client.test.ts`
|
||
|
||
**Interfaces:**
|
||
|
||
- Produces: `type RequestErrorKind = 'network' | 'http' | 'unknown'`。
|
||
- Produces: `class ApiRequestError extends Error { kind: RequestErrorKind; status?: number }`。
|
||
- Produces: `interface RequestClientOptions { baseURL: string; timeoutMs?: number; adapter?: AxiosAdapter }`。
|
||
- Produces: `type RequestClient = <TData>(config: AxiosRequestConfig) => Promise<TData>`。
|
||
- Produces: `createRequestClient(options: RequestClientOptions): RequestClient`。
|
||
- Produces: 默认导出 `request`,其 base URL 为 `import.meta.env.VITE_API_BASE_URL || ''`,默认超时 `10_000` 毫秒。
|
||
- Produces: `@/*` 同时在 TypeScript、Vite 和 Vitest 解析为 `web/src/*`。
|
||
|
||
- [x] **Step 1: 对旧请求符号和 Vite 配置执行影响分析**
|
||
|
||
Run:
|
||
|
||
```text
|
||
gitnexus_impact(target="createApiClient", direction="upstream", includeTests=true)
|
||
gitnexus_impact(target="ApiRequestError", direction="upstream", includeTests=true)
|
||
gitnexus_impact(target="readDevelopmentPublicEnv", direction="upstream", includeTests=true)
|
||
```
|
||
|
||
Expected: 旧请求符号风险 LOW/partial,直接引用仅旧测试;Vite 配置影响开发服务器和配置测试,保持现有 `/api` 代理。
|
||
|
||
- [x] **Step 2: 记录依赖评估和构建基线**
|
||
|
||
在后续 `qa/test-results.md` 预留并最终记录:Axios 1.19.0、MIT、官方仓库、替代项 `fetch/openapi-fetch`、选择原因、退出方式。当前构建基线记录为 JS `163908` 字节、CSS `805` 字节;最终构建使用实际产物重新测量。依赖元数据查询若使用 npm,指定任务临时缓存,避免本机 `~/.npm` 的既有权限问题:
|
||
|
||
```bash
|
||
npm_config_cache=/tmp/a-share-analysis-gov010-npm-cache pnpm view axios version license repository.url --json
|
||
```
|
||
|
||
- [x] **Step 3: 安装 Axios 并移除旧请求库**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
pnpm --filter @a-share-analysis/web remove openapi-fetch
|
||
pnpm --filter @a-share-analysis/web add axios@1.19.0
|
||
```
|
||
|
||
Expected: `web/package.json` 只保留 Axios 作为浏览器 HTTP 请求库,锁文件不再含 `openapi-fetch`。
|
||
|
||
- [x] **Step 4: 写 Axios 封装失败测试**
|
||
|
||
使用自定义 `AxiosAdapter` 返回确定响应,覆盖:
|
||
|
||
```ts
|
||
const request = createRequestClient({
|
||
baseURL: 'http://127.0.0.1:3000/',
|
||
timeoutMs: 10_000,
|
||
adapter: async (config) => ({
|
||
data: healthyDto,
|
||
status: 200,
|
||
statusText: 'OK',
|
||
headers: {},
|
||
config,
|
||
}),
|
||
});
|
||
|
||
await expect(
|
||
request<HealthResponseDto>({ url: '/api/v1/health', method: 'get' }),
|
||
).resolves.toEqual(healthyDto);
|
||
```
|
||
|
||
另外让 adapter 抛出包含 `mysql://root:secret@internal` 的 `AxiosError`,断言最终错误只含 `API 请求失败,请稍后重试`、`kind` 和非敏感 `status`。使用已取消的 `AbortController.signal` 断言取消错误保持 `axios.isCancel(error) === true`。
|
||
|
||
- [x] **Step 5: 运行 Web 测试确认失败**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
pnpm --filter @a-share-analysis/web test -- src/utils/request.test.ts
|
||
```
|
||
|
||
Expected: FAIL,原因是 `web/src/utils/request.ts` 尚不存在。
|
||
|
||
- [x] **Step 6: 实现类型化 request 包装器**
|
||
|
||
核心行为:
|
||
|
||
```ts
|
||
export function createRequestClient({
|
||
baseURL,
|
||
timeoutMs = 10_000,
|
||
adapter,
|
||
}: RequestClientOptions): RequestClient {
|
||
const client = axios.create({
|
||
baseURL: baseURL.replace(/\/$/, ''),
|
||
timeout: timeoutMs,
|
||
adapter,
|
||
});
|
||
|
||
client.interceptors.request.use((config) => config);
|
||
|
||
return async <TData>(config: AxiosRequestConfig) => {
|
||
try {
|
||
const response = await client.request<TData>(config);
|
||
return response.data;
|
||
} catch (error) {
|
||
if (axios.isCancel(error)) throw error;
|
||
throw toApiRequestError(error);
|
||
}
|
||
};
|
||
}
|
||
```
|
||
|
||
请求拦截器保留为后续认证扩展点,但不提前实现 Token 刷新。`toApiRequestError` 不保存原始错误消息、URL、请求头或响应正文。HTTP 状态只允许保存数字状态码。
|
||
|
||
- [x] **Step 7: 增加 `@` 别名并保留现有代理**
|
||
|
||
- `web/tsconfig.json`: `baseUrl: "."`,`paths: { "@/*": ["src/*"] }`。
|
||
- `web/vite.config.ts`: `resolve.alias['@'] = path.resolve(webDirectory, 'src')`。
|
||
- `web/vitest.config.ts`: 使用 `fileURLToPath(new URL('./src', import.meta.url))` 配置同一别名。
|
||
- `vite-config.test.ts`: 同时断言 `resolve.alias` 和原有 `/api` 代理,禁止迁移时破坏同源策略。
|
||
|
||
- [x] **Step 8: 删除旧客户端并运行局部验证**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
rg -n "openapi-fetch|createApiClient|src/api/client" web pnpm-lock.yaml
|
||
pnpm --filter @a-share-analysis/web test -- src/utils/request.test.ts src/vite-config.test.ts
|
||
pnpm --filter @a-share-analysis/web typecheck
|
||
```
|
||
|
||
Expected: `rg` 无匹配;请求与 Vite 测试、类型检查通过。
|
||
|
||
- [x] **Step 9: 检测变化并提交推送**
|
||
|
||
Run GitNexus `detect_changes(scope="all")`,确认只影响 Web 请求基础设施与配置。然后:
|
||
|
||
```bash
|
||
git add web/src/utils web/src/api/client.ts web/src/api/client.test.ts web/package.json web/tsconfig.json web/vite.config.ts web/vitest.config.ts web/src/vite-config.test.ts pnpm-lock.yaml
|
||
git commit -m "refactor(GOV-010): 统一封装前端 Axios 请求"
|
||
git push origin main
|
||
```
|
||
|
||
---
|
||
|
||
### Task 4: 健康 API 分域与 HTTP 架构边界
|
||
|
||
**实施状态:已完成。** 对应提交 `d2c1863`,边界测试 16 项、Web 测试 11 项及契约验证通过并已推送 Gitea。
|
||
|
||
**Files:**
|
||
|
||
- Create: `web/src/api/health/index.test.ts`
|
||
- Create: `web/src/api/health/index.ts`
|
||
- Modify: `tools/boundaries/verify-project-boundaries.test.mjs`
|
||
- Modify: `tools/boundaries/verify-project-boundaries.mjs`
|
||
|
||
**Interfaces:**
|
||
|
||
- Consumes: Task 3 默认导出 `request<TData>(config): Promise<TData>`。
|
||
- Consumes: `components['schemas']['HealthResponseDto']` from `web/src/api/generated/schema.ts`。
|
||
- Produces: `getHealth(signal?: AbortSignal): Promise<HealthResponseDto>`。
|
||
- Boundary: 只有 `web/src/utils/request.ts` 可以导入 `axios` 或创建 Axios 实例;`web/src` 的其他运行时代码禁止调用全局 `fetch`。
|
||
- Boundary: `/api/...` 业务路径字符串只能出现在 `web/src/api/` 或 `web/src/utils/request.ts`;测试和自动生成文件按各自 fixture 验证,不放宽生产源码。
|
||
|
||
- [x] **Step 1: 对边界校验符号执行影响分析**
|
||
|
||
Run:
|
||
|
||
```text
|
||
gitnexus_impact(target="collectSourceFiles", direction="upstream", includeTests=true)
|
||
gitnexus_impact(target="verifyProjectBoundaries", direction="upstream", includeTests=true)
|
||
```
|
||
|
||
Expected: LOW;只影响项目验证和其测试,不进入线上执行流。
|
||
|
||
- [x] **Step 2: 写健康 API 失败测试**
|
||
|
||
使用 Vitest mock `@/utils/request`:
|
||
|
||
```ts
|
||
vi.mock('@/utils/request', () => ({ default: vi.fn() }));
|
||
|
||
await getHealth(signal);
|
||
|
||
expect(request).toHaveBeenCalledWith({
|
||
url: '/api/v1/health',
|
||
method: 'get',
|
||
signal,
|
||
});
|
||
```
|
||
|
||
让 mock 返回完整 `HealthResponseDto`,并通过类型断言证明 `getHealth` 返回 DTO 而不是 `AxiosResponse`。
|
||
|
||
- [x] **Step 3: 写边界失败测试**
|
||
|
||
fixture 覆盖以下违规:
|
||
|
||
- Vue 页面 `import axios from 'axios'`。
|
||
- Store 中 `fetch('/api/v1/health')`。
|
||
- Composable 中 `axios.create()`。
|
||
- 页面中把 `'/api/v1/health'` 传给自定义调用函数。
|
||
- `web/src/api/health/index.ts` 自己导入 Axios 而不使用 `@/utils/request`。
|
||
|
||
合法 fixture 包含 `utils/request.ts` 导入 Axios、`api/health/index.ts` 导入统一 request、页面只导入 `getHealth`。继续保留 Web 禁止导入 Server 和内部消息契约测试。
|
||
|
||
- [x] **Step 4: 运行测试确认失败**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
pnpm --filter @a-share-analysis/web test -- src/api/health/index.test.ts
|
||
npm run test:boundaries
|
||
```
|
||
|
||
Expected: 健康 API 测试因文件不存在失败;边界违规 fixture 因当前校验未识别 Axios/fetch 而失败。
|
||
|
||
- [x] **Step 5: 实现健康业务域 API**
|
||
|
||
```ts
|
||
import type { components } from '@/api/generated/schema';
|
||
import request from '@/utils/request';
|
||
|
||
export type HealthResponseDto = components['schemas']['HealthResponseDto'];
|
||
|
||
/** 健康接口只返回 OpenAPI DTO,不把 Axios 响应对象扩散到功能层。 */
|
||
export function getHealth(signal?: AbortSignal): Promise<HealthResponseDto> {
|
||
return request<HealthResponseDto>({
|
||
url: '/api/v1/health',
|
||
method: 'get',
|
||
signal,
|
||
});
|
||
}
|
||
```
|
||
|
||
保留现有 `api/adapters/health.adapter.ts`;它负责 DTO 到 ViewModel,不移动到全局工具目录,也不接入当前页面。
|
||
|
||
- [x] **Step 6: 实现 AST 边界校验**
|
||
|
||
在现有 TypeScript AST 遍历中收集:
|
||
|
||
- `axios` 的静态/动态导入和 require。
|
||
- 标识符为 `fetch` 的调用。
|
||
- Axios 命名空间的 `create/get/post/put/patch/delete/request` 调用。
|
||
- 调用参数中的 `/api` 绝对业务路径字符串。
|
||
|
||
此外,对 `web/src/api/<业务域>/` 下非测试、非 `generated` 的运行时代码建立正向约束:文件只要声明业务 API 路径,就必须静态导入 `@/utils/request`,不得通过其他本地包装器绕开统一入口。
|
||
|
||
按 `path.relative(webSourceRoot, sourcePath)` 判断允许位置,错误格式必须包含源码路径和违规种类。不要扫描注释或普通展示文本;业务 URL 只检查 CallExpression 参数中的字符串字面量。
|
||
|
||
- [x] **Step 7: 运行局部与契约验证**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
pnpm --filter @a-share-analysis/web test -- src/api/health/index.test.ts src/api/adapters/health.adapter.test.ts
|
||
npm run test:boundaries
|
||
pnpm check:contracts
|
||
pnpm typecheck
|
||
```
|
||
|
||
Expected: 全部 PASS;OpenAPI 输出无业务字段变化,Web 仍不依赖 Server 源码。
|
||
|
||
- [x] **Step 8: 检测变化并提交推送**
|
||
|
||
Run GitNexus `detect_changes(scope="all")`,然后:
|
||
|
||
```bash
|
||
git add web/src/api/health tools/boundaries/verify-project-boundaries.mjs tools/boundaries/verify-project-boundaries.test.mjs
|
||
git commit -m "feat(GOV-010): 建立前端 API 分域边界"
|
||
git push origin main
|
||
```
|
||
|
||
---
|
||
|
||
### Task 5: GOV-010 档案、依赖评估与开发总结
|
||
|
||
**实施状态:进行中。** 开发总结、发布说明、依赖评估和档案状态已补齐;安全审计发现并通过 `e992edc` 修复 Swagger 的 `js-yaml` 传递依赖漏洞,等待本阶段档案提交。
|
||
|
||
**Files:**
|
||
|
||
- Create: `docs/features/GOV-010-development-quality-architecture/development-summary.md`
|
||
- Create: `docs/features/GOV-010-development-quality-architecture/release-notes.md`
|
||
- Modify: `docs/features/GOV-010-development-quality-architecture/manifest.yaml`
|
||
- Modify: `docs/features/GOV-010-development-quality-architecture/design.md`
|
||
- Modify: `docs/features/GOV-010-development-quality-architecture/test-plan.md`
|
||
- Modify: `docs/features/GOV-010-development-quality-architecture/implementation-plan.md`
|
||
|
||
**Interfaces:**
|
||
|
||
- Consumes: Task 1 的固定开发总结章节和 Task 2 模板。
|
||
- Produces: 与实际代码、依赖版本、范围变化和测试结果一致的功能档案。
|
||
|
||
- [x] **Step 1: 对照 Git diff 更新实际完成事实**
|
||
|
||
`development-summary.md` 必须逐条列出 FR-001 至 FR-010 的实际状态;原始需求和需求变化分别记录。明确写出:当前页面仍未接入健康 API、AI Provider 未实现、后端现有健康模块没有为目录外观迁移。
|
||
|
||
同时把已批准档案的章节标题规范化为 Task 1 的门禁标题:设计使用 `安全策略与评估`、`性能目标与评估`,测试计划使用 `安全验证`、`性能验证`,GitNexus 影响计划使用 `直接与间接影响`、`跨模块同步修改`。只调整标题和组织,不改变用户已经批准的结论。
|
||
|
||
- [x] **Step 2: 完成安全与依赖评估**
|
||
|
||
在设计和总结中记录 Axios 1.19.0、MIT、官方来源、锁文件、替代方案、前端体积增量、维护状态和可回退到原生 fetch 的退出方式。运行:
|
||
|
||
```bash
|
||
pnpm audit --prod
|
||
git diff --check
|
||
git status --short
|
||
```
|
||
|
||
若 audit 报告风险,先按可利用性和影响评估,Important 以上不得进入 passed Review;不得为了清零数字盲目升级无关依赖。
|
||
|
||
- [ ] **Step 3: 完成性能证据**
|
||
|
||
构建后记录实际 JS/CSS 文件字节数,与 Task 3 基线 `163908/805` 比较;确认 request 没有默认重试,默认超时为 10 秒。治理校验只在开发/发布路径运行,不做生产负载测试,并在“不适用”结论中写清边界。
|
||
|
||
- [x] **Step 4: 更新清单与发布说明**
|
||
|
||
`manifest.yaml` 状态改为 `verifying`,保留 `release: unreleased`。`release-notes.md` 说明治理门禁、架构规范和 Axios 迁移,不宣称市场概览、AI 或用户功能已完成。
|
||
|
||
- [ ] **Step 5: 校验档案内容**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
npm run test:governance
|
||
pnpm exec prettier --check docs/features/GOV-010-development-quality-architecture
|
||
git diff --check
|
||
```
|
||
|
||
Expected: PASS,且开发总结不存在空章节或无解释占位词。
|
||
|
||
- [ ] **Step 6: 检测变化并提交推送**
|
||
|
||
Run GitNexus `detect_changes(scope="all")`,然后:
|
||
|
||
```bash
|
||
git add docs/features/GOV-010-development-quality-architecture
|
||
git commit -m "docs(GOV-010): 记录开发需求与完成结果"
|
||
git push origin main
|
||
```
|
||
|
||
---
|
||
|
||
### Task 6: 全量验证、视觉回归与 GitNexus 对比
|
||
|
||
**Files:**
|
||
|
||
- Create: `docs/features/GOV-010-development-quality-architecture/qa/test-results.md`
|
||
- Create: `docs/features/GOV-010-development-quality-architecture/qa/visual-qa.md`
|
||
- Create: `docs/features/GOV-010-development-quality-architecture/gitnexus/detected-changes.md`
|
||
- Create: `docs/features/GOV-010-development-quality-architecture/gitnexus/comparison.md`
|
||
- Create or update: `docs/features/GOV-010-development-quality-architecture/gitnexus/after.md`
|
||
- Create: `docs/features/GOV-010-development-quality-architecture/screenshots/iterations/app-shell-desktop-1440x900-<sha>.png`
|
||
- Create: `docs/features/GOV-010-development-quality-architecture/screenshots/iterations/app-shell-mobile-390x844-<sha>.png`
|
||
|
||
**Interfaces:**
|
||
|
||
- Consumes: Tasks 1-5 的完整实现和档案。
|
||
- Produces: 最新、可复现的测试、安全、性能、视觉和 GitNexus 证据。
|
||
|
||
- [ ] **Step 1: 执行全量非浏览器验证**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
pnpm check:contracts
|
||
pnpm lint
|
||
pnpm format:check
|
||
pnpm typecheck
|
||
pnpm test
|
||
pnpm build
|
||
```
|
||
|
||
Expected: 全部退出码 0。任何失败先按 systematic-debugging 查根因并修复,不能只在报告中标记忽略。
|
||
|
||
- [ ] **Step 2: 检查构建产物和敏感信息**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
wc -c web/dist/assets/*.js web/dist/assets/*.css
|
||
rg -n "MYSQL_PASSWORD|AI_API_KEY|Root@|mysql://root:|Authorization: Bearer" web/dist || true
|
||
pnpm audit --prod
|
||
```
|
||
|
||
Expected: 构建产物不含敏感标记;记录实际包体增量和 audit 结论。
|
||
|
||
- [ ] **Step 3: 执行浏览器与源码发布验证**
|
||
|
||
确认本机 Redis 可用后运行:
|
||
|
||
```bash
|
||
pnpm verify:e2e
|
||
pnpm verify:release
|
||
```
|
||
|
||
Expected: 桌面和移动 Chromium 均通过,API 健康契约通过,源码部署门禁通过;不启动 Docker 或替代基础设施。
|
||
|
||
- [ ] **Step 4: 保存同视口视觉证据**
|
||
|
||
使用 Playwright 截取 1440x900 和 390x844 的应用外壳;检查页面可见、无横向溢出、无控制台 error/warning、标题和主内容不重叠。因为本次不改 UI,视觉结论应为“无可观察回归”,而不是宣称新增页面设计。
|
||
|
||
- [ ] **Step 5: 运行 GitNexus 开发后检测**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
npx gitnexus analyze
|
||
npx gitnexus status
|
||
```
|
||
|
||
调用 `gitnexus_detect_changes(scope="compare", base_ref="1c1b15e")`,记录变更符号、执行流、风险和工具限制。`comparison.md` 逐项对照开发前同步修改表,特别确认 HTTP 字段、RocketMQ、MySQL、Redis、Scheduler 和 Worker 未发生计划外变化。
|
||
|
||
- [ ] **Step 6: 填写 QA 与 GitNexus 报告**
|
||
|
||
`test-results.md` 记录命令、时间、退出码、关键输出、Axios 依赖评估、安全扫描和包体数据;`visual-qa.md` 链接两张截图并记录视口与结论;`detected-changes.md` 和 `comparison.md` 不得只写“通过”。
|
||
|
||
- [ ] **Step 7: 执行完成门禁的预检**
|
||
|
||
在 Review 尚未标记 passed 前,`governance:finish` 应明确只因 Review 或尚缺 Review 报告失败,不能因开发总结、安全、性能或影响章节失败。记录预检结果,但不要伪造 passed Review。
|
||
|
||
---
|
||
|
||
### Task 7: 双 Review、完成门禁与最终推送
|
||
|
||
**Files:**
|
||
|
||
- Create: `docs/features/GOV-010-development-quality-architecture/review/code-review.md`
|
||
- Create: `docs/features/GOV-010-development-quality-architecture/review/standards-review.md`
|
||
- Modify: all files implicated by Review findings
|
||
- Modify: `docs/features/GOV-010-development-quality-architecture/development-summary.md`
|
||
- Modify: `docs/features/GOV-010-development-quality-architecture/manifest.yaml`
|
||
- Modify: `docs/features/GOV-010-development-quality-architecture/qa/test-results.md`
|
||
- Modify: `docs/features/GOV-010-development-quality-architecture/gitnexus/*`
|
||
|
||
**Interfaces:**
|
||
|
||
- Consumes: 完整 Git diff、PRD、设计、实施计划、QA 和 GitNexus 证据。
|
||
- Produces: 两份 findings-first Review;只有 Critical 和 Important 全部关闭后才能以独占末行写 `最终结论:passed`。
|
||
- Produces: 通过 `governance:finish` 的 GOV-010 功能档案,但仍保持 `release: unreleased`,除非用户另行确认版本发布。
|
||
|
||
- [ ] **Step 1: 使用代码 Review 流程审查实际实现**
|
||
|
||
按严重程度先列发现,检查请求错误脱敏、取消语义、类型边界、URL/HTTP 绕过、门禁误判、安全和性能证据、测试真实性。没有发现时明确写“未发现 Critical/Important/Minor”,并列残余风险和测试边界。
|
||
|
||
- [ ] **Step 2: 使用规范 Review 逐条审查**
|
||
|
||
检查中文注释、文件拆分、真实重复后抽象、后端按需分层、Axios/API 分域、OpenAPI 类型、GitNexus 同步修改、开发总结、中文提交和 Gitea 推送。不得把模板勾选框直接当证据,需引用文件和命令。
|
||
|
||
- [ ] **Step 3: 修复所有 Critical 和 Important**
|
||
|
||
每个修复先补失败测试并重跑受影响验证;更新 GitNexus 开发后报告和 Review 处置。Minor 可延期,但必须记录理由与后续功能编号。
|
||
|
||
- [ ] **Step 4: 运行最终完整验证**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
pnpm verify:release
|
||
npm run governance:finish -- GOV-010 development-quality-architecture
|
||
git diff --check
|
||
git status --short
|
||
```
|
||
|
||
Expected: 所有命令通过;`governance:finish` 验证独立开发总结、证据章节和双 Review。
|
||
|
||
- [ ] **Step 5: 提交前 GitNexus 检测**
|
||
|
||
调用 `gitnexus_detect_changes(scope="all")`,确认实际影响与 `comparison.md` 一致;发现计划外进程时停止提交,先补设计、测试和用户风险说明。
|
||
|
||
- [ ] **Step 6: 中文提交并立即推送**
|
||
|
||
```bash
|
||
git add AGENTS.md CHANGELOG.md docs tools web server/openapi/openapi.json pnpm-lock.yaml package.json
|
||
git commit -m "feat(GOV-010): 完成开发质量与架构治理"
|
||
git push origin main
|
||
```
|
||
|
||
不使用 `git add .`,避免把本地 env、索引或无关文件纳入提交。推送后核对:
|
||
|
||
```bash
|
||
git rev-parse HEAD
|
||
git ls-remote origin refs/heads/main
|
||
npx gitnexus status
|
||
```
|
||
|
||
Expected: 本地与远程 main SHA 一致;GitNexus 若因最终提交过期,运行 `npx gitnexus analyze`,单独以中文文档提交更新最终统计并再次推送。
|
||
|
||
- [ ] **Step 7: 保持未发布状态**
|
||
|
||
GOV-010 完成开发和 Review 后可将 `manifest.yaml` 状态设为 `reviewing` 或 `approved_for_release`(若现有状态机不支持后者则保持 `reviewing`),但 `release` 继续为 `unreleased`,不创建 `v0.0.8` 或更高标签。版本发布仍需结合 GOV-009 架构复核和用户后续确认。
|