Files
Edu/docs/architecture/issues/contracts/teacher-bff_contract.md

21 KiB
Raw Permalink Blame History

teacher-bff 对接契约

负责人ai03 版本v22026-07-10对齐 president §2.7/§2.17/§5.1 + coord B5/B8 + port-allocation §5 关联:matrix.mdiam.protocore_edu.protocontent.protoanalytics.protomsg.protoai.protocoord-final-decisions.md §2 B1-B8president-final-rulings.md §2.7/§2.17/§5.1


§1 我提供什么(对外接口)

1.1 gRPC 接口(如有)

无对外 gRPC。teacher-bff 是 GraphQL 聚合层B1 裁决P2 起直接 GraphQL

1.2 HTTP 端点(如有)

Method Path 用途 认证 裁决依据
POST /graphql 教师 BFF GraphQL 端点 JWT 必需 + teacher 角色 B1
GET /graphql GraphQL Playground开发环境生产关闭 开发环境公开 ARB-001
GET /healthz 健康检查liveness 公开 G3
GET /readyz 就绪检查readiness按阶段扩展下游探针 公开 G2 + §2.4

1.3 GraphQL schema如 BFF

SDL-firstpresident §2.17 裁决schema 文件路径:

packages/shared-ts/contracts/graphql/teacher-bff.schema.graphql

文件命名遵循 president §2.17 统一规范 <bff-name>.schema.graphql,由 ai03 起草、coord 在批次 1 启动前仲裁第一版。 前端 AIai13/ai16通过 graphql-codegen 生成 TS 类型消费。

核心 Query / Mutation 域:

Query / Mutation 聚合下游 阶段
auth currentUser iam.GetUserInfo + GetEffectivePermissions + GetViewports P2
dashboard teacherDashboard P2: iam gRPC用户基础信息下游字段返 null + extensions.warning
P3+: data-ana.GetTeacherDashboard
P2 null → P4 真实
classes myClasses P2: iam gRPC按 president §3.5P2 班级列表来自 iam 数据)
P3+: core-edu.ClassService.GetClassesByTeacher
P2 iam → P3 core-edu
students classStudents core-edu.ClassService.ListStudentsByClass + iam.BatchGetUsers P3+
exams classExams / createExam / updateExam / deleteExam core-edu.ExamService P3+
homework classHomework / assignHomework core-edu.HomeworkService P3+
grades studentGrades / recordGrade core-edu.GradeService P3+
attendance classAttendance / recordAttendance core-edu.AttendanceServiceC4 裁决 P3 补全) P3+
content textbooks / chapters / knowledgePoints / questions content 4 个 Service P4+
notifications myNotifications / markAsRead msg.NotificationService P5+
ai aiChat / generateQuestion / generateLessonPlan ai.AiServiceA4 裁决 P5 补全 GenerateLessonPlan P5+
admin.* admin.schoolStats / admin.listClasses / admin.listTeachers 等 admin 命名空间,复用 teacher-bff endpointpresident §5.1 P2 预留 schema / P6 实现

admin 命名空间预留president §5.1 + §7.3 强制):

  • P2 预留schema 文件中预留 admin.* Query/Mutation 命名空间占位(含类型定义但 Resolver 返 null
  • P6 实现ai16 admin-portal 复用 teacher-bff GraphQL endpointai03 在 P6 实现 admin Resolver 真实数据
  • 理由admin 操作低 QPS无需独立 admin-bff 服务;减少 ai16 工作量

1.4 Kafka 事件发布(如有)

无。teacher-bff 不发布事件,仅做 gRPC 聚合B7 裁决P2-P4 不订阅 KafkaP5 push-gateway 落地后再订阅)。

1.5 错误码前缀

BFF_TEACHER_B5 + G14 裁决,统一 BFF_ 前缀)。

BFF 越权防御 3 类错误码president §2.7 裁决):

错误码 HTTP 场景 i18n key
BFF_TEACHER_UNAUTHORIZED 401 x-user-id 缺失或无效 error.bffTeacher.unauthorized
BFF_TEACHER_FORBIDDEN_RESOURCE 403 teacherId 与资源无归属关系(场景 A error.bffTeacher.forbidden_resource
BFF_TEACHER_IDENTITY_MISMATCH 403 JWT teacherId 与请求 body teacherId 不一致(场景 B error.bffTeacher.identity_mismatch

其他 BFF_TEACHER_ 错误码(聚合层):

错误码 HTTP 场景
BFF_TEACHER_UPSTREAM_UNAVAILABLE 502 下游 gRPC 不可达
BFF_TEACHER_AGGREGATION_FAILED 500 聚合多下游时部分失败且无降级数据
BFF_TEACHER_VALIDATION_FAILED 400 输入参数校验失败
BFF_TEACHER_INTERNAL_ERROR 500 兜底内部错误

B3 裁决澄清BFF 豁免 @RequirePermission 指不做"功能权限决策",但必须做"数据权限防御"B4 越权防御,见 §3.3)。


§2 我消费什么(依赖上游)

2.1 gRPC 调用(同步)

B2 裁决:首次实现即 gRPC 调用下游,禁止 REST fetch 过渡。 B8 裁决:通过 DownstreamClient 抽象统一封装BFF 模式 v2 标准抽象3 个 BFF 共用)。

RPC 现状标注说明

  • = proto 中已定义(按 packages/shared-proto/proto/ 现状核对)
  • = proto 中未定义,待 coord 补全(已在裁决中明确补全时机)

2.1.1 iam (ai06) — gRPC 50052

Service.RPC 用途 现状 阶段 mock 策略
IamService.GetUserInfo 获取当前教师信息 P2 返回固定 UserInfoteacher 角色)
IamService.GetViewports 教师导航菜单 P2 返回固定视口列表(待 coord 补 proto
IamService.GetEffectivePermissions 权限校验 P2 返回全权限(放行)
IamService.BatchGetUsers 批量补全学生姓名 P3+ 返回固定用户名("学生001"~"学生030"
IamService.GetEffectiveDataScope 数据范围校验 P3+ 返回 OWN 范围
IamService.GetChildrenByParent parent-bff 用) P4 teacher-bff 不调用

iam.proto 现状仅 4 RPCRegister/Login/RefreshToken/GetUserInfomatrix.md §2 标称 12 RPC待 ai06 + coord 按 I1-I8 裁决补全。

2.1.2 core-edu (ai08) — gRPC 50053

Service.RPC 用途 现状 阶段 mock 策略
ExamService.CreateExam 创建考试 P3 返回固定 examId
ExamService.GetExam 获取考试详情 P3 返回固定考试数据
ExamService.ListExamsByClass 按班级列考试 P3 返回固定 5 场考试
ExamService.UpdateExam 更新考试 P3 返回 success=true
ExamService.DeleteExam 删除考试 P3 返回 success=true
HomeworkService.AssignHomework 布置作业 P3 返回固定 homeworkId
HomeworkService.GetHomework 获取作业详情 P3 返回固定作业数据
HomeworkService.ListHomeworkByClass 按班级列作业 P3 返回固定 5 份作业
HomeworkService.SubmitHomework 提交作业 P3 返回 success=truestudent-bff 用)
GradeService.RecordGrade 录入成绩 P3 返回 success=true
GradeService.GetGrade 获取成绩 P3 返回固定成绩数据
GradeService.ListGradesByStudent 按学生列成绩 P3 返回固定 10 条成绩
GradeService.ListGradesByExam 按考试列成绩 P3 返回固定 30 条成绩
GradeService.ListGradesByHomework 按作业列成绩 P3 返回固定 30 条成绩
ClassService.GetClassesByTeacher 教师班级列表 P3 返回固定 3 个 ClassInfo
ClassService.ListStudentsByClass 班级学生名单 P3 返回固定 30 个 StudentInfo
ClassService.BatchGetClasses 批量获取班级 P3 返回固定班级数据
AttendanceService.RecordAttendance 记录考勤 P3 返回 success=trueC4 裁决补全)
AttendanceService.GetClassAttendance 查询考勤 P3 返回固定考勤数据C4 裁决补全)

core_edu.proto 现状 14 RPCExamService 5 + HomeworkService 4 + GradeService 5matrix.md §2 标称 22 RPC 5 Service待 coord 按 C4/C5 裁决补 AttendanceService + ClassServiceGetClassesByTeacher / ListStudentsByClass / BatchGetClasses

2.1.3 content (ai09) — gRPC 50054

Service.RPC 用途 现状 阶段 mock 策略
TextbookService.ListTextbooks 教材列表 P4 返回固定 5 个教材
TextbookService.GetTextbook 获取教材详情 P4 返回固定教材数据
TextbookService.CreateTextbook 创建教材 P4 返回固定 textbookId
KnowledgeGraphService.GetPrerequisites 知识点前置 P4 返回固定知识点依赖
KnowledgeGraphService.GetLearningPath 学习路径 P4 返回固定学习路径
ChapterService.ListChapters 章节列表 P4 返回固定章节树N5 裁决补全)
ChapterService.GetChapter 章节详情 P4 返回固定章节N5 裁决补全)
QuestionService.SearchQuestions 题库检索 P4 返回固定 20 题N3 裁决补全)

content.proto 现状 5 RPCTextbookService 3 + KnowledgeGraphService 2matrix.md §2 标称 18 RPC 4 Service待 coord 按 N3/N5 裁决补 ChapterService + QuestionService。

2.1.4 data-ana (ai11) — gRPC 50055

Service.RPC 用途 现状 阶段 mock 策略
AnalyticsService.GetClassPerformance 班级成绩分析 P4 返回固定分析数据
AnalyticsService.GetStudentWeakness 学生薄弱点 P4 返回固定 3 个薄弱知识点
AnalyticsService.GetLearningTrend 学习趋势 P4 返回固定 12 个月趋势
AnalyticsService.GetTeacherDashboard 教师仪表盘 P4 返回固定仪表盘数据D4 裁决补全)
AnalyticsService.GetWarningList 预警列表 P4 返回固定 5 条预警D4 裁决补全)
AnalyticsService.GetMasteryDistribution 知识掌握分布 P4 返回固定分布数据D4 裁决补全)
AnalyticsService.SubscribeMasteryUpdate (stream) 掌握度订阅 P5+ 流式 mockD4 裁决补全)

analytics.proto 现状 3 RPCmatrix.md §2 标称 12 RPC待 coord 按 D4 裁决补全 4 端 Dashboard + Warning + MasteryDistribution + SubscribeMasteryUpdate Stream RPC。

2.1.5 msg (ai10) — gRPC 50056

Service.RPC 用途 现状 阶段 mock 策略
NotificationService.SendNotification 发送通知 P5 返回固定 notificationId
NotificationService.ListNotifications 教师通知列表 P5 返回固定 10 条通知
NotificationService.MarkAsRead 标记已读 P5 返回 success=true
NotificationService.SearchNotifications 搜索通知 P5 返回固定搜索结果
NotificationPreferenceService.* 通知偏好 P5 返回默认偏好(待 coord 补 proto
NotificationTemplateService.* 通知模板 P5 返回固定模板(待 coord 补 proto

msg.proto 现状 4 RPCNotificationServicematrix.md §2 标称 13 RPC 3 Service待 coord 补 NotificationPreferenceService + NotificationTemplateService。

2.1.6 ai (ai12) — gRPC 50058

Service.RPC 用途 现状 阶段 mock 策略
AiService.Chat AI 对话 P5 返回固定回复
AiService.StreamChat (stream) 流式对话 P5 流式 mockSSE
AiService.GenerateQuestion AI 出题 P5 返回固定题目
AiService.OptimizeExpression 表达优化 P5 返回固定优化结果
AiService.GenerateLessonPlan AI 备课 P5 返回固定教案A4 裁决补全)
AiService.StreamGenerateQuestion (stream) 流式出题 P5 流式 mockA4 裁决补全)

ai.proto 现状 4 RPCmatrix.md §2 标称 6 RPC待 coord 按 A4 裁决补 GenerateLessonPlan + StreamGenerateQuestion。 端口说明ai 服务端口为 50058port-allocation.md §5 最终值push-gateway 50057 豁免释放后 50058 让给 ai

2.2 Kafka 事件订阅(异步)

无。teacher-bff 不订阅 Kafka 事件B7 裁决P2-P4 不订阅仅同步聚合P5 push-gateway 落地后再订阅,届时评估订阅 edu.notification.* 用于实时通知推送)。

2.3 HTTP 调用(如有)

无。B2 裁决:首次实现即 gRPC禁止 REST fetch。


§3 就绪信号

3.1 我依赖的上游就绪标志

上游 AI 就绪信号 阶段
iam ai06 gRPC 50052 + 12 RPC + HealthService SERVING P2
core-edu ai08 gRPC 50053 + 22 RPC + HealthService SERVING P3
content ai09 gRPC 50054 + 18 RPC + HealthService SERVING P4
data-ana ai11 gRPC 50055 + 12 RPC + HealthService SERVING P4
msg ai10 gRPC 50056 + 13 RPC + HealthService SERVING P5
ai ai12 gRPC 50058 + 6 RPC + HealthService SERVING P5
coord coord shared-ts DownstreamClient 抽象包就绪B8 裁决) P2 启动前
coord coord teacher-bff.schema.graphql 第一版仲裁完成(含 admin namespace P2 启动前

3.2 我的就绪标志(供下游消费)

信号 阶段 消费方
teacher-bff GraphQL :3003 启用(/healthz 200 P2 teacher-portal
/readyz 返回 200按阶段扩展探针见 §3.3 P2+ api-gateway
GraphQL schema 可内省POST /graphql P2 teacher-portal / admin-portal
核心 Query 可执行currentUser / myClasses / teacherDashboard P2 teacher-portal
核心 Mutation 可执行createExam / assignHomework / recordGrade P3 teacher-portal
admin namespace 预留schema 含 admin.* 类型P6 实现 Resolver P2 预留 / P6 实现 admin-portal
DownstreamClient 抽象落地3 BFF 共用B8 P2 student-bff / parent-bff

3.3 /readyz 探针按阶段扩展president §2.4 + G2

DownstreamHealthCheck 注册表模式,每个下游注册独立探针,按阶段启用:

阶段 探针列表 项数
P2 Redis PING + iam gRPC 50052 2
P3 + core-edu gRPC 50053 3
P4 + content gRPC 50054 + data-ana gRPC 50055 5
P5 + ai gRPC 50058 + msg gRPC 50056 7

总裁裁决 §2.4:探针列表扩展属"跨阶段扩展例外"president §2.3),允许新增探针但禁止修改已有探针检查项。 软失败规则必需依赖Redis / 已启用 gRPC 下游)失败返 503可选依赖Kafka 消费 / 未启用 gRPC 下游)失败仅告警返 200 + degraded: true

3.4 越权防御B4 + president §2.9

AuthorizationGuard 实现 teacherId 与资源归属校验:

阶段 实现方式 裁决依据
P2 DEV_MODE 放行(环境变量 TEACHER_BFF_DEV_MODE=true+ 日志告警 §2.9
P3+ 接入 core-edu gRPC 真实校验GetClassesByTeacher 比对 teacherId §2.9

B3 裁决澄清BFF 豁免 @RequirePermission 不做"功能权限决策",但必须做"数据权限防御"B4。错误码见 §1.5。


§4 Mock 策略

4.1 我提供的 mock

在 teacher-bff 真实就绪前为下游teacher-portal / admin-portal提供以下 mock

  • GraphQL mock:使用 Apollo Server mockProviders 或 MSW 拦截 POST /graphql
    • currentUser 返回固定教师id="teacher-001", name="张老师", roles=["teacher"]
    • myClasses 返回固定 3 个班级
    • teacherDashboard 返回固定仪表盘数据
    • myNotifications 返回固定 10 条通知
  • admin namespace mockadmin-portal 查询返回固定管理员视角数据(全校统计)

4.2 我消费的 mock

在真实上游就绪前teacher-bff 使用以下 mock详见 §2.1 各表的 mock 策略列):

  • iam mock:固定 UserInfo + 全权限 + 固定视口
  • core-edu mock:固定班级/学生/考试/作业/成绩/考勤数据
  • content mock:固定教材/章节/知识点/题目
  • data-ana mock:固定仪表盘/分析/预警
  • msg mock:固定通知列表 + MarkAsRead success
  • ai mock:固定 AI 回复/题目/教案

所有上游 mock 通过 gRPC client 拦截器实现DownstreamClient 抽象内置 mock 开关B8 裁决),上游就绪后移除拦截器切换真实调用。