1
0

feat: 完善全栈打包质量门禁

在业务开发前补齐 lint、format、verify 与生产运行时契约,确保开发联调和 executable 打包链路可重复验证。
This commit is contained in:
2026-05-09 14:48:49 +08:00
parent 5b412c624d
commit 3f477d1b57
20 changed files with 742 additions and 47 deletions

View File

@@ -0,0 +1,57 @@
## Purpose
定义项目代码质量门禁、格式化检查、快速检查和完整验证命令的行为要求,确保开发者可以通过文档化命令稳定验证源码质量、基础测试和生产 executable 行为。
## Requirements
### Requirement: ESLint 代码质量门禁
项目 SHALL 提供 ESLint 代码质量门禁,用于审查 TypeScript、React 前端、脚本和测试代码中的质量问题。
#### Scenario: 运行 lint 检查
- **WHEN** 开发者运行文档化的 lint 命令
- **THEN** 系统 SHALL 使用 ESLint 检查项目源码、脚本和测试代码,并在发现违规时以非零状态退出
#### Scenario: 检查 React Hooks 规则
- **WHEN** 前端 React 代码违反 Hooks 调用规则
- **THEN** lint 命令 MUST 失败并报告对应违规
#### Scenario: 保护前后端边界
- **WHEN** `src/web` 前端代码导入 `src/server` 后端运行时实现
- **THEN** lint 命令 MUST 失败并报告前后端边界违规
### Requirement: Prettier 代码格式门禁
项目 SHALL 提供 Prettier 格式化和格式检查命令,用于统一代码风格。
#### Scenario: 检查代码格式
- **WHEN** 开发者运行文档化的格式检查命令
- **THEN** 系统 SHALL 使用 Prettier 检查受管理文件,并在发现未格式化文件时以非零状态退出
#### Scenario: 自动格式化代码
- **WHEN** 开发者运行文档化的格式化命令
- **THEN** 系统 SHALL 使用 Prettier 重写受管理文件的格式
#### Scenario: 排除 OpenSpec 文档和生成产物
- **WHEN** Prettier 格式化或格式检查运行
- **THEN** 系统 MUST 排除 `openspec/``dist/``.build/``node_modules/``bun.lock` 和临时构建产物
### Requirement: 快速检查命令
项目 SHALL 提供快速 `check` 命令,用于日常开发期间验证代码质量和基础行为。
#### Scenario: 运行快速检查
- **WHEN** 开发者运行 `bun run check`
- **THEN** 系统 SHALL 依次执行类型检查、lint、格式检查和单元测试
#### Scenario: 快速检查失败
- **WHEN** `check` 中任一子检查失败
- **THEN** `check` MUST 以非零状态退出且不静默忽略失败
### Requirement: 完整验证命令
项目 SHALL 提供完整 `verify` 命令,用于提交前或发布前验证当前源码、测试和生产 executable 行为。
#### Scenario: 运行完整验证
- **WHEN** 开发者运行 `bun run verify`
- **THEN** 系统 SHALL 先运行 `check`,再运行生产构建和 executable smoke test
#### Scenario: 完整验证失败
- **WHEN** `verify` 中任一阶段失败
- **THEN** `verify` MUST 以非零状态退出且不能继续声明验证成功

View File

@@ -26,6 +26,21 @@
- **WHEN** 浏览器从 Vite 开发源请求非 API 前端路由
- **THEN** Vite SHALL 将该请求作为前端应用流量处理,而不是转发到后端
### Requirement: 开发期后端端口一致性
项目 SHALL 保证文档化的全栈开发命令中Vite proxy 目标端口与 Bun 后端监听端口来自同一配置来源。
#### Scenario: 使用默认开发端口
- **WHEN** 开发者未提供端口覆盖并运行文档化的全栈开发命令
- **THEN** Bun 后端 SHALL 监听默认端口,且 Vite SHALL 将 `/api/*` 代理到同一端口
#### Scenario: 使用 PORT 覆盖开发端口
- **WHEN** 开发者通过 `PORT` 覆盖后端端口并运行文档化的全栈开发命令
- **THEN** Bun 后端 SHALL 监听该端口,且 Vite SHALL 将 `/api/*` 代理到同一端口
#### Scenario: 避免代理端口与后端端口分叉
- **WHEN** 开发期脚本需要向 Vite 传递后端端口
- **THEN** 该代理端口 MUST 从文档化的后端端口配置派生,而不是作为独立对外配置导致分叉
### Requirement: 前端使用相对 API 路径
除非有文档化的部署配置覆盖该行为,前端代码 MUST 通过相对 `/api/*` URL 调用后端 API。
@@ -55,6 +70,13 @@
- **WHEN** 开发者运行文档化的全栈开发命令
- **THEN** 系统 SHALL 启动 Vite 前端开发服务器和 `/api/demo` 所需的 Bun 后端服务器
### Requirement: 开发质量命令文档化
项目 SHALL 在前端开发工作流文档中说明日常检查和完整验证命令。
#### Scenario: 查阅开发命令
- **WHEN** 开发者阅读 README 的开发或测试章节
- **THEN** 文档 SHALL 说明 `check` 用于日常开发检查,`verify` 用于提交前或发布前完整验证
### Requirement: 共享 TypeScript 契约
项目 SHALL 为前端和后端共同使用的请求与响应类型提供共享 TypeScript 边界。

View File

@@ -15,6 +15,40 @@
- **WHEN** 通过支持的运行时配置提供 host 或 port
- **THEN** server SHALL 使用该值,且不需要重新构建
### Requirement: HTTP method 语义
系统 SHALL 为运行时端点提供明确的 HTTP method 语义,避免不支持的 method 被错误地当作成功请求处理。
#### Scenario: GET 请求访问运行时端点
- **WHEN** 客户端使用 `GET` 请求 `/health``/api/demo`
- **THEN** Bun server SHALL 返回对应端点的成功响应
#### Scenario: HEAD 请求访问运行时端点
- **WHEN** 客户端使用 `HEAD` 请求 `/health``/api/demo`
- **THEN** Bun server SHALL 返回与 `GET` 相同的成功状态和 headers但 MUST NOT 返回响应体
#### Scenario: 不支持的 method 访问运行时端点
- **WHEN** 客户端使用不支持的 method 请求 `/health``/api/demo`
- **THEN** Bun server MUST 返回 JSON 405 响应,并带有描述允许 method 的 `Allow` header
### Requirement: 运行配置校验
系统 SHALL 对运行时 host 和 port 配置提供稳定、可测试的解析与校验行为。
#### Scenario: 使用默认运行配置
- **WHEN** 未提供 host 或 port 覆盖
- **THEN** server SHALL 使用 README 文档化的默认 host 和 port
#### Scenario: CLI 参数优先于环境变量
- **WHEN** CLI 参数和环境变量同时提供同一项运行配置
- **THEN** server SHALL 使用 CLI 参数中的值
#### Scenario: 拒绝无效端口
- **WHEN** port 配置不是整数、小于 0 或大于 65535
- **THEN** server MUST 拒绝启动并报告无效端口
#### Scenario: 接受端口边界值
- **WHEN** port 配置为 0 或 65535
- **THEN** server SHALL 将其作为有效端口配置处理
### Requirement: API 路由命名空间
系统 MUST 将 `/api/*` 保留给后端 API 路由。
@@ -26,6 +60,17 @@
- **WHEN** 请求访问未注册的 `/api/*` 路由
- **THEN** Bun server MUST 返回 JSON 404 响应,而不是前端 HTML 文档
### Requirement: API 错误响应一致性
系统 SHALL 为 API 命名空间内的错误返回机器可读 JSON 响应。
#### Scenario: 未知 API 路由
- **WHEN** 客户端请求未知的 `/api/*` 路由
- **THEN** Bun server MUST 返回包含 `error``status` 字段的 JSON 404 响应,而不是前端 HTML 文档
#### Scenario: API method 不允许
- **WHEN** 客户端使用不支持的 method 请求已存在的 API 路由
- **THEN** Bun server MUST 返回包含 `error``status` 字段的 JSON 405 响应
### Requirement: Demo API 端点
系统 SHALL 暴露 `/api/demo` 作为稳定 demo 端点,用于证明前后端集成可用。
@@ -59,6 +104,36 @@
- **WHEN** 客户端从生产 Bun runtime 打开前端页面
- **THEN** demo 页面 SHALL 能够从同源调用 `/api/demo` 并展示后端响应
### Requirement: 生产缓存策略
系统 SHALL 为生产静态资源和前端入口 HTML 使用明确的缓存策略。
#### Scenario: 请求前端入口 HTML
- **WHEN** 生产 Bun server 返回前端入口 HTML 文档
- **THEN** 响应 SHALL 使用 `Cache-Control: no-cache`
#### Scenario: 请求构建后的静态资源
- **WHEN** 生产 Bun server 返回 Vite 构建后的静态资源
- **THEN** 响应 SHALL 使用长缓存策略 `public, max-age=31536000, immutable`
#### Scenario: 请求未知静态资源
- **WHEN** 客户端请求不存在的 `/assets/*` 资源或带文件扩展名的未知路径
- **THEN** Bun server MUST 返回 404且 MUST NOT 返回前端入口 HTML 文档
### Requirement: 低风险安全响应头
系统 SHALL 在生产运行时响应中附加低风险安全响应头,提升基础安全性且不提前约束未来前端资源策略。
#### Scenario: 生产 HTML 响应包含安全头
- **WHEN** 生产 Bun server 返回前端 HTML 文档
- **THEN** 响应 SHALL 包含 `X-Content-Type-Options: nosniff``Referrer-Policy` headers
#### Scenario: 生产 JSON 响应包含安全头
- **WHEN** 生产 Bun server 返回 `/health``/api/*` JSON 响应
- **THEN** 响应 SHALL 包含 `X-Content-Type-Options: nosniff``Referrer-Policy` headers
#### Scenario: 生产静态资源响应包含安全头
- **WHEN** 生产 Bun server 返回 Vite 构建后的静态资源
- **THEN** 响应 SHALL 包含 `X-Content-Type-Options: nosniff``Referrer-Policy` headers
### Requirement: SPA fallback 行为
系统 SHALL 在生产环境中为非 API、非静态资源的前端路由返回前端入口 HTML 文档。

View File

@@ -15,6 +15,17 @@
- **WHEN** 前端生产构建失败
- **THEN** 系统 MUST 停止生产构建,且不能输出 stale executable
### Requirement: 构建生成确定性
生产构建 SHALL 以稳定顺序生成嵌入静态资源清单,减少重复构建产生无意义差异。
#### Scenario: 生成静态资源清单
- **WHEN** 生产构建扫描 Vite 输出目录并生成嵌入资源模块
- **THEN** 资源条目 SHALL 按稳定顺序输出
#### Scenario: 重复构建相同前端产物
- **WHEN** Vite 输出内容未变化且生产构建重复运行
- **THEN** 生成的嵌入资源模块 SHALL 保持语义一致且不依赖文件系统遍历顺序
### Requirement: 单 executable 输出
生产构建 SHALL 输出一个 standalone executable其中包含 Bun 后端、必要 server 依赖和构建后的前端资源。
@@ -42,12 +53,20 @@ executable MUST 将环境相关运行时配置保留在嵌入的前端和 server
- **THEN** executable SHALL 使用文档化的默认值
### Requirement: 构建验证
项目 SHALL 提供验证,证明生产 executable 可以服务 API、健康检查、静态资源和 SPA fallback 路由。
项目 SHALL 提供验证,证明生产 executable 可以服务 API、健康检查、静态资源和 SPA fallback 路由,并且完整验证 MUST 针对当前源码重新构建后的 executable 运行
#### Scenario: 验证 executable 路由
- **WHEN** 构建验证针对生成的 executable 运行
- **THEN** 它 SHALL 检查 `/api/demo``/health`、前端根路径、静态资源和前端 fallback 请求
- **THEN** 它 SHALL 检查 `/api/demo``/health`、前端根路径、静态资源、未知 API、未知静态资源和前端 fallback 请求
#### Scenario: 验证生产模式和响应头
- **WHEN** 构建验证针对生成的 executable 运行
- **THEN** 它 SHALL 检查 demo 响应处于 production runtime mode并验证代表性 HTML、JSON 和静态资源响应的缓存或低风险安全 headers
#### Scenario: 完整验证重新构建 executable
- **WHEN** 开发者运行完整验证命令
- **THEN** 系统 MUST 先基于当前源码执行生产构建,再对新生成的 executable 运行 smoke test
#### Scenario: 验证失败
- **WHEN** 任一代表性生产路由检查失败
- **WHEN** 任一代表性生产路由、响应头、生产模式或构建阶段检查失败
- **THEN** 验证 SHALL 使构建或测试命令失败