# 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 覆盖 TypeScript(ts-morph)、Go(tree-sitter-go)、Python(tree-sitter-python)、Proto(buf AST)四类语言 2. **查询命令**: - `pnpm run arch:query -- sql ""` 自定义 SQL 查询 - `pnpm run arch:query -- module-deps` 查模块依赖 - `pnpm run arch:query -- module-reverse-deps ` 查反向依赖 - `pnpm run arch:query -- symbol-refs ` 查符号引用链 - `pnpm run arch:query -- tech-usage ` 查技术使用 - `pnpm run arch:query -- violations` 查架构违规 - `pnpm run arch:query -- stats` 查总体统计 - `pnpm run arch:query -- modules` 查模块列表 3. **arch.db 不替代 004**:arch.db 是"代码现状",004 是"设计意图",两者互补 4. **预期规模**:模块数 ≥ 10(api-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 职责**:业务逻辑,每服务独占 DB(DDD 限界上下文) ### 3.3 模块标准结构(DDD) ``` services/[service]/src/ ├─ [domain]/ # 限界上下文 │ ├─ *.controller.ts # Controller(HTTP/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` - **仅用于类型的导入必须使用 `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` | | 变量/函数 | camelCase(TS)/ lowercase(Go)/ snake_case(Py) | `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 清洗) - **密码哈希**:bcrypt(cost ≥ 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..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) - **事件命名**:`.`(如 `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 + PR,PR 至少 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 规则 - **包管理器分工**: - TypeScript:pnpm workspace(`pnpm-workspace.yaml`) - Go:go.work(`go.work`) - Python:uv 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. 可观测性规范 - **三支柱必须同时启用**(所有服务): - **日志**:pino(TS)/ zap(Go)/ structlog(Python)—— 结构化 JSON - **指标**:prom-client(TS)/ prometheus(Go)/ prometheus-client(Python)—— `/metrics` 端点 - **链路**:OpenTelemetry SDK + OTLP exporter —— 统一 traceparent - **健康检查**:`/health`(liveness)+ `/ready`(readiness),见各服务 `shared/health/` - **请求 ID**:Gateway 注入 `X-Request-Id`,全链路传递(日志、metrics、trace) - **指标命名**:`___`(如 `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。**