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.设计规格文档
This commit is contained in:
SpecialX
2026-07-10 12:58:22 +08:00
parent 2a2a56f541
commit faaaf29f67
120 changed files with 23201 additions and 2 deletions

View File

@@ -0,0 +1,191 @@
# 模块理解确认书 — msg
> AI 标识ai05初版→ ai10复核修订按 ai-allocation.md §3.2 重新分配)
> 负责模块msgP5
> 阶段:架构设计外包 · 阶段 1全局理解
> 初版日期2026-07-09
> 复核修订日期2026-07-09ai10 接手后修正 3 处失实条目 M2/M8/M12并补充 ai-allocation §5 缺失项)
> 关联文档:[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)、[known-issues.md](../../../docs/troubleshooting/known-issues.md)
---
## 1. 我在架构中的位置
- **层级**业务微服务层L5DDD 限界上下文
- **业务领域**D5 沟通通知领域004 §1.1b
- **上游**(谁调用我):
- teacher-bff / student-bff / parent-bff聚合层调 msg 查询用户通知列表、发送通知
- api-gatewayREST 转发通知请求
- Kafka消费 core-edu / iam 事件触发通知004 §4.1 `CoreEdu -.事件.-> Msg``IAM -.事件.-> Msg`
- **下游**(我调用谁):
- MySQL写模型主库独占
- Elasticsearch全文检索已实现 safeSearch
- push-gatewaygRPC 推送通道004 §4.1 `PushGW → Msg`,当前用 fetch POST /internal/push 降级)
- **通信方式**
- 当前HTTP RESTController无 gRPC controller
- 目标态004 §4.1 / pending-features P5gRPC 暴露 `NotificationService`
- Kafka消费 core-eduExamPublished/HomeworkGraded/GradeRecorded、iamUserRegistered事件004 §7.3
- **端口**3007见 [msg env.ts](../src/config/env.ts)
## 2. 我的限界上下文
- **聚合职责**:管理 Notification通知聚合 + NotificationPreference用户通知偏好
- **我的数据属于**D5 沟通通知领域
- **我不负责**
- 不负责 WebSocket 长连接管理(由 push-gateway 承载)
- 不负责业务数据变更(仅消费事件触发通知)
- 不直接访问 core-edu / iam 的数据库
- **现有骨架领域模块**1 个,见 [msg/src](../src)
- `notifications/`:通知 CRUD + ES 全文检索 + Push Gateway 推送 + 用户偏好6 端点)
## 3. 我与外部的契约
- **消费的 proto message**(从 shared-proto
- 消费 `events.proto` 的事件 messageClassEvent/ExamEvent/HomeworkEvent/GradeEvent
- **events.proto 当前无 NotificationEvent**,若 msg 发事件需补充
- **暴露的契约**(见 [msg.proto](../../../packages/shared-proto/proto/msg.proto),包名 `next_edu_cloud.msg.v1`
- `NotificationService`SendNotification / ListNotifications / MarkAsRead / SearchNotifications
- **当前实现均为 RESTgRPC controller 未实现**
- **事件契约**
- 消费004 §7.2 / §7.3
- `edu.identity.user.created` / `edu.identity.user.updated`IAM 发msg 发欢迎通知)
- `edu.teaching.exam.published`core-edu 发msg 推送考试通知给学生)
- `edu.teaching.assignment.submitted`core-edu 发msg 通知教师)
- `edu.teaching.grade.recorded`core-edu 发msg 通知学生)
- `edu.insight.mastery.updated`data-ana 发msg 触发预警)
- 发布无明确pending-features 未要求 msg 发事件)
- **错误码前缀**`MSG_*`MSG_VALIDATION_ERROR / NOT_FOUND / PERMISSION_DENIED / CONFLICT / BUSINESS_ERROR / DATABASE_ERROR / INTERNAL_ERROR见 [application-error.ts](../src/shared/errors/application-error.ts)
- **权限点**3 个,见 [permission.guard.ts](../src/middleware/permission.guard.ts)
- `MSG_NOTIFICATION_SEND``MSG_NOTIFICATION_READ``MSG_NOTIFICATION_MANAGE`
## 4. 我的技术栈
- 语言TypeScript 5.6ESM 模式)
- 框架NestJS 10
- ORMDrizzle ORM 0.31 + mysql2 3.11
- 全文检索:@elastic/elasticsearch 8.15(已实现 safeIndex/safeSearch**无 mapping 定义**,依赖动态 mapping
- 消息总线kafkajs 2.2**已装依赖但无 consumer/producer 代码**env.ts 有 KAFKA_BROKERS 默认值)
- 推送fetch POST 到 push-gateway `/internal/push`降级模式PUSH_GATEWAY_URL 未配置或失败时跳过)
- 幂等去重Redis**env.ts 预留 REDIS_URL 但无 redis 客户端依赖**pending-features P5 要求 event_id 去重)
- 可观测pino + prom-client + OpenTelemetry三支柱已具备
## 5. 我的阶段归属
- **P5 沟通与 AI 阶段**pending-features §P5
- 会话/消息 CRUD + 调 Push Gateway 推送 + 通知偏好
- 多渠道(站内/SMS/邮件/微信),沿用旧项目 dispatcher 模式
- Elasticsearch 题库全文检索(从 MySQL 同步)
- **退出标准**:教师发广播通知 → 全在线学生实时收到Push Gateway→ AI 辅助出题流式返回 → 题库全文检索 < 200ms
- **依赖上游**P1 黄金模板 classes、P3 core-edu事件来源、P5 push-gateway推送通道ai01 设计、P5 ai无直接依赖
## 6. 我需要对齐的黄金模板项(对照 classes 服务)
- [x] 权限装饰器 `@RequirePermission`3 个 MSG_* 权限点,全部 Controller 方法已覆盖)
- [x] 错误码前缀统一(`MSG_*`
- [x] logger / metrics / tracer 三支柱(已具备)
- [x] `/healthz` 健康检查HealthModule 已注册)
- [⚠️] `/readyz`**仅检查 DB `SELECT 1`,未检查 ES 连通性**ES 故障时仍返回 ok
- [x] 优雅关闭 SIGTERMmain.ts 已处理app.close → closeEs → closeDb → shutdownTracer
- [ ] 测试覆盖率 ≥ 80%**当前 0%**,无测试文件)
- [x] Dockerfile 多阶段构建(已具备)
- [x] Zod 输入验证Controller 用 `schema.parse(body)`**GlobalErrorFilter 已识别 ZodError 返回 400**,见 [global-error.filter.ts](../src/shared/errors/global-error.filter.ts) L32-42ai10 复核修正)
- [x] GlobalErrorFilter 统一兜底
## 7. 现有骨架差距与待决策(提请 coord 仲裁)
| # | 差距 | 影响 | 提请决策 |
| --- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| M1 | **Kafka 消费未实现**:装了 kafkajs 但无 consumer 代码,无 shared/kafka/ 目录 | 004 §7.3 列 msg 消费 5 类事件ExamPublished/HomeworkGraded/GradeRecorded/UserRegistered/MasteryUpdated | 阶段 2 设计需补 Kafka consumer + 幂等去重 |
| M2 | **无 Outbox**:骨架无 shared/outbox/ | 004 §7.2 明确 msg 生产 `edu.notification.events`NotificationRequested消费者 push-gateway**ai10 复核msg 必须有 Outbox**004 §7.2/§7.3 已定义,原"无明确"判断失实) | 阶段 2 设计补 Outbox参照 core-edu outbox.publisher.ts |
| M3 | **ES 无 mapping 定义**:依赖动态 mapping索引名 "notifications" 硬编码在 service | 检索质量不稳定,索引管理缺失 | 阶段 2 设计补 mapping + ensureIndex |
| M4 | **无独立 repository**notifications.service.ts 直接用 db无 repository 抽象 | 与黄金模板分层不一致iam 有 repository | 阶段 2 设计补 repository 层 |
| M5 | **Redis 未引入**env.ts 预留 REDIS_URL 但无 redis 客户端依赖 | pending-features P5 要求 event_id 去重Redis SETNX 或 DB 唯一索引) | 阶段 2 设计决策Redis SETNX vs DB 唯一索引 |
| M6 | **createBatch 无事务/无批量优化**for 循环串行调 send无批量 INSERT | 性能瓶颈(广播场景) | 阶段 2 设计改为批量 INSERT |
| M7 | **NotificationsModule 缺 exports**notifications.module.ts 无 `exports: [NotificationsService]` | 未来 BFF 注入受阻 | 阶段 2 设计补 exports |
| M8 | **~~ZodError 未特殊处理~~ai10 复核:已修复,失实条目)**GlobalErrorFilter 已识别 ZodError 返回 400见 [global-error.filter.ts](../src/shared/errors/global-error.filter.ts) L32-42 | 无(已修复) | ✅ 已修复,无需处理 |
| M9 | **gRPC 未实现**proto 定义了 NotificationService但无 gRPC controller | pending-features P5 未强制 gRPC | 确认 P5 是否启用 gRPCai03 提请统一决策) |
| M10 | **README 与实现脱节**README API 表标 `POST /notifications/:id/read`,实际是 PUT漏 batch/user/:userId/user/:userId/page 端点;声称"消费 Kafka 事件"但无代码 | 文档误导 | 阶段 2 设计同步修正 README |
| M11 | **main.ts 与 LifecycleService 重复关闭资源**:两者都调 closeDb/closeEs | 重复关闭可能报错(虽有 try-catch | 阶段 2 设计统一关闭逻辑到 LifecycleService |
| M12 | **~~proto 包名不一致~~ai10 复核:失实条目)**:实际 `next_edu_cloud.msg.v1` 完全符合 project_rules §5 `next_edu_cloud.<domain>.v1` 规范coord 已裁决采用 `next_edu_cloud.*` 格式) | 无(命名正确) | ✅ 命名正确,无需处理 |
---
## 服务审计表 — ai10msg 复核)
> 审计标准对照 [project_rules §3](../../../.trae/rules/project_rules.md) 与 [known-issues §2.2 classes 黄金模板](../../../docs/troubleshooting/known-issues.md)
| 服务 | 权限装饰器 | 错误码前缀 | logger | metrics | tracer | /healthz | /readyz | 优雅关闭 | 测试覆盖率 | Dockerfile |
| ---- | --------------- | ---------- | ------- | -------------- | ------------------------------- | -------- | ---------------- | --------------------------------------- | ---------- | ---------- |
| msg | ✅ 6 端点全覆盖 | ✅ `MSG_*` | ✅ pino | ✅ prom-client | ✅ OTel + auto-instrumentations | ✅ | ⚠️ 仅 DB 不查 ES | ⚠️ main.ts 与 LifecycleService 重复关闭 | 0% | ✅ |
## ai10 复核结论ai-allocation §5 设计重点对照)
ai-allocation.md §5 对 ai10msg明确列出 6 项设计重点,对照现有骨架:
| ai-allocation §5 设计重点 | 现状 | 阶段 2 是否需设计 |
| --------------------------------------------------- | ------------------------------ | ----------------- |
| 通知渠道抽象(站内信/邮件/短信,策略模式) | ❌ 无抽象,硬编码 | ✅ 必须 |
| ES 降级查询策略DB 不可用时走 ES 索引) | ❌ 仅 ES 降级,无 DB 降级到 ES | ✅ 必须 |
| Kafka 消费幂等设计event_id 去重 via Redis SETNX | ❌ 无 Kafka 代码 | ✅ 必须 |
| 与 ai02push-gateway的推送通道协议gRPC | ⚠️ 用 fetch POST 降级,无 gRPC | ✅ 需 gRPC 化 |
| 通知模板管理(模板 CRUD + 变量替换) | ❌ 无模板模块 | ✅ 必须 |
| 已读/未读状态管理Redis 位图) | ❌ 仅 DB boolean | ✅ 必须 |
**新增差距ai10 补充,原 ai05 文档遗漏)**
| # | 差距 | 影响 |
| --- | ------------------------------------------------------------------------------- | ----------------------------------------------------- |
| M13 | **无通知模板模块**:缺 msg_notification_templates 表、模板 CRUD、变量替换、i18n | ai-allocation §5 强制要求 |
| M14 | **无渠道策略抽象**send 方法硬编码 channel 判断,无 ChannelStrategy 接口 | 多渠道扩展困难(未来加微信/钉钉需改核心) |
| M15 | **无 Redis 位图已读/未读**isRead 仅 DB boolean无 unread 计数缓存 | 高频未读数查询打 DB广播场景性能瓶颈 |
| M16 | **无 DB→ES 降级读路径**:仅有 ES→空降级无 DB 故障时走 ES 读模型 | ai-allocation §5 要求 DB 不可用走 ES 索引 |
| M17 | **无投放记录表**:缺 msg_notification_deliveriesper-channel 投递状态) | 无法追踪邮件/短信投递成功失败 |
| M18 | **无幂等键**send 无 idempotencyKey 参数,重复请求会重复发通知 | 客户端重试导致重复通知 |
| M19 | **无通知优先级/分类**:缺 priority/category 字段 | 无法区分紧急通知与普通通知,无法按类退订 |
| M20 | **无调度/延迟发送**:缺 scheduledAt 字段与调度器 | 未来定时通知、每日摘要无法支持 |
| M21 | **权限模型过简**:仅 3 个权限点,硬编码 ROLE_PERMISSIONS | 应对齐 iam 的 RBAC + DataScopeDATA_SCOPE=SELF/ALL |
---
## 跨模块契约对齐提请coord 交叉审查)
### 接口一致性检查msg 相关)
| 本服务声明 | 对方服务声明 | 是否匹配 | 备注 |
| -------------------------------------------- | ------------------------------- | --------- | ------------------------------------------------------------------------------------------------ |
| ai05 msg: 消费 `edu.teaching.exam.published` | ai03 core-edu: 发布考试事件 | ⚠️ 待确认 | ai03 提请 topic 命名统一004 `edu.teaching.exam.published` vs core-edu 代码 `edu.exam.events` |
| ai05 msg: 消费 `edu.identity.user.created` | ai02 iam: 发布用户创建事件 | ⚠️ 待确认 | ai02 设计需确认 topic |
| ai05 msg: 调 push-gateway `/internal/push` | ai01 push-gateway: 暴露推送端点 | ✅ 已实现 | msg 当前用 fetch POSTpush-gateway 已有 /internal/push 端点 |
### 全局冲突检查msg 相关)
| 检查项 | 检查结果 | 备注 |
| -------------------- | --------------- | -------------------------------------------------------------------------------------------------------- |
| 端口不冲突 | ✅ msg 3007 | 与 iam(3002)/classes(3001)/teacher-bff(3003)/core-edu(3004)/content(3005)/data-ana(3006)/ai(3008) 不冲突 |
| Topic 不重复 | ⚠️ 待汇总 | msg 仅消费不发布 |
| 错误码前缀不重叠 | ✅ `MSG_*` 唯一 | 与 iam `IAM_*` / core-edu `CORE_EDU_*` / content `CONTENT_*` 不重叠 |
| Proto message 不遗漏 | ⚠️ 待确认 | events.proto 无 NotificationEvent若 msg 发事件需补充 |
| proto 包名规范 | ⚠️ 不一致 | 实际 `next_edu_cloud.<domain>.v1`,规则要求 `edu.<domain>.v1`**提请 coord 仲裁**ai03 已提请) |
### 待 coord 仲裁的决策项msg 相关)
1. ~~**proto 包名统一**`next_edu_cloud.*` vs `edu.*`~~ai10 复核coord 已裁决 `next_edu_cloud.*`,本项目全部 proto 已采用,无需再仲裁)
2. **gRPC 启用时机**P4/P5 是否启用 gRPC controller还是继续 REST影响 content/msg/iam/core-edu 全部服务)
3. ~~**msg Outbox**:是否需要~~ai10 复核004 §7.2 已明确 msg 生产 `edu.notification.events`**必须有 Outbox**,无需仲裁)
4. **msg Redis 引入**env.ts 预留 REDIS_URL 但无依赖,幂等去重用 Redis SETNX 还是 DB 唯一索引ai10 倾向 Redis SETNX + DB 唯一索引双保险,待 coord 确认 Redis 是否纳入 P5 基础设施)
5. **events.proto 补充**msg 发 NotificationRequested 事件需追加 NotificationEvent messagecoord 维护 proto
---
## 下一步
1. ~~等待 coord 审核本确认书~~ai10 复核修订完成,进入阶段 2
2. 进入**阶段 2模块架构设计文档**,按 ai-allocation.md §7 模板产出 [02-architecture.md](./02-architecture.md)
- msg 模块架构设计文档含通知渠道抽象策略模式、ES 降级查询、Kafka 消费幂等、push-gateway 推送协议、通知模板、已读/未读状态管理)
3. 阶段 2 设计完成后同步更新 README修正 §M10 文档脱节问题)
---
**AI Agent**: ai10 (msg)
**Coordinator**: coord-ai
**Branch**: 单仓库并行模式(直接 push main