Files

101 lines
6.6 KiB
Markdown
Raw Permalink 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.
# 应用工程脚手架基线设计
- 功能编号:GOV-009
- 设计版本:0.1
- 状态:review
- 日期:2026-08-13
## 总体结构
```text
repository
├── web/ Vue 3 独立前端工程
│ ├── src/api/generated/ OpenAPI 生成的类型与客户端
│ ├── src/api/adapters/ DTO 到页面模型的转换
│ ├── src/app/ 路由、状态和应用外壳
│ └── tests/ 组件与浏览器测试
├── server/ NestJS 独立后端工程
│ ├── apps/api/ HTTP 与 OpenAPI 入口
│ ├── apps/scheduler/ 定时触发入口
│ ├── apps/worker/ 任务执行入口
│ └── libs/
│ ├── config/ 进程级配置解析与脱敏
│ ├── http-contracts/ DTO 与 OpenAPI 模型
│ ├── message-contracts/ Server 内部 RocketMQ 事件
│ ├── domain/ 后端业务模型与端口
│ └── infrastructure/ Redis、MySQL、消息适配器
├── deploy/ 环境和部署契约
└── tools/ 治理、Schema 与生成校验
```
根目录只负责编排命令和版本约束,不承载业务运行代码。Web 与 Server 各自拥有依赖、TypeScript 配置和构建产物,可以独立部署;pnpm workspace 只用于一致安装和根命令调度。
## 契约方向
```text
Server DTO + Controller metadata
│
▼
openapi.json
│
▼
Web generated client ──> Web adapter ──> Page model
Scheduler ──> Server message contract ──> Worker
```
HTTP 契约由 Server 单向发布,Web 不导入任何 Server TypeScript 源码。生成客户端只负责传输类型和请求,页面通过 adapter 转换为适合展示的模型,避免后端字段调整直接渗透整个界面。
Server 使用 `@nestjs/swagger` 从 DTO 和 Controller 元数据生成 `openapi.json`;Web 使用 `openapi-typescript` 生成类型,并由 `openapi-fetch` 提供轻量请求客户端。生成过程固定输入与输出路径,检查命令重新生成后要求 Git 无差异,从而发现契约漂移。
RocketMQ 消息契约属于 Server 的进程间协议,只由 Scheduler 与 Worker 使用。数据库实体不会作为 HTTP DTO 或消息载荷直接暴露,避免持久化结构成为跨边界契约。
## Server 进程边界
- API 读取 API、Redis、MySQL 和可选 AI 配置,提供 HTTP 与 OpenAPI。
- Scheduler 读取调度、Redis 和可选 RocketMQ 发送配置,只负责触发任务。
- Worker 读取数据源、Redis、MySQL、可选 RocketMQ 消费和可选 AI 配置,负责执行任务。
- 三个入口复用配置解析和基础设施 adapter,但分别建立 Nest 应用上下文,互不隐式启动。
初始版本的 RocketMQ adapter 只定义接口和明确的 disabled 行为。项目不会选择名称可疑、维护状态不明或不兼容 RocketMQ 5.x Proxy 的 npm 包;真实收发将在客户端验证功能中通过测试 Topic 完成后启用。
## 配置加载
本地启动固定读取 `deploy/env/development/<process>.env.local`;生产运行只依靠 systemd `EnvironmentFile` 注入,不从源码目录寻找生产 env。配置解析采用白名单 Schema,未知键可以保留给其他进程,但当前进程只解析最小集合。
敏感值只用于建立连接,错误对象和日志使用键名而不输出实际值。Web 构建只加载 `web.env.local` 中的 `VITE_` 变量。
## 数据库基线
Schema 工具优先读取 `api.env.local`,不存在时才退回 `api.env.example`。开发数据库主机允许回环地址和代码内固定白名单 `112.192.20.11`,不能由命令行临时追加。其余环境、库名、版本、字符集和排序规则继续严格校验。
当前远程开发库为空。空库仍然是“已启用且已检查”的事实,不应标记为 MySQL 未启用。生成器将保存 format v2 的 `captured_empty` 结构化清单,其中 `object_counts` 全部为零、客户端和服务端版本真实可验证,并对规范化的空结构计算确定性摘要;不创建空 `schema.sql`。验证器继续只读兼容既有 format v1 清单,禁止借格式升级重写历史目录。首次迁移产生对象后,下一发布版本开始生成完整 captured 基线。
Server 数据访问使用 Nest 官方 `@nestjs/typeorm` 集成、TypeORM 和 `mysql2` 驱动。迁移是结构变更的唯一入口,应用启动禁止 `synchronize: true`;Repository 只能通过领域端口进入业务逻辑,不能把 TypeORM 实体直接暴露为 HTTP 或消息契约。
## 错误处理
- Node/pnpm 版本错误在安装或根校验命令开始时失败。
- 必填配置缺失、MySQL 版本错误或字符规则错误时,相应 Server 进程拒绝启动。
- Redis/MySQL 健康检查失败返回不可用状态,但不泄漏目标密码。
- RocketMQ 关闭时报告 disabled;打开但无已验证 adapter 时启动失败,禁止静默退回内存队列。
- OpenAPI 生成文件与 Server 定义不一致时 CI/本地检查失败。
## 测试策略
- 配置 Schema、消息信封、Schema 主机白名单和空库产物使用 Node/Vitest 单元测试。
- API 使用 Nest 测试工具验证健康检查和 OpenAPI。
- Web 使用 Vitest 验证启动外壳和生成客户端边界。
- Playwright 验证 Web 能启动、路由可访问且无阻断错误;GOV-009 不进行业务页面视觉设计。
- 使用真实 Redis 和固定开发 MySQL 执行只读冒烟;RocketMQ 只验证禁用态和既有管理链路,不宣称 Node 消息收发通过。
- Web 与三个 Server 入口执行真实构建验证;源码发布门禁同时核对 systemd 和 Nginx 模板。
- E2E 在启动 API 前只读检查现有本机 Redis;不可达时明确失败,不启动替代基础设施。
## 回退原则
GOV-009 不迁移业务数据。回退时恢复上一 Git 标签即可移除脚手架;本地 `*.env.local` 和基础设施数据不随 Git 回退。若 Schema 工具变化失败,恢复旧工具后仍保留已发布基线,禁止改写历史目录。
## 实施后架构论证门禁
本文档描述的是实施前目标架构。完成代码、测试、构建和 Review 后,必须根据 GitNexus 实际依赖图、Web/Server 目录、三个 Server 进程、OpenAPI 生成链路和源码部署产物另写 `architecture-review.md`。复核需要说明实际实现与目标的偏差、当前选择优于替代方案的理由、何时应拆分或调整。用户再次确认前不发布 `v0.0.8`,也不把本功能视为彻底完成。