fix(docs): 修复 project_rules.md P0 损坏并同步所有引用

- 根目录 project_rules.md 损坏(72 字节乱码),已删除
- 从 CICD 项目迁移完整版至 .trae/rules/project_rules.md(17881 字节)
- 更新 MIGRATION_GUIDE/README/coding-standards 引用至 .trae/rules/
- P0 紧急修复,影响所有 AI 工作流程
This commit is contained in:
SpecialX
2026-07-08 12:50:00 +08:00
parent 4629de1926
commit 3fbb97791d
5 changed files with 644 additions and 242 deletions

View File

@@ -0,0 +1,372 @@
# Edu 项目规则(微服务版)
> 版本1.0
> 日期2026-07-08
> 适用范围Edu 微服务架构DDD + EDA + CQRS多语言 monorepo
> 关联文档:
>
> - [004 架构影响地图](../../docs/architecture/004_architecture_impact_map.md)
> - [理想蓝图 0010](../../docs/architecture/0010_architecture.md)
> - [迁移指南](../../MIGRATION_GUIDE.md)
> - [known-issues 速查](../../docs/troubleshooting/known-issues.md)
---
## 1. 架构图优先规则
**任何任务开始前,必须先查阅架构影响地图,通过图定位代码和模块。**
1. **先图后码**:执行任何分析、修改、搜索任务时,首先运行 `pnpm run arch:scan` 更新 arch.db再通过 `pnpm run arch:query` 查询目标模块、函数、依赖关系,结合阅读 `docs/architecture/004_architecture_impact_map.md` 定位架构设计意图,最后按图索骥读取源码
2. **图未覆盖则先补图**:如果发现项目中存在 arch.db 未记录的模块、函数、表、路由、proto 等结构,**必须先运行 `pnpm run arch:scan` 重新扫描**多语言扫描器TS + Go + Python + Proto然后检查 004 是否需要补充
3. **改码必同步图**:对源码的任何修改完成后,必须运行 `pnpm run arch:scan` 更新 arch.db若架构设计意图有变化同步更新 004
### 架构文档清单
| 文档 | 用途 |
| -------------------------------------------------- | -------------------------------------------------------- |
| `docs/architecture/004_architecture_impact_map.md` | 架构设计意图唯一源(人类可读) |
| `docs/architecture/0010_architecture.md` | 理想蓝图(目标态) |
| `docs/architecture/roadmap/` | 长远规划tech-debt / pending-features |
| `docs/architecture/runbooks/` | 运维手册P6 硬化、post-p6-followup、incident-response |
| `docs/troubleshooting/known-issues.md` | 已知问题速查(场景→技术映射 + 工作经验日志) |
### 需要同步图的场景
- 新增/删除/重命名导出函数、组件、Hook、类型
- 修改函数签名(参数、返回类型)
- 修改权限点Permissions 常量)或角色-权限映射
- 新增/删除数据库表
- 新增/删除路由页面、API 路由、gRPC 服务、proto message
- 修改模块间依赖关系或服务间调用关系
- 新增服务、新增模块、新增 proto 定义
- 修改 Kafka topic、Outbox 事件命名
### 同步方式
- 修改源码后运行 `pnpm run arch:scan` 更新 arch.db强制
- 若架构设计意图变化,同步更新 `docs/architecture/004_architecture_impact_map.md`
- 若发现新的"场景→技术"映射或工作经验,更新 `docs/troubleshooting/known-issues.md`
---
## 2. 架构元数据库规则arch.db
**arch.db 是代码结构唯一源AI 工作前必须运行 `pnpm run arch:scan` 更新。**
1. **多语言扫描**arch.db 覆盖 TypeScriptts-morph、Gotree-sitter-go、Pythontree-sitter-python、Protobuf AST四类语言
2. **查询命令**
- `pnpm run arch:query -- sql "<SQL>"` 自定义 SQL 查询
- `pnpm run arch:query -- module-deps` 查模块依赖
- `pnpm run arch:query -- module-reverse-deps <module>` 查反向依赖
- `pnpm run arch:query -- symbol-refs <symbol>` 查符号引用链
- `pnpm run arch:query -- tech-usage <tag>` 查技术使用
- `pnpm run arch:query -- violations` 查架构违规
- `pnpm run arch:query -- stats` 查总体统计
- `pnpm run arch:query -- modules` 查模块列表
3. **arch.db 不替代 004**arch.db 是"代码现状"004 是"设计意图",两者互补
4. **预期规模**:模块数 ≥ 10api-gateway、push-gateway、teacher-bff、iam、classes、core-edu、content、msg、data-ana、ai符号数 ≥ 100
---
## 3. 编码规范
详细规范见 `docs/standards/coding-standards.md`,以下为核心强制规则。
### 3.1 代码质量规则
- 每次修改后运行 `pnpm run lint``pnpm run typecheck` 确保零错误
- TypeScript 服务必须用 `@RequirePermission()` 装饰器进行权限校验
- 前端组件禁止使用 `role === "xxx"` 硬编码,统一使用 `usePermission().hasPermission()`
- 单文件行数遵循企业级规范:
- 配置文件、常量文件、类型定义文件、proto无限制
- Controller / Service建议 ≤ 500 行
- Repository / data-access建议 ≤ 800 行
- 工具函数:建议 ≤ 40 行
- 自定义 Hook建议 ≤ 80 行
- 硬性上限:任何文件不超过 1000 行,超过必须拆分
### 3.2 架构分层规则(微服务)
- **四层分层**Gateway → BFF → Services → Data
- **依赖方向单向**Gateway → BFF → Services → Data禁止反向依赖
- **服务间通信**:通过 protobuf gRPC 或 Kafka 事件,**禁止直接访问对方 DB**
- **Gateway 职责**JWT 校验、限流、熔断、CORS、请求 ID 注入
- **BFF 职责**:聚合多个 Service 的数据,为前端提供场景化 API
- **Service 职责**:业务逻辑,每服务独占 DBDDD 限界上下文)
### 3.3 模块标准结构DDD
```
services/[service]/src/
├─ [domain]/ # 限界上下文
│ ├─ *.controller.ts # ControllerHTTP/gRPC 入口)
│ ├─ *.service.ts # Application Service编排层
│ ├─ *.repository.ts # Repository数据访问
│ ├─ *.schema.ts # Zod 验证
│ └─ *.dto.ts # DTO
├─ config/ # 配置database / env / kafka / neo4j / elasticsearch
├─ middleware/ # 中间件auth.middleware / permission.guard
├─ shared/ # 共享
│ ├─ errors/ # 错误application-error / global-error.filter
│ ├─ health/ # 健康检查
│ ├─ lifecycle/ # 生命周期
│ ├─ observability/ # 可观测性logger / metrics / tracer
│ └─ outbox/ # Outbox仅事件驱动服务
├─ app.module.ts # 根模块
└─ main.ts # 入口
```
### 3.4 TypeScript 规则
- **禁止 `any`**:未知类型用 `unknown` 并做类型守卫
- **禁止 `as` 断言**(除非从 `unknown` 转换或测试中,需注释原因)
- **函数返回值必须显式标注**,特别是 `Promise<T>`
- **仅用于类型的导入必须使用 `import type`**
- **可选链后禁止跟非空断言 `!`**
- **ESM 模式**NestJS ESM 模式下,相对 import 的 `.js` 后缀(构建产物)
### 3.5 Go 规则
- 包名小写单词,不使用下划线或驼峰
- 导出函数必须有 doc comment`// FuncName ...`
- 错误处理:`if err != nil { return err }`,禁止 `_ = err`
- 不使用 `interface{}`,用 `any`Go 1.18+
- 包内文件命名 lowercase不使用下划线`_test.go`
- 中间件位于 `internal/middleware/`,路由位于 `internal/routing/`
### 3.6 Python 规则
- 类型注解强制(所有函数签名、变量声明)
- FastAPI 路由用 `APIRouter`
- 异步优先:`async def`IO 密集场景禁止同步阻塞调用
- 模块名 snake_case类名 PascalCase
- 配置统一通过 `pydantic-settings` 管理(`config.py`
### 3.7 命名规范(多语言)
| 对象 | 规范 | 示例 |
| ----------- | -------------------------------------------------- | ------------------------------------------------ |
| 目录 | kebab-case | `api-gateway/``core-edu/` |
| TS 组件 | PascalCase | `UserController.ts` |
| TS Hook | camelCase | `useAuth.ts` |
| Go 文件 | lowercase | `circuitbreaker.go` |
| Python 文件 | snake_case | `clickhouse_client.py` |
| Proto 文件 | snake_case | `core_edu.proto` |
| 变量/函数 | camelCaseTS/ lowercaseGo/ snake_casePy | `getUserById` / `getUserById` / `get_user_by_id` |
| 常量 | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` |
| 类/接口 | PascalCase接口不加 `I` 前缀 | `UserService` |
| 布尔值 | `is/has/can/should` 前缀 | `isActive``hasPermission` |
### 3.8 Controller / Server Action 规范
- 每个 Controller 方法必须用 `@RequirePermission()` 装饰器声明权限
- 输入用 Zod / class-validator 验证,验证失败返回结构化错误
- 返回 protobuf message 或 DTO结构同 ActionState
- 错误统一走 `GlobalErrorFilter`
- BFF Controller 聚合多个 Service 调用,禁止直接访问 DB
### 3.9 Tailwind 规范
- 使用 `cn()` 工具函数管理条件类名
- **禁止**字符串拼接动态类名(`bg-${color}-500`
- **禁止**使用任意值(`w-[137px]`),除非有充分理由并注释
- 设计令牌在 `packages/shared-tokens/`(待建立)或 `apps/teacher-portal/src/app/styles/tokens/`
### 3.10 设计令牌规范(强制)
- **禁止硬编码颜色**TSX/TS/CSS 中不得出现 `#hex` 颜色字面量,统一使用 `hsl(var(--*))` 或 Tailwind 类 `bg-*`
- **禁止硬编码字体**:不得出现 `'Inter'`/`'Fraunces'`/`'JetBrains Mono'` 字面量,使用 `var(--font-family-sans/serif/mono)`
- **禁止硬编码字号**:不得出现 `font-size: Npx`,使用 `var(--font-size-1~9)`
- **禁止 Tailwind 任意值**:不得使用 `w-[Npx]`/`h-[Npx]`/`p-[Npx]` 等,映射到 `--space-*` 或 Tailwind 默认阶梯
- **三层令牌**
- Layer 1 Primitive原始色板/字号/间距/阴影,业务代码不直接引用
- Layer 2 Semantic语义令牌light/dark业务代码唯一引用入口
- Layer 3 Tailwind Theme`@theme inline` 将 Semantic 令牌暴露为 `bg-*`/`text-*`/`font-*`
- **改令牌必同步图**:修改令牌定义后,同步更新 004 与 arch.db
- **ESLint 强制约束**
- `no-restricted-syntax`:禁止 `#hex` 字面量
- `design-tokens/no-hardcoded-fonts`:禁止 `'Inter'`/`'Fraunces'` 字面量
- 白名单:`primitive.css``email-channel``manifest.ts`
---
## 4. 安全规范
- **JWT RS256**IAM 签发Gateway 公钥校验(不共享密钥)
- **Cookie**`httpOnly + Secure + SameSite=Strict`
- **环境变量**:服务端变量不加 `NEXT_PUBLIC_` 前缀;前端变量必须加
- **环境校验**:用 `@t3-oss/env-nextjs` + Zod 或 `pydantic-settings` 校验
- **禁止 `dangerouslySetInnerHTML`**(如必须使用,先用 DOMPurify 清洗)
- **密码哈希**bcryptcost ≥ 12禁止 MD5/SHA1
- **限流**Gateway 层 IP 级令牌桶,登录接口额外加用户级限流
- **CORS**:白名单域名,禁止 `*`
- **WAF**:见 `infra/security/waf-rules.conf`
---
## 5. 契约规范
- **契约先行**:服务间通信先定 `.proto`,再写实现
- **工具链**protobuf + buf v2
- **buf lint**`STANDARD` 规则集
- **buf breaking**`FILE` 级别检查CI 强制)
- **proto 文件位置**`packages/shared-proto/proto/`
- **包名规范**`edu.<domain>.v1`(如 `edu.iam.v1``edu.core_edu.v1`
- **生成代码**`buf generate`TS 走 `buf.gen.yaml`Go/Python 各自配置)
- **gRPC 服务端口**:每服务独立端口,见 004 服务清单
---
## 6. 事件驱动规范
- **Outbox 模式**:事务内写业务表 + outbox 表,独立 publisher 投递到 Kafka保证 at-least-once
- **事件命名**`<Aggregate>.<Action>`(如 `ExamCreated``HomeworkSubmitted``GradeReleased`
- **TOPIC_MAP 路由**:每个服务维护 `事件 → topic` 映射(见 `shared/outbox/`
- **幂等性**
- Kafka producer`idempotent=true` + `transactionalId`
- Consumer基于 `event_id` 去重Redis SETNX 或 DB 唯一索引)
- **CDC**MySQL → Debezium → Kafka可选用于读模型同步
- **事件版本**schema 演化用 `v1`/`v2` 后缀,禁止破坏性变更
---
## 7. 提交规范
- 使用 Conventional Commits 格式:`feat(scope): description`
- **类型**`feat``fix``chore``docs``style``refactor``test``perf``ci`
- **scope**(服务名或包名):
- 服务:`iam``classes``core-edu``content``msg``ai``data-ana``api-gateway``push-gateway``teacher-bff`
- 包:`shared-proto``shared-ts``shared-go``shared-py``shared-tokens`
- 基础设施:`infra``k8s``helm``ci`
- 文档:`docs`
- **提交前必须运行**`pnpm run lint` + `pnpm run typecheck`TS`go vet ./...`Go`ruff check src/`Python
- **commitlint + husky**:强制校验(见 `.commitlintrc.js``.husky/commit-msg`
---
## 8. Git 工作流
- **分支策略**trunk-based直接提交 main 分支,小项目)
- **大型团队**feature branch + PRPR 至少 1 人 review
- **pre-commit hook**`lint-staged` 自动修复 + 校验(见 `lint-staged.config.js`
- **commit-msg hook**commitlint 校验格式
- **禁止 force push**:除非显式要求并通知团队
---
## 9. 问题记录规则
**所有工作完成后,必须将遇到的问题记录到 `docs/troubleshooting/known-issues.md`(索引式速查手册)。**
### 必须记录的场景
| 场景 | 记录要求 |
| -------------------------------------------------- | --------------------------------- |
| 构建报错dev/build/lint/tsc/go vet/ruff | 记录到"全局经验"对应主题分区 |
| 运行时异常(白屏/API 报错/数据加载失败/gRPC 错误) | 记录到"模块经验"对应模块分区 |
| 框架/库版本兼容问题 | 记录到"全局经验: 框架与运行时" |
| 依赖配置问题go mod / uv / pnpm workspace | 记录到"全局经验: 依赖管理" |
| 架构约束违规(跨服务访问 DB / 缺契约) | 记录到"全局经验: 架构约束" |
| 多语言 monorepo 问题(共享包链接失败等) | 记录到"全局经验: 多语言 monorepo" |
### 记录格式
索引式表格,指明"场景→技术/规则"映射,不写多行代码示例:
```markdown
### X.X 主题分区
| 场景 | 技术/规则 |
| -------- | ------------------ |
| 简述场景 | 正确做法(一句话) |
```
### 记录要求
- **索引式**:场景→技术/规则映射,不写代码示例和错误示范列
- **去重**:同类问题在原条目补充,不重复创建
- **引用架构规则**:架构分层、模块结构等规则引用 004 和本规则文件,不重复
- **工作经验日志**:在"工作经验日志"区按时间倒序追加50 条上限),记录"做了什么/学到什么/下次注意"
---
## 10. AI 工作强制流程
**所有 AI 工作必须遵循此流程,违反即违规。**
### 阶段 1上下文加载
1. `pnpm run arch:scan` 更新 arch.db
2. `pnpm run arch:query -- module-deps` 查目标模块依赖
3. `pnpm run arch:query -- symbol-refs <目标函数>` 查调用链
4. 阅读 `services/[service]/README.md` 读模块工作流程
5.`docs/troubleshooting/known-issues.md` "模块经验"分区读相关经验
6.`docs/architecture/004_architecture_impact_map.md` 对应章节
### 阶段 2执行工作
1. 按规划执行(契约先行:先 proto再实现
2. 修改代码后立即运行 `pnpm run arch:scan` 更新 arch.db
3. 运行质量校验确保零错误:
- TS`pnpm run lint` + `pnpm run typecheck`
- Go`go vet ./...` + `go build ./...`
- Python`ruff check src/`
### 阶段 3经验沉淀强制不可跳过
1.`docs/troubleshooting/known-issues.md` "工作经验日志"区追加一条记录:
- 日期 + 时间
- 模块
- 做了什么 + 学到什么
2. 若发现新的"场景→技术"映射 → 提炼到对应模块分区
3. 若发现新的架构决策 → 更新 004
4. 若代码结构变化 → `pnpm run arch:scan` 确认 arch.db 已更新
---
## 11. 多语言 monorepo 规则
- **包管理器分工**
- TypeScriptpnpm workspace`pnpm-workspace.yaml`
- Gogo.work`go.work`
- Pythonuv workspace`pyproject.toml``[tool.uv.workspace]`
- **共享包**`packages/`
- `shared-proto`protobuf 契约定义(跨语言共享)
- `shared-ts`TypeScript 共享类型与工具(待建立)
- `shared-go`Go 共享工具(待建立)
- `shared-py`Python 共享工具(待建立)
- `shared-tokens`:设计令牌(待建立)
- **跨语言契约**:通过 protobuf禁止 JSON Schema 或 OpenAPI 作为内部契约
- **依赖版本对齐**:共享依赖(如 uuid、jwt在多语言版本号保持一致
---
## 12. 可观测性规范
- **三支柱必须同时启用**(所有服务):
- **日志**pinoTS/ zapGo/ structlogPython—— 结构化 JSON
- **指标**prom-clientTS/ prometheusGo/ prometheus-clientPython—— `/metrics` 端点
- **链路**OpenTelemetry SDK + OTLP exporter —— 统一 traceparent
- **健康检查**`/health`liveness+ `/ready`readiness见各服务 `shared/health/`
- **请求 ID**Gateway 注入 `X-Request-Id`全链路传递日志、metrics、trace
- **指标命名**`<service>_<module>_<operation>_<unit>`(如 `iam_login_duration_seconds`
- **告警规则**:见 `infra/prometheus/rules.yml` + `infra/alertmanager/alertmanager.yml`
- **Grafana 面板**:见 `infra/grafana/dashboards/`
---
## 13. 部署与基础设施规范
- **容器化**:每服务独立 Dockerfile`services/[service]/Dockerfile`
- **K8s**:基础设施 manifest 位于 `infra/k8s/`,演化目标为 Helm chart`infra/k8s/helm/`
- **命名空间**`edu-system``edu-monitoring``edu-chaos``edu-backup`
- **配置分离**
- ConfigMap非敏感配置环境变量、特性开关
- Secret敏感配置DB 密码、JWT 密钥、API key—— 见 `infra/security/secrets.example.env`
- **备份**:见 `infra/backup/backup-mysql.sh`,每服务独立备份,保留 7 天
- **监控栈**Prometheus + Grafana + Alertmanager`infra/docker-compose.monitoring.yml`
- **混沌工程**:见 `infra/chaos/experiments.yaml`
---
**本规则文件是项目的强制约束,所有 contributor含 AI必须遵守。规则变更需同步更新 004 与 arch.db。**

View File

@@ -5,7 +5,8 @@
> 状态:基线发布
> 维护者:架构组
> 关联文档:
> - [项目规则](./project_rules.md)
>
> - [项目规则](./.trae/rules/project_rules.md)
> - [编码规范](./docs/standards/coding-standards.md)
> - [Git 工作流](./docs/standards/git-workflow.md)
@@ -30,13 +31,13 @@
原始项目 CICD 是基于 Next.js 16 的单应用架构,承载 K12 智慧教务系统 35 个业务模块。随着业务规模扩张与团队增长,单应用架构在以下方面暴露瓶颈:
| 维度 | 单应用瓶颈 | 微服务目标 |
|------|-----------|-----------|
| 团队协作 | 35 模块挤在同一仓库,合并冲突频繁 | 按领域拆分6 领域团队独立迭代 |
| 部署节奏 | 全量构建发布,单模块变更牵动全站 | 服务粒度独立部署,故障爆炸半径缩小 |
| 维度 | 单应用瓶颈 | 微服务目标 |
| -------- | ---------------------------------- | ------------------------------------------------- |
| 团队协作 | 35 模块挤在同一仓库,合并冲突频繁 | 按领域拆分6 领域团队独立迭代 |
| 部署节奏 | 全量构建发布,单模块变更牵动全站 | 服务粒度独立部署,故障爆炸半径缩小 |
| 技术选型 | TypeScript 单语言AI/分析场景受限 | TS业务+ Go网关+ PythonAI/分析)各取所长 |
| 数据规模 | 单 MySQL跨模块联表与读放大 | 读写分离 + CQRSClickHouse 承载分析负载 |
| 可演进性 | 模块间隐式耦合,重构成本高 | DDD 限界上下文显式契约,演化可控 |
| 数据规模 | 单 MySQL跨模块联表与读放大 | 读写分离 + CQRSClickHouse 承载分析负载 |
| 可演进性 | 模块间隐式耦合,重构成本高 | DDD 限界上下文显式契约,演化可控 |
### 1.2 迁移原则
@@ -52,29 +53,29 @@
### 2.1 基本概况
| 属性 | 值 |
|------|-----|
| 仓库路径 | `e:\Desktop\CICD` |
| 技术栈 | Next.js 16 + React 19 + Tailwind v4 + Drizzle ORM |
| 语言 | TypeScript全栈 |
| 架构 | 单应用 + 严格模块化app → modules → shared 三层) |
| 业务模块数 | 35 个 |
| 数据库 | MySQL单库 |
| 认证 | NextAuth.js |
| 部署 | Gitea Actions + Docker standalone |
| 属性 | 值 |
| ---------- | -------------------------------------------------- |
| 仓库路径 | `e:\Desktop\CICD` |
| 技术栈 | Next.js 16 + React 19 + Tailwind v4 + Drizzle ORM |
| 语言 | TypeScript全栈 |
| 架构 | 单应用 + 严格模块化app → modules → shared 三层) |
| 业务模块数 | 35 个 |
| 数据库 | MySQL单库 |
| 认证 | NextAuth.js |
| 部署 | Gitea Actions + Docker standalone |
### 2.2 模块清单(按领域归类)
| 领域 | 模块 |
|------|------|
| 身份与权限 | auth、users、onboarding、settings、permissions |
| 教学组织 | classes、teachers、students、parents、subjects |
| 教学核心 | courses、lessons、schedule、attendance、leave-requests |
| 考试评价 | exams、questions、grading、scores、analytics |
| 作业内容 | homework、textbooks、resources |
| 沟通通知 | messaging、notifications、announcements |
| 智能辅助 | ai备课/出题/分析、search |
| 系统支撑 | audit-logs、reports、dashboard、layout |
| 领域 | 模块 |
| ---------- | ------------------------------------------------------ |
| 身份与权限 | auth、users、onboarding、settings、permissions |
| 教学组织 | classes、teachers、students、parents、subjects |
| 教学核心 | courses、lessons、schedule、attendance、leave-requests |
| 考试评价 | exams、questions、grading、scores、analytics |
| 作业内容 | homework、textbooks、resources |
| 沟通通知 | messaging、notifications、announcements |
| 智能辅助 | ai备课/出题/分析、search |
| 系统支撑 | audit-logs、reports、dashboard、layout |
### 2.3 已沉淀的工程资产
@@ -94,17 +95,17 @@
### 3.1 基本概况
| 属性 | 值 |
|------|-----|
| 仓库路径 | `e:\Desktop\Edu` |
| 远程仓库 | https://git.eazygame.cn/xiner/Edu.git |
| 架构范式 | DDD + EDA + CQRS 微服务 |
| 语言 | TypeScriptNestJS 10+ GoGin 网关)+ PythonFastAPI 分析/AI |
| 前端 | React + Next.js + Module Federation4 微前端) |
| monorepo 策略 | pnpm workspace + go.work + pyproject.toml (uv) |
| 事件总线 | Kafka + Debezium CDC |
| 契约 | protobuf + buf |
| 存储 | MySQL / Redis / ClickHouse / Neo4j / Elasticsearch |
| 属性 | 值 |
| ------------- | ------------------------------------------------------------------ |
| 仓库路径 | `e:\Desktop\Edu` |
| 远程仓库 | https://git.eazygame.cn/xiner/Edu.git |
| 架构范式 | DDD + EDA + CQRS 微服务 |
| 语言 | TypeScriptNestJS 10+ GoGin 网关)+ PythonFastAPI 分析/AI |
| 前端 | React + Next.js + Module Federation4 微前端) |
| monorepo 策略 | pnpm workspace + go.work + pyproject.toml (uv) |
| 事件总线 | Kafka + Debezium CDC |
| 契约 | protobuf + buf |
| 存储 | MySQL / Redis / ClickHouse / Neo4j / Elasticsearch |
### 3.2 整体架构
@@ -164,23 +165,23 @@ flowchart TB
### 3.3 微前端与领域服务映射
| 微前端 | 路由前缀 | 对接 BFF | 主要消费的服务 |
|--------|---------|---------|---------------|
| Admin Shell | `/admin` | Admin BFF | identity、org、insight |
| Teacher Shell | `/teacher` | Teacher BFF | teaching、content、comm |
| Student Shell | `/student` | Student/Parent BFF | teaching、content |
| Parent Shell | `/parent` | Student/Parent BFF | teaching、comm |
| 微前端 | 路由前缀 | 对接 BFF | 主要消费的服务 |
| ------------- | ---------- | ------------------ | ----------------------- |
| Admin Shell | `/admin` | Admin BFF | identity、org、insight |
| Teacher Shell | `/teacher` | Teacher BFF | teaching、content、comm |
| Student Shell | `/student` | Student/Parent BFF | teaching、content |
| Parent Shell | `/parent` | Student/Parent BFF | teaching、comm |
| 微服务 | 原始模块映射 | 主存储 | 对外契约 |
|--------|------------|--------|---------|
| identity | auth、users、onboarding、settings、permissions | MySQL + Redis | identity.proto |
| org | classes、teachers、students、parents、subjects | MySQL | org.proto |
| teaching | courses、lessons、schedule、attendance、leave-requests、exams、homework | MySQL | teaching.proto |
| content | textbooks、resources、questions、grading | MySQL + Elasticsearch | content.proto |
| comm | messaging、notifications、announcements | MySQL + Redis | comm.proto |
| insight | scores、analytics、ai、search、reports、dashboard | ClickHouse + Neo4j | insight.proto |
| auth基础设施 | NextAuth 逻辑下沉 | MySQL + Redis | auth.proto |
| notification基础设施 | notifications channel 抽离 | MySQL + Redis | notification.proto |
| 微服务 | 原始模块映射 | 主存储 | 对外契约 |
| ------------------------ | ----------------------------------------------------------------------- | --------------------- | ------------------ |
| identity | auth、users、onboarding、settings、permissions | MySQL + Redis | identity.proto |
| org | classes、teachers、students、parents、subjects | MySQL | org.proto |
| teaching | courses、lessons、schedule、attendance、leave-requests、exams、homework | MySQL | teaching.proto |
| content | textbooks、resources、questions、grading | MySQL + Elasticsearch | content.proto |
| comm | messaging、notifications、announcements | MySQL + Redis | comm.proto |
| insight | scores、analytics、ai、search、reports、dashboard | ClickHouse + Neo4j | insight.proto |
| auth基础设施 | NextAuth 逻辑下沉 | MySQL + Redis | auth.proto |
| notification基础设施 | notifications channel 抽离 | MySQL + Redis | notification.proto |
---
@@ -190,65 +191,65 @@ flowchart TB
### 4.1 规范类资产
| 资产 | 策略 | 说明 |
|------|------|------|
| 项目规则project_rules | 调整 | 架构图优先保留,分层规则从三层改为微服务分层,新增 DDD/契约/事件驱动规则 |
| 编码规范coding-standards | 调整 | TS 部分保留并补充 NestJS 装饰器/DI 规则,新增 Go、Python、protobuf 章节 |
| Git 工作流 | 调整 | trunk-based 替代分支策略scope 改为服务/包名,新增多语言 monorepo 提交规则 |
| 提交规范Conventional Commits | 直接迁移 | 类型与格式完全沿用 |
| 设计令牌规范 | 调整 | 分层模型保留,分布位置从 `src/app/styles/tokens/` 改为微前端共享包 |
| 安全规范 | 直接迁移 | Cookie 策略、env 校验、XSS 防护、权限校验规则全部沿用 |
| 问题记录规则 | 直接迁移 | known-issues.md 索引式速查手册模式沿用 |
| A11y 规范 | 直接迁移 | WCAG 2.2 AA 目标与工具集沿用 |
| 资产 | 策略 | 说明 |
| -------------------------------- | -------- | --------------------------------------------------------------------------- |
| 项目规则project_rules | 调整 | 架构图优先保留,分层规则从三层改为微服务分层,新增 DDD/契约/事件驱动规则 |
| 编码规范coding-standards | 调整 | TS 部分保留并补充 NestJS 装饰器/DI 规则,新增 Go、Python、protobuf 章节 |
| Git 工作流 | 调整 | trunk-based 替代分支策略scope 改为服务/包名,新增多语言 monorepo 提交规则 |
| 提交规范Conventional Commits | 直接迁移 | 类型与格式完全沿用 |
| 设计令牌规范 | 调整 | 分层模型保留,分布位置从 `src/app/styles/tokens/` 改为微前端共享包 |
| 安全规范 | 直接迁移 | Cookie 策略、env 校验、XSS 防护、权限校验规则全部沿用 |
| 问题记录规则 | 直接迁移 | known-issues.md 索引式速查手册模式沿用 |
| A11y 规范 | 直接迁移 | WCAG 2.2 AA 目标与工具集沿用 |
### 4.2 代码类资产
| 资产 | 策略 | 说明 |
|------|------|------|
| Zod schema 定义 | 直接迁移 | 各模块 schema.ts 平移至对应微服务,复用验证规则 |
| 权限点常量Permissions | 直接迁移 | 集中迁入 identity 服务共享包 |
| Drizzle schema表结构 | 调整 | 按领域拆分到各微服务独占库,关系型字段保持不变 |
| ActionState 类型 | 直接迁移 | 升级为 protobuf message结构不变 |
| Server Actions | 重写 | 改写为 NestJS Controller + Service + Application Service 三层 |
| data-access 层 | 重写 | 改写为 NestJS Repository + Domain Entity |
| UI 组件shared/components | 直接迁移 | 平移至微前端共享包,保持 PascalCase 命名 |
| HookuseAuth、usePermission | 调整 | 改为通过 BFF/gRPC client 获取,接口签名保持不变 |
| 缓存层cacheFn | 重写 | 改为 NestJS Cache 模块 + Redis去除 React cache() |
| arch:scan 工具 | 调整 | 扫描器扩展为多语言TS+Go+Python数据库结构保持 |
| 审计日志三件套 | 直接迁移 | 平移至 notification 服务,日志结构保持 |
| CI/CD 流水线 | 重写 | Gitea Actions 改为多服务并行流水线,新增契约校验阶段 |
| 资产 | 策略 | 说明 |
| ------------------------------ | -------- | ------------------------------------------------------------- |
| Zod schema 定义 | 直接迁移 | 各模块 schema.ts 平移至对应微服务,复用验证规则 |
| 权限点常量Permissions | 直接迁移 | 集中迁入 identity 服务共享包 |
| Drizzle schema表结构 | 调整 | 按领域拆分到各微服务独占库,关系型字段保持不变 |
| ActionState 类型 | 直接迁移 | 升级为 protobuf message结构不变 |
| Server Actions | 重写 | 改写为 NestJS Controller + Service + Application Service 三层 |
| data-access 层 | 重写 | 改写为 NestJS Repository + Domain Entity |
| UI 组件shared/components | 直接迁移 | 平移至微前端共享包,保持 PascalCase 命名 |
| HookuseAuth、usePermission | 调整 | 改为通过 BFF/gRPC client 获取,接口签名保持不变 |
| 缓存层cacheFn | 重写 | 改为 NestJS Cache 模块 + Redis去除 React cache() |
| arch:scan 工具 | 调整 | 扫描器扩展为多语言TS+Go+Python数据库结构保持 |
| 审计日志三件套 | 直接迁移 | 平移至 notification 服务,日志结构保持 |
| CI/CD 流水线 | 重写 | Gitea Actions 改为多服务并行流水线,新增契约校验阶段 |
### 4.3 文档类资产
| 资产 | 策略 | 说明 |
|------|------|------|
| 架构影响地图004 | 重写 | 从单应用模块图改为微服务限界上下文图 |
| K12 功能清单006 | 直接迁移 | 功能清单与架构无关,直接平移 |
| 差距审计报告007 | 调整 | 重新审计各微服务的功能完成度 |
| 模块角色映射008 | 直接迁移 | 角色权限矩阵不变 |
| 路线图roadmap/ | 重写 | 6 阶段微服务路线图 |
| known-issues.md | 直接迁移 | 经验日志平移,新增"微服务"分区 |
| 各模块 README | 重写 | 改为各微服务 README按 DDD 上下文描述 |
| 资产 | 策略 | 说明 |
| ------------------- | -------- | -------------------------------------- |
| 架构影响地图004 | 重写 | 从单应用模块图改为微服务限界上下文图 |
| K12 功能清单006 | 直接迁移 | 功能清单与架构无关,直接平移 |
| 差距审计报告007 | 调整 | 重新审计各微服务的功能完成度 |
| 模块角色映射008 | 直接迁移 | 角色权限矩阵不变 |
| 路线图roadmap/ | 重写 | 6 阶段微服务路线图 |
| known-issues.md | 直接迁移 | 经验日志平移,新增"微服务"分区 |
| 各模块 README | 重写 | 改为各微服务 README按 DDD 上下文描述 |
---
## 五、文档体系映射表
| CICD 文档 | Edu 对应文档 | 关系 |
|-----------|------------|------|
| `.trae/rules/project_rules.md` | `project_rules.md` | 调整(微服务版) |
| `docs/standards/coding-standards.md` | `docs/standards/coding-standards.md` | 调整(多语言版) |
| —(散落在 project_rules | `docs/standards/git-workflow.md` | 新建 |
| `docs/architecture/004_architecture_impact_map.md` | `docs/architecture/001_architecture_overview.md` | 重写 |
| `docs/architecture/006_k12_feature_checklist.md` | `docs/architecture/feature_checklist.md` | 直接迁移 |
| `docs/architecture/007_gap_audit_report.md` | `docs/architecture/gap_audit.md` | 调整 |
| `docs/architecture/008_module_role_mapping.md` | `docs/architecture/role_mapping.md` | 直接迁移 |
| `docs/architecture/roadmap/README.md` | `docs/architecture/roadmap/README.md` | 重写 |
| `docs/architecture/roadmap/tech-debt.md` | `docs/architecture/roadmap/tech-debt.md` | 重写 |
| `docs/architecture/roadmap/decoupling.md` | `docs/architecture/roadmap/migration_phases.md` | 重写(迁移阶段化) |
| `docs/troubleshooting/known-issues.md` | `docs/troubleshooting/known-issues.md` | 直接迁移 + 新分区 |
| `src/modules/[module]/README.md` | `services/[service]/README.md` | 重写 |
| `docs/standards/coding-standards.md` §A11y | `docs/standards/accessibility.md` | 拆分独立 |
| CICD 文档 | Edu 对应文档 | 关系 |
| -------------------------------------------------- | ------------------------------------------------ | ------------------ |
| `.trae/rules/project_rules.md` | `project_rules.md` | 调整(微服务版) |
| `docs/standards/coding-standards.md` | `docs/standards/coding-standards.md` | 调整(多语言版) |
| —(散落在 project_rules | `docs/standards/git-workflow.md` | 新建 |
| `docs/architecture/004_architecture_impact_map.md` | `docs/architecture/001_architecture_overview.md` | 重写 |
| `docs/architecture/006_k12_feature_checklist.md` | `docs/architecture/feature_checklist.md` | 直接迁移 |
| `docs/architecture/007_gap_audit_report.md` | `docs/architecture/gap_audit.md` | 调整 |
| `docs/architecture/008_module_role_mapping.md` | `docs/architecture/role_mapping.md` | 直接迁移 |
| `docs/architecture/roadmap/README.md` | `docs/architecture/roadmap/README.md` | 重写 |
| `docs/architecture/roadmap/tech-debt.md` | `docs/architecture/roadmap/tech-debt.md` | 重写 |
| `docs/architecture/roadmap/decoupling.md` | `docs/architecture/roadmap/migration_phases.md` | 重写(迁移阶段化) |
| `docs/troubleshooting/known-issues.md` | `docs/troubleshooting/known-issues.md` | 直接迁移 + 新分区 |
| `src/modules/[module]/README.md` | `services/[service]/README.md` | 重写 |
| `docs/standards/coding-standards.md` §A11y | `docs/standards/accessibility.md` | 拆分独立 |
---
@@ -283,14 +284,14 @@ gantt
### 6.2 各阶段目标
| 阶段 | 名称 | 目标 | 关键交付物 | 验收信号 |
|------|------|------|-----------|---------|
| P1 | 地基 | 仓库骨架、契约工具链、CI、可观测平台 | monorepo 结构、buf 配置、Kafka 集群、OpenTelemetry | 契约生成 + 一次端到端 trace |
| P2 | 身份 | identity + auth + notification 三服务打通 | JWT 颁发、RBAC、邮件/短信/站内通知 | 用户注册→登录→收到通知 |
| P3 | 核心教学 | org + teaching + content | 班级/课表/作业/题库/考试 | 教师创建作业→学生提交→批改闭环 |
| P4 | 内容分析 | insight + CQRS 读模型 + ES 全文检索 | ClickHouse 报表、ES 搜索、Neo4j 知识图谱 | 多维分析报表 + 全文搜索可用 |
| P5 | 沟通AI | comm + AI 辅助 | 站内信/通知中心、AI 备课/出题/答疑 | 教师用 AI 出题并发布到班级 |
| P6 | 硬化 | 安全加固、灾备、性能、混沌工程 | WAF、定期备份、压测报告、混沌演练 | RPO≤15min、RTO≤30min、P99≤500ms |
| 阶段 | 名称 | 目标 | 关键交付物 | 验收信号 |
| ---- | -------- | ----------------------------------------- | -------------------------------------------------- | ------------------------------- |
| P1 | 地基 | 仓库骨架、契约工具链、CI、可观测平台 | monorepo 结构、buf 配置、Kafka 集群、OpenTelemetry | 契约生成 + 一次端到端 trace |
| P2 | 身份 | identity + auth + notification 三服务打通 | JWT 颁发、RBAC、邮件/短信/站内通知 | 用户注册→登录→收到通知 |
| P3 | 核心教学 | org + teaching + content | 班级/课表/作业/题库/考试 | 教师创建作业→学生提交→批改闭环 |
| P4 | 内容分析 | insight + CQRS 读模型 + ES 全文检索 | ClickHouse 报表、ES 搜索、Neo4j 知识图谱 | 多维分析报表 + 全文搜索可用 |
| P5 | 沟通AI | comm + AI 辅助 | 站内信/通知中心、AI 备课/出题/答疑 | 教师用 AI 出题并发布到班级 |
| P6 | 硬化 | 安全加固、灾备、性能、混沌工程 | WAF、定期备份、压测报告、混沌演练 | RPO≤15min、RTO≤30min、P99≤500ms |
### 6.3 阶段交付门槛
@@ -310,15 +311,16 @@ gantt
**复用方式**:将 CICD 的 `src/app/styles/tokens/` 五层分层模型平移至微前端共享包。
| CICD 位置 | Edu 位置 | 调整 |
|-----------|---------|------|
| `src/app/styles/tokens/primitive.css` | `packages/ui-tokens/primitive.css` | 直接平移 |
| `src/app/styles/tokens/semantic-light.css` | `packages/ui-tokens/semantic-light.css` | 直接平移 |
| `src/app/styles/tokens/semantic-dark.css` | `packages/ui-tokens/semantic-dark.css` | 直接平移 |
| CICD 位置 | Edu 位置 | 调整 |
| ---------------------------------------------- | ------------------------------------------- | -------- |
| `src/app/styles/tokens/primitive.css` | `packages/ui-tokens/primitive.css` | 直接平移 |
| `src/app/styles/tokens/semantic-light.css` | `packages/ui-tokens/semantic-light.css` | 直接平移 |
| `src/app/styles/tokens/semantic-dark.css` | `packages/ui-tokens/semantic-dark.css` | 直接平移 |
| `src/app/styles/tokens/lesson-preparation.css` | `packages/ui-tokens/lesson-preparation.css` | 直接平移 |
| `src/app/styles/tokens/tailwind-theme.css` | `packages/ui-tokens/tailwind-theme.css` | 直接平移 |
| `src/app/styles/tokens/tailwind-theme.css` | `packages/ui-tokens/tailwind-theme.css` | 直接平移 |
**强制规则保持不变**
- 禁止硬编码颜色(`#hex`
- 禁止硬编码字体(`'Inter'`/`'Fraunces'`/`'JetBrains Mono'`
- 禁止硬编码字号(`font-size: Npx`
@@ -329,14 +331,15 @@ gantt
**复用方式**:将 CICD 的 `src/shared/components/ui/` 平移至 `packages/ui-components/`,作为 Module Federation 共享依赖。
| 组件类别 | CICD 路径 | Edu 路径 | 复用要点 |
|---------|----------|---------|---------|
| 基础组件Button/Input/Dialog | `shared/components/ui/` | `packages/ui-components/` | 全部平移,保持 PascalCase 命名 |
| A11y 组件 | `shared/components/a11y/` | `packages/ui-components/a11y/` | skip-link、visually-hidden、focus-trap、aria-status 全部平移 |
| 图表组件 | 各模块内 | `packages/ui-components/charts/` | 收集 recharts 封装,统一暴露 |
| 表单组件 | react-hook-form 封装 | `packages/ui-components/form/` | 与 zod resolver 一同平移 |
| 组件类别 | CICD 路径 | Edu 路径 | 复用要点 |
| ------------------------------- | ------------------------- | -------------------------------- | ------------------------------------------------------------ |
| 基础组件Button/Input/Dialog | `shared/components/ui/` | `packages/ui-components/` | 全部平移,保持 PascalCase 命名 |
| A11y 组件 | `shared/components/a11y/` | `packages/ui-components/a11y/` | skip-link、visually-hidden、focus-trap、aria-status 全部平移 |
| 图表组件 | 各模块内 | `packages/ui-components/charts/` | 收集 recharts 封装,统一暴露 |
| 表单组件 | react-hook-form 封装 | `packages/ui-components/form/` | 与 zod resolver 一同平移 |
**复用规则**
- 组件必须为纯函数,使用 `function` 声明
- 不使用 `React.FC`,直接用函数声明 + 显式标注 props 类型
- 默认服务端组件(微前端 host需要交互时才添加 `"use client"`
@@ -346,14 +349,15 @@ gantt
**复用方式**:将 CICD 的 `requirePermission()` + `usePermission().hasPermission()` 模式平移至 identity 服务 + auth 基础设施服务。
| CICD 资产 | Edu 位置 | 调整 |
|-----------|---------|------|
| `shared/lib/auth-guard.ts`requirePermission | `services/auth/src/guards/permission.guard.ts`NestJS Guard | 改为 NestJS Guard 装饰器 |
| `shared/types/permissions.ts`(权限点常量) | `packages/contracts/src/permissions.ts` | 集中到 contracts 包,多服务共享 |
| `usePermission` Hook | `packages/ui-components/hooks/use-permission.ts` | 通过 BFF 拉取权限Hook 接口不变 |
| 角色权限矩阵008 | `docs/architecture/role_mapping.md` | 直接平移 |
| CICD 资产 | Edu 位置 | 调整 |
| ----------------------------------------------- | -------------------------------------------------------------- | -------------------------------- |
| `shared/lib/auth-guard.ts`requirePermission | `services/auth/src/guards/permission.guard.ts`NestJS Guard | 改为 NestJS Guard 装饰器 |
| `shared/types/permissions.ts`(权限点常量) | `packages/contracts/src/permissions.ts` | 集中到 contracts 包,多服务共享 |
| `usePermission` Hook | `packages/ui-components/hooks/use-permission.ts` | 通过 BFF 拉取权限Hook 接口不变 |
| 角色权限矩阵008 | `docs/architecture/role_mapping.md` | 直接平移 |
**强制规则保持不变**
- 每个 Controller/Action 必须调用 `requirePermission()` 等价物
- 前端组件禁止使用 `role === "xxx"` 硬编码,统一使用 `usePermission().hasPermission()`
@@ -361,36 +365,36 @@ gantt
**复用方式**CICD 的 `cacheFn`React `cache()` + 自定义缓存层)改为 NestJS Cache 模块 + Redis**权限数据不跨请求缓存**的规则沿用。
| CICD 模式 | Edu 模式 | 备注 |
|-----------|---------|------|
| CICD 模式 | Edu 模式 | 备注 |
| ------------------------ | --------------------------------------------------- | ------------------------------------- |
| `cacheFn`React cache | NestJS `@UseInterceptors(CacheInterceptor)` + Redis | 单请求内缓存改为 NestJS REQUEST scope |
| `unstable_cache` | 禁用 | CICD 已禁用Edu 沿用禁用决策 |
| 权限数据缓存 | 仅在 auth 服务内部缓存TTL ≤ 60s | 跨服务不缓存权限 |
| 静态资源缓存 | CDN + 短缓存 | 配置不变 |
| `unstable_cache` | 禁用 | CICD 已禁用Edu 沿用禁用决策 |
| 权限数据缓存 | 仅在 auth 服务内部缓存TTL ≤ 60s | 跨服务不缓存权限 |
| 静态资源缓存 | CDN + 短缓存 | 配置不变 |
### 7.5 Server Action 模式 → Application Service 模式
**复用方式**CICD 的 Server Action 编排模式(权限 + Zod 验证 + 调用 data-access + revalidate平移为 NestJS Application Service 编排模式。
| CICD Server Action 步骤 | NestJS Application Service 对应 |
|------------------------|-------------------------------|
| `requirePermission(perm)` | `@RequirePermission(perm)` 装饰器 + Guard |
| Zod `safeParse` | `ValidationPipe` + DTO class-validator |
| 调用 `data-access` | 调用 Domain Service / Repository |
| `revalidatePath` | 发布领域事件触发读模型更新 |
| 返回 `ActionState<T>` | 返回 protobuf message结构同 ActionState |
| CICD Server Action 步骤 | NestJS Application Service 对应 |
| ------------------------- | ------------------------------------------- |
| `requirePermission(perm)` | `@RequirePermission(perm)` 装饰器 + Guard |
| Zod `safeParse` | `ValidationPipe` + DTO class-validator |
| 调用 `data-access` | 调用 Domain Service / Repository |
| `revalidatePath` | 发布领域事件触发读模型更新 |
| 返回 `ActionState<T>` | 返回 protobuf message结构同 ActionState |
### 7.6 状态管理 5 层模型
**复用方式**CICD 的 5 层状态模型平移至微前端 host 应用。
| 层级 | CICD 方案 | Edu 方案 | 备注 |
|------|----------|---------|------|
| L1 URL | nuqs | nuqs | 直接平移 |
| L2 Server | TanStack Query | TanStack Query | 直接平移 |
| L3 Client Business | Zustand slice | Zustand slice | 直接平移 |
| L4 Global UI | Zustand ui-store + ModalRoot | Zustand ui-store + ModalRoot | 直接平移 |
| L5 Form | react-hook-form + zodResolver | react-hook-form + zodResolver | 直接平移 |
| 层级 | CICD 方案 | Edu 方案 | 备注 |
| ------------------ | ----------------------------- | ----------------------------- | -------- |
| L1 URL | nuqs | nuqs | 直接平移 |
| L2 Server | TanStack Query | TanStack Query | 直接平移 |
| L3 Client Business | Zustand slice | Zustand slice | 直接平移 |
| L4 Global UI | Zustand ui-store + ModalRoot | Zustand ui-store + ModalRoot | 直接平移 |
| L5 Form | react-hook-form + zodResolver | react-hook-form + zodResolver | 直接平移 |
### 7.7 A11y 工具集
@@ -409,23 +413,24 @@ gantt
**复用方式**:平移至 notification 服务,日志结构保持。
| CICD 资产 | Edu 位置 | 备注 |
|-----------|---------|------|
| `shared/lib/login-logger.ts` | `services/notification/src/loggers/login-logger.ts` | 登录尝试日志 |
| CICD 资产 | Edu 位置 | 备注 |
| ----------------------------- | ---------------------------------------------------- | ---------------------------- |
| `shared/lib/login-logger.ts` | `services/notification/src/loggers/login-logger.ts` | 登录尝试日志 |
| `shared/lib/change-logger.ts` | `services/notification/src/loggers/change-logger.ts` | 数据变更日志(监听领域事件) |
| `shared/lib/audit-logger.ts` | `services/notification/src/loggers/audit-logger.ts` | 关键业务操作日志 |
| `shared/lib/audit-logger.ts` | `services/notification/src/loggers/audit-logger.ts` | 关键业务操作日志 |
### 7.9 CI/CD 流水线模式
**复用方式**三套工作流模式沿用CI + 安全扫描 + 灾备演练),但执行方式改为多服务并行。
| CICD 工作流 | Edu 工作流 | 调整 |
|------------|-----------|------|
| `ci.yml` | `.gitea/workflows/ci.yml` | 单体改为矩阵并行(每个服务一个 job |
| `security.yml` | `.gitea/workflows/security.yml` | 新增 Trivy 扫描 Docker 镜像 |
| `dr-drill.yml` | `.gitea/workflows/dr-drill.yml` | 灾备演练改为多服务恢复顺序演练 |
| CICD 工作流 | Edu 工作流 | 调整 |
| -------------- | ------------------------------- | ------------------------------------ |
| `ci.yml` | `.gitea/workflows/ci.yml` | 单体改为矩阵并行(每个服务一个 job |
| `security.yml` | `.gitea/workflows/security.yml` | 新增 Trivy 扫描 Docker 镜像 |
| `dr-drill.yml` | `.gitea/workflows/dr-drill.yml` | 灾备演练改为多服务恢复顺序演练 |
**CI 必须包含**(沿用 CICD 规则):
1. 安装依赖多语言pnpm install / go mod download / uv sync
2. Lint 检查ESLint + golangci-lint + ruff
3. 类型检查tsc --noEmit + go vet + mypy
@@ -478,15 +483,15 @@ gantt
## 附录:迁移过程中的关键决策点
| 决策点 | 选择 | 理由 |
|--------|------|------|
| 服务拆分粒度 | 6 业务 + 2 基础设施 | 平衡团队规模与拆分收益,避免过细导致 RPC 开销 |
| 通信协议 | gRPC内部+ RESTBFF 对外) | 内部高性能,外部兼容性 |
| 事件总线 | Kafka + Debezium CDC | CDC 减少业务代码侵入Outbox 模式保证一致性 |
| 契约工具 | protobuf + buf | 多语言代码生成breaking change 检测 |
| 前端架构 | Module Federation | 微前端独立部署,运行时共享依赖 |
| 状态管理 | 沿用 5 层模型 | 团队熟悉度高,迁移成本低 |
| 数据库拆分 | 每服务独占库 | 杜绝跨服务联表,强制契约化通信 |
| 缓存策略 | NestJS Cache + Redis | 替代 React cache(),规则(权限不跨请求缓存)沿用 |
| 迁移方式 | strangler fig | 风险可控,渐进式切换 |
| arch.db | 多语言扫描扩展 | 复用 CICD 元数据库思路,扩展 Go/Python 扫描器 |
| 决策点 | 选择 | 理由 |
| ------------ | ------------------------------ | ------------------------------------------------ |
| 服务拆分粒度 | 6 业务 + 2 基础设施 | 平衡团队规模与拆分收益,避免过细导致 RPC 开销 |
| 通信协议 | gRPC内部+ RESTBFF 对外) | 内部高性能,外部兼容性 |
| 事件总线 | Kafka + Debezium CDC | CDC 减少业务代码侵入Outbox 模式保证一致性 |
| 契约工具 | protobuf + buf | 多语言代码生成breaking change 检测 |
| 前端架构 | Module Federation | 微前端独立部署,运行时共享依赖 |
| 状态管理 | 沿用 5 层模型 | 团队熟悉度高,迁移成本低 |
| 数据库拆分 | 每服务独占库 | 杜绝跨服务联表,强制契约化通信 |
| 缓存策略 | NestJS Cache + Redis | 替代 React cache(),规则(权限不跨请求缓存)沿用 |
| 迁移方式 | strangler fig | 风险可控,渐进式切换 |
| arch.db | 多语言扫描扩展 | 复用 CICD 元数据库思路,扩展 Go/Python 扫描器 |

View File

@@ -39,7 +39,7 @@ pnpm dev
- [UI 设计系统](docs/standards/ui-design-system.md)
- [Git 工作流](docs/standards/git-workflow.md)
- [已知问题](docs/troubleshooting/known-issues.md)
- [项目规则](project_rules.md)
- [项目规则](.trae/rules/project_rules.md)
- [迁移指南](MIGRATION_GUIDE.md)
## 开发阶段

View File

@@ -5,7 +5,8 @@
> 状态:基线发布
> 适用范围Edu 微服务架构TS + Go + Python + protobuf
> 关联文档:
> - [项目规则](../../project_rules.md)
>
> - [项目规则](../../.trae/rules/project_rules.md)
> - [迁移指南](../../MIGRATION_GUIDE.md)
> - [Git 工作流](./git-workflow.md)
> - [架构总览](../architecture/001_architecture_overview.md)
@@ -85,7 +86,7 @@ import type { UserEntity } from "@/modules/user/domain/user.entity";
#### 2.4.1 模块组织
每个 NestJS 模块对应一个 DDD 聚合,结构见 [project_rules.md §4.1](../../project_rules.md#41-nestjs-业务微服务标准结构)。
每个 NestJS 模块对应一个 DDD 聚合,结构见 [project_rules.md §3.3](../../.trae/rules/project_rules.md#33-模块标准结构ddd)。
#### 2.4.2 装饰器规则
@@ -111,6 +112,7 @@ export class UserController {
```
**规则**
- Controller 必须使用 `@Controller(path)` 装饰器path 使用 kebab-case 复数
- Controller 类必须使用 `@RequirePermission()` 装饰器(类级默认权限)
- 每个 Handler 可选覆盖类级权限(更细粒度)
@@ -131,6 +133,7 @@ export class UserService {
```
**规则**
- 依赖通过构造函数注入,使用 `readonly` 修饰符
- 接口绑定在 Module 的 `providers` 中:`{ provide: "UserRepository", useClass: UserRepoImpl }`
- 禁止使用属性注入(`@Inject()` 属性装饰器)
@@ -152,6 +155,7 @@ export class UserModule {}
```
**规则**
- Module 类名 PascalCase + `Module` 后缀
- `exports` 仅暴露 Application Service不暴露 Repository
- 跨 Module 通信通过 exports 的 Service不直接访问对方 Repository
@@ -190,6 +194,7 @@ export class GetUserByIdHandler implements IQueryHandler<GetUserByIdQuery> {
```
**规则**
- Command 走写路径Command → Handler → Domain → Repository → MySQL + Outbox
- Query 走读路径Query → Handler → Read Model禁止查主库
- Command Handler 必须在事务内写 Outbox 表
@@ -207,7 +212,12 @@ export class UserEntity {
) {}
static create(props: UserCreateProps): UserEntity {
return new UserEntity(crypto.randomUUID(), props.email, props.name, new Date());
return new UserEntity(
crypto.randomUUID(),
props.email,
props.name,
new Date(),
);
}
rename(newName: string): UserRenamedEvent {
@@ -218,6 +228,7 @@ export class UserEntity {
```
**规则**
- Entity 构造函数私有,通过静态工厂方法创建
- Entity 字段私有,通过方法变更状态
- 状态变更方法返回领域事件,由 Application Service 发布
@@ -239,6 +250,7 @@ export class CreateUserDto {
```
**规则**
- DTO 类名 `Create[Entity]Dto` / `Update[Entity]Dto` / `[Entity]Response`
- DTO 字段使用 `readonly` 修饰
- 使用 `class-validator` 装饰器校验
@@ -264,13 +276,13 @@ export class CreateUserDto {
### 2.10 状态管理(沿用 CICD 5 层模型)
| 层级 | 场景 | 方案 |
|------|------|------|
| L1 URL | 可分享、可刷新的状态 | nuqs |
| L2 Server | 服务端数据 | TanStack Query |
| L3 Client Business | 客户端业务状态 | Zustand slice |
| L4 Global UI | 全局 UI 状态 | Zustand ui-store + ModalRoot |
| L5 Form | 表单状态 | react-hook-form + zodResolver |
| 层级 | 场景 | 方案 |
| ------------------ | -------------------- | ----------------------------- |
| L1 URL | 可分享、可刷新的状态 | nuqs |
| L2 Server | 服务端数据 | TanStack Query |
| L3 Client Business | 客户端业务状态 | Zustand slice |
| L4 Global UI | 全局 UI 状态 | Zustand ui-store + ModalRoot |
| L5 Form | 表单状态 | react-hook-form + zodResolver |
---
@@ -328,6 +340,7 @@ user, _ := h.userService.GetUser(ctx, id)
```
**规则**
- 错误必须显式处理,**禁止 `_ = err`**
- 使用 `errors.Is``errors.As` 判断错误类型,禁止字符串匹配
- 自定义错误类型使用 `fmt.Errorf("...: %w", err)` 包装
@@ -349,6 +362,7 @@ type UserService struct {
```
**规则**
- `context.Context` 作为函数第一个参数传递
- **禁止**将 context 存储在结构体字段中
- 超时/取消通过 context 传递,禁止使用 `time.Sleep` 等待
@@ -368,6 +382,7 @@ if err := g.Wait(); err != nil {
```
**规则**
- 优先使用 `errgroup` 管理并发 goroutine
- 禁止裸 `go func()` 不带 recover 和 context
- 共享状态使用 channel 或 `sync` 包,禁止使用 `sync.Mutex` 嵌套锁
@@ -388,6 +403,7 @@ func RegisterRoutes(r *gin.Engine, h *Handler, mw *Middleware) {
```
**规则**
- 路由分组按 API 版本(`/api/v1`
- 中间件链顺序Recovery → RequestID → Logger → RateLimit → Auth → RequirePermission
- Handler 函数签名固定:`func(c *gin.Context)`
@@ -404,6 +420,7 @@ logger.Info("user login", "user_id", userID, "ip", ip)
```
**规则**
- 使用标准库 `log/slog` 结构化日志
- 日志字段使用 kebab-case key
- 必须包含 `request_id` 用于链路追踪
@@ -459,6 +476,7 @@ def get_user(user_id):
```
**规则**
- 所有函数必须标注参数和返回值类型
- 使用 `from __future__ import annotations` 启用延迟注解求值
- 使用 `Optional[T]``T | None`Python 3.10+)标注可选类型
@@ -480,6 +498,7 @@ async def fetch_user(user_id: str) -> User:
```
**规则**
- I/O 操作HTTP、DB、文件必须使用 async/await
- 禁止在 async 函数中调用同步阻塞 I/O必须用 `asyncio.to_thread` 或 async 客户端
- CPU 密集任务用 `asyncio.to_thread` 或进程池
@@ -509,6 +528,7 @@ class UserResponse(BaseModel):
```
**规则**
- 请求模型命名 `[Action][Entity]Request`,响应模型命名 `[Entity]Response`
- 必须使用 `Field` 添加描述、约束
- 复杂校验使用 `@field_validator``@model_validator`
@@ -534,6 +554,7 @@ async def get_user(
```
**规则**
- 路由分组使用 `APIRouter`,按 API 版本组织
- 必须标注 `response_model`
- 权限校验通过 `Depends` 注入,每个 endpoint 显式调用 `require_permission`
@@ -557,6 +578,7 @@ settings = Settings()
```
**规则**
- 配置使用 `pydantic-settings``BaseSettings`
- 环境变量前缀按服务名(`INSIGHT_AI_`
- 禁止在业务代码中直接读取环境变量(`os.getenv`),统一通过 `settings`
@@ -567,39 +589,40 @@ settings = Settings()
### 5.1 命名通用规则
| 对象 | 风格 | 示例 |
|------|------|------|
| 目录 | kebab-case | `user-profile/` |
| 常量 | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` |
| 布尔值 | `is/has/can/should` 前缀 | `isVisible``is_active``hasPermission` |
| 类/接口/结构体 | PascalCase | `UserService``UserFetcher` |
| 服务名 | 小写单数 | `identity``teaching` |
| Kafka topic | 点分小写 | `edu.identity.user.created` |
| protobuf message | PascalCase | `UserCreatedEvent` |
| protobuf 字段 | snake_case | `user_id``created_at` |
| 对象 | 风格 | 示例 |
| ---------------- | ------------------------ | ----------------------------------------- |
| 目录 | kebab-case | `user-profile/` |
| 常量 | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` |
| 布尔值 | `is/has/can/should` 前缀 | `isVisible``is_active``hasPermission` |
| 类/接口/结构体 | PascalCase | `UserService``UserFetcher` |
| 服务名 | 小写单数 | `identity``teaching` |
| Kafka topic | 点分小写 | `edu.identity.user.created` |
| protobuf message | PascalCase | `UserCreatedEvent` |
| protobuf 字段 | snake_case | `user_id``created_at` |
### 5.2 文件行数通用规则
| 文件类型 | 建议行数 | 硬性上限 |
|---------|---------|---------|
| 配置/常量/类型/proto | 无限制 | 无限制 |
| React 组件 | ≤ 500 | 800 |
| NestJS Controller/Service | ≤ 500 | 800 |
| Go handler/middleware | ≤ 400 | 600 |
| Python endpoint/service | ≤ 400 | 600 |
| 工具函数 | ≤ 40 | - |
| 自定义 Hook | ≤ 80 | - |
| **任何文件** | - | **1000超过必须拆分** |
| 文件类型 | 建议行数 | 硬性上限 |
| ------------------------- | -------- | ---------------------- |
| 配置/常量/类型/proto | 无限制 | 无限制 |
| React 组件 | ≤ 500 | 800 |
| NestJS Controller/Service | ≤ 500 | 800 |
| Go handler/middleware | ≤ 400 | 600 |
| Python endpoint/service | ≤ 400 | 600 |
| 工具函数 | ≤ 40 | - |
| 自定义 Hook | ≤ 80 | - |
| **任何文件** | - | **1000超过必须拆分** |
### 5.3 错误处理通用规则
| 语言 | 规则 |
|------|------|
| 语言 | 规则 |
| ---------- | -------------------------------------------------------------- |
| TypeScript | 错误通过抛出异常Application Service 必须捕获并转为结构化响应 |
| Go | 错误必须显式处理,禁止 `_ = err`,使用 `errors.Is/As` 判断类型 |
| Python | 使用异常层次结构,自定义异常继承 `Exception`,禁止裸 `except:` |
| Go | 错误必须显式处理,禁止 `_ = err`,使用 `errors.Is/As` 判断类型 |
| Python | 使用异常层次结构,自定义异常继承 `Exception`,禁止裸 `except:` |
**通用规则**
- 错误信息对内详细(含上下文、堆栈),对外脱敏(不泄露实现细节)
- 错误必须分类业务错误4xx、系统错误5xx、依赖错误502/503
- 错误必须记录日志,包含 request_id 用于链路追踪
@@ -607,13 +630,14 @@ settings = Settings()
### 5.4 日志通用规则
| 语言 | 工具 | 说明 |
|------|------|------|
| 语言 | 工具 | 说明 |
| ---------- | -------------------- | ---------------- |
| TypeScript | NestJS Logger + pino | 结构化 JSON 日志 |
| Go | log/slog | 标准库结构化日志 |
| Python | structlog 或 loguru | 结构化 JSON 日志 |
| Go | log/slog | 标准库结构化日志 |
| Python | structlog 或 loguru | 结构化 JSON 日志 |
**通用规则**
- 日志必须结构化JSON禁止纯文本
- 必须包含 `timestamp``level``service``request_id``trace_id`
- 日志级别DEBUG开发、INFO关键业务、WARN异常可恢复、ERROR系统错误
@@ -622,13 +646,14 @@ settings = Settings()
### 5.5 测试通用规则
| 语言 | 单元测试框架 | 覆盖率目标 |
|------|------------|-----------|
| TypeScript | Vitest + nestjs/testing | ≥ 80% |
| Go | 标准 testing 包 + testify | ≥ 80% |
| Python | pytest + pytest-asyncio | ≥ 80% |
| 语言 | 单元测试框架 | 覆盖率目标 |
| ---------- | ------------------------- | ---------- |
| TypeScript | Vitest + nestjs/testing | ≥ 80% |
| Go | 标准 testing 包 + testify | ≥ 80% |
| Python | pytest + pytest-asyncio | ≥ 80% |
**通用规则**
- 测试文件与源文件同目录或 `tests/` 子目录
- 命名:`*.test.ts` / `*_test.go` / `test_*.py`
- 测试描述说明预期行为("should disable button while loading"
@@ -714,6 +739,7 @@ enum UserStatus {
```
**规则**
- 字段编号禁止复用,删除字段必须 `reserved` 标记
- 枚举第一个值必须为 `*_UNSPECIFIED = 0`
- 时间使用 `google.protobuf.Timestamp`,不使用 string
@@ -770,12 +796,12 @@ buf generate
### 7.1 令牌分层(沿用 CICD 模型,迁移至微前端共享包)
| Layer | 位置 | 用途 |
|-------|------|------|
| Layer 1 Primitive | `packages/ui-tokens/primitive.css` | 原始色板/字号/间距/阴影,业务代码不直接引用 |
| Layer 2 Semantic | `packages/ui-tokens/semantic-light.css` + `semantic-dark.css` | 语义令牌,业务代码唯一引用入口 |
| 模块命名空间 | `packages/ui-tokens/lesson-preparation.css` | `--lp-*` 令牌,明暗双份 |
| Tailwind 暴露 | `packages/ui-tokens/tailwind-theme.css` | `@theme inline` 暴露为 `bg-*`/`text-*`/`font-*` 类 |
| Layer | 位置 | 用途 |
| ----------------- | ------------------------------------------------------------- | -------------------------------------------------- |
| Layer 1 Primitive | `packages/ui-tokens/primitive.css` | 原始色板/字号/间距/阴影,业务代码不直接引用 |
| Layer 2 Semantic | `packages/ui-tokens/semantic-light.css` + `semantic-dark.css` | 语义令牌,业务代码唯一引用入口 |
| 模块命名空间 | `packages/ui-tokens/lesson-preparation.css` | `--lp-*` 令牌,明暗双份 |
| Tailwind 暴露 | `packages/ui-tokens/tailwind-theme.css` | `@theme inline` 暴露为 `bg-*`/`text-*`/`font-*` 类 |
### 7.2 强制规则
@@ -846,11 +872,11 @@ buf generate
### 8.6 依赖扫描
| 语言 | 工具 |
|------|------|
| TS | `npm audit` + Snyk + Trivy |
| Go | `govulncheck` |
| Python | `pip-audit` + `safety` |
| 语言 | 工具 |
| ------ | -------------------------- |
| TS | `npm audit` + Snyk + Trivy |
| Go | `govulncheck` |
| Python | `pip-audit` + `safety` |
高危漏洞阻断合并。
@@ -873,12 +899,12 @@ buf generate
### 9.1 测试分层
| 层级 | TS | Go | Python | 覆盖率 |
|------|-----|-----|--------|--------|
| 单元测试 | Vitest | testing + testify | pytest | ≥ 80% |
| 集成测试 | Vitest + Testcontainers | testing + Testcontainers | pytest + Testcontainers | 关键流程 |
| E2E 测试 | Playwright | - | - | 核心业务路径 |
| 契约测试 | pact + buf | pact + buf | pact + buf | 服务间契约 |
| 层级 | TS | Go | Python | 覆盖率 |
| -------- | ----------------------- | ------------------------ | ----------------------- | ------------ |
| 单元测试 | Vitest | testing + testify | pytest | ≥ 80% |
| 集成测试 | Vitest + Testcontainers | testing + Testcontainers | pytest + Testcontainers | 关键流程 |
| E2E 测试 | Playwright | - | - | 核心业务路径 |
| 契约测试 | pact + buf | pact + buf | pact + buf | 服务间契约 |
### 9.2 测试命令
@@ -965,15 +991,15 @@ pytest tests/integration -v
## 附录:与 CICD 单应用规范的差异
| 项目 | CICD 单应用 | Edu 微服务 | 原因 |
|------|-----------|-----------|------|
| 项目结构 | 单 Next.js 应用 | 多语言 monorepo | 微服务拆分 |
| 数据获取层 | `modules/[module]/data-access.ts` | NestJS Repository + Domain Entity | DDD 分层 |
| 中间件 | `proxy.ts`Next.js 16 | Go Gin Gateway | 网关独立 |
| 通信 | 函数调用 | gRPC + Kafka | 跨进程通信 |
| 状态管理 | Zustand + Context + nuqs | 沿用 | 团队熟悉 |
| 环境变量校验 | `@t3-oss/env-nextjs` + Zod | TS Zod / Go viper / Python pydantic-settings | 多语言 |
| 行数限制 | 单一规范 | 按语言分档 | 各语言惯例 |
| 契约 | 无(内部函数调用) | protobuf + buf | 跨服务通信需要 |
| 事件驱动 | 无 | Kafka + Outbox | 微服务最终一致 |
| 设计令牌 | `src/app/styles/tokens/` | `packages/ui-tokens/` | 微前端共享 |
| 项目 | CICD 单应用 | Edu 微服务 | 原因 |
| ------------ | --------------------------------- | -------------------------------------------- | -------------- |
| 项目结构 | 单 Next.js 应用 | 多语言 monorepo | 微服务拆分 |
| 数据获取层 | `modules/[module]/data-access.ts` | NestJS Repository + Domain Entity | DDD 分层 |
| 中间件 | `proxy.ts`Next.js 16 | Go Gin Gateway | 网关独立 |
| 通信 | 函数调用 | gRPC + Kafka | 跨进程通信 |
| 状态管理 | Zustand + Context + nuqs | 沿用 | 团队熟悉 |
| 环境变量校验 | `@t3-oss/env-nextjs` + Zod | TS Zod / Go viper / Python pydantic-settings | 多语言 |
| 行数限制 | 单一规范 | 按语言分档 | 各语言惯例 |
| 契约 | 无(内部函数调用) | protobuf + buf | 跨服务通信需要 |
| 事件驱动 | 无 | Kafka + Outbox | 微服务最终一致 |
| 设计令牌 | `src/app/styles/tokens/` | `packages/ui-tokens/` | 微前端共享 |

View File

@@ -1 +0,0 @@
4. è¥ä»£ç <C3A7>结构å<E2809E>˜åŒ?â†?`pnpm run arch:scan` 确认 arch.db 已更æ–?