Files
Edu/services/teacher-bff/docs/nextstep.md

317 lines
31 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 下一步工作与上下游依赖
> 模块teacher-bff教学场景域聚合层 BFFGraphQL 聚合层,端口 3003
> 负责人ai03
> 更新日期2026-07-13v2iam 真实数据全量联调 + dataScope 修复)
> 关联文档:[02-architecture-design.md](./02-architecture-design.md)、[admin-portal_contract.md](../../../docs/architecture/issues/contracts/admin-portal_contract.md)
---
## 1. 模块当前状态
teacher-bff 已完成 P2-P6 全部批次admin resolver 重构为扁平命名ARB-001 裁决Docker 镜像构建成功并在本地 Docker 验证通过(接入真实 iam无 mock 数据)。
### 1.1 本地 Docker 验证结果2026-07-13 v2
测试环境:本地 Dockeredu-iam-test + edu-teacher-bff-test 容器,接入 `edu-full_default` 网络,直连 edu-mysql / edu-redis / edu-kafka
```
镜像edu-test-iam:latest、edu-test-teacher-bff:latest
容器edu-iam-testNODE_ENV=production, DEV_MODE=true, HTTP 3002 + gRPC 50052
edu-teacher-bff-testNODE_ENV=production, TEACHER_BFF_DEV_MODE=true, HTTP 3003
测试用户ffd5f3f8-67a3-4774-9ccc-c4c6d2288eafadmin-test@edu.local, role=admin, data_scope=all
```
| 验证项 | 状态 | 说明 |
| -------------------------------------------------------- | ---- | --------------------------------------------------------------------- |
| iam Docker 镜像构建 | ✅ | node:20-alpine + bcryptjs纯 JS无 native 编译) |
| teacher-bff Docker 镜像构建 | ✅ | node:20-alpine + shared-ts 预编译 |
| iam HTTP /healthz | ✅ | 200 |
| iam gRPC 50052 | ✅ | GetUserInfo / BatchGetUsers / GetEffectivePermissions 等方法可调用 |
| teacher-bff /healthz | ✅ | 200 |
| teacher-bff /readyz | ✅ | 7 依赖健康iam gRPC + Redis + 5 个 mock 客户端探针) |
| GraphQL schema introspection | ✅ | 41 Query + 20 Mutation 字段全部存在 |
| `currentUser` 查询UUID | ✅ | 返回真实 iam 数据admin-test@edu.local, dataScope: ALL, 5 权限) |
| `me` 查询UUID | ✅ | 返回真实 iam 数据dataScope: ALLv2 修复) |
| `adminRoles` 查询 | ✅ | 返回真实 iam 角色3 个admin/student/teacher |
| `adminPermissions` 查询 | ✅ | 返回真实 iam 权限点5 个iam:user:read 等) |
| `auditLogs` 查询 | ✅ | 返回真实 iam 审计日志5 条) |
| `adminDashboard` 查询 | ✅ | 返回真实统计数据auditEventsToday: 4 |
| `systemSettings` 查询 | ✅ | 返回真实系统设置academicYear: 2025-2026 |
| `adminUsers` 查询 | ⚠️ | 返回空iam REST /v1/iam/users 未实现,降级模式 B |
| `adminTeachers` / `adminStudents` 查询 | ⚠️ | 返回空core-edu 未接入,降级模式 B |
| `adminSchools` / `adminGrades` / `adminDepartments` 查询 | ⚠️ | 返回空core-edu 未接入,降级模式 B |
| `viewports` / `adminViewports` 查询 | ⚠️ | 返回空iam REST /v1/iam/viewports 返回空数组DB 无 viewport 数据) |
| x-user-data-scope header 透传 | ✅ | CallContext → context.ts → graphql.controller.ts → iam-grpc.client.ts |
| `typecheck` / `lint` / `build` | ✅ | 三项零错误 |
### 1.2 已完成的关键修复
| # | 工作项 | 详情 |
| --- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 1 | admin.resolver.ts 扁平命名重构 | ARB-001 裁决:`adminUsers`/`adminRoles` 直接挂载在根 Query/Mutation不再使用 `admin { users }` 命名空间 |
| 2 | graphql.controller.ts 深合并 resolvers | `mergeResolvers(teacherResolvers, adminResolvers)` 深合并 Query/Mutation 字典,避免浅展开覆盖 |
| 3 | x-user-data-scope header 透传链路 | iam PermissionGuard 检查 `data_scope=all` 跳过权限校验teacher-bff 全链路透传该 header |
| 4 | IamGrpcController 注册修复 | 从 `providers` 数组移到 `controllers` 数组,修复 gRPC GetUserInfo UNIMPLEMENTED 错误 |
| 5 | JWT RS256 密钥生成 | 使用 Node.js crypto 生成 iam-private.pem / iam-public.pem |
| 6 | iam 种子数据 | 插入 4 个角色 + 11 个权限点 + 角色权限关联 + 审计日志 + 设置 data_scope='all' |
| 7 | Dockerfile 修复v2 | node:20-alpine + bcryptjs纯 JS+ shared-ts 预编译 + pnpm prune --prod |
| 8 | bcrypt → bcryptjs 迁移v2 | 避免 native 编译依赖python3/make/g++API 完全兼容 |
| 9 | NODE_ENV=productionv2 | 避免 pino-pretty 在 prune --prod 后缺失dev 模式才使用 transport |
| 10 | IamModule 客户端选择逻辑修复v2 | 按 `IAM_GRPC_TARGET` 是否配置选择 gRPC 或 mock不再受 DEV_MODE 影响 |
| 11 | DataScope 枚举大小写转换v2 | iam DB 存小写self/allGraphQL enum 需大写,在 iam-grpc.client.ts getUserInfo 中 toUpperCase() |
| 12 | `me` 查询 dataScope 修复v2 | teacher.service.ts getCurrentUser 改用 `userInfo.dataScope ?? perms.dataScope`REST /v1/iam/permissions/effective 不返回 dataScope 时回退到 gRPC GetUserInfo 的值 |
---
## 2. 上游依赖teacher-bff 依赖谁)
### 2.1 iam 服务ai06 负责)— P0
| # | 依赖项 | 用途 | 状态 |
| --- | ------------------------------------------------ | ------------------------------------------------------------------ | -------------- |
| 1 | gRPC `GetUserInfo(userId)` :50052 | `currentUser` 查询:获取当前用户信息 + 角色 + 权限 | ✅ 已就绪 |
| 2 | gRPC `BatchGetUsers(userIds)` :50052 | `adminUsers` 查询:批量获取用户信息 | ✅ 已就绪 |
| 3 | gRPC `GetEffectivePermissions(userId)` :50052 | 用户有效权限列表 | ✅ 已就绪 |
| 4 | gRPC `GetEffectiveDataScope(userId)` :50052 | 用户数据范围DataScope 6 级) | ✅ 已就绪 |
| 5 | gRPC `GetViewports(userId)` :50052 | `adminViewports` 查询:视口配置 | ✅ 已就绪 |
| 6 | gRPC `GetPublicKey()` :50052 | RS256 公钥JWT 验签) | ✅ 已就绪 |
| 7 | gRPC `GetChildrenByParent(parentId)` :50052 | 家长端:获取学生-家长关系 | ✅ 已就绪 |
| 8 | REST `GET /v1/iam/roles` :3002 | `adminRoles` 查询:角色列表 | ✅ 已就绪 |
| 9 | REST `GET /v1/iam/permissions` :3002 | `adminPermissions` 查询:权限点列表 | ✅ 已就绪 |
| 10 | REST `GET /v1/iam/audit` :3002 | `auditLogs` 查询:审计日志 | ✅ 已就绪 |
| 11 | REST `GET /v1/iam/viewports` :3002 | `adminViewports` 查询(备选) | ✅ 已就绪 |
| 12 | REST `GET /v1/iam/permissions/effective` :3002 | 用户有效权限(备选) | ✅ 已就绪 |
| 13 | `GET /.well-known/jwks.json` :3002 | RS256 JWKSapi-gateway / push-gateway 验签) | ⏳ 待 iam 实现 |
| 14 | `POST /v1/iam/register` / `POST /v1/iam/login` | 用户注册/登录admin `createUser` 需要) | ✅ 已就绪 |
| 15 | `PATCH /v1/iam/users/:id` | 用户更新admin `updateUser` / `toggleUserStatus` 需要) | ⏳ 待 iam 实现 |
| 16 | `POST /v1/iam/roles` / `PATCH /v1/iam/roles/:id` | 角色创建/更新admin `createRole` / `updateRolePermissions` 需要) | ⏳ 待 iam 实现 |
**关键环境变量**
- `IAM_GRPC_TARGET=iam:50052`
- `IAM_SERVICE_URL=http://iam:3002`
### 2.2 core-edu 服务ai07 负责)— P1
| # | 依赖项 | 用途 | 状态 |
| --- | ---------------------------------------------------- | ----------------------------------- | ------------------- |
| 1 | gRPC `GetDashboard(teacherId)` :50053 | `dashboard` 查询:教师仪表盘聚合 | ⏳ 待 core-edu 实现 |
| 2 | gRPC `ListClasses(teacherId)` :50053 | `classes` / `adminClasses` 查询 | ⏳ 待 core-edu 实现 |
| 3 | gRPC `GetClass(classId)` :50053 | `class` 查询:班级详情 | ⏳ 待 core-edu 实现 |
| 4 | gRPC `ListExams(classId)` :50053 | `exams` 查询:考试列表 | ⏳ 待 core-edu 实现 |
| 5 | gRPC `ListHomework(classId)` :50053 | `homework` 查询:作业列表 | ⏳ 待 core-edu 实现 |
| 6 | gRPC `ListGrades(classId)` :50053 | `grades` 查询:成绩列表 | ⏳ 待 core-edu 实现 |
| 7 | gRPC `CreateExam(input)` :50053 | `createExam` mutation | ⏳ 待 core-edu 实现 |
| 8 | gRPC `AssignHomework(input)` :50053 | `assignHomework` mutation | ⏳ 待 core-edu 实现 |
| 9 | gRPC `RecordGrade(input)` :50053 | `recordGrade` mutation | ⏳ 待 core-edu 实现 |
| 10 | gRPC `GetClassPerformance(classId)` :50053 | `classPerformance` 查询 | ⏳ 待 core-edu 实现 |
| 11 | gRPC `ListSchools()` / `ListGrades(schoolId)` :50053 | `adminSchools` / `adminGrades` 查询 | ⏳ 待 core-edu 实现 |
| 12 | gRPC `ListDepartments(schoolId)` :50053 | `adminDepartments` 查询 | ⏳ 待 core-edu 实现 |
| 13 | gRPC `ListAcademicYears()` :50053 | `adminAcademicYears` 查询 | ⏳ 待 core-edu 实现 |
**当前状态**teacher-bff 中 `CORE_EDU_GRPC_TARGET` 留空,相关查询走降级模式 B返回空结果 + warning 日志)。
### 2.3 content 服务ai08 负责)— P1
| # | 依赖项 | 用途 | 状态 |
| --- | ---------------------------------------- | ----------------------- | ------------------ |
| 1 | gRPC `GetKnowledgePath(classId)` :50054 | `knowledgePath` 查询 | ⏳ 待 content 实现 |
| 2 | gRPC `ListTextbooks()` :50054 | 教材列表 | ⏳ 待 content 实现 |
| 3 | gRPC `ListChapters(textbookId)` :50054 | 章节目录 | ⏳ 待 content 实现 |
| 4 | gRPC `ListLessonPlans(teacherId)` :50054 | `adminLessonPlans` 查询 | ⏳ 待 content 实现 |
| 5 | gRPC `ListCoursePlans(classId)` :50054 | `adminCoursePlans` 查询 | ⏳ 待 content 实现 |
### 2.4 data-ana 服务ai11 负责)— P1
| # | 依赖项 | 用途 | 状态 |
| --- | ----------------------------------------- | ------------------------- | ------------------- |
| 1 | gRPC `GetStudentWeakness(classId)` :50055 | `studentWeakness` 查询 | ⏳ 待 data-ana 实现 |
| 2 | gRPC `GetLearningTrend(classId)` :50055 | `learningTrend` 查询 | ⏳ 待 data-ana 实现 |
| 3 | gRPC `GetGradeInsights(gradeId)` :50055 | `adminGradeInsights` 查询 | ⏳ 待 data-ana 实现 |
### 2.5 msg 服务ai10 负责)— P1
| # | 依赖项 | 用途 | 状态 |
| --- | --------------------------------------- | --------------------------------- | -------------- |
| 1 | gRPC `ListNotifications(userId)` :50056 | `notifications` 查询 | ⏳ 待 msg 实现 |
| 2 | gRPC `MarkNotificationRead(id)` :50056 | `markNotificationAsRead` mutation | ⏳ 待 msg 实现 |
| 3 | gRPC `ListAnnouncements(filter)` :50056 | `adminAnnouncements` 查询 | ⏳ 待 msg 实现 |
| 4 | gRPC `CreateAnnouncement(input)` :50056 | `createAnnouncement` mutation | ⏳ 待 msg 实现 |
| 5 | gRPC `PublishAnnouncement(id)` :50056 | `publishAnnouncement` mutation | ⏳ 待 msg 实现 |
### 2.6 ai 服务ai12 负责)— P1
| # | 依赖项 | 用途 | 状态 |
| --- | ------------------------------------- | --------------------------- | ------------- |
| 1 | gRPC `GenerateQuestion(input)` :50058 | `generateQuestion` mutation | ⏳ 待 ai 实现 |
| 2 | SSE `POST /v1/ai/chat/stream` :3008 | AI 对话流式响应 | ⏳ 待 ai 实现 |
| 3 | gRPC `ListAiProviders()` :50058 | `aiProviders` 查询 | ⏳ 待 ai 实现 |
| 4 | gRPC `GetAiUsage()` :50058 | `aiUsage` 查询 | ⏳ 待 ai 实现 |
### 2.7 Redis基础设施— P0
| 项 | 内容 |
| -------- | ------------------------------------- |
| 依赖内容 | /readyz 探针 + DataLoader 缓存P4+ |
| 端点 | `redis://edu-redis:6379` |
| 当前状态 | ✅ 本地 Docker edu-redis 已就绪 |
### 2.8 Kafka基础设施— P2
| 项 | 内容 |
| -------- | --------------------------------------- |
| 依赖内容 | 可选消费领域事件用于读模型刷新P3+ |
| 端点 | `kafka:29092` |
| 当前状态 | ✅ 本地 Docker edu-kafka 已就绪 |
---
## 3. 下游依赖(谁依赖 teacher-bff
### 3.1 admin-portalai16 负责)— P0
| 能力 | 配置 | 状态 |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| `POST /graphql` :3003 | admin-portal GraphQL 代理目标 | ✅ 已就绪 |
| 40 Query 字段(扁平命名) | currentUser/adminUsers/adminRoles/adminPermissions/adminViewports/adminOrganization/adminClasses/adminTeachers/adminStudents/auditLogs/adminDashboard/systemSettings/auditOverviewStats/auditTrend/dataChangeLogs/loginLogs/adminSchools/adminGrades/adminGradeInsights/adminDepartments/adminAcademicYears/adminAnnouncements/adminInvitationCodes/adminFiles/adminFileStats/aiProviders/aiUsage + teacher 域 14 个 | ✅ 全部实现 |
| 20 Mutation 字段(扁平命名) | createUser/updateUser/toggleUserStatus/createRole/updateRolePermissions/updateViewport/updateSystemSettings/createAnnouncement/publishAnnouncement/archiveAnnouncement/toggleAnnouncementPin/generateInvitationCodes/deleteInvitationCodes/deleteFiles/updateAiProvider + teacher 域 5 个 | ✅ 全部实现 |
| x-user-data-scope header 透传 | admin 角色 data_scope=all 跳过 iam 权限校验 | ✅ 已实现 |
| 降级模式 B | 未就绪下游返回空结果 + warning | ✅ 已实现 |
**portal 需求来源**`apps/admin-portal/docs/nextstep.md` §2.2
### 3.2 teacher-portalai13 负责)— P0
| 能力 | 配置 | 状态 |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
| `POST /graphql` :3003 | teacher-portal GraphQL 代理目标 | ✅ 已就绪 |
| teacher 域 14 Query | dashboard/viewports/me/classes/class/exams/homework/grades/knowledgePath/classPerformance/studentWeakness/learningTrend/notifications | ✅ 全部实现 |
| teacher 域 5 Mutation | createExam/assignHomework/recordGrade/generateQuestion/markNotificationAsRead | ✅ 全部实现 |
| SSE `/v1/teacher/ai/chat/stream` | AI 对话流式透传 | ✅ 已实现ai-chat-sse.controller.ts |
| Zod 输入验证 | createExam/assignHomework/recordGrade/generateQuestion | ✅ 已实现 |
**portal 需求来源**`apps/teacher-portal/nextstep.md`
### 3.3 api-gatewayai01 负责)— P0
| 能力 | 配置 | 状态 |
| ----------------------------- | ----------------------------------------------------- | --------------------- |
| `/api/v1/teacher/*` 反向代理 | → teacher-bff:3003/*(路径重写剥离 /api/v1/teacher | ✅ api-gateway 已配置 |
| `/api/admin/graphql` 反向代理 | → teacher-bff:3003/graphql路径重写剥离 /api/admin | ✅ api-gateway 已配置 |
| `GET /healthz` 端点 | /readyz 下游健康检查 | ✅ 已实现 |
| `GET /readyz` 端点 | iam gRPC + Redis 健康检查 | ✅ 已实现 |
| `GET /metrics` 端点 | Prometheus 指标 | ✅ 已实现 |
---
## 4. GraphQL Schema 清单
### 4.1 Query 字段40 个)
**Teacher 域14 个)**dashboard / viewports / me / classes / class / exams / homework / grades / knowledgePath / classPerformance / studentWeakness / learningTrend / notifications / serverTime
**Admin 域26 个)**currentUser / adminUsers / adminUser / adminRoles / adminPermissions / adminViewports / adminOrganization / adminClasses / adminTeachers / adminStudents / auditLogs / adminDashboard / systemSettings / auditOverviewStats / auditTrend / dataChangeLogs / loginLogs / adminSchools / adminGrades / adminGradeInsights / adminDepartments / adminAcademicYears / adminAnnouncements / adminInvitationCodes / adminFiles / adminFileStats / aiProviders / aiUsage
### 4.2 Mutation 字段20 个)
**Teacher 域5 个)**createExam / assignHomework / recordGrade / generateQuestion / markNotificationAsRead
**Admin 域15 个)**createUser / updateUser / toggleUserStatus / createRole / updateRolePermissions / updateViewport / updateSystemSettings / createAnnouncement / publishAnnouncement / archiveAnnouncement / toggleAnnouncementPin / generateInvitationCodes / deleteInvitationCodes / deleteFiles / updateAiProvider
### 4.3 Schema 文件位置
- `packages/shared-ts/contracts/graphql/teacher-bff.schema.graphql`SDL 定义)
---
## 5. 环境变量清单Docker 部署)
| 变量 | 必填 | 示例值 | 说明 |
| ----------------------------- | ---- | ---------------------------- | ---------------------------------- |
| `PORT` | 是 | `3003` | HTTP 监听端口 |
| `GRAPHQL_PATH` | 否 | `/graphql` | GraphQL 端点路径 |
| `TEACHER_BFF_DEV_MODE` | 是 | `true`/`false` | 越权防御开关P2 放行 / 生产拒绝) |
| `REDIS_URL` | 是 | `redis://edu-redis:6379` | Redis 连接地址 |
| `IAM_GRPC_TARGET` | 是 | `iam:50052` | iam gRPC 目标 |
| `IAM_SERVICE_URL` | 是 | `http://iam:3002` | iam REST 基址 |
| `CORE_EDU_GRPC_TARGET` | 否 | `core-edu:50053` | core-edu gRPC 目标(留空走降级) |
| `CONTENT_GRPC_TARGET` | 否 | `content:50054` | content gRPC 目标(留空走降级) |
| `DATA_ANA_GRPC_TARGET` | 否 | `data-ana:50055` | data-ana gRPC 目标(留空走降级) |
| `MSG_GRPC_TARGET` | 否 | `msg:50056` | msg gRPC 目标(留空走降级) |
| `AI_GRPC_TARGET` | 否 | `ai:50058` | ai gRPC 目标(留空走降级) |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | 否 | `http://otel-collector:4318` | OTLP 上报端点 |
| `LOG_LEVEL` | 否 | `info` | 日志级别 |
---
## 6. 剩余工作
### 6.1 真实下游联调(按优先级)
| # | 工作项 | 阻塞条件 | 状态 |
| --- | ------------------------------------------------------------- | ------------------ | ---- |
| 1 | core-edu gRPC 联调 | core-edu 服务就绪 | ⏳ |
| 2 | content gRPC 联调 | content 服务就绪 | ⏳ |
| 3 | data-ana gRPC 联调 | data-ana 服务就绪 | ⏳ |
| 4 | msg gRPC 联调 | msg 服务就绪 | ⏳ |
| 5 | ai gRPC + SSE 联调 | ai 服务就绪 | ⏳ |
| 6 | iam REST CRUD 端点联调createUser/updateUser/createRole 等) | iam 补齐 REST CRUD | ⏳ |
### 6.2 P6 硬化任务
| # | 工作项 | 状态 |
| --- | ----------------------------- | ------------------------------- |
| 1 | DataLoader 批量查询(防 N+1 | ⏳ 待下游就绪后实现 |
| 2 | Redis 多层缓存 | ⏳ 待下游就绪后实现 |
| 3 | 熔断器opossum配置 | ✅ 已实现circuit-breaker.ts |
| 4 | OTel trace 上报 | ✅ 已实现tracer.ts |
| 5 | Prometheus 指标 | ✅ 已实现metrics.ts |
---
## 7. 已完成项汇总
| 工作项 | 状态 | 验证方式 |
| -------------------------------- | ---- | --------------------------------------------------------------------------------------------------- |
| P2 核心 5 Query | ✅ | typecheck + lint + Docker 联调 |
| P3 teacher 域 Query/Mutation | ✅ | typecheck + lint + Docker 联调 |
| P4 学习分析 Query | ✅ | typecheck + lint |
| P5 通知 + AI Query/Mutation | ✅ | typecheck + lint |
| P6 admin 扁平命名重构ARB-001 | ✅ | typecheck + lint + Docker 联调 |
| P6 admin 41 Query + 20 Mutation | ✅ | schema introspection + Docker 联调 |
| P6 x-user-data-scope header 透传 | ✅ | Docker 联调adminRoles 返回真实数据) |
| P6 IamGrpcController 注册修复 | ✅ | Docker 联调currentUser 返回真实数据) |
| P6 Zod 输入验证 | ✅ | typecheck |
| P6 熔断器opossum | ✅ | typecheck |
| P6 SSE 流式透传 | ✅ | typecheck |
| Docker 镜像构建 | ✅ | edu-test-teacher-bff:latestv2 alpine + bcryptjs |
| Docker 容器运行 | ✅ | /healthz 200 + /readyz 200 |
| 真实 iam 联调(无 mock | ✅ | currentUser/me/adminRoles/adminPermissions/auditLogs/adminDashboard/systemSettings 全部返回真实数据 |
| `me` 查询 dataScope 修复v2 | ✅ | teacher.service.ts 使用 userInfo.dataScopeDocker 验证返回 ALL |
| DataScope 大小写转换v2 | ✅ | iam-grpc.client.ts toUpperCase()Docker 验证 GraphQL enum 正常解析 |
| IamModule 客户端选择修复v2 | ✅ | IAM_GRPC_TARGET 配置后强制 gRPCDEV_MODE 不再触发 mock |
---
## 8. 关键文件路径
| 文件 | 用途 |
| ----------------------------------------------------------------- | --------------------------------------- |
| `services/teacher-bff/src/admin/admin.resolver.ts` | admin GraphQL resolver扁平命名 |
| `services/teacher-bff/src/admin/admin.service.ts` | admin 业务逻辑层 |
| `services/teacher-bff/src/teacher/teacher.resolver.ts` | teacher 域 GraphQL resolver |
| `services/teacher-bff/src/teacher/teacher.service.ts` | teacher 域业务逻辑层 |
| `services/teacher-bff/src/graphql/graphql.controller.ts` | GraphQL 入口 + mergeResolvers 深合并 |
| `services/teacher-bff/src/graphql/context.ts` | GraphQL 上下文(提取 x-user-* headers |
| `services/teacher-bff/src/clients/iam/iam-grpc.client.ts` | iam gRPC + REST 客户端 |
| `services/teacher-bff/src/clients/types.ts` | CallContext含 dataScope 字段) |
| `services/teacher-bff/src/clients/grpc/grpc.factory.ts` | gRPC 客户端工厂 |
| `services/teacher-bff/Dockerfile` | Docker 构建(含 shared-ts 预编译) |
| `packages/shared-ts/contracts/graphql/teacher-bff.schema.graphql` | GraphQL schema 契约 |
| `packages/shared-proto/proto/iam.proto` | iam gRPC proto 契约 |
---
**本文件由 ai03 维护,上游/下游工作项请各负责 AI 完成后通知 ai03 更新状态。**