# 模块理解确认书 — content

> AI 标识：ai05（初稿）→ ai09（复核与阶段 2 接手）
> 负责模块：content（P4）— 按 [ai-allocation.md §3.2](../../../docs/architecture/ai-allocation.md) 最新分配，content 由 ai09 专责
> 阶段：架构设计外包 · 阶段 1（全局理解，ai05 初稿）+ ai09 复核
> 日期：2026-07-09（初稿）/ 2026-07-09（ai09 复核）
> 关联文档：[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-cross-review.md](../../../docs/architecture/coord-cross-review.md)、[known-issues.md](../../../docs/troubleshooting/known-issues.md)

---

## 1. 我在架构中的位置

- **层级**：业务微服务层（L5），DDD 限界上下文
- **业务领域**：D4 内容资源领域（004 §1.1b）
- **上游**（谁调用我）：
  - teacher-bff（3003）：教学场景聚合，教师查教材/知识点/题库
  - student-bff（学习场景，P3 起）：学生查学习路径、知识点前置
  - ai（Python，P5）：gRPC 查询知识点/题库用于 AI 出题（004 §4.1 `AI -.gRPC.-> Content`，§9.3 AI 辅助出题流程）
- **下游**（我调用谁）：
  - MySQL（写模型主库，独占）
  - Neo4j（知识图谱，前置依赖图）
  - Elasticsearch（题库全文检索，P4 后续补充，当前未实现）
- **通信方式**：
  - 当前：HTTP REST（Controller，无 gRPC controller）
  - 目标态（004 §4.1 / pending-features P4）：gRPC 暴露 `TextbookService` + `KnowledgeGraphService`
  - Kafka：消费 core-edu 教学内容变更通知（004 §4.1 `CoreEdu -.事件.-> Content`）；发布 `edu.content.question.published`（004 §7.2）
- **端口**：3005（见 [content env.ts](../src/config/env.ts)）

## 2. 我的限界上下文

- **聚合职责**：管理 Textbook（教材）、Chapter（章节）、KnowledgePoint（知识点）、Question（题库）四个聚合
- **我的数据属于**：D4 内容资源领域
- **我不负责**：
  - 不负责学情分析（D6，由 data-ana 承载）
  - 不负责考试/作业/成绩（D3，由 core-edu 承载）
  - 不负责通知分发（D5，由 msg 承载）
  - 不直接访问 core-edu / iam / msg 的数据库
- **现有骨架领域模块**（4 个，见 [content/src](../src)）：
  - `textbooks/`：教材 CRUD（5 端点）
  - `chapters/`：章节 CRUD（5 端点，按 textbook 查询）
  - `knowledge-points/`：知识点 CRUD + Neo4j 知识图谱（7 端点，含前置链路查询/添加）
  - `questions/`：题库 CRUD（5 端点，4 种题型校验）

## 3. 我与外部的契约

- **消费的 proto message**（从 shared-proto）：
  - 无直接消费其他服务 proto；通过 Kafka 事件接收 core-edu 教学内容变更（事件契约见 `events.proto`）
- **暴露的契约**（见 [content.proto](../../../packages/shared-proto/proto/content.proto)，包名 `next_edu_cloud.content.v1`）：
  - `TextbookService`：CreateTextbook / GetTextbook / ListTextbooks
  - `KnowledgeGraphService`：GetPrerequisites / GetLearningPath
  - **当前实现均为 REST，gRPC controller 未实现**（proto 已定义待迁移）
- **事件契约**：
  - 发布：`edu.content.question.published`（题库新增/发布，消费者 AI、ES，见 004 §7.2）
  - 消费：core-edu 教学内容变更事件（004 §4.1，具体 topic 待 core-edu ai03 设计确认）
- **错误码前缀**：`CONTENT_*`（CONTENT_VALIDATION_ERROR / NOT_FOUND / PERMISSION_DENIED / CONFLICT / BUSINESS_ERROR / DATABASE_ERROR / INTERNAL_ERROR，见 [application-error.ts](../src/shared/errors/application-error.ts)）
- **权限点**（16 个，见 [permission.guard.ts](../src/middleware/permission.guard.ts)）：
  - `CONTENT_TEXTBOOK_{CREATE,READ,UPDATE,DELETE}`
  - `CONTENT_CHAPTER_{CREATE,READ,UPDATE,DELETE}`
  - `CONTENT_QUESTION_{CREATE,READ,UPDATE,DELETE}`
  - `CONTENT_KNOWLEDGE_POINT_{CREATE,READ,UPDATE,DELETE}`

## 4. 我的技术栈

- 语言：TypeScript 5.6（ESM 模式，相对 import 带 `.js` 后缀）
- 框架：NestJS 10
- ORM：Drizzle ORM 0.31 + mysql2 3.11
- 知识图谱：neo4j-driver 5.23（PREREQUISITE_OF 关系，Cypher 查询深度 1..5）
- 全文检索：Elasticsearch（**待引入**，env.ts 预留 ES_URL 但 package.json 未装 @elastic/elasticsearch）
- 可观测：pino logger + prom-client metrics + OpenTelemetry tracer（三支柱已具备）
- 消息总线：Kafka（**待引入**，pending-features P4 未明确要求 content 发事件，但 004 §7.2 列了 `edu.content.question.published`）

## 5. 我的阶段归属

- **P4 内容分析阶段**（pending-features §P4）：
  - 教材/章节/知识点 CRUD（仅 CRUD，不实现检索）+ 知识图谱查询（Neo4j）+ 题库 CRUD（不实现检索）
  - MySQL schema：textbooks / chapters / knowledge_points / questions
  - Neo4j 数据：知识点前置依赖图（从 MySQL 同步）
  - CDC 链路：Debezium 监听 MySQL binlog → Kafka → data-ana 消费写 ClickHouse
- **退出标准**：教师查看知识图谱前置依赖（Neo4j 秒级返回）→ 学生查看学情诊断（ClickHouse 宽表 5s 内返回）→ CDC 链路延迟 < 5s
- **依赖上游**：P1 黄金模板 classes（横切关注点对齐）、P3 core-edu（教学内容变更事件，待 ai03 设计确认 topic）

## 6. 我需要对齐的黄金模板项（对照 classes 服务）

- [x] 权限装饰器 `@RequirePermission`（16 个 CONTENT_* 权限点，全部 Controller 方法已覆盖）
- [x] 错误码前缀统一（`CONTENT_*`）
- [x] logger / metrics / tracer 三支柱（已具备）
- [x] `/healthz` 健康检查（HealthModule 已注册）
- [⚠️] `/readyz`（**仅检查 DB `SELECT 1`，未检查 Neo4j 连通性**，Neo4j 故障时仍返回 ok）
- [x] 优雅关闭 SIGTERM（main.ts 已处理：closeNeo4j → closeDb → shutdownTracer）
- [ ] 测试覆盖率 ≥ 80%（**当前 0%**，无测试文件）
- [x] Dockerfile 多阶段构建（已具备）
- [⚠️] Zod 输入验证（questions 用 service 层手动 if 校验抛 ValidationError，**非 Controller 层 schema.parse**）
- [x] GlobalErrorFilter 统一兜底

## 7. 现有骨架差距与待决策（提请 coord 仲裁）

| #   | 差距                                                                                                                                                                             | 影响                                                                   | 提请决策                                                                      |
| --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| C1  | **ES 完全未实现**：env.ts 预留 ES_URL 但无 @elastic/elasticsearch 依赖、无 config/elasticsearch.ts、无 service 调用                                                              | P4 退出标准要求题库检索，pending-features 注明"P4 仅 CRUD，P5 引入 ES" | 确认 content 的 ES 检索归属 P4 还是 P5（004 §2.2 列 ES 使用者为 Content、AI） |
| C2  | **无 Outbox / Kafka**：骨架无 shared/outbox/，无 Kafka producer/consumer                                                                                                         | 004 §7.2 列 `edu.content.question.published` 事件需发布                | 确认 content 是否需 Outbox（iam 无 Outbox，core-edu 有）                      |
| C3  | **README 与实现脱节**：README 声称 `TextbooksService.createKnowledgeGraph` 和 `getPrerequisites`，源码中 createKnowledgeGraph 不存在，getPrerequisites 在 KnowledgePointsService | 文档误导                                                               | 阶段 2 设计需同步修正 README                                                  |
| C4  | **gRPC 未实现**：proto 定义了 TextbookService/KnowledgeGraphService，但无 gRPC controller                                                                                        | pending-features P4 未强制 gRPC，004 §4.1 目标态 gRPC                  | 确认 P4 是否启用 gRPC（ai03 提请统一决策）                                    |
| C5  | **schema 定义分散**：textbooks.schema.ts 定义 3 张表（textbooks/chapters/knowledgePoints），chapters/knowledge-points schema 仅 re-export；questions.schema.ts 独立              | 维护成本                                                               | 阶段 2 设计统一 schema 归属                                                   |
| C6  | **DB 连接模式与 iam 不一致**：content 用模块级 `const db`，iam 用 `getDb()` 函数式懒加载                                                                                         | 测试 mock 困难                                                         | coord 已在 known-issues 记录"db 常量导出对齐黄金模板"，需确认统一方向         |
| C7  | **表时间戳不统一**：textbooks/questions 有 created_at+updated_at，chapters/knowledge_points 无时间戳                                                                             | 审计追踪缺失                                                           | 阶段 2 设计补齐                                                               |
| C8  | **无外键约束**：questions.knowledge_point_id → knowledge_points.id 等无 Drizzle 外键                                                                                             | 引用完整性靠应用层                                                     | 阶段 2 设计评估是否加外键                                                     |
| C9  | **addPrerequisite 降级策略不一致**：safeCreateNode 非阻塞（Neo4j 失败仅 warn），addPrerequisite 在 Neo4j 不可用时抛 InternalError                                                | 行为不一致                                                             | 阶段 2 设计统一降级策略                                                       |
| C10 | **proto 包名**：实际 `next_edu_cloud.content.v1`，project_rules §5 规定 `edu.content.v1`                                                                                         | 命名规范不一致                                                         | **coord 仲裁**（ai03 已提请）                                                 |

---

## 服务审计表 — ai05（content 部分）

> 审计标准对照 [project_rules §3](../../../.trae/rules/project_rules.md) 与 [known-issues §2.2 classes 黄金模板](../../../docs/troubleshooting/known-issues.md)

| 服务    | 权限装饰器       | 错误码前缀     | logger  | metrics        | tracer                          | /healthz | /readyz             | 优雅关闭              | 测试覆盖率 | Dockerfile |
| ------- | ---------------- | -------------- | ------- | -------------- | ------------------------------- | -------- | ------------------- | --------------------- | ---------- | ---------- |
| content | ✅ 16 端点全覆盖 | ✅ `CONTENT_*` | ✅ pino | ✅ prom-client | ✅ OTel + auto-instrumentations | ✅       | ⚠️ 仅 DB 不查 Neo4j | ✅ closeNeo4j→closeDb | 0%         | ✅         |

---

## 跨模块契约对齐提请（coord 交叉审查）

### 接口一致性检查（content 相关）

| 本服务声明                                                | 对方服务声明                                      | 是否匹配  | 备注                        |
| --------------------------------------------------------- | ------------------------------------------------- | --------- | --------------------------- |
| ai05 content: 暴露 KnowledgeGraphService.GetPrerequisites | ai06 ai: 调 content 查知识点（004 §9.3）          | ⚠️ 待确认 | ai06 设计文档需确认调用签名 |
| ai05 content: 暴露 TextbookService.ListTextbooks          | ai03 teacher-bff: 聚合 content 查教材（004 §4.1） | ⚠️ 待确认 | ai03 设计文档需确认调用     |
| ai05 content: 发布 `edu.content.question.published`       | ai06 ai: 消费题库事件（004 §7.2 消费者 AI）       | ⚠️ 待确认 | ai06 设计需确认是否消费     |

### 全局冲突检查（content 相关）

| 检查项               | 检查结果            | 备注                                                                                                 |
| -------------------- | ------------------- | ---------------------------------------------------------------------------------------------------- |
| 端口不冲突           | ✅ content 3005     | 与 iam(3002)/classes(3001)/teacher-bff(3003)/core-edu(3004)/data-ana(3006)/msg(3007)/ai(3008) 不冲突 |
| Topic 不重复         | ⚠️ 待汇总           | content 发布 `edu.content.question.published`                                                        |
| 错误码前缀不重叠     | ✅ `CONTENT_*` 唯一 | 与 iam `IAM_*` / core-edu `CORE_EDU_*` / msg `MSG_*` 不重叠                                          |
| Proto message 不遗漏 | ⚠️ 待确认           | content.proto 缺 Update/Delete/分页（对比 classes.proto 有 page_token）                              |
| proto 包名规范       | ⚠️ 不一致           | 实际 `next_edu_cloud.<domain>.v1`，规则要求 `edu.<domain>.v1`，**提请 coord 仲裁**（ai03 已提请）    |

### 待 coord 仲裁的决策项（content 相关）

1. **proto 包名统一**：`next_edu_cloud.*` vs `edu.*`（影响全部 proto，需 coord 决策）
2. **gRPC 启用时机**：P4/P5 是否启用 gRPC controller，还是继续 REST（影响 content/msg/iam/core-edu 全部服务）
3. **content ES 检索归属**：P4（pending-features 注明"P4 仅 CRUD，P5 引入 ES"）vs 004 §2.2（列 ES 使用者 Content、AI）—— 需明确 content 何时引入 ES
4. **content Outbox**：是否需要（004 §7.2 列 content 发事件，但 pending-features P4 未要求）

---

## 下一步

1. **等待 coord 审核本确认书**（跨模块契约对齐 + 仲裁项）
2. coord 放行后进入**阶段 2：模块架构设计文档**，按 ai-allocation.md §7 模板产出：
   - content 模块架构设计文档（含 Neo4j 图模型、ES 索引 mapping、题库 CRUD API、与 ai 的 gRPC 接口、教材/章节结构树）
3. 阶段 2 设计完成后同步更新 README（修正 §C3 文档脱节问题）

---

## ai09 复核记录（2026-07-09）

ai05 初稿覆盖了位置/限界上下文/契约/技术栈/黄金模板对齐/差距 10 项，作为阶段 1 的骨架是合格的。ai09 在接手阶段 2 前，对初稿做以下**复核与补强**，依据为 [coord-cross-review.md](../../../docs/architecture/coord-cross-review.md) 已仲裁结论与 [004 §4.2/§7.2/§11.2/§12.2](../../../docs/architecture/004_architecture_impact_map.md) 最新修订：

### A. 已仲裁项状态更新（原 C 列待决策项 → 已裁决）

| 原编号 | 原待决策              | coord 裁决                                                                                                                      | 状态                                   |
| ------ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
| C2     | content 是否需 Outbox | **需要**。004 §7.2 列 `edu.content.question.published` 为领域事件，004 §12.2 规定领域事件强制 Outbox 模式（业务事务事件不豁免） | ✅ 已裁决：P4 必须引入 Outbox          |
| C4     | gRPC 启用时机         | **P4 启用**。004 §4.2 gRPC 启用阶段矩阵明确：P4 content + data-ana 启用 gRPC server                                             | ✅ 已裁决：P4 必须实现 gRPC controller |
| C10    | proto 包名规范        | **保持现状 `next_edu_cloud.content.v1`**。coord 已修订 project_rules §5 与 004 §11.2                                            | ✅ 已裁决                              |

### B. 初稿遗漏项（必须在阶段 2 补全）

| #   | 遗漏                                                      | 依据                                                                                                                               | 阶段 2 处理                                                                             |
| --- | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| L1  | **教材/章节结构树缺 section 层级**                        | [ai-allocation §5 ai09 任务](../../../docs/architecture/ai-allocation.md)：textbook → chapter → section → knowledge-point 四级结构 | 数据模型补 `content_sections` 表                                                        |
| L2  | **题库批量导入 Excel/CSV 完整未设计**                     | ai-allocation §5 明确要求"题库 CRUD 完整 API（含批量导入 Excel/CSV）"                                                              | API 设计补 `POST /questions/batch-import` + 异步任务 + 模板下载                         |
| L3  | **知识图谱可视化数据 API 缺失**                           | ai-allocation §5 明确要求"知识图谱可视化数据 API"                                                                                  | API 设计补 `GET /knowledge-graph/visualization` 返回 nodes/edges 结构                   |
| L4  | **与 ai12（ai 服务）的 gRPC 接口未细化**                  | ai-allocation §5 明确要求"查询知识点/题库用于 AI 出题" + 004 §9.3 AI 辅助出题流程                                                  | 契约设计补 `QuestionBankService.ListQuestions`/`SearchQuestions`/`BatchCreateQuestions` |
| L5  | **ES 索引 mapping 完整未设计**                            | ai-allocation §5 明确要求"ES 索引 mapping 设计（题库全文检索 + 标签过滤 + 难度/年级 facet）"                                       | 阶段 2 完整设计 mapping，但实现归属 P5（pending-features P5 才引入 ES）                 |
| L6  | **readyz 未检查 Neo4j 连通性**                            | 阶段 1 §C 已识别但未决议                                                                                                           | 阶段 2 横切关注点补 Neo4j 健康检查                                                      |
| L7  | **题目审核状态机未设计**                                  | 长远考虑：教师录入/AI 生成/审核/发布/归档的全生命周期                                                                              | 阶段 2 领域模型补 Question.status 状态机                                                |
| L8  | **题库版本化与协作编辑未考虑**                            | 长远考虑：教材版本变更、多人协作出题                                                                                               | 阶段 2 数据模型补 `version`/`updated_by`/`lock_version` 字段                            |
| L9  | **DataScope 下推未在 Repository 体现**                    | 004 §5.3 DataScope 6 级需 Repository 注入 WHERE                                                                                    | 阶段 2 Repository 设计补 DataScope 下推                                                 |
| L10 | **题目/知识点与学科年级的多对多关联未明确**               | 跨教材/跨学科复用题目需多对多                                                                                                      | 数据模型补 `content_question_grades`/`content_kp_grades` 关联表                         |
| L11 | **AI 生成题目回写契约**                                   | 004 §9.3：教师审核后入库 → content.CreateQuestions                                                                                 | 契约设计补 `QuestionBankService.BatchCreateQuestions`                                   |
| L12 | **知识点掌握度反查（data-ana → content 反向查询）未设计** | 004 §8.3 闭环：掌握度更新后推荐练习                                                                                                | 契约补 `KnowledgeGraphService.GetRecommendations(mastery)`                              |

### C. 长远架构必须铺垫的方面（ai09 在阶段 2 重点设计）

| 维度                   | 铺垫点                                                         | 理由                                     |
| ---------------------- | -------------------------------------------------------------- | ---------------------------------------- |
| 多版本教材并存         | textbook.version 字段 + 教材版本切换不破坏题库引用             | K12 教材迭代周期长但必须支持新旧版本共存 |
| 跨学科知识图谱         | Neo4j 节点带 `subject_id`，未来跨学科知识关联（数学→物理前置） | 长远支撑综合题、跨学科出题               |
| 题目去重/相似度        | 设计 content 字段长度 + 未来 embedding 字段占位                | AI 批量出题必然带来重复检测需求          |
| ES 与 MySQL 双写一致性 | 阶段 2 设计 CDC/Outbox → ES 投递方案（P5 落地）                | 避免 P5 引入 ES 时再重构数据流           |
| 知识图谱版本控制       | Neo4j 节点带 `version`/`textbook_id` 属性                      | 教材版本切换时图谱可追溯                 |
| 国际化（i18n）         | 题目/知识点 content 字段预留 `lang` 维度                       | 未来支持少数民族语言版本                 |
| 题库审核工作流         | Question.status 状态机 + 审核记录表                            | 接入 Temporal 工作流时无需重构           |
| gRPC Streaming 出题    | 契约预留 `StreamGenerateQuestions` 方法占位                    | AI 流式出题未来需求                      |

---

**AI Agent**: ai09 (content)
**Coordinator**: coord-ai
**Branch**: 单仓库并行模式（直接 push main）
**阶段 1 状态**: ✅ ai05 初稿 + ai09 复核补强完成，进入阶段 2
