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

200 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.
# student-bff 下游工作清单Next Steps
> 负责人ai04
> 更新日期2026-07-13
> 关联:[student-portal_contract.md](../../docs/architecture/issues/contracts/student-portal_contract.md)、[student-portal_workline.md](../../docs/architecture/issues/worklines/student-portal_workline.md)
---
## 1. 概述
student-bff 已完成全部 35 Query + 23 Mutation + 1 Subscription 的 schema 与 resolver 实现Docker 镜像本地构建与运行验证通过(`MOCK_UPSTREAM=false`)。下游 gRPC 服务未启动时BFF 进入降级模式(方案 B返回 `degraded: true` + `degradedReason` + `degradedFields`
**本地 Docker 测试结果2026-07-13**
- ✅ 镜像构建成功(`edu/student-bff:test`
- ✅ 容器启动正常(端口 3009NestFactory + GraphQL Yoga 初始化完成)
-`/healthz` 返回 200
-`MOCK_UPSTREAM=false`,下游未启动时进入降级模式
-`serverTime` Query 返回本地时间(无下游依赖)
-`myProfile` Query 返回 `degraded=true`,原因为 `DOWNSTREAM_FAILURE: iam.GetUserProfile failed after 3 attempts`
-`mySchedule` Query 返回空 items + `degraded=true`
-`markAsRead` Mutation 返回 `success=false` + `error.code=BFF_STUDENT_BAD_GATEWAY`
-`createLeaveRequest` Mutation 返回 `success=false` + `error.code=BFF_STUDENT_BAD_GATEWAY`
- ✅ B4 越权防御生效:无 `x-user-id` header 时返回 401 UnauthorizedError
- ✅ Kafka 软失败(不影响服务启动,仅 EventSubscriber 不工作)
---
## 2. 上游依赖api-gateway 路由)
### 2.1 api-gatewayai01 负责)
**阻塞级别P0必须完成才能端到端联调**
| # | 工作项 | 详情 |
| --- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| 1 | 新增 `/api/v1/student/graphql` 路由 | 当前 api-gateway 无此路由。需新增 POST `/api/v1/student/graphql` 代理到 student-bff :3009/graphqlARB-019 §21 |
| 2 | JWT 校验 + 用户身份注入 | api-gateway 校验 JWT 后,注入 `x-user-id` / `x-user-roles` / `x-request-id` header 到 student-bff |
| 3 | 学生角色校验 | `/api/v1/student/*` 路由组上添加 `student` 角色门禁,拒绝非 student 角色访问 |
| 4 | 限流配置 | student-bff 路由组配置 IP 级令牌桶限流 |
| 5 | 熔断/重试 | 对 student-bff 后端配置熔断器opossum 已在 student-bff 内部启用gateway 层可加外层熔断) |
**相关文件:**
- `services/api-gateway/main.go`(路由注册)
- `services/api-gateway/internal/middleware/auth.go`JWT 校验)
- `services/api-gateway/internal/proxy/proxy.go`(反向代理)
- `services/api-gateway/internal/config/config.go`(路由配置)
---
## 3. 下游依赖gRPC 微服务)
### 3.1 iam 服务ai06 负责)
**阻塞级别P0影响用户身份相关功能**
| # | gRPC 方法 | 用途 | 当前状态 |
| --- | ---------------- | ------------------------- | -------- |
| 1 | `GetUserProfile` | `myProfile` Query | ❌ 缺失 |
| 2 | `UpdateProfile` | `updateProfile` Mutation | ❌ 缺失 |
| 3 | `ChangePassword` | `changePassword` Mutation | ❌ 缺失 |
**proto 位置:** `packages/shared-proto/proto/iam/v1/iam.proto`
### 3.2 core-edu 服务ai08 负责)
**阻塞级别P0影响学生核心学习功能**
| # | gRPC 方法 | 用途 | 当前状态 |
| --- | ---------------------------- | ------------------------------ | -------- |
| 1 | `GetExam` | `examDetail` Query | ❌ 缺失 |
| 2 | `SubmitExam` | `submitExam` Mutation | ❌ 缺失 |
| 3 | `SaveExamDraft` | `saveExamDraft` Mutation | ❌ 缺失 |
| 4 | `RecordExamViolation` | `recordExamViolation` Mutation | ❌ 缺失 |
| 5 | `GetHomework` | `homeworkDetail` Query | ❌ 缺失 |
| 6 | `GetScheduleByStudent` | `mySchedule` Query | ❌ 缺失 |
| 7 | `ListLeaveRequestsByStudent` | `myLeaveRequests` Query | ❌ 缺失 |
| 8 | `CreateLeaveRequest` | `createLeaveRequest` Mutation | ❌ 缺失 |
| 9 | `CancelLeaveRequest` | `cancelLeaveRequest` Mutation | ❌ 缺失 |
| 10 | `GetReportCard` | `myReportCard` Query | ❌ 缺失 |
**proto 位置:** `packages/shared-proto/proto/core_edu/v1/core_edu.proto`
### 3.3 content 服务ai09 负责)
**阻塞级别P0影响学生内容浏览功能**
| # | gRPC 方法 | 用途 | 当前状态 |
| --- | --------------------------------- | -------------------------------- | -------- |
| 1 | `ListElectiveSelectionsByStudent` | `myElectiveSelections` Query | ❌ 缺失 |
| 2 | `ListAvailableElectiveCourses` | `availableElectiveCourses` Query | ❌ 缺失 |
| 3 | `SelectCourse` | `selectElectiveCourse` Mutation | ❌ 缺失 |
| 4 | `DropCourse` | `dropElectiveCourse` Mutation | ❌ 缺失 |
| 5 | `ListLessonPlansByStudent` | `myLessonPlans` Query | ❌ 缺失 |
| 6 | `GetLessonPlan` | `lessonPlanDetail` Query | ❌ 缺失 |
| 7 | `ListCoursePlansByStudent` | `myCoursePlans` Query | ❌ 缺失 |
| 8 | `GetCoursePlan` | `coursePlanDetail` Query | ❌ 缺失 |
**proto 位置:** `packages/shared-proto/proto/content/v1/content.proto`
### 3.4 data-ana 服务ai12 负责)
**阻塞级别P0影响学生学情分析功能**
| # | gRPC 方法 | 用途 | 当前状态 |
| --- | ------------------------------- | ------------------------------- | -------- |
| 1 | `GetStudentGrowth` | `studentGrowth` Query | ❌ 缺失 |
| 2 | `GetAssignmentAnalysis` | `assignmentAnalysis` Query | ❌ 缺失 |
| 3 | `GetMasterySummary` | `myMasterySummary` Query | ❌ 缺失 |
| 4 | `ListDiagnosticReports` | `myDiagnosticReports` Query | ❌ 缺失 |
| 5 | `ListErrorBookItems` | `myErrorBook` Query | ❌ 缺失 |
| 6 | `ListPracticeSessionsByStudent` | `myPracticeSessions` Query | ❌ 缺失 |
| 7 | `StartPracticeSession` | `startPracticeSession` Query | ❌ 缺失 |
| 8 | `SubmitPracticeAnswer` | `submitPracticeAnswer` Mutation | ❌ 缺失 |
**proto 位置:** `packages/shared-proto/proto/data_ana/v1/data_ana.proto`
### 3.5 msg 服务ai10 负责)
**阻塞级别P0影响学生通知与公告功能**
| # | gRPC 方法 | 用途 | 当前状态 |
| --- | ------------------------------ | --------------------------------------- | -------- |
| 1 | `ListAnnouncements` | `announcements` Query | ❌ 缺失 |
| 2 | `GetAnnouncement` | `announcementDetail` Query | ❌ 缺失 |
| 3 | `MarkNotificationAsRead` | `markAsRead` Mutation | ❌ 缺失 |
| 4 | `MarkAllNotificationsAsRead` | `markAllAsRead` Mutation | ❌ 缺失 |
| 5 | `UpdateNotificationPreference` | `updateNotificationPreference` Mutation | ❌ 缺失 |
| 6 | `MarkAnnouncementRead` | `markAnnouncementRead` Mutation | ❌ 缺失 |
**proto 位置:** `packages/shared-proto/proto/msg/v1/msg.proto`
### 3.6 ai 服务ai11 负责)
**阻塞级别P1影响 AI 辅助功能,可降级)**
| # | gRPC 方法 | 用途 | 当前状态 |
| --- | -------------- | ----------------------- | -------- |
| 1 | `StreamAIChat` | `aiStream` Subscription | ❌ 缺失 |
**proto 位置:** `packages/shared-proto/proto/ai/v1/ai.proto`
### 3.7 push-gatewayai13 负责)
**阻塞级别P1影响实时推送**
| # | 工作项 | 详情 |
| --- | ------------------ | ---------------------------------------------------------------- |
| 1 | WebSocket 推送端点 | student-bff EventSubscriber 接收 Kafka 事件后转发到 push-gateway |
| 2 | Kafka topic 对齐 | student-bff 订阅 `student.notification.*` 等 topic |
---
## 4. student-bff 已完成项汇总
| 工作项 | 状态 | 验证方式 |
| ------------------------------------------- | ---- | ------------------------------------------- |
| Schema 扩展13Q+2M → 35Q+23M+1S | ✅ | `pnpm typecheck` + GraphQL Playground 校验 |
| 22 个扩展 Query Resolver | ✅ | Docker 容器 GraphQL 请求测试 |
| 21 个扩展 Mutation Resolver | ✅ | Docker 容器 GraphQL 请求测试 |
| Zod 输入校验21 个 Mutation Input Schema | ✅ | typecheck + 运行时校验 |
| B4 越权防御assertOwnData | ✅ | 无 `x-user-id` 返回 401 |
| 降级模式(方案 B | ✅ | 下游不可用时返回 `degraded=true` + 原因 |
| Redis 缓存B6 5-30s TTL | ✅ | CacheService 已注入TTL 预设已配置 |
| Kafka EventSubscriber软失败 | ✅ | Kafka 不可用时不阻塞启动 |
| DataLoader 批量加载 | ✅ | createDataLoaders 已注入 context |
| Dockerfile 多阶段构建 | ✅ | `edu/student-bff:test` 构建成功 |
| Docker 本地测试MOCK_UPSTREAM=false | ✅ | healthz + GraphQL Query/Mutation 全部按预期 |
---
## 5. 联调顺序建议
1. **ai06** 完成 iam gRPCGetUserProfile / UpdateProfile / ChangePassword
2. **ai08** 完成 core-edu gRPCGetExam / SubmitExam / GetHomework / GetScheduleByStudent 等 10 个)
3. **ai09** 完成 content gRPC8 个选修/教案/课程计划相关)
4. **ai12** 完成 data-ana gRPC8 个学情分析相关)
5. **ai10** 完成 msg gRPC6 个通知/公告相关)
6. **ai01** 完成 api-gateway `/api/v1/student/graphql` 路由 + JWT 注入
7. **ai11** 完成 ai gRPC StreamAIChatP1
8. **ai13** 完成 push-gateway WebSocketP1
9. 端到端联调student-portal → api-gateway → student-bff → 6 个下游 gRPC 服务)
---
## 6. 已知限制
| # | 限制 | 说明 |
| --- | ------------------------------------- | ------------------------------------------------------------------------------------------ |
| 1 | Kafka 未启动时 EventSubscriber 软失败 | 服务正常启动,但实时事件推送(通知/AI 流式响应)不工作 |
| 2 | 下游 gRPC 未就绪时进入降级模式 | 所有 Query 返回 `degraded=true` + 空数据;所有 Mutation 返回 `success=false` + BAD_GATEWAY |
| 3 | DEV_MODE=true 时跳过 B4 越权校验 | 生产环境必须 `DEV_MODE=false`,由 api-gateway 注入 `x-user-id` header |
| 4 | pino-pretty 仅 devDependencies | 生产环境 `NODE_ENV=production` 时不启用 pino-pretty transport输出结构化 JSON |
| 5 | OTEL_EXPORTER_OTLP_ENDPOINT 未配置 | Tracer 被禁用,需配置 OTLP endpoint 启用全链路追踪 |
---
**本文件由 ai04 维护,下游工作项请各负责 AI 完成后通知 ai04 更新状态。**