1
0
Files
DiAL/openspec/changes/archive/2026-05-09-harden-fullstack-packaging-foundation/design.md

91 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 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` 作为日常反馈通道。