# student-bff 对接契约

> 负责人：ai04
> 关联：[matrix.md](./matrix.md)、[iam.proto](../../../packages/shared-proto/proto/iam.proto)、[core_edu.proto](../../../packages/shared-proto/proto/core_edu.proto)、[content.proto](../../../packages/shared-proto/proto/content.proto)、[analytics.proto](../../../packages/shared-proto/proto/analytics.proto)、[msg.proto](../../../packages/shared-proto/proto/msg.proto)

---

## §1 我提供什么（对外接口）

### 1.1 gRPC 接口（如有）

无对外 gRPC。student-bff 是 GraphQL 聚合层。

### 1.2 HTTP 端点（如有）

| Method | Path     | 用途                                      | 认证                    |
| ------ | -------- | ----------------------------------------- | ----------------------- |
| POST   | /graphql | 学生 BFF GraphQL 端点                     | JWT 必需 + student 角色 |
| GET    | /graphql | GraphQL Playground（开发环境）            | 开发环境公开            |
| GET    | /healthz | 健康检查（liveness）                      | 公开                    |
| GET    | /readyz  | 就绪检查（readiness，含下游 gRPC 连通性） | 公开                    |

### 1.3 GraphQL schema（如 BFF）

GraphQL schema 文件路径：`apps/student-bff/src/schema/*.graphql`（端口 :3009）

核心 Query / Mutation 域：

- **auth**：currentUser（聚合 iam.GetUserInfo + GetEffectivePermissions + GetViewports）
- **myClasses**：我的班级（聚合 core-edu.ClassService.GetClass + ListStudentsByClass）
- **myExams**：我的考试列表（聚合 core-edu.ExamService.ListExamsByClass）
- **myHomework**：我的作业（聚合 core-edu.HomeworkService.ListHomeworkByClass + SubmitHomework）
- **myGrades**：我的成绩（聚合 core-edu.GradeService.ListGradesByStudent）
- **myAttendance**：我的考勤（聚合 core-edu.AttendanceService.ListAttendanceByStudent）
- **content**：textbooks / chapters / learningPath（聚合 content.KnowledgeGraphService.GetLearningPath）
- **dashboard**：studentDashboard（聚合 data-ana.AnalyticsService.GetStudentDashboard）
- **weakness**：myWeakness（聚合 data-ana.AnalyticsService.GetStudentWeakness）
- **trend**：myTrend（聚合 data-ana.AnalyticsService.GetLearningTrend）
- **notifications**：myNotifications / markAsRead（聚合 msg.NotificationService）

### 1.4 Kafka 事件发布（如有）

无。student-bff 不发布事件，仅做 gRPC 聚合。

### 1.5 错误码前缀

`BFF_STUDENT_`（如 BFF_STUDENT_UPSTREAM_UNAVAILABLE、BFF_STUDENT_AGGREGATION_FAILED、BFF_STUDENT_FORBIDDEN）

---

## §2 我消费什么（依赖上游）

### 2.1 gRPC 调用（同步）

| 被调用方        | Service.RPC                               | 用途             | mock 策略                                   |
| --------------- | ----------------------------------------- | ---------------- | ------------------------------------------- |
| iam (ai06)      | IamService.GetUserInfo                    | 获取当前学生信息 | iam 就绪前返回固定 UserInfo（student 角色） |
| iam (ai06)      | IamService.GetEffectivePermissions        | 权限校验         | iam 就绪前返回学生权限集                    |
| iam (ai06)      | IamService.GetViewports                   | 学生导航菜单     | iam 就绪前返回固定视口列表                  |
| core-edu (ai08) | ClassService.GetClass                     | 我的班级详情     | core-edu 就绪前返回固定 ClassInfo           |
| core-edu (ai08) | ClassService.ListStudentsByClass          | 班级同学名单     | core-edu 就绪前返回固定 30 个 StudentInfo   |
| core-edu (ai08) | ExamService.ListExamsByClass              | 我的考试         | core-edu 就绪前返回固定 2 个 Exam           |
| core-edu (ai08) | HomeworkService.ListHomeworkByClass       | 我的作业         | core-edu 就绪前返回固定 3 个 Homework       |
| core-edu (ai08) | HomeworkService.SubmitHomework            | 提交作业         | core-edu 就绪前返回 success=true            |
| core-edu (ai08) | GradeService.ListGradesByStudent          | 我的成绩         | core-edu 就绪前返回固定 5 个 Grade          |
| core-edu (ai08) | AttendanceService.ListAttendanceByStudent | 我的考勤         | core-edu 就绪前返回固定 10 条 Attendance    |
| content (ai09)  | TextbookService.ListTextbooks             | 教材列表         | content 就绪前返回固定 5 个教材             |
| content (ai09)  | ChapterService.ListChapters               | 章节列表         | content 就绪前返回固定章节树                |
| content (ai09)  | KnowledgeGraphService.GetLearningPath     | 学习路径         | content 就绪前返回固定 8 个知识点推荐顺序   |
| data-ana (ai11) | AnalyticsService.GetStudentDashboard      | 学生仪表盘       | data-ana 就绪前返回固定仪表盘               |
| data-ana (ai11) | AnalyticsService.GetStudentWeakness       | 我的薄弱点       | data-ana 就绪前返回固定 3 个 weak_points    |
| data-ana (ai11) | AnalyticsService.GetLearningTrend         | 学习趋势         | data-ana 就绪前返回固定趋势数据             |
| msg (ai10)      | NotificationService.ListNotifications     | 学生通知         | msg 就绪前返回固定 10 条通知                |
| msg (ai10)      | NotificationService.MarkAsRead            | 标记已读         | msg 就绪前返回 success=true                 |

### 2.2 Kafka 事件订阅（异步）

无。student-bff 不订阅 Kafka 事件，仅做同步 gRPC 聚合。

### 2.3 HTTP 调用（如有）

无。

---

## §3 就绪信号

### 3.1 我依赖的上游就绪标志

- [ ] iam gRPC 50052 启用（ai06）
- [ ] core-edu gRPC 50053 启用（ai08）
- [ ] content gRPC 50054 启用（ai09）
- [ ] data-ana gRPC 50055 启用（ai11）
- [ ] msg gRPC 50056 启用（ai10）

### 3.2 我的就绪标志（供下游消费）

- [ ] student-bff GraphQL :3009 启用（/healthz 返回 200）
- [ ] /readyz 返回 200（含 5 个下游 gRPC 连通性检查）
- [ ] GraphQL schema 可内省（POST /graphql 返回 schema）
- [ ] 核心 Query 可执行：currentUser / myClasses / studentDashboard / myGrades
- [ ] 核心 Mutation 可执行：submitHomework / markAsRead

---

## §4 Mock 策略

### 4.1 我提供的 mock

在 student-bff 真实就绪前，为下游（student-portal）提供以下 mock：

- **GraphQL mock**：使用 Apollo Server mockProviders 或 MSW 拦截 POST /graphql
  - currentUser 返回固定学生（id="student-001", name="李同学", roles=["student"]）
  - myClasses 返回固定 1 个班级
  - studentDashboard 返回固定仪表盘（avg_score=85.0, class_rank=5）
  - myGrades 返回固定 5 个成绩
  - myHomework 返回固定 3 个作业（1 个待提交）
  - myNotifications 返回固定 10 条通知

### 4.2 我消费的 mock

在真实上游就绪前，student-bff 使用以下 mock（详见 §2.1 mock 策略列）：

- **iam mock**：固定 UserInfo + 学生权限 + 固定视口
- **core-edu mock**：固定班级/同学/考试/作业/成绩/考勤
- **content mock**：固定教材/章节/学习路径
- **data-ana mock**：固定仪表盘/薄弱点/趋势
- **msg mock**：固定通知列表 + MarkAsRead success

> 所有上游 mock 通过 gRPC client 拦截器实现，上游就绪后移除拦截器切换真实调用。
