Files
Edu/services/core-edu/docs/01-understanding.md
SpecialX faaaf29f67 docs: ai 协作文档体系重构与多 ai 仲裁结果落地
1.AI 协作文档体系重构(objections/worklines/contracts+matrix.md)

2.coord 仲裁文档(final-decisions/cross-review/final-rulings/orchestration)

3.各服务 01/02 文档补全

4.共享包初始化(shared-ts/shared-go/hooks/ui-components/ui-tokens)

5.Proto 契约补全

6.004 架构影响地图更新

7.端口分配表

8.设计规格文档
2026-07-10 12:58:22 +08:00

195 lines
21 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.
# 模块理解确认书 — core-edu
> AI 标识ai08按 [ai-allocation.md §3.2](../../../docs/architecture/ai-allocation.md) 接管,原 ai03 阶段 1 文档已归位)
> 负责模块core-eduP3
> 阶段:架构设计外包 · 阶段 1全局理解· ai08 审计补全版
> 日期2026-07-09初稿/ 2026-07-09ai08 审计补全)
> 关联文档:[ai-allocation.md](../../../docs/architecture/ai-allocation.md)、[004 架构影响地图](../../../docs/architecture/004_architecture_impact_map.md)、[pending-features.md](../../../docs/architecture/roadmap/pending-features.md)、[coord 交叉审查报告](../../../docs/architecture/coord-cross-review.md)
---
## 1. 我在架构中的位置
- **层级**业务微服务层L5同时承载 **D2 教学组织****D3 教学核心** 两个限界上下文(见 [004 §1.1b](../../../docs/architecture/004_architecture_impact_map.md#11b-业务领域视角)
- **上游**
- teacher-bffP2 已 REST fetch 调用 `/exams` `/homework` `/grades`
- student-bffP3 依赖,作答/查成绩)
- parent-bffP4 依赖,查看子女成绩/考勤)
- api-gateway直接路由 `/api/v1/exams` 等,绕过 BFF 的内部直连场景)
- **下游**MySQL独占库 `core_edu_*` 表前缀、KafkaOutbox 事件发布、RedisP3 引入:作业高并发提交锁 + DataScope 缓存 + 短期聚合缓存)
- **通信方式**
- 入口 HTTP当前 REST`/exams``/homework``/grades`),端口 **3004**
- 入口 gRPC**P3 启用**[004 §4.2](../../../docs/architecture/004_architecture_impact_map.md#42-grpc-启用阶段矩阵) 裁决),端口 **50053**proto 已定义 `ExamService/HomeworkService/GradeService`
- 出口Kafka 事件Outbox 模式,[004 §12.2](../../../docs/architecture/004_architecture_impact_map.md#12-架构约束) 强制core-edu 不享受派生数据豁免)
- **端口声明**[coord 全局端口矩阵](../../../docs/architecture/coord-cross-review.md#43-全局端口矩阵coord-裁决基线已同步至-004-12)
- HTTP3004P3
- gRPC50053P3 启用)
- /metrics随 HTTP 3004Prometheus 抓取)
## 2. 我的限界上下文
- **聚合职责**:跨 **D2 教学组织**classes 模块,待合并)+ **D3 教学核心**exams / homework / grades + 排课/考勤 course/lesson/schedule/attendance 四表,[pending-features P3](../../../docs/architecture/roadmap/pending-features.md#p3-核心教学阶段m7-m10) 要求)
- **聚合根**Exam、Homework、Grade、Class待合并、Course、Lesson、Schedule、AttendanceP3 新增)
- **我不负责**
- 不负责题库内容(→ content 服务core-edu 通过事件通知 content 教学内容变更,[004 §4 服务依赖图](../../../docs/architecture/004_architecture_impact_map.md#4-服务依赖图) `CoreEdu -.事件.-> Content`
- 不负责学情分析/掌握度计算(→ data-ana 服务,消费 core-edu 事件)
- 不负责通知投递(→ msg 服务,消费 core-edu 事件)
- 不负责 AI 出题(→ ai 服务ai 通过 gRPC 调 content 查题库)
- 不负责权限/角色管理(→ iamcore-edu 仅消费 iam 事件同步教师关联)
- **数据自治**:独占 `core_edu` 数据库init-sql 中为 `next_edu_cloud.core_edu_*`),表前缀 `core_edu_*`**禁止跨库联表**[004 §12.1](../../../docs/architecture/004_architecture_impact_map.md#12-架构约束)
- **CDC 联动**MySQL binlog 已通过 Debezium 投递到 Kafka 的 `edu-cdc.next_edu_cloud.core_edu_grades` / `core_edu_exams` / `core_edu_homework` / `core_edu_attendance` topic由 data-ana 消费写 ClickHouse 宽表([known-issues §2.6](../../../docs/troubleshooting/known-issues.md) 已实施)
## 3. 我与外部的契约
- **暴露的 gRPC 契约**[core_edu.proto](../../../packages/shared-proto/proto/core_edu.proto),包名 `next_edu_cloud.core_edu.v1`,已定义待 P3 启用 server
- `ExamService`CreateExam / GetExam / ListExamsByClass / UpdateExam / DeleteExam
- `HomeworkService`AssignHomework / GetHomework / ListHomeworkByClass / SubmitHomework
- `GradeService`RecordGrade / GetGrade / ListGradesByStudent/Exam/Homework
- **缺口**:缺 `AttendanceService`coord 整改清单 #14P3 补全,[coord §6](../../../docs/architecture/coord-cross-review.md#6-裁决整改清单汇总)
- **发布的领域事件**[events.proto](../../../packages/shared-proto/proto/events.proto) + [outbox.publisher.ts TOPIC_MAP](../src/shared/outbox/outbox.publisher.ts)
> **coord 已仲裁**[coord §3.1](../../../docs/architecture/coord-cross-review.md#31-core-edu-教学事件-topic-命名双轨p0-最严重)topic 命名**统一为 `edu.teaching.<aggregate>.<action>`**,原代码中的 `edu.exam.events` / `edu.homework.events` / `edu.grade.events` / `edu.class.events` 风格**违规**P3 必须改 TOPIC_MAP。下表已按裁决后规范列出。
| 事件eventType | Topic裁决后 | 触发时机 | 消费者 | 当前状态 |
| ------------------- | ------------------------------------------ | ------------------ | ------------- | ---------- |
| exam.created | `edu.teaching.exam.created` | CreateExam 事务内 | msg、data-ana | ✅ 已发布 |
| exam.updated | `edu.teaching.exam.updated` | UpdateExam | msg | ✅ 已发布 |
| exam.deleted | `edu.teaching.exam.deleted` | DeleteExam | data-ana | ✅ 已发布 |
| exam.published | `edu.teaching.exam.published` | 考试发布(状态机) | msg、data-ana | ❌ P3 新增 |
| homework.assigned | `edu.teaching.homework.assigned` | AssignHomework | msg、data-ana | ✅ 已发布 |
| homework.submitted | `edu.teaching.homework.submitted` | SubmitHomework | data-ana、msg | ✅ 已发布 |
| homework.graded | `edu.teaching.homework.graded` | 教师批改完成 | msg、data-ana | ❌ P3 新增 |
| grade.recorded | `edu.teaching.grade.recorded` | RecordGrade | data-ana、msg | ✅ 已发布 |
| grade.updated | `edu.teaching.grade.updated` | 批改后修正 | data-ana | ❌ P3 新增 |
| class.transferred | `edu.org.class.created`(合并后归 org 域) | classes 合并后 | data-ana | ⚠️ 待合并 |
| attendance.recorded | `edu.teaching.attendance.recorded` | 考勤录入 | data-ana、msg | ❌ P3 新增 |
- **事件 schema 版本化**:所有事件 payload 必须含 `schema_version` 字段(默认 `"v1"`),消费端按版本处理([known-issues §1.3](../../../docs/troubleshooting/known-issues.md))。当前 outbox payload 仅含业务字段,**P3 必须补 `schema_version`**。
- **消费的事件**
- `edu.identity.user.created` / `edu.identity.user.updated` / `edu.identity.user.deleted`IAM初始化/同步教师默认班级关联,[004 §7.2](../../../docs/architecture/004_architecture_impact_map.md#72-事件-topic-分类) 已定义,**当前未消费**P3 待补)
- `edu.insight.mastery.updated`data-ana掌握度更新后 core-edu 可消费用于推荐个性化练习,[004 §8.3](../../../docs/architecture/004_architecture_impact_map.md#83-异步事件闭环))— P3 可选P4 强制
- **错误码前缀**`CORE_EDU_*`(见 [application-error.ts CoreEduErrorCode](../src/shared/errors/application-error.ts)子域exams/homework/grades/attendance**统一用 `CORE_EDU_*`**,不再细分 `EXAMS_` / `HOMEWORK_` / `GRADES_`[coord §5.5](../../../docs/architecture/coord-cross-review.md#55-p1-问题core-edu-子模块前缀) 仲裁)
- **响应信封**:必须遵循 [004 §11.5](../../../docs/architecture/004_architecture_impact_map.md#115-统一响应信封actionstate) ActionState 信封 `{success, data? | error: {code, message, details?, traceId?}}`GlobalErrorFilter 已注册
## 4. 我的技术栈
- 语言TypeScript 5.5+ESM 模式NestJS ESM 模式下相对 import 必须 `.js` 后缀)
- 框架NestJS 10
- ORMDrizzle ORMmysql2 driver直接 `db` 导出,**与 classes 的 `getDb()` 不一致**,需 P3 统一)
- 存储MySQL 8独占库 `core_edu_*` 表前缀、RedisP3 引入、Kafkakafkajsidempotent + transactionalId `core-edu-tx`
- **gRPC server**P3 启用(`@grpc/grpc-js` + `@bufbuild/protobuf`coord 已在 [buf.gen.yaml](../../../packages/shared-proto/buf.gen.yaml) 补 gRPC 插件,[coord 整改 #16](../../../docs/architecture/coord-cross-review.md#6-裁决整改清单汇总)
- **Temporal**P3 引入,仅试点 1 个工作流(考试发布编排:创建作业→通知,[pending-features P3](../../../docs/architecture/roadmap/pending-features.md#p3-核心教学阶段m7-m10)
- 可观测pino + prom-client已 4 指标http_requests_total / request_duration_seconds / outbox_pending / outbox_published_total+ OTel auto-instrumentations已具备
## 5. 我的阶段归属
- **P3 核心教学**:考试全生命周期 + Outbox + Kafka 事件落地
- **退出标准**[pending-features P3](../../../docs/architecture/roadmap/pending-features.md#p3-核心教学阶段m7-m10)):教师创建考试 → 发布 → 学生作答 → 教师批改 → 事件到 Kafka → 成绩统计更新 → 全链路可观测
- **P3 关键功能**
1. CoreEdu 服务考试/作业/成绩域 CRUD + 批改业务编排 + Outbox 事件发布
2. MySQL schemaexams / exam_questions / homework_assignments / homework_submissions / homework_answers / grade_records / outbox_events**当前 schema 仅 4 表**,缺 exam_questions / homework_submissions / homework_answersP3 必须补全)
3. Outbox 模式 + Outbox relay worker**当前 relay 在 NestJS 进程内 setInterval 5spending-features 提及"独立 Go 服务 `services/outbox-relay/`"是远期目标P3 保留进程内模式**
4. Kafka topics`edu.teaching.exam.published` / `edu.teaching.homework.graded` / `edu.teaching.grade.recorded`(按 coord 仲裁后的命名)
5. Teacher BFF 扩展(考试/作业/成绩的查询与 mutation
6. teacher-portal 扩展(考试创建/作业批改/成绩查看页面)
7. student-portal 微前端(学生作答作业页面)
8. Temporal 试点 1 个工作流(考试发布编排)
9. **gRPC server 启用(端口 50053**
10. **排课/考勤数据模型course/lesson/schedule/attendance 四表)+ AttendanceService proto 补全**
- **依赖上游**P1 classes 黄金模板、P2 iam用户身份 + 权限 + DataScope
- **下游依赖方**student-bffP3、parent-bffP4查看子女成绩/考勤、data-ana消费 CDC + 领域事件、msg消费事件触发通知、content接收教学内容变更事件
## 6. 我需要对齐的黄金模板项(对照 classes 服务)
- [x] 权限装饰器 `@RequirePermission`exams.controller 全覆盖;需核对 homework/grades controller
- [x] 错误码前缀 `CORE_EDU_*`(已用 [CoreEduErrorCode 枚举](../src/shared/errors/application-error.ts)
- [x] logger / metrics / tracer 三支柱
- [x] `/healthz` 健康检查
- [x] `/readyz`(已实现 DB SELECT 1 探针,[health.controller.ts](../src/shared/health/health.controller.ts) Drizzle `db.execute(sql\`SELECT 1\`)`**需补 Kafka 连接探针 + Redis ping 探针**
- [x] 优雅关闭 SIGTERMmain.ts 已处理 outboxPublisher.stop + disconnectKafka
- [ ] 测试覆盖率 ≥ 80%**当前 0%**,无测试文件,仅 vitest.config.ts 配置就绪)
- [ ] Dockerfile 多阶段构建(需核对)
- [ ] Zod 输入验证(**当前 Controller 直接接收 body未 Zod 校验**classes 用 zod schema
- [x] GlobalErrorFilter 统一兜底(响应信封 ActionState 对齐,[coord §5.7](../../../docs/architecture/coord-cross-review.md#57-p2-问题错误信封结构不一致)
- [x] Outbox 模式(事务内写业务表 + outbox 表,独立 publisher 投递,**TOPIC_MAP 命名违规待修正**
- [ ] **gRPC server 实现**P3 启用,端口 50053proto 已定义)
- [ ] **ActionState 信封 traceId**GlobalErrorFilter 已输出 traceId需验证
- [ ] **DataScope 下推**004 §5.3 要求 Repository 层根据 dataScope 注入 WHERE当前未实现
- [ ] **Drizzle 访问方式统一**core-edu 用 `export const db`classes 用 `getDb()` 函数式,需 P3 统一为 `getDb()`
- [ ] **kafka.ts 用 logger 替代 console.log/warn**[config/kafka.ts](../src/config/kafka.ts) L20/L22 违反 [known-issues §1.4](../../../docs/troubleshooting/known-issues.md) "禁止 console.*" 规则)
---
## 服务审计表 — ai08core-edu
> 对照 [黄金模板 classes 服务](../../classes/src/),审计已实现的 core-edu 服务。状态:✅ 达标 / ⚠️ 部分 / ❌ 缺失
| 服务 | 权限装饰器 | 错误码前缀 | logger | metrics | tracer | /healthz | /readyz | 优雅关闭 | 测试覆盖率 | Dockerfile | gRPC server | ActionState |
| -------- | -------------------------------------- | --------------- | -------------------------------- | --------------------- | ------------ | -------- | ------------------------------------- | -------- | ---------- | ---------- | ---------------- | ----------- |
| core-edu | ✅ `@RequirePermission(EXAM_*)` 全覆盖 | ✅ `CORE_EDU_*` | ⚠️ pinokafka.ts 仍用 console | ✅ prom-client 4 指标 | ✅ OTel auto | ✅ | ⚠️ DB SELECT 1缺 Kafka/Redis 探针) | ✅ | 0% ❌ | 待核对 | ❌ P3 启用 50053 | ✅ 已对齐 |
### 审计发现的关键差距P3 阶段 2 设计需解决)
> ai03 原列 12 项 + ai08 审计新增 8 项 = 20 项
1. ❌ 考试生命周期状态机缺失(当前仅 `draft` 初值,无 `published → in_progress → grading → graded → archived` 转换与校验)
2. ❌ 作业状态机不完整(仅 `assigned → submitted`,缺 `graded`pending-features 要求 `HomeworkGraded` 事件)
3. ❌ 成绩录入无业务校验(不校验 exam/homework 是否存在、score 是否在 totalScore 范围内、是否重复录入)
4. ❌ 作业提交高并发优化缺失([004 §9.2](../../../docs/architecture/004_architecture_impact_map.md#92-高并发提交) 要求 Redis 分布式锁 + 排队)
5. ❌ 无 `grade.updated` / `homework.graded` 事件触发点proto 已定义service 未实现)
6. ❌ 未消费 IAM `user.created` / `user.updated` / `user.deleted` 事件(初始化教师默认关联)
7. ⚠️ Drizzle `db` 直接导出 vs classes 的 `getDb()` 函数式 — **不一致**,建议统一为 `getDb()`
8. ⚠️ [kafka.ts](../src/config/kafka.ts) 用 `console.log`/`console.warn`,应改用结构化 logger
9. ⚠️ classes 模块在 core-edu 仅有 `classes.module.ts` 占位,**P3 待合并**classes 服务代码迁入 + 删除独立 services/classes
10. ⚠️ 入口仍为 RESTproto gRPC 契约已定义但未接入 `@grpc/grpc-js` + buf generate 代码
11. ❌ 无 Zod 输入验证Controller 直接接收 `body: CreateExamInput`,未走 zod schema
12. ❌ 无测试
13.**TOPIC_MAP 命名违规**coord 已仲裁统一为 `edu.teaching.<aggregate>.<action>`,当前代码用 `edu.exam.events` 等表名分组风格,[coord §3.1](../../../docs/architecture/coord-cross-review.md#31-core-edu-教学事件-topic-命名双轨p0-最严重)
14.**排课/考勤数据模型缺失**pending-features P3 要求 course/lesson/schedule/attendance 四表,当前 core-edu 仅 exams/homework/grades/outbox 四表)
15.**core_edu.proto 缺 AttendanceService**coord 整改 #14P3 必须补全)
16.**DataScope 下推未实现**[004 §5.3](../../../docs/architecture/004_architecture_impact_map.md#53-datascop-6-级数据范围) 要求 Repository 层根据 dataScope 注入 WHERE当前 PermissionGuard 仅做粗粒度角色判断,未做行级数据过滤)
17.**事件 schema_version 字段缺失**[known-issues §1.3](../../../docs/troubleshooting/known-issues.md) 要求 Kafka 事件带 `schema_version`,当前 outbox payload 仅含业务字段)
18.**Temporal 工作流未引入**pending-features P3 要求试点 1 个工作流:考试发布编排,当前未集成)
19. ⚠️ **outbox schema 缺少 event_id 字段**(消费端幂等去重要求 event_id当前 outbox 仅用 id 作主键,但 event_id 应独立于 outbox id 以支持重投递幂等)
20.**成绩计算公式未配置化**ai-allocation §5 ai08 设计重点要求支持加权/平均/自定义公式,当前仅原始 score 存储)
### 跨模块契约对齐ai08 接管后核对 coord 仲裁结果)
| 待确认项 | coord 仲裁结论 | 状态 |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| iam `user.created` 等事件 topic | `edu.identity.user.created` / `.updated` / `.deleted`[004 §7.2](../../../docs/architecture/004_architecture_impact_map.md#72-事件-topic-分类) | ✅ 已仲裁core-edu P3 实现消费端 |
| core-edu 端口 3004 + gRPC 50053 | 不冲突,已纳入 [coord 全局端口矩阵](../../../docs/architecture/coord-cross-review.md#43-全局端口矩阵coord-裁决基线已同步至-004-12) | ✅ 已仲裁 |
| Kafka topic 命名 | **统一为 `edu.teaching.<aggregate>.<action>`**[coord §3.1](../../../docs/architecture/coord-cross-review.md#31-core-edu-教学事件-topic-命名双轨p0-最严重) | ✅ 已仲裁core-edu P3 修 TOPIC_MAP |
| data-ana 消费 core-edu 事件 | 消费 `edu.teaching.exam.created` / `homework.submitted` / `grade.recorded` + CDC topics | ✅ ai06 已确认data-ana 已实施 CDC 消费 |
| msg 消费 core-edu 事件 | 消费 `edu.teaching.exam.created` / `homework.assigned` / `grade.recorded` 触发通知 | ⚠️ 待 ai05 在 msg 02 文档确认消费契约 |
| proto 包名规范 | 保持 `next_edu_cloud.core_edu.v1`[coord §2.1](../../../docs/architecture/coord-cross-review.md#21-proto-包名规范冲突p0-全局) | ✅ 已仲裁 |
| 错误码前缀 | `CORE_EDU_*` 统一(不再细分 `EXAMS_`/`HOMEWORK_`/`GRADES_`[coord §5.5](../../../docs/architecture/coord-cross-review.md#55-p1-问题core-edu-子模块前缀) | ✅ 已仲裁 |
| core_edu.proto AttendanceService 缺失 | P3 补全([coord 整改 #14](../../../docs/architecture/coord-cross-review.md#6-裁决整改清单汇总) | ❌ 待 ai08 P3 补全 proto + service 实现 |
---
## 下一步(阶段 2 入口)
ai08 进入阶段 2按 [ai-allocation.md §5 ai08 设计重点](../../../docs/architecture/ai-allocation.md) 产出模块架构设计文档 `02-architecture-design.md`
- **core-edu 模块架构设计**
- classes 黄金模板对齐Drizzle `getDb()` 统一 + Zod + 测试 + Dockerfile 多阶段)
- 考试生命周期状态机(草稿 → 已发布 → 作答中 → 批改中 → 已出分 → 已归档)
- Outbox 事件定义与发布(补全 `exam.published` / `homework.graded` / `grade.updated` / `attendance.recorded`TOPIC_MAP 重命名为 `edu.teaching.*`payload 补 `schema_version` + `event_id`
- 成绩计算公式与配置化(加权/平均/自定义公式)
- 作业提交高并发优化Redis 分布式锁 + 排队机制)
- 排课/考勤数据模型course/lesson/schedule/attendance 四表)+ AttendanceService proto 补全
- 与 Kafka 的 Relay Worker 轮询逻辑(保留进程内模式,远期迁出独立 Go 服务)
- gRPC server 启用(端口 50053
- DataScope 下推Repository 层 WHERE 注入)
- Temporal 工作流试点(考试发布编排)
- 消费 IAM 事件user.created/updated/deleted
阶段 2 设计需先解决上述 20 项差距与跨模块契约对齐。
---
**AI Agent**: ai08 (core-edu)
**Coordinator**: coord-ai
**Branch**: 单仓库并行模式(直接 push main