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

14 KiB
Raw Permalink Blame History

parent-bff 对接契约

负责人ai05 关联:matrix.mdiam.protocore_edu.protoanalytics.protomsg.proto02-architecture-design.md 修订2026-07-10 ai05 复审修正仲裁引用、proto 包名、契约缺口标注)


§0 契约基线说明

维度 内容
proto 包名前缀 所有 proto 包名统一为 next_edu_cloud.<domain>.v1(如 next_edu_cloud.iam.v1),引用 proto message 时须带完整包名
GraphQL schema 文件 packages/shared-ts/contracts/graphql/parent-bff.graphqlSDL-first 集中管理,对齐 coord ARB-001 模式)
错误码前缀 BFF_PARENT_C1 仲裁BFF 在前)
端口 HTTP 3010不暴露 gRPCC2 仲裁)
API 风格 GraphQL YogaU3 仲裁P4 直接 GraphQL不走 REST 过渡)
权限校验 BFF 豁免 @RequirePermissionU4 仲裁),仅校验 x-user-id + ChildGuard 越权防御

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

1.1 gRPC 接口

无对外 gRPC。parent-bff 是 GraphQL 聚合层,对上游仅暴露 HTTP/GraphQLC2 仲裁)。

1.2 HTTP 端点

Method Path 用途 认证 阶段
POST /graphql 家长 BFF GraphQL 端点U3 仲裁) JWT 必需 + parent 角色 P4
GET /graphql GraphQL Playground仅开发环境 开发环境公开 P4
GET /healthz 健康检查liveness直接返回 ok 公开 P4
GET /readyz 就绪检查readiness含下游 gRPC 连通性02 §9 #7 公开 P4
GET /metrics Prometheus 指标parent_bff_* 公开 P4

网关路径:/api/v1/parent/* → api-gateway 剥离 /api/v1 后代理到 parent-bff:3010 不实现 REST 业务端点02 §4.1,仅保留 /healthz /readyz /metrics 基础端点)

1.3 GraphQL schema

schema 文件packages/shared-ts/contracts/graphql/parent-bff.graphqlSDL-first 完整 schema 定义:见 02-architecture-design.md §4.2 GraphQL Schema 完整定义

核心 Query / Mutation 域(按阶段分级):

类型 字段 聚合下游 ChildGuard 阶段
Query dashboard iam + core-edu 否(聚合所有孩子) P4
Query viewports iam P4
Query me iam P4
Query children iam P4
Query child iam + core-edu P4
Query childGrades core-edu P4
Query childHomework core-edu P4
Query childExams core-edu P4
Query childAnalytics data-ana P4
Query notifications msg P5
Query notificationPreferences msg P5
Mutation selectChild BFF 内部审计) P4
Mutation markNotificationRead msg P5
Mutation updateNotificationPreferences msg P5

统一响应信封GraphQL 规范data/errors错误扩展字段携带 extensions.code = "BFF_PARENT_*"02 §4.5

1.4 Kafka 事件发布

无。parent-bff 不发布领域事件BFF 聚合层无业务状态变更02 §5.6)。

1.5 错误码前缀

BFF_PARENT_C1 仲裁BFF 在前;非 PARENT_BFF_

错误码清单(完整见 02 §6.2

错误码 HTTP 触发条件
BFF_PARENT_VALIDATION_ERROR 400 Zod / GraphQL input 校验失败
BFF_PARENT_UNAUTHORIZED 401 缺失 x-user-id 头
BFF_PARENT_CHILD_NOT_BOUND 403 ChildGuard 拦截childId 不在家长绑定列表
BFF_PARENT_NOT_FOUND 404 资源不存在
BFF_PARENT_BAD_GATEWAY 502 下游服务返回非 ok 或 gRPC rejected
BFF_PARENT_GATEWAY_TIMEOUT 504 下游调用超时
BFF_PARENT_SERVICE_UNAVAILABLE 503 熔断器开启P6
BFF_PARENT_INTERNAL_ERROR 500 未捕获异常

下游错误透传C3 仲裁core-edu 统一 CORE_EDU_*

下游服务 错误码前缀 示例
iam IAM_ IAM_USER_NOT_FOUND
core-edu CORE_EDU_ CORE_EDU_GRADE_NOT_FOUND
data-ana DATA_ANA_ DATA_ANA_ANALYTICS_NOT_READY
msg MSG_ MSG_NOTIFICATION_NOT_FOUND

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

2.1 gRPC 调用(同步)

proto 包名均为 next_edu_cloud.<domain>.v1 状态标注 已有 = proto 已定义; 待补 = proto 缺失;⚠️ 待仲裁 = ai05 提请 coord 仲裁中

被调用方 Service.RPC proto message 包名 用途 mock 策略 状态
iam (ai06) IamService.GetUserInfo next_edu_cloud.iam.v1.UserInfo 获取当前家长信息 返回固定 UserInfoparent 角色) 已有
iam (ai06) IamService.GetViewports next_edu_cloud.iam.v1.Viewport[] 家长导航菜单 返回固定视口列表 待 ai06 补coord-cross-review #1
iam (ai06) IamService.GetEffectivePermissions next_edu_cloud.iam.v1.EffectivePermissions 权限校验 返回家长权限集 待 ai06 补
iam (ai06) IamService.GetChildrenByParent next_edu_cloud.iam.v1.Child[] 查询关联孩子列表(P0 核心依赖 返回固定 2 个 ChildInfo 待 ai06 补(I6 裁决P0 阻塞)
core-edu (ai08) GradeService.ListGradesByStudent next_edu_cloud.core_edu.v1.Grade[] 孩子成绩 返回固定 5 个 Grade 已有
core-edu (ai08) HomeworkService.ListHomeworkByClass next_edu_cloud.core_edu.v1.Homework[] 孩子作业 返回固定 3 个 Homework 已有
core-edu (ai08) ExamService.ListExamsByClass next_edu_cloud.core_edu.v1.Exam[] 孩子考试 返回固定 3 个 Exam 已有
core-edu (ai08) ClassService.GetClass next_edu_cloud.core_edu.v1.Class 孩子班级信息 返回固定 ClassInfo 待补(ISSUE-008proto 缺 ClassService待 coord 仲裁归属)
core-edu (ai08) AttendanceService.ListAttendanceByStudent next_edu_cloud.core_edu.v1.Attendance[] 孩子考勤P5+ 返回固定 10 条 待 ai08 补coord-cross-review #5P3 补全)
data-ana (ai11) AnalyticsService.GetStudentWeakness next_edu_cloud.analytics.v1.StudentWeakness 孩子薄弱点 返回固定 3 个 weak_points 已有
data-ana (ai11) AnalyticsService.GetLearningTrend next_edu_cloud.analytics.v1.LearningTrend 孩子学习趋势 返回固定趋势数据 已有
data-ana (ai11) AnalyticsService.GetClassPerformance next_edu_cloud.analytics.v1.ClassPerformance 班级学情对比 返回固定班级数据 已有
data-ana (ai11) AnalyticsService.GetParentDashboard 家长仪表盘聚合(多子女防 N+1 返回固定仪表盘 ⚠️ 待仲裁02 §14 #3ai05 提请proto 未定义)
msg (ai10) NotificationService.ListNotifications next_edu_cloud.msg.v1.Notification[] 家长通知 返回固定 10 条通知 已有
msg (ai10) NotificationService.MarkAsRead next_edu_cloud.msg.v1.Empty 标记已读 返回 success 已有
msg (ai10) NotificationPreferenceService.* 通知偏好配置 返回固定偏好 待 ai10 补proto + 实现均缺失P5

类型映射注意ISSUE-008

  • core_edu.v1.Grade.scorestring 类型GraphQL Grade.scoreFloat!BFF response-mapper 需做 Number.parseFloat(score) 转换,转换失败抛 BFF_PARENT_BAD_GATEWAY
  • msg.v1.Notification.is_read 映射为 GraphQL Notification.read(字段名重命名)
  • msg.v1.Notificationchild_id 字段ISSUE-007GraphQL Notification.childId 暂从 notification.type+content 解析或置 null待 ai10 补 proto 字段

2.2 Kafka 事件订阅异步P5 可选)

P4 阶段不订阅事件02 §5.1。P5 阶段可选订阅以下 topic 用于实时推送 + 缓存失效02 §5.2)。

Topic 事件 发布方 消费动作 幂等性 阶段
edu.notification.sent 通知发送 msg 推送给家长push-gateway HTTP event_id SETNX P5
edu.notification.read 通知已读 msg 失效 bff:parent:notifications:* event_id SETNX P5
edu.notification.recalled 通知撤回 msg 失效通知缓存 + 推送撤回 event_id SETNX P5
edu.notification.failed 通知失败 msg 记录日志 + 告警 event_id SETNX P5
edu.teaching.grade.recorded 成绩录入 core-edu 失效 bff:parent:grades:{childId} + 推送 event_id SETNX P5
edu.teaching.homework.graded 作业批改 core-edu 失效 bff:parent:homework:{childId} + 推送 event_id SETNX P5
edu.teaching.exam.published 考试发布 core-edu 失效 bff:parent:exams:{childId} + 推送 event_id SETNX P5

消费者组parent-bff-event-subscriber02 §5.5 DLQedu.parent-bff.dlq 提交策略manual commit

2.3 HTTP 调用(非 gRPC

被调用方 Method Path 用途 认证 阶段
push-gateway (ai02) POST /internal/push 推送给在线家长(U2 仲裁push-gateway 豁免 gRPC X-Internal-Key P5

push-gateway HTTP 调用在 P5 阶段启用P4 不涉及。


§3 就绪信号

3.1 我依赖的上游就绪标志

  • iam gRPC 50052 启用ai06—— 核心依赖 GetChildrenByParentI6 裁决P0 阻塞)
  • iam 补 GetViewports / GetEffectivePermissions RPCcoord-cross-review #1
  • iam_student_guardians 表已建立I6 裁决)
  • core-edu gRPC 50053 启用ai08
  • core-edu ClassService.GetClass proto 补全ISSUE-008 待仲裁)
  • data-ana gRPC 50055 启用ai11
  • msg gRPC 50056 启用ai10—— P5
  • msg.proto Notification 补 child_id 字段ISSUE-007 待仲裁)—— P5
  • msg NotificationPreferenceService 补全 —— P5
  • push-gateway /internal/push 启用ai02—— P5
  • api-gateway /parent 路由注册ai01
  • Kafka topic 已创建C5 仲裁)—— P5
  • Redis 已部署且网络可达
  • buf.gen.yaml 补 gRPC TS 插件coord

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

  • parent-bff GraphQL :3010 启用(/healthz 返回 200
  • /readyz 返回 200含 4 个下游 gRPC 连通性检查iam + core-edu + data-ana + Redis02 §9 #7
  • GraphQL schema 可内省POST /graphql 返回 schema
  • 核心 Query 可执行dashboard / children / childGrades / childAnalytics
  • 核心 Mutation 可执行selectChildP4/ markNotificationReadP5
  • DataScope=CHILDREN 校验生效家长只能查自己孩子的数据ChildGuard 基于 iam.GetChildrenByParent 返回的列表校验)
  • /metrics 暴露 parent_bff_* 指标

§4 Mock 策略

4.1 我提供的 mock供下游 parent-portal ai15

在 parent-bff 真实就绪前,为 parent-portal 提供以下 mock

  • GraphQL mock:使用 MSW 拦截 POST /graphql 或 Apollo Server mockProviders
    • dashboard 返回固定家长id="parent-001", name="王家长", roles=["parent"]+ 2 个孩子 + unreadNotifications=3
    • children 返回固定 2 个孩子id="student-001" 李同学 + id="student-002" 李妹妹)
    • childGrades 返回固定 5 个成绩(含 score 字段Float 类型)
    • childAnalytics 返回固定学情child_avg_score=85.0, class_rank=5
    • childHomework 返回固定 3 个作业
    • childExams 返回固定 3 个考试
    • notificationsP5返回固定 10 条通知(含 childId 字段)

4.2 我消费的 mock上游未就绪时

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

  • iam mock:固定 UserInfo + 家长权限 + 固定视口 + 固定 2 个 ChildInfo家长-学生关联核心数据)
  • core-edu mock:固定孩子成绩/作业/考试/班级信息
  • data-ana mock:固定孩子薄弱点/趋势/班级对比
  • msg mockP5固定通知列表含 childId+ MarkAsRead success + 固定偏好配置
  • push-gateway mockP5fetch mock 返回 success
  • RedisTestcontainers 真实 Redis 实例(不用 mock
  • KafkaP5kafkajs mock + jest.mock

关键约束iam.GetChildrenByParent 的 mock 必须返回与 core-edu mock 数据一致的 student_idstudent-001 + student-002否则 ChildGuard 越权校验会失败。parent-bff 启动时校验 myChildren 返回的 user_id 与下游查询的 student_id 一致性。


§5 跨模块契约冲突跟踪

以下为 ai05 复审发现的跨模块契约问题,详见 objections/parent-bff_issue.md

ISSUE 问题 影响 状态
ISSUE-003 contract.md 仲裁引用编号错误I3 → I6 引用勘误,已修正本文档 待 coord 确认
ISSUE-004 004 §4 + matrix.md §1 未同步 C6 仲裁(缺 DataAna + Msg 新 AI 误判依赖 待 coord 仲裁
ISSUE-005 parent-portal 01 文档仍按 REST 消费 parent-bff 跨模块契约冲突 待 coord 仲裁
ISSUE-006 proto 包名引用缺 next_edu_cloud 前缀 gRPC 代码生成错误,已修正本文档 待 coord 确认
ISSUE-007 msg.proto Notification 缺 child_id 字段 按孩子过滤通知失效 待 coord 仲裁
ISSUE-008 core_edu.proto 缺 ClassService + Grade.score 类型不一致 班级信息查询 + 类型转换 待 coord 仲裁