Files
Edu/services/teacher-bff/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

134 lines
12 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.
# 模块理解确认书 — teacher-bff
> AI 标识ai03
> 负责模块teacher-bffP2
> 阶段:架构设计外包 · 阶段 1全局理解
> 日期2026-07-09v1/ 2026-07-09v2 审计修订)
> 关联文档:[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)
>
> **v2 修订说明**:依据 ai-allocation.md §3.2 修正 ai03 责任范围(仅 teacher-bffcore-edu 由 ai08 负责);修正 /readyz 实际状态修正错误码前缀描述补充前瞻性内容SSE 流式透传、Kafka 缓存失效、DataLoader 覆盖、DataScope 透传)。
---
## 1. 我在架构中的位置
- **层级**BFF 聚合层L4
- **上游**api-gatewayGo/Gin通过 HTTP 转发请求,注入 `x-user-id` / `x-user-roles`
- **下游**iam3002 / gRPC 50052、classes3001 / P3 合并入 core-edu、core-edu3004 / gRPC 50053P4 扩展 contentgRPC 50054、data-anagRPC 50055P5 扩展 msggRPC 50056、aigRPC 50057含 StreamChat 流式 RPC
- **通信方式**
- 当前P2对前端 REST对下游 REST `fetch`(同步)
- 目标态004 §4.1 / pending-features P2**gRPC** 调下游业务服务 + **GraphQL Yoga** 对前端暴露 + DataLoader 防 N+1
- 演进路径P2 REST 内部封装为 client 抽象层 → P3 引入 gRPC clientiam + core-edu→ P4 GraphQL Yoga 对前端 + DataLoader + content/data-ana gRPC → P5 SSE 流式透传ai+ msg gRPC + 可选 Kafka 缓存失效消费者
- **端口**3003 HTTP见 [teacher-bff env.ts](../src/config/env.ts)BFF 不暴露 gRPC 端口(只被 Gateway HTTP 调用)
## 2. 我的限界上下文
- **聚合职责**:教学场景域(教师 / 教导主任 / 教研组长 共用)的数据聚合、裁剪、协议转换
- **业务领域**:跨 D2 教学组织 + D3 教学核心 + D1 身份认证(只读拉取视口/权限)
- **我不负责**
- 不持有业务状态(无 DB 写入,无 Outbox
- 不做权限决策(依赖 Gateway JWT 校验 + 下游服务 `@RequirePermission`
- 不直接访问任何业务服务数据库
- **复用策略**004 §5.4):教导主任 / 教研组长复用 Teacher BFF通过视口差异化L1 导航扩展管理菜单L4 DataScope 扩大到年级)
## 3. 我与外部的契约
- **消费的 proto message**(按阶段,详见 [02-architecture-design.md](./02-architecture-design.md) §7
- P2`iam.v1.IamService`GetUserInfo**待补 RPC**GetViewports / GetEffectivePermissions / Logout / GetPublicKey`classes.v1.ClassService`ListClasses / GetClass
- P3`core_edu.v1.ExamService / HomeworkService / GradeService`(全部 RPC**待补 RPC**AttendanceService、GetClassesByTeacher
- P4`content.v1.KnowledgeGraphService`GetPrerequisites / GetLearningPath**待补 RPC**ChapterService / QuestionService`analytics.v1.AnalyticsService`GetClassPerformance / GetStudentWeakness / GetLearningTrend**待补 RPC**GetTeacherDashboardStats
- P5`ai.v1.AiService`GenerateQuestion / **StreamChat 流式 RPC** / Chat / OptimizeExpression`msg.v1.NotificationService`ListNotifications / SearchNotifications / MarkAsRead
- **暴露的 API**(当前 REST目标 GraphQL Yoga详见 02 文档 §4
- `GET /teacher/dashboard` — 聚合 IAM 用户信息 + classes 列表
- `GET /teacher/viewports` — 拉取 IAM 视口配置L1 导航)
- `GET /teacher/classes/:classId/exams` — 聚合 core-edu 考试列表
- `GET /teacher/classes/:classId/homework` — 聚合 core-edu 作业列表
- `GET /teacher/exams/:examId/grades` — 聚合 core-edu 成绩列表
- P4+ 目标GraphQL Query/Mutationdashboard / viewports / classes / exams / homework / grades / knowledgePath / classPerformance / studentWeakness / notifications+ MutationcreateExam / assignHomework / recordGrade / generateQuestion
- P5SSE 流式端点AI 对话透传)
- **错误码前缀**:当前代码用 `TEACHER_BFF_*`(违反 project_memory 规则 "BFF 错误码必须用 `BFF_XXX_` 前缀"**需迁移为 `BFF_TEACHER_*`**coord P0 整改 #3);业务错误透传下游 `CORE_EDU_*` / `IAM_*` / `CLASSES_*`
- **缓存**:聚合结果 Redis 短缓存 5-30s004 §6.3,当前未实现);权限列表 5min 缓存 + 事件驱动失效(订阅 `edu.identity.user.role_changed` / `edu.identity.role.updated`P3+ 引入 Kafka consumerP2 用短 TTL 兜底)
- **DataScope 透传**BFF 不解析 dataScope 语义,从 IAM 获取后作为 gRPC metadata 透传给下游服务,下游 Repository 层注入 WHERE 条件(详见 02 文档 §9
## 4. 我的技术栈
- 语言TypeScript 5.5+ESM 模式,相对 import 带 `.js` 后缀)
- 框架NestJS 10
- 下游通信:当前 `fetch`REST→ P3 引入 `@grpc/grpc-js` + `@bufbuild/protobuf`(经 client 抽象层,平滑切换)
- 对前端:当前 REST → P4 目标 GraphQL Yoga + DataLoaderurql 客户端)
- 缓存Redis待引入ioredis 客户端)
- 流式P5 SSE 透传ai.StreamChat streaming RPC → BFF → 前端 EventSource
- 可观测pino logger + prom-client metrics + OpenTelemetry tracer已具备 [tracer.ts](../src/shared/observability/tracer.ts)
- 弹性P6 引入 circuit breakeropossum+ retrygRPC interceptor
- 测试Vitest待引入目标覆盖率 ≥ 80%
## 5. 我的阶段归属
- **P2 身份**:教师登录 → 获取 JWT → 访问 teacher-portal → 侧边栏按 viewports.L1 渲染 → 空白 Dashboard
- **P3 扩展**:考试/作业/成绩的查询与 mutationiam + core-edu 切 gRPC引入 Redis 聚合缓存
- **P4 扩展**知识图谱查询content+ 学情诊断data-anaGraphQL Yoga 对前端 + DataLoadercontent + data-ana 切 gRPC
- **P5 扩展**AI 辅助出题SSE 流式透传)+ 通知查询聚合msgai + msg 切 gRPC可选 Kafka 缓存失效消费者
- **P6 硬化**circuit breaker + retry + HPA + mTLS99.9% 可用性
- **依赖上游**P1 黄金模板 classes、P2 iamgetEffectivePermissions + 视口)
## 6. 我需要对齐的黄金模板项(对照 classes 服务)
- [ ] 权限装饰器 `@RequirePermission`**BFF 不做权限决策**当前无目标态BFF 不加 Guard仅校验 `x-user-id` 存在)
- [x] 错误处理:[GlobalErrorFilter](../src/shared/errors/global-error.filter.ts) + ApplicationError 层次(**错误码前缀需迁移 `TEACHER_BFF_*``BFF_TEACHER_*`**
- [x] logger / metrics / tracer 三支柱(已具备)
- [x] `/healthz` 健康检查HealthModule 已注册)
- [ ] `/readyz`(端点已存在,但**未做下游就绪探针**,需在 P2 补全:并行 ping iam + classes + core-edu 的 /healthz
- [x] 优雅关闭 SIGTERMmain.ts 已处理)
- [ ] 测试覆盖率 ≥ 80%**当前 0%**无测试文件P2 引入 Vitest
- [x] Dockerfile 多阶段构建builder + runtime已具备见 [Dockerfile](../Dockerfile)
- [ ] Zod 输入验证(当前 Controller 直接透传 unknown**未做 Zod 校验**P2 补全)
- [x] GlobalErrorFilter 统一兜底
---
## 服务审计表 — ai03teacher-bff 部分)
> 对照 [黄金模板 classes 服务](../../classes/src/),审计已实现的 teacher-bff 服务。状态:✅ 达标 / ⚠️ 部分 / ❌ 缺失
| 服务 | 权限装饰器 | 错误码前缀 | logger | metrics | tracer | /healthz | /readyz | 优雅关闭 | 测试覆盖率 | Dockerfile |
| ----------- | --------------------------------------- | ---------------------------------------------- | ------- | -------------- | ------- | -------- | ----------------------- | -------- | ---------- | ---------- |
| teacher-bff | ⚠️ 无BFF 不做权限决策,依赖 Gateway | ⚠️ `TEACHER_BFF_*`(需迁移为 `BFF_TEACHER_*` | ✅ pino | ✅ prom-client | ✅ OTel | ✅ | ⚠️ 端点存在,无下游探针 | ✅ | 0% ❌ | ✅ 多阶段 |
### 审计发现的关键差距P2 阶段 2 设计需解决)
1. ⚠️ 通信方式:当前 REST `fetch`,需引入 client 抽象层为 P3 gRPC 切换铺路GraphQL Yoga + DataLoader 按 coord 仲裁决定 P2 还是 P4 引入(见 02 文档 §4.1
2. ❌ 无 Redis 聚合缓存004 §6.3 要求 5-30s 短缓存)
3. ❌ 无 DataLoader防 N+1pending-features P2 明确要求,目标态必备)
4. ⚠️ `/readyz` 端点存在但无下游就绪探针
5. ⚠️ env 配置用 `IamServiceUrl`/`ClassesServiceUrl`REST URL需抽象为 service target支持 P3+ gRPC target
6. ⚠️ 无 Zod 输入验证
7. ⚠️ 无测试
8. ⚠️ 错误码前缀违反 project_memory 规则,需迁移 `TEACHER_BFF_*``BFF_TEACHER_*`
### 跨模块契约对齐待确认项(提请 coord 交叉审查)
| 待确认项 | 我方期望 | 对方模块 | 状态 |
| -------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------- |
| iam `getEffectivePermissions(userId)` 返回结构 | `{permissions, viewports, dataScope}` 聚合 API建议 `GetEffectiveAccess` RPC | iamai06 | ⚠️ 当前 teacher-bff 调 `/iam/viewports``/iam/me`,未定义此聚合 API 的 proto |
| iam 补 RPCGetViewports / GetEffectivePermissions / Logout / GetPublicKey | 4 个 RPC | iamai06 | ❌ proto 缺失coord 裁决 P2 补全 |
| core-edu 补 AttendanceService + GetClassesByTeacher | 1 个 service + 1 个 RPC | core-eduai08 | ❌ proto 缺失coord 裁决 P3 补全 |
| data-ana 补 GetTeacherDashboardStats | 1 个 RPC | data-anaai11 | ❌ proto 缺失,提请 coord 仲裁 |
| GraphQL vs REST 仲裁 | P2 即 GraphQLpending-featuresvs P2-P3 REST、P4+ GraphQLcoord 裁决) | coord | ⚠️ 表述冲突,需仲裁 |
| core-edu 端口 3004 / gRPC 50053 | 不冲突 | 全局端口矩阵 | 待 coord 核对 |
---
## 下一步(阶段 2 入口)
待 coord 审核本确认书通过后ai03 进入阶段 2按 [ai-allocation.md §5 ai03 设计重点](../../../docs/architecture/ai-allocation.md#ai03--教学场景域) 产出模块架构设计文档 [02-architecture-design.md](./02-architecture-design.md)
- **teacher-bff 模块架构设计**目标态架构GraphQL Yoga + DataLoader + gRPC + Redis 缓存 + SSE 流式透传)+ 分阶段演进路线P2-P6+ 视口推导 + DataScope 透传 + 并行 gRPC 编排与降级策略
阶段 2 设计需先解决上述 8 项差距与跨模块契约对齐。
---
**AI Agent**: ai03 (teacher-bff)
**Coordinator**: coord-ai
**Branch**: 单仓库并行模式(直接 push main