1
0

refactor: 移除 success 字段,简化为 matched 单层判定模型

This commit is contained in:
2026-05-11 13:12:55 +08:00
parent 548b44d28e
commit 35ba56888b
93 changed files with 3893 additions and 103 deletions

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-05-09

View File

@@ -0,0 +1,90 @@
## Context
当前项目是 Bun + TypeScript 的前后端一体化 demo开发期由 Vite React 提供前端 HMRBun 提供 `/api/*``/health`;生产期先构建 Vite 静态资源,再通过 Bun file import 将资源和后端编译为单 executable。
现有能力已经通过 `typecheck`、单元测试和 executable smoke test 验证,但真实业务开发尚未开始。此变更聚焦平台基础设施硬化,目标是在业务 API、数据模型和前端业务页面扩展之前先把开发联调、代码质量、格式一致性、HTTP 契约和生产验证闭环固化下来。
## Goals / Non-Goals
**Goals:**
- 引入 ESLint 审查代码质量、React Hooks 规则和前后端边界。
- 引入 Prettier 统一代码风格,但不格式化 `openspec/`,避免影响 OpenSpec 文档和 tasks 一行一个任务的规则。
- 提供快速 `check` 和完整 `verify` 两层验证命令。
- 让开发期 Vite proxy 目标端口和 Bun server 监听端口保持一致。
- 补齐 HTTP method、JSON 404/405、静态资源缓存和低风险安全头的运行时契约。
- 增强生产 executable smoke test确保验证的是当前源码构建出的生产产物。
- 同步 README使文档描述与脚本、构建中间产物和验证流程一致。
**Non-Goals:**
- 不开发 gateway checker 真实业务能力。
- 不引入数据库、持久化、认证、React Router 或 UI 组件库。
- 不新增 CI 配置;本次仅提供本地 `check``verify` 命令CI 接入留给后续仓库托管策略。
- 不引入 CSP本次只加入低风险安全响应头避免提前约束未来前端资源策略。
- 不做大规模目录重构或业务框架抽象。
## Decisions
### ESLint 和 Prettier 分工
ESLint 只承担质量审查和边界约束不承担缩进、换行、引号等格式职责。Prettier 专门负责代码风格,避免 ESLint stylistic 规则和格式化器重复工作。
备选方案是只引入 ESLint 并启用 stylistic 规则,但后续维护成本更高,且容易和编辑器格式化行为冲突。另一个备选方案是只引入 Prettier但它无法检查 React Hooks、未处理 Promise 或前端误导入后端实现等质量问题。
本次采用的最小依赖集合为 `eslint``@eslint/js``typescript-eslint``eslint-plugin-react-hooks``eslint-plugin-react-refresh``prettier`。暂不引入 `eslint-config-prettier`,除非实现阶段引入会与 Prettier 冲突的 ESLint preset 或 stylistic 规则。
### 验证命令分层
新增 `check``verify` 两层命令:
```text
check
├─ typecheck
├─ lint
├─ format:check
└─ test
verify
├─ check
├─ build
└─ test:smoke
```
`check` 面向日常开发,反馈快;`verify` 面向提交前或发布前验证,包含生产构建和 executable smoke test。备选方案是只提供 `verify`,但每次都构建 executable 会降低日常迭代速度。
### Prettier 忽略范围
Prettier SHALL 忽略 `openspec/``dist/``.build/``node_modules/``bun.lock` 和临时构建产物。`openspec/` 排除是显式决策,因为 OpenSpec tasks 要求一行一个任务Markdown 自动折行可能破坏审阅体验和规则遵循。
### 开发期端口配置
文档化的全栈开发命令以 `PORT` 作为后端端口的唯一对外配置。Vite proxy 使用的 `BACKEND_PORT` 应由开发脚本从 `PORT` 派生,或者明确作为内部变量,避免用户只改 `BACKEND_PORT` 导致 proxy 与 server 分叉。直接运行 Bun server 或生产 executable 时仍可继续使用现有 CLI 参数覆盖 host 和 port。
### 运行配置校验
运行配置继续保持 CLI 参数优先于环境变量,缺省时使用 README 文档化默认值。端口配置必须拒绝非整数、小于 0 或大于 65535 的值,并通过单元测试覆盖默认值、优先级、非法输入和边界值,避免开发期和生产期配置行为分叉。
### HTTP method 和错误契约
现有 demo 端点按路径匹配,后续业务扩展前需要先固化 method 语义。`/health``/api/demo``GET` 为主,并支持 `HEAD` 返回相同状态和 headers 但无响应体;不支持的 method 返回 JSON 405并带 `Allow` header。未知 `/api/*` 继续返回 JSON 404不能落入前端 HTML fallback。
### 生产响应头策略
生产 HTML 使用 `Cache-Control: no-cache`Vite hash 静态资源使用长缓存 `public, max-age=31536000, immutable`。所有生产 HTTP 响应增加低风险安全头,例如 `X-Content-Type-Options: nosniff``Referrer-Policy`。CSP 暂不纳入本次变更,避免后续业务页面接入外部资源时产生过早约束。
### 构建确定性
生成 `.build/static-assets.ts` 时,嵌入资源列表应按稳定顺序输出。这样可以减少重复构建时的无意义差异,也方便 smoke test 和后续审查定位问题。
### Smoke test 增强
`test:smoke` SHALL 针对当前构建出的 executable 验证生产行为,包括 `/health``/api/demo`、未知 API、根 HTML、SPA fallback、静态资源、未知静态资源、生产 runtime mode、缓存头和低风险安全头。`verify` 必须先执行 build 再 smoke避免验证旧产物。
## Risks / Trade-offs
- 新增 ESLint 和 Prettier 会增加开发依赖与初次配置成本 → 采用最小依赖集合,只启用与当前项目直接相关的规则。
- 现有代码可能被 Prettier 产生格式化改动 → 本次作为平台硬化变更集中处理,后续业务变更减少格式噪音。
- 405 和 HEAD 行为会让 HTTP handler 稍复杂 → 在业务 API 扩展前处理,避免未来每个端点重复补语义。
- 安全头不包含 CSP安全强度有限 → 先采用低风险头CSP 在前端资源来源稳定后单独设计。
- `verify` 包含构建和 smoke运行更慢 → 保留快速 `check` 作为日常反馈通道。

View File

@@ -0,0 +1,35 @@
## Why
当前项目已经具备 Bun 后端、Vite React 前端、生产静态资源嵌入和单 executable 打包链路,但仍处于 demo 基础设施阶段。真实业务开发开始前,需要先收紧前后端开发、运行时 HTTP 契约、代码质量门禁和生产验证闭环,避免后续业务变更建立在不稳定或不可重复验证的基础上。
## What Changes
- 增加 ESLint 作为代码质量、React Hooks 和前后端边界审查工具。
- 增加 Prettier 作为代码风格格式化工具,并排除 `openspec/`、构建产物和依赖目录。
- 增加快速 `check` 命令和完整 `verify` 命令,其中 `verify` SHALL 覆盖类型检查、lint、格式检查、单元测试、生产构建和 executable smoke test。
- 明确开发期 Bun server 与 Vite proxy 的端口配置一致性,避免前端代理端口和后端监听端口分叉。
- 补充运行配置校验要求包括默认值、CLI 与环境变量优先级、无效端口拒绝和端口边界行为。
- 强化 HTTP 运行时契约,包括 method 语义、JSON 404/405 错误、静态资源缓存策略和低风险安全响应头。
- 强化单 executable 构建验证,包括确定性资源生成、生产模式验证、静态资源响应头、未知 API、未知 asset 和 SPA fallback 检查。
- 修正 OpenSpec `tasks` artifact 规则键名,避免 CLI 状态命令产生无效规则警告。
- 同步更新 README说明质量门禁、验证命令、构建中间产物和运行配置边界。
## Capabilities
### New Capabilities
- `code-quality-gates`: 定义 ESLint、Prettier、`check``verify` 的质量门禁行为要求。
### Modified Capabilities
- `fullstack-app-runtime`: 补充运行配置校验、HTTP method、JSON 错误、静态资源缓存和低风险安全响应头等运行时契约。
- `frontend-development-workflow`: 补充开发期 Bun server 与 Vite proxy 配置一致性的要求。
- `single-executable-packaging`: 补充确定性构建、完整验证命令和 smoke 覆盖增强要求。
## Impact
- 影响 `package.json` scripts 和开发依赖,新增 lint、format、check、verify 相关命令。
- 影响 ESLint、Prettier 配置文件和忽略规则。
- 影响 `src/server/*` 的 HTTP method、错误响应、静态资源响应头和配置处理。
- 影响 `scripts/build.ts``scripts/dev.ts``scripts/smoke.ts` 的构建、开发联调和验证逻辑。
- 影响 `tests/`需要补充配置解析、HTTP 语义、静态资源响应和验证行为相关测试。
- 影响 `openspec/config.yaml`,修正 `tasks` artifact 规则键名。
- 影响 `README.md`,需要同步开发命令、验证命令、构建流程和边界说明。

View File

@@ -0,0 +1,53 @@
## ADDED 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

@@ -0,0 +1,23 @@
## ADDED Requirements
### 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: 开发质量命令文档化
项目 SHALL 在前端开发工作流文档中说明日常检查和完整验证命令。
#### Scenario: 查阅开发命令
- **WHEN** 开发者阅读 README 的开发或测试章节
- **THEN** 文档 SHALL 说明 `check` 用于日常开发检查,`verify` 用于提交前或发布前完整验证

View File

@@ -0,0 +1,76 @@
## ADDED Requirements
### 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 错误响应一致性
系统 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: 生产缓存策略
系统 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

View File

@@ -0,0 +1,33 @@
## ADDED Requirements
### Requirement: 构建生成确定性
生产构建 SHALL 以稳定顺序生成嵌入静态资源清单,减少重复构建产生无意义差异。
#### Scenario: 生成静态资源清单
- **WHEN** 生产构建扫描 Vite 输出目录并生成嵌入资源模块
- **THEN** 资源条目 SHALL 按稳定顺序输出
#### Scenario: 重复构建相同前端产物
- **WHEN** Vite 输出内容未变化且生产构建重复运行
- **THEN** 生成的嵌入资源模块 SHALL 保持语义一致且不依赖文件系统遍历顺序
## MODIFIED Requirements
### Requirement: 构建验证
项目 SHALL 提供验证,证明生产 executable 可以服务 API、健康检查、静态资源和 SPA fallback 路由,并且完整验证 MUST 针对当前源码重新构建后的 executable 运行。
#### Scenario: 验证 executable 路由
- **WHEN** 构建验证针对生成的 executable 运行
- **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** 任一代表性生产路由、响应头、生产模式或构建阶段检查失败
- **THEN** 验证 SHALL 使构建或测试命令失败

View File

@@ -0,0 +1,34 @@
## 1. 质量门禁配置
- [x] 1.1 添加 `eslint``@eslint/js``typescript-eslint``eslint-plugin-react-hooks``eslint-plugin-react-refresh``prettier` 开发依赖并更新 lockfile
- [x] 1.2 在 `package.json` 新增 `lint``format``format:check``check``verify` 脚本
- [x] 1.3 配置 ESLint 检查 TypeScript、React、脚本和测试代码并启用 React Hooks 规则
- [x] 1.4 配置 ESLint 禁止 `src/web` 导入 `src/server` 后端运行时实现
- [x] 1.5 配置 Prettier 和忽略规则,确保排除 `openspec/``dist/``.build/``node_modules/``bun.lock` 和临时构建产物
## 2. 开发期配置一致性
- [x] 2.1 调整全栈开发脚本,使 Vite proxy 端口从文档化的后端端口配置派生
- [x] 2.2 调整或确认运行配置校验覆盖默认值、CLI 优先级、无效端口和端口边界行为
- [x] 2.3 补充运行配置测试,覆盖默认端口、`PORT` 覆盖、CLI 优先级、无效端口和端口边界
## 3. HTTP 运行时契约
- [x] 3.1 为 `/health``/api/demo` 实现 `GET``HEAD` 语义,并对不支持 method 返回 JSON 405 和 `Allow` header
- [x] 3.2 统一 API 404 和 405 错误响应结构,确保包含 `error``status` 字段
- [x] 3.3 为生产 HTML、JSON 和静态资源响应添加低风险安全 headers
- [x] 3.4 明确生产 HTML、静态资源和未知静态资源的缓存与 404 行为
- [x] 3.5 补充 HTTP handler 单元测试,覆盖 method、HEAD、JSON 错误、缓存 headers、安全 headers 和未知静态资源
## 4. 构建与 Smoke 验证
- [x] 4.1 调整生产构建脚本,按稳定顺序生成嵌入静态资源清单
- [x] 4.2 增强 executable smoke test验证 production runtime mode、未知 API、未知静态资源、SPA fallback、缓存 headers 和低风险安全 headers
- [x] 4.3 确保 `verify` 先运行 `check`,再基于当前源码执行生产构建和 smoke test
## 5. 文档与最终验证
- [x] 5.1 更新 README说明 `check``verify`、lint、format、构建中间产物、运行配置和验证边界
- [x] 5.2 运行 `bun run check` 并修复发现的问题
- [x] 5.3 运行 `bun run verify` 并修复发现的问题
- [x] 5.4 修正 `openspec/config.yaml``tasks` artifact 规则键名并确认 OpenSpec CLI 不再告警