Files
Edu/.trae/rules/project_rules.md

530 lines
29 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.
# 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 工作流
- **分支策略**:分支开发。**人类决策者手动维护分支**(创建分支、合并到 mainAI 不得自行切换/创建/合并分支
- **AI 分支约束(强制)**
- AI 只在人类分配的当前分支上工作
- **禁止** `git checkout -b``git switch``git branch` 创建或切换分支
- **禁止** `git merge``git push origin main`(合并与推送 main 由人类负责)
- AI 完成工作后 `git add` + `git commit` 提交到当前分支,通知人类合并
- **提交前校验**commit 前必须本地通过 `pnpm run lint` + `pnpm run typecheck`TS/ `go vet ./...`Go/ `ruff check src/`Python
- **pre-commit hook**`lint-staged` 自动修复 + 校验(见 `lint-staged.config.js`
- **commit-msg hook**commitlint 校验格式
- **回滚**:由人类在 main 上 `git revert <commit>`,不使用分支回滚
- **默认多 AI 协作**:所有工作默认按多 AI 合作模式进行(见 §14每个 AI 在各自分支独立工作
---
## 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 和本规则文件,不重复
- **只读自己模块分区**AI 查阅 known-issues 时只读自己负责模块的分区,禁止读其他 AI 模块的分区(避免被历史记录误导)
- **禁止工作日志**known-issues 不设"工作经验日志"区,不写流水账、不写"做了什么/学到什么"
- **经验沉淀不标注 AI 身份**:所有经验记录只写"场景→技术/规则"映射,**不得出现 AI 标识(如 ai01/ai02/coord 等)**,避免新同名 AI 将前任记录误认为当前事实
- **模块内经验**:模块内的经验沉淀在各自模块的 README/文档中,同样不标注 AI 身份
---
## 10. AI 工作强制流程
**所有 AI 工作必须遵循此流程,违反即违规。**
### 阶段 1上下文加载按需阅读严格模块边界
> **架构文档按需阅读**:模块开发只读自己模块的架构与服务 README项目整体相关工作跨模块契约、基础设施、文档体系、shared-proto才读全局架构文档。功能开发/文档书写等强依赖场景必须读对应架构。
>
> **严格模块边界**AI 只读自己负责模块的文档与源码不越界阅读其他模块的内部实现细节避免被历史记录或他人方案误导。仅在需要确认跨模块契约时才读对方的对外接口proto/API/事件)。
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` **仅读自己模块的分区**,禁止读其他 AI 模块分区
6. 模块开发:查 `docs/architecture/004_architecture_impact_map.md` **对应模块章节**;全局工作:查 004 全文
### 阶段 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` 对应**模块分区**(索引式一行,不写流水日志,**不标注 AI 身份**
2. 若发现新的架构决策 → 更新 004
3. 若代码结构变化 → `pnpm run arch:scan` 确认 arch.db 已更新
4. 模块内的经验沉淀到**自己模块的 README/文档**,不污染全局 known-issues同样不标注 AI 身份
> **禁止**在 known-issues.md 写"工作经验日志/流水账"。known-issues 是索引式速查手册,只保留场景→技术映射,**不出现任何 AI 标识**。
---
## 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`
---
## 14. 多 AI 协作规范
> **默认多 AI 协作**:所有 AI 工作默认按多 AI 合作模式进行。详细流程见 [多 AI 协作指南](../../docs/standards/multi-ai-collaboration.md),本节为强制约束摘要。
### 14.1 角色与权限
| 角色 | 职责 | 在分支提交 | 合并到 main | force push main |
| -------------------------- | -------------------------------------------------------- | ----------- | ------------------------- | --------------- |
| **协调 AICoordinator** | 契约管理、交叉审查、冲突仲裁、发布 | ✅ | ❌(由人类合并) | ⚠️(仅事故) |
| **开发 AIDev** | 按模块分工写代码、在分支提交 | ✅ | ❌ | ❌ |
| **SRE AI** | `infra/` 维护、部署 | ✅infra | ❌(由人类合并) | ⚠️(仅事故) |
| **人类决策者** | 架构决策、分支管理、合并、Breaking Change 审批、发布确认 | — | ✅(手动合并分支到 main | ⚠️(仅事故) |
> AI 在分配的分支上提交,**不自行合并到 main**。合并由人类决策者负责。
### 14.2 模块单一负责制与模块边界(强制)
- **每个模块(限界上下文)只有一个 AI 负责,禁止并行修改同一模块**
- **严格模块边界**AI 只修改自己负责的目录(`services/<my-service>/``apps/<my-app>/`),禁止越界修改他人模块的源码
- **只读自己模块文档**AI 阅读文档时只读自己模块的 README/设计文档/known-issues 分区,**禁止阅读其他 AI 模块的内部文档和历史记录**(避免被前任同名 AI 的过时方案/审计结果误导)
- **跨模块契约只读接口**需要确认跨模块协同时只读对方的对外接口proto message / API 端点 / Kafka 事件 schema不读对方内部实现
- `shared-proto``shared-tokens``docs/` 由协调 AI 维护,开发 AI 只读引用
- `infra/` 由 SRE AI 专门负责,业务 AI 不直接修改
### 14.3 分支开发规则(强制)
1. **分支由人类创建**:人类决策者为每个任务/模块创建分支并分配给 AIAI 不得自行创建分支
2. **AI 禁止切换分支**AI 不得执行 `git checkout -b``git switch``git branch` 等分支创建/切换命令
3. **AI 禁止合并/推送 main**`git merge``git push origin main` 由人类决策者执行AI 只提交到当前分支
4. **AI 提交流程**`git add <files>``git commit -m "<type>(<scope>): <subject>"` → 通知人类合并
5. **提交前校验**commit 前必须本地通过 `pnpm run lint` + `pnpm run typecheck`TS/ `go vet ./...`Go/ `ruff check src/`Python
6. **提交信息规范**:遵循 Conventional Commits见 §7
### 14.4 跨模块变更顺序(强制)
修改涉及多模块时,按依赖顺序依次在各模块分支完成,由人类决策者按顺序合并到 main
1. `shared-proto`proto 契约)
2. 业务服务classes / iam / core-edu 等)
3. `api-gateway`(路由)
4. BFFteacher-bff 等)
5. 微前端teacher-portal 等)
> 每合并一层到 main 后,再合并下一层。协调 AI 负责监督顺序,避免越级合并导致下游构建失败。
### 14.5 冲突处理规则
- **分支冲突**:由人类决策者在合并时解决,或通知 AI 在分支上 `git rebase` 最新 main 后重新提交
- **架构冲突**:由协调 AI 仲裁保留方案,通过新 commit 修正
- **禁止 `git push --force` 到 main**:仅协调 AI 在事故时可 `--force-with-lease`
### 14.6 经验沉淀规则(强制)
- **不记录工作日志**AI 不在 known-issues.md 或任何文档中写"工作经验日志/流水账"
- **只做经验沉淀**:遇到新的"场景→技术"映射,以索引式一行记录到 known-issues 对应模块分区
- **不标注 AI 身份**:经验沉淀记录**不得出现 AI 标识**(如 ai01/ai02/coord 等),避免新同名 AI 误读
- **模块内经验**:模块内的经验沉淀到各自服务 README/文档,同样不标注 AI 身份
### 14.7 敏感文件保护
以下文件修改需人类决策者额外审批:
- `.env``.env.example``infra/security/secrets.example.env`
- `infra/k8s/`(生产部署)
- `.github/workflows/`CI 配置)
- `.trae/rules/project_rules.md`(项目规则)
---
## 15. CI/CD 规范
> 详细配置见 `.github/workflows/ci.yml`,使用手册见 [cicd-runbook](../../docs/standards/cicd-runbook.md),设计文档见 [no-push-local-build-design](../../docs/superpowers/specs/2026-07-08-cicd-no-push-local-build-design.md)。
### 15.1 核心模式no-push 本地构建
- **不推送镜像到 registry**:构建即部署,镜像只存在于构建机本地
- **不依赖自建镜像**全部使用官方镜像node:22-alpine / golang:1.22-alpine / bufbuild/buf / docker:25-git
- **DooD 模式**deploy job 容器挂载 `/var/run/docker.sock`,容器内 docker 命令作用于宿主机
- **单文件管理**:一个 `.github/workflows/ci.yml` 管全部 CI/CD
### 15.2 流水线阶段
| 阶段 | 并行 | 内容 | 失败策略 |
| ----------------- | ---- | ------------------------------------ | -------- |
| **quality-ts** | ✅ | pnpm lint + typecheck + test + build | 失败阻断 |
| **quality-go** | ✅ | go vet + build + test | 失败阻断 |
| **quality-proto** | ✅ | buf lint + buf breaking | 失败阻断 |
| **deploy** | 串行 | docker compose up --build + 健康检查 | 失败阻断 |
> 质量检查在分支推送时触发,部署仅在合并到 main 时触发。
### 15.3 触发条件
| 事件 | 触发阶段 | 触发条件 |
| ----------------- | ----------------------------------------------- | -------------------------------- |
| 分支 push / PR | quality-ts + quality-go + quality-proto并行 | 分支推送自动 |
| push 到 main | 上述全部 + deploy | 合并后自动 |
| workflow_dispatch | 上述全部 + deploy | 手动触发,支持 `commit_sha` 回滚 |
> **不再支持 tag 发布**no-push 模式下不用 `git tag v*` 触发。版本管理通过 commit SHA 追溯。
### 15.4 镜像规范
- **不推送到 registry**,本地构建本地使用
- **不保留历史镜像**layer cache 在宿主机本地,未变更的层秒过
- **回滚**`git revert` 重跑 CI`workflow_dispatch` 指定 `commit_sha`
### 15.5 部署策略
- **目标环境**:服务器 Docker ComposeP1-P2 阶段K8sP3+ 阶段)
- **部署方式**`docker compose up -d --build --remove-orphans`(在 `/opt/edu/` 目录)
- **部署目录**`/opt/edu/`compose 文件)+ `/opt/edu/repo/`CI 同步的源码,供 build.context 使用)
- **健康检查**:部署后轮询 `/healthz` 端点10 次 × 6 秒),失败输出容器日志
- **回滚**`git revert + push``workflow_dispatch` 指定 `commit_sha`
### 15.6 必需的 CI 文件
| 文件 | 用途 |
| --------------------------------- | ------------------------------------- |
| `.github/workflows/ci.yml` | 唯一 CI/CD 流水线quality + deploy |
| `infra/docker-compose.deploy.yml` | 部署用 composebuild: 替代 image: |
| `infra/docker-compose.tools.yml` | 一次性预拉所有 CI 镜像 |
| `infra/deploy.env.example` | 部署环境变量模板 |
### 15.7 actrunner 配置
```toml
# /etc/gitea/act_runner/config.yaml
container:
valid_volumes:
- /var/run/docker.sock
```
### 15.8 镜像预拉(一次性)
部署前在服务器执行:
```bash
docker compose -f infra/docker-compose.tools.yml pull
```
拉取清单node:22-alpine、golang:1.22-alpine、bufbuild/buf:latest、docker:25-git、node:20-alpine、alpine:3.20、mysql:8.0开发测试、redis:7-alpine开发测试
---
**本规则文件是项目的强制约束,所有 contributor含 AI必须遵守。规则变更需同步更新 004 与 arch.db。**